Working implementation of "Apply to Folders" feature.

This commit is contained in:
Buster Neece 2023-06-15 18:19:11 -05:00
parent c01f3c580c
commit 999b389ee9
No known key found for this signature in database
6 changed files with 127 additions and 29 deletions

View File

@ -195,7 +195,7 @@ final class BatchAction implements SingleActionInterface
foreach ($result->directories as $dir) {
try {
$this->playlistFolderRepo->setPlaylistsForFolder($station, $playlists, $dir);
$this->playlistFolderRepo->setPlaylistsForFolder($station, $dir, $playlists);
} catch (Exception $e) {
$result->errors[] = $dir . ': ' . $e->getMessage();
}

View File

@ -24,8 +24,7 @@ final class GetApplyToAction implements SingleActionInterface
ServerRequest $request,
Response $response,
array $params
): ResponseInterface
{
): ResponseInterface {
/** @var string $id */
$id = $params['id'];

View File

@ -5,6 +5,7 @@ declare(strict_types=1);
namespace App\Controller\Api\Stations\Playlists;
use App\Controller\SingleActionInterface;
use App\Entity\Api\Status;
use App\Entity\Repository\StationPlaylistFolderRepository;
use App\Entity\Repository\StationPlaylistRepository;
use App\Http\Response;
@ -42,9 +43,22 @@ final class PutApplyToAction extends AbstractClonableAction implements SingleAct
$record,
$record->getName() . ' - ' . $directory
);
} else {
$playlist = $record;
}
$this->folderRepo->setPlaylistsForFolder();
$this->folderRepo->addPlaylistsToFolder(
$station,
$directory,
[$playlist]
);
}
return $response->withJson(
new Status(
true,
__('Playlist applied to folders.')
)
);
}
}

View File

@ -8,6 +8,7 @@ use App\Entity\Enums\PlaylistSources;
use App\Entity\Station;
use App\Entity\StationPlaylist;
use App\Entity\StationPlaylistFolder;
use App\Utilities\Arrays;
/**
* @extends AbstractStationBasedRepository<StationPlaylistFolder>
@ -16,41 +17,105 @@ final class StationPlaylistFolderRepository extends AbstractStationBasedReposito
{
protected string $entityClass = StationPlaylistFolder::class;
/**
* @param Station $station
* @param StationPlaylist[] $playlists
* @param string $path
*/
public function setPlaylistsForFolder(
public function addPlaylistsToFolder(
Station $station,
array $playlists,
string $path
string $path,
array $playlists
): void {
if (str_contains($path, '://')) {
[, $path] = explode('://', $path, 2);
$playlists = $this->getEligiblePlaylists($playlists);
foreach ($this->getPlaylistIdsForFolder($station, $path) as $playlistId) {
unset($playlists[$playlistId]);
}
$this->em->createQuery(
<<<'DQL'
DELETE FROM App\Entity\StationPlaylistFolder spf
WHERE spf.station = :station AND spf.path = :path
DQL
)->setParameter('station', $station)
->setParameter('path', $path)
->execute();
foreach ($playlists as $playlistId => $playlistRecord) {
if (PlaylistSources::Songs === $playlistRecord->getSource()) {
/** @var StationPlaylist $playlist */
$playlist = $this->em->getReference(StationPlaylist::class, $playlistId);
/** @var StationPlaylist $playlist */
$playlist = $this->em->getReference(StationPlaylist::class, $playlistId);
$newRecord = new StationPlaylistFolder($station, $playlist, $path);
$this->em->persist($newRecord);
}
$newRecord = new StationPlaylistFolder($station, $playlist, $path);
$this->em->persist($newRecord);
}
$this->em->flush();
}
/**
* @param Station $station
* @param string $path
* @param StationPlaylist[] $playlists
*/
public function setPlaylistsForFolder(
Station $station,
string $path,
array $playlists
): void {
$playlists = $this->getEligiblePlaylists($playlists);
$toDelete = [];
foreach ($this->getPlaylistIdsForFolder($station, $path) as $playlistId) {
if (isset($playlists[$playlistId])) {
unset($playlists[$playlistId]);
} else {
$toDelete[] = $playlistId;
}
}
if (0 !== count($toDelete)) {
$this->em->createQuery(
<<<'DQL'
DELETE FROM App\Entity\StationPlaylistFolder spf
WHERE spf.station = :station
AND spf.path = :path
AND spf.playlist_id IN (:playlistIds)
DQL
)->setParameter('station', $station)
->setParameter('path', $path)
->setParameter('playlistIds', $toDelete)
->execute();
}
foreach ($playlists as $playlistId => $playlistRecord) {
/** @var StationPlaylist $playlist */
$playlist = $this->em->getReference(StationPlaylist::class, $playlistId);
$newRecord = new StationPlaylistFolder($station, $playlist, $path);
$this->em->persist($newRecord);
}
$this->em->flush();
}
/**
* @param array<array-key, StationPlaylist> $playlists
* @return array<int, StationPlaylist>
*/
protected function getEligiblePlaylists(array $playlists): array
{
return Arrays::keyByCallable(
array_filter(
$playlists,
fn(StationPlaylist $playlist) => PlaylistSources::Songs === $playlist->getSource()
),
fn(StationPlaylist $playlist) => $playlist->getIdRequired()
);
}
/**
* @return int[]
*/
protected function getPlaylistIdsForFolder(
Station $station,
string $path
): array {
return $this->em->createQuery(
<<<'DQL'
SELECT spf.playlist_id
FROM App\Entity\StationPlaylistFolder spf
WHERE spf.station = :station AND spf.path = :path
DQL
)->setParameter('station', $station)
->setParameter('path', $path)
->getSingleColumnResult();
}
}

View File

@ -26,6 +26,9 @@ class StationPlaylistFolder implements
#[ORM\JoinColumn(name: 'playlist_id', referencedColumnName: 'id', nullable: false, onDelete: 'CASCADE')]
protected StationPlaylist $playlist;
#[ORM\Column(nullable: false, insertable: false, updatable: false)]
protected int $playlist_id;
#[ORM\Column(length: 500)]
protected string $path;

View File

@ -106,4 +106,21 @@ final class Arrays
return $merged;
}
/**
* @template T of object
*
* @param array<array-key, T> $objects
* @param callable $keyFunction
* @return array<array-key, T>
*/
public static function keyByCallable(array $objects, callable $keyFunction): array
{
$newArray = [];
foreach ($objects as $object) {
$newArray[$keyFunction($object)] = $object;
}
return $newArray;
}
}