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