View source
<?php
namespace Drupal\consumer_image_styles\Normalizer;
use Drupal\consumer_image_styles\ImageStylesProvider;
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, ImageStylesProvider $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);
}
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) {
$variant_link = new Link(CacheableMetadata::createFromObject($image_style), Url::fromUri(file_create_url($image_style
->buildUrl($uri))), [
ImageStylesProvider::DERIVATIVE_LINK_REL,
]);
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 $this->imageFactory
->get($link_context
->getField($resource_type
->getPublicName('uri'))->value)
->isValid();
}
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) {
return array_unique(array_merge($relations, $link
->getLinkRelationTypes()));
}, []);
}
}
return new CacheableNormalization($cacheable_normalization, $normalization);
}
}