3 namespace Drupal\Core\Validation;
5 use Drupal\Component\Plugin\Discovery\StaticDiscoveryDecorator;
6 use Drupal\Core\Cache\CacheBackendInterface;
7 use Drupal\Core\Extension\ModuleHandlerInterface;
8 use Drupal\Core\Plugin\DefaultPluginManager;
9 use Drupal\Core\StringTranslation\TranslatableMarkup;
12 * Constraint plugin manager.
14 * Manages validation constraints based upon
15 * \Symfony\Component\Validator\Constraint, whereas Symfony constraints are
16 * added in manually during construction. Constraint options are passed on as
17 * plugin configuration during plugin instantiation.
19 * While core does not prefix constraint plugins, modules have to prefix them
20 * with the module name in order to avoid any naming conflicts; for example, a
21 * "profile" module would have to prefix any constraints with "Profile".
23 * Constraint plugins may specify data types to which support is limited via the
24 * 'type' key of plugin definitions. See
25 * \Drupal\Core\Validation\Annotation\Constraint for details.
27 * @see \Drupal\Core\Validation\Annotation\Constraint
29 class ConstraintManager extends DefaultPluginManager {
32 * Overrides \Drupal\Component\Plugin\PluginManagerBase::__construct().
34 * @param \Traversable $namespaces
35 * An object that implements \Traversable which contains the root paths
36 * keyed by the corresponding namespace to look for plugin implementations.
37 * @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend
38 * Cache backend instance to use.
39 * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
40 * The module handler to invoke the alter hook with.
42 public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) {
43 parent::__construct('Plugin/Validation/Constraint', $namespaces, $module_handler, NULL, 'Drupal\Core\Validation\Annotation\Constraint');
44 $this->alterInfo('validation_constraint');
45 $this->setCacheBackend($cache_backend, 'validation_constraint_plugins');
51 protected function getDiscovery() {
52 if (!isset($this->discovery)) {
53 $this->discovery = parent::getDiscovery();
54 $this->discovery = new StaticDiscoveryDecorator($this->discovery, [$this, 'registerDefinitions']);
56 return $this->discovery;
61 * Creates a validation constraint.
64 * The name or plugin id of the constraint.
65 * @param mixed $options
66 * The options to pass to the constraint class. Required and supported
67 * options depend on the constraint class.
69 * @return \Symfony\Component\Validator\Constraint
70 * A validation constraint plugin.
72 public function create($name, $options) {
73 if (!is_array($options)) {
74 // Plugins need an array as configuration, so make sure we have one.
75 // The constraint classes support passing the options as part of the
77 $options = isset($options) ? ['value' => $options] : [];
79 return $this->createInstance($name, $options);
83 * Callback for registering definitions for constraints shipped with Symfony.
85 * @see ConstraintManager::__construct()
87 public function registerDefinitions() {
88 $this->getDiscovery()->setDefinition('Callback', [
89 'label' => new TranslatableMarkup('Callback'),
90 'class' => '\Symfony\Component\Validator\Constraints\Callback',
93 $this->getDiscovery()->setDefinition('Blank', [
94 'label' => new TranslatableMarkup('Blank'),
95 'class' => '\Symfony\Component\Validator\Constraints\Blank',
98 $this->getDiscovery()->setDefinition('NotBlank', [
99 'label' => new TranslatableMarkup('Not blank'),
100 'class' => '\Symfony\Component\Validator\Constraints\NotBlank',
103 $this->getDiscovery()->setDefinition('Email', [
104 'label' => new TranslatableMarkup('Email'),
105 'class' => '\Drupal\Core\Validation\Plugin\Validation\Constraint\EmailConstraint',
106 'type' => ['string'],
113 public function processDefinition(&$definition, $plugin_id) {
114 // Make sure 'type' is set and either an array or FALSE.
115 if ($definition['type'] !== FALSE && !is_array($definition['type'])) {
116 $definition['type'] = [$definition['type']];
121 * Returns a list of constraints that support the given type.
123 * @param string $type
124 * The type to filter on.
127 * An array of constraint plugin definitions supporting the given type,
128 * keyed by constraint name (plugin ID).
130 public function getDefinitionsByType($type) {
132 foreach ($this->getDefinitions() as $plugin_id => $definition) {
133 if ($definition['type'] === FALSE || in_array($type, $definition['type'])) {
134 $definitions[$plugin_id] = $definition;