Commit 3ffcebce authored by alexpott's avatar alexpott

Issue #2073661 by amateescu, claudiu.cristea, plopesc, xjm | yched: Add a...

Issue #2073661 by amateescu, claudiu.cristea, plopesc, xjm | yched: Add a EntityReferenceField::referencedEntities() method.
parent 00ec50f0
<?php
/**
* @file
* Contains \Drupal\Core\Field\EntityReferenceFieldItemList.
*/
namespace Drupal\Core\Field;
/**
* Defines a item list class for entity reference fields.
*/
class EntityReferenceFieldItemList extends FieldItemList implements EntityReferenceFieldItemListInterface {
/**
* {@inheritdoc}
*/
public function referencedEntities() {
if (empty($this->list)) {
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];
}
}
return $target_entities;
}
}
<?php
/**
* @file
* Contains \Drupal\Core\Field\EntityReferenceFieldItemListInterface.
*/
namespace Drupal\Core\Field;
/**
* Interface for entity reference lists of field items.
*/
interface EntityReferenceFieldItemListInterface extends FieldItemListInterface {
/**
* Gets the entities referenced by this field, preserving field item deltas.
*
* @return \Drupal\Core\Entity\EntityInterface[]
* An array of entity objects keyed by field item deltas.
*/
public function referencedEntities();
}
......@@ -28,6 +28,7 @@
* label = @Translation("Entity reference"),
* description = @Translation("An entity field containing an entity reference."),
* no_ui = TRUE,
* list_class = "\Drupal\Core\Field\EntityReferenceFieldItemList",
* constraints = {"ValidReference" = {}}
* )
*/
......
......@@ -7,12 +7,12 @@
namespace Drupal\entity_reference\Plugin\Field\FieldType;
use Drupal\Core\Field\FieldItemList;
use Drupal\Core\Field\EntityReferenceFieldItemList;
/**
* Represents a configurable entity_reference entity field.
*/
class ConfigurableEntityReferenceFieldItemList extends FieldItemList {
class ConfigurableEntityReferenceFieldItemList extends EntityReferenceFieldItemList {
/**
* {@inheritdoc}
......
......@@ -10,6 +10,7 @@
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldInstanceConfig;
use Drupal\system\Tests\Entity\EntityUnitTestBase;
use Drupal\Core\Field\FieldDefinitionInterface;
/**
* Tests for the entity reference field.
......@@ -86,7 +87,8 @@ public function setUp() {
'Field test',
$this->referencedEntityType,
'default',
array('target_bundles' => array($this->bundle))
array('target_bundles' => array($this->bundle)),
FieldDefinitionInterface::CARDINALITY_UNLIMITED
);
$this->field = FieldConfig::loadByName($this->entityType, $this->fieldName);
......@@ -116,4 +118,57 @@ public function testEntityReferenceFieldValidation() {
// https://drupal.org/node/2064191 is fixed
}
/**
* Tests the multiple target entities loader.
*/
public function testReferencedEntitiesMultipleLoad() {
// Create the parent entity.
$entity = entity_create($this->entityType, array('type' => $this->bundle));
// Create three target entities and attach them to parent field.
$target_entities = array();
$reference_field = array();
for ($i = 0; $i < 3; $i++) {
$target_entity = entity_create($this->referencedEntityType, array('type' => $this->bundle));
$target_entity->save();
$target_entities[] = $target_entity;
$reference_field[]['target_id'] = $target_entity->id();
}
// Also attach a non-existent entity and a NULL target id.
$reference_field[3]['target_id'] = 99999;
$target_entities[3] = NULL;
$reference_field[4]['target_id'] = NULL;
$target_entities[4] = NULL;
// Attach the first created target entity as the sixth item ($delta == 5) of
// the parent entity field. We want to test the case when the same target
// entity is referenced twice (or more times) in the same entity reference
// field.
$reference_field[5] = $reference_field[0];
$target_entities[5] = $target_entities[0];
// Set the field value.
$entity->{$this->fieldName}->setValue($reference_field);
// Load the target entities using EntityReferenceField::referencedEntities().
$entities = $entity->{$this->fieldName}->referencedEntities();
// Test returned entities:
// - Deltas must be preserved.
// - 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());
}
else {
// A non-existent or NULL entity target id must not return any item in
// the target entities set.
$this->assertFalse(isset($loaded_entities[$delta]));
}
}
}
}
......@@ -7,12 +7,12 @@
namespace Drupal\file\Plugin\Field\FieldType;
use Drupal\Core\Field\FieldItemList;
use Drupal\Core\Field\EntityReferenceFieldItemList;
/**
* Represents a configurable entity file field.
*/
class FileFieldItemList extends FieldItemList {
class FileFieldItemList extends EntityReferenceFieldItemList {
/**
* {@inheritdoc}
......@@ -27,7 +27,7 @@ public function insert() {
$entity = $this->getEntity();
// Add a new usage for newly uploaded files.
foreach ($this->targetEntities() as $file) {
foreach ($this->referencedEntities() as $file) {
\Drupal::service('file.usage')->add($file, 'file', $entity->getEntityTypeId(), $entity->id());
}
}
......@@ -40,8 +40,12 @@ public function update() {
$entity = $this->getEntity();
// Get current target file entities and file IDs.
$files = $this->targetEntities();
$fids = array_keys($files);
$files = $this->referencedEntities();
$fids = array();
foreach ($files as $file) {
$fids[] = $file->id();
}
// On new revisions, all files are considered to be a new usage and no
// deletion of previous file usages are necessary.
......@@ -68,8 +72,8 @@ public function update() {
}
// Add new usage entries for newly added files.
foreach ($files as $fid => $file) {
if (!in_array($fid, $original_fids)) {
foreach ($files as $file) {
if (!in_array($file->id(), $original_fids)) {
\Drupal::service('file.usage')->add($file, 'file', $entity->getEntityTypeId(), $entity->id());
}
}
......@@ -83,7 +87,7 @@ public function delete() {
$entity = $this->getEntity();
// Delete all file usages within this entity.
foreach ($this->targetEntities() as $file) {
foreach ($this->referencedEntities() as $file) {
\Drupal::service('file.usage')->delete($file, 'file', $entity->getEntityTypeId(), $entity->id(), 0);
}
}
......@@ -96,31 +100,9 @@ public function deleteRevision() {
$entity = $this->getEntity();
// Decrement the file usage by 1.
foreach ($this->targetEntities() as $file) {
foreach ($this->referencedEntities() as $file) {
\Drupal::service('file.usage')->delete($file, 'file', $entity->getEntityTypeId(), $entity->id());
}
}
/**
* Collects target file entities for this field.
*
* @return array
* An array with the list of target file entities keyed by file ID.
*
* @todo Drop this when https://drupal.org/node/2073661 lands.
*/
protected function targetEntities() {
if (!isset($this->list)) {
return array();
}
$ids = array();
foreach ($this->list as $item) {
$ids[] = $item->target_id;
}
// Prevent NULLs as target IDs.
$ids = array_filter($ids);
return $ids ? \Drupal::entityManager()->getStorage('file')->loadMultiple($ids) : array();
}
}
......@@ -21,20 +21,15 @@ abstract class TaxonomyFormatterBase extends FormatterBase {
* unsets values for invalid terms that do not exist.
*/
public function prepareView(array $entities_items) {
$tids = array();
$terms = array();
// Collect every possible term attached to any of the fieldable entities.
foreach ($entities_items as $items) {
foreach ($items as $item) {
// Force the array key to prevent duplicates.
if ($item->target_id != NULL) {
$tids[$item->target_id] = $item->target_id;
}
foreach ($items->referencedEntities() as $term) {
$terms[$term->id()] = $term;
}
}
if ($tids) {
$terms = entity_load_multiple('taxonomy_term', $tids);
if ($terms) {
// Iterate through the fieldable entities again to attach the loaded term
// data.
foreach ($entities_items as $items) {
......
......@@ -7,12 +7,12 @@
namespace Drupal\taxonomy\Plugin\Field\FieldType;
use Drupal\Core\Field\FieldItemList;
use Drupal\Core\Field\EntityReferenceFieldItemList;
/**
* Represents a configurable taxonomy_term_reference entity field item list.
*/
class TaxonomyTermReferenceFieldItemList extends FieldItemList {
class TaxonomyTermReferenceFieldItemList extends EntityReferenceFieldItemList {
/**
* {@inheritdoc}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment