consumer_image_styles-8.x-3.0/src/Normalizer/LinkCollectionNormalizer.php

src/Normalizer/LinkCollectionNormalizer.php
<?php

namespace Drupal\consumer_image_styles\Normalizer;

use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\File\FileUrlGeneratorInterface;
use Drupal\Core\Image\ImageFactory;
use Drupal\Core\Url;
use Drupal\consumer_image_styles\ImageStylesProvider;
use Drupal\consumer_image_styles\ImageStylesProviderInterface;
use Drupal\consumers\Entity\Consumer;
use Drupal\consumers\MissingConsumer;
use Drupal\consumers\Negotiator;
use Drupal\image\ImageStyleInterface;
use Drupal\jsonapi\JsonApiResource\Link;
use Drupal\jsonapi\JsonApiResource\LinkCollection;
use Drupal\jsonapi\JsonApiResource\ResourceObject;
use Drupal\jsonapi\Normalizer\Value\CacheableNormalization;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;

/**
 * Custom normalizer that add the derivatives to image entities.
 */
class LinkCollectionNormalizer implements NormalizerInterface {

  /**
   * Consumer Negotiator service.
   *
   * @var \Drupal\consumers\Negotiator
   */
  protected $consumerNegotiator;

  /**
   * Image Styles provider service.
   *
   * @var \Drupal\consumer_image_styles\ImageStylesProviderInterface
   */
  protected $imageStylesProvider;

  /**
   * The Image Factory.
   *
   * @var \Drupal\Core\Image\ImageFactory
   */
  protected $imageFactory;

  /**
   * The Normalizer Serializer.
   *
   * @var \Symfony\Component\Serializer\Normalizer\NormalizerInterface
   */
  protected $inner;

  /**
   * The request stack.
   *
   * @var \Symfony\Component\HttpFoundation\RequestStack
   */
  protected $requestStack;

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

  /**
   * Constructs a LinkCollectionNormalizer object.
   *
   * @param \Symfony\Component\Serializer\Normalizer\NormalizerInterface $inner
   *   The decorated service.
   * @param \Drupal\consumers\Negotiator $consumer_negotiator
   *   The consumer negotiator.
   * @param \Drupal\consumer_image_styles\ImageStylesProviderInterface $imageStylesProvider
   *   Image styles utility.
   * @param \Drupal\Core\Image\ImageFactory $image_factory
   *   The image factory.
   * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
   *   The request stack.
   * @param \Drupal\Core\File\FileUrlGeneratorInterface $file_url_generator
   *   The file URL generator.
   */
  public function __construct(NormalizerInterface $inner, Negotiator $consumer_negotiator, ImageStylesProviderInterface $imageStylesProvider, ImageFactory $image_factory, RequestStack $request_stack, FileUrlGeneratorInterface $file_url_generator) {
    $this->inner = $inner;
    $this->consumerNegotiator = $consumer_negotiator;
    $this->imageStylesProvider = $imageStylesProvider;
    $this->imageFactory = $image_factory;
    $this->requestStack = $request_stack;
    $this->fileUrlGenerator = $file_url_generator;
  }

  /**
   * {@inheritdoc}
   */
  public function supportsNormalization($data, $format = NULL, $context = []): bool {
    return $this->inner->supportsNormalization($data, $format, $context);
  }

  /**
   * {@inheritdoc}
   */
  public function normalize($link_collection, $format = NULL, array $context = []): array|string|int|float|bool|\ArrayObject|NULL {
    assert($link_collection instanceof LinkCollection);
    if ($this->decorationApplies($link_collection) && ($consumer = $this->getConsumer())) {
      $variant_links = $this->buildVariantLinks($link_collection->getContext(), $consumer);
      $normalization = $this->inner->normalize(
        LinkCollection::merge($link_collection, $variant_links),
        $format,
        $context
      );
      return static::addLinkRels($normalization, $variant_links)
        ->withCacheableDependency($consumer);
    }
    return $this->inner->normalize($link_collection, $format, $context);
  }

