[TASK] Make preperations for backporting Flow validation api
[Packages/TYPO3.CMS.git] / typo3 / sysext / extbase / Classes / Error / Result.php
1 <?php
2 namespace TYPO3\CMS\Extbase\Error;
3
4 /* *
5 * This script belongs to the Extbase framework *
6 * *
7 * It is free software; you can redistribute it and/or modify it under *
8 * the terms of the GNU Lesser General Public License as published by the *
9 * Free Software Foundation, either version 3 of the License, or (at your *
10 * option) any later version. *
11 * *
12 * This script is distributed in the hope that it will be useful, but *
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- *
14 * TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser *
15 * General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU Lesser General Public *
18 * License along with the script. *
19 * If not, see http://www.gnu.org/licenses/lgpl.html *
20 * *
21 * The TYPO3 project - inspiring people to share! *
22 * */
23 /**
24 * Result object for operations dealing with objects, such as the Property Mapper or the Validators.
25 *
26 * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License, version 3 or later
27 * @api
28 */
29 class Result {
30
31 /**
32 * @var array<\TYPO3\CMS\Extbase\Error\Error>
33 */
34 protected $errors = array();
35
36 /**
37 * Caches the existence of errors
38 * @var boolean
39 */
40 protected $errorsExist = FALSE;
41
42 /**
43 * @var array<\TYPO3\CMS\Extbase\Error\Warning>
44 */
45 protected $warnings = array();
46
47 /**
48 * Caches the existence of warning
49 * @var boolean
50 */
51 protected $warningsExist = FALSE;
52
53 /**
54 * @var array<\TYPO3\CMS\Extbase\Error\Notice>
55 */
56 protected $notices = array();
57
58 /**
59 * Caches the existence of notices
60 * @var boolean
61 */
62 protected $noticesExist = FALSE;
63
64 /**
65 * The result objects for the sub properties
66 *
67 * @var array<\TYPO3\CMS\Extbase\Error\Result>
68 */
69 protected $propertyResults = array();
70
71 /**
72 * @var \TYPO3\CMS\Extbase\Error\Result
73 */
74 protected $parent = NULL;
75
76 /**
77 * Injects the parent result and propagates the
78 * cached error states upwards
79 *
80 * @param \TYPO3\CMS\Extbase\Error\Error $parent
81 * @return void
82 */
83 public function setParent(Result $parent) {
84 if ($this->parent !== $parent) {
85 $this->parent = $parent;
86 if ($this->hasErrors()) {
87 $parent->setErrorsExist();
88 }
89 if ($this->hasWarnings()) {
90 $parent->setWarningsExist();
91 }
92 if ($this->hasNotices()) {
93 $parent->setNoticesExist();
94 }
95 }
96 }
97
98 /**
99 * Add an error to the current Result object
100 *
101 * @param \TYPO3\CMS\Extbase\Error\Error $error
102 * @return void
103 * @api
104 */
105 public function addError(\TYPO3\CMS\Extbase\Error\Error $error) {
106 $this->errors[] = $error;
107 $this->setErrorsExist();
108 }
109
110 /**
111 * Add a warning to the current Result object
112 *
113 * @param \TYPO3\CMS\Extbase\Error\Warning $warning
114 * @return void
115 * @api
116 */
117 public function addWarning(\TYPO3\CMS\Extbase\Error\Warning $warning) {
118 $this->warnings[] = $warning;
119 $this->setWarningsExist();
120 }
121
122 /**
123 * Add a notice to the current Result object
124 *
125 * @param \TYPO3\CMS\Extbase\Error\Notice $notice
126 * @return void
127 * @api
128 */
129 public function addNotice(\TYPO3\CMS\Extbase\Error\Notice $notice) {
130 $this->notices[] = $notice;
131 $this->setNoticesExist();
132 }
133
134 /**
135 * Get all errors in the current Result object (non-recursive)
136 *
137 * @return array<\TYPO3\CMS\Extbase\Error\Error>
138 * @api
139 */
140 public function getErrors() {
141 return $this->errors;
142 }
143
144 /**
145 * Get all warnings in the current Result object (non-recursive)
146 *
147 * @return array<\TYPO3\CMS\Extbase\Error\Warning>
148 * @api
149 */
150 public function getWarnings() {
151 return $this->warnings;
152 }
153
154 /**
155 * Get all notices in the current Result object (non-recursive)
156 *
157 * @return array<\TYPO3\CMS\Extbase\Error\Notice>
158 * @api
159 */
160 public function getNotices() {
161 return $this->notices;
162 }
163
164 /**
165 * Get the first error object of the current Result object (non-recursive)
166 *
167 * @return \TYPO3\CMS\Extbase\Error\Error
168 * @api
169 */
170 public function getFirstError() {
171 reset($this->errors);
172 return current($this->errors);
173 }
174
175 /**
176 * Get the first warning object of the current Result object (non-recursive)
177 *
178 * @return \TYPO3\CMS\Extbase\Error\Warning
179 * @api
180 */
181 public function getFirstWarning() {
182 reset($this->warnings);
183 return current($this->warnings);
184 }
185
186 /**
187 * Get the first notice object of the curren Result object (non-recursive)
188 *
189 * @return \TYPO3\CMS\Extbase\Error\Notice
190 * @api
191 */
192 public function getFirstNotice() {
193 reset($this->notices);
194 return current($this->notices);
195 }
196
197 /**
198 * Return a Result object for the given property path. This is
199 * a fluent interface, so you will proboably use it like:
200 * $result->forProperty('foo.bar')->getErrors() -- to get all errors
201 * for property "foo.bar"
202 *
203 * @param string $propertyPath
204 * @return \TYPO3\CMS\Extbase\Error\Result
205 * @api
206 */
207 public function forProperty($propertyPath) {
208 if ($propertyPath === '' || $propertyPath === NULL) {
209 return $this;
210 }
211 $propertyPathSegments = explode('.', $propertyPath);
212 return $this->recurseThroughResult($propertyPathSegments);
213 }
214
215 /**
216 * Internal use only!
217 *
218 * @param array $pathSegments
219 * @return \TYPO3\CMS\Extbase\Error\Result
220 */
221 public function recurseThroughResult(array $pathSegments) {
222 if (count($pathSegments) === 0) {
223 return $this;
224 }
225
226 $propertyName = array_shift($pathSegments);
227
228 if (!isset($this->propertyResults[$propertyName])) {
229 $this->propertyResults[$propertyName] = new Result();
230 }
231
232 return $this->propertyResults[$propertyName]->recurseThroughResult($pathSegments);
233 }
234
235 /**
236 * Sets the error cache to TRUE and propagates the information
237 * upwards the Result-Object Tree
238 *
239 * @return void
240 */
241 protected function setErrorsExist() {
242 $this->errorsExist = TRUE;
243 if ($this->parent !== NULL) {
244 $this->parent->setErrorsExist();
245 }
246 }
247
248 /**
249 * Sets the warning cache to TRUE and propagates the information
250 * upwards the Result-Object Tree
251 *
252 * @return void
253 */
254 protected function setWarningsExist() {
255 $this->warningsExist = TRUE;
256 if ($this->parent !== NULL) {
257 $this->parent->setWarningsExist();
258 }
259 }
260
261 /**
262 * Sets the notices cache to TRUE and propagates the information
263 * upwards the Result-Object Tree
264 *
265 * @return void
266 */
267 protected function setNoticesExist() {
268 $this->noticesExist = TRUE;
269 if ($this->parent !== NULL) {
270 $this->parent->setNoticesExist();
271 }
272 }
273
274 /**
275 * Does the current Result object have Notices, Errors or Warnings? (Recursively)
276 *
277 * @return boolean
278 */
279 public function hasMessages() {
280 return $this->errorsExist || $this->noticesExist || $this->warningsExist;
281 }
282
283 /**
284 * Clears the result
285 *
286 * @return void
287 */
288 public function clear() {
289 $this->errors = array();
290 $this->notices = array();
291 $this->warnings = array();
292
293 $this->warningsExist = FALSE;
294 $this->noticesExist = FALSE;
295 $this->errorsExist = FALSE;
296
297 $this->propertyResults = array();
298 }
299
300 /**
301 * Internal use only!
302 *
303 * @param string $propertyName
304 * @param string $checkerMethodName
305 * @return boolean
306 */
307 protected function hasProperty($propertyName, $checkerMethodName) {
308 if (count($this->{$propertyName}) > 0) {
309 return TRUE;
310 }
311 foreach ($this->propertyResults as $subResult) {
312 if ($subResult->{$checkerMethodName}()) {
313 return TRUE;
314 }
315 }
316 return FALSE;
317 }
318
319 /**
320 * Does the current Result object have Errors? (Recursively)
321 *
322 * @return boolean
323 * @api
324 */
325 public function hasErrors() {
326 return $this->hasProperty('errors', 'hasErrors');
327 }
328
329 /**
330 * Does the current Result object have Warnings? (Recursively)
331 *
332 * @return boolean
333 * @api
334 */
335 public function hasWarnings() {
336 return $this->hasProperty('warnings', 'hasWarnings');
337 }
338
339 /**
340 * Does the current Result object have Notices? (Recursively)
341 *
342 * @return boolean
343 * @api
344 */
345 public function hasNotices() {
346 return $this->hasProperty('notices', 'hasNotices');
347 }
348
349 /**
350 * Get a list of all Error objects recursively. The result is an array,
351 * where the key is the property path where the error occurred, and the
352 * value is a list of all errors (stored as array)
353 *
354 * @return array<\TYPO3\CMS\Extbase\Error\Error>
355 * @api
356 */
357 public function getFlattenedErrors() {
358 $result = array();
359 $this->flattenTree('errors', $result, array());
360 return $result;
361 }
362
363 /**
364 * Get a list of all Warning objects recursively. The result is an array,
365 * where the key is the property path where the warning occured, and the
366 * value is a list of all warnings (stored as array)
367 *
368 * @return array<\TYPO3\CMS\Extbase\Error\Warning>
369 * @api
370 */
371 public function getFlattenedWarnings() {
372 $result = array();
373 $this->flattenTree('warnings', $result, array());
374 return $result;
375 }
376
377 /**
378 * Get a list of all Notice objects recursively. The result is an array,
379 * where the key is the property path where the notice occurred, and the
380 * value is a list of all notices (stored as array)
381 *
382 * @return array<\TYPO3\CMS\Extbase\Error\Notice>
383 * @api
384 */
385 public function getFlattenedNotices() {
386 $result = array();
387 $this->flattenTree('notices', $result, array());
388 return $result;
389 }
390
391 /**
392 * Only use internally!
393 *
394 * Flatten a tree of Result objects, based on a certain property.
395 *
396 * @param string $propertyName
397 * @param array $result
398 * @param array $level
399 * @return void
400 */
401 public function flattenTree($propertyName, &$result, $level) {
402 if (count($this->$propertyName) > 0) {
403 $result[implode('.', $level)] = $this->$propertyName;
404 }
405 foreach ($this->propertyResults as $subPropertyName => $subResult) {
406 array_push($level, $subPropertyName);
407 $subResult->flattenTree($propertyName, $result, $level);
408 array_pop($level);
409 }
410 }
411
412 /**
413 * Merge the given Result object into this one.
414 *
415 * @param \TYPO3\CMS\Extbase\Error\Result $otherResult
416 * @return void
417 * @api
418 */
419 public function merge(\TYPO3\CMS\Extbase\Error\Result $otherResult) {
420 $this->mergeProperty($otherResult, 'getErrors', 'addError');
421 $this->mergeProperty($otherResult, 'getWarnings', 'addWarning');
422 $this->mergeProperty($otherResult, 'getNotices', 'addNotice');
423 foreach ($otherResult->getSubResults() as $subPropertyName => $subResult) {
424 $this->forProperty($subPropertyName)->merge($subResult);
425 }
426 }
427
428 /**
429 * Merge a single property from the other result object.
430 *
431 * @param \TYPO3\CMS\Extbase\Error\Result $otherResult
432 * @param string $getterName
433 * @param string $adderName
434 * @return void
435 */
436 protected function mergeProperty(Result $otherResult, $getterName, $adderName) {
437 foreach ($otherResult->$getterName() as $messageInOtherResult) {
438 $this->$adderName($messageInOtherResult);
439 }
440 }
441
442 /**
443 * Get a list of all sub Result objects available.
444 *
445 * @return array<\TYPO3\CMS\Extbase\Error\Result>
446 */
447 public function getSubResults() {
448 return $this->propertyResults;
449 }
450 }
451
452 ?>