diff --git a/app/code/Magento/MediaGalleryMetadata/Model/GetIptcMetadata.php b/app/code/Magento/MediaGalleryMetadata/Model/GetIptcMetadata.php index d7290f31ee34..e100a7f852e4 100644 --- a/app/code/Magento/MediaGalleryMetadata/Model/GetIptcMetadata.php +++ b/app/code/Magento/MediaGalleryMetadata/Model/GetIptcMetadata.php @@ -9,7 +9,6 @@ use Magento\MediaGalleryMetadataApi\Api\Data\MetadataInterface; use Magento\MediaGalleryMetadataApi\Api\Data\MetadataInterfaceFactory; -use Magento\MediaGalleryMetadataApi\Model\SegmentInterface; /** * Get metadata from IPTC block @@ -42,8 +41,8 @@ public function __construct( */ public function execute(string $data): MetadataInterface { - $title = ''; - $description = ''; + $title = null; + $description = null; $keywords = []; if (is_callable('iptcparse')) { @@ -65,7 +64,7 @@ public function execute(string $data): MetadataInterface return $this->metadataFactory->create([ 'title' => $title, 'description' => $description, - 'keywords' => $keywords + 'keywords' => !empty($keywords) ? $keywords : null ]); } } diff --git a/app/code/Magento/MediaGalleryMetadata/Model/Jpeg/Segment/ReadExif.php b/app/code/Magento/MediaGalleryMetadata/Model/Jpeg/Segment/ReadExif.php new file mode 100644 index 000000000000..b6c32296f3f7 --- /dev/null +++ b/app/code/Magento/MediaGalleryMetadata/Model/Jpeg/Segment/ReadExif.php @@ -0,0 +1,104 @@ +metadataFactory = $metadataFactory; + } + + /** + * @inheritdoc + */ + public function execute(FileInterface $file): MetadataInterface + { + if (!is_callable('exif_read_data')) { + throw new LocalizedException( + __('exif_read_data() must be enabled in php configuration') + ); + } + + foreach ($file->getSegments() as $segment) { + if ($this->isExifSegment($segment)) { + return $this->getExifData($file->getPath()); + } + } + + return $this->metadataFactory->create([ + 'title' => null, + 'description' => null, + 'keywords' => null + ]); + } + + /** + * Parese exif data from segment + * + * @param string $filePath + */ + private function getExifData(string $filePath): MetadataInterface + { + $title = null; + $description = null; + $keywords = null; + + $data = exif_read_data($filePath); + + if (!empty($data)) { + $title = isset($data['DocumentName']) ? $data['DocumentName'] : null; + $description = isset($data['ImageDescription']) ? $data['ImageDescription'] : null; + } + + return $this->metadataFactory->create([ + 'title' => $title, + 'description' => $description, + 'keywords' => $keywords + ]); + } + + /** + * Does segment contain Exif data + * + * @param SegmentInterface $segment + * @return bool + */ + private function isExifSegment(SegmentInterface $segment): bool + { + return $segment->getName() === self::EXIF_SEGMENT_NAME + && strncmp( + substr($segment->getData(), self::EXIF_DATA_START_POSITION, 5), + self::EXIF_SEGMENT_START, + 5 + ) == 0; + } +} diff --git a/app/code/Magento/MediaGalleryMetadata/Model/Jpeg/Segment/ReadIptc.php b/app/code/Magento/MediaGalleryMetadata/Model/Jpeg/Segment/ReadIptc.php index 94ccb400e5e0..e56993528a04 100644 --- a/app/code/Magento/MediaGalleryMetadata/Model/Jpeg/Segment/ReadIptc.php +++ b/app/code/Magento/MediaGalleryMetadata/Model/Jpeg/Segment/ReadIptc.php @@ -56,9 +56,9 @@ public function execute(FileInterface $file): MetadataInterface } } return $this->metadataFactory->create([ - 'title' => '', - 'description' => '', - 'keywords' => [] + 'title' => null, + 'description' => null, + 'keywords' => null ]); } diff --git a/app/code/Magento/MediaGalleryMetadata/Model/Jpeg/Segment/ReadXmp.php b/app/code/Magento/MediaGalleryMetadata/Model/Jpeg/Segment/ReadXmp.php index 81ff7200c347..e68c86d35eb9 100644 --- a/app/code/Magento/MediaGalleryMetadata/Model/Jpeg/Segment/ReadXmp.php +++ b/app/code/Magento/MediaGalleryMetadata/Model/Jpeg/Segment/ReadXmp.php @@ -54,9 +54,9 @@ public function execute(FileInterface $file): MetadataInterface } } return $this->metadataFactory->create([ - 'title' => '', - 'description' => '', - 'keywords' => [] + 'title' => null, + 'description' => null, + 'keywords' => null ]); } diff --git a/app/code/Magento/MediaGalleryMetadata/Model/Png/Segment/ReadExif.php b/app/code/Magento/MediaGalleryMetadata/Model/Png/Segment/ReadExif.php new file mode 100644 index 000000000000..09aeaf526443 --- /dev/null +++ b/app/code/Magento/MediaGalleryMetadata/Model/Png/Segment/ReadExif.php @@ -0,0 +1,97 @@ +metadataFactory = $metadataFactory; + } + + /** + * @inheritdoc + */ + public function execute(FileInterface $file): MetadataInterface + { + if (!is_callable('exif_read_data')) { + throw new LocalizedException( + __('exif_read_data() must be enabled in php configuration') + ); + } + + foreach ($file->getSegments() as $segment) { + if ($this->isExifSegment($segment)) { + return $this->getExifData($segment); + } + } + + return $this->metadataFactory->create([ + 'title' => null, + 'description' => null, + 'keywords' => null + ]); + } + + /** + * Parese exif data from segment + * + * @param SegmentInterface $segment + */ + private function getExifData(SegmentInterface $segment): MetadataInterface + { + $title = null; + $description = null; + $keywords = []; + + $data = exif_read_data('data://image/jpeg;base64,' . base64_encode($segment->getData())); + + if ($data) { + $title = isset($data['DocumentName']) ? $data['DocumentName'] : null; + $description = isset($data['ImageDescription']) ? $data['ImageDescription'] : null; + } + + return $this->metadataFactory->create([ + 'title' => $title, + 'description' => $description, + 'keywords' => !empty($keywords) ? $keywords : null + ]); + } + + /** + * Does segment contain Exif data + * + * @param SegmentInterface $segment + * @return bool + */ + private function isExifSegment(SegmentInterface $segment): bool + { + return strcmp($segment->getName(), self::EXIF_SEGMENT_NAME) === 0; + } +} diff --git a/app/code/Magento/MediaGalleryMetadata/Model/Png/Segment/ReadXmp.php b/app/code/Magento/MediaGalleryMetadata/Model/Png/Segment/ReadXmp.php index 83ba554f7bf5..518697d42147 100644 --- a/app/code/Magento/MediaGalleryMetadata/Model/Png/Segment/ReadXmp.php +++ b/app/code/Magento/MediaGalleryMetadata/Model/Png/Segment/ReadXmp.php @@ -55,9 +55,9 @@ public function execute(FileInterface $file): MetadataInterface } } return $this->metadataFactory->create([ - 'title' => '', - 'description' => '', - 'keywords' => [] + 'title' => null, + 'description' => null, + 'keywords' => null ]); } diff --git a/app/code/Magento/MediaGalleryMetadata/Test/Integration/Model/ExtractMetadataTest.php b/app/code/Magento/MediaGalleryMetadata/Test/Integration/Model/ExtractMetadataTest.php index 982ccbb20fe2..ebe96183eb1f 100644 --- a/app/code/Magento/MediaGalleryMetadata/Test/Integration/Model/ExtractMetadataTest.php +++ b/app/code/Magento/MediaGalleryMetadata/Test/Integration/Model/ExtractMetadataTest.php @@ -37,14 +37,14 @@ protected function setUp(): void * @param string $fileName * @param string $title * @param string $description - * @param array $keywords + * @param null|array $keywords * @throws LocalizedException */ public function testExecute( string $fileName, string $title, string $description, - array $keywords + ?array $keywords ): void { $path = realpath(__DIR__ . '/../../_files/' . $fileName); $metadata = $this->extractMetadata->execute($path); @@ -62,6 +62,18 @@ public function testExecute( public function filesProvider(): array { return [ + [ + 'exif_image.png', + 'Exif title png imge', + 'Exif description png imge', + null + ], + [ + 'exif-image.jpeg', + 'Exif Magento title', + 'Exif description metadata', + null + ], [ 'macos-photos.jpeg', 'Title of the magento image', diff --git a/app/code/Magento/MediaGalleryMetadata/Test/_files/empty_iptc.jpeg b/app/code/Magento/MediaGalleryMetadata/Test/_files/empty_iptc.jpeg index 144a56dac2d3..1a345c2d33fd 100644 Binary files a/app/code/Magento/MediaGalleryMetadata/Test/_files/empty_iptc.jpeg and b/app/code/Magento/MediaGalleryMetadata/Test/_files/empty_iptc.jpeg differ diff --git a/app/code/Magento/MediaGalleryMetadata/Test/_files/exif-image.jpeg b/app/code/Magento/MediaGalleryMetadata/Test/_files/exif-image.jpeg new file mode 100644 index 000000000000..cfe27433fd9f Binary files /dev/null and b/app/code/Magento/MediaGalleryMetadata/Test/_files/exif-image.jpeg differ diff --git a/app/code/Magento/MediaGalleryMetadata/Test/_files/exif_image.png b/app/code/Magento/MediaGalleryMetadata/Test/_files/exif_image.png new file mode 100644 index 000000000000..4a6bf30c2d51 Binary files /dev/null and b/app/code/Magento/MediaGalleryMetadata/Test/_files/exif_image.png differ diff --git a/app/code/Magento/MediaGalleryMetadata/Test/_files/macos-preview.png b/app/code/Magento/MediaGalleryMetadata/Test/_files/macos-preview.png index 966520f0d011..95eb45f69b3e 100644 Binary files a/app/code/Magento/MediaGalleryMetadata/Test/_files/macos-preview.png and b/app/code/Magento/MediaGalleryMetadata/Test/_files/macos-preview.png differ diff --git a/app/code/Magento/MediaGalleryMetadata/etc/di.xml b/app/code/Magento/MediaGalleryMetadata/etc/di.xml index d2f1f9051048..4cd9a34e43a9 100644 --- a/app/code/Magento/MediaGalleryMetadata/etc/di.xml +++ b/app/code/Magento/MediaGalleryMetadata/etc/di.xml @@ -112,6 +112,7 @@ Magento\MediaGalleryMetadata\Model\Png\Segment\ReadXmp Magento\MediaGalleryMetadata\Model\Png\Segment\ReadIptc + Magento\MediaGalleryMetadata\Model\Png\Segment\ReadExif @@ -121,6 +122,7 @@ Magento\MediaGalleryMetadata\Model\Jpeg\Segment\ReadXmp Magento\MediaGalleryMetadata\Model\Jpeg\Segment\ReadIptc + Magento\MediaGalleryMetadata\Model\Jpeg\Segment\ReadExif