Skip to content
Snippets Groups Projects

Add generateMultiple(); remove some methods.

Files
2
@@ -158,26 +158,140 @@ class CustomElementGenerator {
}
/**
* Generates a custom element tag for the given entity and view mode.
* Generates a custom element from entity, possibly after translation.
*
* @param \Drupal\Core\Entity\ContentEntityInterface $entity
* Entity to process.
* @param string $viewMode
* View mode used for rendering field values into slots.
* @param string|null $langcode
* (optional) For which language the entity should be rendered, defaults to
* the current content language.
* (optional) For which language the entities should be rendered. Defaults
* to the current content language.
* @param \Drupal\Core\Session\AccountInterface|null $account
* (optional) The user for which to check access when rendering fields.
* Defaults to the current user.
*
* @return \Drupal\custom_elements\CustomElement
* Extracted custom elements containing data attributes and slots.
* Custom element containing entity properties as attributes and slots.
*/
public function generate(ContentEntityInterface $entity, string $viewMode, string $langcode = NULL) {
// Get desired entity translation.
$entity = $this->entityRepository->getTranslationFromContext($entity, $langcode);
$custom_element = $this->getEntityDefaults($entity, $viewMode);
$this->buildEntityContent($entity, $custom_element, $viewMode);
$this->moduleHandler->alter('custom_element_entity', $custom_element, $entity, $viewMode);
    • This pre-existing alter hook is moved into buildEntities(),

      • because that happened to be more convenient
      • and because it feels like generated custom elements should always be passed through an alter, also when called through another public function. (Since all the other public functions are new in 3.x, that's not a backward compatibility issue.)
Please register or sign in to reply
return $custom_element;
public function generate(ContentEntityInterface $entity, string $viewMode, string $langcode = NULL, AccountInterface $account = NULL) {
$custom_elements = $this->generateMultiple([$entity], $viewMode, $langcode, $account);
return current($custom_elements);
}
/**
* Generates custom elements from entities, possibly after translation.
*
* @param \Drupal\Core\Entity\ContentEntityInterface[] $entities
* Entities to process.
* @param string $viewMode
* View mode used for rendering field values into slots.
* @param string|null $langcode
* (optional) For which language the entities should be rendered. Defaults
* to the current content language.
* @param \Drupal\Core\Session\AccountInterface|null $account
* (optional) The user for which to check access when rendering fields.
* Defaults to the current user.
*
* @return \Drupal\custom_elements\CustomElement[]
* Custom elements containing entities' properties as attributes and slots,
* keyed by the same value as the corresponding entities.
*/
public function generateMultiple(array $entities, string $viewMode, string $langcode = NULL, AccountInterface $account = NULL): array {
foreach ($entities as &$entity) {
$entity = $this->entityRepository->getTranslationFromContext($entity, $langcode);
}
return $this->buildEntityContent($entities, $viewMode, $account);
}
/**
* Generates custom elements from entities.
*
* @param \Drupal\Core\Entity\ContentEntityInterface[] $entities
* Entities to process.
* @param string $viewMode
* View mode used for rendering field values into slots.
* @param \Drupal\Core\Session\AccountInterface|null $account
* (optional) The user for which to check access, or NULL to check access
* for the current user.
*
* @return \Drupal\custom_elements\CustomElement[]
* Custom elements containing entities' properties as attributes and slots,
* keyed by the same value as the corresponding entities.
*/
public function buildEntityContent(array $entities, string $viewMode, AccountInterface $account = NULL): array {
// Process custom elements by bundle, because most CE displays require
// components to be prepared by bundle. Retain original order of entities
// in the return value.
$custom_elements = [];
foreach ($entities as $key => $entity) {
$entities_by_type_bundle_key[$entity->getEntityTypeId()][$entity->bundle()][$key] = $entity;
$custom_elements[$key] = $this->getEntityDefaults($entity, $viewMode);
}
foreach ($entities_by_type_bundle_key as $entity_type_id => $entities_by_bundle_key) {
foreach ($entities_by_bundle_key as $bundle => $entities) {
$ce_display = $this->getEntityCeDisplay($entity_type_id, $bundle, $viewMode);
$ce_display->setOriginalMode($viewMode);
if ($entity_view_display = $this->checkLayoutBuilderDisplay($ce_display, current($entities))) {
// Skip processing of display components and let layout builder
// render everything.
foreach ($entities as $key => $entity) {
$custom_elements[$key]->addCacheableDependency($ce_display);
$this->buildLayoutBuilderContent($entity, $custom_elements[$key], $entity_view_display);
}
}
else {
$ce_name = $ce_display->getCustomElementName();
if ($ce_display->getForceAutoProcessing()) {
// Only do auto-processing on entity-level; skip processing of
// display components. This was default behaviour in 2.x.
foreach ($entities as $key => $entity) {
$custom_elements[$key]->addCacheableDependency($ce_display);
$custom_elements[$key]->setTag($ce_name);
$this->process($entity, $custom_elements[$key], $viewMode);
}
}
else {
// Build entity components, one by one, for this bundle's entities.
foreach ($entities as $key => $entity) {
$custom_elements[$key]->addCacheableDependency($ce_display);
$custom_elements[$key]->setTag($ce_name);
}
foreach ($ce_display->getComponents() as $component_name => $display_component) {
if ($formatter = $ce_display->getRenderer($component_name)) {
$grouped_items = [];
$field_name = $display_component['field_name'];
foreach ($entities as $key => $entity) {
if ($this->fieldIsAccessible($entity, $field_name, $custom_elements[$key], $account)) {
$items = $entity->get($field_name);
$items->filterEmptyItems();
$grouped_items[$key] = $items;
}
}
if ($grouped_items) {
$formatter->prepareBuild($grouped_items);
foreach ($grouped_items as $key => $items) {
$formatter->build($items, $custom_elements[$key]);
}
}
}
}
}
}
foreach ($entities as $key => $entity) {
$this->moduleHandler->alter('custom_element_entity', $custom_elements[$key], $entity, $viewMode);
}
}
}
return $custom_elements;
}
/**
@@ -205,18 +319,21 @@ class CustomElementGenerator {
}
/**
* Builds an entity's content as custom element.
*
* @param \Drupal\Core\Entity\ContentEntityInterface $entity
* The entity.
* @param \Drupal\custom_elements\CustomElement $element
* The custom element to add to.
* @param string $viewMode
* The current view mode.
* Checks if both CE and Core display enable Layout Builder;.
*/
public function buildEntityContent(ContentEntityInterface $entity, CustomElement $element, $viewMode) {
$entity_ce_display = $this->getEntityCeDisplay($entity->getEntityTypeId(), $entity->bundle(), $viewMode);
$this->buildCeDisplay($entity, $element, $entity_ce_display, $viewMode);
private function checkLayoutBuilderDisplay(EntityCeDisplayInterface $ceDisplay, ContentEntityInterface $entity): ?CustomElementsLayoutBuilderEntityViewDisplay {
if ($ceDisplay->getUseLayoutBuilder()) {
// 'Use layout builder' must also be enabled on the corresponding core
// display (for view mode or default).
$entity_view_displays = EntityViewDisplay::collectRenderDisplays([$entity], $ceDisplay->getOriginalMode());
$entity_view_display = $entity_view_displays[$entity->bundle()];
if ($entity_view_display->getThirdPartySetting('layout_builder', 'enabled')) {
assert($entity_view_display instanceof CustomElementsLayoutBuilderEntityViewDisplay);
return $entity_view_display;
}
}
return NULL;
}
/**
@@ -256,63 +373,6 @@ class CustomElementGenerator {
$custom_element->addCacheableDependency($display);
}
/**
* Builds an entity's content as custom element using a CE display.
*
* Not accessible or empty fields are not built.
*
* @param \Drupal\Core\Entity\ContentEntityInterface $entity
* The entity.
* @param \Drupal\custom_elements\CustomElement $custom_element
* The custom element.
* @param \Drupal\custom_elements\Entity\EntityCeDisplayInterface $display
* Entity custom element display entity.
* @param string $viewMode
* The view mode being built.
* @param \Drupal\Core\Session\AccountInterface|null $account
* (optional) The user for which to check access, or NULL to check access
* for the current user. Defaults to NULL.
*/
public function buildCeDisplay(ContentEntityInterface $entity, CustomElement $custom_element, EntityCeDisplayInterface $display, string $viewMode, AccountInterface $account = NULL) {
$custom_element->addCacheableDependency($display);
// If 'use layout builder' is enabled, and if it's enabled on the
// corresponding core display (for view mode or default), skip processing
// of the fields in the CE display, and let layout builder render it all.
if ($display->getUseLayoutBuilder()) {
$entity_view_displays = EntityViewDisplay::collectRenderDisplays([$entity], $viewMode);
$entity_view_display = reset($entity_view_displays);
if ($entity_view_display->getThirdPartySetting('layout_builder', 'enabled')) {
assert($entity_view_display instanceof CustomElementsLayoutBuilderEntityViewDisplay);
$this->buildLayoutBuilderContent($entity, $custom_element, $entity_view_display);
return;
}
}
$display->setOriginalMode($viewMode);
$custom_element->setTag($display->getCustomElementName());
// When configured, only do auto-processing on entity-level and skip the
// config of individual components. This is the same behaviour as it was
// default in 2.x.
if ($display->getForceAutoProcessing()) {
$this->process($entity, $custom_element, $viewMode);
return;
}
// Else render using the individual display components.
foreach ($display->getComponents() as $component_name => $display_component) {
if ($formatter = $display->getRenderer($component_name)) {
$field_name = $display_component['field_name'];
if ($this->fieldIsAccessible($entity, $field_name, $custom_element, $account)) {
// @todo Move prepareBuild to prepareView phase.
$formatter->prepareBuild([$entity->get($field_name)]);
$formatter->build($entity->get($field_name), $custom_element);
}
}
}
}
/**
* Gets a Custom Elements display for the entity type, bundle and view mode.
*
Loading