[BUGFIX] Fix several typos in php comments
[Packages/TYPO3.CMS.git] / typo3 / sysext / extbase / Classes / Validation / Validator / GenericObjectValidator.php
1 <?php
2 namespace TYPO3\CMS\Extbase\Validation\Validator;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 use TYPO3\CMS\Extbase\Reflection\ObjectAccess;
18
19 /**
20 * A generic object validator which allows for specifying property validators
21 */
22 class GenericObjectValidator extends AbstractValidator implements ObjectValidatorInterface
23 {
24 /**
25 * @var \SplObjectStorage[]
26 */
27 protected $propertyValidators = [];
28
29 /**
30 * Checks if the given value is valid according to the validator, and returns
31 * the Error Messages object which occurred.
32 *
33 * @param mixed $value The value that should be validated
34 * @return \TYPO3\CMS\Extbase\Error\Result
35 */
36 public function validate($value)
37 {
38 if (is_object($value) && $this->isValidatedAlready($value)) {
39 return $this->result;
40 }
41
42 $this->result = new \TYPO3\CMS\Extbase\Error\Result();
43 if ($this->acceptsEmptyValues === false || $this->isEmpty($value) === false) {
44 if (!is_object($value)) {
45 $this->addError('Object expected, %1$s given.', 1241099149, [gettype($value)]);
46 } elseif ($this->isValidatedAlready($value) === false) {
47 $this->markInstanceAsValidated($value);
48 $this->isValid($value);
49 }
50 }
51
52 return $this->result;
53 }
54
55 /**
56 * Load the property value to be used for validation.
57 *
58 * In case the object is a doctrine proxy, we need to load the real instance first.
59 *
60 * @param object $object
61 * @param string $propertyName
62 * @return mixed
63 */
64 protected function getPropertyValue($object, $propertyName)
65 {
66 // @todo add support for lazy loading proxies, if needed
67 if (ObjectAccess::isPropertyGettable($object, $propertyName)) {
68 return ObjectAccess::getProperty($object, $propertyName);
69 }
70 throw new \RuntimeException(
71 sprintf(
72 'Could not get value of property "%s::%s", make sure the property is either public or has a getter get%3$s(), a hasser has%3$s() or an isser is%3$s().',
73 get_class($object),
74 $propertyName,
75 ucfirst($propertyName)
76 ),
77 1546632293
78 );
79 }
80
81 /**
82 * Checks if the specified property of the given object is valid, and adds
83 * found errors to the $messages object.
84 *
85 * @param mixed $value The value to be validated
86 * @param \Traversable $validators The validators to be called on the value
87 * @param string $propertyName Name of the property to check
88 */
89 protected function checkProperty($value, $validators, $propertyName)
90 {
91 /** @var \TYPO3\CMS\Extbase\Error\Result $result */
92 $result = null;
93 foreach ($validators as $validator) {
94 if ($validator instanceof ObjectValidatorInterface) {
95 $validator->setValidatedInstancesContainer($this->validatedInstancesContainer);
96 }
97 $currentResult = $validator->validate($value);
98 if ($currentResult->hasMessages()) {
99 if ($result == null) {
100 $result = $currentResult;
101 } else {
102 $result->merge($currentResult);
103 }
104 }
105 }
106 if ($result != null) {
107 $this->result->forProperty($propertyName)->merge($result);
108 }
109 }
110
111 /**
112 * Checks if the given value is valid according to the property validators.
113 *
114 * @param mixed $object The value that should be validated
115 */
116 protected function isValid($object)
117 {
118 foreach ($this->propertyValidators as $propertyName => $validators) {
119 $propertyValue = $this->getPropertyValue($object, $propertyName);
120 $this->checkProperty($propertyValue, $validators, $propertyName);
121 }
122 }
123
124 /**
125 * Checks the given object can be validated by the validator implementation
126 *
127 * @param mixed $object The object to be checked
128 * @return bool TRUE if the given value is an object
129 */
130 public function canValidate($object)
131 {
132 return is_object($object);
133 }
134
135 /**
136 * Adds the given validator for validation of the specified property.
137 *
138 * @param string $propertyName Name of the property to validate
139 * @param ValidatorInterface $validator The property validator
140 */
141 public function addPropertyValidator($propertyName, ValidatorInterface $validator)
142 {
143 if (!isset($this->propertyValidators[$propertyName])) {
144 $this->propertyValidators[$propertyName] = new \SplObjectStorage();
145 }
146 $this->propertyValidators[$propertyName]->attach($validator);
147 }
148
149 /**
150 * @param object $object
151 * @return bool
152 */
153 protected function isValidatedAlready($object)
154 {
155 if ($this->validatedInstancesContainer === null) {
156 $this->validatedInstancesContainer = new \SplObjectStorage();
157 }
158 if ($this->validatedInstancesContainer->contains($object)) {
159 return true;
160 }
161
162 return false;
163 }
164
165 /**
166 * @param $object
167 */
168 protected function markInstanceAsValidated($object): void
169 {
170 $this->validatedInstancesContainer->attach($object);
171 }
172
173 /**
174 * Returns all property validators - or only validators of the specified property
175 *
176 * @param string $propertyName Name of the property to return validators for
177 * @return array An array of validators
178 */
179 public function getPropertyValidators($propertyName = null)
180 {
181 if ($propertyName !== null) {
182 return $this->propertyValidators[$propertyName] ?? [];
183 }
184 return $this->propertyValidators;
185 }
186
187 /**
188 * @var \SplObjectStorage
189 */
190 protected $validatedInstancesContainer;
191
192 /**
193 * Allows to set a container to keep track of validated instances.
194 *
195 * @param \SplObjectStorage $validatedInstancesContainer A container to keep track of validated instances
196 */
197 public function setValidatedInstancesContainer(\SplObjectStorage $validatedInstancesContainer)
198 {
199 $this->validatedInstancesContainer = $validatedInstancesContainer;
200 }
201 }