Issue #3324150 by phenaproxima, Wim Leers, Gábor Hojtsy: Add validation constraints to config_entity.dependencies
parent
22a56817e0
commit
adfa35d41f
|
@ -240,6 +240,9 @@ config_dependencies_base:
|
|||
label: 'Configuration entity dependencies'
|
||||
sequence:
|
||||
type: string
|
||||
constraints:
|
||||
NotBlank: []
|
||||
ConfigExists: []
|
||||
content:
|
||||
type: sequence
|
||||
label: 'Content entity dependencies'
|
||||
|
@ -250,11 +253,21 @@ config_dependencies_base:
|
|||
label: 'Module dependencies'
|
||||
sequence:
|
||||
type: string
|
||||
constraints:
|
||||
NotBlank: []
|
||||
ExtensionName: []
|
||||
ExtensionExists: module
|
||||
theme:
|
||||
type: sequence
|
||||
label: 'Theme dependencies'
|
||||
sequence:
|
||||
type: string
|
||||
constraints:
|
||||
NotBlank: []
|
||||
ExtensionName: []
|
||||
ExtensionExists: theme
|
||||
constraints:
|
||||
ValidKeys: '<infer>'
|
||||
|
||||
config_dependencies:
|
||||
type: config_dependencies_base
|
||||
|
@ -263,6 +276,8 @@ config_dependencies:
|
|||
enforced:
|
||||
type: config_dependencies_base
|
||||
label: 'Enforced configuration dependencies'
|
||||
constraints:
|
||||
ValidKeys: '<infer>'
|
||||
|
||||
config_entity:
|
||||
type: mapping
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace Drupal\Core\Config\Plugin\Validation\Constraint;
|
||||
|
||||
use Symfony\Component\Validator\Constraint;
|
||||
|
||||
/**
|
||||
* Checks that the value is the name of an existing config object.
|
||||
*
|
||||
* @Constraint(
|
||||
* id = "ConfigExists",
|
||||
* label = @Translation("Config exists", context = "Validation")
|
||||
* )
|
||||
*/
|
||||
class ConfigExistsConstraint extends Constraint {
|
||||
|
||||
/**
|
||||
* The error message.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public string $message = "The '@name' config does not exist.";
|
||||
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace Drupal\Core\Config\Plugin\Validation\Constraint;
|
||||
|
||||
use Drupal\Core\Config\ConfigFactoryInterface;
|
||||
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\Validator\Constraint;
|
||||
use Symfony\Component\Validator\ConstraintValidator;
|
||||
|
||||
/**
|
||||
* Validates that a given config object exists.
|
||||
*/
|
||||
class ConfigExistsConstraintValidator extends ConstraintValidator implements ContainerInjectionInterface {
|
||||
|
||||
/**
|
||||
* The config factory service.
|
||||
*
|
||||
* @var \Drupal\Core\Config\ConfigFactoryInterface
|
||||
*/
|
||||
protected ConfigFactoryInterface $configFactory;
|
||||
|
||||
/**
|
||||
* Constructs a ConfigExistsConstraintValidator object.
|
||||
*
|
||||
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
|
||||
* The config factory service.
|
||||
*/
|
||||
public function __construct(ConfigFactoryInterface $config_factory) {
|
||||
$this->configFactory = $config_factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static($container->get('config.factory'));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validate(mixed $name, Constraint $constraint) {
|
||||
if (!in_array($name, $this->configFactory->listAll(), TRUE)) {
|
||||
$this->context->addViolation($constraint->message, ['@name' => $name]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace Drupal\Core\Config\Plugin\Validation\Constraint;
|
||||
|
||||
use Symfony\Component\Validator\Constraint;
|
||||
|
||||
/**
|
||||
* Checks that config dependencies contain specific types of entities.
|
||||
*
|
||||
* @Constraint(
|
||||
* id = "RequiredConfigDependencies",
|
||||
* label = @Translation("Required config dependency types", context = "Validation")
|
||||
* )
|
||||
*/
|
||||
class RequiredConfigDependenciesConstraint extends Constraint {
|
||||
|
||||
/**
|
||||
* The error message.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public string $message = 'This @entity_type requires a @dependency_type.';
|
||||
|
||||
/**
|
||||
* The IDs of entity types that need to exist in config dependencies.
|
||||
*
|
||||
* For example, if an entity requires a filter format in its config
|
||||
* dependencies, this should contain `filter_format`.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
public array $entityTypes = [];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getRequiredOptions() {
|
||||
return ['entityTypes'];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDefaultOption() {
|
||||
return 'entityTypes';
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace Drupal\Core\Config\Plugin\Validation\Constraint;
|
||||
|
||||
use Drupal\Core\Config\Entity\ConfigEntityInterface;
|
||||
use Drupal\Core\Config\Entity\ConfigEntityTypeInterface;
|
||||
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\Validator\Constraint;
|
||||
use Symfony\Component\Validator\ConstraintValidator;
|
||||
use Symfony\Component\Validator\Exception\LogicException;
|
||||
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
|
||||
|
||||
/**
|
||||
* Validates the RequiredConfigDependencies constraint.
|
||||
*/
|
||||
class RequiredConfigDependenciesConstraintValidator extends ConstraintValidator implements ContainerInjectionInterface {
|
||||
|
||||
/**
|
||||
* The entity type manager service.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
|
||||
*/
|
||||
protected EntityTypeManagerInterface $entityTypeManager;
|
||||
|
||||
/**
|
||||
* Constructs a RequiredConfigDependenciesConstraintValidator object.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
|
||||
* The entity type manager service.
|
||||
*/
|
||||
public function __construct(EntityTypeManagerInterface $entity_type_manager) {
|
||||
$this->entityTypeManager = $entity_type_manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static(
|
||||
$container->get('entity_type.manager')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validate(mixed $entity, Constraint $constraint) {
|
||||
assert($constraint instanceof RequiredConfigDependenciesConstraint);
|
||||
|
||||
// Only config entities can have config dependencies.
|
||||
if (!$entity instanceof ConfigEntityInterface) {
|
||||
throw new UnexpectedTypeException($entity, ConfigEntityInterface::class);
|
||||
}
|
||||
|
||||
$config_dependencies = $entity->getDependencies()['config'] ?? [];
|
||||
|
||||
foreach ($constraint->entityTypes as $entity_type_id) {
|
||||
$entity_type = $this->entityTypeManager->getDefinition($entity_type_id);
|
||||
|
||||
if (!$entity_type instanceof ConfigEntityTypeInterface) {
|
||||
throw new LogicException("'$entity_type_id' is not a config entity type.");
|
||||
}
|
||||
|
||||
// Ensure the current entity type's config prefix is found in the config
|
||||
// dependencies of the entity being validated.
|
||||
$pattern = sprintf('/^%s\\.\\w+/', $entity_type->getConfigPrefix());
|
||||
if (!preg_grep($pattern, $config_dependencies)) {
|
||||
$this->context->addViolation($constraint->message, [
|
||||
'@entity_type' => $entity->getEntityType()->getSingularLabel(),
|
||||
'@dependency_type' => $entity_type->getSingularLabel(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace Drupal\Core\Extension\Plugin\Validation\Constraint;
|
||||
|
||||
use Symfony\Component\Validator\Constraint;
|
||||
|
||||
/**
|
||||
* Checks that the value is the name of an installed extension.
|
||||
*
|
||||
* @Constraint(
|
||||
* id = "ExtensionExists",
|
||||
* label = @Translation("Extension exists", context = "Validation")
|
||||
* )
|
||||
*/
|
||||
class ExtensionExistsConstraint extends Constraint {
|
||||
|
||||
/**
|
||||
* The error message for a non-existent module.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public string $moduleMessage = "Module '@name' is not installed.";
|
||||
|
||||
/**
|
||||
* The error message for a non-existent theme.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public string $themeMessage = "Theme '@name' is not installed.";
|
||||
|
||||
/**
|
||||
* The type of extension to look for. Can be 'module' or 'theme'.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public string $type;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getRequiredOptions() {
|
||||
return ['type'];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDefaultOption() {
|
||||
return 'type';
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace Drupal\Core\Extension\Plugin\Validation\Constraint;
|
||||
|
||||
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
|
||||
use Drupal\Core\Extension\ModuleHandlerInterface;
|
||||
use Drupal\Core\Extension\ThemeHandlerInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\Validator\Constraint;
|
||||
use Symfony\Component\Validator\ConstraintValidator;
|
||||
|
||||
/**
|
||||
* Validates that a given extension exists.
|
||||
*/
|
||||
class ExtensionExistsConstraintValidator extends ConstraintValidator implements ContainerInjectionInterface {
|
||||
|
||||
/**
|
||||
* The module handler service.
|
||||
*
|
||||
* @var \Drupal\Core\Extension\ModuleHandlerInterface
|
||||
*/
|
||||
protected ModuleHandlerInterface $moduleHandler;
|
||||
|
||||
/**
|
||||
* The theme handler service.
|
||||
*
|
||||
* @var \Drupal\Core\Extension\ThemeHandlerInterface
|
||||
*/
|
||||
protected ThemeHandlerInterface $themeHandler;
|
||||
|
||||
/**
|
||||
* Constructs a ExtensionExistsConstraintValidator object.
|
||||
*
|
||||
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
|
||||
* The module handler service.
|
||||
* @param \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler
|
||||
* The theme handler service.
|
||||
*/
|
||||
public function __construct(ModuleHandlerInterface $module_handler, ThemeHandlerInterface $theme_handler) {
|
||||
$this->moduleHandler = $module_handler;
|
||||
$this->themeHandler = $theme_handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static(
|
||||
$container->get('module_handler'),
|
||||
$container->get('theme_handler')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validate(mixed $extension_name, Constraint $constraint) {
|
||||
$variables = ['@name' => $extension_name];
|
||||
|
||||
switch ($constraint->type) {
|
||||
case 'module':
|
||||
if (!$this->moduleHandler->moduleExists($extension_name)) {
|
||||
$this->context->addViolation($constraint->moduleMessage, $variables);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'theme':
|
||||
if (!$this->themeHandler->themeExists($extension_name)) {
|
||||
$this->context->addViolation($constraint->themeMessage, $variables);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new \InvalidArgumentException("Unknown extension type: '$constraint->type'");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace Drupal\Core\Extension\Plugin\Validation\Constraint;
|
||||
|
||||
use Drupal\Core\Extension\ExtensionDiscovery;
|
||||
use Drupal\Core\Validation\Plugin\Validation\Constraint\RegexConstraint;
|
||||
|
||||
/**
|
||||
* Checks that the value is a valid extension name.
|
||||
*
|
||||
* @Constraint(
|
||||
* id = "ExtensionName",
|
||||
* label = @Translation("Valid extension name", context = "Validation")
|
||||
* )
|
||||
*/
|
||||
class ExtensionNameConstraint extends RegexConstraint {
|
||||
|
||||
/**
|
||||
* Constructs an ExtensionNameConstraint object.
|
||||
*
|
||||
* @param string|array|null $pattern
|
||||
* The regular expression to test for.
|
||||
* @param mixed ...$arguments
|
||||
* Arguments to pass to the parent constructor.
|
||||
*/
|
||||
public function __construct(string|array|null $pattern, ...$arguments) {
|
||||
// Always use the regular expression that ExtensionDiscovery uses to find
|
||||
// valid extensions.
|
||||
$pattern = ExtensionDiscovery::PHP_FUNCTION_PATTERN;
|
||||
parent::__construct($pattern, ...$arguments);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace Drupal\Core\Validation\Plugin\Validation\Constraint;
|
||||
|
||||
use Drupal\Core\Config\Schema\Mapping;
|
||||
use Drupal\Core\TypedData\MapDataDefinition;
|
||||
use Symfony\Component\Validator\Constraint;
|
||||
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||
use Symfony\Component\Validator\Exception\InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* Checks that all the keys of a mapping are known.
|
||||
*
|
||||
* @Constraint(
|
||||
* id = "ValidKeys",
|
||||
* label = @Translation("Valid mapping keys", context = "Validation"),
|
||||
* )
|
||||
*/
|
||||
class ValidKeysConstraint extends Constraint {
|
||||
|
||||
/**
|
||||
* The error message if an invalid key appears.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public string $invalidKeyMessage = "'@key' is not a supported key.";
|
||||
|
||||
/**
|
||||
* The error message if the array being validated is a list.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public string $indexedArrayMessage = 'Numerically indexed arrays are not allowed.';
|
||||
|
||||
/**
|
||||
* Keys which are allowed in the validated array, or `<infer>` to auto-detect.
|
||||
*
|
||||
* @var array|string
|
||||
*/
|
||||
public array|string $allowedKeys;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDefaultOption() {
|
||||
return 'allowedKeys';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getRequiredOptions() {
|
||||
return ['allowedKeys'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of valid keys.
|
||||
*
|
||||
* @param \Symfony\Component\Validator\Context\ExecutionContextInterface $context
|
||||
* The current execution context.
|
||||
*
|
||||
* @return string[]
|
||||
* The keys that will be considered valid.
|
||||
*/
|
||||
public function getAllowedKeys(ExecutionContextInterface $context): array {
|
||||
// If we were given an explicit array of allowed keys, return that.
|
||||
if (is_array($this->allowedKeys)) {
|
||||
return $this->allowedKeys;
|
||||
}
|
||||
// The only other value we'll accept is the string `<infer>`.
|
||||
elseif ($this->allowedKeys === '<infer>') {
|
||||
return static::inferKeys($context->getObject());
|
||||
}
|
||||
throw new InvalidArgumentException("'$this->allowedKeys' is not a valid set of allowed keys.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to auto-detect the schema-defined keys in a mapping.
|
||||
*
|
||||
* @param \Drupal\Core\Config\Schema\Mapping $mapping
|
||||
* The mapping to inspect.
|
||||
*
|
||||
* @return string[]
|
||||
* The keys defined in the mapping's schema.
|
||||
*/
|
||||
protected static function inferKeys(Mapping $mapping): array {
|
||||
$definition = $mapping->getDataDefinition();
|
||||
assert($definition instanceof MapDataDefinition);
|
||||
|
||||
$definition = $definition->toArray();
|
||||
assert(array_key_exists('mapping', $definition));
|
||||
return array_keys($definition['mapping']);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace Drupal\Core\Validation\Plugin\Validation\Constraint;
|
||||
|
||||
use Symfony\Component\Validator\Constraint;
|
||||
use Symfony\Component\Validator\ConstraintValidator;
|
||||
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
|
||||
|
||||
/**
|
||||
* Validates the ValidKeys constraint.
|
||||
*/
|
||||
class ValidKeysConstraintValidator extends ConstraintValidator {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validate(mixed $value, Constraint $constraint) {
|
||||
assert($constraint instanceof ValidKeysConstraint);
|
||||
|
||||
if (!is_array($value)) {
|
||||
throw new UnexpectedTypeException($value, 'array');
|
||||
}
|
||||
|
||||
// Indexed arrays are invalid by definition. array_is_list() returns TRUE
|
||||
// for empty arrays, so only do this check if $value is not empty.
|
||||
if ($value && array_is_list($value)) {
|
||||
$this->context->addViolation($constraint->indexedArrayMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
$invalid_keys = array_diff(
|
||||
array_keys($value),
|
||||
$constraint->getAllowedKeys($this->context)
|
||||
);
|
||||
foreach ($invalid_keys as $key) {
|
||||
$this->context->addViolation($constraint->invalidKeyMessage, ['@key' => $key]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\block_content\Kernel;
|
||||
|
||||
use Drupal\block_content\Entity\BlockContentType;
|
||||
use Drupal\KernelTests\Core\Config\ConfigEntityValidationTestBase;
|
||||
|
||||
/**
|
||||
* Tests validation of block_content_type entities.
|
||||
*
|
||||
* @group block_content
|
||||
*/
|
||||
class BlockContentTypeValidationTest extends ConfigEntityValidationTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['block_content'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
$this->entity = BlockContentType::create([
|
||||
'id' => 'test',
|
||||
'label' => 'Test',
|
||||
]);
|
||||
$this->entity->save();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\comment\Kernel;
|
||||
|
||||
use Drupal\comment\Entity\CommentType;
|
||||
use Drupal\KernelTests\Core\Config\ConfigEntityValidationTestBase;
|
||||
|
||||
/**
|
||||
* Tests validation of comment_type entities.
|
||||
*
|
||||
* @group comment
|
||||
*/
|
||||
class CommentTypeValidationTest extends ConfigEntityValidationTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['comment', 'node'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
$this->entity = CommentType::create([
|
||||
'id' => 'test',
|
||||
'label' => 'Test',
|
||||
'target_entity_type_id' => 'node',
|
||||
]);
|
||||
$this->entity->save();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\contact\Kernel;
|
||||
|
||||
use Drupal\contact\Entity\ContactForm;
|
||||
use Drupal\KernelTests\Core\Config\ConfigEntityValidationTestBase;
|
||||
|
||||
/**
|
||||
* Tests validation of contact_form entities.
|
||||
*
|
||||
* @group contact
|
||||
*/
|
||||
class ContactFormValidationTest extends ConfigEntityValidationTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['contact', 'user'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
$this->entity = ContactForm::create([
|
||||
'id' => 'test',
|
||||
'label' => 'Test',
|
||||
]);
|
||||
$this->entity->save();
|
||||
}
|
||||
|
||||
}
|
|
@ -30,6 +30,11 @@ use Drupal\editor\EditorInterface;
|
|||
* "editor",
|
||||
* "settings",
|
||||
* "image_upload",
|
||||
* },
|
||||
* constraints = {
|
||||
* "RequiredConfigDependencies" = {
|
||||
* "filter_format"
|
||||
* }
|
||||
* }
|
||||
* )
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\editor\Kernel;
|
||||
|
||||
use Drupal\editor\Entity\Editor;
|
||||
use Drupal\filter\Entity\FilterFormat;
|
||||
use Drupal\KernelTests\Core\Config\ConfigEntityValidationTestBase;
|
||||
|
||||
/**
|
||||
* Tests validation of editor entities.
|
||||
*
|
||||
* @group editor
|
||||
*/
|
||||
class EditorValidationTest extends ConfigEntityValidationTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['editor', 'editor_test', 'filter'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
$format = FilterFormat::create([
|
||||
'format' => 'test',
|
||||
'name' => 'Test',
|
||||
]);
|
||||
$format->save();
|
||||
|
||||
$this->entity = Editor::create([
|
||||
'format' => $format->id(),
|
||||
'editor' => 'unicorn',
|
||||
]);
|
||||
$this->entity->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that validation fails if config dependencies are invalid.
|
||||
*/
|
||||
public function testInvalidDependencies(): void {
|
||||
// Remove the config dependencies from the editor entity.
|
||||
$dependencies = $this->entity->getDependencies();
|
||||
$dependencies['config'] = [];
|
||||
$this->entity->set('dependencies', $dependencies);
|
||||
|
||||
$this->assertValidationErrors(['This text editor requires a text format.']);
|
||||
|
||||
// Things look sort-of like `filter.format.*` should fail validation
|
||||
// because they don't exist.
|
||||
$dependencies['config'] = [
|
||||
'filter.format',
|
||||
'filter.format.',
|
||||
];
|
||||
$this->entity->set('dependencies', $dependencies);
|
||||
$this->assertValidationErrors([
|
||||
'This text editor requires a text format.',
|
||||
"The 'filter.format' config does not exist.",
|
||||
"The 'filter.format.' config does not exist.",
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
|
@ -44,6 +44,11 @@ use Drupal\field\FieldConfigInterface;
|
|||
* "default_value_callback",
|
||||
* "settings",
|
||||
* "field_type",
|
||||
* },
|
||||
* constraints = {
|
||||
* "RequiredConfigDependencies" = {
|
||||
* "field_storage_config"
|
||||
* }
|
||||
* }
|
||||
* )
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\field\Kernel\Entity;
|
||||
|
||||
use Drupal\field\Entity\FieldConfig;
|
||||
|
||||
/**
|
||||
* Tests validation of field_config entities.
|
||||
*
|
||||
* @group field
|
||||
*/
|
||||
class FieldConfigValidationTest extends FieldStorageConfigValidationTest {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
// The field storage was created in the parent method.
|
||||
$field_storage = $this->entity;
|
||||
|
||||
$this->entity = FieldConfig::create([
|
||||
'field_storage' => $field_storage,
|
||||
'bundle' => 'user',
|
||||
]);
|
||||
$this->entity->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that validation fails if config dependencies are invalid.
|
||||
*/
|
||||
public function testInvalidDependencies(): void {
|
||||
// Remove the config dependencies from the field entity.
|
||||
$dependencies = $this->entity->getDependencies();
|
||||
$dependencies['config'] = [];
|
||||
$this->entity->set('dependencies', $dependencies);
|
||||
|
||||
$this->assertValidationErrors(['This field requires a field storage.']);
|
||||
|
||||
// Things look sort-of like `field.storage.*.*` should fail validation
|
||||
// because they don't exist.
|
||||
$dependencies['config'] = [
|
||||
'field.storage.fake',
|
||||
'field.storage.',
|
||||
'field.storage.user.',
|
||||
];
|
||||
$this->entity->set('dependencies', $dependencies);
|
||||
$this->assertValidationErrors([
|
||||
"The 'field.storage.fake' config does not exist.",
|
||||
"The 'field.storage.' config does not exist.",
|
||||
"The 'field.storage.user.' config does not exist.",
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\field\Kernel\Entity;
|
||||
|
||||
use Drupal\field\Entity\FieldStorageConfig;
|
||||
use Drupal\KernelTests\Core\Config\ConfigEntityValidationTestBase;
|
||||
|
||||
/**
|
||||
* Tests validation of field_storage_config entities.
|
||||
*
|
||||
* @group field
|
||||
*/
|
||||
class FieldStorageConfigValidationTest extends ConfigEntityValidationTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['field', 'user'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
$this->entity = FieldStorageConfig::create([
|
||||
'type' => 'boolean',
|
||||
'field_name' => 'test',
|
||||
'entity_type' => 'user',
|
||||
]);
|
||||
$this->entity->save();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\filter\Kernel;
|
||||
|
||||
use Drupal\filter\Entity\FilterFormat;
|
||||
use Drupal\KernelTests\Core\Config\ConfigEntityValidationTestBase;
|
||||
|
||||
/**
|
||||
* Tests validation of filter_format entities.
|
||||
*
|
||||
* @group filter
|
||||
*/
|
||||
class FilterFormatValidationTest extends ConfigEntityValidationTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['filter'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
$this->entity = FilterFormat::create([
|
||||
'format' => 'test',
|
||||
'name' => 'Test',
|
||||
]);
|
||||
$this->entity->save();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\image\Kernel;
|
||||
|
||||
use Drupal\image\Entity\ImageStyle;
|
||||
use Drupal\KernelTests\Core\Config\ConfigEntityValidationTestBase;
|
||||
|
||||
/**
|
||||
* Tests validation of image_style entities.
|
||||
*
|
||||
* @group image
|
||||
*/
|
||||
class ImageStyleValidationTest extends ConfigEntityValidationTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['image'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
$this->entity = ImageStyle::create([
|
||||
'name' => 'test',
|
||||
'label' => 'Test',
|
||||
]);
|
||||
$this->entity->save();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\language\Kernel;
|
||||
|
||||
use Drupal\KernelTests\Core\Config\ConfigEntityValidationTestBase;
|
||||
use Drupal\language\Entity\ConfigurableLanguage;
|
||||
|
||||
/**
|
||||
* Tests validation of configurable_language entities.
|
||||
*
|
||||
* @group language
|
||||
*/
|
||||
class ConfigurableLanguageValidationTest extends ConfigEntityValidationTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['language'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
$this->entity = ConfigurableLanguage::createFromLangcode('fr');
|
||||
$this->entity->save();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\language\Kernel;
|
||||
|
||||
use Drupal\KernelTests\Core\Config\ConfigEntityValidationTestBase;
|
||||
use Drupal\language\Entity\ContentLanguageSettings;
|
||||
|
||||
/**
|
||||
* Tests validation of content_language_settings entities.
|
||||
*
|
||||
* @group language
|
||||
*/
|
||||
class ContentLanguageSettingsValidationTest extends ConfigEntityValidationTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['language', 'user'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
$this->entity = ContentLanguageSettings::create([
|
||||
'target_entity_type_id' => 'user',
|
||||
'target_bundle' => 'user',
|
||||
]);
|
||||
$this->entity->save();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\layout_builder\Kernel;
|
||||
|
||||
use Drupal\Core\Entity\Entity\EntityViewMode;
|
||||
use Drupal\KernelTests\Core\Config\ConfigEntityValidationTestBase;
|
||||
use Drupal\layout_builder\Entity\LayoutBuilderEntityViewDisplay;
|
||||
|
||||
/**
|
||||
* Tests validation of Layout Builder's entity_view_display entities.
|
||||
*
|
||||
* @group layout_builder
|
||||
*/
|
||||
class LayoutBuilderEntityViewDisplayValidationTest extends ConfigEntityValidationTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['layout_builder', 'user'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
EntityViewMode::create([
|
||||
'id' => 'user.layout',
|
||||
'label' => 'Layout',
|
||||
'targetEntityType' => 'user',
|
||||
])->save();
|
||||
|
||||
$this->entity = LayoutBuilderEntityViewDisplay::create([
|
||||
'mode' => 'layout',
|
||||
'label' => 'Layout',
|
||||
'targetEntityType' => 'user',
|
||||
'bundle' => 'user',
|
||||
]);
|
||||
$this->entity->save();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\media\Kernel;
|
||||
|
||||
use Drupal\KernelTests\Core\Config\ConfigEntityValidationTestBase;
|
||||
use Drupal\Tests\media\Traits\MediaTypeCreationTrait;
|
||||
|
||||
/**
|
||||
* Tests validation of media_type entities.
|
||||
*
|
||||
* @group media
|
||||
*/
|
||||
class MediaTypeValidationTest extends ConfigEntityValidationTestBase {
|
||||
|
||||
use MediaTypeCreationTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['field', 'media', 'media_test_source'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
$this->entity = $this->createMediaType('test');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\node\Kernel;
|
||||
|
||||
use Drupal\KernelTests\Core\Config\ConfigEntityValidationTestBase;
|
||||
use Drupal\Tests\node\Traits\ContentTypeCreationTrait;
|
||||
|
||||
/**
|
||||
* Tests validation of node_type entities.
|
||||
*
|
||||
* @group node
|
||||
*/
|
||||
class NodeTypeValidationTest extends ConfigEntityValidationTestBase {
|
||||
|
||||
use ContentTypeCreationTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['field', 'node', 'text', 'user'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
$this->installConfig('node');
|
||||
$this->entity = $this->createContentType();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\responsive_image\Kernel;
|
||||
|
||||
use Drupal\KernelTests\Core\Config\ConfigEntityValidationTestBase;
|
||||
use Drupal\responsive_image\Entity\ResponsiveImageStyle;
|
||||
|
||||
/**
|
||||
* Tests validation of responsive_image_style entities.
|
||||
*
|
||||
* @group responsive_image
|
||||
*/
|
||||
class ResponsiveImageStyleValidationTest extends ConfigEntityValidationTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['breakpoint', 'image', 'responsive_image'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
$this->entity = ResponsiveImageStyle::create([
|
||||
'id' => 'test',
|
||||
'label' => 'Test',
|
||||
]);
|
||||
$this->entity->save();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Kernel\Entity;
|
||||
|
||||
use Drupal\KernelTests\Core\Config\ConfigEntityValidationTestBase;
|
||||
use Drupal\rest\Entity\RestResourceConfig;
|
||||
use Drupal\rest\RestResourceConfigInterface;
|
||||
|
||||
/**
|
||||
* Tests validation of rest_resource_config entities.
|
||||
*
|
||||
* @group rest
|
||||
*/
|
||||
class RestResourceConfigValidationTest extends ConfigEntityValidationTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['rest', 'serialization'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
$this->entity = RestResourceConfig::create([
|
||||
'id' => 'test',
|
||||
'plugin_id' => 'entity:date_format',
|
||||
'granularity' => RestResourceConfigInterface::METHOD_GRANULARITY,
|
||||
'configuration' => [],
|
||||
]);
|
||||
$this->entity->save();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\search\Kernel;
|
||||
|
||||
use Drupal\KernelTests\Core\Config\ConfigEntityValidationTestBase;
|
||||
use Drupal\search\Entity\SearchPage;
|
||||
|
||||
/**
|
||||
* Tests validation of search_page entities.
|
||||
*
|
||||
* @group search
|
||||
*/
|
||||
class SearchPageValidationTest extends ConfigEntityValidationTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['search', 'user'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
$this->entity = SearchPage::create([
|
||||
'id' => 'test',
|
||||
'label' => 'Test',
|
||||
'plugin' => 'user_search',
|
||||
]);
|
||||
$this->entity->save();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\shortcut\Kernel;
|
||||
|
||||
use Drupal\KernelTests\Core\Config\ConfigEntityValidationTestBase;
|
||||
use Drupal\shortcut\Entity\ShortcutSet;
|
||||
|
||||
/**
|
||||
* Tests validation of shortcut_set entities.
|
||||
*
|
||||
* @group shortcut
|
||||
*/
|
||||
class ShortcutSetValidationTest extends ConfigEntityValidationTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['link', 'shortcut'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
$this->installConfig('shortcut');
|
||||
$this->installEntitySchema('shortcut');
|
||||
|
||||
$this->entity = ShortcutSet::create([
|
||||
'id' => 'test',
|
||||
'label' => 'Test',
|
||||
]);
|
||||
$this->entity->save();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\system\Kernel\Entity;
|
||||
|
||||
use Drupal\KernelTests\Core\Config\ConfigEntityValidationTestBase;
|
||||
use Drupal\system\Entity\Action;
|
||||
|
||||
/**
|
||||
* Tests validation of action entities.
|
||||
*
|
||||
* @group system
|
||||
*/
|
||||
class ActionValidationTest extends ConfigEntityValidationTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
$this->entity = Action::create([
|
||||
'id' => 'test',
|
||||
'label' => 'Test',
|
||||
'type' => 'test',
|
||||
'plugin' => 'action_goto_action',
|
||||
]);
|
||||
$this->entity->save();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\system\Kernel\Entity;
|
||||
|
||||
use Drupal\KernelTests\Core\Config\ConfigEntityValidationTestBase;
|
||||
use Drupal\system\Entity\Menu;
|
||||
|
||||
/**
|
||||
* Tests validation of menu entities.
|
||||
*
|
||||
* @group system
|
||||
*/
|
||||
class MenuValidationTest extends ConfigEntityValidationTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
$this->entity = Menu::create([
|
||||
'id' => 'test',
|
||||
'label' => 'Test',
|
||||
]);
|
||||
$this->entity->save();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\taxonomy\Kernel;
|
||||
|
||||
use Drupal\KernelTests\Core\Config\ConfigEntityValidationTestBase;
|
||||
use Drupal\taxonomy\Entity\Vocabulary;
|
||||
|
||||
/**
|
||||
* Tests validation of vocabulary entities.
|
||||
*
|
||||
* @group taxonomy
|
||||
*/
|
||||
class VocabularyValidationTest extends ConfigEntityValidationTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['taxonomy'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
$this->entity = Vocabulary::create([
|
||||
'vid' => 'test',
|
||||
'name' => 'Test',
|
||||
]);
|
||||
$this->entity->save();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\user\Kernel;
|
||||
|
||||
use Drupal\KernelTests\Core\Config\ConfigEntityValidationTestBase;
|
||||
use Drupal\user\Entity\Role;
|
||||
|
||||
/**
|
||||
* Tests validation of user_role entities.
|
||||
*
|
||||
* @group user
|
||||
*/
|
||||
class RoleValidationTest extends ConfigEntityValidationTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['user'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
$this->entity = Role::create([
|
||||
'id' => 'test',
|
||||
'label' => 'Test',
|
||||
]);
|
||||
$this->entity->save();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\views\Kernel\Entity;
|
||||
|
||||
use Drupal\KernelTests\Core\Config\ConfigEntityValidationTestBase;
|
||||
use Drupal\views\Entity\View;
|
||||
|
||||
/**
|
||||
* Tests validation of view entities.
|
||||
*
|
||||
* @group views
|
||||
*/
|
||||
class ViewValidationTest extends ConfigEntityValidationTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['views'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
$this->entity = View::create([
|
||||
'id' => 'test',
|
||||
'label' => 'Test',
|
||||
]);
|
||||
$this->entity->save();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\workflows\Kernel;
|
||||
|
||||
use Drupal\KernelTests\Core\Config\ConfigEntityValidationTestBase;
|
||||
use Drupal\workflows\Entity\Workflow;
|
||||
|
||||
/**
|
||||
* Tests validation of workflow entities.
|
||||
*
|
||||
* @group workflows
|
||||
*/
|
||||
class WorkflowValidationTest extends ConfigEntityValidationTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['workflows', 'workflow_type_test'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
$this->entity = Workflow::create([
|
||||
'id' => 'test',
|
||||
'label' => 'Test',
|
||||
'type' => 'workflow_type_test',
|
||||
]);
|
||||
$this->entity->save();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,188 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\KernelTests\Core\Config;
|
||||
|
||||
use Drupal\Component\Utility\NestedArray;
|
||||
use Drupal\Core\Config\Entity\ConfigEntityInterface;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
|
||||
/**
|
||||
* Base class for testing validation of config entities.
|
||||
*
|
||||
* @group config
|
||||
* @group Validation
|
||||
*/
|
||||
abstract class ConfigEntityValidationTestBase extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['system'];
|
||||
|
||||
/**
|
||||
* The config entity being tested.
|
||||
*
|
||||
* @var \Drupal\Core\Config\Entity\ConfigEntityInterface
|
||||
*/
|
||||
protected ConfigEntityInterface $entity;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
$this->installConfig('system');
|
||||
|
||||
// Install Stark so we can add a legitimately installed theme to config
|
||||
// dependencies.
|
||||
$this->container->get('theme_installer')->install(['stark']);
|
||||
$this->container = $this->container->get('kernel')->getContainer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for ::testConfigDependenciesValidation().
|
||||
*
|
||||
* @return array[]
|
||||
* The test cases.
|
||||
*/
|
||||
public function providerConfigDependenciesValidation(): array {
|
||||
return [
|
||||
'valid dependency types' => [
|
||||
[
|
||||
'config' => ['system.site'],
|
||||
'content' => ['node:some-random-uuid'],
|
||||
'module' => ['system'],
|
||||
'theme' => ['stark'],
|
||||
],
|
||||
[],
|
||||
],
|
||||
'unknown dependency type' => [
|
||||
[
|
||||
'fun_stuff' => ['star-trek.deep-space-nine'],
|
||||
],
|
||||
[
|
||||
"'fun_stuff' is not a supported key.",
|
||||
],
|
||||
],
|
||||
'empty string in config dependencies' => [
|
||||
[
|
||||
'config' => [''],
|
||||
],
|
||||
[
|
||||
'This value should not be blank.',
|
||||
"The '' config does not exist.",
|
||||
],
|
||||
],
|
||||
'non-existent config dependency' => [
|
||||
[
|
||||
'config' => ['fake_settings'],
|
||||
],
|
||||
[
|
||||
"The 'fake_settings' config does not exist.",
|
||||
],
|
||||
],
|
||||
'empty string in module dependencies' => [
|
||||
[
|
||||
'module' => [''],
|
||||
],
|
||||
[
|
||||
'This value should not be blank.',
|
||||
"Module '' is not installed.",
|
||||
],
|
||||
],
|
||||
'invalid module dependency' => [
|
||||
[
|
||||
'module' => ['invalid-module-name'],
|
||||
],
|
||||
[
|
||||
'This value is not valid.',
|
||||
"Module 'invalid-module-name' is not installed.",
|
||||
],
|
||||
],
|
||||
'non-installed module dependency' => [
|
||||
[
|
||||
'module' => ['bad_judgment'],
|
||||
],
|
||||
[
|
||||
"Module 'bad_judgment' is not installed.",
|
||||
],
|
||||
],
|
||||
'empty string in theme dependencies' => [
|
||||
[
|
||||
'theme' => [''],
|
||||
],
|
||||
[
|
||||
'This value should not be blank.',
|
||||
"Theme '' is not installed.",
|
||||
],
|
||||
],
|
||||
'invalid theme dependency' => [
|
||||
[
|
||||
'theme' => ['invalid-theme-name'],
|
||||
],
|
||||
[
|
||||
'This value is not valid.',
|
||||
"Theme 'invalid-theme-name' is not installed.",
|
||||
],
|
||||
],
|
||||
'non-installed theme dependency' => [
|
||||
[
|
||||
'theme' => ['ugly_theme'],
|
||||
],
|
||||
[
|
||||
"Theme 'ugly_theme' is not installed.",
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests validation of config dependencies.
|
||||
*
|
||||
* @param array[] $dependencies
|
||||
* The dependencies that should be added to the config entity under test.
|
||||
* @param string[] $expected_messages
|
||||
* The expected constraint violation messages.
|
||||
*
|
||||
* @dataProvider providerConfigDependenciesValidation
|
||||
*/
|
||||
public function testConfigDependenciesValidation(array $dependencies, array $expected_messages): void {
|
||||
$this->assertInstanceOf(ConfigEntityInterface::class, $this->entity);
|
||||
|
||||
// The entity should have valid data to begin with.
|
||||
$this->assertValidationErrors([]);
|
||||
|
||||
// Add the dependencies we were given to the dependencies that may already
|
||||
// exist in the entity.
|
||||
$dependencies = NestedArray::mergeDeep($this->entity->getDependencies(), $dependencies);
|
||||
|
||||
$this->entity->set('dependencies', $dependencies);
|
||||
$this->assertValidationErrors($expected_messages);
|
||||
|
||||
// Enforce these dependencies, and ensure we get the same results.
|
||||
$this->entity->set('dependencies', [
|
||||
'enforced' => $dependencies,
|
||||
]);
|
||||
$this->assertValidationErrors($expected_messages);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts a set of validation errors is raised when the entity is validated.
|
||||
*
|
||||
* @param string[] $expected_messages
|
||||
* The expected validation error messages.
|
||||
*/
|
||||
protected function assertValidationErrors(array $expected_messages): void {
|
||||
/** @var \Drupal\Core\TypedData\TypedDataManagerInterface $typed_data */
|
||||
$typed_data = $this->container->get('typed_data_manager');
|
||||
$definition = $typed_data->createDataDefinition('entity:' . $this->entity->getEntityTypeId());
|
||||
$violations = $typed_data->create($definition, $this->entity)->validate();
|
||||
|
||||
$actual_messages = [];
|
||||
foreach ($violations as $violation) {
|
||||
$actual_messages[] = (string) $violation->getMessage();
|
||||
}
|
||||
$this->assertSame($expected_messages, $actual_messages);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\KernelTests\Core\Config;
|
||||
|
||||
use Drupal\Core\TypedData\DataDefinition;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
|
||||
/**
|
||||
* Tests the ConfigExists constraint validator.
|
||||
*
|
||||
* @group config
|
||||
* @group Validation
|
||||
*
|
||||
* @covers \Drupal\Core\Config\Plugin\Validation\Constraint\ConfigExistsConstraint
|
||||
* @covers \Drupal\Core\Config\Plugin\Validation\Constraint\ConfigExistsConstraintValidator
|
||||
*/
|
||||
class ConfigExistsConstraintValidatorTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['system'];
|
||||
|
||||
/**
|
||||
* Tests the ConfigExists constraint validator.
|
||||
*/
|
||||
public function testValidation(): void {
|
||||
// Create a data definition that specifies the value must be a string with
|
||||
// the name of an existing piece of config.
|
||||
$definition = DataDefinition::create('string')
|
||||
->addConstraint('ConfigExists');
|
||||
|
||||
/** @var \Drupal\Core\TypedData\TypedDataManagerInterface $typed_data */
|
||||
$typed_data = $this->container->get('typed_data_manager');
|
||||
$data = $typed_data->create($definition, 'system.site');
|
||||
|
||||
$violations = $data->validate();
|
||||
$this->assertCount(1, $violations);
|
||||
$this->assertSame("The 'system.site' config does not exist.", (string) $violations->get(0)->getMessage());
|
||||
|
||||
$this->installConfig('system');
|
||||
$this->assertCount(0, $data->validate());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\KernelTests\Core\Entity;
|
||||
|
||||
use Drupal\Core\Field\Entity\BaseFieldOverride;
|
||||
use Drupal\KernelTests\Core\Config\ConfigEntityValidationTestBase;
|
||||
|
||||
/**
|
||||
* Tests validation of base_field_override entities.
|
||||
*
|
||||
* @group Entity
|
||||
* @group Validation
|
||||
*/
|
||||
class BaseFieldOverrideValidationTest extends ConfigEntityValidationTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['user'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
$fields = $this->container->get('entity_field.manager')
|
||||
->getBaseFieldDefinitions('user');
|
||||
|
||||
$this->entity = BaseFieldOverride::createFromBaseFieldDefinition(reset($fields), 'user');
|
||||
$this->entity->save();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\KernelTests\Core\Entity;
|
||||
|
||||
use Drupal\Core\Datetime\Entity\DateFormat;
|
||||
use Drupal\KernelTests\Core\Config\ConfigEntityValidationTestBase;
|
||||
|
||||
/**
|
||||
* Tests validation of date_format entities.
|
||||
*
|
||||
* @group Entity
|
||||
* @group Validation
|
||||
*/
|
||||
class DateFormatValidationTest extends ConfigEntityValidationTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
$this->entity = DateFormat::create([
|
||||
'id' => 'test',
|
||||
'label' => 'Test',
|
||||
'pattern' => 'Y-m-d',
|
||||
]);
|
||||
$this->entity->save();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\KernelTests\Core\Entity;
|
||||
|
||||
use Drupal\Core\Entity\Entity\EntityFormDisplay;
|
||||
|
||||
/**
|
||||
* Tests validation of entity_form_display entities.
|
||||
*
|
||||
* @group Entity
|
||||
* @group Validation
|
||||
*/
|
||||
class EntityFormDisplayValidationTest extends EntityFormModeValidationTest {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
$this->entity = EntityFormDisplay::create([
|
||||
'label' => 'Test',
|
||||
'targetEntityType' => 'user',
|
||||
'bundle' => 'user',
|
||||
// The mode was created by the parent class.
|
||||
'mode' => 'test',
|
||||
]);
|
||||
$this->entity->save();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\KernelTests\Core\Entity;
|
||||
|
||||
use Drupal\Core\Entity\Entity\EntityFormMode;
|
||||
use Drupal\KernelTests\Core\Config\ConfigEntityValidationTestBase;
|
||||
|
||||
/**
|
||||
* Tests validation of entity_form_mode entities.
|
||||
*
|
||||
* @group Entity
|
||||
* @group Validation
|
||||
*/
|
||||
class EntityFormModeValidationTest extends ConfigEntityValidationTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['user'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
$this->installConfig('user');
|
||||
|
||||
$this->entity = EntityFormMode::create([
|
||||
'id' => 'user.test',
|
||||
'label' => 'Test',
|
||||
'targetEntityType' => 'user',
|
||||
]);
|
||||
$this->entity->save();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\KernelTests\Core\Entity;
|
||||
|
||||
use Drupal\Core\Entity\Entity\EntityViewDisplay;
|
||||
|
||||
/**
|
||||
* Tests validation of entity_view_display entities.
|
||||
*
|
||||
* @group Entity
|
||||
* @group Validation
|
||||
*/
|
||||
class EntityViewDisplayValidationTest extends EntityViewModeValidationTest {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
$this->entity = EntityViewDisplay::create([
|
||||
'label' => 'Test',
|
||||
'targetEntityType' => 'user',
|
||||
'bundle' => 'user',
|
||||
// The mode was created by the parent class.
|
||||
'mode' => 'test',
|
||||
]);
|
||||
$this->entity->save();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\KernelTests\Core\Entity;
|
||||
|
||||
use Drupal\Core\Entity\Entity\EntityViewMode;
|
||||
use Drupal\KernelTests\Core\Config\ConfigEntityValidationTestBase;
|
||||
|
||||
/**
|
||||
* Tests validation of entity_view_mode entities.
|
||||
*
|
||||
* @group Entity
|
||||
* @group Validation
|
||||
*/
|
||||
class EntityViewModeValidationTest extends ConfigEntityValidationTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['user'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
$this->installConfig('user');
|
||||
|
||||
$this->entity = EntityViewMode::create([
|
||||
'id' => 'user.test',
|
||||
'label' => 'Test',
|
||||
'targetEntityType' => 'user',
|
||||
]);
|
||||
$this->entity->save();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\KernelTests\Core\Extension;
|
||||
|
||||
use Drupal\Core\TypedData\DataDefinition;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
|
||||
/**
|
||||
* Tests the ExtensionExists constraint validator.
|
||||
*
|
||||
* @group Validation
|
||||
*
|
||||
* @covers \Drupal\Core\Extension\Plugin\Validation\Constraint\ExtensionExistsConstraint
|
||||
* @covers \Drupal\Core\Extension\Plugin\Validation\Constraint\ExtensionExistsConstraintValidator
|
||||
*/
|
||||
class ExtensionExistsConstraintValidatorTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['system'];
|
||||
|
||||
/**
|
||||
* Tests the ExtensionExists constraint validator.
|
||||
*/
|
||||
public function testValidation(): void {
|
||||
// Create a data definition that specifies the value must be a string with
|
||||
// the name of an installed module.
|
||||
$definition = DataDefinition::create('string')
|
||||
->addConstraint('ExtensionExists', 'module');
|
||||
|
||||
/** @var \Drupal\Core\TypedData\TypedDataManagerInterface $typed_data */
|
||||
$typed_data = $this->container->get('typed_data_manager');
|
||||
$data = $typed_data->create($definition, 'user');
|
||||
|
||||
$violations = $data->validate();
|
||||
$this->assertCount(1, $violations);
|
||||
$this->assertSame("Module 'user' is not installed.", (string) $violations->get(0)->getMessage());
|
||||
|
||||
$this->enableModules(['user']);
|
||||
$this->assertCount(0, $data->validate());
|
||||
|
||||
$definition->setConstraints(['ExtensionExists' => 'theme']);
|
||||
$data = $typed_data->create($definition, 'stark');
|
||||
|
||||
$violations = $data->validate();
|
||||
$this->assertCount(1, $violations);
|
||||
$this->assertSame("Theme 'stark' is not installed.", (string) $violations->get(0)->getMessage());
|
||||
|
||||
$this->assertTrue($this->container->get('theme_installer')->install(['stark']));
|
||||
// Installing the theme rebuilds the container, so we need to ensure the
|
||||
// constraint is instantiated with an up-to-date theme handler.
|
||||
$data = $this->container->get('kernel')
|
||||
->getContainer()
|
||||
->get('typed_data_manager')
|
||||
->create($definition, 'stark');
|
||||
$this->assertCount(0, $data->validate());
|
||||
|
||||
// Anything but a module or theme should raise an exception.
|
||||
$definition->setConstraints(['ExtensionExists' => 'profile']);
|
||||
$this->expectExceptionMessage("Unknown extension type: 'profile'");
|
||||
$data->validate();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\KernelTests\Core\Extension;
|
||||
|
||||
use Drupal\Core\TypedData\DataDefinition;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
|
||||
/**
|
||||
* Tests the ExtensionName constraint.
|
||||
*
|
||||
* @group Validation
|
||||
*
|
||||
* @covers \Drupal\Core\Extension\Plugin\Validation\Constraint\ExtensionNameConstraint
|
||||
*/
|
||||
class ExtensionNameConstraintTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['system'];
|
||||
|
||||
/**
|
||||
* Tests the ExtensionName constraint.
|
||||
*/
|
||||
public function testValidation(): void {
|
||||
// Create a data definition that specifies the value must be a string with
|
||||
// the name of a valid extension.
|
||||
$definition = DataDefinition::create('string')
|
||||
->addConstraint('ExtensionName');
|
||||
|
||||
/** @var \Drupal\Core\TypedData\TypedDataManagerInterface $typed_data */
|
||||
$typed_data = $this->container->get('typed_data_manager');
|
||||
$data = $typed_data->create($definition, 'user');
|
||||
|
||||
$this->assertCount(0, $data->validate());
|
||||
|
||||
$data->setValue('invalid-name');
|
||||
$violations = $data->validate();
|
||||
$this->assertCount(1, $violations);
|
||||
$this->assertSame('This value is not valid.', (string) $violations->get(0)->getMessage());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\KernelTests\Core\TypedData;
|
||||
|
||||
use Drupal\Core\TypedData\DataDefinition;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
|
||||
|
||||
/**
|
||||
* Tests the ValidKeys validation constraint.
|
||||
*
|
||||
* @group Validation
|
||||
*
|
||||
* @covers \Drupal\Core\Validation\Plugin\Validation\Constraint\ValidKeysConstraint
|
||||
* @covers \Drupal\Core\Validation\Plugin\Validation\Constraint\ValidKeysConstraintValidator
|
||||
*/
|
||||
class ValidKeysConstraintValidatorTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* Tests the ValidKeys constraint validator.
|
||||
*/
|
||||
public function testValidation(): void {
|
||||
// Create a data definition that specifies certain allowed keys.
|
||||
$definition = DataDefinition::create('any')
|
||||
->addConstraint('ValidKeys', ['north', 'south', 'west']);
|
||||
|
||||
/** @var \Drupal\Core\TypedData\TypedDataManagerInterface $typed_data */
|
||||
$typed_data = $this->container->get('typed_data_manager');
|
||||
|
||||
// Passing a non-array value should raise an exception.
|
||||
try {
|
||||
$typed_data->create($definition, 2501)->validate();
|
||||
$this->fail('Expected an exception but none was raised.');
|
||||
}
|
||||
catch (UnexpectedTypeException $e) {
|
||||
$this->assertSame('Expected argument of type "array", "int" given', $e->getMessage());
|
||||
}
|
||||
|
||||
// Empty arrays are valid.
|
||||
$this->assertCount(0, $typed_data->create($definition, [])->validate());
|
||||
|
||||
// Indexed arrays are never valid.
|
||||
$violations = $typed_data->create($definition, ['north', 'south'])->validate();
|
||||
$this->assertCount(1, $violations);
|
||||
$this->assertSame('Numerically indexed arrays are not allowed.', (string) $violations->get(0)->getMessage());
|
||||
|
||||
// Arrays with automatically assigned keys, AND a valid key, should be
|
||||
// considered invalid overall.
|
||||
$violations = $typed_data->create($definition, ['north', 'south' => 'west'])->validate();
|
||||
$this->assertCount(1, $violations);
|
||||
$this->assertSame("'0' is not a supported key.", (string) $violations->get(0)->getMessage());
|
||||
|
||||
// Associative arrays with an invalid key should be invalid.
|
||||
$violations = $typed_data->create($definition, ['north' => 'south', 'east' => 'west'])->validate();
|
||||
$this->assertCount(1, $violations);
|
||||
$this->assertSame("'east' is not a supported key.", (string) $violations->get(0)->getMessage());
|
||||
|
||||
// If the array only contains the allowed keys, it's fine.
|
||||
$value = [
|
||||
'north' => 'Boston',
|
||||
'south' => 'Atlanta',
|
||||
'west' => 'San Francisco',
|
||||
];
|
||||
$violations = $typed_data->create($definition, $value)->validate();
|
||||
$this->assertCount(0, $violations);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that valid keys can be inferred from the data definition.
|
||||
*/
|
||||
public function testValidKeyInference(): void {
|
||||
// Install the System module and its config so that we can test that the
|
||||
// validator infers the allowed keys from a defined schema.
|
||||
$this->enableModules(['system']);
|
||||
$this->installConfig('system');
|
||||
|
||||
$config = $this->container->get('config.typed')
|
||||
->get('system.site');
|
||||
$config->getDataDefinition()
|
||||
->addConstraint('ValidKeys', '<infer>');
|
||||
|
||||
$data = $config->getValue();
|
||||
$data['invalid-key'] = "There's a snake in my boots.";
|
||||
$config->setValue($data);
|
||||
$violations = $config->validate();
|
||||
$this->assertCount(1, $violations);
|
||||
$this->assertSame("'invalid-key' is not a supported key.", (string) $violations->get(0)->getMessage());
|
||||
|
||||
// Ensure that ValidKeys will freak out if the option is not exactly
|
||||
// `<infer>`.
|
||||
$config->getDataDefinition()
|
||||
->addConstraint('ValidKeys', 'infer');
|
||||
$this->expectExceptionMessage("'infer' is not a valid set of allowed keys.");
|
||||
$config->validate();
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue