diff --git a/core/lib/Drupal/Core/Entity/EntityDisplayBase.php b/core/lib/Drupal/Core/Entity/EntityDisplayBase.php index 34ce858b13..5c3788761e 100644 --- a/core/lib/Drupal/Core/Entity/EntityDisplayBase.php +++ b/core/lib/Drupal/Core/Entity/EntityDisplayBase.php @@ -163,12 +163,12 @@ protected function init() { if (!isset($this->content[$name]) && !isset($this->hidden[$name])) { // Extra fields are visible by default unless they explicitly say so. if (!isset($definition['visible']) || $definition['visible'] == TRUE) { - $this->content[$name] = [ + $this->setComponent($name, [ 'weight' => $definition['weight'] - ]; + ]); } else { - $this->hidden[$name] = TRUE; + $this->removeComponent($name); } } // Ensure extra fields have a 'region'. diff --git a/core/modules/field_ui/tests/src/Kernel/EntityDisplayTest.php b/core/modules/field_ui/tests/src/Kernel/EntityDisplayTest.php index 2d02e44a55..c6a7a3f156 100644 --- a/core/modules/field_ui/tests/src/Kernel/EntityDisplayTest.php +++ b/core/modules/field_ui/tests/src/Kernel/EntityDisplayTest.php @@ -166,7 +166,15 @@ public function testExtraFieldComponent() { // Check that the default visibility taken into account for extra fields // unknown in the display. - $this->assertEqual($display->getComponent('display_extra_field'), ['weight' => 5, 'region' => 'content']); + $this->assertEqual( + $display->getComponent('display_extra_field'), + [ + 'weight' => 5, + 'region' => 'content', + 'settings' => [], + 'third_party_settings' => [], + ] + ); $this->assertNull($display->getComponent('display_extra_field_hidden')); // Check that setting explicit options overrides the defaults. diff --git a/core/modules/rest/tests/src/Functional/EntityResource/EntityViewDisplay/EntityViewDisplayResourceTestBase.php b/core/modules/rest/tests/src/Functional/EntityResource/EntityViewDisplay/EntityViewDisplayResourceTestBase.php index ccc3aad3c0..3278e4157c 100644 --- a/core/modules/rest/tests/src/Functional/EntityResource/EntityViewDisplay/EntityViewDisplayResourceTestBase.php +++ b/core/modules/rest/tests/src/Functional/EntityResource/EntityViewDisplay/EntityViewDisplayResourceTestBase.php @@ -68,6 +68,8 @@ protected function getExpectedNormalizedEntity() { 'links' => [ 'region' => 'content', 'weight' => 100, + 'settings' => [], + 'third_party_settings' => [], ], ], 'dependencies' => [ diff --git a/core/modules/system/system.post_update.php b/core/modules/system/system.post_update.php index 229e309edd..038d4b8290 100644 --- a/core/modules/system/system.post_update.php +++ b/core/modules/system/system.post_update.php @@ -5,7 +5,9 @@ * Post update functions for System. */ +use Drupal\Core\Config\Entity\ConfigEntityUpdater; use Drupal\Core\Entity\Display\EntityDisplayInterface; +use Drupal\Core\Entity\Display\EntityViewDisplayInterface; use Drupal\Core\Entity\Entity\EntityFormDisplay; use Drupal\Core\Entity\Entity\EntityViewDisplay; @@ -139,3 +141,32 @@ function system_post_update_change_delete_action_plugins() { function system_post_update_language_item_callback() { // Empty post-update hook. } + +/** + * Update all entity displays that contain extra fields. + */ +function system_post_update_extra_fields(&$sandbox = NULL) { + $config_entity_updater = \Drupal::classResolver(ConfigEntityUpdater::class); + $entity_field_manager = \Drupal::service('entity_field.manager'); + + $callback = function (EntityDisplayInterface $display) use ($entity_field_manager) { + $display_context = $display instanceof EntityViewDisplayInterface ? 'display' : 'form'; + $extra_fields = $entity_field_manager->getExtraFields($display->getTargetEntityTypeId(), $display->getTargetBundle()); + + // If any extra fields are used as a component, resave the display with the + // updated component information. + $needs_save = FALSE; + if (!empty($extra_fields[$display_context])) { + foreach ($extra_fields[$display_context] as $name => $extra_field) { + if ($component = $display->getComponent($name)) { + $display->setComponent($name, $component); + $needs_save = TRUE; + } + } + } + return $needs_save; + }; + + $config_entity_updater->update($sandbox, 'entity_form_display', $callback); + $config_entity_updater->update($sandbox, 'entity_view_display', $callback); +} diff --git a/core/modules/system/tests/src/Functional/Update/UpdateEntityDisplayTest.php b/core/modules/system/tests/src/Functional/Update/UpdateEntityDisplayTest.php index 698d331099..e7bdcd55ce 100644 --- a/core/modules/system/tests/src/Functional/Update/UpdateEntityDisplayTest.php +++ b/core/modules/system/tests/src/Functional/Update/UpdateEntityDisplayTest.php @@ -7,7 +7,7 @@ use Drupal\FunctionalTests\Update\UpdatePathTestBase; /** - * Tests system_post_update_add_region_to_entity_displays(). + * Tests updates for entity displays. * * @group Update */ @@ -24,8 +24,10 @@ protected function setDatabaseDumpFiles() { /** * Tests that entity displays are updated with regions for their fields. + * + * @see system_post_update_add_region_to_entity_displays() */ - public function testUpdate() { + public function testRegionUpdate() { // No region key appears pre-update. $entity_form_display = EntityFormDisplay::load('node.article.default'); $options = $entity_form_display->getComponent('body'); @@ -47,4 +49,22 @@ public function testUpdate() { $this->assertIdentical('content', $options['region']); } + /** + * Tests that entity displays are updated to properly store extra fields. + * + * @see system_post_update_extra_fields() + */ + public function testExtraFieldsUpdate() { + $assertion = function ($expected_keys) { + $entity_view_display = EntityViewDisplay::load('node.article.default'); + $this->assertEquals($expected_keys, array_keys($entity_view_display->getComponent('links'))); + }; + + // Before the update extra fields are missing additional configuration. + $assertion(['weight', 'region']); + $this->runUpdates(); + // After the update the additional configuration is present. + $assertion(['weight', 'region', 'settings', 'third_party_settings']); + } + }