view_mode_crop-1.0.x-dev/src/Plugin/Field/FieldFormatter/ViewModeCropEntityReferenceEntityFormatter.php
src/Plugin/Field/FieldFormatter/ViewModeCropEntityReferenceEntityFormatter.php
<?php
namespace Drupal\view_mode_crop\Plugin\Field\FieldFormatter;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Entity\Plugin\DataType\EntityAdapter;
use Drupal\Core\Field\EntityReferenceFieldItemListInterface;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\Plugin\Field\FieldFormatter\EntityReferenceEntityFormatter;
use Drupal\Core\TypedData\TranslatableInterface;
/**
* Replaces the EntityReferenceEntityFormatter formatter.
*/
class ViewModeCropEntityReferenceEntityFormatter extends EntityReferenceEntityFormatter {
/**
* {@inheritDoc}
*/
protected function getEntitiesToView(EntityReferenceFieldItemListInterface $items, $langcode) {
$entities = [];
foreach ($items as $delta => $item) {
// Ignore items where no entity could be loaded in prepareView().
if (!empty($item->_loaded)) {
// When referring the same media image entity in a field,
// EntityReferenceFormatterBase should clone $item->entity to make
// CropImageHelper::getUri work with the correct delta.
if (!isset($item->entity)) {
throw new \RuntimeException('Missing entity');
}
$entity = clone $item->entity;
// Set the entity in the correct language for display.
if ($entity instanceof TranslatableInterface) {
$entity = \Drupal::service('entity.repository')
->getTranslationFromContext($entity, $langcode);
}
$access = $this->checkAccess($entity);
// Add the access result's cacheability, ::view() needs it.
// @phpstan-ignore-next-line
$item->_accessCacheability = CacheableMetadata::createFromObject($access);
if ($access->isAllowed()) {
// Add the referring item, in case the formatter needs it.
$entity->_referringItem = $items[$delta];
$entities[$delta] = $entity;
}
}
}
return $entities;
}
/**
* {@inheritDoc}
*/
public function viewElements(FieldItemListInterface $items, $langcode) {
$view_mode = $this->getSetting('view_mode');
$elements = [];
$items_parent = $items->getParent();
if (!$items_parent instanceof EntityAdapter) {
throw new \RuntimeException('Unexpected class ' . get_class($items_parent));
}
/**
* @var \Drupal\Core\Entity\EntityInterface $parent_entity
*/
$parent_entity = $items_parent->getEntity();
foreach ($this->getEntitiesToView($items, $langcode) as $delta => $entity) {
// Due to render caching and delayed calls, the viewElements() method
// will be called later in the rendering process through a '#pre_render'
// callback, so we need to generate a counter that takes into account
// all the relevant information about this field and the referenced
// entity that is being rendered.
$recursive_render_id =
// Include the parent entity so multiple renders of the same referenced
// entity will not hit the recursive protections.
$parent_entity->getEntityTypeId()
. $parent_entity->id()
. $items->getFieldDefinition()->getTargetEntityTypeId()
. $items->getFieldDefinition()->getTargetBundle()
. $items->getName()
// We include the referencing entity, so we can render default images
// without hitting recursive protections.
. $items->getEntity()->id()
. $entity->getEntityTypeId()
. $entity->id();
if (isset(static::$recursiveRenderDepth[$recursive_render_id])) {
static::$recursiveRenderDepth[$recursive_render_id]++;
}
else {
static::$recursiveRenderDepth[$recursive_render_id] = 1;
}
if (static::$recursiveRenderDepth[$recursive_render_id] > static::RECURSIVE_RENDER_LIMIT) {
// Protect ourselves from recursive rendering.
return $elements;
}
$view_builder = $this->entityTypeManager->getViewBuilder($entity->getEntityTypeId());
$elements[$delta] = $view_builder->view($entity, $view_mode, $entity->language()->getId());
// Add a resource attribute to set the mapping property's value to the
// entity's url. Since we don't know what the markup of the entity will
// be, we shouldn't rely on it for structured data such as RDFa.
if (!empty($items[$delta]->_attributes) && !$entity->isNew() && $entity->hasLinkTemplate('canonical')) {
$items[$delta]->_attributes += ['resource' => $entity->toUrl()->toString()];
}
// Add a cache key to make sure the viewed elements cache is related to
// the parent entity's field delta.
$elements[$delta]['#cache']['keys'][] = $parent_entity->getEntityTypeId() . '_' . $parent_entity->id() . '_' . $items->getName() . '_' . $delta;
}
return $elements;
}
}
