![]() Server : Apache System : Linux server2.corals.io 4.18.0-348.2.1.el8_5.x86_64 #1 SMP Mon Nov 15 09:17:08 EST 2021 x86_64 User : corals ( 1002) PHP Version : 7.4.33 Disable Function : exec,passthru,shell_exec,system Directory : /home/corals/old/vendor/magento/module-media-gallery-metadata/Model/Png/Segment/ |
<?php /** * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ declare(strict_types=1); namespace Magento\MediaGalleryMetadata\Model\Png\Segment; use Magento\MediaGalleryMetadata\Model\AddXmpMetadata; use Magento\MediaGalleryMetadata\Model\XmpTemplate; use Magento\MediaGalleryMetadataApi\Api\Data\MetadataInterface; use Magento\MediaGalleryMetadataApi\Model\FileInterface; use Magento\MediaGalleryMetadataApi\Model\FileInterfaceFactory; use Magento\MediaGalleryMetadataApi\Model\SegmentInterface; use Magento\MediaGalleryMetadataApi\Model\SegmentInterfaceFactory; use Magento\MediaGalleryMetadataApi\Model\WriteMetadataInterface; /** * XMP Writer for png format */ class WriteXmp implements WriteMetadataInterface { private const XMP_SEGMENT_NAME = 'iTXt'; private const XMP_SEGMENT_START = "XML:com.adobe.xmp\x00"; /** * @var SegmentInterfaceFactory */ private $segmentFactory; /** * @var FileInterfaceFactory */ private $fileFactory; /** * @var AddXmpMetadata */ private $addXmpMetadata; /** * @var XmpTemplate */ private $xmpTemplate; /** * @param FileInterfaceFactory $fileFactory * @param SegmentInterfaceFactory $segmentFactory * @param AddXmpMetadata $addXmpMetadata * @param XmpTemplate $xmpTemplate */ public function __construct( FileInterfaceFactory $fileFactory, SegmentInterfaceFactory $segmentFactory, AddXmpMetadata $addXmpMetadata, XmpTemplate $xmpTemplate ) { $this->fileFactory = $fileFactory; $this->segmentFactory = $segmentFactory; $this->addXmpMetadata = $addXmpMetadata; $this->xmpTemplate = $xmpTemplate; } /** * Add xmp metadata to the png file * * @param FileInterface $file * @param MetadataInterface $metadata * @return FileInterface */ public function execute(FileInterface $file, MetadataInterface $metadata): FileInterface { $segments = $file->getSegments(); $pngXmpSegments = []; foreach ($segments as $key => $segment) { if ($this->isXmpSegment($segment)) { $pngXmpSegments[$key] = $segment; } } if (empty($pngXmpSegments)) { return $this->fileFactory->create([ 'path' => $file->getPath(), 'segments' => $this->insertPngXmpSegment($segments, $this->createPngXmpSegment($metadata)) ]); } foreach ($pngXmpSegments as $key => $segment) { $segments[$key] = $this->updateSegment($segment, $metadata); } return $this->fileFactory->create([ 'path' => $file->getPath(), 'segments' => $segments ]); } /** * Insert XMP segment to image png segments before IEND chunk * * @param SegmentInterface[] $segments * @param SegmentInterface $xmpSegment * @return SegmentInterface[] */ private function insertPngXmpSegment(array $segments, SegmentInterface $xmpSegment): array { $iendSegmentIndex = count($segments) - 1; return array_merge( array_slice($segments, 0, $iendSegmentIndex), [$xmpSegment], array_slice($segments, $iendSegmentIndex) ); } /** * Write new png segment metadata * * @param MetadataInterface $metadata * @return SegmentInterface */ private function createPngXmpSegment(MetadataInterface $metadata): SegmentInterface { $xmpData = $this->xmpTemplate->get(); return $this->segmentFactory->create([ 'name' => self::XMP_SEGMENT_NAME, 'data' => self::XMP_SEGMENT_START . $this->addXmpMetadata->execute($xmpData, $metadata) ]); } /** * Add metadata to the png xmp segment * * @param SegmentInterface $segment * @param MetadataInterface $metadata * @return SegmentInterface */ private function updateSegment(SegmentInterface $segment, MetadataInterface $metadata): SegmentInterface { return $this->segmentFactory->create([ 'name' => $segment->getName(), 'data' => self::XMP_SEGMENT_START . $this->addXmpMetadata->execute($this->getXmpData($segment), $metadata) ]); } /** * Does segment contain XMP data * * @param SegmentInterface $segment * @return bool */ private function isXmpSegment(SegmentInterface $segment): bool { return $segment->getName() === self::XMP_SEGMENT_NAME && strpos($segment->getData(), '<x:xmpmeta') !== false; } /** * Get XMP xml * * @param SegmentInterface $segment * @return string */ private function getXmpData(SegmentInterface $segment): string { return substr($segment->getData(), strpos($segment->getData(), '<x:xmpmeta')); } }