Part 1 of OpenAPI transition to Attributes.

This commit is contained in:
Buster "Silver Eagle" Neece 2021-12-12 05:01:53 -06:00
parent c2d97a1a36
commit 8042fa9025
No known key found for this signature in database
GPG Key ID: 0FFEF642C60EFD9E
29 changed files with 2183 additions and 1952 deletions

View File

@ -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",

28
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "2ab6f2e1f9e83b7c445c88755f0ae8de",
"content-hash": "0e9f976588b4012a62481a6e95a806e1",
"packages": [
{
"name": "aws/aws-crt-php",
@ -9779,28 +9779,28 @@
},
{
"name": "zircote/swagger-php",
"version": "3.3.2",
"version": "4.0.4",
"source": {
"type": "git",
"url": "https://github.com/zircote/swagger-php.git",
"reference": "68c76ce2bb43fb4603315fb973d4595711dcbfd3"
"reference": "c24704d90fbd296f889744d8da92c67653baef14"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/zircote/swagger-php/zipball/68c76ce2bb43fb4603315fb973d4595711dcbfd3",
"reference": "68c76ce2bb43fb4603315fb973d4595711dcbfd3",
"url": "https://api.github.com/repos/zircote/swagger-php/zipball/c24704d90fbd296f889744d8da92c67653baef14",
"reference": "c24704d90fbd296f889744d8da92c67653baef14",
"shasum": ""
},
"require": {
"doctrine/annotations": "^1.7",
"ext-json": "*",
"php": ">=7.2",
"psr/log": "^1.1",
"psr/log": "^1.1 || ^2.0 || 3.0",
"symfony/finder": ">=2.2",
"symfony/yaml": ">=3.3"
},
"require-dev": {
"composer/package-versions-deprecated": "1.11.99.2",
"composer/package-versions-deprecated": "^1.11",
"friendsofphp/php-cs-fixer": "^2.17 || ^3.0",
"phpunit/phpunit": ">=8"
},
@ -9808,13 +9808,15 @@
"bin/openapi"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.x-dev"
}
},
"autoload": {
"psr-4": {
"OpenApi\\": "src"
},
"files": [
"src/functions.php"
]
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
@ -9846,9 +9848,9 @@
],
"support": {
"issues": "https://github.com/zircote/swagger-php/issues",
"source": "https://github.com/zircote/swagger-php/tree/3.3.2"
"source": "https://github.com/zircote/swagger-php/tree/4.0.4"
},
"time": "2021-11-15T20:45:42+00:00"
"time": "2021-12-10T03:33:50+00:00"
}
],
"packages-dev": [

View File

@ -7,9 +7,11 @@ namespace App\Console\Command;
use App\Console\Application;
use App\Environment;
use App\Version;
use Monolog\Logger;
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,7 +19,8 @@ class GenerateApiDocsCommand extends CommandAbstract
public function __construct(
Application $application,
protected Environment $environment,
protected Version $version
protected Version $version,
protected LoggerInterface $logger
) {
parent::__construct($application);
}
@ -57,6 +60,8 @@ class GenerateApiDocsCommand extends CommandAbstract
]
);
return Generator::scan($finder);
return Generator::scan($finder, [
'logger' => $this->logger
]);
}
}

View File

