diff --git a/core/modules/comment/comment.install b/core/modules/comment/comment.install index 82b578b4895..51aaec9996d 100644 --- a/core/modules/comment/comment.install +++ b/core/modules/comment/comment.install @@ -207,3 +207,16 @@ function comment_update_8600() { $field_storage_definition->setDefaultValueCallback(Comment::class . '::getDefaultHostname'); $entity_definition_update_manager->updateFieldStorageDefinition($field_storage_definition); } + +/** + * Set the 'owner' entity key and update the field. + */ +function comment_update_8601() { + $definition_update_manager = \Drupal::entityDefinitionUpdateManager(); + $entity_type = $definition_update_manager->getEntityType('comment'); + $keys = $entity_type->getKeys(); + $keys['owner'] = 'uid'; + $entity_type->set('entity_keys', $keys); + $definition_update_manager->updateEntityType($entity_type); + $definition_update_manager->updateFieldStorageDefinition($definition_update_manager->getFieldStorageDefinition('uid', 'comment')); +} diff --git a/core/modules/comment/src/Entity/Comment.php b/core/modules/comment/src/Entity/Comment.php index 98562717614..58e4229b1a4 100644 --- a/core/modules/comment/src/Entity/Comment.php +++ b/core/modules/comment/src/Entity/Comment.php @@ -13,7 +13,7 @@ use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Field\BaseFieldDefinition; use Drupal\field\Entity\FieldStorageConfig; use Drupal\user\Entity\User; -use Drupal\user\UserInterface; +use Drupal\user\EntityOwnerTrait; /** * Defines the comment entity class. @@ -52,6 +52,7 @@ use Drupal\user\UserInterface; * "langcode" = "langcode", * "uuid" = "uuid", * "published" = "status", + * "owner" = "uid", * }, * links = { * "canonical" = "/comment/{comment}", @@ -70,6 +71,7 @@ use Drupal\user\UserInterface; class Comment extends ContentEntityBase implements CommentInterface { use EntityChangedTrait; + use EntityOwnerTrait; use EntityPublishedTrait; /** @@ -221,6 +223,7 @@ class Comment extends ContentEntityBase implements CommentInterface { /** @var \Drupal\Core\Field\BaseFieldDefinition[] $fields */ $fields = parent::baseFieldDefinitions($entity_type); $fields += static::publishedBaseFieldDefinitions($entity_type); + $fields += static::ownerBaseFieldDefinitions($entity_type); $fields['cid']->setLabel(t('Comment ID')) ->setDescription(t('The comment ID.')); @@ -256,12 +259,8 @@ class Comment extends ContentEntityBase implements CommentInterface { ]) ->setDisplayConfigurable('form', TRUE); - $fields['uid'] = BaseFieldDefinition::create('entity_reference') - ->setLabel(t('User ID')) - ->setDescription(t('The user ID of the comment author.')) - ->setTranslatable(TRUE) - ->setSetting('target_type', 'user') - ->setDefaultValue(0); + $fields['uid'] + ->setDescription(t('The user ID of the comment author.')); $fields['name'] = BaseFieldDefinition::create('string') ->setLabel(t('Name')) @@ -320,6 +319,13 @@ class Comment extends ContentEntityBase implements CommentInterface { return $fields; } + /** + * {@inheritdoc} + */ + public static function getDefaultEntityOwner() { + return 0; + } + /** * {@inheritdoc} */ @@ -524,29 +530,6 @@ class Comment extends ContentEntityBase implements CommentInterface { return $user; } - /** - * {@inheritdoc} - */ - public function getOwnerId() { - return $this->get('uid')->target_id; - } - - /** - * {@inheritdoc} - */ - public function setOwnerId($uid) { - $this->set('uid', $uid); - return $this; - } - - /** - * {@inheritdoc} - */ - public function setOwner(UserInterface $account) { - $this->set('uid', $account->id()); - return $this; - } - /** * Get the comment type ID for this comment. * diff --git a/core/modules/comment/tests/src/Functional/Hal/CommentHalJsonTestBase.php b/core/modules/comment/tests/src/Functional/Hal/CommentHalJsonTestBase.php index a9cf1c24256..ca19d31cf52 100644 --- a/core/modules/comment/tests/src/Functional/Hal/CommentHalJsonTestBase.php +++ b/core/modules/comment/tests/src/Functional/Hal/CommentHalJsonTestBase.php @@ -42,8 +42,8 @@ abstract class CommentHalJsonTestBase extends CommentResourceTestBase { 'thread' => NULL, 'entity_type' => NULL, 'field_name' => NULL, - 'entity_id' => NULL, 'uid' => "The 'administer comments' permission is required.", + 'entity_id' => NULL, ]; /** diff --git a/core/modules/comment/tests/src/Functional/Rest/CommentResourceTestBase.php b/core/modules/comment/tests/src/Functional/Rest/CommentResourceTestBase.php index 7d1abdbb680..67526341510 100644 --- a/core/modules/comment/tests/src/Functional/Rest/CommentResourceTestBase.php +++ b/core/modules/comment/tests/src/Functional/Rest/CommentResourceTestBase.php @@ -31,9 +31,9 @@ abstract class CommentResourceTestBase extends EntityResourceTestBase { */ protected static $patchProtectedFieldNames = [ 'status' => "The 'administer comments' permission is required.", + 'uid' => "The 'administer comments' permission is required.", 'pid' => NULL, 'entity_id' => NULL, - 'uid' => "The 'administer comments' permission is required.", 'name' => "The 'administer comments' permission is required.", 'homepage' => "The 'administer comments' permission is required.", 'created' => "The 'administer comments' permission is required.", diff --git a/core/modules/comment/tests/src/Functional/Update/CommentUpdateTest.php b/core/modules/comment/tests/src/Functional/Update/CommentUpdateTest.php index d68b1e540ca..45c2115f92a 100644 --- a/core/modules/comment/tests/src/Functional/Update/CommentUpdateTest.php +++ b/core/modules/comment/tests/src/Functional/Update/CommentUpdateTest.php @@ -72,4 +72,22 @@ class CommentUpdateTest extends UpdatePathTestBase { $this->assertTrue(\Drupal::database()->schema()->indexExists('comment_field_data', 'comment__status_comment_type')); } + /** + * Tests that the comment entity type has an 'owner' entity key. + * + * @see comment_update_8600() + */ + public function testOwnerEntityKey() { + // Check that the 'owner' entity key does not exist prior to the update. + $entity_type = \Drupal::entityDefinitionUpdateManager()->getEntityType('comment'); + $this->assertFalse($entity_type->getKey('owner')); + + // Run updates. + $this->runUpdates(); + + // Check that the entity key exists and it has the correct value. + $entity_type = \Drupal::entityDefinitionUpdateManager()->getEntityType('comment'); + $this->assertEquals('uid', $entity_type->getKey('owner')); + } + } diff --git a/core/modules/content_moderation/content_moderation.install b/core/modules/content_moderation/content_moderation.install index ddeecb5624e..e60fc59927c 100644 --- a/core/modules/content_moderation/content_moderation.install +++ b/core/modules/content_moderation/content_moderation.install @@ -29,3 +29,16 @@ function content_moderation_update_8401() { $database_schema->dropTable('content_revision_tracker'); } } + +/** + * Set the 'owner' entity key and update the field. + */ +function content_moderation_update_8600() { + $definition_update_manager = \Drupal::entityDefinitionUpdateManager(); + $entity_type = $definition_update_manager->getEntityType('content_moderation_state'); + $keys = $entity_type->getKeys(); + $keys['owner'] = 'uid'; + $entity_type->set('entity_keys', $keys); + $definition_update_manager->updateEntityType($entity_type); + $definition_update_manager->updateFieldStorageDefinition($definition_update_manager->getFieldStorageDefinition('uid', 'content_moderation_state')); +} diff --git a/core/modules/content_moderation/src/Entity/ContentModerationState.php b/core/modules/content_moderation/src/Entity/ContentModerationState.php index abb92eb8411..48fde7b0f70 100644 --- a/core/modules/content_moderation/src/Entity/ContentModerationState.php +++ b/core/modules/content_moderation/src/Entity/ContentModerationState.php @@ -7,7 +7,7 @@ use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Field\BaseFieldDefinition; use Drupal\Core\TypedData\TranslatableInterface; -use Drupal\user\UserInterface; +use Drupal\user\EntityOwnerTrait; /** * Defines the Content moderation state entity. @@ -37,6 +37,7 @@ use Drupal\user\UserInterface; * "revision" = "revision_id", * "uuid" = "uuid", * "uid" = "uid", + * "owner" = "uid", * "langcode" = "langcode", * } * ) @@ -48,18 +49,18 @@ use Drupal\user\UserInterface; */ class ContentModerationState extends ContentEntityBase implements ContentModerationStateInterface { + use EntityOwnerTrait; + /** * {@inheritdoc} */ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) { $fields = parent::baseFieldDefinitions($entity_type); + $fields += static::ownerBaseFieldDefinitions($entity_type); - $fields['uid'] = BaseFieldDefinition::create('entity_reference') + $fields['uid'] ->setLabel(t('User')) ->setDescription(t('The username of the entity creator.')) - ->setSetting('target_type', 'user') - ->setDefaultValueCallback('Drupal\content_moderation\Entity\ContentModerationState::getCurrentUserId') - ->setTranslatable(TRUE) ->setRevisionable(TRUE); $fields['workflow'] = BaseFieldDefinition::create('entity_reference') @@ -98,36 +99,6 @@ class ContentModerationState extends ContentEntityBase implements ContentModerat return $fields; } - /** - * {@inheritdoc} - */ - public function getOwner() { - return $this->get('uid')->entity; - } - - /** - * {@inheritdoc} - */ - public function getOwnerId() { - return $this->getEntityKey('uid'); - } - - /** - * {@inheritdoc} - */ - public function setOwnerId($uid) { - $this->set('uid', $uid); - return $this; - } - - /** - * {@inheritdoc} - */ - public function setOwner(UserInterface $account) { - $this->set('uid', $account->id()); - return $this; - } - /** * Creates or updates an entity's moderation state whilst saving that entity. * @@ -185,10 +156,14 @@ class ContentModerationState extends ContentEntityBase implements ContentModerat * * @see \Drupal\content_moderation\Entity\ContentModerationState::baseFieldDefinitions() * + * @deprecated The ::getCurrentUserId method is deprecated in 8.6.x and will + * be removed before 9.0.0. + * * @return array * An array of default values. */ public static function getCurrentUserId() { + @trigger_error('The ::getCurrentUserId method is deprecated in 8.6.x and will be removed before 9.0.0.', E_USER_DEPRECATED); return [\Drupal::currentUser()->id()]; } diff --git a/core/modules/content_moderation/tests/src/Functional/Update/ContentModerationUpdateTest.php b/core/modules/content_moderation/tests/src/Functional/Update/ContentModerationUpdateTest.php new file mode 100644 index 00000000000..02b15e8703d --- /dev/null +++ b/core/modules/content_moderation/tests/src/Functional/Update/ContentModerationUpdateTest.php @@ -0,0 +1,43 @@ +databaseDumpFiles = [ + __DIR__ . '/../../../../../system/tests/fixtures/update/drupal-8.4.0.bare.standard.php.gz', + __DIR__ . '/../../../fixtures/update/drupal-8.4.0-content_moderation_installed.php', + ]; + } + + /** + * Tests that the content moderation state entity has an 'owner' entity key. + * + * @see content_moderation_update_8600() + */ + public function testOwnerEntityKey() { + // Check that the 'owner' entity key does not exist prior to the update. + $entity_type = \Drupal::entityDefinitionUpdateManager()->getEntityType('content_moderation_state'); + $this->assertFalse($entity_type->getKey('owner')); + + // Run updates. + $this->runUpdates(); + + // Check that the entity key exists and it has the correct value. + $entity_type = \Drupal::entityDefinitionUpdateManager()->getEntityType('content_moderation_state'); + $this->assertEquals('uid', $entity_type->getKey('owner')); + } + +} diff --git a/core/modules/content_moderation/tests/src/Kernel/ContentModerationStateTest.php b/core/modules/content_moderation/tests/src/Kernel/ContentModerationStateTest.php index 8574ad6a171..c32b1ae70ad 100644 --- a/core/modules/content_moderation/tests/src/Kernel/ContentModerationStateTest.php +++ b/core/modules/content_moderation/tests/src/Kernel/ContentModerationStateTest.php @@ -616,6 +616,16 @@ class ContentModerationStateTest extends KernelTestBase { $this->assertEquals($entity->getLoadedRevisionId(), $cms_entity->get('content_entity_revision_id')->value); } + /** + * Tests the legacy method used as the default entity owner. + * + * @group legacy + * @expectedDeprecation The ::getCurrentUserId method is deprecated in 8.6.x and will be removed before 9.0.0. + */ + public function testGetCurrentUserId() { + $this->assertEquals(['0'], ContentModerationState::getCurrentUserId()); + } + /** * Creates an entity. * diff --git a/core/modules/file/file.install b/core/modules/file/file.install index 6274efc7c91..cca8249a8f7 100644 --- a/core/modules/file/file.install +++ b/core/modules/file/file.install @@ -164,3 +164,16 @@ function file_update_8001() { } } } + +/** + * Set the 'owner' entity key and update the field. + */ +function file_update_8600() { + $definition_update_manager = \Drupal::entityDefinitionUpdateManager(); + $entity_type = $definition_update_manager->getEntityType('file'); + $keys = $entity_type->getKeys(); + $keys['owner'] = 'uid'; + $entity_type->set('entity_keys', $keys); + $definition_update_manager->updateEntityType($entity_type); + $definition_update_manager->updateFieldStorageDefinition($definition_update_manager->getFieldStorageDefinition('uid', 'file')); +} diff --git a/core/modules/file/src/Entity/File.php b/core/modules/file/src/Entity/File.php index 33f6d744cc2..92aa436423e 100644 --- a/core/modules/file/src/Entity/File.php +++ b/core/modules/file/src/Entity/File.php @@ -8,7 +8,7 @@ use Drupal\Core\Entity\EntityStorageInterface; use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Field\BaseFieldDefinition; use Drupal\file\FileInterface; -use Drupal\user\UserInterface; +use Drupal\user\EntityOwnerTrait; /** * Defines the file entity class. @@ -36,13 +36,15 @@ use Drupal\user\UserInterface; * "id" = "fid", * "label" = "filename", * "langcode" = "langcode", - * "uuid" = "uuid" + * "uuid" = "uuid", + * "owner" = "uid", * } * ) */ class File extends ContentEntityBase implements FileInterface { use EntityChangedTrait; + use EntityOwnerTrait; /** * {@inheritdoc} @@ -116,36 +118,6 @@ class File extends ContentEntityBase implements FileInterface { return $this->get('created')->value; } - /** - * {@inheritdoc} - */ - public function getOwner() { - return $this->get('uid')->entity; - } - - /** - * {@inheritdoc} - */ - public function getOwnerId() { - return $this->get('uid')->target_id; - } - - /** - * {@inheritdoc} - */ - public function setOwnerId($uid) { - $this->set('uid', $uid); - return $this; - } - - /** - * {@inheritdoc} - */ - public function setOwner(UserInterface $account) { - $this->set('uid', $account->id()); - return $this; - } - /** * {@inheritdoc} */ @@ -232,6 +204,7 @@ class File extends ContentEntityBase implements FileInterface { public static function baseFieldDefinitions(EntityTypeInterface $entity_type) { /** @var \Drupal\Core\Field\BaseFieldDefinition[] $fields */ $fields = parent::baseFieldDefinitions($entity_type); + $fields += static::ownerBaseFieldDefinitions($entity_type); $fields['fid']->setLabel(t('File ID')) ->setDescription(t('The file ID.')); @@ -241,10 +214,8 @@ class File extends ContentEntityBase implements FileInterface { $fields['langcode']->setLabel(t('Language code')) ->setDescription(t('The file language code.')); - $fields['uid'] = BaseFieldDefinition::create('entity_reference') - ->setLabel(t('User ID')) - ->setDescription(t('The user ID of the file.')) - ->setSetting('target_type', 'user'); + $fields['uid'] + ->setDescription(t('The user ID of the file.')); $fields['filename'] = BaseFieldDefinition::create('string') ->setLabel(t('Filename')) @@ -284,4 +255,11 @@ class File extends ContentEntityBase implements FileInterface { return $fields; } + /** + * {@inheritdoc} + */ + public static function getDefaultEntityOwner() { + return NULL; + } + } diff --git a/core/modules/file/src/FileStorageSchema.php b/core/modules/file/src/FileStorageSchema.php index 17e909ab222..f03d4520295 100644 --- a/core/modules/file/src/FileStorageSchema.php +++ b/core/modules/file/src/FileStorageSchema.php @@ -26,6 +26,11 @@ class FileStorageSchema extends SqlContentEntityStorageSchema { break; } } + // Entity keys automatically have not null assigned to TRUE, but for the + // file entity, NULL is a valid value for uid. + if ($field_name === 'uid') { + $schema['fields']['uid']['not null'] = FALSE; + } return $schema; } diff --git a/core/modules/file/tests/src/Functional/Update/FileUpdateTest.php b/core/modules/file/tests/src/Functional/Update/FileUpdateTest.php index 5a35d63693f..974ec63da66 100644 --- a/core/modules/file/tests/src/Functional/Update/FileUpdateTest.php +++ b/core/modules/file/tests/src/Functional/Update/FileUpdateTest.php @@ -56,4 +56,22 @@ class FileUpdateTest extends UpdatePathTestBase { $this->assertEqual($formatter_settings, ['use_description_as_link_text' => FALSE]); } + /** + * Tests that the file entity type has an 'owner' entity key. + * + * @see file_update_8600() + */ + public function testOwnerEntityKey() { + // Check that the 'owner' entity key does not exist prior to the update. + $entity_type = \Drupal::entityDefinitionUpdateManager()->getEntityType('file'); + $this->assertFalse($entity_type->getKey('owner')); + + // Run updates. + $this->runUpdates(); + + // Check that the entity key exists and it has the correct value. + $entity_type = \Drupal::entityDefinitionUpdateManager()->getEntityType('file'); + $this->assertEqual('uid', $entity_type->getKey('owner')); + } + } diff --git a/core/modules/media/media.install b/core/modules/media/media.install index d3386ea35a7..58c8677f4f3 100644 --- a/core/modules/media/media.install +++ b/core/modules/media/media.install @@ -163,3 +163,16 @@ function media_update_8600() { ->set('oembed_providers_url', 'https://oembed.com/providers.json') ->save(TRUE); } + +/** + * Set the 'owner' entity key and update the field. + */ +function media_update_8601() { + $definition_update_manager = \Drupal::entityDefinitionUpdateManager(); + $entity_type = $definition_update_manager->getEntityType('media'); + $keys = $entity_type->getKeys(); + $keys['owner'] = 'uid'; + $entity_type->set('entity_keys', $keys); + $definition_update_manager->updateEntityType($entity_type); + $definition_update_manager->updateFieldStorageDefinition($definition_update_manager->getFieldStorageDefinition('uid', 'media')); +} diff --git a/core/modules/media/src/Entity/Media.php b/core/modules/media/src/Entity/Media.php index 1bbaf0881d2..ab1f070a1a9 100644 --- a/core/modules/media/src/Entity/Media.php +++ b/core/modules/media/src/Entity/Media.php @@ -10,7 +10,7 @@ use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\media\MediaInterface; use Drupal\media\MediaSourceEntityConstraintsInterface; use Drupal\media\MediaSourceFieldConstraintsInterface; -use Drupal\user\UserInterface; +use Drupal\user\EntityOwnerTrait; /** * Defines the media entity class. @@ -60,6 +60,7 @@ use Drupal\user\UserInterface; * "langcode" = "langcode", * "uuid" = "uuid", * "published" = "status", + * "owner" = "uid", * }, * revision_metadata_keys = { * "revision_user" = "revision_user", @@ -85,6 +86,7 @@ use Drupal\user\UserInterface; */ class Media extends EditorialContentEntityBase implements MediaInterface { + use EntityOwnerTrait; use StringTranslationTrait; /** @@ -130,34 +132,6 @@ class Media extends EditorialContentEntityBase implements MediaInterface { return $this->set('created', $timestamp); } - /** - * {@inheritdoc} - */ - public function getOwner() { - return $this->get('uid')->entity; - } - - /** - * {@inheritdoc} - */ - public function setOwner(UserInterface $account) { - return $this->set('uid', $account->id()); - } - - /** - * {@inheritdoc} - */ - public function getOwnerId() { - return $this->get('uid')->target_id; - } - - /** - * {@inheritdoc} - */ - public function setOwnerId($uid) { - return $this->set('uid', $uid); - } - /** * {@inheritdoc} */ @@ -453,6 +427,7 @@ class Media extends EditorialContentEntityBase implements MediaInterface { */ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) { $fields = parent::baseFieldDefinitions($entity_type); + $fields += static::ownerBaseFieldDefinitions($entity_type); $fields['name'] = BaseFieldDefinition::create('string') ->setLabel(t('Name')) @@ -484,13 +459,10 @@ class Media extends EditorialContentEntityBase implements MediaInterface { ->setDisplayConfigurable('view', TRUE) ->setReadOnly(TRUE); - $fields['uid'] = BaseFieldDefinition::create('entity_reference') + $fields['uid'] ->setLabel(t('Authored by')) ->setDescription(t('The user ID of the author.')) ->setRevisionable(TRUE) - ->setDefaultValueCallback(static::class . '::getCurrentUserId') - ->setSetting('target_type', 'user') - ->setTranslatable(TRUE) ->setDisplayOptions('form', [ 'type' => 'entity_reference_autocomplete', 'weight' => 5, @@ -551,10 +523,14 @@ class Media extends EditorialContentEntityBase implements MediaInterface { * * @see ::baseFieldDefinitions() * + * @deprecated The ::getCurrentUserId method is deprecated in 8.6.x and will + * be removed before 9.0.0. + * * @return int[] * An array of default values. */ public static function getCurrentUserId() { + @trigger_error('The ::getCurrentUserId method is deprecated in 8.6.x and will be removed before 9.0.0.', E_USER_DEPRECATED); return [\Drupal::currentUser()->id()]; } diff --git a/core/modules/media/tests/src/Functional/Update/MediaUpdateTest.php b/core/modules/media/tests/src/Functional/Update/MediaUpdateTest.php index 4d4c3ea76f4..655ff658502 100644 --- a/core/modules/media/tests/src/Functional/Update/MediaUpdateTest.php +++ b/core/modules/media/tests/src/Functional/Update/MediaUpdateTest.php @@ -62,4 +62,22 @@ class MediaUpdateTest extends UpdatePathTestBase { $this->assertSame('', $config->get('iframe_domain')); } + /** + * Tests that the media entity type has an 'owner' entity key. + * + * @see media_update_8600() + */ + public function testOwnerEntityKey() { + // Check that the 'owner' entity key does not exist prior to the update. + $entity_type = \Drupal::entityDefinitionUpdateManager()->getEntityType('media'); + $this->assertFalse($entity_type->getKey('owner')); + + // Run updates. + $this->runUpdates(); + + // Check that the entity key exists and it has the correct value. + $entity_type = \Drupal::entityDefinitionUpdateManager()->getEntityType('media'); + $this->assertEquals('uid', $entity_type->getKey('owner')); + } + } diff --git a/core/modules/media/tests/src/Kernel/MediaTest.php b/core/modules/media/tests/src/Kernel/MediaTest.php index 9c7ca28eef9..4997bb67fa2 100644 --- a/core/modules/media/tests/src/Kernel/MediaTest.php +++ b/core/modules/media/tests/src/Kernel/MediaTest.php @@ -34,4 +34,14 @@ class MediaTest extends MediaKernelTestBase { $this->assertSame($field_definitions['name']->getDisplayOptions('view'), ['region' => 'hidden']); } + /** + * Tests the legacy method used as the default entity owner. + * + * @group legacy + * @expectedDeprecation The ::getCurrentUserId method is deprecated in 8.6.x and will be removed before 9.0.0. + */ + public function testGetCurrentUserId() { + $this->assertEquals(['1'], Media::getCurrentUserId()); + } + } diff --git a/core/modules/node/node.install b/core/modules/node/node.install index 9b0cda8e567..2463b21646f 100644 --- a/core/modules/node/node.install +++ b/core/modules/node/node.install @@ -267,3 +267,16 @@ function node_update_8401() { node_access_needs_rebuild(TRUE); } } + +/** + * Set the 'owner' entity key and update the field. + */ +function node_update_8600() { + $definition_update_manager = \Drupal::entityDefinitionUpdateManager(); + $entity_type = $definition_update_manager->getEntityType('node'); + $keys = $entity_type->getKeys(); + $keys['owner'] = 'uid'; + $entity_type->set('entity_keys', $keys); + $definition_update_manager->updateEntityType($entity_type); + $definition_update_manager->updateFieldStorageDefinition($definition_update_manager->getFieldStorageDefinition('uid', 'node')); +} diff --git a/core/modules/node/src/Entity/Node.php b/core/modules/node/src/Entity/Node.php index 827c459f724..b3d19d4e89e 100644 --- a/core/modules/node/src/Entity/Node.php +++ b/core/modules/node/src/Entity/Node.php @@ -8,7 +8,7 @@ use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Field\BaseFieldDefinition; use Drupal\Core\Session\AccountInterface; use Drupal\node\NodeInterface; -use Drupal\user\UserInterface; +use Drupal\user\EntityOwnerTrait; /** * Defines the node entity class. @@ -59,6 +59,7 @@ use Drupal\user\UserInterface; * "status" = "status", * "published" = "status", * "uid" = "uid", + * "owner" = "uid", * }, * revision_metadata_keys = { * "revision_user" = "revision_uid", @@ -82,6 +83,8 @@ use Drupal\user\UserInterface; */ class Node extends EditorialContentEntityBase implements NodeInterface { + use EntityOwnerTrait; + /** * Whether the node is being previewed or not. * @@ -250,36 +253,6 @@ class Node extends EditorialContentEntityBase implements NodeInterface { return $this; } - /** - * {@inheritdoc} - */ - public function getOwner() { - return $this->get('uid')->entity; - } - - /** - * {@inheritdoc} - */ - public function getOwnerId() { - return $this->getEntityKey('uid'); - } - - /** - * {@inheritdoc} - */ - public function setOwnerId($uid) { - $this->set('uid', $uid); - return $this; - } - - /** - * {@inheritdoc} - */ - public function setOwner(UserInterface $account) { - $this->set('uid', $account->id()); - return $this; - } - /** * {@inheritdoc} */ @@ -300,6 +273,7 @@ class Node extends EditorialContentEntityBase implements NodeInterface { */ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) { $fields = parent::baseFieldDefinitions($entity_type); + $fields += static::ownerBaseFieldDefinitions($entity_type); $fields['title'] = BaseFieldDefinition::create('string') ->setLabel(t('Title')) @@ -318,13 +292,10 @@ class Node extends EditorialContentEntityBase implements NodeInterface { ]) ->setDisplayConfigurable('form', TRUE); - $fields['uid'] = BaseFieldDefinition::create('entity_reference') + $fields['uid'] ->setLabel(t('Authored by')) ->setDescription(t('The username of the content author.')) ->setRevisionable(TRUE) - ->setSetting('target_type', 'user') - ->setDefaultValueCallback('Drupal\node\Entity\Node::getCurrentUserId') - ->setTranslatable(TRUE) ->setDisplayOptions('view', [ 'label' => 'hidden', 'type' => 'author', @@ -409,10 +380,14 @@ class Node extends EditorialContentEntityBase implements NodeInterface { * * @see ::baseFieldDefinitions() * + * @deprecated The ::getCurrentUserId method is deprecated in 8.6.x and will + * be removed before 9.0.0. + * * @return array * An array of default values. */ public static function getCurrentUserId() { + @trigger_error('The ::getCurrentUserId method is deprecated in 8.6.x and will be removed before 9.0.0.', E_USER_DEPRECATED); return [\Drupal::currentUser()->id()]; } diff --git a/core/modules/node/tests/src/Functional/Update/NodeUpdateTest.php b/core/modules/node/tests/src/Functional/Update/NodeUpdateTest.php index 8f53f9b6280..180215b8fb2 100644 --- a/core/modules/node/tests/src/Functional/Update/NodeUpdateTest.php +++ b/core/modules/node/tests/src/Functional/Update/NodeUpdateTest.php @@ -65,4 +65,22 @@ class NodeUpdateTest extends UpdatePathTestBase { } } + /** + * Tests that the node entity type has an 'owner' entity key. + * + * @see node_update_8600() + */ + public function testOwnerEntityKey() { + // Check that the 'owner' entity key does not exist prior to the update. + $entity_type = \Drupal::entityDefinitionUpdateManager()->getEntityType('node'); + $this->assertFalse($entity_type->getKey('owner')); + + // Run updates. + $this->runUpdates(); + + // Check that the entity key exists and it has the correct value. + $entity_type = \Drupal::entityDefinitionUpdateManager()->getEntityType('node'); + $this->assertEquals('uid', $entity_type->getKey('owner')); + } + } diff --git a/core/modules/node/tests/src/Kernel/NodeFieldOverridesTest.php b/core/modules/node/tests/src/Kernel/NodeFieldOverridesTest.php index 7c7bc033488..1d781c6f560 100644 --- a/core/modules/node/tests/src/Kernel/NodeFieldOverridesTest.php +++ b/core/modules/node/tests/src/Kernel/NodeFieldOverridesTest.php @@ -53,7 +53,7 @@ class NodeFieldOverridesTest extends EntityKernelTestBase { $uid_field = \Drupal::entityManager()->getBaseFieldDefinitions('node')['uid']; $config = $uid_field->getConfig('ponies'); $config->save(); - $this->assertEqual($config->get('default_value_callback'), 'Drupal\node\Entity\Node::getCurrentUserId'); + $this->assertEquals($config->get('default_value_callback'), 'Drupal\node\Entity\Node::getDefaultEntityOwner'); /** @var \Drupal\node\NodeInterface $node */ $node = Node::create(['type' => 'ponies']); $owner = $node->getOwner(); diff --git a/core/modules/node/tests/src/Kernel/NodeOwnerTest.php b/core/modules/node/tests/src/Kernel/NodeOwnerTest.php index c12f3115c16..7d54d98012d 100644 --- a/core/modules/node/tests/src/Kernel/NodeOwnerTest.php +++ b/core/modules/node/tests/src/Kernel/NodeOwnerTest.php @@ -6,6 +6,7 @@ use Drupal\KernelTests\Core\Entity\EntityKernelTestBase; use Drupal\language\Entity\ConfigurableLanguage; use Drupal\node\Entity\Node; use Drupal\node\Entity\NodeType; +use Drupal\user\Entity\User; /** * Tests node owner functionality. @@ -75,4 +76,36 @@ class NodeOwnerTest extends EntityKernelTestBase { $this->assertEqual(0, $italian->getOwnerId()); } + /** + * Test an unsaved node owner. + */ + public function testUnsavedNodeOwner() { + $user = User::create([ + 'name' => 'foo', + ]); + $node = Node::create([ + 'type' => 'page', + 'title' => $this->randomMachineName(), + ]); + // Set the node owner while the user is unsaved and then immediately save + // the user and node. + $node->setOwner($user); + $user->save(); + $node->save(); + + // The ID assigned to the newly saved user will now be the owner ID of the + // node. + $this->assertEquals($user->id(), $node->getOwnerId()); + } + + /** + * Tests the legacy method used as the default entity owner. + * + * @group legacy + * @expectedDeprecation The ::getCurrentUserId method is deprecated in 8.6.x and will be removed before 9.0.0. + */ + public function testGetCurrentUserId() { + $this->assertEquals(['0'], Node::getCurrentUserId()); + } + } diff --git a/core/modules/user/src/EntityOwnerTrait.php b/core/modules/user/src/EntityOwnerTrait.php new file mode 100644 index 00000000000..ad55d0f3dc3 --- /dev/null +++ b/core/modules/user/src/EntityOwnerTrait.php @@ -0,0 +1,90 @@ +getClass(), EntityOwnerInterface::class)) { + throw new UnsupportedEntityTypeDefinitionException('The entity type ' . $entity_type->id() . ' does not implement \Drupal\user\EntityOwnerInterface.'); + } + if (!$entity_type->hasKey('owner')) { + throw new UnsupportedEntityTypeDefinitionException('The entity type ' . $entity_type->id() . ' does not have an "owner" entity key.'); + } + + return [ + $entity_type->getKey('owner') => BaseFieldDefinition::create('entity_reference') + ->setLabel(new TranslatableMarkup('User ID')) + ->setSetting('target_type', 'user') + ->setTranslatable($entity_type->isTranslatable()) + ->setDefaultValueCallback(static::class . '::getDefaultEntityOwner'), + ]; + } + + /** + * {@inheritdoc} + */ + public function getOwnerId() { + return $this->getEntityKey('owner'); + } + + /** + * {@inheritdoc} + */ + public function setOwnerId($uid) { + $key = $this->getEntityType()->getKey('owner'); + $this->set($key, $uid); + + return $this; + } + + /** + * {@inheritdoc} + */ + public function getOwner() { + $key = $this->getEntityType()->getKey('owner'); + return $this->get($key)->entity; + } + + /** + * {@inheritdoc} + */ + public function setOwner(UserInterface $account) { + $key = $this->getEntityType()->getKey('owner'); + $this->set($key, $account); + + return $this; + } + + /** + * Default value callback for 'owner' base field. + * + * @return mixed + * A default value for the owner field. + */ + public static function getDefaultEntityOwner() { + return \Drupal::currentUser()->id(); + } + +}