ValidationVisitor.php 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  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;
  11. @trigger_error('The '.__NAMESPACE__.'\ValidationVisitor class is deprecated since version 2.5 and will be removed in 3.0.', E_USER_DEPRECATED);
  12. use Symfony\Component\Translation\TranslatorInterface;
  13. use Symfony\Component\Validator\Exception\NoSuchMetadataException;
  14. use Symfony\Component\Validator\Exception\UnexpectedTypeException;
  15. /**
  16. * Default implementation of {@link ValidationVisitorInterface} and
  17. * {@link GlobalExecutionContextInterface}.
  18. *
  19. * @author Bernhard Schussek <bschussek@gmail.com>
  20. *
  21. * @deprecated since version 2.5, to be removed in 3.0.
  22. */
  23. class ValidationVisitor implements ValidationVisitorInterface, GlobalExecutionContextInterface
  24. {
  25. /**
  26. * @var mixed
  27. */
  28. private $root;
  29. /**
  30. * @var MetadataFactoryInterface
  31. */
  32. private $metadataFactory;
  33. /**
  34. * @var ConstraintValidatorFactoryInterface
  35. */
  36. private $validatorFactory;
  37. /**
  38. * @var TranslatorInterface
  39. */
  40. private $translator;
  41. /**
  42. * @var null|string
  43. */
  44. private $translationDomain;
  45. /**
  46. * @var array
  47. */
  48. private $objectInitializers;
  49. /**
  50. * @var ConstraintViolationList
  51. */
  52. private $violations;
  53. /**
  54. * @var array
  55. */
  56. private $validatedObjects = array();
  57. /**
  58. * Creates a new validation visitor.
  59. *
  60. * @param mixed $root The value passed to the validator
  61. * @param MetadataFactoryInterface $metadataFactory The factory for obtaining metadata instances
  62. * @param ConstraintValidatorFactoryInterface $validatorFactory The factory for creating constraint validators
  63. * @param TranslatorInterface $translator The translator for translating violation messages
  64. * @param string|null $translationDomain The domain of the translation messages
  65. * @param ObjectInitializerInterface[] $objectInitializers The initializers for preparing objects before validation
  66. *
  67. * @throws UnexpectedTypeException If any of the object initializers is not an instance of ObjectInitializerInterface
  68. */
  69. public function __construct($root, MetadataFactoryInterface $metadataFactory, ConstraintValidatorFactoryInterface $validatorFactory, TranslatorInterface $translator, $translationDomain = null, array $objectInitializers = array())
  70. {
  71. foreach ($objectInitializers as $initializer) {
  72. if (!$initializer instanceof ObjectInitializerInterface) {
  73. throw new UnexpectedTypeException($initializer, 'Symfony\Component\Validator\ObjectInitializerInterface');
  74. }
  75. }
  76. $this->root = $root;
  77. $this->metadataFactory = $metadataFactory;
  78. $this->validatorFactory = $validatorFactory;
  79. $this->translator = $translator;
  80. $this->translationDomain = $translationDomain;
  81. $this->objectInitializers = $objectInitializers;
  82. $this->violations = new ConstraintViolationList();
  83. }
  84. /**
  85. * {@inheritdoc}
  86. */
  87. public function visit(MetadataInterface $metadata, $value, $group, $propertyPath)
  88. {
  89. $context = new ExecutionContext(
  90. $this,
  91. $this->translator,
  92. $this->translationDomain,
  93. $metadata,
  94. $value,
  95. $group,
  96. $propertyPath
  97. );
  98. $context->validateValue($value, $metadata->findConstraints($group));
  99. }
  100. /**
  101. * {@inheritdoc}
  102. */
  103. public function validate($value, $group, $propertyPath, $traverse = false, $deep = false)
  104. {
  105. if (null === $value) {
  106. return;
  107. }
  108. if (is_object($value)) {
  109. $hash = spl_object_hash($value);
  110. // Exit, if the object is already validated for the current group
  111. if (isset($this->validatedObjects[$hash][$group])) {
  112. return;
  113. }
  114. // Initialize if the object wasn't initialized before
  115. if (!isset($this->validatedObjects[$hash])) {
  116. foreach ($this->objectInitializers as $initializer) {
  117. if (!$initializer instanceof ObjectInitializerInterface) {
  118. throw new \LogicException('Validator initializers must implement ObjectInitializerInterface.');
  119. }
  120. $initializer->initialize($value);
  121. }
  122. }
  123. // Remember validating this object before starting and possibly
  124. // traversing the object graph
  125. $this->validatedObjects[$hash][$group] = true;
  126. }
  127. // Validate arrays recursively by default, otherwise every driver needs
  128. // to implement special handling for arrays.
  129. // https://github.com/symfony/symfony/issues/6246
  130. if (is_array($value) || ($traverse && $value instanceof \Traversable)) {
  131. foreach ($value as $key => $element) {
  132. // Ignore any scalar values in the collection
  133. if (is_object($element) || is_array($element)) {
  134. // Only repeat the traversal if $deep is set
  135. $this->validate($element, $group, $propertyPath.'['.$key.']', $deep, $deep);
  136. }
  137. }
  138. try {
  139. $this->metadataFactory->getMetadataFor($value)->accept($this, $value, $group, $propertyPath);
  140. } catch (NoSuchMetadataException $e) {
  141. // Metadata doesn't necessarily have to exist for
  142. // traversable objects, because we know how to validate
  143. // them anyway. Optionally, additional metadata is supported.
  144. }
  145. } else {
  146. $this->metadataFactory->getMetadataFor($value)->accept($this, $value, $group, $propertyPath);
  147. }
  148. }
  149. /**
  150. * {@inheritdoc}
  151. */
  152. public function getViolations()
  153. {
  154. return $this->violations;
  155. }
  156. /**
  157. * {@inheritdoc}
  158. */
  159. public function getRoot()
  160. {
  161. return $this->root;
  162. }
  163. /**
  164. * {@inheritdoc}
  165. */
  166. public function getVisitor()
  167. {
  168. return $this;
  169. }
  170. /**
  171. * {@inheritdoc}
  172. */
  173. public function getValidatorFactory()
  174. {
  175. return $this->validatorFactory;
  176. }
  177. /**
  178. * {@inheritdoc}
  179. */
  180. public function getMetadataFactory()
  181. {
  182. return $this->metadataFactory;
  183. }
  184. }