  /**
   * Builds links for the consumer variant.
   *
   * @param \Drupal\jsonapi\JsonApiResource\ResourceObject $resource_object
   *   The Resource Object.
   * @param \Drupal\consumers\Entity\Consumer $consumer
   *   The attached consumer entity.
   *
   * @return \Drupal\jsonapi\JsonApiResource\LinkCollection
   *   The variant links.
   */
  protected function buildVariantLinks(ResourceObject $resource_object, Consumer $consumer) {
    // Prepare some utils.
    $uri = $resource_object->getField($resource_object->getResourceType()->getPublicName('uri'))->value;
    // Generate derivatives only for the found ones.
    $image_styles = $this->imageStylesProvider->loadStyles($consumer);
    return array_reduce($image_styles, function (LinkCollection $decorated, ImageStyleInterface $image_style) use ($uri) {
      $link = $this->imageStylesProvider->buildDerivativeLink($uri, $image_style);
      $dimensions = [];
      if (isset($link['meta']['width'])) {
        $dimensions['width'] = $link['meta']['width'];
      }
      if (isset($link['meta']['height'])) {
        $dimensions['width'] = $link['meta']['height'];
      }
      $variant_link = new Link(
        CacheableMetadata::createFromObject($image_style),
        Url::fromUri($link['href']),
        ImageStylesProvider::DERIVATIVE_LINK_REL,
        // Target attributes can only be strings, but dimensions are links.
        array_map(function (?int $dimension): string {
          return sprintf('%d', $dimension);
        }, $dimensions)
      );
      return $decorated->withLink($image_style->id(), $variant_link);
    }, (new LinkCollection([]))->withContext($resource_object));
  }

  /**
   * Whether this decorator applies to the current data.
   *
   * @param \Drupal\jsonapi\JsonApiResource\LinkCollection $link_collection
   *   The link collection to be normalized.
   *
   * @return bool
   *   TRUE if the link collection belongs to an image file resource object,
   *   FALSE otherwise.
   */
  protected function decorationApplies(LinkCollection $link_collection) {
    $link_context = $link_collection->getContext();
    if (!$link_context instanceof ResourceObject) {
      return FALSE;
    }
    $resource_type = $link_context->getResourceType();
    if ($resource_type->getEntityTypeId() !== 'file') {
      return FALSE;
    }
    $uriField = $link_context->getField($resource_type->getPublicName('uri'));
    return $uriField && in_array(
        mb_strtolower(pathinfo($uriField->value, PATHINFO_EXTENSION)),
        $this->imageFactory->getSupportedExtensions()
      );
  }

  /**
   * Gets the current consumer.
   *
   * @return \Drupal\consumers\Entity\Consumer
   *   The current consumer or NULL if one cannot be negotiated.
   */
  protected function getConsumer() {
    try {
      return $this->consumerNegotiator->negotiateFromRequest($this->requestStack->getCurrentRequest());
    }
    catch (MissingConsumer $e) {
      return NULL;
    }
  }

  /**
   * Adds the derivative link relation type to the normalized link collection.
   *
   * @param \Drupal\jsonapi\Normalizer\Value\CacheableNormalization $cacheable_normalization
   *   The cacheable normalization to which link relations need to be added.
   * @param \Drupal\jsonapi\JsonApiResource\LinkCollection $link_collection
   *   The un-normalized link collection.
   *
   * @return \Drupal\jsonapi\Normalizer\Value\CacheableNormalization
   *   The links normalization with meta.rel added.
   */
  protected static function addLinkRels(CacheableNormalization $cacheable_normalization, LinkCollection $link_collection) {
    $normalization = $cacheable_normalization->getNormalization();
    foreach ($normalization as $key => &$normalized_link) {
      $links = iterator_to_array($link_collection);
      if (isset($links[$key])) {
        $normalized_link['meta']['rel'] = array_reduce($links[$key], function (array $relations, Link $link) {
          $relations[] = $link->getLinkRelationType();
          return array_unique($relations);
        }, []);
      }
    }
    return new CacheableNormalization($cacheable_normalization, $normalization);
  }

  /**
   * {@inheritdoc}
   */
  public function getSupportedTypes(?string $format): array {
    return [
      LinkCollection::class => TRUE,
    ];
  }

}

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

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