Commit dff09a9d authored by larowlan's avatar larowlan

Issue #2905527 by EclipseGc, amateescu, tim.plunkett, larowlan: Introduce a...

Issue #2905527 by EclipseGc, amateescu, tim.plunkett, larowlan: Introduce a sample value entity method to ease plugin filtering via context
parent 3b6a05b5
...@@ -79,6 +79,40 @@ protected function doCreate(array $values) { ...@@ -79,6 +79,40 @@ protected function doCreate(array $values) {
return $entity; return $entity;
} }
/**
* {@inheritdoc}
*/
public function createWithSampleValues($bundle = FALSE, array $values = []) {
// ID and revision should never have sample values generated for them.
$forbidden_keys = [
$this->entityType->getKey('id'),
];
if ($revision_key = $this->entityType->getKey('revision')) {
$forbidden_keys[] = $revision_key;
}
if ($bundle_key = $this->entityType->getKey('bundle')) {
if (!$bundle) {
throw new EntityStorageException("No entity bundle was specified");
}
if (!array_key_exists($bundle, $this->entityManager->getBundleInfo($this->entityTypeId))) {
throw new EntityStorageException(sprintf("Missing entity bundle. The \"%s\" bundle does not exist", $bundle));
}
$values[$bundle_key] = $bundle;
// Bundle is already set
$forbidden_keys[] = $bundle_key;
}
// Forbid sample generation on any keys whose values were submitted.
$forbidden_keys = array_merge($forbidden_keys, array_keys($values));
/** @var \Drupal\Core\Entity\FieldableEntityInterface $entity */
$entity = $this->create($values);
foreach ($entity as $field_name => $value) {
if (!in_array($field_name, $forbidden_keys, TRUE)) {
$entity->get($field_name)->generateSampleItems();
}
}
return $entity;
}
/** /**
* Initializes field values. * Initializes field values.
* *
......
...@@ -23,4 +23,21 @@ interface ContentEntityStorageInterface extends EntityStorageInterface { ...@@ -23,4 +23,21 @@ interface ContentEntityStorageInterface extends EntityStorageInterface {
*/ */
public function createTranslation(ContentEntityInterface $entity, $langcode, array $values = []); public function createTranslation(ContentEntityInterface $entity, $langcode, array $values = []);
/**
* Creates an entity with sample field values.
*
* @param string|bool $bundle
* (optional) The entity bundle.
* @param array $values
* (optional) Any default values to use during generation.
*
* @return \Drupal\Core\Entity\FieldableEntityInterface
* A fieldable content entity.
*
* @throws \Drupal\Core\Entity\EntityStorageException
* Thrown if the bundle does not exist or was needed but not specified.
*/
public function createWithSampleValues($bundle = FALSE, array $values = []);
} }
...@@ -18,4 +18,9 @@ public function createTranslation(ContentEntityInterface $entity, $langcode, arr ...@@ -18,4 +18,9 @@ public function createTranslation(ContentEntityInterface $entity, $langcode, arr
// https://www.drupal.org/node/2618436. // https://www.drupal.org/node/2618436.
} }
/**
* {@inheritdoc}
*/
public function createWithSampleValues($bundle = FALSE, array $values = []) {}
} }
...@@ -259,7 +259,7 @@ public function view($display_options = []) { ...@@ -259,7 +259,7 @@ public function view($display_options = []) {
*/ */
public function generateSampleItems($count = 1) { public function generateSampleItems($count = 1) {
$field_definition = $this->getFieldDefinition(); $field_definition = $this->getFieldDefinition();
$field_type_class = \Drupal::service('plugin.manager.field.field_type')->getPluginClass($field_definition->getType()); $field_type_class = $field_definition->getItemDefinition()->getClass();
for ($delta = 0; $delta < $count; $delta++) { for ($delta = 0; $delta < $count; $delta++) {
$values[$delta] = $field_type_class::generateSampleValue($field_definition); $values[$delta] = $field_type_class::generateSampleValue($field_definition);
} }
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
use Drupal\Core\Field\BaseFieldDefinition; use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\Core\Language\LanguageInterface; use Drupal\Core\Language\LanguageInterface;
use Drupal\user\RoleInterface; use Drupal\user\RoleInterface;
use Drupal\user\TimeZoneItem;
use Drupal\user\UserInterface; use Drupal\user\UserInterface;
/** /**
...@@ -498,6 +499,7 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) { ...@@ -498,6 +499,7 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
->addPropertyConstraints('value', [ ->addPropertyConstraints('value', [
'AllowedValues' => ['callback' => __CLASS__ . '::getAllowedTimezones'], 'AllowedValues' => ['callback' => __CLASS__ . '::getAllowedTimezones'],
]); ]);
$fields['timezone']->getItemDefinition()->setClass(TimeZoneItem::class);
$fields['status'] = BaseFieldDefinition::create('boolean') $fields['status'] = BaseFieldDefinition::create('boolean')
->setLabel(t('User status')) ->setLabel(t('User status'))
......
<?php
namespace Drupal\user;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\Plugin\Field\FieldType\StringItem;
use Drupal\user\Entity\User;
/**
* Defines a custom field item class for the 'timezone' user entity field.
*/
class TimeZoneItem extends StringItem {
/**
* {@inheritdoc}
*/
public static function generateSampleValue(FieldDefinitionInterface $field_definition) {
$timezones = User::getAllowedTimezones();
// We need to vary the selected timezones since we're generating a sample.
$key = rand(0, count($timezones) - 1);
return $timezones[$key];
}
}
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
namespace Drupal\user; namespace Drupal\user;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\Plugin\Field\FieldType\StringItem; use Drupal\Core\Field\Plugin\Field\FieldType\StringItem;
/** /**
...@@ -23,4 +24,14 @@ public function isEmpty() { ...@@ -23,4 +24,14 @@ public function isEmpty() {
return $value === NULL || $value === ''; return $value === NULL || $value === '';
} }
/**
* {@inheritdoc}
*/
public static function generateSampleValue(FieldDefinitionInterface $field_definition) {
$values = parent::generateSampleValue($field_definition);
// User names larger than 60 characters won't pass validation.
$values['value'] = substr($values['value'], 0, UserInterface::USERNAME_MAX_LENGTH);
return $values;
}
} }
...@@ -21,6 +21,14 @@ class UserEntityTest extends KernelTestBase { ...@@ -21,6 +21,14 @@ class UserEntityTest extends KernelTestBase {
*/ */
public static $modules = ['system', 'user', 'field']; public static $modules = ['system', 'user', 'field'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->installEntitySchema('user');
}
/** /**
* Tests some of the methods. * Tests some of the methods.
* *
...@@ -65,4 +73,22 @@ public function testUserMethods() { ...@@ -65,4 +73,22 @@ public function testUserMethods() {
$this->assertEqual([RoleInterface::AUTHENTICATED_ID, 'test_role_two'], $user->getRoles()); $this->assertEqual([RoleInterface::AUTHENTICATED_ID, 'test_role_two'], $user->getRoles());
} }
/**
* Tests that all user fields validate properly.
*
* @see \Drupal\Core\Field\FieldItemListInterface::generateSampleItems
* @see \Drupal\Core\Field\FieldItemInterface::generateSampleValue()
* @see \Drupal\Core\Entity\FieldableEntityInterface::validate()
*/
public function testUserValidation() {
$user = User::create([]);
foreach ($user as $field_name => $field) {
if (!in_array($field_name, ['uid'])) {
$user->$field_name->generateSampleItems();
}
}
$violations = $user->validate();
$this->assertFalse((bool) $violations->count());
}
} }
<?php
namespace Drupal\KernelTests\Core\Entity;
use Drupal\Core\Entity\FieldableEntityInterface;
use Drupal\KernelTests\KernelTestBase;
use Drupal\node\Entity\NodeType;
use Drupal\taxonomy\Entity\Vocabulary;
/**
* Tests the ContentEntityStorageBase::createWithSampleValues method.
*
* @coversDefaultClass \Drupal\Core\Entity\ContentEntityStorageBase
* @group Entity
*/
class CreateSampleEntityTest extends KernelTestBase {
/**
* The entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* {@inheritdoc}
*/
public static $modules = ['system', 'field', 'filter', 'text', 'file', 'user', 'node', 'comment', 'taxonomy'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setup();
$this->installEntitySchema('file');
$this->installEntitySchema('user');
$this->installEntitySchema('node');
$this->installEntitySchema('node_type');
$this->installEntitySchema('file');
$this->installEntitySchema('comment');
$this->installEntitySchema('comment_type');
$this->installEntitySchema('taxonomy_vocabulary');
$this->installEntitySchema('taxonomy_term');
$this->entityTypeManager = $this->container->get('entity_type.manager');
NodeType::create(['type' => 'article', 'name' => 'Article'])->save();
NodeType::create(['type' => 'page', 'name' => 'Page'])->save();
Vocabulary::create(['name' => 'Tags', 'vid' => 'tags'])->save();
}
/**
* Tests sample value content entity creation of all types.
*
* @covers ::createWithSampleValues
*/
public function testSampleValueContentEntity() {
foreach ($this->entityTypeManager->getDefinitions() as $entity_type_id => $definition) {
if ($definition->entityClassImplements(FieldableEntityInterface::class)) {
$label = $definition->getKey('label');
$values = [];
if ($label) {
$title = $this->randomString();
$values[$label] = $title;
}
// Create sample entities with bundles.
if ($bundle_type = $definition->getBundleEntityType()) {
foreach ($this->entityTypeManager->getStorage($bundle_type)->loadMultiple() as $bundle) {
$entity = $this->entityTypeManager->getStorage($entity_type_id)->createWithSampleValues($bundle->id(), $values);
$violations = $entity->validate();
$this->assertCount(0, $violations);
if ($label) {
$this->assertEquals($title, $entity->label());
}
}
}
// Create sample entities without bundles.
else {
$entity = $this->entityTypeManager->getStorage($entity_type_id)->createWithSampleValues(FALSE, $values);
$violations = $entity->validate();
$this->assertCount(0, $violations);
if ($label) {
$this->assertEquals($title, $entity->label());
}
}
}
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment