vendor/shopware/platform/src/Core/Content/ImportExport/DataAbstractionLayer/Serializer/Entity/MediaSerializer.php line 112

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