Merge commit '28de7fdf86dfcd38fb3f9c30ac30a311e4c23467' into ci-testing
This commit is contained in:
commit
4d3a16f3cb
|
@ -36,7 +36,7 @@ jobs:
|
|||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: '8.0'
|
||||
php-version: '8.1'
|
||||
extensions: intl, maxminddb
|
||||
tools: composer:v2, cs2pr
|
||||
|
||||
|
@ -110,6 +110,7 @@ jobs:
|
|||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v1
|
||||
id: qemu
|
||||
with:
|
||||
platforms: arm64
|
||||
|
||||
|
@ -182,7 +183,7 @@ jobs:
|
|||
with:
|
||||
context: .
|
||||
push: true
|
||||
platforms : linux/amd64,linux/arm64
|
||||
# platforms : linux/amd64,linux/arm64
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
cache-from: type=registry,ref=ghcr.io/azuracast/web:buildcache
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
}
|
||||
],
|
||||
"require": {
|
||||
"php": "^8.0",
|
||||
"php": "^8.1",
|
||||
"ext-PDO": "*",
|
||||
"ext-fileinfo": "*",
|
||||
"ext-gd": "*",
|
||||
|
@ -89,7 +89,7 @@
|
|||
"theiconic/php-ga-measurement-protocol": "^2.9",
|
||||
"vlucas/phpdotenv": "^5.3",
|
||||
"wikimedia/composer-merge-plugin": "dev-master",
|
||||
"zircote/swagger-php": "^3"
|
||||
"zircote/swagger-php": "^4"
|
||||
},
|
||||
"replace": {
|
||||
"symfony/polyfill-iconv": "1.99",
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -16,6 +16,9 @@ parameters:
|
|||
bootstrapFiles:
|
||||
- ./util/phpstan.php
|
||||
|
||||
scanDirectories:
|
||||
- ./vendor/zircote/swagger-php/src/Annotations
|
||||
|
||||
universalObjectCratesClasses:
|
||||
- App\Session\NamespaceInterface
|
||||
- App\View
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -225,7 +225,11 @@ class AppFactory
|
|||
|
||||
protected static function applyPhpSettings(Environment $environment): void
|
||||
{
|
||||
error_reporting(E_ALL & ~E_NOTICE & ~E_WARNING & ~E_STRICT);
|
||||
error_reporting(
|
||||
$environment->isProduction()
|
||||
? E_ALL & ~E_NOTICE & ~E_WARNING & ~E_STRICT & ~E_DEPRECATED
|
||||
: E_ALL & ~E_NOTICE
|
||||
);
|
||||
|
||||
$displayStartupErrors = (!$environment->isProduction() || $environment->isCli())
|
||||
? '1'
|
||||
|
@ -240,13 +244,16 @@ class AppFactory
|
|||
? '/dev/stderr'
|
||||
: $environment->getTempDirectory() . '/php_errors.log'
|
||||
);
|
||||
ini_set('session.use_only_cookies', '1');
|
||||
ini_set('session.cookie_httponly', '1');
|
||||
ini_set('session.cookie_lifetime', '86400');
|
||||
ini_set('session.use_strict_mode', '1');
|
||||
|
||||
if (!headers_sent()) {
|
||||
ini_set('session.use_only_cookies', '1');
|
||||
ini_set('session.cookie_httponly', '1');
|
||||
ini_set('session.cookie_lifetime', '86400');
|
||||
ini_set('session.use_strict_mode', '1');
|
||||
|
||||
session_cache_limiter('');
|
||||
}
|
||||
|
||||
date_default_timezone_set('UTC');
|
||||
|
||||
session_cache_limiter('');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -135,6 +135,23 @@ class BackupCommand extends CommandAbstract
|
|||
);
|
||||
|
||||
switch ($file_ext) {
|
||||
case 'tzst':
|
||||
$this->passThruProcess(
|
||||
$io,
|
||||
array_merge(
|
||||
[
|
||||
'tar',
|
||||
'-I',
|
||||
'zstd',
|
||||
'-cf',
|
||||
$tmpPath,
|
||||
],
|
||||
$files_to_backup
|
||||
),
|
||||
'/'
|
||||
);
|
||||
break;
|
||||
|
||||
case 'gz':
|
||||
case 'tgz':
|
||||
$this->passThruProcess(
|
||||
|
|
|
@ -43,6 +43,20 @@ class RestoreCommand extends CommandAbstract
|
|||
$file_ext = strtolower(pathinfo($path, PATHINFO_EXTENSION));
|
||||
|
||||
switch ($file_ext) {
|
||||
case 'tzst':
|
||||
$this->passThruProcess(
|
||||
$io,
|
||||
[
|
||||
'tar',
|
||||
'-I',
|
||||
'unzstd',
|
||||
'-xvf',
|
||||
$path,
|
||||
],
|
||||
'/'
|
||||
);
|
||||
break;
|
||||
|
||||
case 'gz':
|
||||
case 'tgz':
|
||||
$this->passThruProcess(
|
||||
|
|
|
@ -10,6 +10,7 @@ use App\Version;
|
|||
use OpenApi\Annotations\OpenApi;
|
||||
use OpenApi\Generator;
|
||||
use OpenApi\Util;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
|
||||
class GenerateApiDocsCommand extends CommandAbstract
|
||||
|
@ -17,14 +18,15 @@ class GenerateApiDocsCommand extends CommandAbstract
|
|||
public function __construct(
|
||||
Application $application,
|
||||
protected Environment $environment,
|
||||
protected Version $version
|
||||
protected Version $version,
|
||||
protected LoggerInterface $logger
|
||||
) {
|
||||
parent::__construct($application);
|
||||
}
|
||||
|
||||
public function __invoke(SymfonyStyle $io): int
|
||||
{
|
||||
$yaml = $this->generate()->toYaml();
|
||||
$yaml = $this->generate()?->toYaml();
|
||||
$yaml_path = $this->environment->getBaseDirectory() . '/web/static/api/openapi.yml';
|
||||
|
||||
file_put_contents($yaml_path, $yaml);
|
||||
|
@ -36,7 +38,7 @@ class GenerateApiDocsCommand extends CommandAbstract
|
|||
public function generate(
|
||||
bool $useCurrentVersion = false,
|
||||
string $apiBaseUrl = 'https://demo.azuracast.com/api'
|
||||
): OpenApi {
|
||||
): ?OpenApi {
|
||||
define('AZURACAST_API_URL', $apiBaseUrl);
|
||||
define('AZURACAST_API_NAME', 'AzuraCast Public Demo Server');
|
||||
define(
|
||||
|
@ -57,6 +59,8 @@ class GenerateApiDocsCommand extends CommandAbstract
|
|||
]
|
||||
);
|
||||
|
||||
return Generator::scan($finder);
|
||||
return Generator::scan($finder, [
|
||||
'logger' => $this->logger,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -8,88 +8,92 @@ use App\Entity;
|
|||
use OpenApi\Annotations as OA;
|
||||
|
||||
/**
|
||||
* @OA\Get(path="/admin/custom_fields",
|
||||
* operationId="getCustomFields",
|
||||
* tags={"Administration: Custom Fields"},
|
||||
* description="List all current custom fields in the system.",
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(type="array", @OA\Items(ref="#/components/schemas/CustomField"))
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Post(path="/admin/custom_fields",
|
||||
* operationId="addCustomField",
|
||||
* tags={"Administration: Custom Fields"},
|
||||
* description="Create a new custom field.",
|
||||
* @OA\RequestBody(
|
||||
* @OA\JsonContent(ref="#/components/schemas/CustomField")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/CustomField")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Get(path="/admin/custom_field/{id}",
|
||||
* operationId="getCustomField",
|
||||
* tags={"Administration: Custom Fields"},
|
||||
* description="Retrieve details for a single custom field.",
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/CustomField")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Put(path="/admin/custom_field/{id}",
|
||||
* operationId="editCustomField",
|
||||
* tags={"Administration: Custom Fields"},
|
||||
* description="Update details of a single custom field.",
|
||||
* @OA\RequestBody(
|
||||
* @OA\JsonContent(ref="#/components/schemas/CustomField")
|
||||
* ),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Status")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Delete(path="/admin/custom_field/{id}",
|
||||
* operationId="deleteCustomField",
|
||||
* tags={"Administration: Custom Fields"},
|
||||
* description="Delete a single custom field.",
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Status")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @extends AbstractAdminApiCrudController<Entity\CustomField>
|
||||
*/
|
||||
class CustomFieldsController extends AbstractAdminApiCrudController
|
||||
{
|
||||
protected string $entityClass = Entity\CustomField::class;
|
||||
protected string $resourceRouteName = 'api:admin:custom_field';
|
||||
|
||||
/**
|
||||
* @OA\Get(path="/admin/custom_fields",
|
||||
* tags={"Administration: Custom Fields"},
|
||||
* description="List all current custom fields in the system.",
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(type="array", @OA\Items(ref="#/components/schemas/CustomField"))
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Post(path="/admin/custom_fields",
|
||||
* tags={"Administration: Custom Fields"},
|
||||
* description="Create a new custom field.",
|
||||
* @OA\RequestBody(
|
||||
* @OA\JsonContent(ref="#/components/schemas/CustomField")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/CustomField")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Get(path="/admin/custom_field/{id}",
|
||||
* tags={"Administration: Custom Fields"},
|
||||
* description="Retrieve details for a single custom field.",
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/CustomField")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Put(path="/admin/custom_field/{id}",
|
||||
* tags={"Administration: Custom Fields"},
|
||||
* description="Update details of a single custom field.",
|
||||
* @OA\RequestBody(
|
||||
* @OA\JsonContent(ref="#/components/schemas/CustomField")
|
||||
* ),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Status")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
* @OA\Delete(path="/admin/custom_field/{id}",
|
||||
* tags={"Administration: Custom Fields"},
|
||||
* description="Delete a single custom field.",
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Status")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*/
|
||||
}
|
||||
|
|
|
@ -10,23 +10,21 @@ use App\Http\ServerRequest;
|
|||
use OpenApi\Annotations as OA;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
/**
|
||||
* @OA\Get(path="/admin/permissions",
|
||||
* operationId="getPermissions",
|
||||
* tags={"Administration: Roles"},
|
||||
* description="Return a list of all available permissions.",
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="Success",
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*/
|
||||
class PermissionsController
|
||||
{
|
||||
/**
|
||||
* @OA\Get(path="/admin/permissions",
|
||||
* tags={"Administration: Roles"},
|
||||
* description="Return a list of all available permissions.",
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="Success",
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @param ServerRequest $request
|
||||
* @param Response $response
|
||||
*/
|
||||
public function __invoke(
|
||||
ServerRequest $request,
|
||||
Response $response,
|
||||
|
|
|
@ -13,6 +13,19 @@ use Doctrine\ORM\EntityManagerInterface;
|
|||
use OpenApi\Annotations as OA;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
/**
|
||||
* @OA\Get(path="/internal/relays",
|
||||
* operationId="internalGetRelayDetails",
|
||||
* tags={"Administration: Relays"},
|
||||
* description="Returns all necessary information to relay all 'relayable' stations.",
|
||||
* parameters={},
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="Success",
|
||||
* @OA\JsonContent(type="array", @OA\Items(ref="#/components/schemas/Api_Admin_Relay"))
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
class RelaysController
|
||||
{
|
||||
public function __construct(
|
||||
|
@ -21,21 +34,6 @@ class RelaysController
|
|||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @OA\Get(path="/internal/relays",
|
||||
* tags={"Administration: Relays"},
|
||||
* description="Returns all necessary information to relay all 'relayable' stations.",
|
||||
* parameters={},
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="Success",
|
||||
* @OA\JsonContent(type="array", @OA\Items(ref="#/components/schemas/Api_Admin_Relay"))
|
||||
* )
|
||||
* )
|
||||
*
|
||||
* @param ServerRequest $request
|
||||
* @param Response $response
|
||||
*/
|
||||
public function __invoke(ServerRequest $request, Response $response): ResponseInterface
|
||||
{
|
||||
$stations = $this->getManageableStations($request);
|
||||
|
|
|
@ -7,12 +7,96 @@ 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;
|
||||
|
||||
/**
|
||||
* @OA\Get(path="/admin/roles",
|
||||
* operationId="getRoles",
|
||||
* tags={"Administration: Roles"},
|
||||
* description="List all current roles in the system.",
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(type="array", @OA\Items(ref="#/components/schemas/Role"))
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Post(path="/admin/roles",
|
||||
* operationId="addRole",
|
||||
* tags={"Administration: Roles"},
|
||||
* description="Create a new role.",
|
||||
* @OA\RequestBody(
|
||||
* @OA\JsonContent(ref="#/components/schemas/Role")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Role")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Get(path="/admin/role/{id}",
|
||||
* operationId="getRole",
|
||||
* tags={"Administration: Roles"},
|
||||
* description="Retrieve details for a single current role.",
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Role ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Role")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Put(path="/admin/role/{id}",
|
||||
* operationId="editRole",
|
||||
* tags={"Administration: Roles"},
|
||||
* description="Update details of a single role.",
|
||||
* @OA\RequestBody(
|
||||
* @OA\JsonContent(ref="#/components/schemas/Role")
|
||||
* ),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Role ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Status")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Delete(path="/admin/role/{id}",
|
||||
* operationId="deleteRole",
|
||||
* tags={"Administration: Roles"},
|
||||
* description="Delete a single role.",
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Role ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Status")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @extends AbstractAdminApiCrudController<Entity\Role>
|
||||
*/
|
||||
class RolesController extends AbstractAdminApiCrudController
|
||||
|
@ -30,96 +114,15 @@ class RolesController extends AbstractAdminApiCrudController
|
|||
parent::__construct($em, $serializer, $validator);
|
||||
}
|
||||
|
||||
/**
|
||||
* @OA\Get(path="/admin/roles",
|
||||
* tags={"Administration: Roles"},
|
||||
* description="List all current roles in the system.",
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(type="array", @OA\Items(ref="#/components/schemas/Role"))
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Post(path="/admin/roles",
|
||||
* tags={"Administration: Roles"},
|
||||
* description="Create a new role.",
|
||||
* @OA\RequestBody(
|
||||
* @OA\JsonContent(ref="#/components/schemas/Role")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Role")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Get(path="/admin/role/{id}",
|
||||
* tags={"Administration: Roles"},
|
||||
* description="Retrieve details for a single current role.",
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Role ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Role")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Put(path="/admin/role/{id}",
|
||||
* tags={"Administration: Roles"},
|
||||
* description="Update details of a single role.",
|
||||
* @OA\RequestBody(
|
||||
* @OA\JsonContent(ref="#/components/schemas/Role")
|
||||
* ),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Role ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Status")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Delete(path="/admin/role/{id}",
|
||||
* tags={"Administration: Roles"},
|
||||
* description="Delete a single role.",
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Role ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Status")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @inheritdoc
|
||||
*/
|
||||
|
||||
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);
|
||||
|
|
|
@ -7,7 +7,6 @@ namespace App\Controller\Api\Admin;
|
|||
use App\Controller\Api\AbstractApiCrudController;
|
||||
use App\Doctrine\ReloadableEntityManagerInterface;
|
||||
use App\Entity;
|
||||
use App\Exception\ValidationException;
|
||||
use App\Http\Response;
|
||||
use App\Http\ServerRequest;
|
||||
use OpenApi\Annotations as OA;
|
||||
|
@ -17,6 +16,31 @@ use Symfony\Component\Serializer\Serializer;
|
|||
use Symfony\Component\Validator\Validator\ValidatorInterface;
|
||||
|
||||
/**
|
||||
* @OA\Get(path="/admin/settings",
|
||||
* operationId="getSettings",
|
||||
* tags={"Administration: Settings"},
|
||||
* description="List the current values of all editable system settings.",
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Settings")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Put(path="/admin/settings",
|
||||
* operationId="editSettings",
|
||||
* tags={"Administration: Settings"},
|
||||
* description="Update settings to modify any settings provided.",
|
||||
* @OA\RequestBody(
|
||||
* @OA\JsonContent(ref="#/components/schemas/Settings")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Status")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @extends AbstractApiCrudController<Entity\Settings>
|
||||
*/
|
||||
class SettingsController extends AbstractApiCrudController
|
||||
|
@ -32,20 +56,6 @@ class SettingsController extends AbstractApiCrudController
|
|||
parent::__construct($em, $serializer, $validator);
|
||||
}
|
||||
|
||||
/**
|
||||
* @OA\Get(path="/admin/settings",
|
||||
* tags={"Administration: Settings"},
|
||||
* description="List the current values of all editable system settings.",
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Settings")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @param ServerRequest $request
|
||||
* @param Response $response
|
||||
*/
|
||||
public function listAction(
|
||||
ServerRequest $request,
|
||||
Response $response,
|
||||
|
@ -60,25 +70,6 @@ class SettingsController extends AbstractApiCrudController
|
|||
return $response->withJson($this->toArray($settings, $context));
|
||||
}
|
||||
|
||||
/**
|
||||
* @OA\Put(path="/admin/settings",
|
||||
* tags={"Administration: Settings"},
|
||||
* description="Update settings to modify any settings provided.",
|
||||
* @OA\RequestBody(
|
||||
* @OA\JsonContent(ref="#/components/schemas/Settings")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Status")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @param ServerRequest $request
|
||||
* @param Response $response
|
||||
*
|
||||
* @throws ValidationException
|
||||
*/
|
||||
public function updateAction(
|
||||
ServerRequest $request,
|
||||
Response $response,
|
||||
|
|
|
@ -18,6 +18,88 @@ use Symfony\Component\Serializer\Serializer;
|
|||
use Symfony\Component\Validator\Validator\ValidatorInterface;
|
||||
|
||||
/**
|
||||
* @OA\Get(path="/admin/stations",
|
||||
* operationId="adminGetStations",
|
||||
* tags={"Administration: Stations"},
|
||||
* description="List all current stations in the system.",
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(type="array", @OA\Items(ref="#/components/schemas/Station"))
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Post(path="/admin/stations",
|
||||
* operationId="adminAddStation",
|
||||
* tags={"Administration: Stations"},
|
||||
* description="Create a new station.",
|
||||
* @OA\RequestBody(
|
||||
* @OA\JsonContent(ref="#/components/schemas/Station")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Station")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Get(path="/admin/station/{id}",
|
||||
* operationId="adminGetStation",
|
||||
* tags={"Administration: Stations"},
|
||||
* description="Retrieve details for a single station.",
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Station")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Put(path="/admin/station/{id}",
|
||||
* operationId="adminEditStation",
|
||||
* tags={"Administration: Stations"},
|
||||
* description="Update details of a single station.",
|
||||
* @OA\RequestBody(
|
||||
* @OA\JsonContent(ref="#/components/schemas/Station")
|
||||
* ),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Status")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Delete(path="/admin/station/{id}",
|
||||
* operationId="adminDeleteStation",
|
||||
* tags={"Administration: Stations"},
|
||||
* description="Delete a single station.",
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Status")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @extends AbstractAdminApiCrudController<Entity\Station>
|
||||
*/
|
||||
class StationsController extends AbstractAdminApiCrudController
|
||||
|
@ -37,85 +119,6 @@ class StationsController extends AbstractAdminApiCrudController
|
|||
parent::__construct($reloadableEm, $serializer, $validator);
|
||||
}
|
||||
|
||||
/**
|
||||
* @OA\Get(path="/admin/stations",
|
||||
* tags={"Administration: Stations"},
|
||||
* description="List all current stations in the system.",
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(type="array", @OA\Items(ref="#/components/schemas/Station"))
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Post(path="/admin/stations",
|
||||
* tags={"Administration: Stations"},
|
||||
* description="Create a new station.",
|
||||
* @OA\RequestBody(
|
||||
* @OA\JsonContent(ref="#/components/schemas/Station")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Station")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Get(path="/admin/station/{id}",
|
||||
* tags={"Administration: Stations"},
|
||||
* description="Retrieve details for a single station.",
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Station")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Put(path="/admin/station/{id}",
|
||||
* tags={"Administration: Stations"},
|
||||
* description="Update details of a single station.",
|
||||
* @OA\RequestBody(
|
||||
* @OA\JsonContent(ref="#/components/schemas/Station")
|
||||
* ),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Status")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Delete(path="/admin/station/{id}",
|
||||
* tags={"Administration: Stations"},
|
||||
* description="Delete a single station.",
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Status")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*/
|
||||
|
||||
protected function viewRecord(object $record, ServerRequest $request): mixed
|
||||
{
|
||||
if (!($record instanceof $this->entityClass)) {
|
||||
|
|
|
@ -16,6 +16,88 @@ use Symfony\Component\Serializer\Serializer;
|
|||
use Symfony\Component\Validator\Validator\ValidatorInterface;
|
||||
|
||||
/**
|
||||
* @OA\Get(path="/admin/storage_locations",
|
||||
* operationId="getStorageLocations",
|
||||
* tags={"Administration: Storage Locations"},
|
||||
* description="List all current storage locations in the system.",
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(type="array", @OA\Items(ref="#/components/schemas/Api_Admin_StorageLocation"))
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Post(path="/admin/storage_locations",
|
||||
* operationId="addStorageLocation",
|
||||
* tags={"Administration: Storage Locations"},
|
||||
* description="Create a new storage location.",
|
||||
* @OA\RequestBody(
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Admin_StorageLocation")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Admin_StorageLocation")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Get(path="/admin/storage_location/{id}",
|
||||
* operationId="getStorageLocation",
|
||||
* tags={"Administration: Storage Locations"},
|
||||
* description="Retrieve details for a single storage location.",
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="User ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Admin_StorageLocation")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Put(path="/admin/storage_location/{id}",
|
||||
* operationId="editStorageLocation",
|
||||
* tags={"Administration: Storage Locations"},
|
||||
* description="Update details of a single storage location.",
|
||||
* @OA\RequestBody(
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Admin_StorageLocation")
|
||||
* ),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Storage Location ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Status")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Delete(path="/admin/storage_location/{id}",
|
||||
* operationId="deleteStorageLocation",
|
||||
* tags={"Administration: Storage Locations"},
|
||||
* description="Delete a single storage location.",
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Storage Location ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Status")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @extends AbstractAdminApiCrudController<Entity\StorageLocation>
|
||||
*/
|
||||
class StorageLocationsController extends AbstractAdminApiCrudController
|
||||
|
@ -32,85 +114,6 @@ class StorageLocationsController extends AbstractAdminApiCrudController
|
|||
parent::__construct($em, $serializer, $validator);
|
||||
}
|
||||
|
||||
/**
|
||||
* @OA\Get(path="/admin/storage_locations",
|
||||
* tags={"Administration: Storage Locations"},
|
||||
* description="List all current storage locations in the system.",
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(type="array", @OA\Items(ref="#/components/schemas/Api_Admin_StorageLocation"))
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Post(path="/admin/storage_locations",
|
||||
* tags={"Administration: Storage Locations"},
|
||||
* description="Create a new storage location.",
|
||||
* @OA\RequestBody(
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Admin_StorageLocation")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Admin_StorageLocation")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Get(path="/admin/storage_location/{id}",
|
||||
* tags={"Administration: Storage Locations"},
|
||||
* description="Retrieve details for a single storage location.",
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="User ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Admin_StorageLocation")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Put(path="/admin/storage_location/{id}",
|
||||
* tags={"Administration: Storage Locations"},
|
||||
* description="Update details of a single storage location.",
|
||||
* @OA\RequestBody(
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Admin_StorageLocation")
|
||||
* ),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Storage Location ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Status")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Delete(path="/admin/storage_location/{id}",
|
||||
* tags={"Administration: Storage Locations"},
|
||||
* description="Delete a single storage location.",
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Storage Location ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Status")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*/
|
||||
|
||||
public function listAction(ServerRequest $request, Response $response): ResponseInterface
|
||||
{
|
||||
$qb = $this->em->createQueryBuilder();
|
||||
|
|
|
@ -8,10 +8,93 @@ 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;
|
||||
|
||||
/**
|
||||
* @OA\Get(path="/admin/users",
|
||||
* operationId="getUsers",
|
||||
* tags={"Administration: Users"},
|
||||
* description="List all current users in the system.",
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(type="array", @OA\Items(ref="#/components/schemas/User"))
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Post(path="/admin/users",
|
||||
* operationId="addUser",
|
||||
* tags={"Administration: Users"},
|
||||
* description="Create a new user.",
|
||||
* @OA\RequestBody(
|
||||
* @OA\JsonContent(ref="#/components/schemas/User")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/User")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Get(path="/admin/user/{id}",
|
||||
* operationId="getUser",
|
||||
* tags={"Administration: Users"},
|
||||
* description="Retrieve details for a single current user.",
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="User ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/User")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Put(path="/admin/user/{id}",
|
||||
* operationId="editUser",
|
||||
* tags={"Administration: Users"},
|
||||
* description="Update details of a single user.",
|
||||
* @OA\RequestBody(
|
||||
* @OA\JsonContent(ref="#/components/schemas/User")
|
||||
* ),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="User ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Status")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Delete(path="/admin/user/{id}",
|
||||
* operationId="deleteUser",
|
||||
* tags={"Administration: Users"},
|
||||
* description="Delete a single user.",
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="User ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Status")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @extends AbstractAdminApiCrudController<Entity\User>
|
||||
*/
|
||||
class UsersController extends AbstractAdminApiCrudController
|
||||
|
@ -19,72 +102,10 @@ class UsersController extends AbstractAdminApiCrudController
|
|||
protected string $entityClass = Entity\User::class;
|
||||
protected string $resourceRouteName = 'api:admin:user';
|
||||
|
||||
/**
|
||||
* @OA\Get(path="/admin/users",
|
||||
* tags={"Administration: Users"},
|
||||
* description="List all current users in the system.",
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(type="array", @OA\Items(ref="#/components/schemas/User"))
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Post(path="/admin/users",
|
||||
* tags={"Administration: Users"},
|
||||
* description="Create a new user.",
|
||||
* @OA\RequestBody(
|
||||
* @OA\JsonContent(ref="#/components/schemas/User")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/User")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Get(path="/admin/user/{id}",
|
||||
* tags={"Administration: Users"},
|
||||
* description="Retrieve details for a single current user.",
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="User ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/User")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Put(path="/admin/user/{id}",
|
||||
* tags={"Administration: Users"},
|
||||
* description="Update details of a single user.",
|
||||
* @OA\RequestBody(
|
||||
* @OA\JsonContent(ref="#/components/schemas/User")
|
||||
* ),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="User ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Status")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*/
|
||||
|
||||
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);
|
||||
|
@ -135,26 +156,6 @@ class UsersController extends AbstractAdminApiCrudController
|
|||
return $response->withJson(Entity\Api\Status::updated());
|
||||
}
|
||||
|
||||
/**
|
||||
* @OA\Delete(path="/admin/user/{id}",
|
||||
* tags={"Administration: Users"},
|
||||
* description="Delete a single user.",
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="User ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Status")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function deleteAction(ServerRequest $request, Response $response, mixed $id): ResponseInterface
|
||||
{
|
||||
$record = $this->getRecord($id);
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,9 +22,9 @@ class OpenApiAction
|
|||
(string)$request->getRouter()->fromHere(absolute: true)
|
||||
);
|
||||
|
||||
$yaml = $apiDocsCommand->generate(true, $apiBaseUrl)->toYaml();
|
||||
$yaml = $apiDocsCommand->generate(true, $apiBaseUrl)?->toYaml();
|
||||
|
||||
$response->getBody()->write($yaml);
|
||||
$response->getBody()->write($yaml ?? '');
|
||||
return $response->withHeader('Content-Type', 'text/x-yaml');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,93 @@ use Symfony\Component\Serializer\Serializer;
|
|||
use Symfony\Component\Validator\Validator\ValidatorInterface;
|
||||
|
||||
/**
|
||||
* @OA\Get(path="/station/{station_id}/files",
|
||||
* operationId="getFiles",
|
||||
* tags={"Stations: Media"},
|
||||
* description="List all current uploaded files.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(type="array", @OA\Items(ref="#/components/schemas/StationMedia"))
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Post(path="/station/{station_id}/files",
|
||||
* operationId="addFile",
|
||||
* tags={"Stations: Media"},
|
||||
* description="Upload a new file.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\RequestBody(
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_UploadFile")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/StationMedia")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Get(path="/station/{station_id}/file/{id}",
|
||||
* operationId="getFile",
|
||||
* tags={"Stations: Media"},
|
||||
* description="Retrieve details for a single file.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Media ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/StationMedia")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Put(path="/station/{station_id}/file/{id}",
|
||||
* operationId="editFile",
|
||||
* tags={"Stations: Media"},
|
||||
* description="Update details of a single file.",
|
||||
* @OA\RequestBody(
|
||||
* @OA\JsonContent(ref="#/components/schemas/StationMedia")
|
||||
* ),
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Media ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Status")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Delete(path="/station/{station_id}/file/{id}",
|
||||
* operationId="deleteFile",
|
||||
* tags={"Stations: Media"},
|
||||
* description="Delete a single file.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Media ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Status")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @extends AbstractStationApiCrudController<Entity\StationMedia>
|
||||
*/
|
||||
class FilesController extends AbstractStationApiCrudController
|
||||
|
@ -42,95 +129,6 @@ class FilesController extends AbstractStationApiCrudController
|
|||
parent::__construct($em, $serializer, $validator);
|
||||
}
|
||||
|
||||
/**
|
||||
* @OA\Get(path="/station/{station_id}/files",
|
||||
* tags={"Stations: Media"},
|
||||
* description="List all current uploaded files.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(type="array", @OA\Items(ref="#/components/schemas/StationMedia"))
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Post(path="/station/{station_id}/files",
|
||||
* tags={"Stations: Media"},
|
||||
* description="Upload a new file.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\RequestBody(
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_UploadFile")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/StationMedia")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Get(path="/station/{station_id}/file/{id}",
|
||||
* tags={"Stations: Media"},
|
||||
* description="Retrieve details for a single file.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Media ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/StationMedia")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Put(path="/station/{station_id}/file/{id}",
|
||||
* tags={"Stations: Media"},
|
||||
* description="Update details of a single file.",
|
||||
* @OA\RequestBody(
|
||||
* @OA\JsonContent(ref="#/components/schemas/StationMedia")
|
||||
* ),
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Media ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Status")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Delete(path="/station/{station_id}/file/{id}",
|
||||
* tags={"Stations: Media"},
|
||||
* description="Delete a single file.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Media ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Status")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param ServerRequest $request
|
||||
* @param Response $response
|
||||
*
|
||||
*/
|
||||
public function listAction(ServerRequest $request, Response $response): ResponseInterface
|
||||
{
|
||||
$storageLocation = $this->getStation($request)->getMediaStorageLocation();
|
||||
|
|
|
@ -15,6 +15,40 @@ use Doctrine\ORM\EntityManagerInterface;
|
|||
use OpenApi\Annotations as OA;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
/**
|
||||
* @OA\Get(path="/station/{station_id}/history",
|
||||
* operationId="getStationHistory",
|
||||
* tags={"Stations: History"},
|
||||
* description="Return song playback history items for a given station.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="start",
|
||||
* description="The start date for records, in YYYY-MM-DD format.",
|
||||
* in="query",
|
||||
* required=false,
|
||||
* @OA\Schema(
|
||||
* type="string"
|
||||
* )
|
||||
* ),
|
||||
* @OA\Parameter(
|
||||
* name="end",
|
||||
* description="The end date for records, in YYYY-MM-DD format.",
|
||||
* in="query",
|
||||
* required=false,
|
||||
* @OA\Schema(
|
||||
* type="string"
|
||||
* )
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="Success",
|
||||
* @OA\JsonContent(type="array", @OA\Items(ref="#/components/schemas/Api_DetailedSongHistory"))
|
||||
* ),
|
||||
* @OA\Response(response=404, description="Station not found"),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*/
|
||||
class HistoryController
|
||||
{
|
||||
public function __construct(
|
||||
|
@ -24,38 +58,6 @@ class HistoryController
|
|||
}
|
||||
|
||||
/**
|
||||
* @OA\Get(path="/station/{station_id}/history",
|
||||
* tags={"Stations: History"},
|
||||
* description="Return song playback history items for a given station.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="start",
|
||||
* description="The start date for records, in YYYY-MM-DD format.",
|
||||
* in="query",
|
||||
* required=false,
|
||||
* @OA\Schema(
|
||||
* type="string"
|
||||
* )
|
||||
* ),
|
||||
* @OA\Parameter(
|
||||
* name="end",
|
||||
* description="The end date for records, in YYYY-MM-DD format.",
|
||||
* in="query",
|
||||
* required=false,
|
||||
* @OA\Schema(
|
||||
* type="string"
|
||||
* )
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="Success",
|
||||
* @OA\JsonContent(type="array", @OA\Items(ref="#/components/schemas/Api_DetailedSongHistory"))
|
||||
* ),
|
||||
* @OA\Response(response=404, description="Station not found"),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @param ServerRequest $request
|
||||
* @param Response $response
|
||||
*/
|
||||
|
|
|
@ -5,14 +5,36 @@ declare(strict_types=1);
|
|||
namespace App\Controller\Api\Stations;
|
||||
|
||||
use App\Entity;
|
||||
use App\Exception;
|
||||
use App\Exception\NotFoundException;
|
||||
use App\Http\Response;
|
||||
use App\Http\ServerRequest;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use OpenApi\Annotations as OA;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
/**
|
||||
* @OA\Get(path="/stations",
|
||||
* operationId="getStations",
|
||||
* tags={"Stations: General"},
|
||||
* description="Returns a list of stations.",
|
||||
* parameters={},
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(type="array",
|
||||
* @OA\Items(ref="#/components/schemas/Api_NowPlaying_Station")
|
||||
* )
|
||||
* )
|
||||
* )
|
||||
*
|
||||
* @OA\Get(path="/station/{station_id}",
|
||||
* operationId="getStation",
|
||||
* tags={"Stations: General"},
|
||||
* description="Return information about a single station.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_NowPlaying_Station")
|
||||
* ),
|
||||
* @OA\Response(response=404, description="Station not found")
|
||||
* )
|
||||
*/
|
||||
class IndexController
|
||||
{
|
||||
public function __construct(
|
||||
|
@ -21,23 +43,6 @@ class IndexController
|
|||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @OA\Get(path="/stations",
|
||||
* tags={"Stations: General"},
|
||||
* description="Returns a list of stations.",
|
||||
* parameters={},
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(type="array",
|
||||
* @OA\Items(ref="#/components/schemas/Api_NowPlaying_Station")
|
||||
* )
|
||||
* )
|
||||
* )
|
||||
* @param ServerRequest $request
|
||||
* @param Response $response
|
||||
*
|
||||
* @throws NotFoundException
|
||||
* @throws Exception
|
||||
*/
|
||||
public function listAction(ServerRequest $request, Response $response): ResponseInterface
|
||||
{
|
||||
$stations_raw = $this->em->getRepository(Entity\Station::class)
|
||||
|
@ -57,21 +62,6 @@ class IndexController
|
|||
return $response->withJson($stations);
|
||||
}
|
||||
|
||||
/**
|
||||
* @OA\Get(path="/station/{station_id}",
|
||||
* tags={"Stations: General"},
|
||||
* description="Return information about a single station.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_NowPlaying_Station")
|
||||
* ),
|
||||
* @OA\Response(response=404, description="Station not found")
|
||||
* )
|
||||
* @param ServerRequest $request
|
||||
* @param Response $response
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function indexAction(ServerRequest $request, Response $response): ResponseInterface
|
||||
{
|
||||
$station = $request->getStation();
|
||||
|
|
|
@ -18,24 +18,26 @@ use GuzzleHttp\Psr7\Stream;
|
|||
use League\Csv\Writer;
|
||||
use OpenApi\Annotations as OA;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use RuntimeException;
|
||||
|
||||
/**
|
||||
* @OA\Get(path="/station/{station_id}/listeners",
|
||||
* operationId="getStationListeners",
|
||||
* tags={"Stations: Listeners"},
|
||||
* description="Return detailed information about current listeners.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="Success",
|
||||
* @OA\JsonContent(type="array", @OA\Items(ref="#/components/schemas/Api_Listener"))
|
||||
* ),
|
||||
* @OA\Response(response=404, description="Station not found"),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*/
|
||||
class ListenersAction
|
||||
{
|
||||
/**
|
||||
* @OA\Get(path="/station/{station_id}/listeners",
|
||||
* tags={"Stations: Listeners"},
|
||||
* description="Return detailed information about current listeners.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="Success",
|
||||
* @OA\JsonContent(type="array", @OA\Items(ref="#/components/schemas/Api_Listener"))
|
||||
* ),
|
||||
* @OA\Response(response=404, description="Station not found"),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*/
|
||||
public function __invoke(
|
||||
ServerRequest $request,
|
||||
Response $response,
|
||||
|
@ -240,7 +242,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();
|
||||
|
|
|
@ -17,6 +17,93 @@ use Symfony\Component\Serializer\Serializer;
|
|||
use Symfony\Component\Validator\Validator\ValidatorInterface;
|
||||
|
||||
/**
|
||||
* @OA\Get(path="/station/{station_id}/mounts",
|
||||
* operationId="getStationMounts",
|
||||
* tags={"Stations: Mount Points"},
|
||||
* description="List all current mount points.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(type="array", @OA\Items(ref="#/components/schemas/StationMount"))
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Post(path="/station/{station_id}/mounts",
|
||||
* operationId="addMount",
|
||||
* tags={"Stations: Mount Points"},
|
||||
* description="Create a new mount point.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\RequestBody(
|
||||
* @OA\JsonContent(ref="#/components/schemas/StationMount")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/StationMount")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Get(path="/station/{station_id}/mount/{id}",
|
||||
* operationId="getMount",
|
||||
* tags={"Stations: Mount Points"},
|
||||
* description="Retrieve details for a single mount point.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Streamer ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/StationMount")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Put(path="/station/{station_id}/mount/{id}",
|
||||
* operationId="editMount",
|
||||
* tags={"Stations: Mount Points"},
|
||||
* description="Update details of a single mount point.",
|
||||
* @OA\RequestBody(
|
||||
* @OA\JsonContent(ref="#/components/schemas/StationMount")
|
||||
* ),
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Streamer ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Status")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Delete(path="/station/{station_id}/mount/{id}",
|
||||
* operationId="deleteMount",
|
||||
* tags={"Stations: Mount Points"},
|
||||
* description="Delete a single mount point.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="StationMount ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Status")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @extends AbstractStationApiCrudController<Entity\StationMount>
|
||||
*/
|
||||
class MountsController extends AbstractStationApiCrudController
|
||||
|
@ -33,90 +120,6 @@ class MountsController extends AbstractStationApiCrudController
|
|||
parent::__construct($em, $serializer, $validator);
|
||||
}
|
||||
|
||||
/**
|
||||
* @OA\Get(path="/station/{station_id}/mounts",
|
||||
* tags={"Stations: Mount Points"},
|
||||
* description="List all current mount points.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(type="array", @OA\Items(ref="#/components/schemas/StationMount"))
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Post(path="/station/{station_id}/mounts",
|
||||
* tags={"Stations: Mount Points"},
|
||||
* description="Create a new mount point.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\RequestBody(
|
||||
* @OA\JsonContent(ref="#/components/schemas/StationMount")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/StationMount")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Get(path="/station/{station_id}/mount/{id}",
|
||||
* tags={"Stations: Mount Points"},
|
||||
* description="Retrieve details for a single mount point.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Streamer ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/StationMount")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Put(path="/station/{station_id}/mount/{id}",
|
||||
* tags={"Stations: Mount Points"},
|
||||
* description="Update details of a single mount point.",
|
||||
* @OA\RequestBody(
|
||||
* @OA\JsonContent(ref="#/components/schemas/StationMount")
|
||||
* ),
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Streamer ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Status")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Delete(path="/station/{station_id}/mount/{id}",
|
||||
* tags={"Stations: Mount Points"},
|
||||
* description="Delete a single mount point.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="StationMount ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Status")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*/
|
||||
|
||||
protected function viewRecord(object $record, ServerRequest $request): mixed
|
||||
{
|
||||
/** @var Entity\StationMount $record */
|
||||
|
|
|
@ -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,93 @@ use Psr\Http\Message\ResponseInterface;
|
|||
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
|
||||
|
||||
/**
|
||||
* @OA\Get(path="/station/{station_id}/playlists",
|
||||
* operationId="getPlaylists",
|
||||
* tags={"Stations: Playlists"},
|
||||
* description="List all current playlists.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(type="array", @OA\Items(ref="#/components/schemas/StationPlaylist"))
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Post(path="/station/{station_id}/playlists",
|
||||
* operationId="addPlaylist",
|
||||
* tags={"Stations: Playlists"},
|
||||
* description="Create a new playlist.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\RequestBody(
|
||||
* @OA\JsonContent(ref="#/components/schemas/StationPlaylist")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/StationPlaylist")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Get(path="/station/{station_id}/playlist/{id}",
|
||||
* operationId="getPlaylist",
|
||||
* tags={"Stations: Playlists"},
|
||||
* description="Retrieve details for a single playlist.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Playlist ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/StationPlaylist")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Put(path="/station/{station_id}/playlist/{id}",
|
||||
* operationId="editPlaylist",
|
||||
* tags={"Stations: Playlists"},
|
||||
* description="Update details of a single playlist.",
|
||||
* @OA\RequestBody(
|
||||
* @OA\JsonContent(ref="#/components/schemas/StationPlaylist")
|
||||
* ),
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Playlist ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Status")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Delete(path="/station/{station_id}/playlist/{id}",
|
||||
* operationId="deletePlaylist",
|
||||
* tags={"Stations: Playlists"},
|
||||
* description="Delete a single playlist relay.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Playlist ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Status")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @extends AbstractScheduledEntityController<Entity\StationPlaylist>
|
||||
*/
|
||||
class PlaylistsController extends AbstractScheduledEntityController
|
||||
|
@ -21,90 +108,6 @@ class PlaylistsController extends AbstractScheduledEntityController
|
|||
protected string $entityClass = Entity\StationPlaylist::class;
|
||||
protected string $resourceRouteName = 'api:stations:playlist';
|
||||
|
||||
/**
|
||||
* @OA\Get(path="/station/{station_id}/playlists",
|
||||
* tags={"Stations: Playlists"},
|
||||
* description="List all current playlists.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(type="array", @OA\Items(ref="#/components/schemas/StationPlaylist"))
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Post(path="/station/{station_id}/playlists",
|
||||
* tags={"Stations: Playlists"},
|
||||
* description="Create a new playlist.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\RequestBody(
|
||||
* @OA\JsonContent(ref="#/components/schemas/StationPlaylist")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/StationPlaylist")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Get(path="/station/{station_id}/playlist/{id}",
|
||||
* tags={"Stations: Playlists"},
|
||||
* description="Retrieve details for a single playlist.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Playlist ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/StationPlaylist")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Put(path="/station/{station_id}/playlist/{id}",
|
||||
* tags={"Stations: Playlists"},
|
||||
* description="Update details of a single playlist.",
|
||||
* @OA\RequestBody(
|
||||
* @OA\JsonContent(ref="#/components/schemas/StationPlaylist")
|
||||
* ),
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Playlist ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Status")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Delete(path="/station/{station_id}/playlist/{id}",
|
||||
* tags={"Stations: Playlists"},
|
||||
* description="Delete a single playlist relay.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Playlist ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Status")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*/
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
|
|
|
@ -13,11 +13,135 @@ use App\Http\Response;
|
|||
use App\Http\ServerRequest;
|
||||
use App\Service\Flow\UploadedFile;
|
||||
use InvalidArgumentException;
|
||||
use OpenApi\Annotations as OA;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use RuntimeException;
|
||||
use Symfony\Component\Serializer\Serializer;
|
||||
use Symfony\Component\Validator\Validator\ValidatorInterface;
|
||||
|
||||
/**
|
||||
* @OA\Get(path="/station/{station_id}/podcast/{podcast_id}/episodes",
|
||||
* operationId="getEpisodes",
|
||||
* tags={"Stations: Podcasts"},
|
||||
* description="List all current episodes for a given podcast ID.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="podcast_id",
|
||||
* in="path",
|
||||
* description="Podcast ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="string")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(type="array", @OA\Items(ref="#/components/schemas/Api_PodcastEpisode"))
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Post(path="/station/{station_id}/podcast/{podcast_id}/episodes",
|
||||
* operationId="addEpisode",
|
||||
* tags={"Stations: Podcasts"},
|
||||
* description="Create a new podcast episode.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="podcast_id",
|
||||
* in="path",
|
||||
* description="Podcast ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="string")
|
||||
* ),
|
||||
* @OA\RequestBody(
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_PodcastEpisode")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_PodcastEpisode")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Get(path="/station/{station_id}/podcast/{podcast_id}/episode/{id}",
|
||||
* operationId="getEpisode",
|
||||
* tags={"Stations: Podcasts"},
|
||||
* description="Retrieve details for a single podcast episode.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="podcast_id",
|
||||
* in="path",
|
||||
* description="Podcast ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="string")
|
||||
* ),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Podcast Episode ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="string")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_PodcastEpisode")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Put(path="/station/{station_id}/podcast/{podcast_id}/episode/{id}",
|
||||
* operationId="editEpisode",
|
||||
* tags={"Stations: Podcasts"},
|
||||
* description="Update details of a single podcast episode.",
|
||||
* @OA\RequestBody(
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_PodcastEpisode")
|
||||
* ),
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="podcast_id",
|
||||
* in="path",
|
||||
* description="Podcast ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="string")
|
||||
* ),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Podcast Episode ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="string")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Status")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Delete(path="/station/{station_id}/podcast/{podcast_id}/episode/{id}",
|
||||
* operationId="deleteEpisode",
|
||||
* tags={"Stations: Podcasts"},
|
||||
* description="Delete a single podcast episode.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="podcast_id",
|
||||
* in="path",
|
||||
* description="Podcast ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="string")
|
||||
* ),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Podcast Episode ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="string")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Status")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @extends AbstractApiCrudController<Entity\PodcastEpisode>
|
||||
*/
|
||||
class PodcastEpisodesController extends AbstractApiCrudController
|
||||
|
@ -36,125 +160,6 @@ class PodcastEpisodesController extends AbstractApiCrudController
|
|||
parent::__construct($em, $serializer, $validator);
|
||||
}
|
||||
|
||||
/**
|
||||
* @OA\Get(path="/station/{station_id}/podcast/{podcast_id}/episodes",
|
||||
* tags={"Stations: Podcasts"},
|
||||
* description="List all current episodes for a given podcast ID.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="podcast_id",
|
||||
* in="path",
|
||||
* description="Podcast ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="string")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(type="array", @OA\Items(ref="#/components/schemas/Api_PodcastEpisode"))
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Post(path="/station/{station_id}/podcast/{podcast_id}/episodes",
|
||||
* tags={"Stations: Podcasts"},
|
||||
* description="Create a new podcast episode.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="podcast_id",
|
||||
* in="path",
|
||||
* description="Podcast ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="string")
|
||||
* ),
|
||||
* @OA\RequestBody(
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_PodcastEpisode")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_PodcastEpisode")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Get(path="/station/{station_id}/podcast/{podcast_id}/episode/{id}",
|
||||
* tags={"Stations: Podcasts"},
|
||||
* description="Retrieve details for a single podcast episode.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="podcast_id",
|
||||
* in="path",
|
||||
* description="Podcast ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="string")
|
||||
* ),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Podcast Episode ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="string")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_PodcastEpisode")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Put(path="/station/{station_id}/podcast/{podcast_id}/episode/{id}",
|
||||
* tags={"Stations: Podcasts"},
|
||||
* description="Update details of a single podcast episode.",
|
||||
* @OA\RequestBody(
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_PodcastEpisode")
|
||||
* ),
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="podcast_id",
|
||||
* in="path",
|
||||
* description="Podcast ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="string")
|
||||
* ),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Podcast Episode ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="string")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Status")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Delete(path="/station/{station_id}/podcast/{podcast_id}/episode/{id}",
|
||||
* tags={"Stations: Podcasts"},
|
||||
* description="Delete a single podcast episode.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="podcast_id",
|
||||
* in="path",
|
||||
* description="Podcast ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="string")
|
||||
* ),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Podcast Episode ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="string")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Status")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*/
|
||||
|
||||
public function listAction(
|
||||
ServerRequest $request,
|
||||
Response $response,
|
||||
|
@ -208,7 +213,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();
|
||||
|
|
|
@ -20,6 +20,93 @@ use Symfony\Component\Serializer\Serializer;
|
|||
use Symfony\Component\Validator\Validator\ValidatorInterface;
|
||||
|
||||
/**
|
||||
* @OA\Get(path="/station/{station_id}/podcasts",
|
||||
* operationId="getPodcasts",
|
||||
* tags={"Stations: Podcasts"},
|
||||
* description="List all current podcasts.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(type="array", @OA\Items(ref="#/components/schemas/Api_Podcast"))
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Post(path="/station/{station_id}/podcasts",
|
||||
* operationId="addPodcast",
|
||||
* tags={"Stations: Podcasts"},
|
||||
* description="Create a new podcast.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\RequestBody(
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Podcast")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Podcast")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Get(path="/station/{station_id}/podcast/{id}",
|
||||
* operationId="getPodcast",
|
||||
* tags={"Stations: Podcasts"},
|
||||
* description="Retrieve details for a single podcast.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Podcast ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="string")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Podcast")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Put(path="/station/{station_id}/podcast/{id}",
|
||||
* operationId="editPodcast",
|
||||
* tags={"Stations: Podcasts"},
|
||||
* description="Update details of a single podcast.",
|
||||
* @OA\RequestBody(
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Podcast")
|
||||
* ),
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Podcast ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="string")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Status")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Delete(path="/station/{station_id}/podcast/{id}",
|
||||
* operationId="deletePodcast",
|
||||
* tags={"Stations: Podcasts"},
|
||||
* description="Delete a single podcast.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Podcast ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="string")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Status")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @extends AbstractApiCrudController<Entity\Podcast>
|
||||
*/
|
||||
class PodcastsController extends AbstractApiCrudController
|
||||
|
@ -37,93 +124,6 @@ class PodcastsController extends AbstractApiCrudController
|
|||
parent::__construct($em, $serializer, $validator);
|
||||
}
|
||||
|
||||
/**
|
||||
* @OA\Get(path="/station/{station_id}/podcasts",
|
||||
* tags={"Stations: Podcasts"},
|
||||
* description="List all current podcasts.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(type="array", @OA\Items(ref="#/components/schemas/Api_Podcast"))
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Post(path="/station/{station_id}/podcasts",
|
||||
* tags={"Stations: Podcasts"},
|
||||
* description="Create a new podcast.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\RequestBody(
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Podcast")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Podcast")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Get(path="/station/{station_id}/podcast/{id}",
|
||||
* tags={"Stations: Podcasts"},
|
||||
* description="Retrieve details for a single podcast.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Podcast ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="string")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Podcast")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Put(path="/station/{station_id}/podcast/{id}",
|
||||
* tags={"Stations: Podcasts"},
|
||||
* description="Update details of a single podcast.",
|
||||
* @OA\RequestBody(
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Podcast")
|
||||
* ),
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Podcast ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="string")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Status")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Delete(path="/station/{station_id}/podcast/{id}",
|
||||
* tags={"Stations: Podcasts"},
|
||||
* description="Delete a single podcast.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Podcast ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="string")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Status")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*/
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function listAction(ServerRequest $request, Response $response): ResponseInterface
|
||||
{
|
||||
$station = $request->getStation();
|
||||
|
|
|
@ -15,6 +15,61 @@ use Symfony\Component\Serializer\Serializer;
|
|||
use Symfony\Component\Validator\Validator\ValidatorInterface;
|
||||
|
||||
/**
|
||||
* @OA\Get(path="/station/{station_id}/queue",
|
||||
* operationId="getQueue",
|
||||
* tags={"Stations: Queue"},
|
||||
* description="Return information about the upcoming song playback queue.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(type="array",
|
||||
* @OA\Items(ref="#/components/schemas/Api_StationQueueDetailed")
|
||||
* )
|
||||
* ),
|
||||
* @OA\Response(response=404, description="Station not found"),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}}
|
||||
* )
|
||||
*
|
||||
* @OA\Get(path="/station/{station_id}/queue/{id}",
|
||||
* operationId="getQueueItem",
|
||||
* tags={"Stations: Queue"},
|
||||
* description="Retrieve details of a single queued item.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Queue Item ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_StationQueueDetailed")
|
||||
* ),
|
||||
* @OA\Response(response=404, description="Station or Queue ID not found"),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}}
|
||||
* )
|
||||
*
|
||||
* @OA\Delete(path="/station/{station_id}/queue/{id}",
|
||||
* operationId="deleteQueueItem",
|
||||
* tags={"Stations: Queue"},
|
||||
* description="Delete a single queued item.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Queue Item ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Status")
|
||||
* ),
|
||||
* @OA\Response(response=404, description="Station or Queue ID not found"),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}}
|
||||
* )
|
||||
*
|
||||
* @extends AbstractStationApiCrudController<Entity\StationQueue>
|
||||
*/
|
||||
class QueueController extends AbstractStationApiCrudController
|
||||
|
@ -32,23 +87,6 @@ class QueueController extends AbstractStationApiCrudController
|
|||
parent::__construct($em, $serializer, $validator);
|
||||
}
|
||||
|
||||
/**
|
||||
* @OA\Get(path="/station/{station_id}/queue",
|
||||
* tags={"Stations: Queue"},
|
||||
* description="Return information about the upcoming song playback queue.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(type="array",
|
||||
* @OA\Items(ref="#/components/schemas/Api_StationQueueDetailed")
|
||||
* )
|
||||
* ),
|
||||
* @OA\Response(response=404, description="Station not found"),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}}
|
||||
* )
|
||||
*
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function listAction(
|
||||
ServerRequest $request,
|
||||
Response $response
|
||||
|
@ -63,46 +101,6 @@ class QueueController extends AbstractStationApiCrudController
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @OA\Get(path="/station/{station_id}/queue/{id}",
|
||||
* tags={"Stations: Queue"},
|
||||
* description="Retrieve details of a single queued item.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Queue Item ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_StationQueueDetailed")
|
||||
* ),
|
||||
* @OA\Response(response=404, description="Station or Queue ID not found"),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}}
|
||||
* )
|
||||
*
|
||||
* @OA\Delete(path="/station/{station_id}/queue/{id}",
|
||||
* tags={"Stations: Queue"},
|
||||
* description="Delete a single queued item.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Queue Item ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Status")
|
||||
* ),
|
||||
* @OA\Response(response=404, description="Station or Queue ID not found"),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}}
|
||||
* )
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param object $record
|
||||
* @param ServerRequest $request
|
||||
|
|
|
@ -11,6 +11,93 @@ use InvalidArgumentException;
|
|||
use OpenApi\Annotations as OA;
|
||||
|
||||
/**
|
||||
* @OA\Get(path="/station/{station_id}/remotes",
|
||||
* operationId="getRelays",
|
||||
* tags={"Stations: Remote Relays"},
|
||||
* description="List all current remote relays.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(type="array", @OA\Items(ref="#/components/schemas/Api_StationRemote"))
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Post(path="/station/{station_id}/remotes",
|
||||
* operationId="addRelay",
|
||||
* tags={"Stations: Remote Relays"},
|
||||
* description="Create a new remote relay.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\RequestBody(
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_StationRemote")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_StationRemote")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Get(path="/station/{station_id}/remote/{id}",
|
||||
* operationId="getRelay",
|
||||
* tags={"Stations: Remote Relays"},
|
||||
* description="Retrieve details for a single remote relay.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Remote Relay ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_StationRemote")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Put(path="/station/{station_id}/remote/{id}",
|
||||
* operationId="editRelay",
|
||||
* tags={"Stations: Remote Relays"},
|
||||
* description="Update details of a single remote relay.",
|
||||
* @OA\RequestBody(
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_StationRemote")
|
||||
* ),
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Remote Relay ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Status")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Delete(path="/station/{station_id}/remote/{id}",
|
||||
* operationId="deleteRelay",
|
||||
* tags={"Stations: Remote Relays"},
|
||||
* description="Delete a single remote relay.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Remote Relay ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Status")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @extends AbstractStationApiCrudController<Entity\StationRemote>
|
||||
*/
|
||||
class RemotesController extends AbstractStationApiCrudController
|
||||
|
@ -18,90 +105,6 @@ class RemotesController extends AbstractStationApiCrudController
|
|||
protected string $entityClass = Entity\StationRemote::class;
|
||||
protected string $resourceRouteName = 'api:stations:remote';
|
||||
|
||||
/**
|
||||
* @OA\Get(path="/station/{station_id}/remotes",
|
||||
* tags={"Stations: Remote Relays"},
|
||||
* description="List all current remote relays.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(type="array", @OA\Items(ref="#/components/schemas/Api_StationRemote"))
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Post(path="/station/{station_id}/remotes",
|
||||
* tags={"Stations: Remote Relays"},
|
||||
* description="Create a new remote relay.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\RequestBody(
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_StationRemote")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_StationRemote")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Get(path="/station/{station_id}/remote/{id}",
|
||||
* tags={"Stations: Remote Relays"},
|
||||
* description="Retrieve details for a single remote relay.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Remote Relay ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_StationRemote")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Put(path="/station/{station_id}/remote/{id}",
|
||||
* tags={"Stations: Remote Relays"},
|
||||
* description="Update details of a single remote relay.",
|
||||
* @OA\RequestBody(
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_StationRemote")
|
||||
* ),
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Remote Relay ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Status")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Delete(path="/station/{station_id}/remote/{id}",
|
||||
* tags={"Stations: Remote Relays"},
|
||||
* description="Delete a single remote relay.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Remote Relay ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Status")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*/
|
||||
|
||||
protected function viewRecord(object $record, ServerRequest $request): mixed
|
||||
{
|
||||
if (!($record instanceof Entity\StationRemote)) {
|
||||
|
|
|
@ -14,6 +14,43 @@ use Doctrine\ORM\EntityManagerInterface;
|
|||
use OpenApi\Annotations as OA;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
/**
|
||||
* @OA\Get(path="/station/{station_id}/requests",
|
||||
* operationId="getRequestableSongs",
|
||||
* tags={"Stations: Song Requests"},
|
||||
* description="Return a list of requestable songs.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="Success",
|
||||
* @OA\Schema(
|
||||
* type="array",
|
||||
* @OA\Items(ref="#/components/schemas/Api_StationRequest")
|
||||
* )
|
||||
* ),
|
||||
* @OA\Response(response=404, description="Station not found"),
|
||||
* @OA\Response(response=403, description="Station does not support requests")
|
||||
* )
|
||||
*
|
||||
* @OA\Post(path="/station/{station_id}/request/{request_id}",
|
||||
* operationId="submitSongRequest",
|
||||
* tags={"Stations: Song Requests"},
|
||||
* description="Submit a song request.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="request_id",
|
||||
* description="The requestable song ID",
|
||||
* in="path",
|
||||
* required=true,
|
||||
* @OA\Schema(
|
||||
* type="string"
|
||||
* )
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success"),
|
||||
* @OA\Response(response=404, description="Station not found"),
|
||||
* @OA\Response(response=403, description="Station does not support requests")
|
||||
* )
|
||||
*/
|
||||
class RequestsController
|
||||
{
|
||||
public function __construct(
|
||||
|
@ -23,29 +60,6 @@ class RequestsController
|
|||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @OA\Get(path="/station/{station_id}/requests",
|
||||
* tags={"Stations: Song Requests"},
|
||||
* description="Return a list of requestable songs.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="Success",
|
||||
* @OA\Schema(
|
||||
* type="array",
|
||||
* @OA\Items(ref="#/components/schemas/Api_StationRequest")
|
||||
* )
|
||||
* ),
|
||||
* @OA\Response(response=404, description="Station not found"),
|
||||
* @OA\Response(response=403, description="Station does not support requests")
|
||||
* )
|
||||
*
|
||||
* @param ServerRequest $request
|
||||
* @param Response $response
|
||||
*
|
||||
* @throws Exception
|
||||
* @throws Exception\InvalidRequestAttribute
|
||||
*/
|
||||
public function listAction(ServerRequest $request, Response $response): ResponseInterface
|
||||
{
|
||||
$station = $request->getStation();
|
||||
|
@ -125,31 +139,6 @@ class RequestsController
|
|||
return $paginator->write($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @OA\Post(path="/station/{station_id}/request/{request_id}",
|
||||
* tags={"Stations: Song Requests"},
|
||||
* description="Submit a song request.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="request_id",
|
||||
* description="The requestable song ID",
|
||||
* in="path",
|
||||
* required=true,
|
||||
* @OA\Schema(
|
||||
* type="string"
|
||||
* )
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success"),
|
||||
* @OA\Response(response=404, description="Station not found"),
|
||||
* @OA\Response(response=403, description="Station does not support requests")
|
||||
* )
|
||||
*
|
||||
* @param ServerRequest $request
|
||||
* @param Response $response
|
||||
* @param string $media_id
|
||||
*
|
||||
* @throws Exception\InvalidRequestAttribute
|
||||
*/
|
||||
public function submitAction(ServerRequest $request, Response $response, string $media_id): ResponseInterface
|
||||
{
|
||||
$station = $request->getStation();
|
||||
|
|
|
@ -16,39 +16,39 @@ use Psr\Http\Message\ResponseInterface;
|
|||
use Symfony\Component\Cache\CacheItem;
|
||||
use Symfony\Contracts\Cache\CacheInterface;
|
||||
|
||||
/**
|
||||
* @OA\Get(path="/station/{station_id}/schedule",
|
||||
* operationId="getSchedule",
|
||||
* tags={"Stations: Schedules"},
|
||||
* description="Return upcoming and currently ongoing schedule entries.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="now",
|
||||
* description="The date/time to compare schedule items to. Defaults to the current date and time.",
|
||||
* in="query",
|
||||
* required=false,
|
||||
* @OA\Schema(type="string")
|
||||
* ),
|
||||
* @OA\Parameter(
|
||||
* name="rows",
|
||||
* description="The number of upcoming/ongoing schedule entries to return. Defaults to 5.",
|
||||
* in="query",
|
||||
* required=false,
|
||||
* @OA\Schema(type="integer")
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="Success",
|
||||
* @OA\JsonContent(type="array", @OA\Items(ref="#/components/schemas/Api_StationSchedule"))
|
||||
* ),
|
||||
* @OA\Response(response=404, description="Station not found"),
|
||||
* @OA\Response(response=403, description="Access denied")
|
||||
* )
|
||||
*/
|
||||
class ScheduleAction
|
||||
{
|
||||
use HasScheduleDisplay;
|
||||
|
||||
/**
|
||||
* @OA\Get(path="/station/{station_id}/schedule",
|
||||
* tags={"Stations: Schedules"},
|
||||
* description="Return upcoming and currently ongoing schedule entries.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="now",
|
||||
* description="The date/time to compare schedule items to. Defaults to the current date and time.",
|
||||
* in="query",
|
||||
* required=false,
|
||||
* @OA\Schema(type="string")
|
||||
* ),
|
||||
* @OA\Parameter(
|
||||
* name="rows",
|
||||
* description="The number of upcoming/ongoing schedule entries to return. Defaults to 5.",
|
||||
* in="query",
|
||||
* required=false,
|
||||
* @OA\Schema(type="integer")
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="Success",
|
||||
* @OA\JsonContent(type="array", @OA\Items(ref="#/components/schemas/Api_StationSchedule"))
|
||||
* ),
|
||||
* @OA\Response(response=404, description="Station not found"),
|
||||
* @OA\Response(response=403, description="Access denied")
|
||||
* )
|
||||
*/
|
||||
|
||||
public function __invoke(
|
||||
ServerRequest $request,
|
||||
Response $response,
|
||||
|
|
|
@ -15,6 +15,71 @@ use Doctrine\ORM\EntityManagerInterface;
|
|||
use OpenApi\Annotations as OA;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
/**
|
||||
* @OA\Get(path="/station/{station_id}/status",
|
||||
* operationId="getServiceStatus",
|
||||
* tags={"Stations: Service Control"},
|
||||
* description="Retrieve the current status of all serivces associated with the radio broadcast.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="Success",
|
||||
* @OA\Schema(ref="#/components/schemas/Api_StationServiceStatus")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access Forbidden", @OA\Schema(ref="#/components/schemas/Api_Error")),
|
||||
* security={{"api_key": {}}}
|
||||
* )
|
||||
*
|
||||
* @OA\Post(path="/station/{station_id}/restart",
|
||||
* operationId="restartServices",
|
||||
* tags={"Stations: Service Control"},
|
||||
* description="Restart all services associated with the radio broadcast.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Response(response=200, description="Success", @OA\Schema(ref="#/components/schemas/Api_Status")),
|
||||
* @OA\Response(response=403, description="Access Forbidden", @OA\Schema(ref="#/components/schemas/Api_Error")),
|
||||
* security={{"api_key": {}}}
|
||||
* )
|
||||
*
|
||||
* @OA\Post(path="/station/{station_id}/frontend/{action}",
|
||||
* operationId="doFrontendServiceAction",
|
||||
* tags={"Stations: Service Control"},
|
||||
* description="Perform service control actions on the radio frontend (Icecast, SHOUTcast, etc.)",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="action",
|
||||
* description="The action to perform (start, stop, restart)",
|
||||
* in="path",
|
||||
* required=false,
|
||||
* @OA\Schema(
|
||||
* type="string",
|
||||
* default="restart"
|
||||
* )
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success", @OA\Schema(ref="#/components/schemas/Api_Status")),
|
||||
* @OA\Response(response=403, description="Access Forbidden", @OA\Schema(ref="#/components/schemas/Api_Error")),
|
||||
* security={{"api_key": {}}}
|
||||
* )
|
||||
*
|
||||
* @OA\Post(path="/station/{station_id}/backend/{action}",
|
||||
* operationId="doBackendServiceAction",
|
||||
* tags={"Stations: Service Control"},
|
||||
* description="Perform service control actions on the radio backend (Liquidsoap)",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="action",
|
||||
* description="The action to perform (for all: start, stop, restart; for Liquidsoap only: skip, disconnect)",
|
||||
* in="path",
|
||||
* required=false,
|
||||
* @OA\Schema(
|
||||
* type="string",
|
||||
* default="restart"
|
||||
* )
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success", @OA\Schema(ref="#/components/schemas/Api_Status")),
|
||||
* @OA\Response(response=403, description="Access Forbidden", @OA\Schema(ref="#/components/schemas/Api_Error")),
|
||||
* security={{"api_key": {}}}
|
||||
* )
|
||||
*/
|
||||
class ServicesController
|
||||
{
|
||||
public function __construct(
|
||||
|
@ -23,23 +88,6 @@ class ServicesController
|
|||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @OA\Get(path="/station/{station_id}/status",
|
||||
* tags={"Stations: Service Control"},
|
||||
* description="Retrieve the current status of all serivces associated with the radio broadcast.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="Success",
|
||||
* @OA\Schema(ref="#/components/schemas/Api_StationServiceStatus")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access Forbidden", @OA\Schema(ref="#/components/schemas/Api_Error")),
|
||||
* security={{"api_key": {}}}
|
||||
* )
|
||||
*
|
||||
* @param ServerRequest $request
|
||||
* @param Response $response
|
||||
*/
|
||||
public function statusAction(ServerRequest $request, Response $response): ResponseInterface
|
||||
{
|
||||
$station = $request->getStation();
|
||||
|
@ -57,19 +105,6 @@ class ServicesController
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @OA\Post(path="/station/{station_id}/restart",
|
||||
* tags={"Stations: Service Control"},
|
||||
* description="Restart all services associated with the radio broadcast.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Response(response=200, description="Success", @OA\Schema(ref="#/components/schemas/Api_Status")),
|
||||
* @OA\Response(response=403, description="Access Forbidden", @OA\Schema(ref="#/components/schemas/Api_Error")),
|
||||
* security={{"api_key": {}}}
|
||||
* )
|
||||
*
|
||||
* @param ServerRequest $request
|
||||
* @param Response $response
|
||||
*/
|
||||
public function restartAction(ServerRequest $request, Response $response): ResponseInterface
|
||||
{
|
||||
$station = $request->getStation();
|
||||
|
@ -78,34 +113,10 @@ class ServicesController
|
|||
return $response->withJson(new Entity\Api\Status(true, __('Station restarted.')));
|
||||
}
|
||||
|
||||
/**
|
||||
* @OA\Post(path="/station/{station_id}/frontend/{action}",
|
||||
* tags={"Stations: Service Control"},
|
||||
* description="Perform service control actions on the radio frontend (Icecast, SHOUTcast, etc.)",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="action",
|
||||
* description="The action to perform (start, stop, restart)",
|
||||
* in="path",
|
||||
* required=false,
|
||||
* @OA\Schema(
|
||||
* type="string",
|
||||
* default="restart"
|
||||
* )
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success", @OA\Schema(ref="#/components/schemas/Api_Status")),
|
||||
* @OA\Response(response=403, description="Access Forbidden", @OA\Schema(ref="#/components/schemas/Api_Error")),
|
||||
* security={{"api_key": {}}}
|
||||
* )
|
||||
*
|
||||
* @param ServerRequest $request
|
||||
* @param Response $response
|
||||
* @param string $do
|
||||
*/
|
||||
public function frontendAction(
|
||||
ServerRequest $request,
|
||||
Response $response,
|
||||
$do = 'restart'
|
||||
string $do = 'restart'
|
||||
): ResponseInterface {
|
||||
$station = $request->getStation();
|
||||
$frontend = $request->getStationFrontend();
|
||||
|
@ -141,36 +152,11 @@ class ServicesController
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @OA\Post(path="/station/{station_id}/backend/{action}",
|
||||
* tags={"Stations: Service Control"},
|
||||
* description="Perform service control actions on the radio backend (Liquidsoap)",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="action",
|
||||
* description="The action to perform (for all: start, stop, restart; for Liquidsoap only: skip, disconnect)",
|
||||
* in="path",
|
||||
* required=false,
|
||||
* @OA\Schema(
|
||||
* type="string",
|
||||
* default="restart"
|
||||
* )
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success", @OA\Schema(ref="#/components/schemas/Api_Status")),
|
||||
* @OA\Response(response=403, description="Access Forbidden", @OA\Schema(ref="#/components/schemas/Api_Error")),
|
||||
* security={{"api_key": {}}}
|
||||
* )
|
||||
*
|
||||
* @param ServerRequest $request
|
||||
* @param Response $response
|
||||
* @param AutoDJ $autodj
|
||||
* @param string $do
|
||||
*/
|
||||
public function backendAction(
|
||||
ServerRequest $request,
|
||||
Response $response,
|
||||
AutoDJ $autodj,
|
||||
$do = 'restart'
|
||||
string $do = 'restart'
|
||||
): ResponseInterface {
|
||||
$station = $request->getStation();
|
||||
$backend = $request->getStationBackend();
|
||||
|
|
|
@ -8,94 +8,97 @@ use App\Entity;
|
|||
use OpenApi\Annotations as OA;
|
||||
|
||||
/**
|
||||
* @OA\Get(path="/station/{station_id}/sftp-users",
|
||||
* operationId="getSftpUsers",
|
||||
* tags={"Stations: SFTP Users"},
|
||||
* description="List all current SFTP users.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(type="array", @OA\Items(ref="#/components/schemas/SftpUser"))
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Post(path="/station/{station_id}/sftp-users",
|
||||
* operationId="addSftpUser",
|
||||
* tags={"Stations: SFTP Users"},
|
||||
* description="Create a new SFTP user.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\RequestBody(
|
||||
* @OA\JsonContent(ref="#/components/schemas/SftpUser")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/SftpUser")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Get(path="/station/{station_id}/sftp-user/{id}",
|
||||
* operationId="getSftpUser",
|
||||
* tags={"Stations: SFTP Users"},
|
||||
* description="Retrieve details for a single SFTP user.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="SFTP User ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/SftpUser")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Put(path="/station/{station_id}/sftp-user/{id}",
|
||||
* operationId="editSftpUser",
|
||||
* tags={"Stations: SFTP Users"},
|
||||
* description="Update details of a single SFTP user.",
|
||||
* @OA\RequestBody(
|
||||
* @OA\JsonContent(ref="#/components/schemas/SftpUser")
|
||||
* ),
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Remote Relay ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Status")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Delete(path="/station/{station_id}/sftp-user/{id}",
|
||||
* operationId="deleteSftpUser",
|
||||
* tags={"Stations: SFTP Users"},
|
||||
* description="Delete a single remote relay.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Remote Relay ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Status")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @extends AbstractStationApiCrudController<Entity\SftpUser>
|
||||
*/
|
||||
class SftpUsersController extends AbstractStationApiCrudController
|
||||
{
|
||||
protected string $entityClass = Entity\SftpUser::class;
|
||||
protected string $resourceRouteName = 'api:stations:sftp-user';
|
||||
|
||||
/**
|
||||
* @OA\Get(path="/station/{station_id}/sftp-users",
|
||||
* tags={"Stations: SFTP Users"},
|
||||
* description="List all current SFTP users.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(type="array", @OA\Items(ref="#/components/schemas/SftpUser"))
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Post(path="/station/{station_id}/sftp-users",
|
||||
* tags={"Stations: SFTP Users"},
|
||||
* description="Create a new SFTP user.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\RequestBody(
|
||||
* @OA\JsonContent(ref="#/components/schemas/SftpUser")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/SftpUser")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Get(path="/station/{station_id}/sftp-user/{id}",
|
||||
* tags={"Stations: SFTP Users"},
|
||||
* description="Retrieve details for a single SFTP user.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="SFTP User ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/SftpUser")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Put(path="/station/{station_id}/sftp-user/{id}",
|
||||
* tags={"Stations: SFTP Users"},
|
||||
* description="Update details of a single SFTP user.",
|
||||
* @OA\RequestBody(
|
||||
* @OA\JsonContent(ref="#/components/schemas/SftpUser")
|
||||
* ),
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Remote Relay ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Status")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Delete(path="/station/{station_id}/sftp-user/{id}",
|
||||
* tags={"Stations: SFTP Users"},
|
||||
* description="Delete a single remote relay.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Remote Relay ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Status")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*/
|
||||
}
|
||||
|
|
|
@ -13,6 +13,93 @@ use OpenApi\Annotations as OA;
|
|||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
/**
|
||||
* @OA\Get(path="/station/{station_id}/streamers",
|
||||
* operationId="getStreamers",
|
||||
* tags={"Stations: Streamers/DJs"},
|
||||
* description="List all current Streamer/DJ accounts for the specified station.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(type="array", @OA\Items(ref="#/components/schemas/StationStreamer"))
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Post(path="/station/{station_id}/streamers",
|
||||
* operationId="addStreamer",
|
||||
* tags={"Stations: Streamers/DJs"},
|
||||
* description="Create a new Streamer/DJ account.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\RequestBody(
|
||||
* @OA\JsonContent(ref="#/components/schemas/StationStreamer")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/StationStreamer")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Get(path="/station/{station_id}/streamer/{id}",
|
||||
* operationId="getStreamer",
|
||||
* tags={"Stations: Streamers/DJs"},
|
||||
* description="Retrieve details for a single Streamer/DJ account.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Streamer ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/StationStreamer")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Put(path="/station/{station_id}/streamer/{id}",
|
||||
* operationId="editStreamer",
|
||||
* tags={"Stations: Streamers/DJs"},
|
||||
* description="Update details of a single Streamer/DJ account.",
|
||||
* @OA\RequestBody(
|
||||
* @OA\JsonContent(ref="#/components/schemas/StationStreamer")
|
||||
* ),
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Streamer ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Status")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Delete(path="/station/{station_id}/streamer/{id}",
|
||||
* operationId="deleteStreamer",
|
||||
* tags={"Stations: Streamers/DJs"},
|
||||
* description="Delete a single Streamer/DJ account.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="StationStreamer ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Status")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @extends AbstractScheduledEntityController<Entity\StationStreamer>
|
||||
*/
|
||||
class StreamersController extends AbstractScheduledEntityController
|
||||
|
@ -20,96 +107,6 @@ class StreamersController extends AbstractScheduledEntityController
|
|||
protected string $entityClass = Entity\StationStreamer::class;
|
||||
protected string $resourceRouteName = 'api:stations:streamer';
|
||||
|
||||
/**
|
||||
* @OA\Get(path="/station/{station_id}/streamers",
|
||||
* tags={"Stations: Streamers/DJs"},
|
||||
* description="List all current Streamer/DJ accounts for the specified station.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(type="array", @OA\Items(ref="#/components/schemas/StationStreamer"))
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Post(path="/station/{station_id}/streamers",
|
||||
* tags={"Stations: Streamers/DJs"},
|
||||
* description="Create a new Streamer/DJ account.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\RequestBody(
|
||||
* @OA\JsonContent(ref="#/components/schemas/StationStreamer")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/StationStreamer")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Get(path="/station/{station_id}/streamer/{id}",
|
||||
* tags={"Stations: Streamers/DJs"},
|
||||
* description="Retrieve details for a single Streamer/DJ account.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Streamer ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/StationStreamer")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Put(path="/station/{station_id}/streamer/{id}",
|
||||
* tags={"Stations: Streamers/DJs"},
|
||||
* description="Update details of a single Streamer/DJ account.",
|
||||
* @OA\RequestBody(
|
||||
* @OA\JsonContent(ref="#/components/schemas/StationStreamer")
|
||||
* ),
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Streamer ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Status")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Delete(path="/station/{station_id}/streamer/{id}",
|
||||
* tags={"Stations: Streamers/DJs"},
|
||||
* description="Delete a single Streamer/DJ account.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="StationStreamer ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Status")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*/
|
||||
|
||||
/**
|
||||
* Controller used to respond to AJAX requests from the streamer "Schedule View".
|
||||
*
|
||||
* @param ServerRequest $request
|
||||
* @param Response $response
|
||||
*/
|
||||
public function scheduleAction(ServerRequest $request, Response $response): ResponseInterface
|
||||
{
|
||||
$station = $request->getStation();
|
||||
|
|
|
@ -6,9 +6,97 @@ namespace App\Controller\Api\Stations;
|
|||
|
||||
use App\Entity;
|
||||
use App\Http\ServerRequest;
|
||||
use InvalidArgumentException;
|
||||
use OpenApi\Annotations as OA;
|
||||
|
||||
/**
|
||||
* @OA\Get(path="/station/{station_id}/webhooks",
|
||||
* operationId="getWebhooks",
|
||||
* tags={"Stations: Web Hooks"},
|
||||
* description="List all current web hooks.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(type="array", @OA\Items(ref="#/components/schemas/StationWebhook"))
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Post(path="/station/{station_id}/webhooks",
|
||||
* operationId="addWebhook",
|
||||
* tags={"Stations: Web Hooks"},
|
||||
* description="Create a new web hook.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\RequestBody(
|
||||
* @OA\JsonContent(ref="#/components/schemas/StationWebhook")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/StationWebhook")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Get(path="/station/{station_id}/webhook/{id}",
|
||||
* operationId="getWebhook",
|
||||
* tags={"Stations: Web Hooks"},
|
||||
* description="Retrieve details for a single web hook.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Web Hook ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/StationWebhook")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Put(path="/station/{station_id}/webhook/{id}",
|
||||
* operationId="editWebhook",
|
||||
* tags={"Stations: Web Hooks"},
|
||||
* description="Update details of a single web hook.",
|
||||
* @OA\RequestBody(
|
||||
* @OA\JsonContent(ref="#/components/schemas/StationWebhook")
|
||||
* ),
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Web Hook ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Status")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Delete(path="/station/{station_id}/webhook/{id}",
|
||||
* operationId="deleteWebhook",
|
||||
* tags={"Stations: Web Hooks"},
|
||||
* description="Delete a single web hook relay.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Web Hook ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Status")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @extends AbstractStationApiCrudController<Entity\StationWebhook>
|
||||
*/
|
||||
class WebhooksController extends AbstractStationApiCrudController
|
||||
|
@ -16,94 +104,10 @@ class WebhooksController extends AbstractStationApiCrudController
|
|||
protected string $entityClass = Entity\StationWebhook::class;
|
||||
protected string $resourceRouteName = 'api:stations:webhook';
|
||||
|
||||
/**
|
||||
* @OA\Get(path="/station/{station_id}/webhooks",
|
||||
* tags={"Stations: Web Hooks"},
|
||||
* description="List all current web hooks.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(type="array", @OA\Items(ref="#/components/schemas/StationWebhook"))
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Post(path="/station/{station_id}/webhooks",
|
||||
* tags={"Stations: Web Hooks"},
|
||||
* description="Create a new web hook.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\RequestBody(
|
||||
* @OA\JsonContent(ref="#/components/schemas/StationWebhook")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/StationWebhook")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Get(path="/station/{station_id}/webhook/{id}",
|
||||
* tags={"Stations: Web Hooks"},
|
||||
* description="Retrieve details for a single web hook.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Web Hook ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/StationWebhook")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Put(path="/station/{station_id}/webhook/{id}",
|
||||
* tags={"Stations: Web Hooks"},
|
||||
* description="Update details of a single web hook.",
|
||||
* @OA\RequestBody(
|
||||
* @OA\JsonContent(ref="#/components/schemas/StationWebhook")
|
||||
* ),
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Web Hook ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Status")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*
|
||||
* @OA\Delete(path="/station/{station_id}/webhook/{id}",
|
||||
* tags={"Stations: Web Hooks"},
|
||||
* description="Delete a single web hook relay.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Web Hook ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Status")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": {}}},
|
||||
* )
|
||||
*/
|
||||
|
||||
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,
|
||||
|
|
|
@ -95,7 +95,7 @@ class PodcastMedia implements IdentifiableEntityInterface
|
|||
public function setLength(float $length): self
|
||||
{
|
||||
$lengthMin = floor($length / 60);
|
||||
$lengthSec = $length % 60;
|
||||
$lengthSec = (int)$length % 60;
|
||||
|
||||
$this->length = $length;
|
||||
$this->length_text = $lengthMin . ':' . str_pad((string)$lengthSec, 2, '0', STR_PAD_LEFT);
|
||||
|
|
|
@ -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,11 +22,11 @@ class StationSchedule implements IdentifiableEntityInterface
|
|||
{
|
||||
use Traits\HasAutoIncrementId;
|
||||
|
||||
#[ORM\ManyToOne(inversedBy: 'schedules')]
|
||||
#[ORM\ManyToOne(inversedBy: 'schedule_items')]
|
||||
#[ORM\JoinColumn(name: 'playlist_id', referencedColumnName: 'id', nullable: true, onDelete: 'CASCADE')]
|
||||
protected ?StationPlaylist $playlist = null;
|
||||
|
||||
#[ORM\ManyToOne(inversedBy: 'schedules')]
|
||||
#[ORM\ManyToOne(inversedBy: 'schedule_items')]
|
||||
#[ORM\JoinColumn(name: 'streamer_id', referencedColumnName: 'id', nullable: true, onDelete: 'CASCADE')]
|
||||
protected ?StationStreamer $streamer = null;
|
||||
|
||||
|
|
|
@ -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 [];
|
||||
|
|
|
@ -34,7 +34,7 @@ else
|
|||
fi
|
||||
|
||||
APP_ENV="${APP_ENV:-production}"
|
||||
UPDATE_REVISION="${UPDATE_REVISION:-67}"
|
||||
UPDATE_REVISION="${UPDATE_REVISION:-68}"
|
||||
|
||||
echo "Updating AzuraCast (Environment: $APP_ENV, Update revision: $UPDATE_REVISION)"
|
||||
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
- gzip
|
||||
- zip
|
||||
- unzip
|
||||
- zstd
|
||||
|
||||
- name: Install Focal Packages (20.04)
|
||||
apt:
|
||||
|
|
|
@ -57,33 +57,46 @@
|
|||
- php7.4-bcmath
|
||||
- php7.4-gmp
|
||||
- php7.4-maxminddb
|
||||
- php8.0-fpm
|
||||
- php8.0-cli
|
||||
- php8.0-gd
|
||||
- php8.0-curl
|
||||
- php8.0-xml
|
||||
- php8.0-zip
|
||||
- php8.0-mysqlnd
|
||||
- php8.0-mbstring
|
||||
- php8.0-intl
|
||||
- php8.0-redis
|
||||
- php8.0-bcmath
|
||||
- php8.0-gmp
|
||||
- php8.0-maxminddb
|
||||
|
||||
- name : Install PHP 8.0
|
||||
- name : Install PHP 8.1
|
||||
apt :
|
||||
name : "{{ packages }}"
|
||||
state : latest
|
||||
vars :
|
||||
packages :
|
||||
- php8.0-fpm
|
||||
- php8.0-cli
|
||||
- php8.0-gd
|
||||
- php8.0-curl
|
||||
- php8.0-xml # IceCast XML config
|
||||
- php8.0-zip # Composer installs
|
||||
- php8.0-mysqlnd # MySQL Native Driver (Doctrine)
|
||||
- php8.0-mbstring # Codeception Tests
|
||||
- php8.0-intl # Localization
|
||||
- php8.0-redis # Cache
|
||||
- php8.0-bcmath # BigInteger
|
||||
- php8.0-gmp # BigInteger and PHP-IP
|
||||
- php8.0-maxminddb # Maxmind (GeoIP) DB native ext
|
||||
- php8.1-fpm
|
||||
- php8.1-cli
|
||||
- php8.1-gd
|
||||
- php8.1-curl
|
||||
- php8.1-xml # IceCast XML config
|
||||
- php8.1-zip # Composer installs
|
||||
- php8.1-mysqlnd # MySQL Native Driver (Doctrine)
|
||||
- php8.1-mbstring # Codeception Tests
|
||||
- php8.1-intl # Localization
|
||||
- php8.1-redis # Cache
|
||||
- php8.1-bcmath # BigInteger
|
||||
- php8.1-gmp # BigInteger and PHP-IP
|
||||
- php8.1-maxminddb # Maxmind (GeoIP) DB native ext
|
||||
|
||||
- name: Configure PHP FPM Pool
|
||||
template : src=fpmpool.j2 dest=/etc/php/8.0/fpm/pool.d/www.conf force=true
|
||||
template : src=fpmpool.j2 dest=/etc/php/8.1/fpm/pool.d/www.conf force=true
|
||||
|
||||
- name: Configure php-fpm php.ini
|
||||
ini_file:
|
||||
dest : /etc/php/8.0/fpm/php.ini
|
||||
dest : /etc/php/8.1/fpm/php.ini
|
||||
section: PHP
|
||||
option: "{{ item.option }}"
|
||||
value: "{{ item.value }}"
|
||||
|
@ -94,7 +107,7 @@
|
|||
|
||||
- name: Configure php-cli php.ini
|
||||
ini_file:
|
||||
dest : /etc/php/8.0/cli/php.ini
|
||||
dest : /etc/php/8.1/cli/php.ini
|
||||
section: PHP
|
||||
option: "{{ item.option }}"
|
||||
value: "{{ item.value }}"
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
- { role : nginx, when : update_revision|int < 60 }
|
||||
- { role : redis, when : update_revision|int < 57 }
|
||||
- { role: beanstalkd, when: update_revision|int < 67 }
|
||||
- { role : php, when : update_revision|int < 62 }
|
||||
- { role : php, when : update_revision|int < 68 }
|
||||
- composer
|
||||
- { role : influxdb, when : update_revision|int < 58 }
|
||||
- { role : ufw, when : update_revision|int < 12 }
|
||||
|
|
|
@ -5,4 +5,7 @@ set -x
|
|||
|
||||
apt-get update
|
||||
|
||||
# Prevent systemd auto-startup
|
||||
ln -s /dev/null /etc/systemd/system/beanstalkd.service
|
||||
|
||||
$minimal_apt_get_install beanstalkd
|
||||
|
|
|
@ -3,9 +3,10 @@ set -e
|
|||
source /bd_build/buildconfig
|
||||
set -x
|
||||
|
||||
$minimal_apt_get_install cron
|
||||
# Prevent systemd auto-startup
|
||||
ln -s /dev/null /etc/systemd/system/cron.service
|
||||
|
||||
service cron stop
|
||||
$minimal_apt_get_install cron
|
||||
|
||||
chmod 600 /etc/crontab
|
||||
|
||||
|
@ -21,4 +22,4 @@ rm -f /etc/cron.daily/password
|
|||
rm -f /etc/cron.weekly/fstrim
|
||||
|
||||
cp -r /bd_build/cron/. /etc/cron.d/
|
||||
chmod -R 600 /etc/cron.d/*
|
||||
chmod -R 600 /etc/cron.d/*
|
||||
|
|
|
@ -3,7 +3,7 @@ set -e
|
|||
source /bd_build/buildconfig
|
||||
set -x
|
||||
|
||||
PHP_VERSION=8.0
|
||||
PHP_VERSION=8.1
|
||||
|
||||
add-apt-repository -y ppa:ondrej/php
|
||||
apt-get update
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
source /bd_build/buildconfig
|
||||
set -x
|
||||
|
||||
$minimal_apt_get_install zstd
|
162
util/openapi.php
162
util/openapi.php
|
@ -2,80 +2,88 @@
|
|||
|
||||
use OpenApi\Annotations as OA;
|
||||
|
||||
/**
|
||||
* @OA\Info(
|
||||
* version=AZURACAST_VERSION,
|
||||
* title="AzuraCast",
|
||||
* description="AzuraCast is a standalone, turnkey web radio management tool. Radio stations hosted by AzuraCast expose a public API for viewing now playing data, making requests and more.",
|
||||
* @OA\License(
|
||||
* name="Apache 2.0",
|
||||
* url="http://www.apache.org/licenses/LICENSE-2.0.html"
|
||||
* )
|
||||
* )
|
||||
*
|
||||
* @OA\Server(
|
||||
* description=AZURACAST_API_NAME,
|
||||
* url=AZURACAST_API_URL
|
||||
* )
|
||||
*
|
||||
* @OA\ExternalDocumentation(
|
||||
* description="AzuraCast on GitHub",
|
||||
* url="https://github.com/AzuraCast/AzuraCast"
|
||||
* )
|
||||
*
|
||||
* @OA\Parameter(
|
||||
* parameter="station_id_required",
|
||||
* name="station_id",
|
||||
* description="The station ID",
|
||||
* example=1,
|
||||
* in="path",
|
||||
* required=true,
|
||||
* @OA\Schema(
|
||||
* anyOf={@OA\Schema(type="integer", format="int64"), @OA\Schema(type="string", format="string")}
|
||||
* )
|
||||
* )
|
||||
*
|
||||
* @OA\Response(
|
||||
* response="todo",
|
||||
* description="This API call has no documented response (yet)",
|
||||
* )
|
||||
*
|
||||
* @OA\Tag(
|
||||
* name="Now Playing",
|
||||
* description="Endpoints that provide full summaries of the current state of stations.",
|
||||
* )
|
||||
*
|
||||
* @OA\Tag(name="Stations: General")
|
||||
* @OA\Tag(name="Stations: Song Requests")
|
||||
* @OA\Tag(name="Stations: Service Control")
|
||||
*
|
||||
* @OA\Tag(name="Stations: History")
|
||||
* @OA\Tag(name="Stations: Listeners")
|
||||
* @OA\Tag(name="Stations: Schedules")
|
||||
* @OA\Tag(name="Stations: Media")
|
||||
* @OA\Tag(name="Stations: Mount Points")
|
||||
* @OA\Tag(name="Stations: Playlists")
|
||||
* @OA\Tag(name="Stations: Podcasts")
|
||||
* @OA\Tag(name="Stations: Queue")
|
||||
* @OA\Tag(name="Stations: Remote Relays")
|
||||
* @OA\Tag(name="Stations: SFTP Users")
|
||||
* @OA\Tag(name="Stations: Streamers/DJs")
|
||||
* @OA\Tag(name="Stations: Web Hooks")
|
||||
*
|
||||
* @OA\Tag(name="Administration: Custom Fields")
|
||||
* @OA\Tag(name="Administration: Users")
|
||||
* @OA\Tag(name="Administration: Relays")
|
||||
* @OA\Tag(name="Administration: Roles")
|
||||
* @OA\Tag(name="Administration: Settings")
|
||||
* @OA\Tag(name="Administration: Stations")
|
||||
* @OA\Tag(name="Administration: Storage Locations")
|
||||
*
|
||||
* @OA\Tag(name="Miscellaneous")
|
||||
*
|
||||
* @OA\SecurityScheme(
|
||||
* type="apiKey",
|
||||
* in="header",
|
||||
* securityScheme="api_key",
|
||||
* name="X-API-Key"
|
||||
* )
|
||||
*/
|
||||
#[
|
||||
OA\OpenApi(
|
||||
info: new OA\Info(
|
||||
version: AZURACAST_VERSION,
|
||||
title: 'AzuraCast',
|
||||
description: "AzuraCast is a standalone, turnkey web radio management tool. Radio stations hosted by AzuraCast expose a public API for viewing now playing data, making requests and more.",
|
||||
license: new OA\License(
|
||||
name: 'Apache 2.0',
|
||||
url: "http://www.apache.org/licenses/LICENSE-2.0.html"
|
||||
),
|
||||
),
|
||||
servers: [
|
||||
new OA\Server(
|
||||
description: AZURACAST_API_NAME,
|
||||
url: AZURACAST_API_URL
|
||||
),
|
||||
],
|
||||
externalDocs: new OA\ExternalDocumentation(
|
||||
description: "AzuraCast on GitHub",
|
||||
url: "https://github.com/AzuraCast/AzuraCast"
|
||||
),
|
||||
tags: [
|
||||
new OA\Tag(
|
||||
name: "Now Playing",
|
||||
description: "Endpoints that provide full summaries of the current state of stations.",
|
||||
),
|
||||
|
||||
new OA\Tag(name: "Stations: General"),
|
||||
new OA\Tag(name: "Stations: Song Requests"),
|
||||
new OA\Tag(name: "Stations: Service Control"),
|
||||
|
||||
new OA\Tag(name: "Stations: History"),
|
||||
new OA\Tag(name: "Stations: Listeners"),
|
||||
new OA\Tag(name: "Stations: Schedules"),
|
||||
new OA\Tag(name: "Stations: Media"),
|
||||
new OA\Tag(name: "Stations: Mount Points"),
|
||||
new OA\Tag(name: "Stations: Playlists"),
|
||||
new OA\Tag(name: "Stations: Podcasts"),
|
||||
new OA\Tag(name: "Stations: Queue"),
|
||||
new OA\Tag(name: "Stations: Remote Relays"),
|
||||
new OA\Tag(name: "Stations: SFTP Users"),
|
||||
new OA\Tag(name: "Stations: Streamers/DJs"),
|
||||
new OA\Tag(name: "Stations: Web Hooks"),
|
||||
|
||||
new OA\Tag(name: "Administration: Custom Fields"),
|
||||
new OA\Tag(name: "Administration: Users"),
|
||||
new OA\Tag(name: "Administration: Relays"),
|
||||
new OA\Tag(name: "Administration: Roles"),
|
||||
new OA\Tag(name: "Administration: Settings"),
|
||||
new OA\Tag(name: "Administration: Stations"),
|
||||
new OA\Tag(name: "Administration: Storage Locations"),
|
||||
|
||||
new OA\Tag(name: "Miscellaneous"),
|
||||
]
|
||||
),
|
||||
OA\Parameter(
|
||||
name: "station_id_required",
|
||||
in: "path",
|
||||
required: true,
|
||||
schema: new OA\Schema(
|
||||
properties: [
|
||||
'anyOf' => [
|
||||
new OA\Schema(type: "integer", format: "int64"),
|
||||
new OA\Schema(type: "string", format: "string")
|
||||
]
|
||||
]
|
||||
),
|
||||
),
|
||||
OA\Response(
|
||||
response: "todo",
|
||||
description: "This API call has no documented response (yet)",
|
||||
),
|
||||
OA\SecurityScheme(
|
||||
type: "apiKey",
|
||||
in: "header",
|
||||
securityScheme: "api_key",
|
||||
name: "X-API-Key"
|
||||
)
|
||||
]
|
||||
class OpenApi
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue