diff --git a/docs/upgrade/upgrade-2.0.md b/docs/upgrade/upgrade-2.0.md index 899e10ac..d6f8dec7 100644 --- a/docs/upgrade/upgrade-2.0.md +++ b/docs/upgrade/upgrade-2.0.md @@ -161,6 +161,22 @@ Removed all deprecations of the v1.x releases. - [BC] Class Webgriffe\SyliusAkeneoPlugin\Repository\QueueItemRepositoryInterface has been deleted - [BC] Class Webgriffe\SyliusAkeneoPlugin\Entity\QueueItemInterface has been deleted +### Remove only temporary files from current akeneo entity import ([#176](https://github.com/webgriffe/SyliusAkeneoPlugin/pull/176)) + +#### TL;DR + +Now, the Webgriffe\SyliusAkeneoPlugin\TemporaryFilesManagerInterface service requires a file identifier to remove only +the temporary files related to the current Akeneo entity import. + +#### BC Breaks + +##### Changed +- [BC] The number of required arguments for Webgriffe\SyliusAkeneoPlugin\TemporaryFilesManager#generateTemporaryFilePath() increased from 0 to 1 +- [BC] The number of required arguments for Webgriffe\SyliusAkeneoPlugin\TemporaryFilesManager#deleteAllTemporaryFiles() increased from 0 to 1 +- [BC] The number of required arguments for Webgriffe\SyliusAkeneoPlugin\TemporaryFilesManagerInterface#generateTemporaryFilePath() increased from 0 to 1 +- [BC] The number of required arguments for Webgriffe\SyliusAkeneoPlugin\TemporaryFilesManagerInterface#deleteAllTemporaryFiles() increased from 0 to 1 + + ### Test changes #### TL;DR diff --git a/spec/ValueHandler/FileAttributeValueHandlerSpec.php b/spec/ValueHandler/FileAttributeValueHandlerSpec.php index 4c9aa51f..1a945602 100644 --- a/spec/ValueHandler/FileAttributeValueHandlerSpec.php +++ b/spec/ValueHandler/FileAttributeValueHandlerSpec.php @@ -41,11 +41,12 @@ public function let( $supportChannel->setCode('support'); $product->getChannels()->willReturn(new ArrayCollection([$commerceChannel, $supportChannel])); $productVariant->getProduct()->willReturn($product); + $productVariant->getCode()->willReturn('VARIANT_1'); $apiClient->getAttributeApi()->willReturn($attributeApi); $apiClient->getProductMediaFileApi()->willReturn($productMediaFileApi); $productMediaFileApi->download(Argument::type('string'))->willReturn(new Response(200, [], '__FILE_CONTENT__')); $attributeApi->get('allegato_1')->willReturn(['type' => 'pim_catalog_file']); - $temporaryFilesManager->generateTemporaryFilePath()->willReturn('tempfile'); + $temporaryFilesManager->generateTemporaryFilePath('product-variant-VARIANT_1')->willReturn('tempfile'); $this->beConstructedWith($apiClient, $filesystem, $temporaryFilesManager, 'allegato_1', 'public/media/attachment/product/'); } diff --git a/spec/ValueHandler/ImageValueHandlerSpec.php b/spec/ValueHandler/ImageValueHandlerSpec.php index 437e0303..7ca819d6 100644 --- a/spec/ValueHandler/ImageValueHandlerSpec.php +++ b/spec/ValueHandler/ImageValueHandlerSpec.php @@ -65,10 +65,11 @@ public function let( $product->getChannels()->willReturn(new ArrayCollection([$commerceChannel, $supportChannel])); $productVariant->addImage($productImage)->hasReturnVoid(); $productVariant->getProduct()->willReturn($product); + $productVariant->getCode()->willReturn('VARIANT_1'); $productImageRepository ->findBy(['owner' => $product, 'type' => self::SYLIUS_IMAGE_TYPE]) ->willReturn(new ArrayCollection([])); - $temporaryFilesManager->generateTemporaryFilePath()->willReturn('tempfile'); + $temporaryFilesManager->generateTemporaryFilePath('product-variant-VARIANT_1')->willReturn('tempfile'); $this->beConstructedWith( $productImageFactory, $productImageRepository, diff --git a/src/MessageHandler/ItemImportHandler.php b/src/MessageHandler/ItemImportHandler.php index e674ccb3..680bde3d 100644 --- a/src/MessageHandler/ItemImportHandler.php +++ b/src/MessageHandler/ItemImportHandler.php @@ -9,6 +9,7 @@ use Webgriffe\SyliusAkeneoPlugin\ImporterRegistryInterface; use Webgriffe\SyliusAkeneoPlugin\Message\ItemImport; use Webgriffe\SyliusAkeneoPlugin\TemporaryFilesManager; +use Webgriffe\SyliusAkeneoPlugin\TemporaryFilesManagerInterface; final class ItemImportHandler { @@ -26,7 +27,7 @@ public function __invoke(ItemImport $message): void try { $importer->import($akeneoIdentifier); } finally { - $this->temporaryFilesManager->deleteAllTemporaryFiles(); + $this->temporaryFilesManager->deleteAllTemporaryFiles(TemporaryFilesManagerInterface::PRODUCT_VARIANT_PREFIX . $akeneoIdentifier); } } diff --git a/src/TemporaryFilesManager.php b/src/TemporaryFilesManager.php index 7b5a63fb..7192d647 100644 --- a/src/TemporaryFilesManager.php +++ b/src/TemporaryFilesManager.php @@ -9,22 +9,38 @@ final class TemporaryFilesManager implements TemporaryFilesManagerInterface { - public function __construct(private Filesystem $filesystem, private Finder $finder, private string $temporaryDirectory, private string $temporaryFilesPrefix) - { + public function __construct( + private Filesystem $filesystem, + private Finder $finder, + private string $temporaryDirectory, + private string $temporaryFilesPrefix, + ) { } - public function generateTemporaryFilePath(): string + public function generateTemporaryFilePath(string $fileIdentifier): string { - return $this->filesystem->tempnam($this->temporaryDirectory, $this->temporaryFilesPrefix); + return $this->filesystem->tempnam( + $this->temporaryDirectory, + $this->getFilePrefix($fileIdentifier), + ); } - public function deleteAllTemporaryFiles(): void + public function deleteAllTemporaryFiles(string $fileIdentifier): void { $tempFiles = $this->finder->in($this->temporaryDirectory)->depth('== 0')->files()->name( - $this->temporaryFilesPrefix . '*', + $this->getFilePrefix($fileIdentifier) . '*', ); foreach ($tempFiles as $tempFile) { $this->filesystem->remove($tempFile->getPathname()); } } + + private function getFilePrefix(string $fileIdentifier): string + { + return sprintf( + '%s-%s-', + rtrim($this->temporaryFilesPrefix, '-'), + rtrim($fileIdentifier, '-'), + ); + } } diff --git a/src/TemporaryFilesManagerInterface.php b/src/TemporaryFilesManagerInterface.php index 2b7ad08c..ce9b6e88 100644 --- a/src/TemporaryFilesManagerInterface.php +++ b/src/TemporaryFilesManagerInterface.php @@ -6,7 +6,9 @@ interface TemporaryFilesManagerInterface { - public function generateTemporaryFilePath(): string; + public const PRODUCT_VARIANT_PREFIX = 'product-variant-'; - public function deleteAllTemporaryFiles(): void; + public function generateTemporaryFilePath(string $fileIdentifier): string; + + public function deleteAllTemporaryFiles(string $fileIdentifier): void; } diff --git a/src/ValueHandler/FileAttributeValueHandler.php b/src/ValueHandler/FileAttributeValueHandler.php index 4a659e6c..4bc51e02 100644 --- a/src/ValueHandler/FileAttributeValueHandler.php +++ b/src/ValueHandler/FileAttributeValueHandler.php @@ -86,7 +86,9 @@ public function handle($subject, string $attribute, array $value): void // TODO remove existing image? See https://github.com/webgriffe/SyliusAkeneoPlugin/issues/61 return; } - $downloadedFile = $this->downloadFile($mediaCode); + $fileIdentifier = $subject->getCode(); + Assert::notNull($fileIdentifier); + $downloadedFile = $this->downloadFile($mediaCode, $fileIdentifier); $relativeFilePath = $mediaCode; $this->moveFileToAttachmentFolder($relativeFilePath, $downloadedFile); @@ -133,7 +135,7 @@ private function getValue(array $value, ProductInterface $product): ?string throw new InvalidArgumentException('Invalid Akeneo attachment data: cannot find the media code.'); } - private function downloadFile(string $mediaCode): SplFileInfo + private function downloadFile(string $mediaCode, string $fileIdentifier): SplFileInfo { $response = $this->apiClient->getProductMediaFileApi()->download($mediaCode); $statusClass = (int) ($response->getStatusCode() / 100); @@ -144,14 +146,9 @@ private function downloadFile(string $mediaCode): SplFileInfo throw new SymfonyHttpException((int) $responseResult['code'], (string) $responseResult['message']); } - $tempName = $this->generateTempFilePath(); + $tempName = $this->temporaryFilesManager->generateTemporaryFilePath(TemporaryFilesManagerInterface::PRODUCT_VARIANT_PREFIX . $fileIdentifier); file_put_contents($tempName, $bodyContents); return new File($tempName); } - - private function generateTempFilePath(): string - { - return $this->temporaryFilesManager->generateTemporaryFilePath(); - } } diff --git a/src/ValueHandler/ImageValueHandler.php b/src/ValueHandler/ImageValueHandler.php index 4e13f0bd..7fde6d68 100644 --- a/src/ValueHandler/ImageValueHandler.php +++ b/src/ValueHandler/ImageValueHandler.php @@ -67,7 +67,9 @@ public function handle($subject, string $attribute, array $value): void return; } - $imageFile = $this->downloadFile($mediaCode); + $fileIdentifier = $subject->getCode(); + Assert::notNull($fileIdentifier); + $imageFile = $this->downloadFile($mediaCode, $fileIdentifier); $productImage = $this->getExistentProductVariantImage($subject, $product); if ($productImage === null) { @@ -168,7 +170,7 @@ private function getValue(array $value, ProductInterface $product): ?string throw new InvalidArgumentException('Invalid Akeneo value data: cannot find the media code.'); } - private function downloadFile(string $mediaCode): SplFileInfo + private function downloadFile(string $mediaCode, string $fileIdentifier): SplFileInfo { $response = $this->apiClient->getProductMediaFileApi()->download($mediaCode); $statusClass = (int) ($response->getStatusCode() / 100); @@ -179,14 +181,9 @@ private function downloadFile(string $mediaCode): SplFileInfo throw new HttpException((int) $responseResult['code'], (string) $responseResult['message']); } - $tempName = $this->generateTempFilePath(); + $tempName = $this->temporaryFilesManager->generateTemporaryFilePath(TemporaryFilesManagerInterface::PRODUCT_VARIANT_PREFIX . $fileIdentifier); file_put_contents($tempName, $bodyContents); return new File($tempName); } - - private function generateTempFilePath(): string - { - return $this->temporaryFilesManager->generateTemporaryFilePath(); - } } diff --git a/tests/Behat/Context/Cli/ImportCommandContext.php b/tests/Behat/Context/Cli/ImportCommandContext.php index e34b4a74..5c356a86 100644 --- a/tests/Behat/Context/Cli/ImportCommandContext.php +++ b/tests/Behat/Context/Cli/ImportCommandContext.php @@ -24,6 +24,14 @@ public function __construct( ) { } + /** + * @BeforeScenario + */ + public function before(): void + { + vfsStream::setup(); + } + /** * @When I import items for all importers modified since date :date */ diff --git a/tests/Behat/Context/System/FilesystemContext.php b/tests/Behat/Context/System/FilesystemContext.php index 86c6e341..6da4cdd7 100644 --- a/tests/Behat/Context/System/FilesystemContext.php +++ b/tests/Behat/Context/System/FilesystemContext.php @@ -5,15 +5,10 @@ namespace Tests\Webgriffe\SyliusAkeneoPlugin\Behat\Context\System; use Behat\Behat\Context\Context; -use org\bovigo\vfs\vfsStream; -use org\bovigo\vfs\vfsStreamContainer; use Webmozart\Assert\Assert; final class FilesystemContext implements Context { - /** @phpstan-ignore-next-line */ - private ?vfsStreamContainer $vfsStream = null; - public function __construct(private string $temporaryDirectory, private string $temporaryFilesPrefix) { } @@ -23,7 +18,9 @@ public function __construct(private string $temporaryDirectory, private string $ */ public function before(): void { - $this->vfsStream = vfsStream::setup('root'); + if (!file_exists($this->temporaryDirectory)) { + mkdir($this->temporaryDirectory); + } } /** diff --git a/tests/Behat/Resources/services.xml b/tests/Behat/Resources/services.xml index 5d7f5566..a8eac704 100644 --- a/tests/Behat/Resources/services.xml +++ b/tests/Behat/Resources/services.xml @@ -1,6 +1,9 @@ + + %kernel.project_dir%/var/tmp/ + diff --git a/tests/Unit/TemporaryFilesManagerTest.php b/tests/Unit/TemporaryFilesManagerTest.php index 89c56150..c6fbf681 100644 --- a/tests/Unit/TemporaryFilesManagerTest.php +++ b/tests/Unit/TemporaryFilesManagerTest.php @@ -30,31 +30,33 @@ public function it_generates_temporary_file_path(): void { $this->assertMatchesRegularExpression( '|' . vfsStream::url('root') . '/akeneo-.*|', - $this->temporaryFileManager->generateTemporaryFilePath(), + $this->temporaryFileManager->generateTemporaryFilePath('VARIANT_1'), ); } /** @test */ public function it_deletes_all_temporary_files(): void { - touch(vfsStream::url('root') . '/akeneo-temp1'); - touch(vfsStream::url('root') . '/akeneo-temp2'); - touch(vfsStream::url('root') . '/akeneo-temp3'); + touch(vfsStream::url('root') . '/akeneo-VARIANT_1-temp1'); + touch(vfsStream::url('root') . '/akeneo-VARIANT_1-temp2'); + touch(vfsStream::url('root') . '/akeneo-VARIANT_1-temp3'); - $this->temporaryFileManager->deleteAllTemporaryFiles(); + $this->temporaryFileManager->deleteAllTemporaryFiles('VARIANT_1'); - $this->assertFileDoesNotExist(vfsStream::url('root') . '/akeneo-temp1'); - $this->assertFileDoesNotExist(vfsStream::url('root') . '/akeneo-temp2'); - $this->assertFileDoesNotExist(vfsStream::url('root') . '/akeneo-temp3'); + $this->assertFileDoesNotExist(vfsStream::url('root') . '/akeneo-VARIANT_1-temp1'); + $this->assertFileDoesNotExist(vfsStream::url('root') . '/akeneo-VARIANT_1-temp2'); + $this->assertFileDoesNotExist(vfsStream::url('root') . '/akeneo-VARIANT_1-temp3'); } /** @test */ public function it_does_not_delete_not_managed_temporary_files(): void { touch(vfsStream::url('root') . '/not-managed-temp-file'); + touch(vfsStream::url('root') . '/VARIANT_1-not-managed-temp-file'); - $this->temporaryFileManager->deleteAllTemporaryFiles(); + $this->temporaryFileManager->deleteAllTemporaryFiles('VARIANT_1'); $this->assertFileExists(vfsStream::url('root') . '/not-managed-temp-file'); + $this->assertFileExists(vfsStream::url('root') . '/VARIANT_1-not-managed-temp-file'); } }