Issue #2905527 by EclipseGc, amateescu, tim.plunkett, larowlan: Introduce a sample value entity method to ease plugin filtering via context
parent
3b6a05b573
commit
dff09a9d5c
|
@ -79,6 +79,40 @@ abstract class ContentEntityStorageBase extends EntityStorageBase implements Con
|
|||
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.
|
||||
*
|
||||
|
|
|
@ -23,4 +23,21 @@ interface ContentEntityStorageInterface extends EntityStorageInterface {
|
|||
*/
|
||||
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 @@ class KeyValueContentEntityStorage extends KeyValueEntityStorage implements Cont
|
|||
// https://www.drupal.org/node/2618436.
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function createWithSampleValues($bundle = FALSE, array $values = []) {}
|
||||
|
||||
}
|
||||
|
|
|
@ -259,7 +259,7 @@ class FieldItemList extends ItemList implements FieldItemListInterface {
|
|||
*/
|
||||
public function generateSampleItems($count = 1) {
|
||||
$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++) {
|
||||
$values[$delta] = $field_type_class::generateSampleValue($field_definition);
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ use Drupal\Core\Entity\EntityTypeInterface;
|
|||
use Drupal\Core\Field\BaseFieldDefinition;
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
use Drupal\user\RoleInterface;
|
||||
use Drupal\user\TimeZoneItem;
|
||||
use Drupal\user\UserInterface;
|
||||
|
||||
/**
|
||||
|
@ -498,6 +499,7 @@ class User extends ContentEntityBase implements UserInterface {
|
|||
->addPropertyConstraints('value', [
|
||||
'AllowedValues' => ['callback' => __CLASS__ . '::getAllowedTimezones'],
|
||||
]);
|
||||
$fields['timezone']->getItemDefinition()->setClass(TimeZoneItem::class);
|
||||
|
||||
$fields['status'] = BaseFieldDefinition::create('boolean')
|
||||
->setLabel(t('User status'))
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
<?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 @@
|
|||
|
||||
namespace Drupal\user;
|
||||
|
||||
use Drupal\Core\Field\FieldDefinitionInterface;
|
||||
use Drupal\Core\Field\Plugin\Field\FieldType\StringItem;
|
||||
|
||||
/**
|
||||
|
@ -23,4 +24,14 @@ class UserNameItem extends StringItem {
|
|||
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 {
|
|||
*/
|
||||
public static $modules = ['system', 'user', 'field'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->installEntitySchema('user');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests some of the methods.
|
||||
*
|
||||
|
@ -65,4 +73,22 @@ class UserEntityTest extends KernelTestBase {
|
|||
$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());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
<?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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue