Problem
EntityReferenceFormatterBase::needsEntityLoad contains a logic error.
Current implementation:
<?php
protected function needsEntityLoad(EntityReferenceItem $item) {
return !$item->hasNewEntity();
}
?>
Above implementation always returns TRUE in case the item doesn't have a new entity. This implies to return also TRUE in the following cases, but shouldn't:
- The field item already loaded its entity, i.e. no need for loading it again
- The field item is empty, i.e. doesn't have any reference to a (non-new) entity
While the first case is a performance consideration, the second case might cause faulty situations e.g. when extending EntityReferenceFormatterBase.
A plugin extending EntityReferenceFormatterBase
which appends further entities, e.g. like this (pseudocode):
<?php
class ContentTeaserFormatter extends EntityReferenceEntityFormatter {
public function prepareView(array $entities_items) {
$content = Node::load(123);
foreach ($entities_items as $items) {
$items->set($delta, $content);
parent::prepareView($entities_items);
}
}
}
}
?>
This would throw following error:
Warning: array_flip(): Can only flip STRING and INTEGER values! in Drupal\Core\Entity\EntityStorageBase->loadMultiple() (line 227 of core/lib/Drupal/Core/Entity/EntityStorageBase.php).
Drupal\Core\Entity\EntityStorageBase->loadMultiple(Array) (Line: 139)
Drupal\Core\Field\Plugin\Field\FieldFormatter\EntityReferenceFormatterBase->prepareView(Array) (Line: 189)
Proposed solution
Replace current implementation with
<?php
if (isset($item->entity) && $item->entity instanceof EntityInterface) {
$item->_loaded = TRUE;
}
else {
$item->_loaded = FALSE;
}
return isset($item->target_id) && !$item->_loaded;
?>
See also attached patch.