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\Util\PropertyPath;
10use Symfony\Component\Validator\Violation\ConstraintViolationBuilderInterface;
11
12/**
13 * Defines a constraint violation builder for the Typed Data validator.
14 *
15 * We do not use the builder provided by Symfony as it is marked internal.
16 *
17 * @codingStandardsIgnoreStart
18 */
19class ConstraintViolationBuilder implements ConstraintViolationBuilderInterface {
20
21  /**
22   * The list of violations.
23   *
24   * @var \Symfony\Component\Validator\ConstraintViolationList
25   */
26  protected $violations;
27
28  /**
29   * The violation message.
30   *
31   * @var string
32   */
33  protected $message;
34
35  /**
36   * The message parameters.
37   *
38   * @var array
39   */
40  protected $parameters;
41
42  /**
43   * The root path.
44   *
45   * @var mixed
46   */
47  protected $root;
48
49  /**
50   * The invalid value caused the violation.
51   *
52   * @var mixed
53   */
54  protected $invalidValue;
55
56  /**
57   * The property path.
58   *
59   * @var string
60   */
61  protected $propertyPath;
62
63  /**
64   * The translator.
65   *
66   * @var \Drupal\Core\Validation\TranslatorInterface
67   */
68  protected $translator;
69
70  /**
71   * The translation domain.
72   *
73   * @var string|null
74   */
75  protected $translationDomain;
76
77  /**
78   * The number used
79   * @var int|null
80   */
81  protected $plural;
82
83  /**
84   * @var Constraint
85   */
86  protected $constraint;
87
88  /**
89   * @var mixed
90   */
91  protected $code;
92
93  /**
94   * @var mixed
95   */
96  protected $cause;
97
98  /**
99   * Constructs a new ConstraintViolationBuilder instance.
100   *
101   * @param \Symfony\Component\Validator\ConstraintViolationList $violations
102   *   The violation list.
103   * @param \Symfony\Component\Validator\Constraint $constraint
104   *   The constraint.
105   * @param string $message
106   *   The message.
107   * @param array $parameters
108   *   The message parameters.
109   * @param mixed $root
110   *   The root.
111   * @param string $propertyPath
112   *   The property string.
113   * @param mixed $invalidValue
114   *   The invalid value.
115   * @param \Drupal\Core\Validation\TranslatorInterface $translator
116   *   The translator.
117   * @param null $translationDomain
118   *   (optional) The translation domain.
119   */
120  public function __construct(ConstraintViolationList $violations, Constraint $constraint, $message, array $parameters, $root, $propertyPath, $invalidValue, TranslatorInterface $translator, $translationDomain = null)
121    {
122      $this->violations = $violations;
123      $this->message = $message;
124      $this->parameters = $parameters;
125      $this->root = $root;
126      $this->propertyPath = $propertyPath;
127      $this->invalidValue = $invalidValue;
128      $this->translator = $translator;
129      $this->translationDomain = $translationDomain;
130      $this->constraint = $constraint;
131    }
132
133    /**
134     * {@inheritdoc}
135     */
136    public function atPath($path)
137    {
138      $this->propertyPath = PropertyPath::append($this->propertyPath, $path);
139
140      return $this;
141    }
142
143    /**
144     * {@inheritdoc}
145     */
146    public function setParameter($key, $value)
147    {
148      $this->parameters[$key] = $value;
149
150      return $this;
151    }
152
153    /**
154     * {@inheritdoc}
155     */
156    public function setParameters(array $parameters)
157    {
158      $this->parameters = $parameters;
159
160      return $this;
161    }
162
163    /**
164     * {@inheritdoc}
165     */
166    public function setTranslationDomain($translationDomain)
167    {
168      $this->translationDomain = $translationDomain;
169
170      return $this;
171    }
172
173    /**
174     * {@inheritdoc}
175     */
176    public function setInvalidValue($invalidValue)
177    {
178      $this->invalidValue = $invalidValue;
179
180      return $this;
181    }
182
183    /**
184     * {@inheritdoc}
185     */
186    public function setPlural($number)
187    {
188      $this->plural = $number;
189
190      return $this;
191    }
192
193    /**
194     * {@inheritdoc}
195     */
196    public function setCode($code)
197    {
198      $this->code = $code;
199
200      return $this;
201    }
202
203    /**
204     * {@inheritdoc}
205     */
206    public function setCause($cause)
207    {
208      $this->cause = $cause;
209
210      return $this;
211    }
212
213    /**
214     * {@inheritdoc}
215     */
216    public function addViolation()
217    {
218      if (null === $this->plural) {
219        $translatedMessage = $this->translator->trans(
220          $this->message,
221          $this->parameters,
222          $this->translationDomain
223        );
224      } else {
225        try {
226          $translatedMessage = $this->translator->transChoice(
227            $this->message,
228            $this->plural,
229            $this->parameters,
230            $this->translationDomain#
231          );
232        } catch (\InvalidArgumentException $e) {
233          $translatedMessage = $this->translator->trans(
234            $this->message,
235            $this->parameters,
236            $this->translationDomain
237          );
238        }
239      }
240
241      $this->violations->add(new ConstraintViolation(
242        $translatedMessage,
243        $this->message,
244        $this->parameters,
245        $this->root,
246        $this->propertyPath,
247        $this->invalidValue,
248        $this->plural,
249        $this->code,
250        $this->constraint,
251        $this->cause
252      ));
253    }
254}
255