diff --git a/core/modules/entity_reference/entity_reference.module b/core/modules/entity_reference/entity_reference.module index e44cc32..de7e7f1 100644 --- a/core/modules/entity_reference/entity_reference.module +++ b/core/modules/entity_reference/entity_reference.module @@ -232,3 +232,71 @@ function entity_reference_create_instance($entity_type, $bundle, $field_name, $f } } +/** + * Implements hook_entity_bundle_rename(). + */ +function entity_reference_entity_bundle_rename($entity_type, $bundle_old, $bundle_new) { + // Reflect bundle name changes in the definitions of existing entity reference + // field instance. + foreach (entity_load_multiple('field_instance') as $instance) { + $field = $instance->getField(); + if ($field->type != 'entity_reference' || $field->settings['target_type'] != $entity_type) { + // Not an entity reference field, referencing the given entity type. + continue; + } + if (empty($instance->settings['handler_settings']['target_bundles'])) { + // Instance is referencing all bundles. + continue; + } + + $update_instance = FALSE; + foreach ($instance->settings['handler_settings']['target_bundles'] as $delta => $bundle) { + if ($bundle == $bundle_old) { + $instance->settings['handler_settings']['target_bundles'][$delta] = $bundle_new; + $update_instance = TRUE; + } + } + if ($update_instance) { + $instance->save(); + } + } +} + +/** + * Implements hook_entity_bundle_delete(). + */ +function entity_reference_entity_bundle_delete($entity_type, $bundle) { + // Iterate over all entity reference fields referencing the given entity type + // and delete those which target only the bundle that was deleted. + foreach (entity_load_multiple('field_instance') as $instance) { + $field = $instance->getField(); + if ($field->type != 'entity_reference' || $field->settings['target_type'] != $entity_type) { + // Not an entity reference field, referencing the given entity type. + continue; + } + if (empty($instance->settings['handler_settings']['target_bundles'])) { + // Instance is referencing all bundles. + continue; + } + + $modified_instance = FALSE; + foreach ($instance->settings['handler_settings']['target_bundles'] as $delta => $target_bundle) { + if ($target_bundle == $bundle) { + unset($instance->settings['handler_settings']['target_bundles'][$delta]); + $modified_instance = TRUE; + } + } + if ($modified_instance) { + if (!empty($instance->settings['handler_settings']['target_bundles'])) { + // Re-key the 'target_bundles' array. + $instance->settings['handler_settings']['target_bundles'] = array_values($instance->settings['handler_settings']['target_bundles']); + } + else { + drupal_set_message(t('The %field field on the %bundle bundle was referencing the deleted bundle and is no longer filtering on bundles. Please update this field.', array('%field' => $instance->getLabel(), '%bundle' => $instance->targetBundle())), 'warning'); + } + + // Update the instance definition with the new target bundles. + $instance->save(); + } + } +} diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceFieldTest.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceFieldTest.php index 4119240..d085bfe 100644 --- a/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceFieldTest.php +++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceFieldTest.php @@ -7,6 +7,7 @@ namespace Drupal\entity_reference\Tests; +use Drupal\Component\Utility\Unicode; use Drupal\system\Tests\Entity\EntityUnitTestBase; use Drupal\field\Field; @@ -117,4 +118,41 @@ public function testEntityReferenceFieldValidation() { // https://drupal.org/node/2064191 is fixed } + /** + * Tests that bundle changes are mirrored in field definitions. + */ + public function testEntityReferenceFieldChangeMachineName() { + // Add several entries in the 'target_bundles' setting, to make sure that + // they all get updated. + $test_bundle_2 = Unicode::strtolower($this->randomName()); + entity_test_create_bundle($test_bundle_2, NULL, $this->referencedEntityType); + $this->instance->settings['handler_settings']['target_bundles'] = array( + $test_bundle_2, + $this->bundle, + ); + $this->instance->save(); + + // Change the machine name. + $test_bundle_2_new = Unicode::strtolower($this->randomName()); + entity_test_rename_bundle($test_bundle_2, $test_bundle_2_new, $this->referencedEntityType); + + // Check that the field instance settings have changed. + $instances = Field::fieldInfo()->getBundleInstances($this->entityType, $this->bundle); + $instance_settings = $instances[$this->fieldName]->getSetting('handler_settings'); + $target_bundles = $instance_settings['target_bundles']; + $this->assertEqual($target_bundles[0], $test_bundle_2_new, 'Index 0: Machine name was updated correctly.'); + $this->assertEqual($target_bundles[1], $this->bundle, 'Index 1: Machine name was left untouched.'); + $this->assertEqual(count($target_bundles), 2, "The 'target_bundles' setting contains two elements."); + + // Delete a bundle. + entity_test_delete_bundle($test_bundle_2_new, $this->referencedEntityType); + + // Check that the field instance settings have changed. + $instances = Field::fieldInfo()->getBundleInstances($this->entityType, $this->bundle); + $instance_settings = $instances[$this->fieldName]->getSetting('handler_settings'); + $target_bundles = $instance_settings['target_bundles']; + $this->assertEqual($target_bundles[0], $this->bundle, 'Index 0: The bundle that was not removed is still referenced.'); + $this->assertEqual(count($target_bundles), 1, "The 'target_bundles' setting contains only one element."); + } + }