Skip to content

Commit

Permalink
Feaure copy between lic (#87)
Browse files Browse the repository at this point in the history
* Wip copy between licences
* Search by url
  • Loading branch information
TomasHermanek authored Oct 23, 2024
1 parent e55ecf4 commit 3db2b48
Show file tree
Hide file tree
Showing 42 changed files with 1,220 additions and 48 deletions.
1 change: 1 addition & 0 deletions .env.test
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ MESSENGER_DISTRIBUTION_TOPIC=anzu_core_dam_distribution
MESSENGER_DISTRIBUTION_REMOTE_PROCESSED_CHECK_TOPIC=anzu_core_dam_distribution_remote_check
MESSENGER_NOTIFICATION_TOPIC=notification_server_internal
MESSENGER_PROPERTY_REFRESH_TOPIC=anzu_core_dam_property_refresh
MESSENGER_ASSET_COPY_TOPIC=anzu_core_dam_asset_copy

YOUTUBE_API_KEY=''

Expand Down
1 change: 1 addition & 0 deletions psalm.xml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
<RedundantCast errorLevel="suppress"/>
<MoreSpecificReturnType errorLevel="suppress"/>
<LessSpecificReturnStatement errorLevel="suppress"/>
<DeprecatedTrait errorLevel="suppress"/>
<MissingConstructor errorLevel="suppress"/>
<PropertyNotSetInConstructor errorLevel="suppress"/>
<UnsafeInstantiation errorLevel="suppress"/>
Expand Down
29 changes: 29 additions & 0 deletions src/Controller/Api/Adm/V1/ImageController.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use AnzuSystems\CoreDamBundle\Domain\AssetFile\AssetFileDownloadFacade;
use AnzuSystems\CoreDamBundle\Domain\AssetFileRoute\AssetFileRouteFacade;
use AnzuSystems\CoreDamBundle\Domain\Chunk\ChunkFacade;
use AnzuSystems\CoreDamBundle\Domain\Image\ImageCopyFacade;
use AnzuSystems\CoreDamBundle\Domain\Image\ImageFacade;
use AnzuSystems\CoreDamBundle\Domain\Image\ImagePositionFacade;
use AnzuSystems\CoreDamBundle\Domain\Image\ImageStatusFacade;
Expand All @@ -25,20 +26,26 @@
use AnzuSystems\CoreDamBundle\Exception\AssetSlotUsedException;
use AnzuSystems\CoreDamBundle\Exception\ForbiddenOperationException;
use AnzuSystems\CoreDamBundle\Exception\InvalidExtSystemConfigurationException;
use AnzuSystems\CoreDamBundle\Model\Attributes\SerializeIterableParam;
use AnzuSystems\CoreDamBundle\Model\Dto\Asset\AssetAdmFinishDto;
use AnzuSystems\CoreDamBundle\Model\Dto\AssetExternalProvider\UploadAssetFromExternalProviderDto;
use AnzuSystems\CoreDamBundle\Model\Dto\AssetFileRoute\AssetFileRouteAdmDetailDecorator;
use AnzuSystems\CoreDamBundle\Model\Dto\Audio\AudioFileAdmDetailDto;
use AnzuSystems\CoreDamBundle\Model\Dto\Chunk\ChunkAdmCreateDto;
use AnzuSystems\CoreDamBundle\Model\Dto\Image\AssetFileCopyResultDto;
use AnzuSystems\CoreDamBundle\Model\Dto\Image\ImageAdmCreateDto;
use AnzuSystems\CoreDamBundle\Model\Dto\Image\ImageCopyDto;
use AnzuSystems\CoreDamBundle\Model\Dto\Image\ImageFileAdmDetailDto;
use AnzuSystems\CoreDamBundle\Model\OpenApi\Request\OARequest as OADamRequest;
use AnzuSystems\CoreDamBundle\Security\Permission\DamPermissions;
use AnzuSystems\SerializerBundle\Attributes\SerializeParam;
use AnzuSystems\SerializerBundle\Exception\SerializerException;
use Doctrine\Common\Collections\Collection;
use OpenApi\Attributes as OA;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
use Throwable;

#[Route(path: '/image', name: 'adm_image_v1_')]
#[OA\Tag('Image')]
Expand All @@ -51,6 +58,7 @@ public function __construct(
private readonly AssetFileDownloadFacade $assetFileDownloadFacade,
private readonly ImagePositionFacade $imagePositionFacade,
private readonly AssetFileRouteFacade $routeFacade,
private readonly ImageCopyFacade $imageCopyFacade,
) {
}

Expand Down Expand Up @@ -273,6 +281,27 @@ public function generateDownloadUrl(ImageFile $image): JsonResponse
);
}

/**
* @param Collection<int, ImageCopyDto> $copyList
* @throws Throwable
*
* @throws ForbiddenOperationException
*/
#[Route(
path: '/copy-to-licence',
name: 'copy_image',
methods: [Request::METHOD_PATCH]
)]
#[OADamRequest([ImageCopyDto::class]), OAResponse([AssetFileCopyResultDto::class]), OAResponseValidation]
public function copyToLicence(#[SerializeIterableParam(type: ImageCopyDto::class)] Collection $copyList): JsonResponse
{
$this->denyAccessUnlessGranted(DamPermissions::DAM_IMAGE_CREATE);

return $this->okResponse(
$this->imageCopyFacade->prepareCopyList($copyList)
);
}

/**
* @throws ForbiddenOperationException
*/
Expand Down
3 changes: 2 additions & 1 deletion src/Controller/ImageController.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Routing\Requirement\Requirement;

#[Route(path: '/image', name: 'image_')]
final class ImageController extends AbstractImageController
Expand Down Expand Up @@ -77,7 +78,7 @@ public function animation(
path: '/{requestWidth}{requestHeight}{regionOfInterestId}{quality}/{imageId}.jpg',
name: 'get_one_file_name',
requirements: [
'imageId' => '[0-9a-zA-Z-]+',
'imageId' => Requirement::UUID,
'requestWidth' => 'w\d+',
'requestHeight' => '-h\d+',
'regionOfInterestId' => '(-c\d+)|',
Expand Down
17 changes: 8 additions & 9 deletions src/DataFixtures/AssetLicenceFixtures.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,20 +46,19 @@ public function load(ProgressBar $progressBar): void

private function getData(): Generator
{
$existingLicence = $this->assetLicenceRepository->find(self::DEFAULT_LICENCE_ID);
if ($existingLicence) {
return;
}

/** @var ExtSystem $cmsExtSystem */
$cmsExtSystem = $this->entityManager->find(
ExtSystem::class,
1
);

yield (new AssetLicence())
->setId(self::DEFAULT_LICENCE_ID)
->setExtId('1')
->setExtSystem($cmsExtSystem);
$existingLicence = $this->assetLicenceRepository->find(self::DEFAULT_LICENCE_ID);
if (null === $existingLicence) {
yield (new AssetLicence())
->setId(self::DEFAULT_LICENCE_ID)
->setExtId('1')
->setExtSystem($cmsExtSystem);
}

}
}
28 changes: 28 additions & 0 deletions src/DependencyInjection/AnzuSystemsCoreDamExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
use AnzuSystems\CoreDamBundle\Messenger\Message\AssetFileMetadataProcessMessage;
use AnzuSystems\CoreDamBundle\Messenger\Message\AssetRefreshPropertiesMessage;
use AnzuSystems\CoreDamBundle\Messenger\Message\AudioFileChangeStateMessage;
use AnzuSystems\CoreDamBundle\Messenger\Message\CopyAssetFileMessage;
use AnzuSystems\CoreDamBundle\Messenger\Message\DistributeMessage;
use AnzuSystems\CoreDamBundle\Messenger\Message\DistributionRemoteProcessingCheckMessage;
use AnzuSystems\CoreDamBundle\Messenger\Message\DocumentFileChangeStateMessage;
Expand Down Expand Up @@ -108,6 +109,8 @@ public function prepend(ContainerBuilder $container): void
$distributionRemoteProcessedCheckTopicDsn = "%env(MESSENGER_TRANSPORT_DSN)%/{$distributionRemoteProcessedCheckTopic}";
$assetPropertyRefreshTopic = '%env(MESSENGER_PROPERTY_REFRESH_TOPIC)%';
$assetPropertyRefreshTopicDsn = "%env(MESSENGER_TRANSPORT_DSN)%/{$assetPropertyRefreshTopic}";
$assetCopyTopic = '%env(MESSENGER_ASSET_COPY_TOPIC)%';
$assetCopyTopicDsn = "%env(MESSENGER_TRANSPORT_DSN)%/{$assetCopyTopic}";

$container->prependExtensionConfig('framework', [
'messenger' => [
Expand Down Expand Up @@ -362,6 +365,30 @@ public function prepend(ContainerBuilder $container): void
],
],
],
$assetCopyTopic => [
'dsn' => $assetCopyTopicDsn,
'options' => [
'topic' => [
'name' => $assetCopyTopic,
'options' => [
'labels' => [
'application' => $applicationName,
'name' => $assetCopyTopic,
'topic' => $assetCopyTopic,
],
],
],
'subscription' => [
'name' => $assetCopyTopic,
'options' => [
'labels' => [
'application' => $applicationName,
'name' => $assetCopyTopic,
],
],
],
],
],
],
'routing' => [
VideoFileChangeStateMessage::class => $videoFileChangeStateTopic,
Expand All @@ -374,6 +401,7 @@ public function prepend(ContainerBuilder $container): void
DistributionRemoteProcessingCheckMessage::class => $distributionRemoteProcessedCheckTopic,
JwVideoThumbnailPosterMessage::class => $distributionRemoteProcessedCheckTopic,
AssetRefreshPropertiesMessage::class => $assetPropertyRefreshTopic,
CopyAssetFileMessage::class => $assetCopyTopic,
],
],
]);
Expand Down
68 changes: 68 additions & 0 deletions src/Domain/Asset/AssetCopyBuilder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<?php

declare(strict_types=1);

namespace AnzuSystems\CoreDamBundle\Domain\Asset;

use AnzuSystems\CoreDamBundle\Domain\AbstractManager;
use AnzuSystems\CoreDamBundle\Domain\AssetFile\AssetFileFactory;
use AnzuSystems\CoreDamBundle\Domain\AssetMetadata\AssetMetadataManager;
use AnzuSystems\CoreDamBundle\Domain\AssetSlot\AssetSlotManager;
use AnzuSystems\CoreDamBundle\Entity\Asset;
use AnzuSystems\CoreDamBundle\Entity\AssetLicence;
use AnzuSystems\CoreDamBundle\Entity\AssetSlot;
use AnzuSystems\CoreDamBundle\Model\Enum\AssetStatus;

class AssetCopyBuilder extends AbstractManager
{
public function __construct(
private readonly AssetMetadataManager $assetMetadataManager,
private readonly AssetFileFactory $assetFileFactory,
private readonly AssetSlotManager $assetSlotManager,
) {
}

public function buildDraftAssetCopy(Asset $asset, AssetLicence $assetLicence, bool $flush = true): Asset
{
$assetCopy = $asset->__copy();
$assetCopy->getAttributes()->setStatus(AssetStatus::Draft);
$this->trackCreation($assetCopy);
$assetCopy->setLicence($assetLicence);
$assetCopy->setExtSystem($assetLicence->getExtSystem());
$this->entityManager->persist($assetCopy);
$this->assetMetadataManager->create($assetCopy->getMetadata(), false);
$this->copySlots($asset, $assetCopy);

foreach ($assetCopy->getSlots() as $assetSlot) {
if ($assetSlot->getFlags()->isMain()) {
$assetCopy->setMainFile($assetSlot->getAssetFile());

break;
}
}

$this->flush($flush);

return $assetCopy;
}

private function copySlots(Asset $asset, Asset $assetCopy): void
{
foreach ($asset->getSlots() as $assetSlot) {
$slotCopy = $this->copySlotToAsset($assetSlot, $assetCopy);
$assetCopy->addSlot($slotCopy);
$slotCopy->setAsset($assetCopy);
}
}

private function copySlotToAsset(AssetSlot $assetSlot, Asset $assetCopy): AssetSlot
{
$slotCopy = $assetSlot->__copy();
$blankAssetFile = $this->assetFileFactory->createForAsset($assetCopy);
$blankAssetFile->setAsset($assetCopy);
$blankAssetFile->addSlot($slotCopy);
$this->assetSlotManager->create($slotCopy, false);

return $slotCopy;
}
}
14 changes: 14 additions & 0 deletions src/Domain/AssetFile/AbstractAssetFileFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use AnzuSystems\CoreDamBundle\Domain\AssetFileMetadata\AssetFileMetadataManager;
use AnzuSystems\CoreDamBundle\Domain\Configuration\ExtSystemConfigurationProvider;
use AnzuSystems\CoreDamBundle\Domain\Image\ImageStatusFacade;
use AnzuSystems\CoreDamBundle\Entity\Asset;
use AnzuSystems\CoreDamBundle\Entity\AssetFile;
use AnzuSystems\CoreDamBundle\Entity\AssetFileMetadata;
use AnzuSystems\CoreDamBundle\Entity\AssetLicence;
Expand Down Expand Up @@ -104,6 +105,19 @@ public function createFromFile(AdapterFile $file, AssetLicence $assetLicence, ?s
return $assetFile;
}

public function createForAsset(Asset $asset): AssetFile
{
/** @var T $assetFile */
$assetFile = match ($asset->getAssetType()) {
AssetType::Image => $this->createBlankImage($asset->getLicence()),
AssetType::Video => $this->createBlankVideo($asset->getLicence()),
AssetType::Audio => $this->createBlankAudio($asset->getLicence()),
AssetType::Document => $this->createBlankDocument($asset->getLicence()),
};

return $this->assetFileManager->create($assetFile, false);
}

/**
* @return T
*/
Expand Down
43 changes: 43 additions & 0 deletions src/Domain/AssetFile/AssetFileCopyBuilder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

declare(strict_types=1);

namespace AnzuSystems\CoreDamBundle\Domain\AssetFile;

use AnzuSystems\CoreDamBundle\Domain\AssetFile\FileProcessor\AssetFileStorageOperator;
use AnzuSystems\CoreDamBundle\Domain\Image\ImageFileCopyBuilder;
use AnzuSystems\CoreDamBundle\Entity\AssetFile;
use AnzuSystems\CoreDamBundle\Entity\ImageFile;
use AnzuSystems\CoreDamBundle\Exception\RuntimeException;
use League\Flysystem\FilesystemException;

final readonly class AssetFileCopyBuilder
{
public function __construct(
private AssetFileStorageOperator $assetFileStorageOperator,
private ImageFileCopyBuilder $imageFileCopyBuilder,
) {
}

/**
* @throws FilesystemException
*/
public function copy(AssetFile $assetFile, AssetFile $targetAssetFile): void
{
$targetAssetFile->setAssetAttributes(clone $assetFile->getAssetAttributes());
$this->assetFileStorageOperator->copyToAssetFile($assetFile, $targetAssetFile);
if ($assetFile instanceof ImageFile && $targetAssetFile instanceof ImageFile) {
$this->imageFileCopyBuilder->copy($assetFile, $targetAssetFile);

return;
}

throw new RuntimeException(
sprintf(
'Unsupported copy AssetFile combination. Copy from (%s) to (%s)',
$assetFile::class,
$targetAssetFile::class
)
);
}
}
4 changes: 2 additions & 2 deletions src/Domain/AssetFile/AssetFileStatusManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ public function toProcessed(AssetFile $assetFile): AssetFile
/**
* @throws SerializerException
*/
public function toFailed(AssetFile $assetFile, AssetFileFailedType $failedType, Throwable $throwable): AssetFile
public function toFailed(AssetFile $assetFile, AssetFileFailedType $failedType, ?Throwable $throwable = null): AssetFile
{
$this->changeTransition($assetFile, AssetFileProcessStatus::Failed, $failedType);

Expand All @@ -88,7 +88,7 @@ public function toFailed(AssetFile $assetFile, AssetFileFailedType $failedType,
'Asset file (%s) process failed reason (%s). (%s',
(string) $assetFile->getId(),
$failedType->toString(),
$throwable->getMessage()
$throwable?->getMessage()
),
exception: $throwable
);
Expand Down
22 changes: 22 additions & 0 deletions src/Domain/AssetFile/FileProcessor/AssetFileStorageOperator.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,26 @@ public function save(AssetFile $assetFile, AdapterFile $file): AssetFile

return $assetFile;
}

/**
* @throws FilesystemException
*/
public function copyToAssetFile(AssetFile $sourceAssetFile, AssetFile $targetAssetFile): void
{
$path = $this->nameGenerator->generatePath(
$this->fileHelper->guessExtension($sourceAssetFile->getAssetAttributes()->getMimeType()),
true
);

$sourceFileSystem = $this->fileSystemProvider->getFilesystemByStorable($sourceAssetFile);
$targetFileSystem = $this->fileSystemProvider->getFilesystemByStorable($targetAssetFile);

$targetFileSystem->writeStream(
$path->getRelativePath(),
$sourceFileSystem->readStream($sourceAssetFile->getFilePath())
);

$targetAssetFile->getAssetAttributes()
->setFilePath($path->getRelativePath());
}
}
Loading

0 comments on commit 3db2b48

Please sign in to comment.