ExecutionContext.php 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\Validator\Context;
  11. use Symfony\Component\Validator\Constraint;
  12. use Symfony\Component\Validator\ConstraintViolation;
  13. use Symfony\Component\Validator\ConstraintViolationList;
  14. use Symfony\Component\Validator\ConstraintViolationListInterface;
  15. use Symfony\Component\Validator\Mapping\ClassMetadataInterface;
  16. use Symfony\Component\Validator\Mapping\MemberMetadata;
  17. use Symfony\Component\Validator\Mapping\MetadataInterface;
  18. use Symfony\Component\Validator\Mapping\PropertyMetadataInterface;
  19. use Symfony\Component\Validator\Util\PropertyPath;
  20. use Symfony\Component\Validator\Validator\LazyProperty;
  21. use Symfony\Component\Validator\Validator\ValidatorInterface;
  22. use Symfony\Component\Validator\Violation\ConstraintViolationBuilder;
  23. use Symfony\Component\Validator\Violation\ConstraintViolationBuilderInterface;
  24. use Symfony\Contracts\Translation\TranslatorInterface;
  25. /**
  26. * The context used and created by {@link ExecutionContextFactory}.
  27. *
  28. * @author Bernhard Schussek <bschussek@gmail.com>
  29. *
  30. * @see ExecutionContextInterface
  31. *
  32. * @internal since version 2.5. Code against ExecutionContextInterface instead.
  33. */
  34. class ExecutionContext implements ExecutionContextInterface
  35. {
  36. /**
  37. * @var ValidatorInterface
  38. */
  39. private $validator;
  40. /**
  41. * The root value of the validated object graph.
  42. *
  43. * @var mixed
  44. */
  45. private $root;
  46. /**
  47. * @var TranslatorInterface
  48. */
  49. private $translator;
  50. /**
  51. * @var string
  52. */
  53. private $translationDomain;
  54. /**
  55. * The violations generated in the current context.
  56. *
  57. * @var ConstraintViolationList
  58. */
  59. private $violations;
  60. /**
  61. * The currently validated value.
  62. *
  63. * @var mixed
  64. */
  65. private $value;
  66. /**
  67. * The currently validated object.
  68. *
  69. * @var object|null
  70. */
  71. private $object;
  72. /**
  73. * The property path leading to the current value.
  74. *
  75. * @var string
  76. */
  77. private $propertyPath = '';
  78. /**
  79. * The current validation metadata.
  80. *
  81. * @var MetadataInterface|null
  82. */
  83. private $metadata;
  84. /**
  85. * The currently validated group.
  86. *
  87. * @var string|null
  88. */
  89. private $group;
  90. /**
  91. * The currently validated constraint.
  92. *
  93. * @var Constraint|null
  94. */
  95. private $constraint;
  96. /**
  97. * Stores which objects have been validated in which group.
  98. *
  99. * @var array
  100. */
  101. private $validatedObjects = [];
  102. /**
  103. * Stores which class constraint has been validated for which object.
  104. *
  105. * @var array
  106. */
  107. private $validatedConstraints = [];
  108. /**
  109. * Stores which objects have been initialized.
  110. *
  111. * @var array
  112. */
  113. private $initializedObjects;
  114. private $cachedObjectsRefs;
  115. /**
  116. * @param mixed $root The root value of the validated object graph
  117. *
  118. * @internal Called by {@link ExecutionContextFactory}. Should not be used in user code.
  119. */
  120. public function __construct(ValidatorInterface $validator, $root, TranslatorInterface $translator, string $translationDomain = null)
  121. {
  122. $this->validator = $validator;
  123. $this->root = $root;
  124. $this->translator = $translator;
  125. $this->translationDomain = $translationDomain;
  126. $this->violations = new ConstraintViolationList();
  127. $this->cachedObjectsRefs = new \SplObjectStorage();
  128. }
  129. /**
  130. * {@inheritdoc}
  131. */
  132. public function setNode($value, ?object $object, MetadataInterface $metadata = null, string $propertyPath)
  133. {
  134. $this->value = $value;
  135. $this->object = $object;
  136. $this->metadata = $metadata;
  137. $this->propertyPath = (string) $propertyPath;
  138. }
  139. /**
  140. * {@inheritdoc}
  141. */
  142. public function setGroup(?string $group)
  143. {
  144. $this->group = $group;
  145. }
  146. /**
  147. * {@inheritdoc}
  148. */
  149. public function setConstraint(Constraint $constraint)
  150. {
  151. $this->constraint = $constraint;
  152. }
  153. /**
  154. * {@inheritdoc}
  155. */
  156. public function addViolation(string $message, array $parameters = [])
  157. {
  158. $this->violations->add(new ConstraintViolation(
  159. $this->translator->trans($message, $parameters, $this->translationDomain),
  160. $message,
  161. $parameters,
  162. $this->root,
  163. $this->propertyPath,
  164. $this->getValue(),
  165. null,
  166. null,
  167. $this->constraint
  168. ));
  169. }
  170. /**
  171. * {@inheritdoc}
  172. */
  173. public function buildViolation(string $message, array $parameters = []): ConstraintViolationBuilderInterface
  174. {
  175. return new ConstraintViolationBuilder(
  176. $this->violations,
  177. $this->constraint,
  178. $message,
  179. $parameters,
  180. $this->root,
  181. $this->propertyPath,
  182. $this->getValue(),
  183. $this->translator,
  184. $this->translationDomain
  185. );
  186. }
  187. /**
  188. * {@inheritdoc}
  189. */
  190. public function getViolations(): ConstraintViolationListInterface
  191. {
  192. return $this->violations;
  193. }
  194. /**
  195. * {@inheritdoc}
  196. */
  197. public function getValidator(): ValidatorInterface
  198. {
  199. return $this->validator;
  200. }
  201. /**
  202. * {@inheritdoc}
  203. */
  204. public function getRoot()
  205. {
  206. return $this->root;
  207. }
  208. /**
  209. * {@inheritdoc}
  210. */
  211. public function getValue()
  212. {
  213. if ($this->value instanceof LazyProperty) {
  214. return $this->value->getPropertyValue();
  215. }
  216. return $this->value;
  217. }
  218. /**
  219. * {@inheritdoc}
  220. */
  221. public function getObject()
  222. {
  223. return $this->object;
  224. }
  225. /**
  226. * {@inheritdoc}
  227. */
  228. public function getMetadata(): ?MetadataInterface
  229. {
  230. return $this->metadata;
  231. }
  232. /**
  233. * {@inheritdoc}
  234. */
  235. public function getGroup(): ?string
  236. {
  237. return $this->group;
  238. }
  239. public function getConstraint(): ?Constraint
  240. {
  241. return $this->constraint;
  242. }
  243. /**
  244. * {@inheritdoc}
  245. */
  246. public function getClassName(): ?string
  247. {
  248. return $this->metadata instanceof MemberMetadata || $this->metadata instanceof ClassMetadataInterface ? $this->metadata->getClassName() : null;
  249. }
  250. /**
  251. * {@inheritdoc}
  252. */
  253. public function getPropertyName(): ?string
  254. {
  255. return $this->metadata instanceof PropertyMetadataInterface ? $this->metadata->getPropertyName() : null;
  256. }
  257. /**
  258. * {@inheritdoc}
  259. */
  260. public function getPropertyPath(string $subPath = ''): string
  261. {
  262. return PropertyPath::append($this->propertyPath, $subPath);
  263. }
  264. /**
  265. * {@inheritdoc}
  266. */
  267. public function markGroupAsValidated(string $cacheKey, string $groupHash)
  268. {
  269. if (!isset($this->validatedObjects[$cacheKey])) {
  270. $this->validatedObjects[$cacheKey] = [];
  271. }
  272. $this->validatedObjects[$cacheKey][$groupHash] = true;
  273. }
  274. /**
  275. * {@inheritdoc}
  276. */
  277. public function isGroupValidated(string $cacheKey, string $groupHash): bool
  278. {
  279. return isset($this->validatedObjects[$cacheKey][$groupHash]);
  280. }
  281. /**
  282. * {@inheritdoc}
  283. */
  284. public function markConstraintAsValidated(string $cacheKey, string $constraintHash)
  285. {
  286. $this->validatedConstraints[$cacheKey.':'.$constraintHash] = true;
  287. }
  288. /**
  289. * {@inheritdoc}
  290. */
  291. public function isConstraintValidated(string $cacheKey, string $constraintHash): bool
  292. {
  293. return isset($this->validatedConstraints[$cacheKey.':'.$constraintHash]);
  294. }
  295. /**
  296. * {@inheritdoc}
  297. */
  298. public function markObjectAsInitialized(string $cacheKey)
  299. {
  300. $this->initializedObjects[$cacheKey] = true;
  301. }
  302. /**
  303. * {@inheritdoc}
  304. */
  305. public function isObjectInitialized(string $cacheKey): bool
  306. {
  307. return isset($this->initializedObjects[$cacheKey]);
  308. }
  309. /**
  310. * @internal
  311. *
  312. * @param object $object
  313. *
  314. * @return string
  315. */
  316. public function generateCacheKey($object)
  317. {
  318. if (!isset($this->cachedObjectsRefs[$object])) {
  319. $this->cachedObjectsRefs[$object] = spl_object_hash($object);
  320. }
  321. return $this->cachedObjectsRefs[$object];
  322. }
  323. public function __clone()
  324. {
  325. $this->violations = clone $this->violations;
  326. }
  327. }