Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feaure copy between lic #87

Merged
merged 14 commits into from
Oct 23, 2024
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
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
Loading