View source
<?php
namespace Drupal\consumer_image_styles\Normalizer;
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\Core\Image\ImageFactory;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Url;
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;
class LinkCollectionNormalizer implements NormalizerInterface {
protected $consumerNegotiator;
protected $imageStylesProvider;
protected $imageFactory;
protected $inner;
protected $requestStack;
public function __construct(NormalizerInterface $inner, Negotiator $consumer_negotiator, ImageStylesProviderInterface $imageStylesProvider, ImageFactory $image_factory, RequestStack $request_stack) {
$this->inner = $inner;
$this->consumerNegotiator = $consumer_negotiator;
$this->imageStylesProvider = $imageStylesProvider;
$this->imageFactory = $image_factory;
$this->requestStack = $request_stack;
}
public function supportsNormalization($data, $format = NULL) {
return $this->inner
->supportsNormalization($data, $format);
}
public function normalize($link_collection, $format = NULL, array $context = []) {
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);
}
protected function buildVariantLinks(ResourceObject $resource_object, Consumer $consumer) {
$uri = $resource_object
->getField($resource_object
->getResourceType()
->getPublicName('uri'))->value;
$image_styles = $this->imageStylesProvider
->loadStyles($consumer);
return array_reduce($image_styles, function (LinkCollection $decorated, ImageStyleInterface $image_style) use ($uri) {
$image = $this->imageFactory
->get($uri);
$dimensions = [
'width' => $image
->getWidth(),
'height' => $image
->getHeight(),
];
$image_style
->transformDimensions($dimensions, $uri);
$variant_link = new Link(CacheableMetadata::createFromObject($image_style), Url::fromUri(file_create_url($image_style
->buildUrl($uri))), ImageStylesProvider::DERIVATIVE_LINK_REL, array_map(function (int $dimension) : string {
return sprintf('%d', $dimension);
}, $dimensions));
return $decorated
->withLink($image_style
->id(), $variant_link);
}, (new LinkCollection([]))
->withContext($resource_object));
}
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;
}
return in_array(mb_strtolower(pathinfo($link_context
->getField($resource_type
->getPublicName('uri'))->value, PATHINFO_EXTENSION)), $this->imageFactory
->getSupportedExtensions());
}
protected function getConsumer() {
try {
return $this->consumerNegotiator
->negotiateFromRequest($this->requestStack
->getCurrentRequest());
} catch (MissingConsumer $e) {
return NULL;
}
}
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);
}
}