[!!!][FEATURE] Improve error and message handling
authorSebastian Kurfuerst <sebastian@typo3.org>
Tue, 21 Jun 2011 07:17:14 +0000 (09:17 +0200)
committerSebastian Kurfuerst <sebastian@typo3.org>
Thu, 30 Jun 2011 05:27:35 +0000 (07:27 +0200)
ERROR HANDLING:
- Error\Result as base class for generic "Results" (used by validation
  and by Property Mapping)
- Error\Message as base class for a generic error message, with
  subclasses Error, Warning and Notice.

This is a backport of f25803698d14e994a8c6582c6d47299ded2ca567 from FLOW3.

Resolves: #27650
Related: #27059
Change-Id: I6882744fb0121f2faa7733b250bef88b34e550a9

typo3/sysext/extbase/Classes/Error/Error.php
typo3/sysext/extbase/Classes/Error/Message.php [new file with mode: 0644]
typo3/sysext/extbase/Classes/Error/Notice.php [new file with mode: 0644]
typo3/sysext/extbase/Classes/Error/Result.php [new file with mode: 0644]
typo3/sysext/extbase/Classes/Error/Warning.php [new file with mode: 0644]
typo3/sysext/extbase/Tests/Unit/Error/ErrorTest.php [new file with mode: 0644]
typo3/sysext/extbase/Tests/Unit/Error/ResultTest.php [new file with mode: 0644]

index a9708a0..a527ca1 100644 (file)
@@ -1,90 +1,40 @@
 <?php
-/***************************************************************
-*  Copyright notice
-*
-*  (c) 2009 Jochen Rau <jochen.rau@typoplanet.de>
-*  All rights reserved
-*
-*  This class is a backport of the corresponding class of FLOW3.
-*  All credits go to the v5 team.
-*
-*  This script is part of the TYPO3 project. The TYPO3 project is
-*  free software; you can redistribute it and/or modify
-*  it under the terms of the GNU General Public License as published by
-*  the Free Software Foundation; either version 2 of the License, or
-*  (at your option) any later version.
-*
-*  The GNU General Public License can be found at
-*  http://www.gnu.org/copyleft/gpl.html.
-*
-*  This script is distributed in the hope that it will be useful,
-*  but WITHOUT ANY WARRANTY; without even the implied warranty of
-*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-*  GNU General Public License for more details.
-*
-*  This copyright notice MUST APPEAR in all copies of the script!
-***************************************************************/
+
+/*                                                                        *
+ * This script belongs to the Extbase framework                           *
+ *                                                                        *
+ * It is free software; you can redistribute it and/or modify it under    *
+ * the terms of the GNU Lesser General Public License as published by the *
+ * Free Software Foundation, either version 3 of the License, or (at your *
+ * option) any later version.                                             *
+ *                                                                        *
+ * This script is distributed in the hope that it will be useful, but     *
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN-    *
+ * TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser       *
+ * General Public License for more details.                               *
+ *                                                                        *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with the script.                                         *
+ * If not, see http://www.gnu.org/licenses/lgpl.html                      *
+ *                                                                        *
+ * The TYPO3 project - inspiring people to share!                         *
+ *                                                                        */
+
+/**
+ */
+
 /**
  * An object representation of a generic error. Subclass this to create
  * more specific errors if necessary.
  *
- * @package Extbase
- * @subpackage Error
- * @version $Id$
  * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License, version 3 or later
- * @scope prototype
  * @api
  */
