diff --git a/core/lib/Drupal/Core/Validation/ConstraintFactory.php b/core/lib/Drupal/Core/Validation/ConstraintFactory.php new file mode 100644 index 0000000000..3196dae1cb --- /dev/null +++ b/core/lib/Drupal/Core/Validation/ConstraintFactory.php @@ -0,0 +1,38 @@ +discovery->getDefinition($plugin_id); + $plugin_class = static::getPluginClass($plugin_id, $plugin_definition, $this->interface); + + // If the plugin provides a factory method, pass the container to it. + if (is_subclass_of($plugin_class, ContainerFactoryPluginInterface::class)) { + return $plugin_class::create(\Drupal::getContainer(), $configuration, $plugin_id, $plugin_definition); + } + + // If the plugin is a Symfony Constraint, use the correct constructor. + if (is_subclass_of($plugin_class, Constraint::class)) { + return new $plugin_class($configuration); + } + + // Otherwise, create the plugin as normal. + return new $plugin_class($configuration, $plugin_id, $plugin_definition); + } + +} diff --git a/core/lib/Drupal/Core/Validation/ConstraintManager.php b/core/lib/Drupal/Core/Validation/ConstraintManager.php index 79da1d6e8a..c5faab67ed 100644 --- a/core/lib/Drupal/Core/Validation/ConstraintManager.php +++ b/core/lib/Drupal/Core/Validation/ConstraintManager.php @@ -40,6 +40,7 @@ class ConstraintManager extends DefaultPluginManager { * The module handler to invoke the alter hook with. */ public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) { + $this->factory = new ConstraintFactory($this); parent::__construct('Plugin/Validation/Constraint', $namespaces, $module_handler, NULL, 'Drupal\Core\Validation\Annotation\Constraint'); $this->alterInfo('validation_constraint'); $this->setCacheBackend($cache_backend, 'validation_constraint_plugins'); diff --git a/core/modules/system/tests/modules/entity_test/src/Plugin/Validation/Constraint/EntityTestContainerFactoryPlugin.php b/core/modules/system/tests/modules/entity_test/src/Plugin/Validation/Constraint/EntityTestContainerFactoryPlugin.php new file mode 100644 index 0000000000..224e7bbd1f --- /dev/null +++ b/core/modules/system/tests/modules/entity_test/src/Plugin/Validation/Constraint/EntityTestContainerFactoryPlugin.php @@ -0,0 +1,31 @@ +getValidationConstraintManager(); + + // If the plugin is a \Symfony\Component\Validator\Constraint, they will be + // created first. + $this->assertInstanceOf(Constraint::class, $constraint_manager->create('Uuid', [])); + + // If the plugin implements the + // \Drupal\Core\Plugin\ContainerFactoryPluginInterface, they will be created + // second. + $container_factory_plugin = $constraint_manager->create('EntityTestContainerFactoryPlugin', []); + $this->assertNotInstanceOf(Constraint::class, $container_factory_plugin); + $this->assertInstanceOf(ContainerFactoryPluginInterface::class, $container_factory_plugin); + + // Plugins that are not a \Symfony\Component\Validator\Constraint or do not + // implement the \Drupal\Core\Plugin\ContainerFactoryPluginInterface are + // created last. + $default_plugin = $constraint_manager->create('EntityTestDefaultPlugin', []); + $this->assertNotInstanceOf(Constraint::class, $default_plugin); + $this->assertNotInstanceOf(ContainerFactoryPluginInterface::class, $default_plugin); + $this->assertInstanceOf(PluginBase::class, $default_plugin); + } + +}