Issue #2370703 by amateescu, yched: Fixed ER's "autocreate" feature is mostly broken (and untested).
parent
b733559eb7
commit
c18ba6aad5
|
@ -23,27 +23,29 @@ class EntityReferenceFieldItemList extends FieldItemList implements EntityRefere
|
|||
return array();
|
||||
}
|
||||
|
||||
// Get a list of items having non-empty target ids.
|
||||
$list = array_filter($this->list, function($item) {
|
||||
return (bool) $item->target_id;
|
||||
});
|
||||
|
||||
$ids = array();
|
||||
foreach ($list as $delta => $item) {
|
||||
$ids[$delta] = $item->target_id;
|
||||
}
|
||||
if (empty($ids)) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$target_type = $this->getFieldDefinition()->getSetting('target_type');
|
||||
$entities = \Drupal::entityManager()->getStorage($target_type)->loadMultiple($ids);
|
||||
|
||||
$target_entities = array();
|
||||
foreach ($ids as $delta => $target_id) {
|
||||
if (isset($entities[$target_id])) {
|
||||
$target_entities[$delta] = $entities[$target_id];
|
||||
// Collect the IDs of existing entities to load, and directly grab the
|
||||
// "autocreate" entities that are already populated in $item->entity.
|
||||
$target_entities = $ids = array();
|
||||
foreach ($this->list as $delta => $item) {
|
||||
if ($item->target_id !== NULL) {
|
||||
$ids[$delta] = $item->target_id;
|
||||
}
|
||||
elseif ($item->hasNewEntity()) {
|
||||
$target_entities[$delta] = $item->entity;
|
||||
}
|
||||
}
|
||||
|
||||
// Load and add the existing entities.
|
||||
if ($ids) {
|
||||
$target_type = $this->getFieldDefinition()->getSetting('target_type');
|
||||
$entities = \Drupal::entityManager()->getStorage($target_type)->loadMultiple($ids);
|
||||
foreach ($ids as $delta => $target_id) {
|
||||
if (isset($entities[$target_id])) {
|
||||
$target_entities[$delta] = $entities[$target_id];
|
||||
}
|
||||
}
|
||||
// Ensure the returned array is ordered by deltas.
|
||||
ksort($target_entities);
|
||||
}
|
||||
|
||||
return $target_entities;
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
namespace Drupal\Core\Field\Plugin\Field\FieldType;
|
||||
|
||||
use Drupal\Core\Config\Entity\ConfigEntityType;
|
||||
use Drupal\Core\Entity\Entity;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\Entity\TypedData\EntityDataDefinition;
|
||||
use Drupal\Core\Field\FieldDefinitionInterface;
|
||||
|
@ -166,7 +166,7 @@ class EntityReferenceItem extends FieldItemBase {
|
|||
|
||||
// If there is an unsaved entity, return it as part of the field item values
|
||||
// to ensure idempotency of getValue() / setValue().
|
||||
if ($this->hasUnsavedEntity()) {
|
||||
if ($this->hasNewEntity()) {
|
||||
$values['entity'] = $this->entity;
|
||||
}
|
||||
return $values;
|
||||
|
@ -191,11 +191,10 @@ class EntityReferenceItem extends FieldItemBase {
|
|||
*/
|
||||
public function isEmpty() {
|
||||
// Avoid loading the entity by first checking the 'target_id'.
|
||||
$target_id = $this->target_id;
|
||||
if ($target_id !== NULL) {
|
||||
if ($this->target_id !== NULL) {
|
||||
return FALSE;
|
||||
}
|
||||
if ($this->entity && $this->entity instanceof Entity) {
|
||||
if ($this->entity && $this->entity instanceof EntityInterface) {
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
|
@ -205,12 +204,12 @@ class EntityReferenceItem extends FieldItemBase {
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function preSave() {
|
||||
if ($this->hasUnsavedEntity()) {
|
||||
if ($this->hasNewEntity()) {
|
||||
$this->entity->save();
|
||||
}
|
||||
// Handle the case where an unsaved entity was directly set using the public
|
||||
// 'entity' property and then saved before this entity. In this case
|
||||
// ::hasUnsavedEntity() will return FALSE but $this->target_id will still be
|
||||
// ::hasNewEntity() will return FALSE but $this->target_id will still be
|
||||
// empty.
|
||||
if (empty($this->target_id) && $this->entity) {
|
||||
$this->target_id = $this->entity->id();
|
||||
|
@ -239,7 +238,7 @@ class EntityReferenceItem extends FieldItemBase {
|
|||
* @return bool
|
||||
* TRUE if the item holds an unsaved entity.
|
||||
*/
|
||||
public function hasUnsavedEntity() {
|
||||
public function hasNewEntity() {
|
||||
return $this->target_id === NULL && ($entity = $this->entity) && $entity->isNew();
|
||||
}
|
||||
|
||||
|
|
|
@ -30,6 +30,14 @@ abstract class EntityReferenceFormatterBase extends FormatterBase {
|
|||
|
||||
$parent_entity_langcode = $items->getEntity()->language()->getId();
|
||||
foreach ($items as $delta => $item) {
|
||||
// The "originalEntity" property is assigned in self::prepareView() and
|
||||
// its absence means that the referenced entity was neither found in the
|
||||
// persistent storage nor is it a new entity (e.g. from "autocreate").
|
||||
if (!isset($item->originalEntity)) {
|
||||
$item->access = FALSE;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($item->originalEntity instanceof TranslatableInterface && $item->originalEntity->hasTranslation($parent_entity_langcode)) {
|
||||
$entity = $item->originalEntity->getTranslation($parent_entity_langcode);
|
||||
}
|
||||
|
@ -51,47 +59,38 @@ abstract class EntityReferenceFormatterBase extends FormatterBase {
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* Mark the accessible IDs a user can see. We do not unset unaccessible
|
||||
* values, as other may want to act on those values, even if they can
|
||||
* not be accessed.
|
||||
* Loads the entities referenced in that field across all the entities being
|
||||
* viewed, and places them in a custom item property for getEntitiesToView().
|
||||
*/
|
||||
public function prepareView(array $entities_items) {
|
||||
$target_ids = array();
|
||||
|
||||
// Collect every possible entity attached to any of the entities.
|
||||
// Load the existing (non-autocreate) entities. For performance, we want to
|
||||
// use a single "multiple entity load" to load all the entities for the
|
||||
// multiple "entity reference item lists" that are being displayed. We thus
|
||||
// cannot use
|
||||
// \Drupal\Core\Field\EntityReferenceFieldItemList::referencedEntities().
|
||||
$ids = array();
|
||||
foreach ($entities_items as $items) {
|
||||
foreach ($items as $item) {
|
||||
if (!empty($item->target_id)) {
|
||||
$target_ids[] = $item->target_id;
|
||||
if ($item->target_id !== NULL) {
|
||||
$ids[] = $item->target_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$target_type = $this->getFieldSetting('target_type');
|
||||
|
||||
$target_entities = array();
|
||||
|
||||
if ($target_ids) {
|
||||
$target_entities = entity_load_multiple($target_type, $target_ids);
|
||||
if ($ids) {
|
||||
$target_type = $this->getFieldSetting('target_type');
|
||||
$target_entities = \Drupal::entityManager()->getStorage($target_type)->loadMultiple($ids);
|
||||
}
|
||||
|
||||
// Iterate through the fieldable entities again to attach the loaded data.
|
||||
// For each item, place the referenced entity where getEntitiesToView()
|
||||
// reads it.
|
||||
foreach ($entities_items as $items) {
|
||||
$rekey = FALSE;
|
||||
foreach ($items as $item) {
|
||||
if ($item->target_id !== 0 && !isset($target_entities[$item->target_id])) {
|
||||
// The entity no longer exists, so empty the item.
|
||||
$item->setValue(NULL);
|
||||
$rekey = TRUE;
|
||||
continue;
|
||||
if (isset($target_entities[$item->target_id])) {
|
||||
$item->originalEntity = $target_entities[$item->target_id];
|
||||
}
|
||||
elseif ($item->hasNewEntity()) {
|
||||
$item->originalEntity = $item->entity;
|
||||
}
|
||||
|
||||
$item->originalEntity = $target_entities[$item->target_id];
|
||||
}
|
||||
|
||||
// Re-key the items array if needed.
|
||||
if ($rekey) {
|
||||
$items->filterEmptyItems();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -66,7 +66,7 @@ class EntityReferenceLabelFormatter extends EntityReferenceFormatterBase {
|
|||
$label = $entity->label();
|
||||
// If the link is to be displayed and the entity has a uri, display a
|
||||
// link.
|
||||
if ($this->getSetting('link') && $uri = $entity->urlInfo()) {
|
||||
if ($this->getSetting('link') && !$entity->isNew() && $uri = $entity->urlInfo()) {
|
||||
$elements[$delta] = [
|
||||
'#type' => 'link',
|
||||
'#title' => $label,
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
|
||||
namespace Drupal\entity_reference\Plugin\Field\FieldWidget;
|
||||
|
||||
use Drupal\Core\Field\FieldItemListInterface;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
|
||||
/**
|
||||
|
@ -43,18 +42,6 @@ class AutocompleteWidget extends AutocompleteWidgetBase {
|
|||
) + parent::defaultSettings();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getEntityIds(FieldItemListInterface $items, $delta) {
|
||||
// The autocomplete widget outputs one entity label per form element.
|
||||
if (isset($items[$delta])) {
|
||||
return array($items[$delta]->target_id);
|
||||
}
|
||||
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
namespace Drupal\entity_reference\Plugin\Field\FieldWidget;
|
||||
|
||||
use Drupal\Component\Utility\Tags;
|
||||
use Drupal\Core\Field\EntityReferenceFieldItemListInterface;
|
||||
use Drupal\Core\Field\FieldItemListInterface;
|
||||
use Drupal\Core\Field\WidgetBase;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
|
@ -116,47 +117,32 @@ abstract class AutocompleteWidgetBase extends WidgetBase {
|
|||
/**
|
||||
* Gets the entity labels.
|
||||
*/
|
||||
protected function getLabels(FieldItemListInterface $items, $delta) {
|
||||
protected function getLabels(EntityReferenceFieldItemListInterface $items, $delta) {
|
||||
if ($items->isEmpty()) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$entity_labels = array();
|
||||
$handles_multiple_values = $this->handlesMultipleValues();
|
||||
foreach ($items->referencedEntities() as $referenced_delta => $referenced_entity) {
|
||||
// The autocomplete widget outputs one entity label per form element.
|
||||
if (!$handles_multiple_values && $referenced_delta != $delta) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Load those entities and loop through them to extract their labels.
|
||||
$entities = entity_load_multiple($this->getFieldSetting('target_type'), $this->getEntityIds($items, $delta));
|
||||
$key = $referenced_entity->label();
|
||||
|
||||
// Take into account "autocreate" items.
|
||||
if (!$referenced_entity->isNew()) {
|
||||
$key .= ' (' . $referenced_entity->id() . ')';
|
||||
}
|
||||
|
||||
foreach ($entities as $entity_id => $entity_item) {
|
||||
$label = $entity_item->label();
|
||||
$key = "$label ($entity_id)";
|
||||
// Labels containing commas or quotes must be wrapped in quotes.
|
||||
$key = Tags::encode($key);
|
||||
$entity_labels[] = $key;
|
||||
$entity_labels[] = Tags::encode($key);
|
||||
}
|
||||
return $entity_labels;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds an array of entity IDs for which to get the entity labels.
|
||||
*
|
||||
* @param \Drupal\Core\Field\FieldItemListInterface $items
|
||||
* Array of default values for this field.
|
||||
* @param int $delta
|
||||
* The order of a field item in the array of subelements (0, 1, 2, etc).
|
||||
*
|
||||
* @return array
|
||||
* An array of entity IDs.
|
||||
*/
|
||||
protected function getEntityIds(FieldItemListInterface $items, $delta) {
|
||||
$entity_ids = array();
|
||||
|
||||
foreach ($items as $item) {
|
||||
$entity_ids[] = $item->target_id;
|
||||
}
|
||||
|
||||
return $entity_ids;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new entity from a label entered in the autocomplete input.
|
||||
*
|
||||
|
|
|
@ -127,6 +127,12 @@ class EntityReferenceFieldTest extends EntityUnitTestBase {
|
|||
$reference_field[5] = $reference_field[0];
|
||||
$target_entities[5] = $target_entities[0];
|
||||
|
||||
// Create a new target entity that is not saved, thus testing the
|
||||
// "autocreate" feature.
|
||||
$target_entity_unsaved = entity_create($this->referencedEntityType, array('type' => $this->bundle, 'name' => $this->randomString()));
|
||||
$reference_field[6]['entity'] = $target_entity_unsaved;
|
||||
$target_entities[6] = $target_entity_unsaved;
|
||||
|
||||
// Set the field value.
|
||||
$entity->{$this->fieldName}->setValue($reference_field);
|
||||
|
||||
|
@ -138,9 +144,16 @@ class EntityReferenceFieldTest extends EntityUnitTestBase {
|
|||
// - Non-existent entities must not be retrieved in target entities result.
|
||||
foreach ($target_entities as $delta => $target_entity) {
|
||||
if (!empty($target_entity)) {
|
||||
// There must be an entity in the loaded set having the same id for the
|
||||
// same delta.
|
||||
$this->assertEqual($target_entity->id(), $entities[$delta]->id());
|
||||
if (!$target_entity->isNew()) {
|
||||
// There must be an entity in the loaded set having the same id for
|
||||
// the same delta.
|
||||
$this->assertEqual($target_entity->id(), $entities[$delta]->id());
|
||||
}
|
||||
else {
|
||||
// For entities that were not yet saved, there must an entity in the
|
||||
// loaded set having the same label for the same delta.
|
||||
$this->assertEqual($target_entity->label(), $entities[$delta]->label());
|
||||
}
|
||||
}
|
||||
else {
|
||||
// A non-existent or NULL entity target id must not return any item in
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
namespace Drupal\entity_reference\Tests;
|
||||
|
||||
use Drupal\Core\Cache\Cache;
|
||||
use Drupal\Core\Field\FieldStorageDefinitionInterface;
|
||||
use Drupal\filter\Entity\FilterFormat;
|
||||
use Drupal\system\Tests\Entity\EntityUnitTestBase;
|
||||
|
||||
|
@ -44,7 +45,15 @@ class EntityReferenceFormatterTest extends EntityUnitTestBase {
|
|||
*
|
||||
* @var \Drupal\Core\Entity\EntityInterface
|
||||
*/
|
||||
protected $referencedEntity = NULL;
|
||||
protected $referencedEntity;
|
||||
|
||||
/**
|
||||
* The entity that is not yet saved to its persistent storage to be referenced
|
||||
* in this test.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityInterface
|
||||
*/
|
||||
protected $unsavedReferencedEntity;
|
||||
|
||||
/**
|
||||
* Modules to install.
|
||||
|
@ -56,7 +65,11 @@ class EntityReferenceFormatterTest extends EntityUnitTestBase {
|
|||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
entity_reference_create_field($this->entityType, $this->bundle, $this->fieldName, 'Field test', $this->entityType);
|
||||
// The label formatter rendering generates links, so build the router.
|
||||
$this->installSchema('system', 'router');
|
||||
$this->container->get('router.builder')->rebuild();
|
||||
|
||||
entity_reference_create_field($this->entityType, $this->bundle, $this->fieldName, 'Field test', $this->entityType, 'default', array(), FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED);
|
||||
|
||||
// Set up a field, so that the entity that'll be referenced bubbles up a
|
||||
// cache tag when rendering it entirely.
|
||||
|
@ -91,6 +104,13 @@ class EntityReferenceFormatterTest extends EntityUnitTestBase {
|
|||
'format' => 'full_html',
|
||||
);
|
||||
$this->referencedEntity->save();
|
||||
|
||||
// Create another entity to be referenced but do not save it.
|
||||
$this->unsavedReferencedEntity = entity_create($this->entityType, array('name' => $this->randomMachineName()));
|
||||
$this->unsavedReferencedEntity->body = array(
|
||||
'value' => '<p>Hello, unsaved world!</p>',
|
||||
'format' => 'full_html',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -130,21 +150,11 @@ class EntityReferenceFormatterTest extends EntityUnitTestBase {
|
|||
*/
|
||||
public function testIdFormatter() {
|
||||
$formatter = 'entity_reference_entity_id';
|
||||
$field_name = $this->fieldName;
|
||||
|
||||
// Create the entity that will have the entity reference field.
|
||||
$referencing_entity = entity_create($this->entityType, array('name' => $this->randomMachineName()));
|
||||
$referencing_entity->save();
|
||||
$referencing_entity->{$field_name}->entity = $this->referencedEntity;
|
||||
$referencing_entity->{$field_name}->access = TRUE;
|
||||
|
||||
// Build the renderable array for the entity reference field.
|
||||
$items = $referencing_entity->get($field_name);
|
||||
$build = $items->view(array('type' => $formatter));
|
||||
|
||||
$this->assertEqual($build[0]['#markup'], $this->referencedEntity->id(), format_string('The markup returned by the @formatter formatter is correct.', array('@formatter' => $formatter)));
|
||||
$this->assertEqual($build[0]['#cache']['tags'], $this->referencedEntity->getCacheTags(), format_string('The @formatter formatter has the expected cache tags.', array('@formatter' => $formatter)));
|
||||
$build = $this->buildRenderArray([$this->referencedEntity, $this->unsavedReferencedEntity], $formatter);
|
||||
|
||||
$this->assertEqual($build[0]['#markup'], $this->referencedEntity->id(), sprintf('The markup returned by the %s formatter is correct for an item with a saved entity.', $formatter));
|
||||
$this->assertEqual($build[0]['#cache']['tags'], $this->referencedEntity->getCacheTags(), sprintf('The %s formatter has the expected cache tags.', $formatter));
|
||||
$this->assertTrue(!isset($build[1]), sprintf('The markup returned by the %s formatter is correct for an item with a unsaved entity.', $formatter));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -152,25 +162,16 @@ class EntityReferenceFormatterTest extends EntityUnitTestBase {
|
|||
*/
|
||||
public function testEntityFormatter() {
|
||||
$formatter = 'entity_reference_entity_view';
|
||||
$field_name = $this->fieldName;
|
||||
$build = $this->buildRenderArray([$this->referencedEntity, $this->unsavedReferencedEntity], $formatter);
|
||||
|
||||
// Create the entity that will have the entity reference field.
|
||||
$referencing_entity = entity_create($this->entityType, array('name' => $this->randomMachineName()));
|
||||
$referencing_entity->save();
|
||||
$referencing_entity->{$field_name}->entity = $this->referencedEntity;
|
||||
$referencing_entity->{$field_name}->access = TRUE;
|
||||
|
||||
// Build the renderable array for the entity reference field.
|
||||
$items = $referencing_entity->get($field_name);
|
||||
$build = $items->view(array('type' => $formatter));
|
||||
|
||||
$expected_rendered_name_field = '<div class="field field-entity-test--name field-name-name field-type-string field-label-hidden">
|
||||
// Test the first field item.
|
||||
$expected_rendered_name_field_1 = '<div class="field field-entity-test--name field-name-name field-type-string field-label-hidden">
|
||||
<div class="field-items">
|
||||
<div class="field-item">' . $this->referencedEntity->label() . '</div>
|
||||
</div>
|
||||
</div>
|
||||
';
|
||||
$expected_rendered_body_field = '<div class="field field-entity-test--body field-name-body field-type-text field-label-above">
|
||||
$expected_rendered_body_field_1 = '<div class="field field-entity-test--body field-name-body field-type-text field-label-above">
|
||||
<div class="field-label">Body</div>
|
||||
<div class="field-items">
|
||||
<div class="field-item"><p>Hello, world!</p></div>
|
||||
|
@ -178,13 +179,84 @@ class EntityReferenceFormatterTest extends EntityUnitTestBase {
|
|||
</div>
|
||||
';
|
||||
drupal_render($build[0]);
|
||||
$this->assertEqual($build[0]['#markup'], 'default | ' . $this->referencedEntity->label() . $expected_rendered_name_field . $expected_rendered_body_field, format_string('The markup returned by the @formatter formatter is correct.', array('@formatter' => $formatter)));
|
||||
$this->assertEqual($build[0]['#markup'], 'default | ' . $this->referencedEntity->label() . $expected_rendered_name_field_1 . $expected_rendered_body_field_1, sprintf('The markup returned by the %s formatter is correct for an item with a saved entity.', $formatter));
|
||||
$expected_cache_tags = Cache::mergeTags(
|
||||
\Drupal::entityManager()->getViewBuilder($this->entityType)->getCacheTags(),
|
||||
$this->referencedEntity->getCacheTags(),
|
||||
FilterFormat::load('full_html')->getCacheTags()
|
||||
);
|
||||
$this->assertEqual($build[0]['#cache']['tags'], $expected_cache_tags, format_string('The @formatter formatter has the expected cache tags.', array('@formatter' => $formatter)));
|
||||
|
||||
// Test the second field item.
|
||||
drupal_render($build[1]);
|
||||
$this->assertEqual($build[1]['#markup'], $this->unsavedReferencedEntity->label(), sprintf('The markup returned by the %s formatter is correct for an item with a unsaved entity.', $formatter));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the label formatter.
|
||||
*/
|
||||
public function testLabelFormatter() {
|
||||
$formatter = 'entity_reference_label';
|
||||
|
||||
// The 'link' settings is TRUE by default.
|
||||
$build = $this->buildRenderArray([$this->referencedEntity, $this->unsavedReferencedEntity], $formatter);
|
||||
|
||||
$expected_item_1 = array(
|
||||
'#type' => 'link',
|
||||
'#title' => $this->referencedEntity->label(),
|
||||
'#url' => $this->referencedEntity->urlInfo(),
|
||||
'#options' => $this->referencedEntity->urlInfo()->getOptions(),
|
||||
'#cache' => array(
|
||||
'tags' => $this->referencedEntity->getCacheTags(),
|
||||
),
|
||||
);
|
||||
$this->assertEqual(drupal_render($build[0]), drupal_render($expected_item_1), sprintf('The markup returned by the %s formatter is correct for an item with a saved entity.', $formatter));
|
||||
|
||||
// The second referenced entity is "autocreated", therefore not saved and
|
||||
// lacking any URL info.
|
||||
$expected_item_2 = array(
|
||||
'#markup' => $this->unsavedReferencedEntity->label(),
|
||||
'#cache' => array(
|
||||
'tags' => $this->unsavedReferencedEntity->getCacheTags(),
|
||||
),
|
||||
);
|
||||
$this->assertEqual($build[1], $expected_item_2, sprintf('The markup returned by the %s formatter is correct for an item with a unsaved entity.', $formatter));
|
||||
|
||||
// Test with the 'link' setting set to FALSE.
|
||||
$build = $this->buildRenderArray([$this->referencedEntity, $this->unsavedReferencedEntity], $formatter, array('link' => FALSE));
|
||||
$this->assertEqual($build[0]['#markup'], $this->referencedEntity->label(), sprintf('The markup returned by the %s formatter is correct for an item with a saved entity.', $formatter));
|
||||
$this->assertEqual($build[1]['#markup'], $this->unsavedReferencedEntity->label(), sprintf('The markup returned by the %s formatter is correct for an item with a unsaved entity.', $formatter));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets field values and returns a render array as built by
|
||||
* \Drupal\Core\Field\FieldItemListInterface::view().
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityInterface[] $referenced_entities
|
||||
* An array of entity objects that will be referenced.
|
||||
* @param string $formatter
|
||||
* The formatted plugin that will be used for building the render array.
|
||||
* @param array $formatter_options
|
||||
* Settings specific to the formatter. Defaults to the formatter's default
|
||||
* settings.
|
||||
*
|
||||
* @return array
|
||||
* A render array.
|
||||
*/
|
||||
protected function buildRenderArray(array $referenced_entities, $formatter, $formatter_options = array()) {
|
||||
// Create the entity that will have the entity reference field.
|
||||
$referencing_entity = entity_create($this->entityType, array('name' => $this->randomMachineName()));
|
||||
|
||||
$delta = 0;
|
||||
foreach ($referenced_entities as $referenced_entity) {
|
||||
$referencing_entity->{$this->fieldName}[$delta]->entity = $referenced_entity;
|
||||
$referencing_entity->{$this->fieldName}[$delta++]->access = TRUE;
|
||||
}
|
||||
|
||||
// Build the renderable array for the entity reference field.
|
||||
$items = $referencing_entity->get($this->fieldName);
|
||||
|
||||
return $items->view(array('type' => $formatter, 'settings' => $formatter_options));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -85,7 +85,11 @@ class EntityReferenceIntegrationTest extends WebTestBase {
|
|||
// Try to post the form again with no modification and check if the field
|
||||
// values remain the same.
|
||||
$entity = current(entity_load_multiple_by_properties($this->entityType, array('name' => $entity_name)));
|
||||
$this->drupalPostForm($this->entityType . '/manage/' . $entity->id(), array(), t('Save'));
|
||||
$this->drupalGet($this->entityType . '/manage/' . $entity->id());
|
||||
$this->assertFieldByName($this->fieldName . '[0][target_id]', $referenced_entities[0]->label() . ' (' . $referenced_entities[0]->id() . ')');
|
||||
$this->assertFieldByName($this->fieldName . '[1][target_id]', $referenced_entities[1]->label() . ' (' . $referenced_entities[1]->id() . ')');
|
||||
|
||||
$this->drupalPostForm(NULL, array(), t('Save'));
|
||||
$this->assertFieldValues($entity_name, $referenced_entities);
|
||||
|
||||
// Test the 'entity_reference_autocomplete_tags' widget.
|
||||
|
@ -107,7 +111,10 @@ class EntityReferenceIntegrationTest extends WebTestBase {
|
|||
// Try to post the form again with no modification and check if the field
|
||||
// values remain the same.
|
||||
$entity = current(entity_load_multiple_by_properties($this->entityType, array('name' => $entity_name)));
|
||||
$this->drupalPostForm($this->entityType . '/manage/' . $entity->id(), array(), t('Save'));
|
||||
$this->drupalGet($this->entityType . '/manage/' . $entity->id());
|
||||
$this->assertFieldByName($this->fieldName . '[target_id]', $target_id . ' (' . $referenced_entities[1]->id() . ')');
|
||||
|
||||
$this->drupalPostForm(NULL, array(), t('Save'));
|
||||
$this->assertFieldValues($entity_name, $referenced_entities);
|
||||
|
||||
// Test all the other widgets supported by the entity reference field.
|
||||
|
|
|
@ -37,7 +37,9 @@ abstract class TaxonomyFormatterBase extends FormatterBase {
|
|||
$term = $translated_term;
|
||||
}
|
||||
}
|
||||
$terms[$term->id()] = $term;
|
||||
if (!$term->isNew()) {
|
||||
$terms[$term->id()] = $term;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($terms) {
|
||||
|
@ -53,7 +55,7 @@ abstract class TaxonomyFormatterBase extends FormatterBase {
|
|||
$item->entity = $terms[$item->target_id];
|
||||
}
|
||||
// Terms to be created are not in $terms, but are still legitimate.
|
||||
elseif ($item->hasUnsavedEntity()) {
|
||||
elseif ($item->hasNewEntity()) {
|
||||
// Leave the item in place.
|
||||
}
|
||||
// Otherwise, unset the instance value, since the term does not exist.
|
||||
|
|
Loading…
Reference in New Issue