224 lines
7.2 KiB
PHP
224 lines
7.2 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Media;
|
|
|
|
use App\Doctrine\ReadWriteBatchIteratorAggregate;
|
|
use App\Entity;
|
|
use App\Flysystem\ExtendedFilesystemInterface;
|
|
use App\Utilities\File;
|
|
use Doctrine\ORM\EntityManagerInterface;
|
|
use Throwable;
|
|
|
|
final class BatchUtilities
|
|
{
|
|
public function __construct(
|
|
private readonly EntityManagerInterface $em,
|
|
private readonly Entity\Repository\StationMediaRepository $mediaRepo,
|
|
private readonly Entity\Repository\UnprocessableMediaRepository $unprocessableMediaRepo,
|
|
) {
|
|
}
|
|
|
|
public function handleRename(
|
|
string $from,
|
|
string $to,
|
|
Entity\StorageLocation $storageLocation,
|
|
?ExtendedFilesystemInterface $fs = null
|
|
): void {
|
|
$fs ??= $storageLocation->getFilesystem();
|
|
|
|
if ($fs->isDir($to)) {
|
|
// Update the paths of all media contained within the directory.
|
|
$toRename = [
|
|
$this->iterateMediaInDirectory($storageLocation, $from),
|
|
$this->iterateUnprocessableMediaInDirectory($storageLocation, $from),
|
|
$this->iteratePlaylistFoldersInDirectory($storageLocation, $from),
|
|
];
|
|
|
|
foreach ($toRename as $iterator) {
|
|
foreach ($iterator as $record) {
|
|
/** @var Entity\Interfaces\PathAwareInterface $record */
|
|
$record->setPath(
|
|
File::renameDirectoryInPath($record->getPath(), $from, $to)
|
|
);
|
|
$this->em->persist($record);
|
|
}
|
|
}
|
|
} else {
|
|
$record = $this->mediaRepo->findByPath($from, $storageLocation);
|
|
|
|
if ($record instanceof Entity\StationMedia) {
|
|
$record->setPath($to);
|
|
$this->em->persist($record);
|
|
$this->em->flush();
|
|
} else {
|
|
$record = $this->unprocessableMediaRepo->findByPath($from, $storageLocation);
|
|
|
|
if ($record instanceof Entity\UnprocessableMedia) {
|
|
$record->setPath($to);
|
|
$this->em->persist($record);
|
|
$this->em->flush();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param array $files
|
|
* @param array $directories
|
|
* @param Entity\StorageLocation $storageLocation
|
|
* @param ExtendedFilesystemInterface|null $fs
|
|
*
|
|
* @return Entity\StationPlaylist[] Affected playlists
|
|
*/
|
|
public function handleDelete(
|
|
array $files,
|
|
array $directories,
|
|
Entity\StorageLocation $storageLocation,
|
|
?ExtendedFilesystemInterface $fs = null
|
|
): array {
|
|
$fs ??= $storageLocation->getFilesystem();
|
|
$affectedPlaylists = [];
|
|
|
|
/*
|
|
* NOTE: This iteration clears the entity manager.
|
|
*/
|
|
foreach ($this->iterateMedia($storageLocation, $files) as $media) {
|
|
try {
|
|
foreach ($this->mediaRepo->remove($media, false, $fs) as $playlistId => $playlist) {
|
|
if (!isset($affectedPlaylists[$playlistId])) {
|
|
$affectedPlaylists[$playlistId] = $playlist;
|
|
}
|
|
}
|
|
} catch (Throwable) {
|
|
}
|
|
}
|
|
|
|
/*
|
|
* NOTE: This iteration clears the entity manager.
|
|
*/
|
|
foreach ($this->iterateUnprocessableMedia($storageLocation, $files) as $unprocessableMedia) {
|
|
$this->em->remove($unprocessableMedia);
|
|
}
|
|
|
|
foreach ($directories as $dir) {
|
|
foreach ($this->iteratePlaylistFoldersInDirectory($storageLocation, $dir) as $playlistFolder) {
|
|
$this->em->remove($playlistFolder);
|
|
}
|
|
}
|
|
|
|
$this->em->flush();
|
|
|
|
return $affectedPlaylists;
|
|
}
|
|
|
|
/**
|
|
* Iterate through the found media records, while occasionally flushing and clearing the entity manager.
|
|
*
|
|
* @note This function flushes the entity manager.
|
|
*
|
|
* @param Entity\StorageLocation $storageLocation
|
|
* @param array $paths
|
|
*
|
|
* @return iterable|Entity\StationMedia[]
|
|
*/
|
|
public function iterateMedia(Entity\StorageLocation $storageLocation, array $paths): iterable
|
|
{
|
|
return ReadWriteBatchIteratorAggregate::fromTraversableResult(
|
|
$this->mediaRepo->iteratePaths($paths, $storageLocation),
|
|
$this->em,
|
|
25
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @param Entity\StorageLocation $storageLocation
|
|
* @param string $dir
|
|
*
|
|
* @return iterable|Entity\StationMedia[]
|
|
*/
|
|
public function iterateMediaInDirectory(Entity\StorageLocation $storageLocation, string $dir): iterable
|
|
{
|
|
$query = $this->em->createQuery(
|
|
<<<'DQL'
|
|
SELECT sm
|
|
FROM App\Entity\StationMedia sm
|
|
WHERE sm.storage_location = :storageLocation
|
|
AND sm.path LIKE :path
|
|
DQL
|
|
)->setParameter('storageLocation', $storageLocation)
|
|
->setParameter('path', $dir . '/%');
|
|
|
|
return ReadWriteBatchIteratorAggregate::fromQuery($query, 25);
|
|
}
|
|
|
|
/**
|
|
* Iterate through unprocessable media, while occasionally flushing and clearing the entity manager.
|
|
*
|
|
* @note This function flushes the entity manager.
|
|
*
|
|
* @param Entity\StorageLocation $storageLocation
|
|
* @param array $paths
|
|
*
|
|
* @return iterable|Entity\UnprocessableMedia[]
|
|
*/
|
|
public function iterateUnprocessableMedia(Entity\StorageLocation $storageLocation, array $paths): iterable
|
|
{
|
|
return ReadWriteBatchIteratorAggregate::fromTraversableResult(
|
|
$this->unprocessableMediaRepo->iteratePaths($paths, $storageLocation),
|
|
$this->em,
|
|
25
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @param Entity\StorageLocation $storageLocation
|
|
* @param string $dir
|
|
*
|
|
* @return iterable|Entity\UnprocessableMedia[]
|
|
*/
|
|
public function iterateUnprocessableMediaInDirectory(
|
|
Entity\StorageLocation $storageLocation,
|
|
string $dir
|
|
): iterable {
|
|
$query = $this->em->createQuery(
|
|
<<<'DQL'
|
|
SELECT upm
|
|
FROM App\Entity\UnprocessableMedia upm
|
|
WHERE upm.storage_location = :storageLocation
|
|
AND upm.path LIKE :path
|
|
DQL
|
|
)->setParameter('storageLocation', $storageLocation)
|
|
->setParameter('path', $dir . '/%');
|
|
|
|
return ReadWriteBatchIteratorAggregate::fromQuery($query, 25);
|
|
}
|
|
|
|
/**
|
|
* @param Entity\StorageLocation $storageLocation
|
|
* @param string $dir
|
|
*
|
|
* @return iterable|Entity\StationPlaylistFolder[]
|
|
*/
|
|
public function iteratePlaylistFoldersInDirectory(
|
|
Entity\StorageLocation $storageLocation,
|
|
string $dir
|
|
): iterable {
|
|
$query = $this->em->createQuery(
|
|
<<<'DQL'
|
|
SELECT spf
|
|
FROM App\Entity\StationPlaylistFolder spf
|
|
WHERE spf.station IN (
|
|
SELECT s FROM App\Entity\Station s
|
|
WHERE s.media_storage_location = :storageLocation
|
|
)
|
|
AND spf.path LIKE :path
|
|
DQL
|
|
)->setParameter('storageLocation', $storageLocation)
|
|
->setParameter('path', $dir . '%');
|
|
|
|
return ReadWriteBatchIteratorAggregate::fromQuery($query, 25);
|
|
}
|
|
}
|