-class Tx_Extbase_Error_Error {
+class Tx_Extbase_Error_Error extends Tx_Extbase_Error_Message {
 
        /**
-        * @var string The default (english) error message.
+        * @var string
         */
        protected $message = 'Unknown error';
-
-       /**
-        * @var string The error code
-        */
-       protected $code;
-
-       /**
-        * Constructs this error
-        *
-        * @param string $message: An english error message which is used if no other error message can be resolved
-        * @param integer $code: A unique error code
-        * @api
-        */
-       public function __construct($message, $code) {
-               $this->message = $message;
-               $this->code = $code;
-       }
-
-       /**
-        * Returns the error message
-        * @return string The error message
-        * @api
-        */
-       public function getMessage() {
-               return $this->message;
-       }
-
-       /**
-        * Returns the error code
-        * @return string The error code
-        * @api
-        */
-       public function getCode() {
-               return $this->code;
-       }
-
-       /**
-        * Converts this error into a string
-        *
-        * @return string
-        * @api
-        */
-       public function __toString() {
-               return $this->message . ' (#' . $this->code . ')';
-       }
 }
 ?>
\ No newline at end of file
diff --git a/typo3/sysext/extbase/Classes/Error/Message.php b/typo3/sysext/extbase/Classes/Error/Message.php
new file mode 100644 (file)
index 0000000..d26c7d0
--- /dev/null
@@ -0,0 +1,91 @@
+<?php
+
+/*                                                                        *
+ * This script belongs to the Extbase framework                           *
+ *                                                                        *
+ * It is free software; you can redistribute it and/or modify it under    *
+ * the terms of the GNU Lesser General Public License as published by the *
+ * Free Software Foundation, either version 3 of the License, or (at your *
+ * option) any later version.                                             *
+ *                                                                        *
+ * This script is distributed in the hope that it will be useful, but     *
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN-    *
+ * TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser       *
+ * General Public License for more details.                               *
+ *                                                                        *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with the script.                                         *
+ * If not, see http://www.gnu.org/licenses/lgpl.html                      *
+ *                                                                        *
+ * The TYPO3 project - inspiring people to share!                         *
+ *                                                                        */
+
+/**
+ */
+
+/**
+ * An object representation of a generic message. Usually, you will use Error, Warning or Notice instead of this one.
+ *
+ * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License, version 3 or later
+ * @api
+ */
+class Tx_Extbase_Error_Message {
+
+       /**
+        * The default (english) error message
+        * @var string
+        */
+       protected $message = 'Unknown message';
+
+       /**
+        * The error code
+        * @var string
+        */
+       protected $code;
+
+       /**
+        * Constructs this error
+        *
+        * @param string $message An english error message which is used if no other error message can be resolved
+        * @param integer $code A unique error code
+        * @author Robert Lemke <robert@typo3.org>
+        * @api
+        */
+       public function __construct($message, $code) {
+               $this->message = $message;
+               $this->code = $code;
+       }
+
+       /**
+        * Returns the error message
+        * @return string The error message
+        * @author Andreas Förthner <andreas.foerthner@netlogix.de>
+        * @api
+        */
+       public function getMessage() {
+               return $this->message;
+       }
+
+       /**
+        * Returns the error code
+        * @return string The error code
+        * @author Andreas Förthner <andreas.foerthner@netlogix.de>
+        * @api
+        */
+       public function getCode() {
+               return $this->code;
+       }
+
+       /**
+        * Converts this error into a string
+        *
+        * @return string
+        * @author Robert Lemke <robert@typo3.org>
+        * @api
+        */
+       public function __toString() {
+               return $this->message . ' (#' . $this->code . ')';
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/typo3/sysext/extbase/Classes/Error/Notice.php b/typo3/sysext/extbase/Classes/Error/Notice.php
new file mode 100644 (file)
index 0000000..76d6770
--- /dev/null
@@ -0,0 +1,41 @@
+<?php
+
+/*                                                                        *
+ * This script belongs to the Extbase framework                           *
+ *                                                                        *
+ * It is free software; you can redistribute it and/or modify it under    *
+ * the terms of the GNU Lesser General Public License as published by the *
+ * Free Software Foundation, either version 3 of the License, or (at your *
+ * option) any later version.                                             *
+ *                                                                        *
+ * This script is distributed in the hope that it will be useful, but     *
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN-    *
+ * TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser       *
+ * General Public License for more details.                               *
+ *                                                                        *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with the script.                                         *
+ * If not, see http://www.gnu.org/licenses/lgpl.html                      *
+ *                                                                        *
+ * The TYPO3 project - inspiring people to share!                         *
+ *                                                                        */
+
+/**
+ */
+
+/**
+ * An object representation of a generic notice. Subclass this to create
+ * more specific notices if necessary.
+ *
+ * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License, version 3 or later
+ * @api
+ */
+class Tx_Extbase_Error_Notice extends Tx_Extbase_Error_Message {
+
+       /**
+        * @var string
+        */
+       protected $message = 'Unknown notice';
+}
+
+?>
\ No newline at end of file
diff --git a/typo3/sysext/extbase/Classes/Error/Result.php b/typo3/sysext/extbase/Classes/Error/Result.php
new file mode 100644 (file)
index 0000000..5319703
--- /dev/null
@@ -0,0 +1,348 @@
+<?php
+
+/*                                                                        *
+ * This script belongs to the Extbase framework                           *
+ *                                                                        *
+ * It is free software; you can redistribute it and/or modify it under    *
+ * the terms of the GNU Lesser General Public License as published by the *
+ * Free Software Foundation, either version 3 of the License, or (at your *
+ * option) any later version.                                             *
+ *                                                                        *
+ * This script is distributed in the hope that it will be useful, but     *
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN-    *
+ * TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser       *
+ * General Public License for more details.                               *
+ *                                                                        *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with the script.                                         *
+ * If not, see http://www.gnu.org/licenses/lgpl.html                      *
+ *                                                                        *
+ * The TYPO3 project - inspiring people to share!                         *
+ *                                                                        */
+
+/**
+ * Result object for operations dealing with objects, such as the Property Mapper or the Validators.
+ *
+ * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License, version 3 or later
+ * @api
+ */
+class Tx_Extbase_Error_Result {
+
+       /**
+        * @var array<Tx_Extbase_Error_Error>
+        */
+       protected $errors = array();
+
+       /**
+        * @var array<Tx_Extbase_Error_Warning>
+        */
+       protected $warnings = array();
+
+       /**
+        * @var array<Tx_Extbase_Error_Notice>
+        */
+       protected $notices = array();
+
+       /**
+        * The result objects for the sub properties
+        *
+        * @var array<Tx_Extbase_Error_Result>
+        */
+       protected $propertyResults = array();
+
+       /**
+        * Add an error to the current Result object
+        *
+        * @param Tx_Extbase_Error_Error $error
+        * @return void
+        * @api
+        */
+       public function addError(Tx_Extbase_Error_Error $error) {
+               $this->errors[] = $error;
+       }
+
+       /**
+        * Add a warning to the current Result object
+        *
+        * @param Tx_Extbase_Error_Warning $warning
+        * @return void
+        * @api
+        */
+       public function addWarning(Tx_Extbase_Error_Warning $warning) {
+               $this->warnings[] = $warning;
+       }
+
+       /**
+        * Add a notice to the current Result object
+        *
+        * @param Tx_Extbase_Error_Notice $notice
+        * @return void
+        * @api
+        */
+       public function addNotice(Tx_Extbase_Error_Notice $notice) {
+               $this->notices[] = $notice;
+       }
+
+       /**
+        * Get all errors in the current Result object (non-recursive)
+        *
+        * @return array<Tx_Extbase_Error_Error>
+        * @api
+        */
+       public function getErrors() {
+               return $this->errors;
+       }
+
+       /**
+        * Get all warnings in the current Result object (non-recursive)
+        *
+        * @return array<Tx_Extbase_Error_Warning>
+        * @api
+        */
+       public function getWarnings() {
+               return $this->warnings;
+       }
+
+       /**
+        * Get all notices in the current Result object (non-recursive)
+        *
+        * @return array<Tx_Extbase_Error_Notice>
+        * @api
+        */
+       public function getNotices() {
+               return $this->notices;
+       }
+
+       /**
+        * Get the first error object of the current Result object (non-recursive)
+        *
+        * @return Tx_Extbase_Error_Error
+        * @api
+        */
+       public function getFirstError() {
+               reset($this->errors);
+               return current($this->errors);
+       }
+
+       /**
+        * Get the first warning object of the current Result object (non-recursive)
+        *
+        * @return Tx_Extbase_Error_Warning
+        * @api
+        */
+       public function getFirstWarning() {
+               reset($this->warnings);
+               return current($this->warnings);
+       }
+
+       /**
+        * Get the first notice object of the curren Result object (non-recursive)
+        *
+        * @return Tx_Extbase_Error_Notice
+        * @api
+        */
+       public function getFirstNotice() {
+               reset($this->notices);
+               return current($this->notices);
+       }
+
+       /**
+        * Return a Result object for the given property path. This is
+        * a fluent interface, so you will proboably use it like:
+        * $result->forProperty('foo.bar')->getErrors() -- to get all errors
+        * for property "foo.bar"
+        *
+        * @param string $propertyPath
+        * @return Tx_Extbase_Error_Result
+        * @author Sebastian Kurfürst <sebastian@typo3.org>
+        * @api
+        */
+       public function forProperty($propertyPath) {
+               if ($propertyPath === '' || $propertyPath === NULL) {
+                       return $this;
+               }
+               $propertyPathSegments = explode('.', $propertyPath);
+               return $this->recurseThroughResult($propertyPathSegments);
+       }
+
+       /**
+        * Internal use only!
+        *
+        * @param array $pathSegments
+        * @return Tx_Extbase_Error_Result
+        * @author Sebastian Kurfürst <sebastian@typo3.org>
+        */
+       public function recurseThroughResult(array $pathSegments) {
+               if (count($pathSegments) === 0) {
+                       return $this;
+               }
+
+               $propertyName = array_shift($pathSegments);
+
+               if (!isset($this->propertyResults[$propertyName])) {
+                       $this->propertyResults[$propertyName] = new Tx_Extbase_Error_Result();
+               }
+
+               return $this->propertyResults[$propertyName]->recurseThroughResult($pathSegments);
+       }
+
+       /**
+        * Internal use only!
+        *
+        * @param string $propertyName
+        * @param string $checkerMethodName
+        * @return boolean
+        * @author Sebastian Kurfürst <sebastian@typo3.org>
+        */
+       protected function hasProperty($propertyName, $checkerMethodName) {
+               if (count($this->$propertyName) > 0) {
+                       return TRUE;
+               }
+
+               foreach ($this->propertyResults as $subResult) {
+                       if ($subResult->$checkerMethodName()) {
+                               return TRUE;
+                       }
+               }
+
+               return FALSE;
+       }
+
+       /**
+        * Does the current Result object have Errors? (Recursively)
+        *
+        * @return boolean
+        * @api
+        */
+       public function hasErrors() {
+               return $this->hasProperty('errors', 'hasErrors');
+       }
+
+
+       /**
+        * Does the current Result object have Warnings? (Recursively)
+        *
+        * @return boolean
+        * @api
+        */
+       public function hasWarnings() {
+               return $this->hasProperty('warnings', 'hasWarnings');
+       }
+
+       /**
+        * Does the current Result object have Notices? (Recursively)
+        *
+        * @return boolean
+        * @api
+        */
+       public function hasNotices() {
+               return $this->hasProperty('notices', 'hasNotices');
+       }
+
+       /**
+        * Get a list of all Error objects recursively. The result is an array,
+        * where the key is the property path where the error occured, and the
+        * value is a list of all errors (stored as array)
+        *
+        * @return array<Tx_Extbase_Error_Error>
+        * @api
+        */
+       public function getFlattenedErrors() {
+               $result = array();
+               $this->flattenTree('errors', $result, array());
+               return $result;
+       }
+
+       /**
+        * Get a list of all Warning objects recursively. The result is an array,
+        * where the key is the property path where the warning occured, and the
+        * value is a list of all warnings (stored as array)
+        *
+        * @return array<Tx_Extbase_Error_Warning>
+        * @api
+        */
+       public function getFlattenedWarnings() {
+               $result = array();
+               $this->flattenTree('warnings', $result, array());
+               return $result;
+       }
+
+       /**
+        * Get a list of all Notice objects recursively. The result is an array,
+        * where the key is the property path where the notice occured, and the
+        * value is a list of all notices (stored as array)
+        *
+        * @return array<Tx_Extbase_Error_Notice>
+        * @api
+        */
+       public function getFlattenedNotices() {
+               $result = array();
+               $this->flattenTree('notices', $result, array());
+               return $result;
+       }
+
+       /**
+        * Only use internally!
+        *
+        * Flatten a tree of Result objects, based on a certain property.
+        *
+        * @param string $propertyName
+        * @param array $result
+        * @param array $level
+        * @return void
+        */
+       public function flattenTree($propertyName, &$result, $level) {
+               if (count($this->$propertyName) > 0) {
+                       $result[implode('.', $level)] = $this->$propertyName;
+               }
+               foreach ($this->propertyResults as $subPropertyName => $subResult) {
+                       array_push($level, $subPropertyName);
+                       $subResult->flattenTree($propertyName, $result, $level);
+                       array_pop($level);
+               }
+       }
+
+       /**
+        * Merge the given Result object into this one.
+        *
+        * @param Tx_Extbase_Error_Result $otherResult
+        * @return void
+        * @author Sebastian Kurfürst <sebastian@typo3.org>
+        * @api
+        */
+       public function merge(Tx_Extbase_Error_Result $otherResult) {
+               $this->mergeProperty($otherResult, 'getErrors', 'addError');
+               $this->mergeProperty($otherResult, 'getWarnings', 'addWarning');
+               $this->mergeProperty($otherResult, 'getNotices', 'addNotice');
+
+               foreach ($otherResult->getSubResults() as $subPropertyName => $subResult) {
+                       $this->forProperty($subPropertyName)->merge($subResult);
+               }
+       }
+
+       /**
+        * Merge a single property from the other result object.
+        *
+        * @param Tx_Extbase_Error_Result $otherResult
+        * @param string $getterName
+        * @param string $adderName
+        * @return void
+        * @author Sebastian Kurfürst <sebastian@typo3.org>
+        */
+       protected function mergeProperty(Tx_Extbase_Error_Result $otherResult, $getterName, $adderName) {
+               foreach ($otherResult->$getterName() as $messageInOtherResult) {
+                       $this->$adderName($messageInOtherResult);
+               }
+       }
+
+       /**
+        * Get a list of all sub Result objects available.
+        *
+        * @return array<Tx_Extbase_Erro_Result>
+        */
+       public function getSubResults() {
+               return $this->propertyResults;
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/typo3/sysext/extbase/Classes/Error/Warning.php b/typo3/sysext/extbase/Classes/Error/Warning.php
new file mode 100644 (file)
index 0000000..c65cbbf
--- /dev/null
@@ -0,0 +1,40 @@
+<?php
+
+/*                                                                        *
+ * This script belongs to the Extbase framework                           *
+ *                                                                        *
+ * It is free software; you can redistribute it and/or modify it under    *
+ * the terms of the GNU Lesser General Public License as published by the *
+ * Free Software Foundation, either version 3 of the License, or (at your *
+ * option) any later version.                                             *
+ *                                                                        *
+ * This script is distributed in the hope that it will be useful, but     *
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN-    *
+ * TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser       *
+ * General Public License for more details.                               *
+ *                                                                        *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with the script.                                         *
+ * If not, see http://www.gnu.org/licenses/lgpl.html                      *
+ *                                                                        *
+ * The TYPO3 project - inspiring people to share!                         *
+ *                                                                        */
+
+/**
+ */
+
+/**
+ * An object representation of a generic warning. Subclass this to create
+ * more specific warnings if necessary.
+ *
+ * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License, version 3 or later
+ * @api
+ */
+class Tx_Extbase_Error_Warning extends Tx_Extbase_Error_Message {
+
+       /**
+        * @var string
+        */
+       protected $message = 'Unknown warning';
+}
+?>
\ No newline at end of file
diff --git a/typo3/sysext/extbase/Tests/Unit/Error/ErrorTest.php b/typo3/sysext/extbase/Tests/Unit/Error/ErrorTest.php
new file mode 100644 (file)
index 0000000..2ae3eaa
--- /dev/null
@@ -0,0 +1,53 @@
+<?php
+
+/*                                                                        *
+ * This script belongs to the Extbase framework.                            *
+ *                                                                        *
+ * It is free software; you can redistribute it and/or modify it under    *
+ * the terms of the GNU Lesser General Public License as published by the *
+ * Free Software Foundation, either version 3 of the License, or (at your *
+ * option) any later version.                                             *
+ *                                                                        *
+ * This script is distributed in the hope that it will be useful, but     *
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN-    *
+ * TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser       *
+ * General Public License for more details.                               *
+ *                                                                        *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with the script.                                         *
+ * If not, see http://www.gnu.org/licenses/lgpl.html                      *
+ *                                                                        *
+ * The TYPO3 project - inspiring people to share!                         *
+ *                                                                        */
+
+/**
+ * Testcase for the Error object
+ *
+ * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License, version 3 or later
+ */
+class Tx_Extbase_Tests_Unit_Error_ErrorTest extends Tx_Extbase_Tests_Unit_BaseTestCase {
+
+       /**
+        * @test
+        * @author Andreas Förthner <andreas.foerthner@netlogix.de>
+        */
+       public function theConstructorSetsTheErrorMessageCorrectly() {
+               $errorMessage = 'The message';
+               $error = new Tx_Extbase_Error_Error($errorMessage, 0);
+
+               $this->assertEquals($errorMessage, $error->getMessage());
+       }
+
+       /**
+        * @test
+        * @author Andreas Förthner <andreas.foerthner@netlogix.de>
+        */
+       public function theConstructorSetsTheErrorCodeCorrectly() {
+               $errorCode = 123456789;
+               $error = new Tx_Extbase_Error_Error('', $errorCode);
+
+               $this->assertEquals($errorCode, $error->getCode());
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/typo3/sysext/extbase/Tests/Unit/Error/ResultTest.php b/typo3/sysext/extbase/Tests/Unit/Error/ResultTest.php
new file mode 100644 (file)
index 0000000..1f16143
--- /dev/null
@@ -0,0 +1,259 @@
+<?php
+
+/*                                                                        *
+ * This script belongs to the Extbase framework.                          *
+ *                                                                        *
+ * It is free software; you can redistribute it and/or modify it under    *
+ * the terms of the GNU Lesser General Public License as published by the *
+ * Free Software Foundation, either version 3 of the License, or (at your *
+ * option) any later version.                                             *
+ *                                                                        *
+ * This script is distributed in the hope that it will be useful, but     *
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN-    *
+ * TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser       *
+ * General Public License for more details.                               *
+ *                                                                        *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with the script.                                         *
+ * If not, see http://www.gnu.org/licenses/lgpl.html                      *
+ *                                                                        *
+ * The TYPO3 project - inspiring people to share!                         *
+ *                                                                        */
+
+/**
+ * Testcase for the Error Container object
+ *
+ * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License, version 3 or later
+ */
+class Tx_Extbase_Tests_Unit_Error_ResultTest extends Tx_Extbase_Tests_Unit_BaseTestCase {
+
+       /**
+        *
+        * @var Tx_Extbase_Error_Result
+        */
+       protected $result;
+
+       public function setUp() {
+               $this->result = new Tx_Extbase_Error_Result();
+       }
+
+       public function dataTypes() {
+               return array(
+                       array('Error', 'Errors'),
+                       array('Warning', 'Warnings'),
+                       array('Notice', 'Notices')
+               );
+       }
+
+       protected function getMockMessage($type) {
+               return $this->getMock('Tx_Extbase_Error_' . $type, array(), array(), '', FALSE);
+       }
+
+       /**
+        * @test
+        * @dataProvider dataTypes
+        * @author Sebastian Kurfürst <sebastian@typo3.org>
+        */
+       public function addedMessagesShouldBeRetrievableAgain($dataTypeInSingular, $dataTypeInPlural) {
+               $message = $this->getMockMessage($dataTypeInSingular);
+               $addMethodName = 'add' . $dataTypeInSingular;
+               $this->result->$addMethodName($message);
+
+               $getterMethodName = 'get' . $dataTypeInPlural;
+               $this->assertEquals(array($message), $this->result->$getterMethodName());
+       }
+
+       /**
+        * @test
+        * @dataProvider dataTypes
+        * @author Sebastian Kurfürst <sebastian@typo3.org>
+        */
+       public function getMessageShouldNotBeRecursive($dataTypeInSingular, $dataTypeInPlural) {
+               $message = $this->getMockMessage($dataTypeInSingular);
+               $addMethodName = 'add' . $dataTypeInSingular;
+               $this->result->forProperty('foo')->$addMethodName($message);
+
+               $getterMethodName = 'get' . $dataTypeInPlural;
+               $this->assertEquals(array(), $this->result->$getterMethodName());
+       }
+
+       /**
+        * @test
+        * @dataProvider dataTypes
+        * @author Sebastian Kurfürst <sebastian@typo3.org>
+        */
+       public function getFirstMessageShouldReturnFirstMessage($dataTypeInSingular, $dataTypeInPlural) {
+               $message1 = $this->getMockMessage($dataTypeInSingular);
+               $message2 = $this->getMockMessage($dataTypeInSingular);
+               $addMethodName = 'add' . $dataTypeInSingular;
+               $this->result->$addMethodName($message1);
+               $this->result->$addMethodName($message2);
+
+               $getterMethodName = 'getFirst' . $dataTypeInSingular;
+               $this->assertSame($message1, $this->result->$getterMethodName());
+       }
+
+       /**
+        * @test
+        * @author Sebastian Kurfürst <sebastian@typo3.org>
+        */
+       public function forPropertyShouldReturnSubResult() {
+               $container2 = $this->result->forProperty('foo.bar');
+               $this->assertInstanceOf('Tx_Extbase_Error_Result', $container2);
+               $this->assertSame($container2, $this->result->forProperty('foo')->forProperty('bar'));
+       }
+
+       /**
+        * @test
+        * @author Sebastian Kurfürst <sebastian@typo3.org>
+        */
+       public function forPropertyWithEmptyStringShouldReturnSelf() {
+               $container2 = $this->result->forProperty('');
+               $this->assertSame($container2, $this->result);
+       }
+
+       /**
+        * @test
+        * @author Sebastian Kurfürst <sebastian@typo3.org>
+        */
+       public function forPropertyWithNullShouldReturnSelf() {
+               $container2 = $this->result->forProperty(NULL);
+               $this->assertSame($container2, $this->result);
+       }
+
+       /**
+        * @test
+        * @dataProvider dataTypes
+        * @author Sebastian Kurfürst <sebastian@typo3.org>
+        */
+       public function hasMessagesShouldReturnTrueIfTopLevelObjectHasMessages($dataTypeInSingular, $dataTypeInPlural) {
+               $message = $this->getMockMessage($dataTypeInSingular);
+               $addMethodName = 'add' . $dataTypeInSingular;
+               $this->result->$addMethodName($message);
+
+               $methodName = 'has' . $dataTypeInPlural;
+               $this->assertTrue($this->result->$methodName());
+       }
+
+       /**
+        * @test
+        * @dataProvider dataTypes
+        * @author Sebastian Kurfürst <sebastian@typo3.org>
+        */
+       public function hasMessageshouldReturnTrueIfSubObjectHasErrors($dataTypeInSingular, $dataTypeInPlural) {
+               $addMethodName = 'add' . $dataTypeInSingular;
+               $methodName = 'has' . $dataTypeInPlural;
+
+               $message = $this->getMockMessage($dataTypeInSingular);
+               $this->result->forProperty('foo.bar')->$addMethodName($message);
+               $this->assertTrue($this->result->$methodName());
+       }
+
+       /**
+        * @test
+        * @dataProvider dataTypes
+        * @author Sebastian Kurfürst <sebastian@typo3.org>
+        */
+       public function hasMessagesShouldReturnFalseIfSubObjectHasNoErrors($dataTypeInSingular, $dataTypeInPlural) {
+               $methodName = 'has' . $dataTypeInPlural;
+
+               $this->result->forProperty('foo.baz');
+               $this->result->forProperty('foo.bar');
+               $this->assertFalse($this->result->$methodName());
+       }
+
+       /**
+        * @test
+        * @dataProvider dataTypes
+        * @author Sebastian Kurfürst <sebastian@typo3.org>
+        */
+       public function getFlattenedMessagesShouldReturnAllSubMessages($dataTypeInSingular, $dataTypeInPlural) {
+               $message1 = $this->getMockMessage($dataTypeInSingular);
+               $message2 = $this->getMockMessage($dataTypeInSingular);
+               $message3 = $this->getMockMessage($dataTypeInSingular);
+               $message4 = $this->getMockMessage($dataTypeInSingular);
+               $message5 = $this->getMockMessage($dataTypeInSingular);
+
+               $addMethodName = 'add' . $dataTypeInSingular;
+               $this->result->forProperty('foo.bar')->$addMethodName($message1);
+               $this->result->forProperty('foo.baz')->$addMethodName($message2);
+               $this->result->forProperty('foo')->$addMethodName($message3);
+               $this->result->$addMethodName($message4);
+               $this->result->$addMethodName($message5);
+
+               $getMethodName = 'getFlattened' . $dataTypeInPlural;
+               $expected = array(
+                       '' => array($message4, $message5),
+                       'foo' => array($message3),
+                       'foo.bar' => array($message1),
+                       'foo.baz' => array($message2)
+
+               );
+               $this->assertEquals($expected, $this->result->$getMethodName());
+       }
+
+       /**
+        * @test
+        * @dataProvider dataTypes
+        * @author Sebastian Kurfürst <sebastian@typo3.org>
+        */
+       public function getFlattenedMessagesShouldNotContainEmptyResults($dataTypeInSingular, $dataTypeInPlural) {
+               $message1 = $this->getMockMessage($dataTypeInSingular);
+               $message2 = $this->getMockMessage($dataTypeInSingular);
+
+               $addMethodName = 'add' . $dataTypeInSingular;
+               $this->result->forProperty('foo.bar')->$addMethodName($message1);
+               $this->result->forProperty('foo.baz')->$addMethodName($message2);
+
+               $getMethodName = 'getFlattened' . $dataTypeInPlural;
+               $expected = array(
+                       'foo.bar' => array($message1),
+                       'foo.baz' => array($message2)
+
+               );
+               $this->assertEquals($expected, $this->result->$getMethodName());
+       }
+
+       /**
+        * @test
+        * @author Sebastian Kurfürst <sebastian@typo3.org>
+        */
+       public function mergeShouldMergeTwoResults() {
+               $notice1 = $this->getMockMessage('Notice');
+               $notice2 = $this->getMockMessage('Notice');
+               $notice3 = $this->getMockMessage('Notice');
+               $warning1 = $this->getMockMessage('Warning');
+               $warning2 = $this->getMockMessage('Warning');
+               $warning3 = $this->getMockMessage('Warning');
+               $error1 = $this->getMockMessage('Error');
+               $error2 = $this->getMockMessage('Error');
+               $error3 = $this->getMockMessage('Error');
+
+               $otherResult = new Tx_Extbase_Error_Result();
+
+               $otherResult->addNotice($notice1);
+               $otherResult->forProperty('foo.bar')->addNotice($notice2);
+               $this->result->forProperty('foo')->addNotice($notice3);
+
+               $otherResult->addWarning($warning1);
+               $this->result->addWarning($warning2);
+               $this->result->addWarning($warning3);
+
+               $otherResult->forProperty('foo')->addError($error1);
+               $otherResult->forProperty('foo')->addError($error2);
+               $otherResult->addError($error3);
+
+               $this->result->merge($otherResult);
+
+               $this->assertSame(array($notice1), $this->result->getNotices(), 'Notices are not merged correctly without recursion');
+               $this->assertSame(array($notice3), $this->result->forProperty('foo')->getNotices(), 'Original sub-notices are overridden.');
+               $this->assertSame(array($notice2), $this->result->forProperty('foo')->forProperty('bar')->getNotices(), 'Sub-notices are not copied.');
+
+               $this->assertSame(array($warning2, $warning3, $warning1), $this->result->getWarnings());
+
+               $this->assertSame(array($error3), $this->result->getErrors());
+               $this->assertSame(array($error1, $error2), $this->result->forProperty('foo')->getErrors());
+       }
+}
+
+?>
\ No newline at end of file