--- /dev/null
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator;
+
+@trigger_error('The '.__NAMESPACE__.'\ValidationVisitor class is deprecated since version 2.5 and will be removed in 3.0.', E_USER_DEPRECATED);
+
+use Symfony\Component\Translation\TranslatorInterface;
+use Symfony\Component\Validator\Exception\NoSuchMetadataException;
+use Symfony\Component\Validator\Exception\UnexpectedTypeException;
+
+/**
+ * Default implementation of {@link ValidationVisitorInterface} and
+ * {@link GlobalExecutionContextInterface}.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ *
+ * @deprecated since version 2.5, to be removed in 3.0.
+ */
+class ValidationVisitor implements ValidationVisitorInterface, GlobalExecutionContextInterface
+{
+ /**
+ * @var mixed
+ */
+ private $root;
+
+ /**
+ * @var MetadataFactoryInterface
+ */
+ private $metadataFactory;
+
+ /**
+ * @var ConstraintValidatorFactoryInterface
+ */
+ private $validatorFactory;
+
+ /**
+ * @var TranslatorInterface
+ */
+ private $translator;
+
+ /**
+ * @var null|string
+ */
+ private $translationDomain;
+
+ /**
+ * @var array
+ */
+ private $objectInitializers;
+
+ /**
+ * @var ConstraintViolationList
+ */
+ private $violations;
+
+ /**
+ * @var array
+ */
+ private $validatedObjects = array();
+
+ /**
+ * Creates a new validation visitor.
+ *
+ * @param mixed $root The value passed to the validator
+ * @param MetadataFactoryInterface $metadataFactory The factory for obtaining metadata instances
+ * @param ConstraintValidatorFactoryInterface $validatorFactory The factory for creating constraint validators
+ * @param TranslatorInterface $translator The translator for translating violation messages
+ * @param string|null $translationDomain The domain of the translation messages
+ * @param ObjectInitializerInterface[] $objectInitializers The initializers for preparing objects before validation
+ *
+ * @throws UnexpectedTypeException If any of the object initializers is not an instance of ObjectInitializerInterface
+ */
+ public function __construct($root, MetadataFactoryInterface $metadataFactory, ConstraintValidatorFactoryInterface $validatorFactory, TranslatorInterface $translator, $translationDomain = null, array $objectInitializers = array())
+ {
+ foreach ($objectInitializers as $initializer) {
+ if (!$initializer instanceof ObjectInitializerInterface) {
+ throw new UnexpectedTypeException($initializer, 'Symfony\Component\Validator\ObjectInitializerInterface');
+ }
+ }
+
+ $this->root = $root;
+ $this->metadataFactory = $metadataFactory;
+ $this->validatorFactory = $validatorFactory;
+ $this->translator = $translator;
+ $this->translationDomain = $translationDomain;
+ $this->objectInitializers = $objectInitializers;
+ $this->violations = new ConstraintViolationList();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function visit(MetadataInterface $metadata, $value, $group, $propertyPath)
+ {
+ $context = new ExecutionContext(
+ $this,
+ $this->translator,
+ $this->translationDomain,
+ $metadata,
+ $value,
+ $group,
+ $propertyPath
+ );
+
+ $context->validateValue($value, $metadata->findConstraints($group));
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function validate($value, $group, $propertyPath, $traverse = false, $deep = false)
+ {
+ if (null === $value) {
+ return;
+ }
+
+ if (is_object($value)) {
+ $hash = spl_object_hash($value);
+
+ // Exit, if the object is already validated for the current group
+ if (isset($this->validatedObjects[$hash][$group])) {
+ return;
+ }
+
+ // Initialize if the object wasn't initialized before
+ if (!isset($this->validatedObjects[$hash])) {
+ foreach ($this->objectInitializers as $initializer) {
+ if (!$initializer instanceof ObjectInitializerInterface) {
+ throw new \LogicException('Validator initializers must implement ObjectInitializerInterface.');
+ }
+ $initializer->initialize($value);
+ }
+ }
+
+ // Remember validating this object before starting and possibly
+ // traversing the object graph
+ $this->validatedObjects[$hash][$group] = true;
+ }
+
+ // Validate arrays recursively by default, otherwise every driver needs
+ // to implement special handling for arrays.
+ // https://github.com/symfony/symfony/issues/6246
+ if (is_array($value) || ($traverse && $value instanceof \Traversable)) {
+ foreach ($value as $key => $element) {
+ // Ignore any scalar values in the collection
+ if (is_object($element) || is_array($element)) {
+ // Only repeat the traversal if $deep is set
+ $this->validate($element, $group, $propertyPath.'['.$key.']', $deep, $deep);
+ }
+ }
+
+ try {
+ $this->metadataFactory->getMetadataFor($value)->accept($this, $value, $group, $propertyPath);
+ } catch (NoSuchMetadataException $e) {
+ // Metadata doesn't necessarily have to exist for
+ // traversable objects, because we know how to validate
+ // them anyway. Optionally, additional metadata is supported.
+ }
+ } else {
+ $this->metadataFactory->getMetadataFor($value)->accept($this, $value, $group, $propertyPath);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getViolations()
+ {
+ return $this->violations;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getRoot()
+ {
+ return $this->root;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getVisitor()
+ {
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getValidatorFactory()
+ {
+ return $this->validatorFactory;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getMetadataFactory()
+ {
+ return $this->metadataFactory;
+ }
+}