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;
60 * Creates a validation constraint.
63 * The name or plugin id of the constraint.
64 * @param mixed $options
65 * The options to pass to the constraint class. Required and supported
66 * options depend on the constraint class.
68 * @return \Symfony\Component\Validator\Constraint
69 * A validation constraint plugin.
71 public function create($name, $options) {
72 if (!is_array($options)) {
73 // Plugins need an array as configuration, so make sure we have one.
74 // The constraint classes support passing the options as part of the
76 $options = isset($options) ? ['value' => $options] : [];
78 return $this->createInstance($name, $options);
82 * Callback for registering definitions for constraints shipped with Symfony.
84 * @see ConstraintManager::__construct()
86 public function registerDefinitions() {
87 $this->getDiscovery()->setDefinition('Callback', [
88 'label' => new TranslatableMarkup('Callback'),
89 'class' => '\Symfony\Component\Validator\Constraints\Callback',
92 $this->getDiscovery()->setDefinition('Blank', [
93 'label' => new TranslatableMarkup('Blank'),
94 'class' => '\Symfony\Component\Validator\Constraints\Blank',
97 $this->getDiscovery()->setDefinition('NotBlank', [
98 'label' => new TranslatableMarkup('Not blank'),
99 'class' => '\Symfony\Component\Validator\Constraints\NotBlank',
102 $this->getDiscovery()->setDefinition('Email', [
103 'label' => new TranslatableMarkup('Email'),
104 'class' => '\Drupal\Core\Validation\Plugin\Validation\Constraint\EmailConstraint',
105 'type' => ['string'],
112 public function processDefinition(&$definition, $plugin_id) {
113 // Make sure 'type' is set and either an array or FALSE.
114 if ($definition['type'] !== FALSE && !is_array($definition['type'])) {
115 $definition['type'] = [$definition['type']];
120 * Returns a list of constraints that support the given type.
122 * @param string $type
123 * The type to filter on.
126 * An array of constraint plugin definitions supporting the given type,
127 * keyed by constraint name (plugin ID).
129 public function getDefinitionsByType($type) {
131 foreach ($this->getDefinitions() as $plugin_id => $definition) {
132 if ($definition['type'] === FALSE || in_array($type, $definition['type'])) {
133 $definitions[$plugin_id] = $definition;