1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Component\Validator\Validator;
13
14use Symfony\Component\Validator\ConstraintValidatorFactoryInterface;
15use Symfony\Component\Validator\Context\ExecutionContextFactoryInterface;
16use Symfony\Component\Validator\Context\ExecutionContextInterface;
17use Symfony\Component\Validator\MetadataFactoryInterface;
18use Symfony\Component\Validator\ObjectInitializerInterface;
19
20/**
21 * Recursive implementation of {@link ValidatorInterface}.
22 *
23 * @since  2.5
24 * @author Bernhard Schussek <bschussek@gmail.com>
25 */
26class RecursiveValidator implements ValidatorInterface
27{
28    /**
29     * @var ExecutionContextFactoryInterface
30     */
31    protected $contextFactory;
32
33    /**
34     * @var MetadataFactoryInterface
35     */
36    protected $metadataFactory;
37
38    /**
39     * @var ConstraintValidatorFactoryInterface
40     */
41    protected $validatorFactory;
42
43    /**
44     * @var ObjectInitializerInterface[]
45     */
46    protected $objectInitializers;
47
48    /**
49     * Creates a new validator.
50     *
51     * @param ExecutionContextFactoryInterface    $contextFactory     The factory for
52     *                                                                creating new contexts
53     * @param MetadataFactoryInterface            $metadataFactory    The factory for
54     *                                                                fetching the metadata
55     *                                                                of validated objects
56     * @param ConstraintValidatorFactoryInterface $validatorFactory   The factory for creating
57     *                                                                constraint validators
58     * @param ObjectInitializerInterface[]        $objectInitializers The object initializers
59     */
60    public function __construct(ExecutionContextFactoryInterface $contextFactory, MetadataFactoryInterface $metadataFactory, ConstraintValidatorFactoryInterface $validatorFactory, array $objectInitializers = array())
61    {
62        $this->contextFactory = $contextFactory;
63        $this->metadataFactory = $metadataFactory;
64        $this->validatorFactory = $validatorFactory;
65        $this->objectInitializers = $objectInitializers;
66    }
67
68    /**
69     * {@inheritdoc}
70     */
71    public function startContext($root = null)
72    {
73        return new RecursiveContextualValidator(
74            $this->contextFactory->createContext($this, $root),
75            $this->metadataFactory,
76            $this->validatorFactory,
77            $this->objectInitializers
78        );
79    }
80
81    /**
82     * {@inheritdoc}
83     */
84    public function inContext(ExecutionContextInterface $context)
85    {
86        return new RecursiveContextualValidator(
87            $context,
88            $this->metadataFactory,
89            $this->validatorFactory,
90            $this->objectInitializers
91        );
92    }
93
94    /**
95     * {@inheritdoc}
96     */
97    public function getMetadataFor($object)
98    {
99        return $this->metadataFactory->getMetadataFor($object);
100    }
101
102    /**
103     * {@inheritdoc}
104     */
105    public function hasMetadataFor($object)
106    {
107        return $this->metadataFactory->hasMetadataFor($object);
108    }
109
110    /**
111     * {@inheritdoc}
112     */
113    public function validate($value, $constraints = null, $groups = null)
114    {
115        return $this->startContext($value)
116            ->validate($value, $constraints, $groups)
117            ->getViolations();
118    }
119
120    /**
121     * {@inheritdoc}
122     */
123    public function validateProperty($object, $propertyName, $groups = null)
124    {
125        return $this->startContext($object)
126            ->validateProperty($object, $propertyName, $groups)
127            ->getViolations();
128    }
129
130    /**
131     * {@inheritdoc}
132     */
133    public function validatePropertyValue($objectOrClass, $propertyName, $value, $groups = null)
134    {
135        // If a class name is passed, take $value as root
136        return $this->startContext(is_object($objectOrClass) ? $objectOrClass : $value)
137            ->validatePropertyValue($objectOrClass, $propertyName, $value, $groups)
138            ->getViolations();
139    }
140}
141