Revert "[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 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 if (strpos($propertyPath, '.') !== FALSE) {
212 return $this->recurseThroughResult(explode('.', $propertyPath));
213 }
214 if (!isset($this->propertyResults[$propertyPath])) {
215 $this->propertyResults[$propertyPath] = new Result();
216 $this->propertyResults[$propertyPath]->setParent($this);
217 }
218 return $this->propertyResults[$propertyPath];
219 }
220
221 /**
222 * Internal use only!
223 *
224 * @param array $pathSegments
225 * @return \TYPO3\CMS\Extbase\Error\Result
226 */
227 public function recurseThroughResult(array $pathSegments) {
228 if (count($pathSegments) === 0) {
229 return $this;
230 }
231
232 $propertyName = array_shift($pathSegments);
233
234 if (!isset($this->propertyResults[$propertyName])) {
235 $this->propertyResults[$propertyName] = new Result();
236 $this->propertyResults[$propertyName]->setParent($this);
237 }
238
239 return $this->propertyResults[$propertyName]->recurseThroughResult($pathSegments);
240 }
241
242 /**
243 * Sets the error cache to TRUE and propagates the information
244 * upwards the Result-Object Tree
245 *
246 * @return void
247 */
248 protected function setErrorsExist() {
249 $this->errorsExist = TRUE;
250 if ($this->parent !== NULL) {
251 $this->parent->setErrorsExist();
252 }
253 }
254
255 /**
256 * Sets the warning cache to TRUE and propagates the information
257 * upwards the Result-Object Tree
258 *
259 * @return void
260 */
261 protected function setWarningsExist() {
262 $this->warningsExist = TRUE;
263 if ($this->parent !== NULL) {
264 $this->parent->setWarningsExist();
265 }
266 }
267
268 /**
269 * Sets the notices cache to TRUE and propagates the information
270 * upwards the Result-Object Tree
271 *
272 * @return void
273 */
274 protected function setNoticesExist() {
275 $this->noticesExist = TRUE;
276 if ($this->parent !== NULL) {
277 $this->parent->setNoticesExist();
278 }
279 }
280
281 /**
282 * Does the current Result object have Notices, Errors or Warnings? (Recursively)
283 *
284 * @return boolean
285 */
286 public function hasMessages() {
287 return $this->errorsExist || $this->noticesExist || $this->warningsExist;
288 }
289
290 /**
291 * Clears the result
292 *
293 * @return void
294 */
295 public function clear() {
296 $this->errors = array();
297 $this->notices = array();
298 $this->warnings = array();
299
300 $this->warningsExist = FALSE;
301 $this->noticesExist = FALSE;
302 $this->errorsExist = FALSE;
303
304 $this->propertyResults = array();
305 }
306
307 /**
308 * Internal use only!
309 *
310 * @param string $propertyName
311 * @param string $checkerMethodName
312 * @return boolean
313 */
314 protected function hasProperty($propertyName, $checkerMethodName) {
315 if (count($this->{$propertyName}) > 0) {
316 return TRUE;
317 }
318 foreach ($this->propertyResults as $subResult) {
319 if ($subResult->{$checkerMethodName}()) {
320 return TRUE;
321 }
322 }
323 return FALSE;
324 }
325
326 /**
327 * Does the current Result object have Errors? (Recursively)
328 *
329 * @return boolean
330 * @api
331 */
332 public function hasErrors() {
333 return $this->hasProperty('errors', 'hasErrors');
334 }
335
336 /**
337 * Does the current Result object have Warnings? (Recursively)
338 *
339 * @return boolean
340 * @api
341 */
342 public function hasWarnings() {
343 return $this->hasProperty('warnings', 'hasWarnings');
344 }
345
346 /**
347 * Does the current Result object have Notices? (Recursively)
348 *
349 * @return boolean
350 * @api
351 */
352 public function hasNotices() {
353 return $this->hasProperty('notices', 'hasNotices');
354 }
355
356 /**
357 * Get a list of all Error objects recursively. The result is an array,
358 * where the key is the property path where the error occurred, and the
359 * value is a list of all errors (stored as array)
360 *
361 * @return array<\TYPO3\CMS\Extbase\Error\Error>
362 * @api
363 */
364 public function getFlattenedErrors() {
365 $result = array();
366 $this->flattenTree('errors', $result, array());
367 return $result;
368 }
369
370 /**
371 * Get a list of all Warning objects recursively. The result is an array,
372 * where the key is the property path where the warning occurred, and the
373 * value is a list of all warnings (stored as array)
374 *
375 * @return array<\TYPO3\CMS\Extbase\Error\Warning>
376 * @api
377 */
378 public function getFlattenedWarnings() {
379 $result = array();
380 $this->flattenTree('warnings', $result, array());
381 return $result;
382 }
383
384 /**
385 * Get a list of all Notice objects recursively. The result is an array,
386 * where the key is the property path where the notice occurred, and the
387 * value is a list of all notices (stored as array)
388 *
389 * @return array<\TYPO3\CMS\Extbase\Error\Notice>
390 * @api
391 */
392 public function getFlattenedNotices() {
393 $result = array();
394 $this->flattenTree('notices', $result, array());
395 return $result;
396 }
397
398 /**
399 * Only use internally!
400 *
401 * Flatten a tree of Result objects, based on a certain property.
402 *
403 * @param string $propertyName
404 * @param array $result
405 * @param array $level
406 * @return void
407 */
408 public function flattenTree($propertyName, &$result, $level) {
409 if (count($this->$propertyName) > 0) {
410 $result[implode('.', $level)] = $this->$propertyName;
411 }
412 foreach ($this->propertyResults as $subPropertyName => $subResult) {
413 array_push($level, $subPropertyName);
414 $subResult->flattenTree($propertyName, $result, $level);
415 array_pop($level);
416 }
417 }
418
419 /**
420 * Merge the given Result object into this one.
421 *
422 * @param \TYPO3\CMS\Extbase\Error\Result $otherResult
423 * @return void
424 * @api
425 */
426 public function merge(Result $otherResult) {
427 if ($otherResult->errorsExist) {
428 $this->mergeProperty($otherResult, 'getErrors', 'addError');
429 }
430 if ($otherResult->warningsExist) {
431 $this->mergeProperty($otherResult, 'getWarnings', 'addWarning');
432 }
433 if ($otherResult->noticesExist) {
434 $this->mergeProperty($otherResult, 'getNotices', 'addNotice');
435 }
436
437 foreach ($otherResult->getSubResults() as $subPropertyName => $subResult) {
438 /** @var $subResult Result */
439 if (array_key_exists($subPropertyName, $this->propertyResults) && $this->propertyResults[$subPropertyName]->hasMessages()) {
440 $this->forProperty($subPropertyName)->merge($subResult);
441 } else {
442 $this->propertyResults[$subPropertyName] = $subResult;
443 $subResult->setParent($this);
444 }
445 }
446 }
447
448 /**
449 * Merge a single property from the other result object.
450 *
451 * @param \TYPO3\CMS\Extbase\Error\Result $otherResult
452 * @param string $getterName
453 * @param string $adderName
454 * @return void
455 */
456 protected function mergeProperty(Result $otherResult, $getterName, $adderName) {
457 foreach ($otherResult->$getterName() as $messageInOtherResult) {
458 $this->$adderName($messageInOtherResult);
459 }
460 }
461
462 /**
463 * Get a list of all sub Result objects available.
464 *
465 * @return array<\TYPO3\CMS\Extbase\Error\Result>
466 */
467 public function getSubResults() {
468 return $this->propertyResults;
469 }
470 }