Skip to content
Snippets Groups Projects

Render entity reference items in fibers.

Open catch requested to merge issue/drupal-3519387:3519387-render-entity-reference into 11.x
1 file
+ 86
46
Compare changes
  • Side-by-side
  • Inline
@@ -59,59 +59,99 @@ public function settingsSummary() {
@@ -59,59 +59,99 @@ public function settingsSummary() {
*/
*/
public function viewElements(FieldItemListInterface $items, $langcode) {
public function viewElements(FieldItemListInterface $items, $langcode) {
$elements = [];
$elements = [];
$output_as_link = $this->getSetting('link');
 
$fibers = [];
foreach ($this->getEntitiesToView($items, $langcode) as $delta => $entity) {
foreach ($this->getEntitiesToView($items, $langcode) as $delta => $entity) {
$elements[$delta] = ['#entity' => $entity];
$attributes = $items[$delta]->_attributes ?? NULL;
$label = $entity->label();
// Unset field item attributes since they will be included in the
$cacheability = CacheableMetadata::createFromObject($entity);
// formatter output and shouldn't be rendered in the field template.
// If the link is to be displayed and the entity has a uri, display a
unset($items[$delta]->_attributes);
// link.
if ($output_as_link && !$entity->isNew()) {
$fibers[$delta] = new \Fiber(function() use ($entity, $attributes) {
try {
return $this->buildEntityElement($entity, $attributes);
$uri = $entity->toUrl();
});
}
}
catch (UndefinedLinkTemplateException) {
// This exception is thrown by
$iterations = 0;
// \Drupal\Core\Entity\EntityInterface::toUrl() and it means that the
while (count($fibers) > 0) {
// entity type doesn't have a link template nor a valid
foreach ($fibers as $key => $fiber) {
// "uri_callback", so don't bother trying to output a link for the
if (!$fiber->isStarted()) {
// rest of the referenced entities.
$fiber->start();
$elements[$delta]['#plain_text'] = $label;
}
$cacheability->applyTo($elements[$delta]);
elseif ($fiber->isSuspended()) {
continue;
$fiber->resume();
}
}
// If the Fiber hasn't terminated by this point, move onto the
$uri_access = $uri->access(return_as_object: TRUE);
// next placeholder, we'll resume this Fiber again when we get
$cacheability->addCacheableDependency($uri_access);
// back here.
if ($uri_access->isAllowed()) {
if (!$fiber->isTerminated()) {
$elements[$delta] += [
// If we've gone through the placeholders once already, and
'#type' => 'link',
// they're still not finished, then start to allow code higher
'#title' => $label,
// up the stack to get on with something else.
'#url' => $uri,
if ($iterations) {
'#options' => $uri->getOptions(),
$fiber = \Fiber::getCurrent();
];
if ($fiber !== NULL) {
$fiber->suspend();
if (!empty($items[$delta]->_attributes)) {
}
$elements[$delta]['#options'] += ['attributes' => []];
}
$elements[$delta]['#options']['attributes'] += $items[$delta]->_attributes;
continue;
// Unset field item attributes since they have been included in the
}
// formatter output and shouldn't be rendered in the field template.
$elements[$key] = $fiber->getReturn();
unset($items[$delta]->_attributes);
unset($fibers[$key]);
}
}
}
}
else {
$elements[$delta]['#plain_text'] = $label;
return $elements;
}
}
 
 
/**
 
* Build the render array for a specific entity.
 
*/
 
protected function buildEntityElement(EntityInterface $entity): array {
 
$output_as_link = $this->getSetting('link');
 
$build = ['#entity' => $entity];
 
$label = $entity->label();
 
$cacheability = CacheableMetadata::createFromObject($entity);
 
// If the link is to be displayed and the entity has a uri, display a
 
// link.
 
if ($output_as_link && !$entity->isNew()) {
 
try {
 
$uri = $entity->toUrl();
}
}
else {
catch (UndefinedLinkTemplateException) {
$elements[$delta]['#plain_text'] = $label;
// This exception is thrown by
 
// \Drupal\Core\Entity\EntityInterface::toUrl() and it means that the
 
// entity type doesn't have a link template nor a valid
 
// "uri_callback", so don't bother trying to output a link for the
 
// rest of the referenced entities.
 
$build['#plain_text'] = $label;
 
$cacheability->applyTo($build);
 
return $build;
}
}
$cacheability->applyTo($elements[$delta]);
$uri_access = $uri->access(return_as_object: TRUE);
 
$cacheability->addCacheableDependency($uri_access);
 
if ($uri_access->isAllowed()) {
 
$build += [
 
'#type' => 'link',
 
'#title' => $label,
 
'#url' => $uri,
 
'#options' => $uri->getOptions(),
 
];
 
 
}
 
else {
 
$build['#plain_text'] = $label;
 
}
 
}
 
else {
 
$build['#plain_text'] = $label;
}
}
return $elements;
$cacheability->applyTo($build);
 
 
return $build;
}
}
/**
/**
Loading