vendor/shopware/core/Content/ImportExport/DataAbstractionLayer/Serializer/Entity/MediaSerializer.php line 123

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Shopware\Core\Content\ImportExport\DataAbstractionLayer\Serializer\Entity;
  3. use Shopware\Core\Content\ImportExport\Struct\Config;
  4. use Shopware\Core\Content\Media\Aggregate\MediaFolder\MediaFolderEntity;
  5. use Shopware\Core\Content\Media\File\FileSaver;
  6. use Shopware\Core\Content\Media\File\MediaFile;
  7. use Shopware\Core\Content\Media\MediaService;
  8. use Shopware\Core\Framework\Context;
  9. use Shopware\Core\Framework\DataAbstractionLayer\EntityDefinition;
  10. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
  11. use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityWrittenEvent;
  12. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  13. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
  14. use Shopware\Core\Framework\Uuid\Uuid;
  15. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  16. use Symfony\Component\HttpFoundation\Request;
  17. class MediaSerializer extends EntitySerializer implements EventSubscriberInterface
  18. {
  19.     /**
  20.      * @var FileSaver
  21.      */
  22.     private $fileSaver;
  23.     /**
  24.      * @var MediaService
  25.      */
  26.     private $mediaService;
  27.     /**
  28.      * @var EntityRepositoryInterface
  29.      */
  30.     private $mediaFolderRepository;
  31.     /**
  32.      * @var EntityRepositoryInterface
  33.      */
  34.     private $mediaRepository;
  35.     /**
  36.      * @var array[]
  37.      */
  38.     private $mediaFiles = [];
  39.     /**
  40.      * @var string[]
  41.      */
  42.     private $urlMediaIdMapping = [];
  43.     public function __construct(
  44.         MediaService $mediaService,
  45.         FileSaver $fileSaver,
  46.         EntityRepositoryInterface $mediaFolderRepository,
  47.         EntityRepositoryInterface $mediaRepository
  48.     ) {
  49.         $this->mediaService $mediaService;
  50.         $this->fileSaver $fileSaver;
  51.         $this->mediaFolderRepository $mediaFolderRepository;
  52.         $this->mediaRepository $mediaRepository;
  53.     }
  54.     public function serialize(Config $configEntityDefinition $definition$value): iterable
  55.     {
  56.         yield from parent::serialize($config$definition$value);
  57.     }
  58.     public function deserialize(Config $configEntityDefinition $definition$value)
  59.     {
  60.         $value is_array($value) ? $value iterator_to_array($value);
  61.         $deserialized parent::deserialize($config$definition$value);
  62.         if (is_iterable($deserialized)) {
  63.             $deserialized iterator_to_array($deserialized);
  64.         }
  65.         $url $value['url'] ?? null;
  66.         if ($url === null || !filter_var($urlFILTER_VALIDATE_URL)) {
  67.             return $deserialized;
  68.         }
  69.         $media null;
  70.         if (isset($deserialized['id'])) {
  71.             $media $this->mediaRepository->search(new Criteria([$value['id']]), Context::createDefaultContext())->first();
  72.         }
  73.         if ($media === null || $media->getUrl() !== $url) {
  74.             $entityName $config->get('sourceEntity') ?? $definition->getEntityName();
  75.             $deserialized['mediaFolderId'] = $deserialized['mediaFolderId']
  76.                 ?? $this->getMediaFolderId($deserialized['id'] ?? null$entityName);
  77.             $deserialized['id'] = $deserialized['id'] ?? Uuid::randomHex();
  78.             $parsed parse_url($url);
  79.             $pathInfo pathinfo($parsed['path']);
  80.             $media $this->fetchFileFromURL((string) $url$pathInfo['extension'] ?? '');
  81.             $this->mediaFiles[$deserialized['id']] = [
  82.                 'media' => $media,
  83.                 'destination' => $pathInfo['filename'] ?? $deserialized['id'],
  84.             ];
  85.         }
  86.         return $deserialized;
  87.     }
  88.     public function supports(string $entity): bool
  89.     {
  90.         return $entity === 'media';
  91.     }
  92.     public static function getSubscribedEvents()
  93.     {
  94.         return [
  95.             'media.written' => 'persistMedia',
  96.         ];
  97.     }
  98.     /**
  99.      * @internal
  100.      */
  101.     public function persistMedia(EntityWrittenEvent $event): void
  102.     {
  103.         if (empty($this->mediaFiles)) {
  104.             return;
  105.         }
  106.         $mediaFiles $this->mediaFiles;
  107.         // prevent recursion
  108.         $this->mediaFiles = [];
  109.         foreach ($event->getIds() as $id) {
  110.             if (!isset($mediaFiles[$id])) {
  111.                 continue;
  112.             }
  113.             $mediaFile $mediaFiles[$id];
  114.             $this->fileSaver->persistFileToMedia(
  115.                 $mediaFile['media'],
  116.                 $mediaFile['destination'],
  117.                 $id,
  118.                 $event->getContext()
  119.             );
  120.         }
  121.     }
  122.     private function getMediaFolderId(?string $id$entity): string
  123.     {
  124.         if ($id !== null) {
  125.             /** @var MediaFolderEntity|null $folder */
  126.             $folder $this->mediaFolderRepository->search(new Criteria([$id]), Context::createDefaultContext())->first();
  127.             if ($folder !== null) {
  128.                 return $folder->getId();
  129.             }
  130.         }
  131.         $criteria = new Criteria();
  132.         $criteria->addFilter(new EqualsFilter('media_folder.defaultFolder.entity'$entity));
  133.         $criteria->addAssociation('defaultFolder');
  134.         /** @var MediaFolderEntity|null $default */
  135.         $default $this->mediaFolderRepository->search($criteriaContext::createDefaultContext())->first();
  136.         if ($default !== null) {
  137.             return $default->getId();
  138.         }
  139.         $criteria = new Criteria();
  140.         $criteria->addFilter(new EqualsFilter('media_folder.defaultFolder.entity''import_export_profile'));
  141.         $criteria->addAssociation('defaultFolder');
  142.         /** @var MediaFolderEntity|null $fallback */
  143.         $fallback $this->mediaFolderRepository->search($criteriaContext::createDefaultContext())->first();
  144.         if ($fallback === null) {
  145.             throw new \RuntimeException('Failed to find default media folder for import_export_profile');
  146.         }
  147.         return $fallback->getId();
  148.     }
  149.     private function fetchFileFromURL(string $urlstring $extension): MediaFile
  150.     {
  151.         $request = new Request();
  152.         $request->query->set('url'$url);
  153.         $request->query->set('extension'$extension);
  154.         $request->request->set('url'$url);
  155.         $request->request->set('extension'$extension);
  156.         $request->headers->set('content-type''application/json');
  157.         return $this->mediaService->fetchFile($request);
  158.     }
  159. }