From e43e16e78f99a7fd4e77a4e8cdeb6edcae699ff7 Mon Sep 17 00:00:00 2001 From: Dennis Garding Date: Mon, 10 Aug 2026 08:41:18 +0200 Subject: [PATCH 1/4] fix: normalize Magento category media paths --- .../Magento/Converter/CategoryConverter.php | 19 ++++++- .../Magento2CategoryConverterTest.php | 53 +++++++++++++++++-- 2 files changed, 66 insertions(+), 6 deletions(-) diff --git a/src/Profile/Magento/Converter/CategoryConverter.php b/src/Profile/Magento/Converter/CategoryConverter.php index 1a95522..c2b04c3 100644 --- a/src/Profile/Magento/Converter/CategoryConverter.php +++ b/src/Profile/Magento/Converter/CategoryConverter.php @@ -28,6 +28,12 @@ #[Package('fundamentals@after-sales')] abstract class CategoryConverter extends MagentoConverter { + private const DIRECTORY_SEPERATOR = '/'; + + private const CATEGORY_MEDIA_PATH = '/media/catalog/category/'; + + private const CATEGORY_MEDIA_PATH_WITHOUT_SLASH = 'media/catalog/category/'; + protected string $connectionId; protected Context $context; @@ -384,7 +390,7 @@ protected function getCategoryMedia(string $path): array [ 'runId' => $this->runId, 'entity' => MediaDataSet::getEntity(), - 'uri' => '/media/catalog/category/' . $path, + 'uri' => $this->createMediaUri($path), 'fileName' => $categoryMedia['id'], 'fileSize' => 0, 'mediaId' => $categoryMedia['id'], @@ -406,4 +412,15 @@ private function parentIsRoot(array $data, ?array $rootCategoryMapping): bool return true; } + + private function createMediaUri(string $path): string + { + $normalizedPath = \ltrim($path, self::DIRECTORY_SEPERATOR); + + if (\str_starts_with($normalizedPath, self::CATEGORY_MEDIA_PATH_WITHOUT_SLASH)) { + return self::DIRECTORY_SEPERATOR . $normalizedPath; + } + + return self::CATEGORY_MEDIA_PATH . $normalizedPath; + } } diff --git a/tests/Profile/Magento2/Converter/Magento2CategoryConverterTest.php b/tests/Profile/Magento2/Converter/Magento2CategoryConverterTest.php index 26554f1..f07627b 100644 --- a/tests/Profile/Magento2/Converter/Magento2CategoryConverterTest.php +++ b/tests/Profile/Magento2/Converter/Magento2CategoryConverterTest.php @@ -7,6 +7,7 @@ namespace Swag\MigrationMagento\Test\Profile\Magento2\Converter; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Shopware\Core\Framework\Context; use Shopware\Core\Framework\Log\Package; @@ -76,9 +77,11 @@ class Magento2CategoryConverterTest extends TestCase private string $defaultLanguageUuid; + private DummyMediaFileService $mediaFileService; + protected function setUp(): void { - $mediaFileService = new DummyMediaFileService(); + $this->mediaFileService = new DummyMediaFileService(); $mappingService = new DummyMagentoMappingService(); $this->loggingService = new DummyLoggingService(); @@ -163,10 +166,10 @@ protected function setUp(): void $defaultCmsPageLookup = $this->getContainer()->get(DefaultCmsPageLookup::class); $languageLookup = $this->getContainer()->get(LanguageLookup::class); - $this->categoryConverter20 = new Magento20CategoryConverter($mappingService, $this->loggingService, $mediaFileService, $mediaFolderLookup, $lowestRootCategoryLookup, $defaultCmsPageLookup, $languageLookup); - $this->categoryConverter21 = new Magento21CategoryConverter($mappingService, $this->loggingService, $mediaFileService, $mediaFolderLookup, $lowestRootCategoryLookup, $defaultCmsPageLookup, $languageLookup); - $this->categoryConverter22 = new Magento22CategoryConverter($mappingService, $this->loggingService, $mediaFileService, $mediaFolderLookup, $lowestRootCategoryLookup, $defaultCmsPageLookup, $languageLookup); - $this->categoryConverter23 = new Magento23CategoryConverter($mappingService, $this->loggingService, $mediaFileService, $mediaFolderLookup, $lowestRootCategoryLookup, $defaultCmsPageLookup, $languageLookup); + $this->categoryConverter20 = new Magento20CategoryConverter($mappingService, $this->loggingService, $this->mediaFileService, $mediaFolderLookup, $lowestRootCategoryLookup, $defaultCmsPageLookup, $languageLookup); + $this->categoryConverter21 = new Magento21CategoryConverter($mappingService, $this->loggingService, $this->mediaFileService, $mediaFolderLookup, $lowestRootCategoryLookup, $defaultCmsPageLookup, $languageLookup); + $this->categoryConverter22 = new Magento22CategoryConverter($mappingService, $this->loggingService, $this->mediaFileService, $mediaFolderLookup, $lowestRootCategoryLookup, $defaultCmsPageLookup, $languageLookup); + $this->categoryConverter23 = new Magento23CategoryConverter($mappingService, $this->loggingService, $this->mediaFileService, $mediaFolderLookup, $lowestRootCategoryLookup, $defaultCmsPageLookup, $languageLookup); } public function testSupports(): void @@ -224,6 +227,46 @@ public function testConvert20(): void ); } + #[DataProvider('categoryImagePathProvider')] + public function testConvertCategoryImagePath(string $sourcePath, string $expectedUri): void + { + $categoryData = require __DIR__ . '/../../../_fixtures/category_data.php'; + $categoryData[1]['image'] = $sourcePath; + + $this->mediaFileService->resetMediaFileArray(); + $this->categoryConverter20->convert( + $categoryData[1], + Context::createDefaultContext(), + $this->migrationContext20 + ); + + $mediaFiles = $this->mediaFileService->getMediaFileArray(); + + static::assertCount(1, $mediaFiles); + static::assertSame($expectedUri, $mediaFiles[0]['uri']); + } + + /** + * @return iterable + */ + public static function categoryImagePathProvider(): iterable + { + yield 'bare category image filename' => [ + 'sourcePath' => 'example.jpg', + 'expectedUri' => '/media/catalog/category/example.jpg', + ]; + + yield 'category image with existing media prefix' => [ + 'sourcePath' => '/media/catalog/category/example.jpg', + 'expectedUri' => '/media/catalog/category/example.jpg', + ]; + + yield 'category image with existing media prefix without leading slash' => [ + 'sourcePath' => 'media/catalog/category/example.jpg', + 'expectedUri' => '/media/catalog/category/example.jpg', + ]; + } + public function testConvert21(): void { $categoryData = require __DIR__ . '/../../../_fixtures/category_data.php'; From c2890be0b5f877a737e88e44c0c8e29e02478424 Mon Sep 17 00:00:00 2001 From: Dennis Garding Date: Mon, 10 Aug 2026 08:48:28 +0200 Subject: [PATCH 2/4] adjust method --- .../Magento/Converter/CategoryConverter.php | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/Profile/Magento/Converter/CategoryConverter.php b/src/Profile/Magento/Converter/CategoryConverter.php index c2b04c3..780b263 100644 --- a/src/Profile/Magento/Converter/CategoryConverter.php +++ b/src/Profile/Magento/Converter/CategoryConverter.php @@ -28,11 +28,9 @@ #[Package('fundamentals@after-sales')] abstract class CategoryConverter extends MagentoConverter { - private const DIRECTORY_SEPERATOR = '/'; + private const DIRECTORY_SEPARATOR = '/'; - private const CATEGORY_MEDIA_PATH = '/media/catalog/category/'; - - private const CATEGORY_MEDIA_PATH_WITHOUT_SLASH = 'media/catalog/category/'; + private const CATEGORY_MEDIA_PATH = 'media/catalog/category/'; protected string $connectionId; @@ -415,12 +413,12 @@ private function parentIsRoot(array $data, ?array $rootCategoryMapping): bool private function createMediaUri(string $path): string { - $normalizedPath = \ltrim($path, self::DIRECTORY_SEPERATOR); + $normalizedPath = \ltrim($path, self::DIRECTORY_SEPARATOR); - if (\str_starts_with($normalizedPath, self::CATEGORY_MEDIA_PATH_WITHOUT_SLASH)) { - return self::DIRECTORY_SEPERATOR . $normalizedPath; + if (\str_starts_with($normalizedPath, self::CATEGORY_MEDIA_PATH)) { + return self::DIRECTORY_SEPARATOR . $normalizedPath; } - return self::CATEGORY_MEDIA_PATH . $normalizedPath; + return self::DIRECTORY_SEPARATOR . self::CATEGORY_MEDIA_PATH . $normalizedPath; } } From 23754ec36f86a767d0174ec033cd42db7b552f67 Mon Sep 17 00:00:00 2001 From: Dennis Garding Date: Mon, 10 Aug 2026 09:38:04 +0200 Subject: [PATCH 3/4] add changelog --- CHANGELOG.md | 4 ++++ CHANGELOG_de-DE.md | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9792823..72bd589 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +# [NEXT] +- Fixes errors when downloading media. +- Fixes errors when migrating category images. + # 13.0.0 - Compatibility with Migration Assistant version 18. diff --git a/CHANGELOG_de-DE.md b/CHANGELOG_de-DE.md index 764fbc3..31cad1e 100644 --- a/CHANGELOG_de-DE.md +++ b/CHANGELOG_de-DE.md @@ -1,3 +1,7 @@ +# [NEXT] +- Behebt Fehler beim Herunterladen von Medien. +- Behebt Fehler bei der Migration von Kategoriebildern. + # 13.0.0 - Kompatibilität mit Migration Assistant Version 18. From d81a569883e35ef763f2779bab6daf14c6644b2f Mon Sep 17 00:00:00 2001 From: Dennis Garding Date: Mon, 10 Aug 2026 11:25:20 +0200 Subject: [PATCH 4/4] Fix phpstan --- tests/Profile/Magento/Media/LocalMediaProcessorTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/Profile/Magento/Media/LocalMediaProcessorTest.php b/tests/Profile/Magento/Media/LocalMediaProcessorTest.php index 410ada3..bfaed44 100644 --- a/tests/Profile/Magento/Media/LocalMediaProcessorTest.php +++ b/tests/Profile/Magento/Media/LocalMediaProcessorTest.php @@ -68,7 +68,6 @@ public function testCopyMediaFiles(): void $mediaProcessor = $this->createLocaleMediaProcessor($mediaFiles); $reflectionMethod = (new \ReflectionClass(LocalMediaProcessor::class))->getMethod('copyMediaFiles'); - $reflectionMethod->setAccessible(true); $result = $reflectionMethod->invokeArgs($mediaProcessor, [$mediaFiles, $mappedWorkload, $migrationContext, Context::createDefaultContext()]); foreach ($result as $workload) {