content_sync-8.x-2.x-dev/src/Normalizer/FileEntityNormalizer.php

src/Normalizer/FileEntityNormalizer.php
<?php

namespace Drupal\content_sync\Normalizer;

use Drupal\content_sync\Plugin\SyncNormalizerDecoratorManager;
use Drupal\Core\File\FileSystemInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Entity\EntityTypeRepositoryInterface;
use Drupal\Core\Entity\EntityFieldManagerInterface;
use Drupal\Component\Render\FormattableMarkup;
use Drupal\Core\File\FileUrlGeneratorInterface;

/**
 * Adds the file URI to embedded file entities.
 */
class FileEntityNormalizer extends ContentEntityNormalizer {

  /**
   * The interface or class that this Normalizer supports.
   *
   * @var string
   */
  protected $supportedInterfaceOrClass = 'Drupal\file\FileInterface';

  /**
   * File system service.
   *
   * @var \Drupal\Core\File\FileSystemInterface
   */
  protected $fileSystem;

  /**
   * The file URL generator.
   *
   * @var \Drupal\Core\File\FileUrlGeneratorInterface
   */
  protected $fileUrlGenerator;

  /**
   * FileEntityNormalizer constructor.
   *
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   *   The entity type manager.
   * @param \Drupal\Core\Entity\EntityTypeRepositoryInterface $entity_type_repository
   *   The entity type repository.
   * @param \Drupal\Core\Entity\EntityFieldManagerInterface $entity_field_manager
   *   The entity field manager.
   *
   * @param \Drupal\content_sync\Plugin\SyncNormalizerDecoratorManager $decorator_manager
   *
   * @param \Drupal\Core\File\FileSystemInterface $file_system
   *   File system service.
   * @param \Drupal\Core\File\FileUrlGeneratorInterface $file_url_generator
   *   The file URL generator.
   */
  public function __construct(
      EntityTypeManagerInterface $entity_type_manager,
      EntityTypeRepositoryInterface $entity_type_repository,
      EntityFieldManagerInterface $entity_field_manager,
      SyncNormalizerDecoratorManager $decorator_manager,
      FileSystemInterface $file_system,
      FileUrlGeneratorInterface $file_url_generator) {
    parent::__construct($entity_type_manager,
                        $entity_type_repository,
                        $entity_field_manager,
                        $decorator_manager);
    $this->fileSystem = $file_system;
    $this->fileUrlGenerator = $file_url_generator;
  }

  /**
   * {@inheritdoc}
   */
  public function denormalize($data, $class, $format = NULL, array $serializer_context = array()): array|string|int|float|bool|\ArrayObject|NULL {

    $file_data = '';

    // Check if the image is available as base64-encoded image.
    if (!empty($data['data'][0]['value'])) {
      $file_data = $data['data'][0]['value'];
      // Avoid 'data' being treated as a field.
      unset($data['data']);
    }

    // If a directory is set, we must to copy the file to the file system.
    if (!empty($serializer_context['content_sync_directory_files'])) {
      $scheme = \Drupal::service('stream_wrapper_manager')->getScheme($data['uri'][0]['value']);
      if (!empty($scheme)) {
        $source_path = realpath($serializer_context['content_sync_directory_files']) . '/' .$scheme . '/';
        $source      = str_replace($scheme . '://', $source_path, $data['uri'][0]['value']);
        if (file_exists($source)) {
          $file = $this->fileSystem->realpath($data['uri'][0]['value']);
          if (!file_exists($file) || (md5_file($file) !== md5_file($source))) {
            $dir = $this->fileSystem->dirname($data['uri'][0]['value']);
            $this->fileSystem->prepareDirectory($dir, FileSystemInterface::CREATE_DIRECTORY);
            $uri = $this->fileSystem->copy($source, $data['uri'][0]['value']);
            $data['uri'] = [
              [
                'value' => $uri,
                'url' => str_replace($GLOBALS['base_url'], '', $this->fileUrlGenerator->generateAbsoluteString($uri))
              ]
            ];

            // We just need one method to create the image.
            $file_data = '';
          }
        }
      }
    }

    $entity = parent::denormalize($data, $class, $format, $serializer_context);

    // If the image was sent as base64 we must to create the physical file.
    if ($file_data) {
      // Decode and save to file.
      $file_contents = base64_decode($file_data);
      $dirname = $this->fileSystem->dirname($entity->getFileUri());
      $this->fileSystem->prepareDirectory($dirname, FileSystemInterface::CREATE_DIRECTORY);
      if ($uri = $this->fileSystem->saveData($file_contents, $entity->getFileUri())) {
        $entity->setFileUri($uri);
      }
      else {
        throw new \RuntimeException(new FormattableMarkup('Failed to write @filename.', ['@filename' => $entity->getFilename()]));
      }
    }

    // If the image was sent as URL we must to create the physical file.
    /*if ($file_data) {
      // Decode and save to file.
      $file_contents = base64_decode($file_data);
      $dirname = $this->fileSystem->dirname($entity->getFileUri());
      file_prepare_directory($dirname, FILE_CREATE_DIRECTORY);
      if ($uri = file_unmanaged_save_data($file_contents, $entity->getFileUri())) {
        $entity->setFileUri($uri);
      }
      else {
        throw new \RuntimeException(SafeMarkup::format('Failed to write @filename.', array('@filename' => $entity->getFilename())));
      }
    }*/

    return $entity;
  }

  /**
   * {@inheritdoc}
   */
  public function normalize($object, $format = NULL, array $serializer_context = array()): array|\ArrayObject|bool|float|int|NULL|string {
    $data = parent::normalize($object, $format, $serializer_context);

    // The image will be saved in the export directory.
    if (!empty($serializer_context['content_sync_directory_files'])) {
      $uri = $object->getFileUri();
      $scheme = \Drupal::service('stream_wrapper_manager')->getScheme($uri);
      $destination = "{$serializer_context['content_sync_directory_files']}/{$scheme}/";
      $destination = str_replace($scheme . '://', $destination, $uri);
      $prep_dir = $this->fileSystem->dirname($destination);
      $this->fileSystem->prepareDirectory($prep_dir, FileSystemInterface::CREATE_DIRECTORY);
      // Exception for when the file doesn't exist
      // TODO: add a notice/log about it.
      if (file_exists($uri)) {
        $this->fileSystem->copy($uri, $destination, FileSystemInterface::EXISTS_REPLACE);
      }
    }

    // Set base64-encoded file contents to the "data" property.
    if (!empty($serializer_context['content_sync_file_base_64'])) {
      $file_data = base64_encode(file_get_contents($object->getFileUri()));
      $data['data'] = [['value' => $file_data]];
    }

    return $data;
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc