Created
January 29, 2021 08:09
-
-
Save opi/879fe7d9932c25a41daa9c42f1dc804b to your computer and use it in GitHub Desktop.
mymodule/src/Plugin/Field/FieldFormatter/ParagraphsBetterSummaryFormatter.php A Better Paragraphs Summary Formatter
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Drupal\mobilis\Plugin\Field\FieldFormatter; | |
use Drupal\Core\Entity\EntityDisplayRepositoryInterface; | |
use Drupal\Core\Entity\EntityTypeManagerInterface; | |
use Drupal\Core\Form\FormStateInterface; | |
use Drupal\Core\Field\FieldDefinitionInterface; | |
use Drupal\Core\Field\FieldItemListInterface; | |
use Drupal\Core\Field\Plugin\Field\FieldFormatter\EntityReferenceFormatterBase; | |
use Drupal\paragraphs\ParagraphInterface; | |
use Drupal\Core\Logger\LoggerChannelFactoryInterface; | |
use Symfony\Component\DependencyInjection\ContainerInterface; | |
/** | |
* Plugin implementation of the 'paragraphs_better_summary' formatter. | |
* | |
* @FieldFormatter( | |
* id = "paragraphs_better_summary", | |
* label = @Translation("Paragraph better summary"), | |
* field_types = { | |
* "entity_reference_revisions" | |
* } | |
* ) | |
*/ | |
class ParagraphsBetterSummaryFormatter extends EntityReferenceFormatterBase { | |
/** | |
* The number of times this formatter allows rendering the same entity. | |
* | |
* @var int | |
*/ | |
const RECURSIVE_RENDER_LIMIT = 20; | |
/** | |
* The logger factory. | |
* | |
* @var \Drupal\Core\Logger\LoggerChannelFactoryInterface | |
*/ | |
protected $loggerFactory; | |
/** | |
* The entity type manager. | |
* | |
* @var \Drupal\Core\Entity\EntityTypeManagerInterface | |
*/ | |
protected $entityTypeManager; | |
/** | |
* The entity display repository. | |
* | |
* @var \Drupal\Core\Entity\EntityDisplayRepositoryInterface | |
*/ | |
protected $entityDisplayRepository; | |
/** | |
* An array of counters for the recursive rendering protection. | |
* | |
* Each counter takes into account all the relevant information about the | |
* field and the referenced entity that is being rendered. | |
* | |
* @see \Drupal\Core\Field\Plugin\Field\FieldFormatter\EntityReferenceEntityFormatter::viewElements() | |
* | |
* @var array | |
*/ | |
protected static $recursiveRenderDepth = []; | |
/** | |
* Constructs an EntityReferenceEntityFormatter instance. | |
* | |
* @param string $plugin_id | |
* The plugin_id for the formatter. | |
* @param mixed $plugin_definition | |
* The plugin implementation definition. | |
* @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition | |
* The definition of the field to which the formatter is associated. | |
* @param array $settings | |
* The formatter settings. | |
* @param string $label | |
* The formatter label display setting. | |
* @param string $view_mode | |
* The view mode. | |
* @param array $third_party_settings | |
* Any third party settings settings. | |
* @param \Drupal\Core\Logger\LoggerChannelFactoryInterface $logger_factory | |
* The logger factory. | |
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager | |
* The entity type manager. | |
* @param \Drupal\Core\Entity\EntityDisplayRepositoryInterface $entity_display_repository | |
* The entity display repository. | |
*/ | |
public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, $label, $view_mode, array $third_party_settings, LoggerChannelFactoryInterface $logger_factory, EntityTypeManagerInterface $entity_type_manager, EntityDisplayRepositoryInterface $entity_display_repository) { | |
parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $label, $view_mode, $third_party_settings); | |
$this->loggerFactory = $logger_factory; | |
$this->entityTypeManager = $entity_type_manager; | |
$this->entityDisplayRepository = $entity_display_repository; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { | |
return new static( | |
$plugin_id, | |
$plugin_definition, | |
$configuration['field_definition'], | |
$configuration['settings'], | |
$configuration['label'], | |
$configuration['view_mode'], | |
$configuration['third_party_settings'], | |
$container->get('logger.factory'), | |
$container->get('entity_type.manager'), | |
$container->get('entity_display.repository') | |
); | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public static function defaultSettings() { | |
return [ | |
'allowed_bundles' => [], | |
'limit' => 1, | |
'view_mode' => 'default', | |
] + parent::defaultSettings(); | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function settingsForm(array $form, FormStateInterface $form_state) { | |
$target_type = $this->getFieldSetting('target_type'); | |
$bundles = \Drupal::service('entity_type.bundle.info')->getBundleInfo($target_type); | |
$target_bundles = $this->getFieldSetting('handler_settings')['target_bundles']; | |
$options = []; | |
foreach($target_bundles as $bundle) { | |
$options[$bundle] = $bundles[$bundle]['label']; | |
} | |
$elements['allowed_bundles'] = [ | |
'#title' => t("Allowed bundles"), | |
'#type' => 'checkboxes', | |
'#options' => $options, | |
'#default_value' => $this->getSetting('allowed_bundles'), | |
'#description' => t('Select allowed bundles'), | |
]; | |
$elements['view_mode'] = [ | |
'#title' => t('View mode'), | |
'#type' => 'select', | |
'#options' => $this->entityDisplayRepository->getViewModeOptions($this->getFieldSetting('target_type')), | |
'#default_value' => $this->getSetting('view_mode'), | |
'#required' => TRUE, | |
]; | |
$elements['limit'] = [ | |
'#title' => t("Limit"), | |
'#type' => 'number', | |
'#min' => 0, | |
'#step' => 1, | |
'#size' => 2, | |
'#default_value' => $this->getSetting('limit'), | |
'#description' => t('Limit the number of paragraphs items to be returned. 0 to set no limit.'), | |
]; | |
return $elements; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function settingsSummary() { | |
$summary = []; | |
// Alowed bundles | |
$target_type = $this->getFieldSetting('target_type'); | |
$bundles = \Drupal::service('entity_type.bundle.info')->getBundleInfo($target_type); | |
$allowed_bundles = array_filter($this->getSetting('allowed_bundles')); | |
if (empty($allowed_bundles)) { | |
$allowed_bundles[] = t("All"); | |
} | |
else { | |
foreach($allowed_bundles as $bundle) { | |
$allowed_bundles[$bundle] = $bundles[$bundle]['label']; | |
} | |
} | |
$summary[] = t("Allowed bundles: @allowed_bundles", [ | |
'@allowed_bundles' => implode(', ', $allowed_bundles) | |
]); | |
// View mode | |
$view_modes = $this->entityDisplayRepository->getViewModeOptions($this->getFieldSetting('target_type')); | |
$view_mode = $this->getSetting('view_mode'); | |
$summary[] = t('Rendered as @mode', ['@mode' => isset($view_modes[$view_mode]) ? $view_modes[$view_mode] : $view_mode]); | |
// Limit | |
$limit = $this->getSetting('limit') ?? t('Unlimited'); | |
$summary[] = t("Limit: @limit", ['@limit' => $limit]); | |
return $summary; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function viewElements(FieldItemListInterface $items, $langcode) { | |
$view_mode = $this->getSetting('view_mode'); | |
$allowed_bundles = $this->getSetting('allowed_bundles'); | |
$limit = $this->getSetting('limit'); | |
$elements = []; | |
$entities_to_view = $this->getEntitiesToView($items, $langcode); | |
foreach ($entities_to_view 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 = $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; | |
} | |
// Protect ourselves from recursive rendering. | |
if (static::$recursiveRenderDepth[$recursive_render_id] > static::RECURSIVE_RENDER_LIMIT) { | |
$this->loggerFactory->get('entity')->error('Recursive rendering detected when rendering entity %entity_type: %entity_id, using the %field_name field on the %parent_entity_type:%parent_bundle %parent_entity_id entity. Aborting rendering.', [ | |
'%entity_type' => $entity->getEntityTypeId(), | |
'%entity_id' => $entity->id(), | |
'%field_name' => $items->getName(), | |
'%parent_entity_type' => $items->getFieldDefinition()->getTargetEntityTypeId(), | |
'%parent_bundle' => $items->getFieldDefinition()->getTargetBundle(), | |
'%parent_entity_id' => $items->getEntity()->id(), | |
]); | |
return $elements; | |
} | |
/** | |
* The next part is the only one to differ from EntityReferenceEntityFormatter | |
*/ | |
if (empty($allowed_bundles[$entity->bundle()])) { | |
continue; | |
} | |
$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()]; | |
} | |
// Handle limit | |
if ($limit && count($elements) >= $limit) { | |
break; | |
} | |
} | |
return $elements; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public static function isApplicable(FieldDefinitionInterface $field_definition) { | |
$target_type = $field_definition->getSetting('target_type'); | |
$paragraph_type = \Drupal::entityTypeManager()->getDefinition($target_type); | |
if ($paragraph_type) { | |
return $paragraph_type->entityClassImplements(ParagraphInterface::class); | |
} | |
return FALSE; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment