Issue #2905527 by EclipseGc, amateescu, tim.plunkett, larowlan: Introduce a sample value entity method to ease plugin filtering via context

8.5.x
Lee Rowlands 2017-09-21 07:36:14 +10:00
parent 3b6a05b573
commit dff09a9d5c
No known key found for this signature in database
GPG Key ID: 2B829A3DF9204DC4
9 changed files with 209 additions and 1 deletions

View File

@ -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.
*

View File

@ -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 = []);
}

View File

@ -18,4 +18,9 @@ class KeyValueContentEntityStorage extends KeyValueEntityStorage implements Cont
// https://www.drupal.org/node/2618436.
}
/**
* {@inheritdoc}
*/
public function createWithSampleValues($bundle = FALSE, array $values = []) {}
}

View File

@ -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);
}

View File

@ -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'))

View File

@ -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];
}
}

View File

@ -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;
}
}

View File

@ -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());
}
}

View File

@ -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());
}
}
}
}
}
}