diff --git a/Classes/Service/DestinationDataImportService/FilesAssignment.php b/Classes/Service/DestinationDataImportService/FilesAssignment.php index a61c799..3067bf0 100644 --- a/Classes/Service/DestinationDataImportService/FilesAssignment.php +++ b/Classes/Service/DestinationDataImportService/FilesAssignment.php @@ -29,6 +29,7 @@ use TYPO3\CMS\Core\Log\LogManager; use TYPO3\CMS\Core\Resource\DuplicationBehavior; use TYPO3\CMS\Core\Resource\File; +use TYPO3\CMS\Core\Resource\Folder; use TYPO3\CMS\Core\Resource\Index\MetaDataRepository; use TYPO3\CMS\Core\Resource\ResourceFactory; use TYPO3\CMS\Core\Utility\GeneralUtility; @@ -67,27 +68,26 @@ public function getImages( } $fileUrl = urldecode((string)$mediaObject['url']); - $orgFileNameSanitized = $importFolder->getStorage()->sanitizeFileName(basename($fileUrl)); - - $this->logger->info('File attached.', [$fileUrl, $orgFileNameSanitized]); - - if ($importFolder->hasFile($orgFileNameSanitized)) { - $this->logger->info('File already exists.', [$orgFileNameSanitized]); - } elseif ($filename = $this->loadFile($fileUrl)) { - $this->logger->info('Adding file to FAL.', [$filename]); - $importFolder->addFile($filename, basename($fileUrl), DuplicationBehavior::REPLACE); + $fileName = $this->createFileName($fileUrl, $importFolder); + $this->logger->info('File attached.', [$fileUrl, $fileName]); + + if ($importFolder->hasFile($fileName)) { + $this->logger->info('File already exists.', [$fileName]); + } elseif ($tempFileName = $this->loadFile($fileUrl)) { + $this->logger->info('Adding file to FAL.', [$fileName]); + $importFolder->addFile($tempFileName, $fileName, DuplicationBehavior::REPLACE); } else { continue; } - if ($importFolder->hasFile($orgFileNameSanitized) === false) { - $this->logger->warning('Could not find file.', [$orgFileNameSanitized]); + if ($importFolder->hasFile($fileName) === false) { + $this->logger->warning('Could not find file.', [$fileName]); continue; } - $file = $importFolder->getStorage()->getFileInFolder($orgFileNameSanitized, $importFolder); + $file = $importFolder->getStorage()->getFileInFolder($fileName, $importFolder); if (!$file instanceof File) { - $this->logger->warning('Could not find file.', [$orgFileNameSanitized]); + $this->logger->warning('Could not find file.', [$fileName]); continue; } @@ -98,6 +98,18 @@ public function getImages( return $images; } + private function createFileName(string $url, Folder $importFolder): string + { + $extension = pathinfo($url, PATHINFO_EXTENSION); + + $fileName = basename($url); + if ($fileName === '.' . $extension) { + $fileName = hash('sha256', $url) . '.' . $extension; + } + + return $importFolder->getStorage()->sanitizeFileName($fileName); + } + private function loadFile(string $fileUrl): string { $this->logger->info('Getting file.', [$fileUrl]); diff --git a/Documentation/Changelog/4.2.1.rst b/Documentation/Changelog/4.2.1.rst index 5f9b3ba..9557b91 100644 --- a/Documentation/Changelog/4.2.1.rst +++ b/Documentation/Changelog/4.2.1.rst @@ -28,6 +28,13 @@ Fixes back to `date_default_timezone_get()` call. That way it should be useful for most systems out of the box. +* Handle destination.one files without file name. + + It is possible to have files such as `https://dam.destination.one/2675868/3dc0a9dccd0dad46c73e669ece428c634ff8324ea3d01a4858a1c43169deed41/.jpg`. + Those were not handled correctly yet. + We now also handle those cases. + We will generate a hash from the URL as file name in order to still use those files. + Tasks ----- diff --git a/Tests/Functional/Import/DestinationDataTest/Assertions/ImportHandlesImageWithoutFileName.php b/Tests/Functional/Import/DestinationDataTest/Assertions/ImportHandlesImageWithoutFileName.php new file mode 100644 index 0000000..19d1a2a --- /dev/null +++ b/Tests/Functional/Import/DestinationDataTest/Assertions/ImportHandlesImageWithoutFileName.php @@ -0,0 +1,42 @@ + [ + [ + 'uid' => 1, + 'pid' => 0, + 'missing' => 0, + 'storage' => 1, + 'type' => File::FILETYPE_IMAGE, + 'identifier' => '/staedte/beispielstadt/events/bf126089c94f95031fa07bf9d7d9b10c3e58aafebdef31f0b60604da13019b8d.jpg', + 'extension' => 'jpg', + 'name' => 'bf126089c94f95031fa07bf9d7d9b10c3e58aafebdef31f0b60604da13019b8d.jpg', + ], + ], + 'sys_file_reference' => [ + [ + 'uid' => 1, + 'pid' => 2, + 'uid_local' => 1, + 'uid_foreign' => 1, + 'tablenames' => 'tx_events_domain_model_event', + 'fieldname' => 'images', + 'sorting_foreign' => 1, + 'title' => null, + 'description' => null, + 'alternative' => null, + ], + ], + 'sys_file_metadata' => [ + [ + 'uid' => 1, + 'pid' => 0, + 'file' => 1, + 'title' => null, + ], + ], +]; diff --git a/Tests/Functional/Import/DestinationDataTest/Fixtures/ResponseWithNewImageWithoutFileName.json b/Tests/Functional/Import/DestinationDataTest/Fixtures/ResponseWithNewImageWithoutFileName.json new file mode 100644 index 0000000..99498bc --- /dev/null +++ b/Tests/Functional/Import/DestinationDataTest/Fixtures/ResponseWithNewImageWithoutFileName.json @@ -0,0 +1,33 @@ +{ + "items": [ + { + "global_id": "e_100347853", + "title": "Allerlei Weihnachtliches (Heute mit Johannes Geißer)", + "media_objects": [ + { + "rel": "default", + "url": "https://dam.destination.one/849917/279ac45b3fc701a7197131f627164fffd9f8cc77bc75165e2fc2b864ed606920/.jpg", + "type": "image/jpeg", + "latitude": null, + "longitude": null, + "width": 1920, + "height": 1080, + "value": "" + } + ], + "timeIntervals": [ + { + "weekdays": [], + "start": "2022-12-19T15:00:00+01:00", + "end": "2022-12-19T16:30:00+01:00", + "tz": "Europe/Berlin", + "interval": 1 + } + ], + "source": { + "url": "http://destination.one/", + "value": "destination.one" + } + } + ] +} diff --git a/Tests/Functional/Import/DestinationDataTest/ImportHandlesImagesTest.php b/Tests/Functional/Import/DestinationDataTest/ImportHandlesImagesTest.php index 44c54c6..aa0875c 100644 --- a/Tests/Functional/Import/DestinationDataTest/ImportHandlesImagesTest.php +++ b/Tests/Functional/Import/DestinationDataTest/ImportHandlesImagesTest.php @@ -60,6 +60,31 @@ public function addsNewImages(): void $this->assertEmptyLog(); } + #[Test] + public function addsNewImageWithoutFileName(): void + { + $this->setUpResponses([ + new Response(200, [], file_get_contents(__DIR__ . '/Fixtures/ResponseWithNewImageWithoutFileName.json') ?: ''), + new Response(200, [], file_get_contents(__DIR__ . '/Fixtures/ExampleImage.jpg') ?: ''), + ]); + + $this->executeCommand(); + + $this->assertPHPDataSet(__DIR__ . '/Assertions/ImportHandlesImageWithoutFileName.php'); + + $importedFiles = GeneralUtility::getFilesInDir($this->fileImportPath); + self::assertIsArray($importedFiles, 'Failed to retrieve imported files from filesystem.'); + self::assertSame( + [ + 'bf126089c94f95031fa07bf9d7d9b10c3e58aafebdef31f0b60604da13019b8d.jpg', + ], + array_values($importedFiles), + 'Got unexpected number of files' + ); + + $this->assertEmptyLog(); + } + #[Test] public function addsMultipleImagesToSingleEvent(): void {