diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php index bb5e762..902b5c2 100644 --- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php +++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php @@ -284,9 +284,12 @@ public function hasNewEntity() { * {@inheritdoc} */ public static function calculateDependencies(FieldDefinitionInterface $field_definition) { - $dependencies = []; + $dependencies = parent::calculateDependencies($field_definition); + $manager = \Drupal::entityManager(); + $target_entity_type = $manager->getDefinition($field_definition->getFieldStorageDefinition()->getSetting('target_type')); + + // Depend on default values entity types configurations. if ($default_value = $field_definition->getDefaultValueLiteral()) { - $target_entity_type = \Drupal::entityManager()->getDefinition($field_definition->getFieldStorageDefinition()->getSetting('target_type')); foreach ($default_value as $value) { if (is_array($value) && isset($value['target_uuid'])) { $entity = \Drupal::entityManager()->loadEntityByUuid($target_entity_type->id(), $value['target_uuid']); @@ -298,6 +301,19 @@ public static function calculateDependencies(FieldDefinitionInterface $field_def } } } + + // Depend on target bundle configurations. + $handler = $field_definition->getSetting('handler_settings'); + if (!empty($handler['target_bundles'])) { + if ($bundle_entity_type_id = $target_entity_type->getBundleEntityType()) { + if ($storage = $manager->getStorage($bundle_entity_type_id)) { + foreach ($storage->loadMultiple($handler['target_bundles']) as $bundle) { + $dependencies[$bundle->getConfigDependencyKey()][] = $bundle->getConfigDependencyName(); + } + } + } + } + return $dependencies; } @@ -305,12 +321,14 @@ public static function calculateDependencies(FieldDefinitionInterface $field_def * {@inheritdoc} */ public static function onDependencyRemoval(FieldDefinitionInterface $field_definition, array $dependencies) { - $changed = FALSE; + $changed = parent::calculateDependencies($field_definition, $dependencies); + $manager = \Drupal::entityManager(); + $target_entity_type = $manager->getDefinition($field_definition->getFieldStorageDefinition()->getSetting('target_type')); + if ($default_value = $field_definition->getDefaultValueLiteral()) { - $target_entity_type = \Drupal::entityManager()->getDefinition($field_definition->getFieldStorageDefinition()->getSetting('target_type')); foreach ($default_value as $key => $value) { if (is_array($value) && isset($value['target_uuid'])) { - $entity = \Drupal::entityManager()->loadEntityByUuid($target_entity_type->id(), $value['target_uuid']); + $entity = $manager->loadEntityByUuid($target_entity_type->id(), $value['target_uuid']); // @see \Drupal\Core\Field\EntityReferenceFieldItemList::processDefaultValue() if ($entity && isset($dependencies[$entity->getConfigDependencyKey()][$entity->getConfigDependencyName()])) { unset($default_value[$key]); @@ -322,6 +340,25 @@ public static function onDependencyRemoval(FieldDefinitionInterface $field_defin $field_definition->setDefaultValue($default_value); } } + $bundles_changed = FALSE; + $handler = $field_definition->getSetting('handler_settings'); + if (!empty($handler['target_bundles'])) { + if ($bundle_entity_type_id = $target_entity_type->getBundleEntityType()) { + if ($storage = $manager->getStorage($bundle_entity_type_id)) { + foreach ($storage->loadMultiple($handler['target_bundles']) as $bundle) { + if (isset($dependencies[$bundle->getConfigDependencyKey()][$bundle->getConfigDependencyName()])) { + unset($handler['target_bundles'][$bundle->id()]); + $bundles_changed = TRUE; + } + } + } + } + } + if ($bundles_changed) { + $field_definition->setSetting('handler_settings', $handler); + } + $changed |= $bundles_changed; + return $changed; } diff --git a/core/modules/entity_reference/entity_reference.module b/core/modules/entity_reference/entity_reference.module index a07bef0..a09a53c 100644 --- a/core/modules/entity_reference/entity_reference.module +++ b/core/modules/entity_reference/entity_reference.module @@ -10,7 +10,6 @@ use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Render\Element; use Drupal\Core\Routing\RouteMatchInterface; -use Drupal\field\Entity\FieldStorageConfig; use Drupal\field\Entity\FieldConfig; use Drupal\field\FieldStorageConfigInterface; use Drupal\field\FieldConfigInterface; @@ -211,3 +210,40 @@ function entity_reference_query_entity_reference_alter(AlterableInterface $query $handler = $query->getMetadata('entity_reference_selection_handler'); $handler->entityQueryAlter($query); } + +/** + * Implements hook_entity_bundle_rename(). + * + * @todo Move this in an event subscriber once + * https://www.drupal.org/node/2553169 is in. + */ +function entity_reference_entity_bundle_rename($entity_type, $bundle_old, $bundle_new) { + $map = \Drupal::entityManager()->getFieldMapByFieldType('entity_reference'); + $ids = []; + foreach ($map as $type => $info) { + foreach ($info as $name => $data) { + foreach ($data['bundles'] as $bundle) { + $ids[] = "$type.$bundle.$name"; + } + } + } + + /** @var \Drupal\field\Entity\FieldConfig $config */ + foreach (FieldConfig::loadMultiple($ids) as $config) { + if ($config->getSetting('target_type') == $entity_type) { + $handler = $config->getSetting('handler_settings'); + $bundles = !empty($handler['target_bundles']) ? array_keys($handler['target_bundles']) : []; + foreach ($bundles as $bundle) { + if ($bundle == $bundle_old) { + $handler['target_bundles'][$bundle_new] = $bundle_new; + unset($handler['target_bundles'][$bundle_old]); + $config->setSetting('handler_settings', $handler); + $config->save(); + break; + } + } + } + } + // Release memory. + unset($map, $ids); +} diff --git a/core/modules/entity_reference/src/Tests/EntityReferenceSettingsTest.php b/core/modules/entity_reference/src/Tests/EntityReferenceSettingsTest.php new file mode 100644 index 0000000..17e986f --- /dev/null +++ b/core/modules/entity_reference/src/Tests/EntityReferenceSettingsTest.php @@ -0,0 +1,96 @@ +installEntitySchema('node'); + $this->installEntitySchema('taxonomy_term'); + + $this->nodeType = NodeType::create([ + 'type' => Unicode::strtolower($this->randomMachineName()), + 'name' => $this->randomString(), + ]); + $this->nodeType->save(); + + $this->vocabulary = Vocabulary::create([ + 'vid' => Unicode::strtolower($this->randomMachineName()), + 'name' => $this->randomString(), + ]); + $this->vocabulary->save(); + } + + /** + * Tests that bundle changes are mirrored in field definitions. + */ + public function testSyncTargetBundleChanges() { + // Attach an entity reference field to $this->nodeType. + $name = Unicode::strtolower($this->randomMachineName()); + $label = $this->randomString(); + $vid = $this->vocabulary->id(); + $handler_settings = ['target_bundles' => [$vid => $vid]]; + $this->createEntityReferenceField('node', $this->nodeType->id(), $name, $label, 'taxonomy_term', 'default', $handler_settings); + + // Change the vocabulary vid. + $new_vid = Unicode::strtolower($this->randomMachineName()); + $this->vocabulary->set('vid', $new_vid); + $this->vocabulary->save(); + + // Reload the field config and test the target vocabulary. + $field_config = FieldConfig::loadByName('node', $this->nodeType->id(), $name); + $handler_settings = $field_config->getSetting('handler_settings'); + $vid = key($handler_settings['target_bundles']); + $this->assertIdentical($vid, $new_vid); + + // Delete the vocabulary. + $this->vocabulary->delete(); + // Reload and test again. + $field_config = FieldConfig::loadByName('node', $this->nodeType->id(), $name); + $handler_settings = $field_config->getSetting('handler_settings'); + $this->assertTrue(empty($handler_settings['target_bundles'])); + } + +} diff --git a/core/modules/taxonomy/src/Entity/Vocabulary.php b/core/modules/taxonomy/src/Entity/Vocabulary.php index 2855c65..31eb26b 100644 --- a/core/modules/taxonomy/src/Entity/Vocabulary.php +++ b/core/modules/taxonomy/src/Entity/Vocabulary.php @@ -127,40 +127,6 @@ public function getDescription() { */ public function postSave(EntityStorageInterface $storage, $update = TRUE) { parent::postSave($storage, $update); - - if ($update && $this->getOriginalId() != $this->id() && !$this->isSyncing()) { - // Reflect machine name changes in the definitions of existing 'taxonomy' - // fields. - $field_ids = array(); - $field_map = \Drupal::entityManager()->getFieldMapByFieldType('entity_reference'); - foreach ($field_map as $entity_type => $field_storages) { - foreach ($field_storages as $field_storage => $info) { - $field_ids[] = $entity_type . '.' . $field_storage; - } - } - - $field_storages = \Drupal::entityManager()->getStorage('field_storage_config')->loadMultiple($field_ids); - $taxonomy_fields = array_filter($field_storages, function ($field_storage) { - return $field_storage->getType() == 'entity_reference' && $field_storage->getSetting('target_type') == 'taxonomy_term'; - }); - - foreach ($taxonomy_fields as $field_storage) { - $update_storage = FALSE; - - $allowed_values = $field_storage->getSetting('allowed_values'); - foreach ($allowed_values as &$value) { - if ($value['vocabulary'] == $this->getOriginalId()) { - $value['vocabulary'] = $this->id(); - $update_storage = TRUE; - } - } - $field_storage->setSetting('allowed_values', $allowed_values); - - if ($update_storage) { - $field_storage->save(); - } - } - } $storage->resetCache($update ? array($this->getOriginalId()) : array()); }