Pull merge.
[yaffs-website] / web / core / lib / Drupal / Core / Validation / ConstraintManager.php
1 <?php
2
3 namespace Drupal\Core\Validation;
4
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;
10
11 /**
12  * Constraint plugin manager.
13  *
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.
18  *
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".
22  *
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.
26  *
27  * @see \Drupal\Core\Validation\Annotation\Constraint
28  */
29 class ConstraintManager extends DefaultPluginManager {
30
31   /**
32    * Overrides \Drupal\Component\Plugin\PluginManagerBase::__construct().
33    *
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.
41    */
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');
46   }
47
48   /**
49    * {@inheritdoc}
50    */
51   protected function getDiscovery() {
52     if (!isset($this->discovery)) {
53       $this->discovery = parent::getDiscovery();
54       $this->discovery = new StaticDiscoveryDecorator($this->discovery, [$this, 'registerDefinitions']);
55     }
56     return $this->discovery;
57   }
58
59   /**
60    * Creates a validation constraint.
61    *
62    * @param string $name
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.
67    *
68    * @return \Symfony\Component\Validator\Constraint
69    *   A validation constraint plugin.
70    */
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
75       // 'value' key also.
76       $options = isset($options) ? ['value' => $options] : [];
77     }
78     return $this->createInstance($name, $options);
79   }
80
81   /**
82    * Callback for registering definitions for constraints shipped with Symfony.
83    *
84    * @see ConstraintManager::__construct()
85    */
86   public function registerDefinitions() {
87     $this->getDiscovery()->setDefinition('Callback', [
88       'label' => new TranslatableMarkup('Callback'),
89       'class' => '\Symfony\Component\Validator\Constraints\Callback',
90       'type' => FALSE,
91     ]);
92     $this->getDiscovery()->setDefinition('Blank', [
93       'label' => new TranslatableMarkup('Blank'),
94       'class' => '\Symfony\Component\Validator\Constraints\Blank',
95       'type' => FALSE,
96     ]);
97     $this->getDiscovery()->setDefinition('NotBlank', [
98       'label' => new TranslatableMarkup('Not blank'),
99       'class' => '\Symfony\Component\Validator\Constraints\NotBlank',
100       'type' => FALSE,
101     ]);
102     $this->getDiscovery()->setDefinition('Email', [
103       'label' => new TranslatableMarkup('Email'),
104       'class' => '\Drupal\Core\Validation\Plugin\Validation\Constraint\EmailConstraint',
105       'type' => ['string'],
106     ]);
107   }
108
109   /**
110    * {@inheritdoc}
111    */
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']];
116     }
117   }
118
119   /**
120    * Returns a list of constraints that support the given type.
121    *
122    * @param string $type
123    *   The type to filter on.
124    *
125    * @return array
126    *   An array of constraint plugin definitions supporting the given type,
127    *   keyed by constraint name (plugin ID).
128    */
129   public function getDefinitionsByType($type) {
130     $definitions = [];
131     foreach ($this->getDefinitions() as $plugin_id => $definition) {
132       if ($definition['type'] === FALSE || in_array($type, $definition['type'])) {
133         $definitions[$plugin_id] = $definition;
134       }
135     }
136     return $definitions;
137   }
138
139 }