diff --git a/core/modules/aggregator/aggregator.install b/core/modules/aggregator/aggregator.install index 58766f4..cd7203f 100644 --- a/core/modules/aggregator/aggregator.install +++ b/core/modules/aggregator/aggregator.install @@ -37,23 +37,3 @@ function aggregator_update_8001() { /** * @} End of "addtogroup updates-8.0.0-rc". */ - -/** - * @addtogroup updates-8.3.x - * @{ - */ - -/** - * Update the 'fid' and 'refresh' fields in order to make them required at the - * storage level. - */ -function aggregator_update_8300() { - $manager = \Drupal::entityDefinitionUpdateManager(); - $manager->updateFieldStorageDefinition($manager->getFieldStorageDefinition('fid', 'aggregator_item')); - $manager->updateFieldStorageDefinition($manager->getFieldStorageDefinition('refresh', 'aggregator_feed')); -} - -/** - * @} End of "addtogroup updates-8.3.x". - */ - diff --git a/core/modules/block_content/block_content.install b/core/modules/block_content/block_content.install index 47c3f52..4279cde 100644 --- a/core/modules/block_content/block_content.install +++ b/core/modules/block_content/block_content.install @@ -61,20 +61,3 @@ function block_content_update_8003() { \Drupal::entityDefinitionUpdateManager() ->installFieldStorageDefinition('revision_user', 'block_content', 'block_content', $revision_user); } - -/** - * @addtogroup updates-8.3.x - * @{ - */ - -/** - * Update the 'info' field in order to make it required at the storage level. - */ -function block_content_update_8300() { - $manager = \Drupal::entityDefinitionUpdateManager(); - $manager->updateFieldStorageDefinition($manager->getFieldStorageDefinition('info', 'block_content')); -} - -/** - * @} End of "addtogroup updates-8.3.x". - */ diff --git a/core/modules/comment/comment.install b/core/modules/comment/comment.install index c750917..895c039 100644 --- a/core/modules/comment/comment.install +++ b/core/modules/comment/comment.install @@ -206,14 +206,5 @@ function comment_update_8301() { } /** - * Update the 'entity_id' field in order to make it required at the storage - * level. - */ -function comment_update_8302() { - $manager = \Drupal::entityDefinitionUpdateManager(); - $manager->updateFieldStorageDefinition($manager->getFieldStorageDefinition('entity_id', 'comment')); -} - -/** * @} End of "addtogroup updates-8.3.x". */ diff --git a/core/modules/menu_link_content/menu_link_content.install b/core/modules/menu_link_content/menu_link_content.install index 7449685..43c75ec 100644 --- a/core/modules/menu_link_content/menu_link_content.install +++ b/core/modules/menu_link_content/menu_link_content.install @@ -16,20 +16,3 @@ function menu_link_content_install() { // https://www.drupal.org/node/1965074 module_set_weight('menu_link_content', 1); } - -/** - * @addtogroup updates-8.3.x - * @{ - */ - -/** - * Update the 'title' field in order to make it required at the storage level. - */ -function menu_link_content_update_8300() { - $manager = \Drupal::entityDefinitionUpdateManager(); - $manager->updateFieldStorageDefinition($manager->getFieldStorageDefinition('title', 'menu_link_content')); -} - -/** - * @} End of "addtogroup updates-8.3.x". - */ diff --git a/core/modules/node/node.install b/core/modules/node/node.install index 0dd2de2..a61e8ac 100644 --- a/core/modules/node/node.install +++ b/core/modules/node/node.install @@ -189,7 +189,9 @@ function node_update_8002() { // Regenerate entity type indexes, this should drop "node__default_langcode". $manager->updateEntityType($manager->getEntityType('node')); // Regenerate "langcode" indexes, this should drop "node_field__langcode". - $manager->updateFieldStorageDefinition($manager->getFieldStorageDefinition('langcode', 'node')); + $field_definition = $manager->getFieldStorageDefinition('langcode', 'node'); + $field_definition->setStorageRequired(TRUE); + $manager->updateFieldStorageDefinition($field_definition); } /** @@ -253,11 +255,16 @@ function node_update_8301() { } /** - * Update the 'status' field in order to make it required at the storage level. + * Update the 'uid' field in order to make it required at the storage level. */ function node_update_8302() { - $manager = \Drupal::entityDefinitionUpdateManager(); - $manager->updateFieldStorageDefinition($manager->getFieldStorageDefinition('title', 'node')); + // The SQL content entity schema no longer uses entity keys to mark their + // corresponding fields as NOT NULL in the database, so we need to update the + // 'uid' field manually. + $definition_update_manager = \Drupal::entityDefinitionUpdateManager(); + $field_storage_definition = $definition_update_manager->getFieldStorageDefinition('uid', 'node'); + $field_storage_definition->setStorageRequired(TRUE); + $definition_update_manager->updateFieldStorageDefinition($field_storage_definition); } /** diff --git a/core/modules/shortcut/shortcut.install b/core/modules/shortcut/shortcut.install index f50a605..8df408f 100644 --- a/core/modules/shortcut/shortcut.install +++ b/core/modules/shortcut/shortcut.install @@ -67,20 +67,3 @@ function shortcut_uninstall() { \Drupal::configFactory()->getEditable('seven.settings')->clear('third_party_settings.shortcut')->save(TRUE); } } - -/** - * @addtogroup updates-8.3.x - * @{ - */ - -/** - * Update the 'title' field in order to make it required at the storage level. - */ -function shortcut_update_8300() { - $manager = \Drupal::entityDefinitionUpdateManager(); - $manager->updateFieldStorageDefinition($manager->getFieldStorageDefinition('title', 'shortcut')); -} - -/** - * @} End of "addtogroup updates-8.3.x". - */ diff --git a/core/modules/system/src/Tests/Entity/EntityDefinitionTestTrait.php b/core/modules/system/src/Tests/Entity/EntityDefinitionTestTrait.php index 0123597..a53c8b1 100644 --- a/core/modules/system/src/Tests/Entity/EntityDefinitionTestTrait.php +++ b/core/modules/system/src/Tests/Entity/EntityDefinitionTestTrait.php @@ -137,12 +137,10 @@ protected function modifyBaseField() { /** * Promotes a field to an entity key. */ - protected function makeBaseFieldEntityKey() { - $entity_type = clone $this->entityManager->getDefinition('entity_test_update'); - $entity_keys = $entity_type->getKeys(); - $entity_keys['new_base_field'] = 'new_base_field'; - $entity_type->set('entity_keys', $entity_keys); - $this->state->set('entity_test_update.entity_type', $entity_type); + protected function makeBaseFieldRequired() { + $definitions = \Drupal::state()->get('entity_test_update.additional_base_field_definitions', []); + $definitions['new_base_field']->setRequired(TRUE); + $this->state->set('entity_test_update.additional_base_field_definitions', $definitions); } /** diff --git a/core/modules/system/system.install b/core/modules/system/system.install index 6dc2663..ac17e3e 100644 --- a/core/modules/system/system.install +++ b/core/modules/system/system.install @@ -13,6 +13,8 @@ use Drupal\Core\Url; use Drupal\Core\Database\Database; use Drupal\Core\DrupalKernel; +use Drupal\Core\Entity\Sql\SqlEntityStorageInterface; +use Drupal\Core\Field\BaseFieldDefinition; use Drupal\Core\Site\Settings; use Drupal\Core\StreamWrapper\PrivateStream; use Drupal\Core\StreamWrapper\PublicStream; @@ -1794,3 +1796,65 @@ function system_update_8203() { ->set('logging', 1) ->save(TRUE); } + +/** + * @addtogroup updates-8.3.x + * @{ + */ + +/** + * Update all the required base fields in order to make them NOT NULL at the + * storage level. + */ +function system_update_8300() { + $entity_type_manager = \Drupal::entityTypeManager(); + $definition_update_manager = \Drupal::entityDefinitionUpdateManager(); + /** @var \Drupal\Core\Entity\EntityLastInstalledSchemaRepositoryInterface $entity_last_installed_schema_respository */ + $entity_last_installed_schema_respository = \Drupal::service('entity.last_installed_schema.repository'); + + foreach ($entity_type_manager->getDefinitions() as $entity_type_id => $entityType) { + $original_entity_type = $entity_last_installed_schema_respository->getLastInstalledDefinition($entity_type_id); + $storage = $entity_type_manager->getStorage($entity_type_id); + if ($storage instanceof SqlEntityStorageInterface) { + foreach ($entity_last_installed_schema_respository->getLastInstalledFieldStorageDefinitions($entity_type_id) as $field_name => $field_definition) { + /** @var \Drupal\Core\Field\BaseFieldDefinition $field_definition */ + if ($field_definition instanceof BaseFieldDefinition) { + $field_name = $field_definition->getName(); + + // The SQL content entity schema no longer uses entity keys to mark + // their corresponding fields as NOT NULL in the database, so we need + // to update them manually. + $entity_keys_names = [ + $original_entity_type->getKey('id'), + $original_entity_type->getKey('uuid'), + $original_entity_type->getKey('revision'), + $original_entity_type->getKey('langcode'), + ]; + if (in_array($field_name, $entity_keys_names)) { + $field_definition->setStorageRequired(TRUE); + } + + if ($field_name == $original_entity_type->getKey('published')) { + $field_definition->setRequired(TRUE); + } + + // The 'fid' base field of aggregator items should have been marked as + // required in aggregator_update_8001(), but it was not so we need to + // correct it here. + // @see https://www.drupal.org/node/2602662 + if ($field_name == 'fid' && $field_definition->getTargetEntityTypeId() == 'aggregator_item') { + $field_definition->setRequired(TRUE); + } + + if ($field_definition->isStorageRequired()) { + $definition_update_manager->updateFieldStorageDefinition($field_definition); + } + } + } + } + } +} + +/** + * @} End of "addtogroup updates-8.3.x". + */ diff --git a/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestMulRevChanged.php b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestMulRevChanged.php index 3913075..a3fb47e 100644 --- a/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestMulRevChanged.php +++ b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestMulRevChanged.php @@ -58,6 +58,7 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) { ->setLabel(t('Revision ID')) ->setDescription(t('The version id of the test entity.')) ->setReadOnly(TRUE) + ->setStorageRequired(TRUE) ->setSetting('unsigned', TRUE); $fields['revision_translation_affected'] = BaseFieldDefinition::create('boolean') diff --git a/core/modules/user/user.install b/core/modules/user/user.install index 3c7a0b7..7cc46ef 100644 --- a/core/modules/user/user.install +++ b/core/modules/user/user.install @@ -107,20 +107,3 @@ function user_update_8100() { /** * @} End of "addtogroup updates-8.1.0-beta". */ - -/** - * @addtogroup updates-8.3.x - * @{ - */ - -/** - * Update the 'name' field in order to make it required at the storage level. - */ -function user_update_8300() { - $manager = \Drupal::entityDefinitionUpdateManager(); - $manager->updateFieldStorageDefinition($manager->getFieldStorageDefinition('name', 'user')); -} - -/** - * @} End of "addtogroup updates-8.3.x" - */ diff --git a/core/tests/Drupal/KernelTests/Core/Entity/EntityDefinitionUpdateTest.php b/core/tests/Drupal/KernelTests/Core/Entity/EntityDefinitionUpdateTest.php index e49ee7e..a738a76 100644 --- a/core/tests/Drupal/KernelTests/Core/Entity/EntityDefinitionUpdateTest.php +++ b/core/tests/Drupal/KernelTests/Core/Entity/EntityDefinitionUpdateTest.php @@ -765,9 +765,9 @@ public function testBaseFieldEntityKeyUpdateWithExistingData() { $entity = $this->entityManager->getStorage('entity_test_update')->create(); $entity->save(); - // Promote the base field to an entity key. This will trigger the addition - // of a NOT NULL constraint. - $this->makeBaseFieldEntityKey(); + // Make the base field required. This will trigger the addition of a NOT + // NULL constraint. + $this->makeBaseFieldRequired(); // Try to apply the update and verify they fail since we have a NULL value. $message = 'An error occurs when trying to enabling NOT NULL constraints with NULL data.'; diff --git a/core/tests/Drupal/Tests/Core/Entity/Sql/SqlContentEntityStorageSchemaTest.php b/core/tests/Drupal/Tests/Core/Entity/Sql/SqlContentEntityStorageSchemaTest.php index 1ce87c5..6ecf896 100644 --- a/core/tests/Drupal/Tests/Core/Entity/Sql/SqlContentEntityStorageSchemaTest.php +++ b/core/tests/Drupal/Tests/Core/Entity/Sql/SqlContentEntityStorageSchemaTest.php @@ -74,6 +74,7 @@ protected function setUp() { 'columns' => array( 'value' => array( 'type' => 'int', + 'not null' => TRUE, ), ), )); @@ -500,6 +501,7 @@ public function testGetSchemaTranslatable() { 'columns' => array( 'value' => array( 'type' => 'varchar', + 'not null' => TRUE, ), ), )); @@ -509,6 +511,7 @@ public function testGetSchemaTranslatable() { 'value' => array( 'type' => 'int', 'size' => 'tiny', + 'not null' => TRUE, ), ), )); @@ -618,6 +621,7 @@ public function testGetSchemaRevisionableTranslatable() { 'columns' => array( 'value' => array( 'type' => 'int', + 'not null' => TRUE, ), ), )); @@ -625,6 +629,7 @@ public function testGetSchemaRevisionableTranslatable() { 'columns' => array( 'value' => array( 'type' => 'varchar', + 'not null' => TRUE, ), ), )); @@ -633,6 +638,7 @@ public function testGetSchemaRevisionableTranslatable() { 'value' => array( 'type' => 'int', 'size' => 'tiny', + 'not null' => TRUE, ), ), )); @@ -1403,6 +1409,9 @@ public function setUpStorageDefinition($field_name, array $schema) { $this->storageDefinitions[$field_name]->expects($this->any()) ->method('getColumns') ->will($this->returnValue($schema['columns'])); + $this->storageDefinitions[$field_name]->expects($this->any()) + ->method('isStorageRequired') + ->will($this->returnValue(TRUE)); // Add property definitions. if (!empty($schema['columns'])) { $property_definitions = array(); diff --git a/core/tests/Drupal/Tests/Core/Field/TestBaseFieldDefinitionInterface.php b/core/tests/Drupal/Tests/Core/Field/TestBaseFieldDefinitionInterface.php index 953c902..afd19f7 100644 --- a/core/tests/Drupal/Tests/Core/Field/TestBaseFieldDefinitionInterface.php +++ b/core/tests/Drupal/Tests/Core/Field/TestBaseFieldDefinitionInterface.php @@ -4,9 +4,10 @@ use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Field\FieldStorageDefinitionInterface; +use Drupal\Core\Field\RequiredFieldStorageDefinitionInterface; /** * Defines a test interface to mock entity base field definitions. */ -interface TestBaseFieldDefinitionInterface extends FieldDefinitionInterface, FieldStorageDefinitionInterface { +interface TestBaseFieldDefinitionInterface extends FieldDefinitionInterface, FieldStorageDefinitionInterface, RequiredFieldStorageDefinitionInterface { }