1<?php 2 3namespace Drupal\Core\TypedData\Validation; 4 5use Drupal\Core\Validation\TranslatorInterface; 6use Symfony\Component\Validator\Constraint; 7use Symfony\Component\Validator\ConstraintViolation; 8use Symfony\Component\Validator\ConstraintViolationList; 9use Symfony\Component\Validator\Context\ExecutionContextInterface; 10use Symfony\Component\Validator\Mapping\MetadataInterface; 11use Symfony\Component\Validator\Util\PropertyPath; 12use Symfony\Component\Validator\Validator\ValidatorInterface; 13 14/** 15 * Defines an execution context class. 16 * 17 * We do not use the context provided by Symfony as it is marked internal, so 18 * this class is pretty much the same, but has some code style changes as well 19 * as exceptions for methods we don't support. 20 */ 21class ExecutionContext implements ExecutionContextInterface { 22 23 /** 24 * @var \Symfony\Component\Validator\Validator\ValidatorInterface 25 */ 26 protected $validator; 27 28 /** 29 * The root value of the validated object graph. 30 * 31 * @var mixed 32 */ 33 protected $root; 34 35 /** 36 * @var \Drupal\Core\Validation\TranslatorInterface 37 */ 38 protected $translator; 39 40 /** 41 * @var string 42 */ 43 protected $translationDomain; 44 45 /** 46 * The violations generated in the current context. 47 * 48 * @var \Symfony\Component\Validator\ConstraintViolationList 49 */ 50 protected $violations; 51 52 /** 53 * The currently validated value. 54 * 55 * @var mixed 56 */ 57 protected $value; 58 59 /** 60 * The currently validated typed data object. 61 * 62 * @var \Drupal\Core\TypedData\TypedDataInterface 63 */ 64 protected $data; 65 66 /** 67 * The property path leading to the current value. 68 * 69 * @var string 70 */ 71 protected $propertyPath = ''; 72 73 /** 74 * The current validation metadata. 75 * 76 * @var \Symfony\Component\Validator\Mapping\MetadataInterface|null 77 */ 78 protected $metadata; 79 80 /** 81 * The currently validated group. 82 * 83 * @var string|null 84 */ 85 protected $group; 86 87 /** 88 * The currently validated constraint. 89 * 90 * @var \Symfony\Component\Validator\Constraint|null 91 */ 92 protected $constraint; 93 94 /** 95 * Stores which objects have been validated in which group. 96 * 97 * @var array 98 */ 99 protected $validatedObjects = []; 100 101 /** 102 * Stores which class constraint has been validated for which object. 103 * 104 * @var array 105 */ 106 protected $validatedConstraints = []; 107 108 /** 109 * Creates a new ExecutionContext. 110 * 111 * @param \Symfony\Component\Validator\Validator\ValidatorInterface $validator 112 * The validator. 113 * @param mixed $root 114 * The root. 115 * @param \Drupal\Core\Validation\TranslatorInterface $translator 116 * The translator. 117 * @param string $translationDomain 118 * (optional) The translation domain. 119 * 120 * @internal Called by \Drupal\Core\TypedData\Validation\ExecutionContextFactory. 121 * Should not be used in user code. 122 */ 123 public function __construct(ValidatorInterface $validator, $root, TranslatorInterface $translator, $translationDomain = NULL) { 124 $this->validator = $validator; 125 $this->root = $root; 126 $this->translator = $translator; 127 $this->translationDomain = $translationDomain; 128 $this->violations = new ConstraintViolationList(); 129 } 130 131 /** 132 * {@inheritdoc} 133 */ 134 public function setNode($value, $object, MetadataInterface $metadata = NULL, $propertyPath) { 135 $this->value = $value; 136 $this->data = $object; 137 $this->metadata = $metadata; 138 $this->propertyPath = (string) $propertyPath; 139 } 140 141 /** 142 * {@inheritdoc} 143 */ 144 public function setGroup($group) { 145 $this->group = $group; 146 } 147 148 /** 149 * {@inheritdoc} 150 */ 151 public function setConstraint(Constraint $constraint) { 152 $this->constraint = $constraint; 153 } 154 155 /** 156 * {@inheritdoc} 157 */ 158 public function addViolation($message, array $parameters = [], $invalidValue = NULL, $plural = NULL, $code = NULL) { 159 // The parameters $invalidValue and following are ignored by the new 160 // API, as they are not present in the new interface anymore. 161 // You should use buildViolation() instead. 162 if (func_num_args() > 2) { 163 throw new \LogicException('Legacy validator API is unsupported.'); 164 } 165 166 $this->violations->add(new ConstraintViolation($this->translator->trans($message, $parameters, $this->translationDomain), $message, $parameters, $this->root, $this->propertyPath, $this->value, NULL, NULL, $this->constraint)); 167 } 168 169 /** 170 * {@inheritdoc} 171 */ 172 public function buildViolation($message, array $parameters = []) { 173 return new ConstraintViolationBuilder($this->violations, $this->constraint, $message, $parameters, $this->root, $this->propertyPath, $this->value, $this->translator, $this->translationDomain); 174 } 175 176 /** 177 * {@inheritdoc} 178 */ 179 public function getViolations() { 180 return $this->violations; 181 } 182 183 /** 184 * {@inheritdoc} 185 */ 186 public function getValidator() { 187 return $this->validator; 188 } 189 190 /** 191 * {@inheritdoc} 192 */ 193 public function getRoot() { 194 return $this->root; 195 } 196 197 /** 198 * {@inheritdoc} 199 */ 200 public function getValue() { 201 return $this->value; 202 } 203 204 /** 205 * {@inheritdoc} 206 */ 207 public function getObject() { 208 return $this->data; 209 } 210 211 /** 212 * {@inheritdoc} 213 */ 214 public function getMetadata() { 215 return $this->metadata; 216 } 217 218 /** 219 * {@inheritdoc} 220 */ 221 public function getGroup() { 222 return Constraint::DEFAULT_GROUP; 223 } 224 225 /** 226 * {@inheritdoc} 227 */ 228 public function getClassName() { 229 return get_class($this->data); 230 } 231 232 /** 233 * {@inheritdoc} 234 */ 235 public function getPropertyName() { 236 return $this->data->getName(); 237 } 238 239 /** 240 * {@inheritdoc} 241 */ 242 public function getPropertyPath($sub_path = '') { 243 return PropertyPath::append($this->propertyPath, $sub_path); 244 } 245 246 /** 247 * {@inheritdoc} 248 */ 249 public function addViolationAt($subPath, $message, array $parameters = [], $invalidValue = NULL, $plural = NULL, $code = NULL) { 250 throw new \LogicException('Legacy validator API is unsupported.'); 251 } 252 253 /** 254 * {@inheritdoc} 255 */ 256 public function validate($value, $subPath = '', $groups = NULL, $traverse = FALSE, $deep = FALSE) { 257 throw new \LogicException('Legacy validator API is unsupported.'); 258 } 259 260 /** 261 * {@inheritdoc} 262 */ 263 public function markConstraintAsValidated($cache_key, $constraint_hash) { 264 $this->validatedConstraints[$cache_key . ':' . $constraint_hash] = TRUE; 265 } 266 267 /** 268 * {@inheritdoc} 269 */ 270 public function isConstraintValidated($cache_key, $constraint_hash) { 271 return isset($this->validatedConstraints[$cache_key . ':' . $constraint_hash]); 272 } 273 274 /** 275 * {@inheritdoc} 276 */ 277 public function validateValue($value, $constraints, $subPath = '', $groups = NULL) { 278 throw new \LogicException('Legacy validator API is unsupported.'); 279 } 280 281 /** 282 * {@inheritdoc} 283 */ 284 public function markGroupAsValidated($cache_key, $group_hash) { 285 $this->validatedObjects[$cache_key][$group_hash] = TRUE; 286 } 287 288 /** 289 * {@inheritdoc} 290 */ 291 public function isGroupValidated($cache_key, $group_hash) { 292 return isset($this->validatedObjects[$cache_key][$group_hash]); 293 } 294 295 /** 296 * {@inheritdoc} 297 */ 298 public function markObjectAsInitialized($cache_key) { 299 // Not supported, so nothing todo. 300 } 301 302 /** 303 * {@inheritdoc} 304 */ 305 public function isObjectInitialized($cache_key) { 306 // Not supported, so nothing todo. 307 } 308 309 /** 310 * {@inheritdoc} 311 */ 312 public function getMetadataFactory() { 313 throw new \LogicException('Legacy validator API is unsupported.'); 314 } 315 316} 317