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 70f9dc9f452071c13cfe4b684162adb24182e455..3d839c270976ee8e59de40c4b45b1b8d79ba598a 100644 --- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php +++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php @@ -4,6 +4,7 @@ use Drupal\Component\Utility\Html; use Drupal\Component\Utility\NestedArray; +use Drupal\Core\Entity\ContentEntityStorageInterface; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Entity\FieldableEntityInterface; @@ -296,6 +297,37 @@ public static function generateSampleValue(FieldDefinitionInterface $field_defin $values['target_id'] = array_rand($referenceable[$group]); return $values; } + + // Attempt to create a sample entity, avoiding recursion. + $entity_storage = \Drupal::entityTypeManager()->getStorage($options['target_type']); + if ($options['target_type'] !== $field_definition->getTargetEntityTypeId() && $entity_storage instanceof ContentEntityStorageInterface) { + $bundle = static::getRandomBundle($entity_type, $options['handler_settings']); + $values['entity'] = $entity_storage->createWithSampleValues($bundle); + return $values; + } + } + + /** + * Gets a bundle for a given entity type and selection options. + * + * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type + * The entity type. + * @param array $selection_settings + * An array of selection settings. + * + * @return string|null + * Either the bundle string, or NULL if there is no bundle. + */ + protected static function getRandomBundle(EntityTypeInterface $entity_type, array $selection_settings) { + if ($bundle_key = $entity_type->getKey('bundle')) { + if (!empty($selection_settings['target_bundles'])) { + $bundle_ids = $selection_settings['target_bundles']; + } + else { + $bundle_ids = \Drupal::service('entity_type.bundle.info')->getBundleInfo($entity_type->id()); + } + return array_rand($bundle_ids); + } } /** diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/LanguageItem.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/LanguageItem.php index 18935c1b8f5b3031f149c4986493701081867be9..1925474e41cc8223420862ac467b0c909df76c65 100644 --- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/LanguageItem.php +++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/LanguageItem.php @@ -2,6 +2,7 @@ namespace Drupal\Core\Field\Plugin\Field\FieldType; +use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Field\FieldStorageDefinitionInterface; use Drupal\Core\Field\FieldItemBase; use Drupal\Core\Language\LanguageInterface; @@ -117,4 +118,20 @@ public function onChange($property_name, $notify = TRUE) { parent::onChange($property_name, $notify); } + /** + * {@inheritdoc} + */ + public static function generateSampleValue(FieldDefinitionInterface $field_definition) { + // Defer to the callback in the item definition as it can be overridden. + $constraint = $field_definition->getItemDefinition()->getConstraint('ComplexData'); + if (isset($constraint['value']['AllowedValues']['callback'])) { + $languages = $constraint['value']['AllowedValues']['callback'](); + } + else { + $languages = static::getAllowedLanguageCodes(); + } + $values['value'] = $languages[array_rand($languages)]; + return $values; + } + } diff --git a/core/modules/aggregator/tests/src/Kernel/Migrate/MigrateAggregatorStubTest.php b/core/modules/aggregator/tests/src/Kernel/Migrate/MigrateAggregatorStubTest.php index 6d96aa1de1d9685b6c39270f75a796d327eabe88..8de1487d0cb62dc4b2049855f959d04766d370ff 100644 --- a/core/modules/aggregator/tests/src/Kernel/Migrate/MigrateAggregatorStubTest.php +++ b/core/modules/aggregator/tests/src/Kernel/Migrate/MigrateAggregatorStubTest.php @@ -2,7 +2,6 @@ namespace Drupal\Tests\aggregator\Kernel\Migrate; -use Drupal\migrate\MigrateException; use Drupal\Tests\migrate_drupal\Kernel\MigrateDrupalTestBase; use Drupal\migrate_drupal\Tests\StubTestTrait; @@ -40,18 +39,6 @@ public function testFeedStub() { * Tests creation of aggregator feed items. */ public function testItemStub() { - try { - // We expect an exception, because there's no feed to reference. - $this->performStubTest('aggregator_item'); - $this->fail('Expected exception has not been thrown.'); - } - catch (MigrateException $e) { - $this->assertIdentical($e->getMessage(), - 'Stubbing failed, unable to generate value for field fid'); - } - - // The stub should pass when there's a feed to point to. - $this->createStub('aggregator_feed'); $this->performStubTest('aggregator_item'); } diff --git a/core/modules/comment/tests/src/Kernel/Migrate/MigrateCommentStubTest.php b/core/modules/comment/tests/src/Kernel/Migrate/MigrateCommentStubTest.php index 0b256ea51a2dfc039cf19840b98862cfd835f31b..3b0674222cd13efb6a3adc7941f76c868ec985a7 100644 --- a/core/modules/comment/tests/src/Kernel/Migrate/MigrateCommentStubTest.php +++ b/core/modules/comment/tests/src/Kernel/Migrate/MigrateCommentStubTest.php @@ -3,7 +3,6 @@ namespace Drupal\Tests\comment\Kernel\Migrate; use Drupal\comment\Entity\CommentType; -use Drupal\migrate\MigrateException; use Drupal\Tests\migrate_drupal\Kernel\MigrateDrupalTestBase; use Drupal\migrate_drupal\Tests\StubTestTrait; use Drupal\node\Entity\NodeType; @@ -29,6 +28,8 @@ protected function setUp() { parent::setUp(); $this->installEntitySchema('comment'); $this->installEntitySchema('node'); + $this->installSchema('system', ['sequences']); + // Make sure uid 0 is created (default uid for comments is 0). $storage = \Drupal::entityManager()->getStorage('user'); // Insert a row for the anonymous user. @@ -55,18 +56,6 @@ protected function setUp() { * Tests creation of comment stubs. */ public function testStub() { - try { - // We expect an exception, because there's no node to reference. - $this->performStubTest('comment'); - $this->fail('Expected exception has not been thrown.'); - } - catch (MigrateException $e) { - $this->assertIdentical($e->getMessage(), - 'Stubbing failed, unable to generate value for field entity_id'); - } - - // The stub should pass when there's a node to point to. - $this->createStub('node'); $this->performStubTest('comment'); } diff --git a/core/modules/field/tests/src/Kernel/EntityReference/EntityReferenceItemTest.php b/core/modules/field/tests/src/Kernel/EntityReference/EntityReferenceItemTest.php index 391d8db065e3324250d7c83e3cb1f9abe9f22e7e..c0e58e04e9e5917a20001014862f9b2d032e7990 100644 --- a/core/modules/field/tests/src/Kernel/EntityReference/EntityReferenceItemTest.php +++ b/core/modules/field/tests/src/Kernel/EntityReference/EntityReferenceItemTest.php @@ -16,6 +16,7 @@ use Drupal\field\Entity\FieldStorageConfig; use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait; use Drupal\node\NodeInterface; +use Drupal\taxonomy\TermInterface; use Drupal\Tests\field\Kernel\FieldKernelTestBase; use Drupal\file\Entity\File; use Drupal\node\Entity\Node; @@ -193,6 +194,24 @@ public function testContentEntityReferenceItem() { $entity = EntityTest::create(['user_id' => ['target_id' => (int) $user->id(), 'entity' => $user]]); } + /** + * Tests the ::generateSampleValue() method. + */ + public function testGenerateSampleValue() { + $entity = EntityTest::create(); + + // Test while a term exists. + $entity->field_test_taxonomy_term->generateSampleItems(); + $this->assertInstanceOf(TermInterface::class, $entity->field_test_taxonomy_term->entity); + $this->entityValidateAndSave($entity); + + // Delete the term and test again. + $this->term->delete(); + $entity->field_test_taxonomy_term->generateSampleItems(); + $this->assertInstanceOf(TermInterface::class, $entity->field_test_taxonomy_term->entity); + $this->entityValidateAndSave($entity); + } + /** * Tests referencing content entities with string IDs. */ diff --git a/core/modules/user/src/Entity/User.php b/core/modules/user/src/Entity/User.php index f254ccff9377326ed21b6036073b3ce5dfdbc0af..54439cff9323894dc98e05655ea5043d58a5766b 100644 --- a/core/modules/user/src/Entity/User.php +++ b/core/modules/user/src/Entity/User.php @@ -9,6 +9,7 @@ use Drupal\Core\Field\BaseFieldDefinition; use Drupal\Core\Language\LanguageInterface; use Drupal\user\RoleInterface; +use Drupal\user\StatusItem; use Drupal\user\TimeZoneItem; use Drupal\user\UserInterface; @@ -505,6 +506,7 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) { ->setLabel(t('User status')) ->setDescription(t('Whether the user is active or blocked.')) ->setDefaultValue(FALSE); + $fields['status']->getItemDefinition()->setClass(StatusItem::class); $fields['created'] = BaseFieldDefinition::create('created') ->setLabel(t('Created')) diff --git a/core/modules/user/src/StatusItem.php b/core/modules/user/src/StatusItem.php new file mode 100644 index 0000000000000000000000000000000000000000..76c2117ffa074f77c5021fd9158cf65f8a13f7c9 --- /dev/null +++ b/core/modules/user/src/StatusItem.php @@ -0,0 +1,25 @@ +<?php + +namespace Drupal\user; + +use Drupal\Core\Field\FieldDefinitionInterface; +use Drupal\Core\Field\Plugin\Field\FieldType\BooleanItem; + +/** + * Defines the 'status' entity field type. + * + * @todo Consider making this a full field type plugin in + * https://www.drupal.org/project/drupal/issues/2936864. + */ +class StatusItem extends BooleanItem { + + /** + * {@inheritdoc} + */ + public static function generateSampleValue(FieldDefinitionInterface $field_definition) { + // Always generate a sample with an enabled status. + $values['value'] = 1; + return $values; + } + +}