@ -8,15 +8,8 @@ use App\Entity;
use OpenApi\Annotations as OA;
/**
* @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",
* operationId="getCustomFields",
* tags={"Administration: Custom Fields"},
* description="List all current custom fields in the system.",
* @OA\Response(response=200, description="Success",
@ -27,6 +20,7 @@ class CustomFieldsController extends AbstractAdminApiCrudController
* )
*
* @OA\Post(path="/admin/custom_fields",
* operationId="addCustomField",
* tags={"Administration: Custom Fields"},
* description="Create a new custom field.",
* @OA\RequestBody(
@ -40,6 +34,7 @@ class CustomFieldsController extends AbstractAdminApiCrudController
* )
*
* @OA\Get(path="/admin/custom_field/{id}",
* operationId="getCustomField",
* tags={"Administration: Custom Fields"},
* description="Retrieve details for a single custom field.",
* @OA\Parameter(
@ -57,6 +52,7 @@ class CustomFieldsController extends AbstractAdminApiCrudController
* )
*
* @OA\Put(path="/admin/custom_field/{id}",
* operationId="editCustomField",
* tags={"Administration: Custom Fields"},
* description="Update details of a single custom field.",
* @OA\RequestBody(
@ -75,7 +71,9 @@ class CustomFieldsController extends AbstractAdminApiCrudController
* @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(
@ -91,5 +89,11 @@ class CustomFieldsController extends AbstractAdminApiCrudController
* @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';
}

View File

@ -10,10 +10,9 @@ use App\Http\ServerRequest;
use OpenApi\Annotations as OA;
use Psr\Http\Message\ResponseInterface;
class PermissionsController
{
/**
/**
* @OA\Get(path="/admin/permissions",
* operationId="getPermissions",
* tags={"Administration: Roles"},
* description="Return a list of all available permissions.",
* @OA\Response(
@ -23,10 +22,9 @@ class PermissionsController
* @OA\Response(response=403, description="Access denied"),
* security={{"api_key": {}}},
* )
*
* @param ServerRequest $request
* @param Response $response
*/
class PermissionsController
{
public function __invoke(
ServerRequest $request,
Response $response,

View File

@ -13,16 +13,9 @@ use Doctrine\ORM\EntityManagerInterface;
use OpenApi\Annotations as OA;
use Psr\Http\Message\ResponseInterface;
class RelaysController
{
public function __construct(
protected EntityManagerInterface $em,
protected Adapters $adapters
) {
}
/**
/**
* @OA\Get(path="/internal/relays",
* operationId="internalGetRelayDetails",
* tags={"Administration: Relays"},
* description="Returns all necessary information to relay all 'relayable' stations.",
* parameters={},
@ -32,10 +25,15 @@ class RelaysController
* @OA\JsonContent(type="array", @OA\Items(ref="#/components/schemas/Api_Admin_Relay"))
* )
* )
*
* @param ServerRequest $request
* @param Response $response
*/
class RelaysController
{
public function __construct(
protected EntityManagerInterface $em,
protected Adapters $adapters
) {
}
public function __invoke(ServerRequest $request, Response $response): ResponseInterface
{
$stations = $this->getManageableStations($request);

View File

@ -15,25 +15,8 @@ use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Validator\Validator\ValidatorInterface;
/**
* @extends AbstractAdminApiCrudController<Entity\Role>
*/
class RolesController extends AbstractAdminApiCrudController
{
protected string $entityClass = Entity\Role::class;
protected string $resourceRouteName = 'api:admin:role';
public function __construct(
protected Acl $acl,
protected Entity\Repository\RolePermissionRepository $permissionRepo,
ReloadableEntityManagerInterface $em,
Serializer $serializer,
ValidatorInterface $validator
) {
parent::__construct($em, $serializer, $validator);
}
/**
* @OA\Get(path="/admin/roles",
* operationId="getRoles",
* tags={"Administration: Roles"},
* description="List all current roles in the system.",
* @OA\Response(response=200, description="Success",
@ -44,6 +27,7 @@ class RolesController extends AbstractAdminApiCrudController
* )
*
* @OA\Post(path="/admin/roles",
* operationId="addRole",
* tags={"Administration: Roles"},
* description="Create a new role.",
* @OA\RequestBody(
@ -57,6 +41,7 @@ class RolesController extends AbstractAdminApiCrudController
* )
*
* @OA\Get(path="/admin/role/{id}",
* operationId="getRole",
* tags={"Administration: Roles"},
* description="Retrieve details for a single current role.",
* @OA\Parameter(
@ -74,6 +59,7 @@ class RolesController extends AbstractAdminApiCrudController
* )
*
* @OA\Put(path="/admin/role/{id}",
* operationId="editRole",
* tags={"Administration: Roles"},
* description="Update details of a single role.",
* @OA\RequestBody(
@ -94,6 +80,7 @@ class RolesController extends AbstractAdminApiCrudController
* )
*
* @OA\Delete(path="/admin/role/{id}",
* operationId="deleteRole",
* tags={"Administration: Roles"},
* description="Delete a single role.",
* @OA\Parameter(
@ -110,8 +97,22 @@ class RolesController extends AbstractAdminApiCrudController
* security={{"api_key": {}}},
* )
*
* @inheritdoc
* @extends AbstractAdminApiCrudController<Entity\Role>
*/
class RolesController extends AbstractAdminApiCrudController
{
protected string $entityClass = Entity\Role::class;
protected string $resourceRouteName = 'api:admin:role';
public function __construct(
protected Acl $acl,
protected Entity\Repository\RolePermissionRepository $permissionRepo,
ReloadableEntityManagerInterface $em,
Serializer $serializer,
ValidatorInterface $validator
) {
parent::__construct($em, $serializer, $validator);
}
protected function deleteRecord(object $record): void
{

View File

@ -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,

View File

@ -18,27 +18,8 @@ use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Validator\Validator\ValidatorInterface;
/**
* @extends AbstractAdminApiCrudController<Entity\Station>
*/
class StationsController extends AbstractAdminApiCrudController
{
protected string $entityClass = Entity\Station::class;
protected string $resourceRouteName = 'api:admin:station';
public function __construct(
protected Entity\Repository\StationRepository $stationRepo,
protected Entity\Repository\StorageLocationRepository $storageLocationRepo,
protected Adapters $adapters,
protected Configuration $configuration,
protected ReloadableEntityManagerInterface $reloadableEm,
Serializer $serializer,
ValidatorInterface $validator
) {
parent::__construct($reloadableEm, $serializer, $validator);
}
/**
* @OA\Get(path="/admin/stations",
* operationId="adminGetStations",
* tags={"Administration: Stations"},
* description="List all current stations in the system.",
* @OA\Response(response=200, description="Success",
@ -49,6 +30,7 @@ class StationsController extends AbstractAdminApiCrudController
* )
*
* @OA\Post(path="/admin/stations",
* operationId="adminAddStation",
* tags={"Administration: Stations"},
* description="Create a new station.",
* @OA\RequestBody(
@ -62,6 +44,7 @@ class StationsController extends AbstractAdminApiCrudController
* )
*
* @OA\Get(path="/admin/station/{id}",
* operationId="adminGetStation",
* tags={"Administration: Stations"},
* description="Retrieve details for a single station.",
* @OA\Parameter(
@ -79,6 +62,7 @@ class StationsController extends AbstractAdminApiCrudController
* )
*
* @OA\Put(path="/admin/station/{id}",
* operationId="adminEditStation",
* tags={"Administration: Stations"},
* description="Update details of a single station.",
* @OA\RequestBody(
@ -99,6 +83,7 @@ class StationsController extends AbstractAdminApiCrudController
* )
*
* @OA\Delete(path="/admin/station/{id}",
* operationId="adminDeleteStation",
* tags={"Administration: Stations"},
* description="Delete a single station.",
* @OA\Parameter(
@ -114,7 +99,25 @@ class StationsController extends AbstractAdminApiCrudController
* @OA\Response(response=403, description="Access denied"),
* security={{"api_key": {}}},
* )
*
* @extends AbstractAdminApiCrudController<Entity\Station>
*/
class StationsController extends AbstractAdminApiCrudController
{
protected string $entityClass = Entity\Station::class;
protected string $resourceRouteName = 'api:admin:station';
public function __construct(
protected Entity\Repository\StationRepository $stationRepo,
protected Entity\Repository\StorageLocationRepository $storageLocationRepo,
protected Adapters $adapters,
protected Configuration $configuration,
protected ReloadableEntityManagerInterface $reloadableEm,
Serializer $serializer,
ValidatorInterface $validator
) {
parent::__construct($reloadableEm, $serializer, $validator);
}
protected function viewRecord(object $record, ServerRequest $request): mixed
{

View File

@ -16,24 +16,8 @@ use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Validator\Validator\ValidatorInterface;
/**
* @extends AbstractAdminApiCrudController<Entity\StorageLocation>
*/
class StorageLocationsController extends AbstractAdminApiCrudController
{
protected string $entityClass = Entity\StorageLocation::class;
protected string $resourceRouteName = 'api:admin:storage_location';
public function __construct(
protected Entity\Repository\StorageLocationRepository $storageLocationRepo,
ReloadableEntityManagerInterface $em,
Serializer $serializer,
ValidatorInterface $validator
) {
parent::__construct($em, $serializer, $validator);
}
/**
* @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",
@ -44,6 +28,7 @@ class StorageLocationsController extends AbstractAdminApiCrudController
* )
*
* @OA\Post(path="/admin/storage_locations",
* operationId="addStorageLocation",
* tags={"Administration: Storage Locations"},
* description="Create a new storage location.",
* @OA\RequestBody(
@ -57,6 +42,7 @@ class StorageLocationsController extends AbstractAdminApiCrudController
* )
*
* @OA\Get(path="/admin/storage_location/{id}",
* operationId="getStorageLocation",
* tags={"Administration: Storage Locations"},
* description="Retrieve details for a single storage location.",
* @OA\Parameter(
@ -74,6 +60,7 @@ class StorageLocationsController extends AbstractAdminApiCrudController
* )
*
* @OA\Put(path="/admin/storage_location/{id}",
* operationId="editStorageLocation",
* tags={"Administration: Storage Locations"},
* description="Update details of a single storage location.",
* @OA\RequestBody(
@ -94,6 +81,7 @@ class StorageLocationsController extends AbstractAdminApiCrudController
* )
*
* @OA\Delete(path="/admin/storage_location/{id}",
* operationId="deleteStorageLocation",
* tags={"Administration: Storage Locations"},
* description="Delete a single storage location.",
* @OA\Parameter(
@ -109,7 +97,22 @@ class StorageLocationsController extends AbstractAdminApiCrudController
* @OA\Response(response=403, description="Access denied"),
* security={{"api_key": {}}},
* )
*
* @extends AbstractAdminApiCrudController<Entity\StorageLocation>
*/
class StorageLocationsController extends AbstractAdminApiCrudController
{
protected string $entityClass = Entity\StorageLocation::class;
protected string $resourceRouteName = 'api:admin:storage_location';
public function __construct(
protected Entity\Repository\StorageLocationRepository $storageLocationRepo,
ReloadableEntityManagerInterface $em,
Serializer $serializer,
ValidatorInterface $validator
) {
parent::__construct($em, $serializer, $validator);
}
public function listAction(ServerRequest $request, Response $response): ResponseInterface
{

View File

@ -13,15 +13,8 @@ use OpenApi\Annotations as OA;
use Psr\Http\Message\ResponseInterface;
/**
* @extends AbstractAdminApiCrudController<Entity\User>
*/
class UsersController extends AbstractAdminApiCrudController
{
protected string $entityClass = Entity\User::class;
protected string $resourceRouteName = 'api:admin:user';
/**
* @OA\Get(path="/admin/users",
* operationId="getUsers",
* tags={"Administration: Users"},
* description="List all current users in the system.",
* @OA\Response(response=200, description="Success",
@ -32,6 +25,7 @@ class UsersController extends AbstractAdminApiCrudController
* )
*
* @OA\Post(path="/admin/users",
* operationId="addUser",
* tags={"Administration: Users"},
* description="Create a new user.",
* @OA\RequestBody(
@ -45,6 +39,7 @@ class UsersController extends AbstractAdminApiCrudController
* )
*
* @OA\Get(path="/admin/user/{id}",
* operationId="getUser",
* tags={"Administration: Users"},
* description="Retrieve details for a single current user.",
* @OA\Parameter(
@ -62,6 +57,7 @@ class UsersController extends AbstractAdminApiCrudController
* )
*
* @OA\Put(path="/admin/user/{id}",
* operationId="editUser",
* tags={"Administration: Users"},
* description="Update details of a single user.",
* @OA\RequestBody(
@ -80,7 +76,31 @@ class UsersController extends AbstractAdminApiCrudController
* @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
{
protected string $entityClass = Entity\User::class;
protected string $resourceRouteName = 'api:admin:user';
protected function viewRecord(object $record, ServerRequest $request): mixed
{
@ -136,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);

View File

@ -22,28 +22,8 @@ use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Validator\Validator\ValidatorInterface;
/**
* @extends AbstractStationApiCrudController<Entity\StationMedia>
*/
class FilesController extends AbstractStationApiCrudController
{
protected string $entityClass = Entity\StationMedia::class;
protected string $resourceRouteName = 'api:stations:file';
public function __construct(
protected Adapters $adapters,
protected MessageBus $messageBus,
protected Entity\Repository\CustomFieldRepository $customFieldsRepo,
protected Entity\Repository\StationMediaRepository $mediaRepo,
protected Entity\Repository\StationPlaylistMediaRepository $playlistMediaRepo,
ReloadableEntityManagerInterface $em,
Serializer $serializer,
ValidatorInterface $validator
) {
parent::__construct($em, $serializer, $validator);
}
/**
* @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"),
@ -55,6 +35,7 @@ class FilesController extends AbstractStationApiCrudController
* )
*
* @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"),
@ -69,6 +50,7 @@ class FilesController extends AbstractStationApiCrudController
* )
*
* @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"),
@ -87,6 +69,7 @@ class FilesController extends AbstractStationApiCrudController
* )
*
* @OA\Put(path="/station/{station_id}/file/{id}",
* operationId="editFile",
* tags={"Stations: Media"},
* description="Update details of a single file.",
* @OA\RequestBody(
@ -108,6 +91,7 @@ class FilesController extends AbstractStationApiCrudController
* )
*
* @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"),
@ -124,13 +108,27 @@ class FilesController extends AbstractStationApiCrudController
* @OA\Response(response=403, description="Access denied"),
* security={{"api_key": {}}},
* )
*/
/**
* @param ServerRequest $request
* @param Response $response
*
* @extends AbstractStationApiCrudController<Entity\StationMedia>
*/
class FilesController extends AbstractStationApiCrudController
{
protected string $entityClass = Entity\StationMedia::class;
protected string $resourceRouteName = 'api:stations:file';
public function __construct(
protected Adapters $adapters,
protected MessageBus $messageBus,
protected Entity\Repository\CustomFieldRepository $customFieldsRepo,
protected Entity\Repository\StationMediaRepository $mediaRepo,
protected Entity\Repository\StationPlaylistMediaRepository $playlistMediaRepo,
ReloadableEntityManagerInterface $em,
Serializer $serializer,
ValidatorInterface $validator
) {
parent::__construct($em, $serializer, $validator);
}
public function listAction(ServerRequest $request, Response $response): ResponseInterface
{
$storageLocation = $this->getStation($request)->getMediaStorageLocation();

View File

@ -15,16 +15,9 @@ use Doctrine\ORM\EntityManagerInterface;
use OpenApi\Annotations as OA;
use Psr\Http\Message\ResponseInterface;
class HistoryController
{
public function __construct(
protected EntityManagerInterface $em,
protected Entity\ApiGenerator\SongHistoryApiGenerator $songHistoryApiGenerator
) {
}
/**
/**
* @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"),
@ -55,7 +48,16 @@ class HistoryController
* @OA\Response(response=403, description="Access denied"),
* security={{"api_key": {}}},
* )
*
*/
class HistoryController
{
public function __construct(
protected EntityManagerInterface $em,
protected Entity\ApiGenerator\SongHistoryApiGenerator $songHistoryApiGenerator
) {
}
/**
* @param ServerRequest $request
* @param Response $response
*/

View File

@ -5,24 +5,15 @@ 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;
class IndexController
{
public function __construct(
protected EntityManagerInterface $em,
protected Entity\ApiGenerator\StationApiGenerator $stationApiGenerator
) {
}
/**
/**
* @OA\Get(path="/stations",
* operationId="getStations",
* tags={"Stations: General"},
* description="Returns a list of stations.",
* parameters={},
@ -32,12 +23,26 @@ class IndexController
* )
* )
* )
* @param ServerRequest $request
* @param Response $response
*
* @throws NotFoundException
* @throws Exception
* @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(
protected EntityManagerInterface $em,
protected Entity\ApiGenerator\StationApiGenerator $stationApiGenerator
) {
}
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();

View File

@ -20,10 +20,9 @@ use OpenApi\Annotations as OA;
use Psr\Http\Message\ResponseInterface;
use RuntimeException;
class ListenersAction
{
/**
/**
* @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"),
@ -37,6 +36,8 @@ class ListenersAction
* security={{"api_key": {}}},
* )
*/
class ListenersAction
{
public function __invoke(
ServerRequest $request,
Response $response,

View File

@ -17,24 +17,8 @@ use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Validator\Validator\ValidatorInterface;
/**
* @extends AbstractStationApiCrudController<Entity\StationMount>
*/
class MountsController extends AbstractStationApiCrudController
{
protected string $entityClass = Entity\StationMount::class;
protected string $resourceRouteName = 'api:stations:mount';
public function __construct(
ReloadableEntityManagerInterface $em,
Serializer $serializer,
ValidatorInterface $validator,
protected Entity\Repository\StationMountRepository $mountRepo
) {
parent::__construct($em, $serializer, $validator);
}
/**
* @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"),
@ -46,6 +30,7 @@ class MountsController extends AbstractStationApiCrudController
* )
*
* @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"),
@ -60,6 +45,7 @@ class MountsController extends AbstractStationApiCrudController
* )
*
* @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"),
@ -78,6 +64,7 @@ class MountsController extends AbstractStationApiCrudController
* )
*
* @OA\Put(path="/station/{station_id}/mount/{id}",
* operationId="editMount",
* tags={"Stations: Mount Points"},
* description="Update details of a single mount point.",
* @OA\RequestBody(
@ -99,6 +86,7 @@ class MountsController extends AbstractStationApiCrudController
* )
*
* @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"),
@ -115,7 +103,22 @@ class MountsController extends AbstractStationApiCrudController
* @OA\Response(response=403, description="Access denied"),
* security={{"api_key": {}}},
* )
*
* @extends AbstractStationApiCrudController<Entity\StationMount>
*/
class MountsController extends AbstractStationApiCrudController
{
protected string $entityClass = Entity\StationMount::class;
protected string $resourceRouteName = 'api:stations:mount';
public function __construct(
ReloadableEntityManagerInterface $em,
Serializer $serializer,
ValidatorInterface $validator,
protected Entity\Repository\StationMountRepository $mountRepo
) {
parent::__construct($em, $serializer, $validator);
}
protected function viewRecord(object $record, ServerRequest $request): mixed
{

View File

@ -14,15 +14,8 @@ use Psr\Http\Message\ResponseInterface;
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
/**
* @extends AbstractScheduledEntityController<Entity\StationPlaylist>
*/
class PlaylistsController extends AbstractScheduledEntityController
{
protected string $entityClass = Entity\StationPlaylist::class;
protected string $resourceRouteName = 'api:stations:playlist';
/**
* @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"),
@ -34,6 +27,7 @@ class PlaylistsController extends AbstractScheduledEntityController
* )
*
* @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"),
@ -48,6 +42,7 @@ class PlaylistsController extends AbstractScheduledEntityController
* )
*
* @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"),
@ -66,6 +61,7 @@ class PlaylistsController extends AbstractScheduledEntityController
* )
*
* @OA\Put(path="/station/{station_id}/playlist/{id}",
* operationId="editPlaylist",
* tags={"Stations: Playlists"},
* description="Update details of a single playlist.",
* @OA\RequestBody(
@ -87,6 +83,7 @@ class PlaylistsController extends AbstractScheduledEntityController
* )
*
* @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"),
@ -103,7 +100,13 @@ class PlaylistsController extends AbstractScheduledEntityController
* @OA\Response(response=403, description="Access denied"),
* security={{"api_key": {}}},
* )
*
* @extends AbstractScheduledEntityController<Entity\StationPlaylist>
*/
class PlaylistsController extends AbstractScheduledEntityController
{
protected string $entityClass = Entity\StationPlaylist::class;
protected string $resourceRouteName = 'api:stations:playlist';
/**
* @inheritDoc

View File

@ -13,32 +13,15 @@ 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;
/**
* @extends AbstractApiCrudController<Entity\PodcastEpisode>
*/
class PodcastEpisodesController extends AbstractApiCrudController
{
protected string $entityClass = Entity\PodcastEpisode::class;
protected string $resourceRouteName = 'api:stations:podcast:episode';
public function __construct(
ReloadableEntityManagerInterface $em,
Serializer $serializer,
ValidatorInterface $validator,
protected Entity\Repository\StationRepository $stationRepository,
protected Entity\Repository\PodcastRepository $podcastRepository,
protected Entity\Repository\PodcastEpisodeRepository $episodeRepository
) {
parent::__construct($em, $serializer, $validator);
}
/**
* @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"),
@ -57,6 +40,7 @@ class PodcastEpisodesController extends AbstractApiCrudController
* )
*
* @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"),
@ -78,6 +62,7 @@ class PodcastEpisodesController extends AbstractApiCrudController
* )
*
* @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"),
@ -103,6 +88,7 @@ class PodcastEpisodesController extends AbstractApiCrudController
* )
*
* @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(
@ -131,6 +117,7 @@ class PodcastEpisodesController extends AbstractApiCrudController
* )
*
* @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"),
@ -154,7 +141,24 @@ class PodcastEpisodesController extends AbstractApiCrudController
* @OA\Response(response=403, description="Access denied"),
* security={{"api_key": {}}},
* )
*
* @extends AbstractApiCrudController<Entity\PodcastEpisode>
*/
class PodcastEpisodesController extends AbstractApiCrudController
{
protected string $entityClass = Entity\PodcastEpisode::class;
protected string $resourceRouteName = 'api:stations:podcast:episode';
public function __construct(
ReloadableEntityManagerInterface $em,
Serializer $serializer,
ValidatorInterface $validator,
protected Entity\Repository\StationRepository $stationRepository,
protected Entity\Repository\PodcastRepository $podcastRepository,
protected Entity\Repository\PodcastEpisodeRepository $episodeRepository
) {
parent::__construct($em, $serializer, $validator);
}
public function listAction(
ServerRequest $request,

View File

@ -20,25 +20,8 @@ use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Validator\Validator\ValidatorInterface;
/**
* @extends AbstractApiCrudController<Entity\Podcast>
*/
class PodcastsController extends AbstractApiCrudController
{
protected string $entityClass = Entity\Podcast::class;
protected string $resourceRouteName = 'api:stations:podcast';
public function __construct(
ReloadableEntityManagerInterface $em,
Serializer $serializer,
ValidatorInterface $validator,
protected Entity\Repository\StationRepository $stationRepository,
protected Entity\Repository\PodcastRepository $podcastRepository
) {
parent::__construct($em, $serializer, $validator);
}
/**
* @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"),
@ -50,6 +33,7 @@ class PodcastsController extends AbstractApiCrudController
* )
*
* @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"),
@ -64,6 +48,7 @@ class PodcastsController extends AbstractApiCrudController
* )
*
* @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"),
@ -82,6 +67,7 @@ class PodcastsController extends AbstractApiCrudController
* )
*
* @OA\Put(path="/station/{station_id}/podcast/{id}",
* operationId="editPodcast",
* tags={"Stations: Podcasts"},
* description="Update details of a single podcast.",
* @OA\RequestBody(
@ -103,6 +89,7 @@ class PodcastsController extends AbstractApiCrudController
* )
*
* @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"),
@ -119,11 +106,24 @@ class PodcastsController extends AbstractApiCrudController
* @OA\Response(response=403, description="Access denied"),
* security={{"api_key": {}}},
* )
*
* @extends AbstractApiCrudController<Entity\Podcast>
*/
class PodcastsController extends AbstractApiCrudController
{
protected string $entityClass = Entity\Podcast::class;
protected string $resourceRouteName = 'api:stations:podcast';
public function __construct(
ReloadableEntityManagerInterface $em,
Serializer $serializer,
ValidatorInterface $validator,
protected Entity\Repository\StationRepository $stationRepository,
protected Entity\Repository\PodcastRepository $podcastRepository
) {
parent::__construct($em, $serializer, $validator);
}
/**
* @inheritDoc
*/
public function listAction(ServerRequest $request, Response $response): ResponseInterface
{
$station = $request->getStation();

View File

@ -15,25 +15,8 @@ use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Validator\Validator\ValidatorInterface;
/**
* @extends AbstractStationApiCrudController<Entity\StationQueue>
*/
class QueueController extends AbstractStationApiCrudController
{
protected string $entityClass = Entity\StationQueue::class;
protected string $resourceRouteName = 'api:stations:queue:record';
public function __construct(
protected Entity\ApiGenerator\StationQueueApiGenerator $queueApiGenerator,
protected Entity\Repository\StationQueueRepository $queueRepo,
App\Doctrine\ReloadableEntityManagerInterface $em,
Serializer $serializer,
ValidatorInterface $validator,
) {
parent::__construct($em, $serializer, $validator);
}
/**
* @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"),
@ -47,24 +30,8 @@ class QueueController extends AbstractStationApiCrudController
* security={{"api_key": {}}}
* )
*
* @inheritdoc
*/
public function listAction(
ServerRequest $request,
Response $response
): ResponseInterface {
$station = $request->getStation();
$query = $this->queueRepo->getUnplayedQuery($station);
return $this->listPaginatedFromQuery(
$request,
$response,
$query
);
}
/**
* @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"),
@ -84,6 +51,7 @@ class QueueController extends AbstractStationApiCrudController
* )
*
* @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"),
@ -101,7 +69,37 @@ class QueueController extends AbstractStationApiCrudController
* @OA\Response(response=403, description="Access denied"),
* security={{"api_key": {}}}
* )
*
* @extends AbstractStationApiCrudController<Entity\StationQueue>
*/
class QueueController extends AbstractStationApiCrudController
{
protected string $entityClass = Entity\StationQueue::class;
protected string $resourceRouteName = 'api:stations:queue:record';
public function __construct(
protected Entity\ApiGenerator\StationQueueApiGenerator $queueApiGenerator,
protected Entity\Repository\StationQueueRepository $queueRepo,
App\Doctrine\ReloadableEntityManagerInterface $em,
Serializer $serializer,
ValidatorInterface $validator,
) {
parent::__construct($em, $serializer, $validator);
}
public function listAction(
ServerRequest $request,
Response $response
): ResponseInterface {
$station = $request->getStation();
$query = $this->queueRepo->getUnplayedQuery($station);
return $this->listPaginatedFromQuery(
$request,
$response,
$query
);
}
/**
* @param object $record

View File

@ -11,15 +11,8 @@ use InvalidArgumentException;
use OpenApi\Annotations as OA;
/**
* @extends AbstractStationApiCrudController<Entity\StationRemote>
*/
class RemotesController extends AbstractStationApiCrudController
{
protected string $entityClass = Entity\StationRemote::class;
protected string $resourceRouteName = 'api:stations:remote';
/**
* @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"),
@ -31,6 +24,7 @@ class RemotesController extends AbstractStationApiCrudController
* )
*
* @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"),
@ -45,6 +39,7 @@ class RemotesController extends AbstractStationApiCrudController
* )
*
* @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"),
@ -63,6 +58,7 @@ class RemotesController extends AbstractStationApiCrudController
* )
*
* @OA\Put(path="/station/{station_id}/remote/{id}",
* operationId="editRelay",
* tags={"Stations: Remote Relays"},
* description="Update details of a single remote relay.",
* @OA\RequestBody(
@ -84,6 +80,7 @@ class RemotesController extends AbstractStationApiCrudController
* )
*
* @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"),
@ -100,7 +97,13 @@ class RemotesController extends AbstractStationApiCrudController
* @OA\Response(response=403, description="Access denied"),
* security={{"api_key": {}}},
* )
*
* @extends AbstractStationApiCrudController<Entity\StationRemote>
*/
class RemotesController extends AbstractStationApiCrudController
{
protected string $entityClass = Entity\StationRemote::class;
protected string $resourceRouteName = 'api:stations:remote';
protected function viewRecord(object $record, ServerRequest $request): mixed
{

View File

@ -14,17 +14,9 @@ use Doctrine\ORM\EntityManagerInterface;
use OpenApi\Annotations as OA;
use Psr\Http\Message\ResponseInterface;
class RequestsController
{
public function __construct(
protected EntityManagerInterface $em,
protected Entity\Repository\StationRequestRepository $requestRepo,
protected Entity\ApiGenerator\SongApiGenerator $songApiGenerator
) {
}
/**
/**
* @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"),
@ -40,12 +32,34 @@ class RequestsController
* @OA\Response(response=403, description="Station does not support requests")
* )
*
* @param ServerRequest $request
* @param Response $response
*
* @throws Exception
* @throws Exception\InvalidRequestAttribute
* @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(
protected EntityManagerInterface $em,
protected Entity\Repository\StationRequestRepository $requestRepo,
protected Entity\ApiGenerator\SongApiGenerator $songApiGenerator
) {
}
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();

View File

@ -16,12 +16,9 @@ use Psr\Http\Message\ResponseInterface;
use Symfony\Component\Cache\CacheItem;
use Symfony\Contracts\Cache\CacheInterface;
class ScheduleAction
{
use HasScheduleDisplay;
/**
/**
* @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"),
@ -48,6 +45,9 @@ class ScheduleAction
* @OA\Response(response=403, description="Access denied")
* )
*/
class ScheduleAction
{
use HasScheduleDisplay;
public function __invoke(
ServerRequest $request,

View File

@ -15,16 +15,9 @@ use Doctrine\ORM\EntityManagerInterface;
use OpenApi\Annotations as OA;
use Psr\Http\Message\ResponseInterface;
class ServicesController
{
public function __construct(
protected EntityManagerInterface $em,
protected Configuration $configuration
) {
}
/**
/**
* @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"),
@ -37,28 +30,8 @@ class ServicesController
* security={{"api_key": {}}}
* )
*
* @param ServerRequest $request
* @param Response $response
*/
public function statusAction(ServerRequest $request, Response $response): ResponseInterface
{
$station = $request->getStation();
$backend = $request->getStationBackend();
$frontend = $request->getStationFrontend();
return $response->withJson(
new Entity\Api\StationServiceStatus(
$backend->isRunning($station),
$frontend->isRunning($station),
$station->getHasStarted(),
$station->getNeedsRestart()
)
);
}
/**
* @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"),
@ -67,19 +40,8 @@ class ServicesController
* security={{"api_key": {}}}
* )
*
* @param ServerRequest $request
* @param Response $response
*/
public function restartAction(ServerRequest $request, Response $response): ResponseInterface
{
$station = $request->getStation();
$this->configuration->writeConfiguration($station, true);
return $response->withJson(new Entity\Api\Status(true, __('Station restarted.')));
}
/**
* @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"),
@ -98,10 +60,59 @@ class ServicesController
* security={{"api_key": {}}}
* )
*
* @param ServerRequest $request
* @param Response $response
* @param string $do
* @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(
protected EntityManagerInterface $em,
protected Configuration $configuration
) {
}
public function statusAction(ServerRequest $request, Response $response): ResponseInterface
{
$station = $request->getStation();
$backend = $request->getStationBackend();
$frontend = $request->getStationFrontend();
return $response->withJson(
new Entity\Api\StationServiceStatus(
$backend->isRunning($station),
$frontend->isRunning($station),
$station->getHasStarted(),
$station->getNeedsRestart()
)
);
}
public function restartAction(ServerRequest $request, Response $response): ResponseInterface
{
$station = $request->getStation();
$this->configuration->writeConfiguration($station, true);
return $response->withJson(new Entity\Api\Status(true, __('Station restarted.')));
}
public function frontendAction(
ServerRequest $request,
Response $response,
@ -141,31 +152,6 @@ 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,

View File

@ -8,15 +8,8 @@ use App\Entity;
use OpenApi\Annotations as OA;
/**
* @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",
* operationId="getSftpUsers",
* tags={"Stations: SFTP Users"},
* description="List all current SFTP users.",
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
@ -28,6 +21,7 @@ class SftpUsersController extends AbstractStationApiCrudController
* )
*
* @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"),
@ -42,6 +36,7 @@ class SftpUsersController extends AbstractStationApiCrudController
* )
*
* @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"),
@ -60,6 +55,7 @@ class SftpUsersController extends AbstractStationApiCrudController
* )
*
* @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(
@ -81,6 +77,7 @@ class SftpUsersController extends AbstractStationApiCrudController
* )
*
* @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"),
@ -97,5 +94,11 @@ class SftpUsersController extends AbstractStationApiCrudController
* @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';
}

View File

@ -13,15 +13,8 @@ use OpenApi\Annotations as OA;
use Psr\Http\Message\ResponseInterface;
/**
* @extends AbstractScheduledEntityController<Entity\StationStreamer>
*/
class StreamersController extends AbstractScheduledEntityController
{
protected string $entityClass = Entity\StationStreamer::class;
protected string $resourceRouteName = 'api:stations:streamer';
/**
* @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"),
@ -33,6 +26,7 @@ class StreamersController extends AbstractScheduledEntityController
* )
*
* @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"),
@ -47,6 +41,7 @@ class StreamersController extends AbstractScheduledEntityController
* )
*
* @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"),
@ -65,6 +60,7 @@ class StreamersController extends AbstractScheduledEntityController
* )
*
* @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(
@ -86,6 +82,7 @@ class StreamersController extends AbstractScheduledEntityController
* )
*
* @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"),
@ -102,14 +99,14 @@ class StreamersController extends AbstractScheduledEntityController
* @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
* @extends AbstractScheduledEntityController<Entity\StationStreamer>
*/
class StreamersController extends AbstractScheduledEntityController
{
protected string $entityClass = Entity\StationStreamer::class;
protected string $resourceRouteName = 'api:stations:streamer';
public function scheduleAction(ServerRequest $request, Response $response): ResponseInterface
{
$station = $request->getStation();

View File

@ -10,15 +10,8 @@ use InvalidArgumentException;
use OpenApi\Annotations as OA;
/**
* @extends AbstractStationApiCrudController<Entity\StationWebhook>
*/
class WebhooksController extends AbstractStationApiCrudController
{
protected string $entityClass = Entity\StationWebhook::class;
protected string $resourceRouteName = 'api:stations:webhook';
/**
* @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"),
@ -30,6 +23,7 @@ class WebhooksController extends AbstractStationApiCrudController
* )
*
* @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"),
@ -44,6 +38,7 @@ class WebhooksController extends AbstractStationApiCrudController
* )
*
* @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"),
@ -62,6 +57,7 @@ class WebhooksController extends AbstractStationApiCrudController
* )
*
* @OA\Put(path="/station/{station_id}/webhook/{id}",
* operationId="editWebhook",
* tags={"Stations: Web Hooks"},
* description="Update details of a single web hook.",
* @OA\RequestBody(
@ -83,6 +79,7 @@ class WebhooksController extends AbstractStationApiCrudController
* )
*
* @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"),
@ -99,7 +96,13 @@ class WebhooksController extends AbstractStationApiCrudController
* @OA\Response(response=403, description="Access denied"),
* security={{"api_key": {}}},
* )
*
* @extends AbstractStationApiCrudController<Entity\StationWebhook>
*/
class WebhooksController extends AbstractStationApiCrudController
{
protected string $entityClass = Entity\StationWebhook::class;
protected string $resourceRouteName = 'api:stations:webhook';
protected function viewRecord(object $record, ServerRequest $request): mixed
{

View File

@ -2,80 +2,86 @@
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(
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