diff --git a/core/lib/Drupal/Core/Field/FieldTypePluginManager.php b/core/lib/Drupal/Core/Field/FieldTypePluginManager.php index 66b17b977fcdd3cbe7ad9fe3d10a63ac55de618b..f3f6fe0b52c788f334f6701042be482ad71ba1d6 100644 --- a/core/lib/Drupal/Core/Field/FieldTypePluginManager.php +++ b/core/lib/Drupal/Core/Field/FieldTypePluginManager.php @@ -226,6 +226,15 @@ public function getUiDefinitions() { return $definitions; } + /** + * {@inheritdoc} + */ + public function getEntityTypeUiDefinitions(string $entity_type_id): array { + $ui_definitions = $this->getUiDefinitions(); + $this->moduleHandler->alter('field_info_entity_type_ui_definitions', $ui_definitions, $entity_type_id); + return $ui_definitions; + } + /** * {@inheritdoc} */ diff --git a/core/lib/Drupal/Core/Field/FieldTypePluginManagerInterface.php b/core/lib/Drupal/Core/Field/FieldTypePluginManagerInterface.php index 1473fd2b81d9533deba0db023e4a5c36559f01af..b40be64ee5a6b0813acaba343467c389dd32eb2b 100644 --- a/core/lib/Drupal/Core/Field/FieldTypePluginManagerInterface.php +++ b/core/lib/Drupal/Core/Field/FieldTypePluginManagerInterface.php @@ -113,6 +113,20 @@ public function getFieldSettingsSummary(FieldDefinitionInterface $field_definiti */ public function getUiDefinitions(); + /** + * Get the field type definitions that can be added via UI for an entity type. + * + * @param string $entity_type_id + * The entity type id. + * + * @return array + * An array of field type definitions. + * + * @see \Drupal\Core\Field\FieldTypePluginManagerInterface::getUiDefinitions() + * @see hook_field_info_entity_type_ui_definitions_alter() + */ + public function getEntityTypeUiDefinitions(string $entity_type_id): array; + /** * Returns preconfigured field options for a field type. * diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module index a3a80c8b83314201496d5b00d10bff44bacf7aa3..db13e9a6709024fbe4faa78c316967bcafe95263 100644 --- a/core/modules/comment/comment.module +++ b/core/modules/comment/comment.module @@ -238,23 +238,15 @@ function comment_form_field_ui_field_storage_add_form_alter(&$form, FormStateInt if ($form_state->get('entity_type_id') == 'comment' && $route_match->getParameter('commented_entity_type')) { $form['#title'] = \Drupal::service('comment.manager')->getFieldUIPageTitle($route_match->getParameter('commented_entity_type'), $route_match->getParameter('field_name')); } - if (!_comment_entity_uses_integer_id($form_state->get('entity_type_id'))) { - $form['add']['new_storage_type']['#process'][] = 'comment_new_storage_type_process_callback'; - } } /** - * Process callback to remove comment type field option. + * Implements hook_field_info_entity_type_ui_definitions_alter(). */ -function comment_new_storage_type_process_callback($element, &$form_state, $form) { - foreach ($element as $key => $value) { - if (isset($value['radio']['#return_value']) && $value['radio']['#return_value'] === 'comment') { - // You cannot use comment fields on entity types with non-integer IDs. - unset($element[$key]); - } +function comment_field_info_entity_type_ui_definitions_alter(array &$ui_definitions, string $entity_type_id) { + if (!_comment_entity_uses_integer_id($entity_type_id)) { + unset($ui_definitions['comment']); } - - return $element; } /** diff --git a/core/modules/field/field.api.php b/core/modules/field/field.api.php index ed9b86a8afff9732aa5c1c66cc0bdf118985453e..ac963a3952c2b4436b3ae15294cf55e2f77ba414 100644 --- a/core/modules/field/field.api.php +++ b/core/modules/field/field.api.php @@ -57,6 +57,26 @@ function hook_field_info_alter(&$info) { } } +/** + * Alters the UI field definitions. + * + * This hook can be used for altering field definitions available in the UI + * dynamically per entity type. For example, it can be used to hide field types + * that are incompatible with an entity type. + * + * @param array $ui_definitions + * Definition of all field types that can be added via UI. + * @param string $entity_type_id + * The entity type id. + * + * @see \Drupal\Core\Field\FieldTypePluginManagerInterface::getEntityTypeUiDefinitions + */ +function hook_field_info_entity_type_ui_definitions_alter(array &$ui_definitions, string $entity_type_id) { + if ($entity_type_id === 'node') { + unset($ui_definitions['field_type_not_compatible_with_node']); + } +} + /** * Perform alterations on preconfigured field options. * diff --git a/core/modules/field/tests/modules/field_test/field_test.module b/core/modules/field/tests/modules/field_test/field_test.module index 91ca8c0f9080947df3eb8979251b51ca23b79cdd..f6b2dbf8144879178ba1ecfca676522dea9bc0e1 100644 --- a/core/modules/field/tests/modules/field_test/field_test.module +++ b/core/modules/field/tests/modules/field_test/field_test.module @@ -15,6 +15,7 @@ use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Render\Element; +use Drupal\Core\StringTranslation\TranslatableMarkup; use Drupal\field\FieldStorageConfigInterface; require_once __DIR__ . '/field_test.entity.inc'; @@ -215,3 +216,12 @@ function field_test_field_ui_preconfigured_options_alter(array &$options, $field ]; } } + +/** + * Implements hook_field_info_entity_type_ui_definitions_alter(). + */ +function field_test_field_info_entity_type_ui_definitions_alter(array &$ui_definitions, string $entity_type_id) { + if ($entity_type_id === 'node') { + $ui_definitions['boolean']['label'] = new TranslatableMarkup('Boolean (overridden by alter)'); + } +} diff --git a/core/modules/field/tests/src/Kernel/FieldTypePluginManagerTest.php b/core/modules/field/tests/src/Kernel/FieldTypePluginManagerTest.php index 73b769836b285021984542d7ff9e8ec6c002d09e..83aae5e2b4ce99967e3c45a4bc4c4e48b0517fc7 100644 --- a/core/modules/field/tests/src/Kernel/FieldTypePluginManagerTest.php +++ b/core/modules/field/tests/src/Kernel/FieldTypePluginManagerTest.php @@ -110,6 +110,18 @@ public function testMainProperty() { } } + /** + * Tests UI definitions per entity type. + */ + public function testUiDefinitionsPerEntityType() { + /** @var \Drupal\Core\Field\FieldTypePluginManagerInterface $field_type_manager */ + $field_type_manager = \Drupal::service('plugin.manager.field.field_type'); + $definitions = $field_type_manager->getEntityTypeUiDefinitions('node'); + $this->assertEquals('Boolean (overridden by alter)', (string) $definitions['boolean']['label']); + $definitions = $field_type_manager->getEntityTypeUiDefinitions('entity_test'); + $this->assertEquals('Boolean', (string) $definitions['boolean']['label']); + } + /** * Enable all core modules. */ diff --git a/core/modules/field_ui/src/Form/FieldStorageAddForm.php b/core/modules/field_ui/src/Form/FieldStorageAddForm.php index 8c98931840862bfd7b3527be40b24dea98cb02fb..6d5ff8bc3145c3b74dc9c8dd5cc1335f766afd48 100644 --- a/core/modules/field_ui/src/Form/FieldStorageAddForm.php +++ b/core/modules/field_ui/src/Form/FieldStorageAddForm.php @@ -150,7 +150,7 @@ public function buildForm(array $form, FormStateInterface $form_state, $entity_t ]; $field_type_options = $unique_definitions = []; - $grouped_definitions = $this->fieldTypePluginManager->getGroupedDefinitions($this->fieldTypePluginManager->getUiDefinitions(), 'label', 'id'); + $grouped_definitions = $this->fieldTypePluginManager->getGroupedDefinitions($this->fieldTypePluginManager->getEntityTypeUiDefinitions($this->entityTypeId), 'label', 'id'); $category_definitions = $this->fieldTypeCategoryManager->getDefinitions(); // Invoke a hook to get category properties. foreach ($grouped_definitions as $category => $field_types) { diff --git a/core/modules/field_ui/tests/src/Functional/ManageFieldsTest.php b/core/modules/field_ui/tests/src/Functional/ManageFieldsTest.php index aa44488680506d2ce0f4ba80f2b9065b7fc4edb4..8bd98ebe26f91dc9ca6bdad1687ff38c8e5c488b 100644 --- a/core/modules/field_ui/tests/src/Functional/ManageFieldsTest.php +++ b/core/modules/field_ui/tests/src/Functional/ManageFieldsTest.php @@ -345,4 +345,15 @@ public function testFieldTypeCardinalityAlter() { $this->assertSession()->elementTextContains('css', '#edit-field-storage', 'Greetings from Drupal\field_test\Plugin\Field\FieldType\TestItem::storageSettingsForm'); } + /** + * Tests hook_field_info_entity_type_ui_definitions_alter(). + */ + public function testFieldUiDefinitionsAlter() { + $user = $this->drupalCreateUser(['administer node fields']); + $node_type = $this->drupalCreateContentType(); + $this->drupalLogin($user); + $this->drupalGet('/admin/structure/types/manage/' . $node_type->id() . '/fields/add-field'); + $this->assertSession()->pageTextContains('Boolean (overridden by alter)'); + } + }