diff --git a/core/config/schema/core.data_types.schema.yml b/core/config/schema/core.data_types.schema.yml index ab6b9440652475eb206b405d18d5acaaa9f3f9f2..763d0966da8a9006c8ae687f4f42953a55edae8a 100644 --- a/core/config/schema/core.data_types.schema.yml +++ b/core/config/schema/core.data_types.schema.yml @@ -355,9 +355,6 @@ base_entity_reference_field_settings: target_type: type: string label: 'Type of item to reference' - target_bundle: - type: string - label: 'Bundle of item to reference' field_config_base: type: config_entity 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 18c050646f361ba84d70c3d05b2a306073e6cfd4..70397fa1e64523e748ce27b9ea8dc04a03f64f20 100644 --- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php +++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php @@ -45,7 +45,6 @@ class EntityReferenceItem extends FieldItemBase { public static function defaultStorageSettings() { return array( 'target_type' => \Drupal::moduleHandler()->moduleExists('node') ? 'node' : 'user', - 'target_bundle' => NULL, ) + parent::defaultStorageSettings(); } @@ -93,16 +92,11 @@ public static function propertyDefinitions(FieldStorageDefinitionInterface $fiel ->setComputed(TRUE) ->setReadOnly(FALSE) ->setTargetDefinition(EntityDataDefinition::create($settings['target_type'])) + // We can add a constraint for the target entity type. The list of + // referenceable bundles is a field setting, so the corresponding + // constraint is added dynamically in ::getConstraints(). ->addConstraint('EntityType', $settings['target_type']); - if (isset($settings['target_bundle'])) { - $properties['entity']->addConstraint('Bundle', $settings['target_bundle']); - // Set any further bundle constraints on the target definition as well, - // such that it can derive more special data types if possible. For - // example, "entity:node:page" instead of "entity:node". - $properties['entity']->getTargetDefinition() - ->addConstraint('Bundle', $settings['target_bundle']); - } return $properties; } @@ -151,6 +145,28 @@ public static function schema(FieldStorageDefinitionInterface $field_definition) return $schema; } + /** + * {@inheritdoc} + */ + public function getConstraints() { + $constraints = parent::getConstraints(); + list($current_handler) = explode(':', $this->getSetting('handler'), 2); + if ($current_handler === 'default') { + $handler_settings = $this->getSetting('handler_settings'); + if (!empty($handler_settings['target_bundles'])) { + $constraint_manager = \Drupal::typedDataManager()->getValidationConstraintManager(); + $constraints[] = $constraint_manager->create('ComplexData', [ + 'entity' => [ + 'Bundle' => [ + 'bundle' => $handler_settings['target_bundles'], + ], + ], + ]); + } + } + return $constraints; + } + /** * {@inheritdoc} */ diff --git a/core/modules/entity_reference/src/ConfigurableEntityReferenceItem.php b/core/modules/entity_reference/src/ConfigurableEntityReferenceItem.php index 376fef859100e7a546d48b63ece8e98f13633a54..332de7b80238aa878f9cb122aa624f0cd9850c4a 100644 --- a/core/modules/entity_reference/src/ConfigurableEntityReferenceItem.php +++ b/core/modules/entity_reference/src/ConfigurableEntityReferenceItem.php @@ -30,17 +30,6 @@ */ class ConfigurableEntityReferenceItem extends EntityReferenceItem implements OptionsProviderInterface, PreconfiguredFieldUiOptionsInterface { - /** - * {@inheritdoc} - */ - public static function defaultStorageSettings() { - $settings = parent::defaultStorageSettings(); - // The target bundle is handled by the 'target_bundles' property in the - // 'handler_settings' instance setting. - unset($settings['target_bundle']); - return $settings; - } - /** * {@inheritdoc} */ diff --git a/core/modules/field/field.install b/core/modules/field/field.install new file mode 100644 index 0000000000000000000000000000000000000000..f381b05548b1080bcc33ef83868b538648e696d8 --- /dev/null +++ b/core/modules/field/field.install @@ -0,0 +1,28 @@ +<?php + +/** + * @file + * Install, update and uninstall functions for the field module. + */ + +/** + * Removes the stale 'target_bundle' storage setting on entity_reference fields. + */ +function field_update_8001() { + $config = \Drupal::configFactory(); + /** @var \Drupal\Core\Field\FieldTypePluginManager $field_type_manager */ + $field_type_manager = \Drupal::service('plugin.manager.field.field_type'); + $item_class = 'Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem'; + + // Iterate on all fields storage. + foreach ($config->listAll('field.storage.') as $field_id) { + $field_storage = $config->getEditable($field_id); + $class = $field_type_manager->getPluginClass($field_storage->get('type')); + + // Deal only with entity reference fields and descendants. + if ($class == $item_class || is_subclass_of($class, $item_class)) { + // Remove 'target_bundle' from settings. + $field_storage->clear('settings.target_bundle')->save(TRUE); + } + } +} diff --git a/core/modules/field/src/Tests/Migrate/d6/MigrateFieldInstanceTest.php b/core/modules/field/src/Tests/Migrate/d6/MigrateFieldInstanceTest.php index c0fb2f5344c0ef47f5aad4d220e497f8d9d652d1..19f835f56faa41733fd01c2dc3af75b53263885b 100644 --- a/core/modules/field/src/Tests/Migrate/d6/MigrateFieldInstanceTest.php +++ b/core/modules/field/src/Tests/Migrate/d6/MigrateFieldInstanceTest.php @@ -83,7 +83,6 @@ public function testFieldInstanceSettings() { // storages so we end up with the default value for this setting. 'handler' => 'default:node', 'handler_settings' => array(), - 'target_bundle' => NULL, ); $field_settings = $field->getSettings(); ksort($expected); diff --git a/core/modules/field/src/Tests/Update/EntityReferenceTargetBundleUpdateTest.php b/core/modules/field/src/Tests/Update/EntityReferenceTargetBundleUpdateTest.php new file mode 100644 index 0000000000000000000000000000000000000000..07b2d74fe043883f1bc2b31c5797801782285eea --- /dev/null +++ b/core/modules/field/src/Tests/Update/EntityReferenceTargetBundleUpdateTest.php @@ -0,0 +1,53 @@ +<?php + +/** + * @file + * Contains \Drupal\field\Tests\Update\EntityReferenceTargetBundleUpdateTest. + */ + +namespace Drupal\field\Tests\Update; + +use Drupal\system\Tests\Update\UpdatePathTestBase; + +/** + * Tests that field settings are properly updated during database updates. + * + * @group field + */ +class EntityReferenceTargetBundleUpdateTest extends UpdatePathTestBase { + + /** + * {@inheritdoc} + */ + protected function setDatabaseDumpFiles() { + $this->databaseDumpFiles = [ + __DIR__ . '/../../../../system/tests/fixtures/update/drupal-8.bare.standard.php.gz', + ]; + } + + /** + * Tests field_update_8001(). + * + * @see field_update_8001() + */ + public function testFieldUpdate8001() { + $configFactory = $this->container->get('config.factory'); + + // Load the 'node.field_image' field storage config, and check that is has + // a 'target_bundle' setting. + /** @var \Drupal\Core\Config\Config */ + $config = $configFactory->get('field.storage.node.field_image'); + $settings = $config->get('settings'); + $this->assertTrue(array_key_exists('target_bundle', $settings)); + + // Run updates. + $this->runUpdates(); + + // Reload the config, and check that the 'target_bundle' setting has been + // removed. + $config = $configFactory->get('field.storage.node.field_image'); + $settings = $config->get('settings'); + $this->assertFalse(array_key_exists('target_bundle', $settings)); + } + +} diff --git a/core/modules/system/src/Tests/Entity/EntityFieldTest.php b/core/modules/system/src/Tests/Entity/EntityFieldTest.php index 5d93c7862df7c7809f7607261b13a1d3fdf236be..6fae79b31dd3a25bb78cd1efc7e4b354d96f816b 100644 --- a/core/modules/system/src/Tests/Entity/EntityFieldTest.php +++ b/core/modules/system/src/Tests/Entity/EntityFieldTest.php @@ -689,9 +689,9 @@ public function testEntityConstraintValidation() { $definition = BaseFieldDefinition::create('entity_reference') ->setLabel('Test entity') ->setSetting('target_type', 'node') - ->setSetting('target_bundle', 'article'); + ->setSetting('handler_settings', ['target_bundles' => ['article' => 'article']]); $reference_field = \Drupal::TypedDataManager()->create($definition); - $reference = $reference_field->appendItem(array('entity' => $node))->get('entity'); + $reference = $reference_field->appendItem(array('entity' => $node)); $violations = $reference->validate(); $this->assertEqual($violations->count(), 1); diff --git a/core/profiles/standard/config/install/field.storage.node.field_image.yml b/core/profiles/standard/config/install/field.storage.node.field_image.yml index 9c1a644890aa4ad8ecc049ba8f29b84bb8e6b0db..ad719e4e6acf38d5f18fee5e57a48d48c380f4ff 100644 --- a/core/profiles/standard/config/install/field.storage.node.field_image.yml +++ b/core/profiles/standard/config/install/field.storage.node.field_image.yml @@ -19,7 +19,6 @@ settings: target_type: file display_field: false display_default: false - target_bundle: null module: image locked: false cardinality: 1 diff --git a/core/profiles/standard/config/install/field.storage.user.user_picture.yml b/core/profiles/standard/config/install/field.storage.user.user_picture.yml index 48da5578a52a6a439dc4471ad8da39455f204fdf..d81db8bb9b4be81dda425f525f544c77b17e2016 100644 --- a/core/profiles/standard/config/install/field.storage.user.user_picture.yml +++ b/core/profiles/standard/config/install/field.storage.user.user_picture.yml @@ -19,7 +19,6 @@ settings: target_type: file display_field: false display_default: false - target_bundle: null module: image locked: false cardinality: 1