133 lines
4.1 KiB
PHP
133 lines
4.1 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Controller\Api\Stations\Requests;
|
|
|
|
use App\Controller\Api\Stations\AbstractSearchableListAction;
|
|
use App\Entity\Api\StationRequest;
|
|
use App\Entity\ApiGenerator\SongApiGenerator;
|
|
use App\Entity\Station;
|
|
use App\Entity\StationMedia;
|
|
use App\Entity\StationPlaylist;
|
|
use App\Exception\StationUnsupportedException;
|
|
use App\Http\Response;
|
|
use App\Http\ServerRequest;
|
|
use App\OpenApi;
|
|
use App\Radio\AutoDJ\Scheduler;
|
|
use Carbon\CarbonImmutable;
|
|
use OpenApi\Attributes as OA;
|
|
use Psr\Cache\CacheItemPoolInterface;
|
|
use Psr\Http\Message\ResponseInterface;
|
|
|
|
#[
|
|
OA\Get(
|
|
path: '/station/{station_id}/requests',
|
|
operationId: 'getRequestableSongs',
|
|
description: 'Return a list of requestable songs.',
|
|
tags: ['Stations: Song Requests'],
|
|
parameters: [
|
|
new OA\Parameter(ref: OpenApi::REF_STATION_ID_REQUIRED),
|
|
],
|
|
responses: [
|
|
new OA\Response(
|
|
response: 200,
|
|
description: 'Success',
|
|
content: new OA\JsonContent(
|
|
type: 'array',
|
|
items: new OA\Items(ref: '#/components/schemas/Api_StationRequest')
|
|
)
|
|
),
|
|
new OA\Response(ref: OpenApi::REF_RESPONSE_ACCESS_DENIED, response: 403),
|
|
new OA\Response(ref: OpenApi::REF_RESPONSE_NOT_FOUND, response: 404),
|
|
new OA\Response(ref: OpenApi::REF_RESPONSE_GENERIC_ERROR, response: 500),
|
|
]
|
|
)
|
|
]
|
|
final class ListAction extends AbstractSearchableListAction
|
|
{
|
|
public function __construct(
|
|
private readonly Scheduler $scheduler,
|
|
SongApiGenerator $songApiGenerator,
|
|
CacheItemPoolInterface $psr6Cache,
|
|
) {
|
|
parent::__construct($songApiGenerator, $psr6Cache);
|
|
}
|
|
|
|
public function __invoke(
|
|
ServerRequest $request,
|
|
Response $response,
|
|
array $params
|
|
): ResponseInterface {
|
|
$station = $request->getStation();
|
|
|
|
$playlists = $this->getPlaylists($station);
|
|
if (empty($playlists)) {
|
|
throw StationUnsupportedException::requests();
|
|
}
|
|
|
|
$paginator = $this->getPaginator($request, $playlists);
|
|
|
|
$router = $request->getRouter();
|
|
|
|
$paginator->setPostprocessor(
|
|
function (StationMedia $media) use ($station, $router) {
|
|
$row = new StationRequest();
|
|
$row->song = ($this->songApiGenerator)($media, $station, $router->getBaseUrl());
|
|
$row->request_id = $media->getUniqueId();
|
|
$row->request_url = $router->named(
|
|
'api:requests:submit',
|
|
[
|
|
'station_id' => $station->getId(),
|
|
'media_id' => $media->getUniqueId(),
|
|
]
|
|
);
|
|
|
|
$row->resolveUrls($router->getBaseUrl());
|
|
|
|
return $row;
|
|
}
|
|
);
|
|
|
|
return $paginator->write($response);
|
|
}
|
|
|
|
/**
|
|
* @param Station $station
|
|
* @return int[]
|
|
*/
|
|
private function getPlaylists(
|
|
Station $station
|
|
): array {
|
|
$item = $this->psr6Cache->getItem('station_' . $station->getIdRequired() . '_requestable_playlists');
|
|
|
|
if (!$item->isHit()) {
|
|
$playlists = $this->em->createQuery(
|
|
<<<DQL
|
|
SELECT sp FROM App\Entity\StationPlaylist sp
|
|
WHERE sp.station = :station
|
|
AND sp.is_enabled = 1 AND sp.include_in_requests = 1
|
|
DQL
|
|
)->setParameter('station', $station)
|
|
->toIterable();
|
|
|
|
$ids = [];
|
|
$now = CarbonImmutable::now($station->getTimezoneObject());
|
|
|
|
/** @var StationPlaylist $playlist */
|
|
foreach ($playlists as $playlist) {
|
|
if ($this->scheduler->isPlaylistScheduledToPlayNow($playlist, $now, true)) {
|
|
$ids[] = $playlist->getIdRequired();
|
|
}
|
|
}
|
|
|
|
$item->set($ids);
|
|
$item->expiresAfter(600);
|
|
|
|
$this->psr6Cache->save($item);
|
|
}
|
|
|
|
return $item->get();
|
|
}
|
|
}
|