Initial import
authorlolli <lolli@735d13b6-9817-0410-8766-e36946ffe9aa>
Fri, 15 Feb 2013 14:44:34 +0000 (14:44 +0000)
committerlolli <lolli@735d13b6-9817-0410-8766-e36946ffe9aa>
Fri, 15 Feb 2013 14:44:34 +0000 (14:44 +0000)
git-svn-id: https://svn.typo3.org/TYPO3v4/Extensions/lw_enet_multiple_action_forms/trunk@71237 735d13b6-9817-0410-8766-e36946ffe9aa

52 files changed:
Classes/Comparison/Constraint/AbstractCompositeConstraint.php [new file with mode: 0644]
Classes/Comparison/Constraint/AbstractConstraint.php [new file with mode: 0644]
Classes/Comparison/Constraint/ConjunctionConstraint.php [new file with mode: 0644]
Classes/Comparison/Constraint/ConstraintInterface.php [new file with mode: 0644]
Classes/Comparison/Constraint/EmptyConstraint.php [new file with mode: 0644]
Classes/Comparison/Constraint/EqualConstraint.php [new file with mode: 0644]
Classes/Comparison/Constraint/IsFalseConstraint.php [new file with mode: 0644]
Classes/Comparison/Constraint/IsNullConstraint.php [new file with mode: 0644]
Classes/Comparison/Constraint/IsTrueConstraint.php [new file with mode: 0644]
Classes/Comparison/Constraint/NotEmptyConstraint.php [new file with mode: 0644]
Classes/Comparison/Constraint/NotEqualConstraint.php [new file with mode: 0644]
Classes/Comparison/ConstraintResolver.php [new file with mode: 0644]
Classes/Comparison/Exception.php [new file with mode: 0644]
Classes/Comparison/Exception/InvalidConstraintConfiguration.php [new file with mode: 0644]
Classes/Comparison/Exception/NoSuchConstraint.php [new file with mode: 0644]
Classes/Domain/Validator/AbstractModelValidator.php [new file with mode: 0644]
Classes/MVC/Controller/AbstractController.php [new file with mode: 0644]
Classes/MVC/Controller/Action.php [new file with mode: 0644]
Classes/MVC/Controller/Action/Override/ConstraintResolver.php [new file with mode: 0644]
Classes/MVC/Controller/Action/Override/Exception.php [new file with mode: 0644]
Classes/MVC/Controller/Action/Override/Exception/InvalidActionMethod.php [new file with mode: 0644]
Classes/MVC/Controller/Exception.php [new file with mode: 0644]
Classes/MVC/Controller/Exception/ActionSequenceAnnotationMissing.php [new file with mode: 0644]
Classes/MVC/Web/BackendRequestHandler.php [new file with mode: 0644]
Classes/MVC/Web/FrontendRequestHandler.php [new file with mode: 0644]
Classes/Service/ActionSequence.php [new file with mode: 0644]
Classes/Service/Reflection.php [new file with mode: 0644]
Classes/Session/AdapterInterface.php [new file with mode: 0644]
Classes/Session/PersistenceInterface.php [new file with mode: 0644]
Classes/Session/Typo3SessionAdapter.php [new file with mode: 0644]
Classes/Utility/AnnotationParser.php [new file with mode: 0644]
Classes/Utility/Annotations/ConstraintParser.php [new file with mode: 0644]
Classes/Utility/Annotations/ValidatorParser.php [new file with mode: 0644]
Classes/Utility/Controller.php [new file with mode: 0644]
Classes/Utility/String.php [new file with mode: 0644]
Classes/Validation/NestedObjectValidatorResolver.php [new file with mode: 0644]
Classes/Validation/Validator/AbstractObjectValidator.php [new file with mode: 0644]
Classes/Validation/Validator/GenericObjectValidator.php [new file with mode: 0644]
Classes/Validation/Validator/TraversableObjectValidator.php [new file with mode: 0644]
Classes/Validation/ValidatorResolver.php [new file with mode: 0644]
Configuration/TypoScript/constants.txt [new file with mode: 0644]
Configuration/TypoScript/setup.txt [new file with mode: 0644]
Documentation/manual.sxw [new file with mode: 0644]
Resources/Private/.htaccess [new file with mode: 0644]
Resources/Private/Language/locallang.xml [new file with mode: 0644]
Resources/Private/Language/locallang_db.xml [new file with mode: 0644]
Resources/Public/JavaScript/LwEnetMultipleActionForms.js [new file with mode: 0644]
ext_autoload.php [new file with mode: 0644]
ext_emconf.php [new file with mode: 0644]
ext_icon.gif [new file with mode: 0644]
ext_localconf.php [new file with mode: 0644]
ext_tables.php [new file with mode: 0644]

diff --git a/Classes/Comparison/Constraint/AbstractCompositeConstraint.php b/Classes/Comparison/Constraint/AbstractCompositeConstraint.php
new file mode 100644 (file)
index 0000000..54cce00
--- /dev/null
@@ -0,0 +1,113 @@
+<?php
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Helge Funk <helge.funk@e-net.info>
+ *
+ *  All rights reserved
+ *
+ *  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 3 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!
+ ***************************************************************/
+
+
+/**
+ *
+ * @package LwEnetMultipleActionForms
+ * @subpackage Comparison|Constraint
+ * @scope prototype
+ *
+ */
+abstract class Tx_LwEnetMultipleActionForms_Comparison_Constraint_AbstractCompositeConstraint implements Tx_LwEnetMultipleActionForms_Comparison_Constraint_ConstraintInterface, Countable {
+
+       /**
+        * @var array
+        */
+       protected $options = array();
+
+       /**
+        * @var Tx_Extbase_Persistence_ObjectStorage
+        */
+       protected $constraints;
+
+       /**
+        * @var array
+        */
+       protected $errors = array();
+
+       /**
+        * Constructs the validator conjunction
+        *
+        */
+       public function __construct() {
+               $this->constraints = new Tx_Extbase_Persistence_ObjectStorage();
+       }
+
+       /**
+        * Does nothing.
+        *
+        * @param array $options Not used
+        * @return void
+        */
+       public function setOptions(array $options) {
+       }
+
+       /**
+        * Returns an array of errors which occurred during the last isValid() call.
+        *
+        * @return array An array of Tx_Extbase_Validation_Error objects or an empty array if no errors occurred.
+        */
+       public function getErrors() {
+               return $this->errors;
+       }
+
+       /**
+        * Adds a new validator to the conjunction.
+        *
+        * @param Tx_LwEnetMultipleActionForms_Comparison_Constraint_ConstraintInterface $constraint The validator that should be added
+        * @return void
+        */
+       public function addConstraint(Tx_LwEnetMultipleActionForms_Comparison_Constraint_ConstraintInterface $constraint) {
+               $this->constraints->attach($constraint);
+       }
+
+       /**
+        * Removes the specified validator.
+        *
+        * @param Tx_LwEnetMultipleActionForms_Comparison_Constraint_ConstraintInterface $constraint The validator to remove
+        */
+       public function removeConstraint(Tx_LwEnetMultipleActionForms_Comparison_Constraint_ConstraintInterface $constraint) {
+               if (!$this->constraints->contains($constraint)) {
+                        throw new Tx_LwEnetMultipleActionForms_MVC_Controller_Action_Exception_NoSuchConstraint(
+                                'Cannot remove override condition because its not in the conjunction.',
+                                1322226420
+                        );
+               }
+               $this->constraints->detach($constraint);
+       }
+
+       /**
+        * Returns the number of validators contained in this conjunction.
+        *
+        * @return integer The number of validators
+        */
+       public function count() {
+               return count($this->constraints);
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/Classes/Comparison/Constraint/AbstractConstraint.php b/Classes/Comparison/Constraint/AbstractConstraint.php
new file mode 100644 (file)
index 0000000..eac965e
--- /dev/null
@@ -0,0 +1,77 @@
+<?php
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Helge Funk <helge.funk@e-net.info>
+ *
+ *  All rights reserved
+ *
+ *  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 3 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!
+ ***************************************************************/
+
+
+/**
+ *
+ * @package LwEnetMultipleActionForms
+ * @subpackage Comparison|Constraint
+ * @scope prototype
+ *
+ */
+abstract class Tx_LwEnetMultipleActionForms_Comparison_Constraint_AbstractConstraint implements Tx_LwEnetMultipleActionForms_Comparison_Constraint_ConstraintInterface {
+       /**
+        * @var array
+        */
+       protected $options = array();
+
+       /**
+        * @var array
+        */
+       protected $errors = array();
+
+       /**
+        * Sets options for the validator
+        *
+        * @param array $options Options for the validator
+        * @return void
+        */
+       public function setOptions(array $options) {
+               $this->options = $options;
+       }
+
+       /**
+        * Returns an array of errors which occurred during the last isValid() call.
+        *
+        * @return array An array of Tx_Extbase_Validation_Error objects or an empty array if no errors occurred.
+        */
+       public function getErrors() {
+               return $this->errors;
+       }
+
+       /**
+        * Creates a new validation error object and adds it to $this->errors
+        *
+        * @param string $message The error message
+        * @param integer $code The error code (a unix timestamp)
+        * @return void
+        */
+       protected function addError($message, $code) {
+               $this->errors[] = new Tx_Extbase_Validation_Error($message, $code);
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/Classes/Comparison/Constraint/ConjunctionConstraint.php b/Classes/Comparison/Constraint/ConjunctionConstraint.php
new file mode 100644 (file)
index 0000000..ef7b17d
--- /dev/null
@@ -0,0 +1,57 @@
+<?php
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Helge Funk <helge.funk@e-net.info>
+ *
+ *  All rights reserved
+ *
+ *  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 3 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!
+ ***************************************************************/
+
+
+/**
+ *
+ * @package LwEnetMultipleActionForms
+ * @subpackage Comparison|Constraint
+ *
+ */
+class Tx_LwEnetMultipleActionForms_Comparison_Constraint_ConjunctionConstraint extends Tx_LwEnetMultipleActionForms_Comparison_Constraint_AbstractCompositeConstraint {
+
+       /**
+        * Checks if the given value is valid according to the validators of the conjunction.
+        *
+        * If at least one error occurred, the result is FALSE.
+        *
+        * @param mixed $value The value that should be validated
+        * @return boolean
+        */
+       public function isComplied($value) {
+               $result = FALSE;
+               /** @var $constraint Tx_LwEnetMultipleActionForms_Comparison_Constraint_ConstraintInterface */
+               foreach ($this->constraints as $constraint) {
+                       if ($constraint->isComplied($value) === TRUE) {
+                               $this->errors = array_merge($this->errors, $constraint->getErrors());
+                               $result = TRUE;
+                       }
+               }
+               return $result;
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/Classes/Comparison/Constraint/ConstraintInterface.php b/Classes/Comparison/Constraint/ConstraintInterface.php
new file mode 100644 (file)
index 0000000..8f8373d
--- /dev/null
@@ -0,0 +1,67 @@
+<?php
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Helge Funk <helge.funk@e-net.info>
+ *
+ *  All rights reserved
+ *
+ *  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 3 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!
+ ***************************************************************/
+
+
+/**
+ *
+ * @package LwEnetMultipleActionForms
+ * @subpackage Comparison|Constraint
+ *
+ */
+interface Tx_LwEnetMultipleActionForms_Comparison_Constraint_ConstraintInterface {
+
+       /**
+        * Checks if the given value is valid according to the validator.
+        *
+        * If at least one error occurred, the result is FALSE and any errors can
+        * be retrieved through the getErrors() method.
+        *
+        * Note that all implementations of this method should set $this->errors() to an
+        * empty array before validating.
+        *
+        * @param mixed $value The value that should be validated
+        * @return boolean TRUE if the value is valid, FALSE if an error occured
+        */
+       public function isComplied($value);
+
+       /**
+        * Sets validation options for the validator
+        *
+        * @param array $validationOptions The validation options
+        * @return void
+        */
+       public function setOptions(array $options);
+
+       /**
+        * Returns an array of errors which occurred during the last isValid() call.
+        *
+        * @return array An array of error messages or an empty array if no errors occurred.
+        */
+       public function getErrors();
+
+}
+
+?>
\ No newline at end of file
diff --git a/Classes/Comparison/Constraint/EmptyConstraint.php b/Classes/Comparison/Constraint/EmptyConstraint.php
new file mode 100644 (file)
index 0000000..36ca4c8
--- /dev/null
@@ -0,0 +1,49 @@
+<?php
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Helge Funk <helge.funk@e-net.info>
+ *
+ *  All rights reserved
+ *
+ *  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 3 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!
+ ***************************************************************/
+
+
+/**
+ *
+ * @package LwEnetMultipleActionForms
+ * @subpackage Comparison|Constraint
+ *
+ */
+class Tx_LwEnetMultipleActionForms_Comparison_Constraint_EmptyConstraint extends Tx_LwEnetMultipleActionForms_Comparison_Constraint_AbstractConstraint {
+
+       /**
+        * Returns TRUE, if the given property ($propertyValue) is a valid text (contains no XML tags).
+        *
+        * If at least one error occurred, the result is FALSE.
+        *
+        * @param mixed $value The value that should be validated
+        * @return boolean TRUE if the value is valid, FALSE if an error occured
+        */
+       public function isComplied($value) {
+               return empty($value);
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/Classes/Comparison/Constraint/EqualConstraint.php b/Classes/Comparison/Constraint/EqualConstraint.php
new file mode 100644 (file)
index 0000000..9fb14f9
--- /dev/null
@@ -0,0 +1,77 @@
+<?php
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Helge Funk <helge.funk@e-net.info>
+ *
+ *  All rights reserved
+ *
+ *  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 3 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!
+ ***************************************************************/
+
+
+/**
+ *
+ * @package LwEnetMultipleActionForms
+ * @subpackage Comparison|Constraint
+ *
+ */
+class Tx_LwEnetMultipleActionForms_Comparison_Constraint_EqualConstraint extends Tx_LwEnetMultipleActionForms_Comparison_Constraint_AbstractConstraint {
+
+       /**
+        * Returns TRUE, if the given property ($propertyValue) is a valid text (contains no XML tags).
+        *
+        * If at least one error occurred, the result is FALSE.
+        *
+        * @param mixed $value The value that should be validated
+        * @return boolean TRUE if the value is valid, FALSE if an error occured
+        */
+       public function isComplied($value) {
+               $isComplied = FALSE;
+
+               if (isset($this->options['property']) && is_array($value)) {
+                       $comparisonValue = $value[$this->options['property']];
+               } else {
+                       $comparisonValue = $value;
+               }
+
+               if (isset($this->options['value'])) {
+                       $isComplied = $comparisonValue === $this->options['value'];
+               } elseif (isset($this->options['valueList'])) {
+                       $isComplied = !$this->isValueInList($comparisonValue, $this->options['valueList']);
+               } else {
+                       throw new Tx_LwEnetMultipleActionForms_Comparison_Exception_InvalidConstraintConfiguration(
+                               'Invalid configuration options set for ' . get_class($this),
+                               1323181731
+                       );
+               }
+               return $isComplied;
+       }
+
+       /**
+        * @param string $value
+        * @param string $valueList
+        * @return bool
+        */
+       protected function isValueInList($value, $valueList) {
+               $valueList = t3lib_div::trimExplode(',', $valueList);
+               return !in_array($value, $valueList);
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/Classes/Comparison/Constraint/IsFalseConstraint.php b/Classes/Comparison/Constraint/IsFalseConstraint.php
new file mode 100644 (file)
index 0000000..a96f9a6
--- /dev/null
@@ -0,0 +1,49 @@
+<?php
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2012 Helge Funk <helge.funk@e-net.info>
+ *
+ *  All rights reserved
+ *
+ *  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 3 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!
+ ***************************************************************/
+
+
+/**
+ *
+ * @package LwEnetMultipleActionForms
+ * @subpackage Comparison|Constraint
+ *
+ */
+class Tx_LwEnetMultipleActionForms_Comparison_Constraint_IsFalseConstraint extends Tx_LwEnetMultipleActionForms_Comparison_Constraint_AbstractConstraint {
+
+       /**
+        * Returns TRUE, if the given property ($propertyValue) is a valid text (contains no XML tags).
+        *
+        * If at least one error occurred, the result is FALSE.
+        *
+        * @param mixed $value The value that should be validated
+        * @return boolean TRUE if the value is valid, FALSE if an error occured
+        */
+       public function isComplied($value) {
+               return ($value === FALSE);
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/Classes/Comparison/Constraint/IsNullConstraint.php b/Classes/Comparison/Constraint/IsNullConstraint.php
new file mode 100644 (file)
index 0000000..683b182
--- /dev/null
@@ -0,0 +1,49 @@
+<?php
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Helge Funk <helge.funk@e-net.info>
+ *
+ *  All rights reserved
+ *
+ *  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 3 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!
+ ***************************************************************/
+
+
+/**
+ *
+ * @package LwEnetMultipleActionForms
+ * @subpackage Comparison|Constraint
+ *
+ */
+class Tx_LwEnetMultipleActionForms_Comparison_Constraint_IsNullConstraint extends Tx_LwEnetMultipleActionForms_Comparison_Constraint_AbstractConstraint {
+
+       /**
+        * Returns TRUE, if the given property ($propertyValue) is a valid text (contains no XML tags).
+        *
+        * If at least one error occurred, the result is FALSE.
+        *
+        * @param mixed $value The value that should be validated
+        * @return boolean TRUE if the value is valid, FALSE if an error occured
+        */
+       public function isComplied($value) {
+               return is_null($value);
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/Classes/Comparison/Constraint/IsTrueConstraint.php b/Classes/Comparison/Constraint/IsTrueConstraint.php
new file mode 100644 (file)
index 0000000..a13a0bc
--- /dev/null
@@ -0,0 +1,49 @@
+<?php
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2012 Helge Funk <helge.funk@e-net.info>
+ *
+ *  All rights reserved
+ *
+ *  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 3 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!
+ ***************************************************************/
+
+
+/**
+ *
+ * @package LwEnetMultipleActionForms
+ * @subpackage Comparison|Constraint
+ *
+ */
+class Tx_LwEnetMultipleActionForms_Comparison_Constraint_IsTrueConstraint extends Tx_LwEnetMultipleActionForms_Comparison_Constraint_AbstractConstraint {
+
+       /**
+        * Returns TRUE, if the given property ($propertyValue) is a valid text (contains no XML tags).
+        *
+        * If at least one error occurred, the result is FALSE.
+        *
+        * @param mixed $value The value that should be validated
+        * @return boolean TRUE if the value is valid, FALSE if an error occured
+        */
+       public function isComplied($value) {
+               return ($value === TRUE);
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/Classes/Comparison/Constraint/NotEmptyConstraint.php b/Classes/Comparison/Constraint/NotEmptyConstraint.php
new file mode 100644 (file)
index 0000000..485e230
--- /dev/null
@@ -0,0 +1,52 @@
+<?php
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Helge Funk <helge.funk@e-net.info>
+ *
+ *  All rights reserved
+ *
+ *  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 3 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!
+ ***************************************************************/
+
+
+/**
+ *
+ * @package LwEnetMultipleActionForms
+ * @subpackage Comparison|Constraint
+ *
+ */
+class Tx_LwEnetMultipleActionForms_Comparison_Constraint_NotEmptyConstraint extends Tx_LwEnetMultipleActionForms_Comparison_Constraint_AbstractConstraint {
+
+       /**
+        * Returns TRUE, if the given property ($propertyValue) is a valid text (contains no XML tags).
+        *
+        * If at least one error occurred, the result is FALSE.
+        *
+        * @param mixed $value The value that should be validated
+        * @return boolean TRUE if the value is valid, FALSE if an error occured
+        */
+       public function isComplied($value) {
+               /** @var $constraint Tx_LwEnetMultipleActionForms_Comparison_Constraint_EmptyConstraint */
+               $constraint = t3lib_div::makeInstance('Tx_LwEnetMultipleActionForms_Comparison_Constraint_EmptyConstraint');
+               $constraint->setOptions($this->options);
+               return !$constraint->isComplied($value);
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/Classes/Comparison/Constraint/NotEqualConstraint.php b/Classes/Comparison/Constraint/NotEqualConstraint.php
new file mode 100644 (file)
index 0000000..ecbb153
--- /dev/null
@@ -0,0 +1,52 @@
+<?php
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Helge Funk <helge.funk@e-net.info>
+ *
+ *  All rights reserved
+ *
+ *  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 3 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!
+ ***************************************************************/
+
+
+/**
+ *
+ * @package LwEnetMultipleActionForms
+ * @subpackage Comparison|Constraint
+ *
+ */
+class Tx_LwEnetMultipleActionForms_Comparison_Constraint_NotEqualConstraint extends Tx_LwEnetMultipleActionForms_Comparison_Constraint_AbstractConstraint {
+
+       /**
+        * Returns TRUE, if the given property ($propertyValue) is a valid text (contains no XML tags).
+        *
+        * If at least one error occurred, the result is FALSE.
+        *
+        * @param mixed $value The value that should be validated
+        * @return boolean TRUE if the value is complied, FALSE if an error occured
+        */
+       public function isComplied($value) {
+               /** @var $constraint Tx_LwEnetMultipleActionForms_Comparison_Constraint_EqualConstraint */
+               $constraint = t3lib_div::makeInstance('Tx_LwEnetMultipleActionForms_Comparison_Constraint_EqualConstraint');
+               $constraint->setOptions($this->options);
+               return !$constraint->isComplied($value);
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/Classes/Comparison/ConstraintResolver.php b/Classes/Comparison/ConstraintResolver.php
new file mode 100644 (file)
index 0000000..ba36dbe
--- /dev/null
@@ -0,0 +1,117 @@
+<?php
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Helge Funk <helge.funk@e-net.info>
+ *
+ *  All rights reserved
+ *
+ *  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 3 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!
+ ***************************************************************/
+
+
+/**
+ *
+ * @package LwEnetMultipleActionForms
+ * @subpackage Comparison
+ *
+ */
+class Tx_LwEnetMultipleActionForms_Comparison_ConstraintResolver implements t3lib_Singleton {
+
+       /**
+        * @var Tx_Extbase_Object_ObjectManagerInterface
+        */
+       protected $objectManager;
+
+       /**
+        * @var Tx_Extbase_Reflection_Service
+        */
+       protected $reflectionService;
+
+       /**
+        * Injects the object manager
+        *
+        * @param Tx_Extbase_Object_ObjectManagerInterface $objectManager A reference to the object manager
+        * @return void
+        */
+       public function injectObjectManager(Tx_Extbase_Object_ObjectManagerInterface $objectManager) {
+               $this->objectManager = $objectManager;
+       }
+
+       /**
+        * Injects the reflection service
+        *
+        * @param Tx_Extbase_Reflection_Service $reflectionService
+        * @return void
+        */
+       public function injectReflectionService(Tx_Extbase_Reflection_Service $reflectionService) {
+               $this->reflectionService = $reflectionService;
+       }
+
+       /**
+        * Get a validator for a given data type. Returns a validator implementing
+        * the Tx_Extbase_Validation_Validator_ValidatorInterface or NULL if no validator
+        * could be resolved.
+        *
+        * @param string $constraintName Either one of the built-in data types or fully qualified validator class name
+        * @param array $constraintOptions Options to be passed to the validator
+        * @return Tx_LwEnetMultipleActionForms_Comparison_Constraint_ConstraintInterface Validator or NULL if none found.
+        */
+       public function createConstraint($constraintName, array $constraintOptions = array()) {
+               $constraintClassName = $this->resolveConstraintObjectName($constraintName);
+               if ($constraintClassName === FALSE) return NULL;
+               $constraint = $this->objectManager->get($constraintClassName);
+               if (!($constraint instanceof Tx_LwEnetMultipleActionForms_Comparison_Constraint_ConstraintInterface)) {
+                       return NULL;
+               }
+
+               $constraint->setOptions($constraintOptions);
+               return $constraint;
+       }
+
+       /**
+        *
+        *
+        * Returns an object of an appropriate validator for the given class. If no validator is available
+        * FALSE is returned
+        *
+        * @param string $constraintName Either the fully qualified class name of the validator or the short name of a built-in validator
+        * @return string Name of the validator object or FALSE
+        */
+       protected function resolveConstraintObjectName($constraintName) {
+               if (strstr($constraintName, '_') !== FALSE && class_exists($constraintName)) return $constraintName;
+
+               $possibleClassName = 'Tx_LwEnetMultipleActionForms_Comparison_Constraint_' . $this->unifyConstraintName($constraintName) . 'Constraint';
+               if (class_exists($possibleClassName)) return $possibleClassName;
+
+               return FALSE;
+       }
+
+       /**
+        * Preprocess data types. Used to map primitive PHP types to DataTypes used in Extbase.
+        *
+        * @param string $constraintName Data type to unify
+        * @return string unified data type
+        */
+       protected function unifyConstraintName($constraintName) {
+               return ucfirst($constraintName);
+       }
+
+}
+
+?>
\ No newline at end of file
diff --git a/Classes/Comparison/Exception.php b/Classes/Comparison/Exception.php
new file mode 100644 (file)
index 0000000..6e20fc5
--- /dev/null
@@ -0,0 +1,38 @@
+<?php
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Helge Funk <helge.funk@e-net.info>
+ *
+ *  All rights reserved
+ *
+ *  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 3 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!
+ ***************************************************************/
+
+/**
+ * A generic Comparison Exception
+ *
+ * @package LwEnetMultipleActionForms
+ * @subpackage Validation|Validator
+ *
+ */
+class Tx_LwEnetMultipleActionForms_Comparison_Exception extends Tx_Extbase_Exception {
+
+}
+
+?>
\ No newline at end of file
diff --git a/Classes/Comparison/Exception/InvalidConstraintConfiguration.php b/Classes/Comparison/Exception/InvalidConstraintConfiguration.php
new file mode 100644 (file)
index 0000000..d04f380
--- /dev/null
@@ -0,0 +1,38 @@
+<?php
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Helge Funk <helge.funk@e-net.info>
+ *
+ *  All rights reserved
+ *
+ *  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 3 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!
+ ***************************************************************/
+
+/**
+ * A generic Comparison Exception
+ *
+ * @package LwEnetMultipleActionForms
+ * @subpackage Validation|Validator
+ *
+ */
+class Tx_LwEnetMultipleActionForms_Comparison_Exception_InvalidConstraintConfiguration extends Tx_Extbase_Exception {
+
+}
+
+?>
\ No newline at end of file
diff --git a/Classes/Comparison/Exception/NoSuchConstraint.php b/Classes/Comparison/Exception/NoSuchConstraint.php
new file mode 100644 (file)
index 0000000..c70b22f
--- /dev/null
@@ -0,0 +1,38 @@
+<?php
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Helge Funk <helge.funk@e-net.info>
+ *
+ *  All rights reserved
+ *
+ *  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 3 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!
+ ***************************************************************/
+
+/**
+ * A generic Comparison Exception
+ *
+ * @package LwEnetMultipleActionForms
+ * @subpackage Validation|Validator
+ *
+ */
+class Tx_LwEnetMultipleActionForms_Comparison_Exception_NoSuchConstraint extends Tx_Extbase_Exception {
+
+}
+
+?>
\ No newline at end of file
diff --git a/Classes/Domain/Validator/AbstractModelValidator.php b/Classes/Domain/Validator/AbstractModelValidator.php
new file mode 100644 (file)
index 0000000..44ac7d6
--- /dev/null
@@ -0,0 +1,160 @@
+<?php
+/***************************************************************
+*  Copyright notice
+*
+*  (c) 2012 Christian Kuhn <lolli@schwarzbu.ch>
+*  All rights reserved
+*
+*  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!
+***************************************************************/
+
+/**
+ * Form validator
+ *
+ * @package TYPO3
+ * @subpackage lw_enet_multiple_action_forms
+ * @author Christian Kuhn <lolli@schwarzbu.ch>
+ */
+class Tx_LwEnetMultipleActionForms_Domain_Validator_AbstractModelValidator extends Tx_Extbase_Validation_Validator_AbstractValidator {
+
+       /**
+        * @var Tx_LwEnetMultipleActionForms_Service_ActionSequence
+        */
+       protected $actionSequenceService;
+
+       /**
+        * Injects the action sequence service
+        *
+        * @param Tx_LwEnetMultipleActionForms_Service_ActionSequence $actionSequenceService
+        * @return void
+        */
+       public function injectActionSequenceService(Tx_LwEnetMultipleActionForms_Service_ActionSequence $actionSequenceService) {
+               $this->actionSequenceService = $actionSequenceService;
+       }
+
+       /**
+        * Is valid
+        *
+        * @param Tx_Extbase_DomainObject_AbstractDomainObject $object
+        * @return boolean $isValid
+        */
+       public function isValid($object) {
+                       /** @var $object Tx_Extbase_DomainObject_AbstractDomainObject */
+               if (!($object instanceof Tx_Extbase_DomainObject_AbstractDomainObject)) {
+                       throw new Exception(
+                               'Value is not an instance of Tx_Extbase_DomainObject_AbstractDomainObject',
+                               1327485943
+                       );
+               }
+
+               $isValid = TRUE;
+               try {
+                       $this->callValidationMethods($object);
+               } catch (Tx_Extbase_Validation_Exception $e) {
+                       $isValid = FALSE;
+               }
+
+               if (count($this->errors) > 0) {
+                       $isValid = FALSE;
+               }
+
+               return $isValid;
+       }
+
+       /**
+        * Call validation methods
+        *
+        * @param Tx_Extbase_DomainObject_AbstractDomainObject $object
+        * @return void
+        */
+       protected function callValidationMethods(Tx_Extbase_DomainObject_AbstractDomainObject $object) {
+                       // Call generic method for all action if exists
+               if (method_exists($this, 'generalValidation')) {
+                       $this->generalValidation($object);
+               }
+
+                       // Call specifec method per action if exists
+               $actionValidationMethodName = $this->actionSequenceService->getCurrentAction()->getActionMethodName() . 'Validation';
+               if (method_exists($this, $actionValidationMethodName)) {
+                       call_user_func(
+                               array($this, $actionValidationMethodName),
+                               $object
+                       );
+               }
+       }
+
+       /**
+        * Add a property error to error container.
+        * This is done by extbase itself for single validators at properties, but
+        * not in our 'validate the whole model' context here. The methods mimics
+        * the property error adding handling and must be called explicitly.
+        *
+        * @param string $propertyName
+        * @param string $message
+        * @param string $code
+        */
+       protected function addPropertyError($propertyName, $message, $code) {
+               if (!($this->errors[$propertyName] instanceof Tx_Extbase_Validation_PropertyError)) {
+                       $propertyError = new Tx_Extbase_Validation_PropertyError($propertyName);
+               } else {
+                       $propertyError = $this->errors[$propertyName];
+               }
+               $propertyError->addErrors(
+                       array(
+                               new Tx_Extbase_Validation_Error($message, $code)
+                       )
+               );
+               $this->errors[$propertyName] = $propertyError;
+       }
+
+       /**
+        * @param $propertyName
+        * @param $childPropertyName
+        * @param Tx_Extbase_Validation_PropertyError $childPropertyError
+        */
+       protected function addChildPropertyErrorToProperty($propertyName, $childPropertyName, Tx_Extbase_Validation_PropertyError $childPropertyError) {
+               if (!($this->errors[$propertyName] instanceof Tx_Extbase_Validation_PropertyError)) {
+                       $propertyError = new Tx_Extbase_Validation_PropertyError($propertyName);
+               } else {
+                       $propertyError = $this->errors[$propertyName];
+               }
+               $propertyError->addErrors(
+                       array(
+                               $childPropertyName => $childPropertyError
+                       )
+               );
+               $this->errors[$propertyName] = $propertyError;
+       }
+
+       /**
+        * @param string $propertyName
+        * @param string $message
+        * @param string $code
+        * @return Tx_Extbase_Validation_PropertyError
+        */
+       protected function createPropertyError($propertyName, $message, $code) {
+               $propertyError = new Tx_Extbase_Validation_PropertyError($propertyName);
+               $propertyError->addErrors(
+                       array(
+                               new Tx_Extbase_Validation_Error($message, $code)
+                       )
+               );
+               return $propertyError;
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/Classes/MVC/Controller/AbstractController.php b/Classes/MVC/Controller/AbstractController.php
new file mode 100644 (file)
index 0000000..8377602
--- /dev/null
@@ -0,0 +1,535 @@
+<?php
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Helge Funk <helge.funk@e-net.info>
+ *
+ *  All rights reserved
+ *
+ *  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 3 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!
+ ***************************************************************/
+
+
+/**
+ *
+ *
+ * @package lw_enet_multiple_action_forms
+ * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License, version 3 or later
+ *
+ */
+abstract class Tx_LwEnetMultipleActionForms_MVC_Controller_AbstractController extends Tx_Extbase_MVC_Controller_ActionController {
+
+       /**
+        * @var string
+        */
+       protected $sessionPersistenceInterface = 'Tx_LwEnetMultipleActionForms_Session_PersistenceInterface';
+
+       /**
+        * @var boolean True if action manually persisted the arguments already
+        */
+       protected $argumentsPersisted = FALSE;
+
+       /**
+        * @var Tx_LwEnetMultipleActionForms_Service_ActionSequence
+        */
+       protected $actionSequenceService;
+
+       /**
+        * @var Tx_LwEnetMultipleActionForms_MVC_Controller_Action_Override_ConstraintResolver
+        */
+       protected $actionOverrideConstraintResolver;
+
+       /**
+        * @var Tx_LwEnetMultipleActionForms_Session_AdapterInterface
+        */
+       protected $sessionAdapter;
+
+       /**
+        * @var array<Tx_LwEnetMultipleActionForms_Comparison_Constraint_ConstraintInterface>
+        */
+       protected $actionOverrideConstraints;
+
+       /**
+        * Injects the action sequence service
+        *
+        * @param Tx_LwEnetMultipleActionForms_Service_ActionSequence $actionSequenceService
+        * @return void
+        */
+       public function injectActionSequenceService(Tx_LwEnetMultipleActionForms_Service_ActionSequence $actionSequenceService) {
+               $this->actionSequenceService = $actionSequenceService;
+       }
+
+       /**
+        * Injects the validator resolver
+        *
+        * @param Tx_LwEnetMultipleActionForms_MVC_Controller_Action_Override_ConstraintResolver $actionOverrideConstraintResolver
+        * @return void
+        */
+       public function injectOverrideActionConstraintResolver(Tx_LwEnetMultipleActionForms_MVC_Controller_Action_Override_ConstraintResolver $actionOverrideConstraintResolver) {
+               $this->actionOverrideConstraintResolver = $actionOverrideConstraintResolver;
+       }
+
+       /**
+        * Injects session adapter
+        *
+        * @param Tx_LwEnetMultipleActionForms_Session_AdapterInterface $sessionAdapter
+        */
+       public function injectSessionAdapter(Tx_LwEnetMultipleActionForms_Session_AdapterInterface $sessionAdapter) {
+               $this->sessionAdapter = $sessionAdapter;
+       }
+
+       /**
+        * @param $actionMethodName
+        * @return void
+        */
+       protected function initializeActionMethodOverrideConditions($actionMethodName) {
+               $this->actionOverrideConstraints = $this->actionOverrideConstraintResolver->buildMethodArgumentsOverrideActionConstraints(
+                       get_class($this), $actionMethodName
+               );
+       }
+
+       /**
+        * Handles a request. The result output is returned by altering the given response.
+        *
+        * @param Tx_Extbase_MVC_RequestInterface $request The request object
+        * @param Tx_Extbase_MVC_ResponseInterface $response The response, modified by this handler
+        * @return void
+        */
+       public function processRequest(Tx_Extbase_MVC_RequestInterface $request, Tx_Extbase_MVC_ResponseInterface $response) {
+               $this->actionSequenceService->initialize($this, $request);
+               parent::processRequest($request, $response);
+       }
+
+       /**
+        * Resolves and checks the current action method name
+        *
+        * @return string Method name of the current action
+        * @throws Tx_Extbase_MVC_Exception_NoSuchAction if the action specified in the request object does not exist (and if there's no default action either).
+        */
+       protected function resolveActionMethodName() {
+               $actionMethodName = $this->actionSequenceService->getCurrentAction()->getActionMethodName();
+               $this->initializeActionMethodOverrideConditions($actionMethodName);
+
+               /** @var $argument Tx_Extbase_MVC_Controller_Argument */
+               foreach ($this->request->getArguments() as $argumentName => $argumentValue) {
+                       if (!is_null($this->actionOverrideConstraints[$argumentName])) {
+                               if ($this->actionOverrideConstraints[$argumentName]->isComplied($argumentValue) === TRUE) {
+
+                                               // Forward to next action if this action is to be omitted
+                                       $nextAction = $this->actionSequenceService->getNextAction();
+                                       if ($actionMethodName !== $nextAction->getActionMethodName()) {
+                                               $actionMethodName = $nextAction->getActionMethodName();
+                                               $this->actionSequenceService->getCurrentAction()->setOmitted(TRUE);
+                                               $this->actionSequenceService->persistOmittedActions();
+                                               $this->forward(
+                                                       $this->actionSequenceService->getNextAction()->getName(),
+                                                       $this->request->getControllerName(),
+                                                       $this->request->getControllerExtensionName(),
+                                                       $this->request->getArguments()
+                                               );
+                                       } else {
+                                                throw new Tx_LwEnetMultipleActionForms_MVC_Controller_Action_Override_Exception_InvalidActionMethod(
+                                                        'Can\'t resolve action "' . $actionMethodName . '" does not exist in controller "' . get_class($this) . '".',
+                                                        1322231384
+                                                );
+                                       }
+                               }
+                       }
+               }
+
+               if (!method_exists($this, $actionMethodName)) {
+                        throw new Tx_Extbase_MVC_Exception_NoSuchAction(
+                                'An action "' . $actionMethodName . '" does not exist in controller "' . get_class($this) . '".',
+                                1186669086
+                        );
+               }
+
+                       // Here should the persisted properties be dropped
+               $this->dropObsoleteProperties($actionMethodName);
+
+               return $actionMethodName;
+       }
+
+
+       /**
+        * @param string $actionMethodName
+        */
+       protected function dropObsoleteProperties($actionMethodName) {
+               $persistedControllerData = $this->sessionAdapter->load($this->request->getControllerObjectName());
+
+                       /** @var $methodReflection Tx_Extbase_Reflection_MethodReflection */
+               $methodReflection = $this->objectManager->get(
+                       'Tx_Extbase_Reflection_MethodReflection',
+                       get_class($this),
+                       $actionMethodName
+               );
+
+                       /** @var $parameterReflection Tx_Extbase_Reflection_ParameterReflection */
+               foreach ($methodReflection->getParameters() as $parameterReflection) {
+                               // @todo: check for implementation of interface Tx_LwEnetMultipleActionForms_Session_PersistenceInterface
+                       if (!isset($persistedControllerData['Arguments'][$parameterReflection->getName()])) {
+                               continue;
+                       } else {
+                               $persistedArgument = $persistedControllerData['Arguments'][$parameterReflection->getName()];
+                       }
+
+                       if ($this->request->hasArgument($parameterReflection->getName()) ) {
+                               $argument = $this->request->getArgument($parameterReflection->getName());
+
+                                       /** @var $classReflection Tx_Extbase_Reflection_ClassReflection */
+                               $classReflection = $parameterReflection->getClass();
+                               $propertyDependencies = $this->buildPropertyDependencies($parameterReflection->getClass());
+
+                               foreach ($propertyDependencies as $propertyName => $dependentPropertyNames) {
+                                       if (isset($persistedArgument[$propertyName]) && isset($argument[$propertyName])) {
+                                                       // @todo: check different types
+                                                       // Compare property values
+                                                       // Warning: This is no type safe comparison by intention:
+                                                       //              if for example a product uid is persisted as int, the incoming
+                                                       //              POST set is a string. If the value itself is not changed, it
+                                                       //              should not be dropped
+                                               if ($persistedArgument[$propertyName] != $argument[$propertyName]) {
+                                                       foreach ($dependentPropertyNames as $dependentPropertyName) {
+                                                               unset($argument[$dependentPropertyName]);
+                                                       }
+                                               }
+                                       }
+                               }
+                               $this->request->setArgument($parameterReflection->getName(), $argument);
+                       }
+               }
+       }
+
+       /**
+        * @param Tx_Extbase_Reflection_ClassReflection $classReflection
+        * @return array
+        */
+       protected function buildPropertyDependencies(Tx_Extbase_Reflection_ClassReflection $classReflection) {
+               $propertyDependencies = array();
+                       /** @var $propertyReflection Tx_Extbase_Reflection_PropertyReflection */
+               foreach ($classReflection->getProperties() as $propertyReflection) {
+                       if ($propertyReflection->isTaggedWith('dependency')) {
+                               $tagValues = $propertyReflection->getTagValues('dependency');
+                               foreach ($tagValues as $tagValue) {
+                                       $propertyToBeChanged = ltrim($tagValue, '$');
+                                       // propertyToBeChanged => propertiesToBeDropped
+                                       $propertyDependencies[$propertyToBeChanged][] = $propertyReflection->getName();
+                               }
+                       }
+               }
+
+                       // @todo; Add recursive relation processing
+                       // build related dependencies
+               foreach ($propertyDependencies as $propertyName => $propertyDependency) {
+                       foreach ($propertyDependency as $dependentProperty) {
+                               if (array_key_exists($dependentProperty, $propertyDependencies)) {
+                                       $propertyDependencies[$propertyName] = array_merge(
+                                               $propertyDependencies[$dependentProperty],
+                                               $propertyDependency
+                                       );
+                               }
+                       }
+               }
+
+               return $propertyDependencies;
+       }
+
+       /**
+        * Calls the specified action method and passes the arguments.
+        *
+        * If the action returns a string, it is appended to the content in the
+        * response object. If the action doesn't return anything and a valid
+        * view exists, the view is rendered automatically.
+        *
+        * @return void
+        * @api
+        */
+       protected function callActionMethod() {
+               $this->view->assign('actionSequenceData', $this->actionSequenceService->toArray());
+
+                       // @deprecated since Extbase 1.4.0, will be removed with Extbase 1.6.0.
+               $preparedArguments = array();
+
+               /** @var $argument Tx_Extbase_MVC_Controller_Argument */
+               foreach ($this->arguments as $argument) {
+                       $preparedArguments[$argument->getName()] = $argument->getValue();
+               }
+
+               if ($this->argumentsMappingResults->hasErrors()) {
+                       $this->actionSequenceService->persistOmittedActions();
+                       $actionResult = call_user_func(
+                               array($this, $this->errorMethodName)
+                       );
+               } else {
+                       $actionResult = call_user_func_array(
+                               array($this, $this->actionMethodName),
+                               $preparedArguments
+                       );
+                       if ($this->actionSequenceService->getCurrentAction()->isFinalAction()) {
+                               $this->sessionAdapter->clear();
+                       } else {
+                               if (!$this->argumentsPersisted) {
+                                       $this->persistArgumentsWithReferrerCheck($preparedArguments);
+                                       $this->argumentsPersisted = TRUE;
+                               }
+                       }
+               }
+
+               if ($actionResult === NULL && $this->view instanceof Tx_Extbase_MVC_View_ViewInterface) {
+                       $this->response->appendContent($this->view->render());
+               } elseif (is_string($actionResult) && strlen($actionResult) > 0) {
+                       $this->response->appendContent($actionResult);
+               } elseif (is_object($actionResult) && method_exists($actionResult, '__toString')) {
+                       $this->response->appendContent((string)$actionResult);
+               }
+       }
+
+       /**
+        * Persist arguments with additional referrer test
+        *
+        * @param array $arguments
+        * @return void
+        */
+       public function persistArgumentsWithReferrerCheck(array $arguments) {
+               if (!$this->request->hasArgument('__referrer')) {
+                       return;
+               }
+
+               $this->persistArguments($arguments);
+       }
+
+       /**
+        * persist arguments in session
+        *
+        * @param array $arguments
+        * @return void
+        */
+       public function persistArguments(array $arguments) {
+               foreach ($arguments as $argumentName => $argumentValue) {
+                       if ($this->isObjectImplementingSessionPersistenceInterface($argumentValue)) {
+                               $propertyData = array(
+                                       $argumentName => $this->convertObjectToArrayRecursively($argumentValue)
+                               );
+
+                               $this->storeSessionData('Arguments', $propertyData);
+                       }
+               }
+       }
+
+       /**
+        * @param Tx_LwEnetMultipleActionForms_Session_PersistenceInterface $sessionPersistenceObject
+        * @return array
+        */
+       protected function convertObjectToArrayRecursively(Tx_LwEnetMultipleActionForms_Session_PersistenceInterface $sessionPersistenceObject) {
+               $objectData = array();
+               /** @var $reflectionService Tx_LwEnetMultipleActionForms_Service_Reflection */
+               $reflectionService = $this->objectManager->get('Tx_LwEnetMultipleActionForms_Service_Reflection');
+               foreach ($reflectionService->getClassPropertiesToPersistInSession($sessionPersistenceObject) as $propertyName) {
+                       $propertyValue = call_user_func(
+                               array($sessionPersistenceObject, 'get' . ucfirst($propertyName))
+                       );
+                       if (isset($propertyValue) === TRUE) {
+                               if (is_object($propertyValue)) {
+                                       if ($this->isObjectImplementingSessionPersistenceInterface($propertyValue) === TRUE) {
+                                               $nestedObjectData = $this->convertObjectToArrayRecursively($propertyValue);
+                                               if (count($nestedObjectData) > 0) {
+                                                       $objectData[$propertyName] = $nestedObjectData;
+                                               }
+                                       } elseif ($this->isObjectImplementingDomainObjectInterface($propertyValue) === TRUE) {
+                                               $objectData[$propertyName] = $propertyValue->getUid();
+                                       } elseif ($this->isTraversableObjectProperty($sessionPersistenceObject, $propertyName) === TRUE) {
+                                               foreach ($propertyValue as $object) {
+                                                       if ($this->isObjectImplementingSessionPersistenceInterface($object)) {
+                                                               $objectData[$propertyName][] = $this->convertObjectToArrayRecursively($object);
+                                                       } elseif ($this->isObjectImplementingDomainObjectInterface($object) === TRUE) {
+                                                               $objectData[$propertyName][] = $object->getUid();
+                                                       } else {
+                                                               debug('Not handled child object!');
+                                                       }
+                                               }
+                                       } elseif ($propertyValue instanceof DateTime) {
+                                               $objectData[$propertyName] = $propertyValue->format('c');
+                                       } else {
+                                               debug('Not handled object');
+                                               // Not handled objects
+                                       }
+                               } else {
+                                       $objectData[$propertyName] = $propertyValue;
+                               }
+                       }
+               }
+               return $objectData;
+       }
+
+       /**
+        * Store session data
+        *
+        * @param string $key
+        * @param mixed $data
+        * @return void
+        */
+       protected function storeSessionData($key, $data) {
+               $className = get_class($this);
+               $sessionData = $this->sessionAdapter->load($className);
+               $sessionData[$key] = $data;
+               $this->sessionAdapter->store($className, $sessionData);
+       }
+
+       /**
+        * @param object $object
+        * @return bool
+        */
+       protected function isObjectImplementingSessionPersistenceInterface($object) {
+               if (is_object($object)) {
+                       $result = in_array(
+                               Tx_LwEnetMultipleActionForms_Session_AdapterInterface::SESSION_PERSISTENCE_INTERFACE,
+                               class_implements($object)
+                       );
+               } else {
+                       $result = FALSE;
+               }
+               return $result;
+       }
+
+       /**
+        * @param object $object
+        * @return bool
+        */
+       protected function isObjectImplementingDomainObjectInterface($object) {
+               if (is_object($object)) {
+                       $result = in_array(
+                               'Tx_Extbase_DomainObject_DomainObjectInterface',
+                               class_implements($object)
+                       );
+               } else {
+                       $result = FALSE;
+               }
+               return $result;
+       }
+
+       /**
+        * @param object $object
+        * @param string $propertyName
+        * @return bool
+        */
+       protected function isTraversableObjectProperty($object, $propertyName) {
+               if (is_object($object)) {
+                       /** @var $classSchema Tx_Extbase_Reflection_ClassSchema */
+                       $classSchema = $this->reflectionService->getClassSchema($object);
+                       if ($classSchema->hasProperty($propertyName)) {
+                               $propertyInformation = $classSchema->getProperty($propertyName);
+                               $result = in_array(
+                                       $propertyInformation['type'],
+                                       array('array', 'ArrayObject', 'SplObjectStorage', 'Tx_Extbase_Persistence_ObjectStorage')
+                               );
+                       } else {
+                               $result = FALSE;
+                       }
+               } else {
+                       $result = FALSE;
+               }
+               return $result;
+       }
+
+       /**
+        * A special action which is called if the originally intended action could
+        * not be called, for example if the arguments were not valid.
+        *
+        * The default implementation sets a flash message, request errors and forwards back
+        * to the originating action. This is suitable for most actions dealing with form input.
+        *
+        * We clear the page cache by default on an error as well, as we need to make sure the
+        * data is re-evaluated when the user changes something.
+        *
+        * @return string
+        * @api
+        */
+       protected function errorAction() {
+               $this->request->setErrors($this->argumentsMappingResults->getErrors());
+               $this->clearCacheOnError();
+
+               $errorFlashMessage = $this->getErrorFlashMessage();
+               if ($errorFlashMessage !== FALSE) {
+                       $this->flashMessageContainer->add($errorFlashMessage, '', t3lib_FlashMessage::ERROR);
+               }
+
+               $sessionData = $this->sessionAdapter->load(get_class($this));
+
+               $refererIsFirstAction = FALSE;
+               if ($this->request->hasArgument('__referrer')) {
+                       $refererAction = $this->actionSequenceService->getReferrerAction();
+                       if ($refererAction instanceof Tx_LwEnetMultipleActionForms_MVC_Controller_Action && $refererAction->getIndex() === 0) {
+                               $refererIsFirstAction = TRUE;
+                       }
+               }
+
+               /*
+                * test sessionError
+                * 1) no arguments in session
+                * 2) we are not no first action
+                * 3) referer is not first action
+                */
+               if (is_array($sessionData['Arguments']) === FALSE && $this->actionSequenceService->isFirstAction() === FALSE && $refererIsFirstAction === FALSE) {
+                       if (isset($this->settings['errorPidOnSessionErrors'])) {
+                               $pageUid = (int)$this->settings['errorPidOnSessionErrors'];
+                               $uriBuilder = $this->controllerContext->getUriBuilder();
+                               $uri = $uriBuilder->setTargetPageUid($pageUid)->build();
+                               $this->redirectToURI($uri);
+                       } else {
+                               $this->flashMessageContainer->flush();
+                               $this->flashMessageContainer->add(
+                                       Tx_Extbase_Utility_Localization::translate(
+                                               'errorAction.sessionError.message',
+                                               'LwEnetMultipleActionForms'
+                                       ),
+                                       Tx_Extbase_Utility_Localization::translate(
+                                               'errorAction.sessionError.title',
+                                               'LwEnetMultipleActionForms'
+                                       ),
+                                       t3lib_FlashMessage::WARNING
+                               );
+
+                               $this->redirect(
+                                       $this->actionSequenceService->getFirstAction()->getName(),
+                                       $this->request->getControllerName(),
+                                       $this->request->getControllerExtensionName()
+                               );
+                       }
+               }
+
+               if ($this->request->hasArgument('__referrer')) {
+                       $referrer = $this->request->getArgument('__referrer');
+                       $this->forward($referrer['actionName'], $referrer['controllerName'], $referrer['extensionName'], $this->request->getArguments());
+               }
+
+               $this->redirect(
+                       array_shift($this->actionSequenceService->getSequence()),
+                       $this->request->getControllerName(),
+                       $this->request->getControllerExtensionName()
+               );
+       }
+
+       /**
+        * @return string
+        */
+       public function getActionMethodName() {
+               return $this->request->getControllerActionName() . 'Action';
+       }
+
+}
+?>
diff --git a/Classes/MVC/Controller/Action.php b/Classes/MVC/Controller/Action.php
new file mode 100644 (file)
index 0000000..db29520
--- /dev/null
@@ -0,0 +1,163 @@
+<?php
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Helge Funk <helge.funk@e-net.info>
+ *
+ *  All rights reserved
+ *
+ *  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 3 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!
+ ***************************************************************/
+
+
+/**
+ *
+ *
+ * @package lw_enet_multiple_action_forms
+ * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License, version 3 or later
+ *
+ */
+class Tx_LwEnetMultipleActionForms_MVC_Controller_Action {
+
+       /**
+        * @var Tx_Extbase_Reflection_MethodReflection
+        */
+       protected $methodReflection;
+
+       /**
+        * name
+        * @var string
+        */
+       protected $name;
+
+       /**
+        * index
+        * @var integer
+        */
+       protected $index;
+
+       /**
+        * omitted
+        * @var boolean
+        */
+       protected $omitted;
+
+       /**
+        * Final action
+        *
+        * @var boolean
+        */
+       protected $finalAction;
+
+       /**
+        * @param string $name
+        * @param integer $index
+        * @param Tx_Extbase_Reflection_MethodReflection $methodReflection
+        * @return Tx_LwEnetMultipleActionForms_MVC_Controller_Action
+        */
+       public function __construct($name, $index, Tx_Extbase_Reflection_MethodReflection $methodReflection) {
+               $this->name = $name;
+               $this->index = (int)$index;
+               $this->methodReflection = $methodReflection;
+               $this->omitted = FALSE;
+       }
+
+       /**
+        * Getter for methodReflection
+        *
+        * @return Tx_Extbase_Reflection_MethodReflection methodReflection
+        */
+       public function getMethodReflection() {
+               return $this->methodReflection;
+       }
+
+       /**
+        * Getter for name
+        *
+        * @return string name
+        */
+       public function getName() {
+               return $this->name;
+       }
+
+       /**
+        * Getter for index
+        *
+        * @return integer index
+        */
+       public function getIndex() {
+               return $this->index;
+       }
+
+       /**
+        * Setter for omitted
+        *
+        * @param boolean $omitted
+        * @return void
+        */
+       public function setOmitted($omitted) {
+               $this->omitted = $omitted;
+       }
+
+       /**
+        * Getter for omitted
+        *
+        * @return boolean omitted
+        */
+       public function getOmitted() {
+               return $this->omitted;
+       }
+
+       /**
+        * Getter for actionMethodName
+        *
+        * @return string actionMethodName
+        */
+       public function getActionMethodName() {
+               return $this->name . 'Action';
+       }
+
+       /**
+        * @return bool
+        */
+       public function isPreviewAction() {
+               return $this->methodReflection->isTaggedWith('previewAction');
+       }
+
+       /**
+        * @return bool
+        */
+       public function isFinalAction() {
+               if (isset($this->finalAction)) {
+                       return $this->finalAction;
+               } else {
+                       return $this->methodReflection->isTaggedWith('finalAction');
+               }
+       }
+
+       /**
+        * Possibility to overrule final action
+        *
+        * @param boolan $finalAction
+        */
+       public function setFinalAction($finalAction) {
+               $this->finalAction = $finalAction;
+       }
+
+}
+?>
\ No newline at end of file
diff --git a/Classes/MVC/Controller/Action/Override/ConstraintResolver.php b/Classes/MVC/Controller/Action/Override/ConstraintResolver.php
new file mode 100644 (file)
index 0000000..7e21df9
--- /dev/null
@@ -0,0 +1,94 @@
+<?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!
+***************************************************************/
+
+/**
+ * Validator resolver to automatically find a appropriate validator for a given subject
+ *
+ * @package Extbase
+ * @subpackage Validation
+ * @version $Id$
+ */
+class Tx_LwEnetMultipleActionForms_MVC_Controller_Action_Override_ConstraintResolver extends Tx_LwEnetMultipleActionForms_Comparison_ConstraintResolver {
+
+       /**
+        * @param string $className
+        * @param string $methodName
+        * @return array
+        * @throws Tx_LwEnetMultipleActionForms_MVC_Controller_Action_Override_Exception_InvalidConditionConfiguration|Tx_LwEnetMultipleActionForms_MVC_Controller_Action_Override_Exception_NoSuchCondition
+        */
+       public function buildMethodArgumentsOverrideActionConstraints($className, $methodName) {
+               $constraintConjunctions = array();
+
+               $methodParameters = $this->reflectionService->getMethodParameters($className, $methodName);
+               $methodTagsValues = $this->reflectionService->getMethodTagsValues($className, $methodName);
+
+               if (!count($methodParameters)) {
+                       // early return in case no parameters were found.
+                       return $constraintConjunctions;
+               }
+
+               if (isset($methodTagsValues['actionOverrideConstraint'])) {
+                       foreach ($methodParameters as $parameterName => $methodParameter) {
+                               $constraintConjunctions[$parameterName] = $this->createConstraint('Conjunction');
+                       }
+
+                       $parsedConstraints = Tx_LwEnetMultipleActionForms_Utility_Annotations_ConstraintParser::parseConstraintAnnotations(
+                               $methodTagsValues['actionOverrideConstraint']
+                       );
+                       foreach ($parsedConstraints as $parsedConstraint) {
+                               if (is_array($parsedConstraint['constraintOptions'])) {
+                                       $newConstraint = $this->createConstraint(
+                                               $parsedConstraint['constraintName'],
+                                               $parsedConstraint['constraintOptions']
+                                       );
+                               } else {
+                                       $newConstraint = $this->createConstraint($parsedConstraint['constraintName']);
+                               }
+                               if ($newConstraint === NULL) {
+                                       throw new Tx_LwEnetMultipleActionForms_Comparison_Exception_NoSuchConstraint(
+                                               'Invalid overrideCondition annotation in ' . $className . '->' . $methodName . '(): Could not resolve class name for overrideCondition "' . $parsedConstraint['constraintName'] . '".',
+                                               1322225440
+                                       );
+                               }
+
+                               if  (isset($constraintConjunctions[$parsedConstraint['constraintProperty']])) {
+                                       $constraintConjunctions[$parsedConstraint['constraintProperty']]->addConstraint(
+                                               $newConstraint
+                                       );
+                               } else {
+                                       throw new Tx_LwEnetMultipleActionForms_Comparison_Exception_InvalidConstraintConfiguration(
+                                               'Invalid overrideCondition annotation in ' . $className . '->' . $methodName . '(): OverrideCondition specified for argument name "' . $parsedConstraint['constraintProperty'] . '", but this argument does not exist.',
+                                               1253172726
+                                       );
+                               }
+                       }
+               }
+               return $constraintConjunctions;
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/Classes/MVC/Controller/Action/Override/Exception.php b/Classes/MVC/Controller/Action/Override/Exception.php
new file mode 100644 (file)
index 0000000..84f4ccd
--- /dev/null
@@ -0,0 +1,39 @@
+<?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!
+***************************************************************/
+
+/**
+ * A generic validation exception
+ *
+ * @package Extbase
+ * @subpackage Validation
+ * @version $ID:$
+ */
+class Tx_LwEnetMultipleActionForms_MVC_Controller_Action_Override_Exception extends Tx_Extbase_Exception {
+
+}
+
+?>
\ No newline at end of file
diff --git a/Classes/MVC/Controller/Action/Override/Exception/InvalidActionMethod.php b/Classes/MVC/Controller/Action/Override/Exception/InvalidActionMethod.php
new file mode 100644 (file)
index 0000000..0a28e09
--- /dev/null
@@ -0,0 +1,39 @@
+<?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!
+***************************************************************/
+
+/**
+ * A "InvalidValidationConfiguration" Exception
+ *
+ * @package Extbase
+ * @subpackage Validation\Exception
+ * @version $ID:$
+ */
+class Tx_LwEnetMultipleActionForms_MVC_Controller_Action_Override_Exception_InvalidActionMethod extends Tx_LwEnetMultipleActionForms_MVC_Controller_Action_Override_Exception {
+
+}
+
+?>
\ No newline at end of file
diff --git a/Classes/MVC/Controller/Exception.php b/Classes/MVC/Controller/Exception.php
new file mode 100644 (file)
index 0000000..f815037
--- /dev/null
@@ -0,0 +1,38 @@
+<?php
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Helge Funk <helge.funk@e-net.info>
+ *
+ *  All rights reserved
+ *
+ *  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 3 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!
+ ***************************************************************/
+
+/**
+ * A generic Controller Exception
+ *
+ * @package lw_enet_multiple_action_forms
+ * @subpackage Controller
+ * @version $Id$
+ */
+class Tx_LwEnetMultipleActionForms_MVC_Controller_Exception extends Tx_Extbase_Exception {
+
+}
+
+?>
\ No newline at end of file
diff --git a/Classes/MVC/Controller/Exception/ActionSequenceAnnotationMissing.php b/Classes/MVC/Controller/Exception/ActionSequenceAnnotationMissing.php
new file mode 100644 (file)
index 0000000..fed04f2
--- /dev/null
@@ -0,0 +1,38 @@
+<?php
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Helge Funk <helge.funk@e-net.info>
+ *
+ *  All rights reserved
+ *
+ *  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 3 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!
+ ***************************************************************/
+
+/**
+ * A generic Controller Exception
+ *
+ * @package lw_enet_multiple_action_forms
+ * @subpackage Controller
+ * @version $Id$
+ */
+class Tx_LwEnetMultipleActionForms_MVC_Controller_Exception_ActionSequenceAnnotationMissing extends Tx_Extbase_Exception {
+
+}
+
+?>
\ No newline at end of file
diff --git a/Classes/MVC/Web/BackendRequestHandler.php b/Classes/MVC/Web/BackendRequestHandler.php
new file mode 100644 (file)
index 0000000..602b918
--- /dev/null
@@ -0,0 +1,121 @@
+<?php
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Helge Funk <helge.funk@e-net.info>
+ *
+ *  All rights reserved
+ *
+ *  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 3 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!
+ ***************************************************************/
+
+
+/**
+ *
+ *
+ * @package lw_enet_multiple_action_forms
+ * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License, version 3 or later
+ *
+ */
+class Tx_LwEnetMultipleActionForms_MVC_Web_BackendRequestHandler extends Tx_Extbase_MVC_Web_BackendRequestHandler {
+
+       /**
+        * @var Tx_Extbase_MVC_Web_Request
+        */
+       protected $request;
+
+       /**
+        * @var Tx_LwEnetMultipleActionForms_Session_BackendSessionAdapter
+        */
+       protected $sessionAdapter;
+
+       /**
+        * Injects session adapter
+        *
+        * @param Tx_LwEnetMultipleActionForms_Session_AdapterInterface $sessionAdapter
+        */
+       public function injectSessionAdapter(Tx_LwEnetMultipleActionForms_Session_AdapterInterface $sessionAdapter) {
+               $this->sessionAdapter = $sessionAdapter;
+       }
+
+       /**
+        * Handles the web request. The response will automatically be sent to the client.
+        *
+        * @return Tx_Extbase_MVC_Web_Response
+        */
+       public function handleRequest() {
+                       /** @var $requestHashService Tx_Extbase_Security_Channel_RequestHashService */
+               $requestHashService = $this->objectManager->get('Tx_Extbase_Security_Channel_RequestHashService'); // singleton
+               $requestHashService->verifyRequest($this->request);
+
+                       /** @var $response Tx_Extbase_MVC_Web_Response */
+               $response = $this->objectManager->create('Tx_Extbase_MVC_Web_Response');
+
+               if ($this->request->hasArgument('__referrer')) {
+                       $persistedControllerData = $this->sessionAdapter->load($this->request->getControllerObjectName());
+                       if (count($persistedControllerData) > 0) {
+                               foreach ($persistedControllerData['Arguments'] as $argumentName => $argumentValue) {
+                                       if ($this->request->hasArgument($argumentName)) {
+                                               $argument = $this->request->getArgument($argumentName);
+                                               $argument = t3lib_div::array_merge_recursive_overrule(
+                                                       $argumentValue,
+                                                       $argument
+                                               );
+                                               $this->request->setArgument($argumentName, $argument);
+                                       } else {
+                                               // @todo: is this case needed anymore???
+                                               $this->request->setHmacVerified(TRUE);
+                                               $this->request->setArgument($argumentName, $argumentValue);
+                                       }
+                               }
+                       }
+               } else {
+                       $this->sessionAdapter->clear();
+               }
+
+               $this->dispatcher->dispatch($this->request, $response);
+
+               return $response;
+       }
+
+       /**
+        * This request handler can handle a web request invoked by the backend.
+        *
+        * @return boolean If we are in backend mode TRUE otherwise FALSE
+        */
+       public function canHandleRequest() {
+               $this->request = $this->requestBuilder->build();
+               $isMultipleActionFormsController = is_subclass_of(
+                       $this->request->getControllerObjectName(),
+                       'Tx_LwEnetMultipleActionForms_MVC_Controller_AbstractController'
+               );
+               return (TYPO3_MODE === 'BE') && ($isMultipleActionFormsController === TRUE);
+       }
+
+       /**
+        * Returns the priority - how eager the handler is to actually handle the
+        * request.
+        *
+        * @return integer The priority of the request handler.
+        */
+       public function getPriority() {
+               return 110;
+       }
+
+}
+?>
\ No newline at end of file
diff --git a/Classes/MVC/Web/FrontendRequestHandler.php b/Classes/MVC/Web/FrontendRequestHandler.php
new file mode 100644 (file)
index 0000000..49d4434
--- /dev/null
@@ -0,0 +1,149 @@
+<?php
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Helge Funk <helge.funk@e-net.info>
+ *
+ *  All rights reserved
+ *
+ *  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 3 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!
+ ***************************************************************/
+
+
+/**
+ *
+ *
+ * @package lw_enet_multiple_action_forms
+ * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License, version 3 or later
+ *
+ */
+class Tx_LwEnetMultipleActionForms_MVC_Web_FrontendRequestHandler extends Tx_Extbase_MVC_Web_FrontendRequestHandler {
+
+       /**
+        * @var array
+        */
+       protected $sessionData;
+
+       /**
+        * @var Tx_LwEnetMultipleActionForms_Session_AdapterInterface
+        */
+       protected $sessionAdapter;
+
+       /**
+        * @var Tx_Extbase_MVC_Web_Request
+        */
+       protected $request;
+
+       /**
+        * Injects session adapter
+        *
+        * @param Tx_LwEnetMultipleActionForms_Session_AdapterInterface $sessionAdapter
+        */
+       public function injectSessionAdapter(Tx_LwEnetMultipleActionForms_Session_AdapterInterface $sessionAdapter) {
+               $this->sessionAdapter = $sessionAdapter;
+       }
+
+       /**
+        * Handles the web request. The response will automatically be sent to the client.
+        *
+        * @return Tx_Extbase_MVC_Web_Response
+        */
+       public function handleRequest() {
+
+               if (!($this->request instanceof Tx_Extbase_MVC_Request)) {
+                       // @todo: throw exception if request is not initialized
+               }
+
+               /** @var $requestHashService Tx_Extbase_Security_Channel_RequestHashService */
+               $requestHashService = $this->objectManager->get('Tx_Extbase_Security_Channel_RequestHashService'); // singleton
+               $requestHashService->verifyRequest($this->request);
+
+               if ($this->isCacheable($this->request->getControllerName(), $this->request->getControllerActionName())) {
+                       $this->request->setIsCached(TRUE);
+               } else {
+                       $contentObject = $this->configurationManager->getContentObject();
+                       if ($contentObject->getUserObjectType() === tslib_cObj::OBJECTTYPE_USER) {
+                               $contentObject->convertToUserIntObject();
+                               // tslib_cObj::convertToUserIntObject() will recreate the object, so we have to stop the request here
+                               return;
+                       }
+                       $this->request->setIsCached(FALSE);
+               }
+               $response = $this->objectManager->create('Tx_Extbase_MVC_Web_Response');
+
+                       // Debug request arguments of this request
+                       // This commented debug is committed by purpose, please do net remove
+               //debug($this->request->getArguments(), 'Incoming arguments', __FILE__, __LINE__);
+
+               if ($this->request->hasArgument('__referrer')) {
+                       $persistedControllerData = $this->sessionAdapter->load($this->request->getControllerObjectName());
+
+                               // Debug data coming from session
+                               // This commented debug is committed by purpose, please do net remove
+                       //debug($this->request->getArguments(), 'Persisted data coming from session', __FILE__, __LINE__);
+
+                       if (count($persistedControllerData) > 0 && isset($persistedControllerData['Arguments'])) {
+                               foreach ($persistedControllerData['Arguments'] as $argumentName => $argumentValue) {
+                                       if ($this->request->hasArgument($argumentName)) {
+                                               $argument = $this->request->getArgument($argumentName);
+                                               $argument = t3lib_div::array_merge_recursive_overrule(
+                                                       $argumentValue,
+                                                       $argument
+                                               );
+                                               $this->request->setArgument($argumentName, $argument);
+                                       } else {
+                                                       // @todo: is this case needed anymore???
+                                               $this->request->setHmacVerified(TRUE);
+                                               $this->request->setArgument($argumentName, $argumentValue);
+                                       }
+                               }
+                       }
+               } else {
+                       $this->sessionAdapter->clear();
+               }
+               $this->dispatcher->dispatch($this->request, $response);
+
+               return $response;
+       }
+
+       /**
+        * This request handler can handle any web request.
+        *
+        * @return boolean If the request is a web request, TRUE otherwise FALSE
+        */
+       public function canHandleRequest() {
+               $this->request = $this->requestBuilder->build();
+               $isMultipleActionFormsController = is_subclass_of(
+                       $this->request->getControllerObjectName(),
+                       'Tx_LwEnetMultipleActionForms_MVC_Controller_AbstractController'
+               );
+               return (TYPO3_MODE === 'FE') && ($isMultipleActionFormsController === TRUE);
+       }
+
+       /**
+        * Returns the priority - how eager the handler is to actually handle the
+        * request.
+        *
+        * @return integer The priority of the request handler.
+        */
+       public function getPriority() {
+               return 110;
+       }
+
+}
+?>
diff --git a/Classes/Service/ActionSequence.php b/Classes/Service/ActionSequence.php
new file mode 100644 (file)
index 0000000..c7bc98a
--- /dev/null
@@ -0,0 +1,475 @@
+<?php
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Helge Funk <helge.funk@e-net.info>
+ *
+ *  All rights reserved
+ *
+ *  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 3 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!
+ ***************************************************************/
+
+
+/**
+ *
+ *
+ * @package lw_enet_multiple_action_forms
+ * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License, version 3 or later
+ *
+ */
+class Tx_LwEnetMultipleActionForms_Service_ActionSequence implements t3lib_Singleton {
+
+       /**
+        * @var Tx_Extbase_Object_ObjectManagerInterface
+        */
+       protected $objectManager;
+
+       /**
+        * @var Tx_Extbase_MVC_RequestInterface
+        */
+       protected $request;
+
+       /**
+        * @var array<Tx_LwEnetMultipleActionForms_MVC_Controller_Action>
+        */
+       protected $sequence;
+
+       /**
+        * @var Tx_Extbase_Reflection_Service
+        */
+       protected $reflectionService;
+
+       /**
+        * @var Tx_Extbase_Reflection_ClassReflection
+        */
+       protected $controllerReflection;
+
+       /**
+        * @var Tx_LwEnetMultipleActionForms_Session_AdapterInterface
+        */
+       protected $sessionAdapter;
+
+       /**
+        * @var array
+        */
+       protected $omittedActions;
+
+       /**
+        * @param Tx_LwEnetMultipleActionForms_MVC_Controller_AbstractController $controller
+        * @param  Tx_Extbase_MVC_RequestInterface $request
+        * @return Tx_LwEnetMultipleActionForms_Service_ActionSequence
+        * @throws Tx_LwEnetMultipleActionForms_MVC_Controller_Exception_ActionSequenceAnnotationMissing
+        */
+       public function initialize(Tx_LwEnetMultipleActionForms_MVC_Controller_AbstractController $controller, Tx_Extbase_MVC_RequestInterface $request) {
+               $this->request = $request;
+
+               /** @var $classReflection Tx_Extbase_Reflection_ClassReflection */
+               $this->controllerReflection = $this->objectManager->get(
+                       'Tx_Extbase_Reflection_ClassReflection',
+                       $controller
+               );
+
+               if ($this->controllerReflection->isTaggedWith('actionSequence')) {
+                       $actionSequenceValues = $this->controllerReflection->getTagValues('actionSequence');
+                       $actions = t3lib_div::trimExplode(
+                               ',',
+                               array_shift($actionSequenceValues),
+                               TRUE
+                       );
+
+                       foreach ($actions as $actionIndex => $actionName) {
+                               $actionMethodName = $actionName . 'Action';
+                               if ($this->controllerReflection->hasMethod($actionMethodName)) {
+                                       /** @var $action Tx_LwEnetMultipleActionForms_MVC_Controller_Action */
+                                       $action = $this->objectManager->get(
+                                               'Tx_LwEnetMultipleActionForms_MVC_Controller_Action',
+                                               $actionName,
+                                               $actionIndex,
+                                               $this->controllerReflection->getMethod($actionMethodName)
+                                       );
+                                       $this->sequence[$actionIndex] = $action;
+                               } else {
+                                       throw new Tx_Extbase_MVC_Exception_NoSuchAction(
+                                               'No such action in Controller: ' . get_class($controller) . '->' . $actionMethodName,
+                                               1322527814
+                                       );
+                               }
+                       }
+
+               } else {
+                       throw new Tx_LwEnetMultipleActionForms_MVC_Controller_Exception_ActionSequenceAnnotationMissing(
+                               'ActionSequence annotation missing in Controller: ' . get_class($this),
+                               1322141888
+                       );
+               }
+
+               if ($this->getReferrerAction() instanceof Tx_LwEnetMultipleActionForms_MVC_Controller_Action) {
+                       if ($this->getReferrerAction()->getIndex() > $this->getCurrentAction()->getIndex()) {
+                               $this->resetOmittedActions();
+                       }
+               }
+       }
+
+       /**
+        * Injects the object manager
+        *
+        * @param Tx_Extbase_Object_ObjectManagerInterface $objectManager
+        * @return void
+        */
+       public function injectObjectManager(Tx_Extbase_Object_ObjectManagerInterface $objectManager) {
+               $this->objectManager = $objectManager;
+       }
+
+       /**
+        * Injects the reflection service
+        *
+        * @param Tx_Extbase_Reflection_Service $reflectionService
+        * @return void
+        */
+       public function injectReflectionService(Tx_Extbase_Reflection_Service $reflectionService) {
+               $this->reflectionService = $reflectionService;
+       }
+
+       /**
+        * Injects session adapter
+        *
+        * @param Tx_LwEnetMultipleActionForms_Session_AdapterInterface $sessionAdapter
+        */
+       public function injectSessionAdapter(Tx_LwEnetMultipleActionForms_Session_AdapterInterface $sessionAdapter) {
+               $this->sessionAdapter = $sessionAdapter;
+       }
+
+       /**
+        * @return void
+        * @throws Tx_LwEnetMultipleActionForms_Controller_Exception
+        */
+       public function initializeObject() {
+
+       }
+
+       /**
+        * Getter for sequence
+        *
+        * @return array sequence
+        */
+       public function getSequence() {
+               return $this->sequence;
+       }
+
+       /**
+        * Getter for request
+        *
+        * @return Tx_Extbase_MVC_RequestInterface request
+        */
+       public function getRequest() {
+               return $this->request;
+       }
+
+       /**
+        * Setter for controllerReflection
+        *
+        * @param Tx_Extbase_Reflection_ClassReflection $controllerReflection
+        * @return void
+        */
+       public function setControllerReflection(Tx_Extbase_Reflection_ClassReflection $controllerReflection) {
+               $this->controllerReflection = $controllerReflection;
+       }
+
+       /**
+        * Getter for controllerReflection
+        *
+        * @return Tx_Extbase_Reflection_ClassReflection controllerReflection
+        */
+       public function getControllerReflection() {
+               return $this->controllerReflection;
+       }
+
+       /**
+        * @return bool
+        */
+       public function isFirstAction() {
+               /** @var $firstAction Tx_LwEnetMultipleActionForms_MVC_Controller_Action */
+               $firstAction = reset($this->sequence);
+               return ($firstAction == $this->getCurrentAction());
+       }
+
+       /**
+        * @return bool
+        */
+       public function isLastAction() {
+               /** @var $lastAction Tx_LwEnetMultipleActionForms_MVC_Controller_Action */
+               $lastAction = end($this->sequence);
+               return ($lastAction == $this->getCurrentAction());
+       }
+
+       /**
+        * @return Tx_LwEnetMultipleActionForms_MVC_Controller_Action
+        */
+       public function getCurrentAction() {
+               return $this->getActionByActionName($this->request->getControllerActionName());
+       }
+
+       /**
+        * @return integer
+        * @deprecated
+        */
+       public function getCurrentActionIndex() {
+               $result = array_search($this->getCurrentAction(), $this->sequence);
+               if ($result === FALSE) {
+                       $result = 0;
+               }
+               return (int)$result;
+       }
+
+       /**
+        * @return Tx_LwEnetMultipleActionForms_MVC_Controller_Action
+        */
+       public function getReferrerAction() {
+               $referrer = NULL;
+               if ($this->request->hasArgument('__referrer')) {
+                       $referrer = $this->request->getArgument('__referrer');
+               }
+               return $this->getActionByActionName($referrer['actionName']);
+       }
+
+       public function getFirstAction() {
+               $actions = $this->getSequence();
+               return $actions[0];
+       }
+
+       /**
+        * @return Tx_LwEnetMultipleActionForms_MVC_Controller_Action
+        */
+       public function getPreviousAction() {
+               $previousAction = $this->getCurrentAction();
+               $omittedActions = $this->getOmittedActions();
+               $actionIndex = $this->getCurrentActionIndex() - 1;
+               while (!is_null($this->sequence[$actionIndex])) {
+                       /** @var $action Tx_LwEnetMultipleActionForms_MVC_Controller_Action */
+                       $action = $this->sequence[$actionIndex];
+                       if (!in_array($action->getName(), $omittedActions)) {
+                               $previousAction = $action;
+                               break 1;
+                       }
+                       $actionIndex--;
+               }
+               return $previousAction;
+       }
+
+       /**
+        * @return Tx_LwEnetMultipleActionForms_MVC_Controller_Action
+        */
+       public function getNextAction() {
+               $nextAction = $this->getCurrentAction();
+               $result = array_search($this->getCurrentAction(), $this->sequence);
+               if ($result !== FALSE) {
+                       if (!is_null($this->sequence[($result + 1)])) {
+                               $nextAction = $this->sequence[($result + 1)];
+                       }
+               }
+               return $nextAction;
+       }
+
+       /**
+        * @return array
+        */
+       public function toArray() {
+               $actionFlowData = array(
+                       'actionSequence' => $this->getSequence(),
+                       'actionCount' => count($this->getSequence()),
+                       'previousAction' => $this->getPreviousAction(),
+                       'currentAction' => $this->getCurrentAction(),
+                       'nextAction' => $this->getNextAction(),
+                       'isFirstAction' => $this->isFirstAction(),
+                       'isLastAction' => $this->isLastAction(),
+                       'isPreviewAction' => $this->getCurrentAction()->isPreviewAction(),
+                       'isFinalAction' => $this->getCurrentAction()->isFinalAction(),
+               );
+               return $actionFlowData;
+       }
+
+       /**
+        * @param $actionName
+        * @return int
+        */
+       public function getActionIndexByActionName($actionName) {
+               $actionIndex = NULL;
+               /** @var $action Tx_LwEnetMultipleActionForms_MVC_Controller_Action */
+               foreach ($this->sequence as $actionIndex => $action) {
+                       if ($actionName == $action->getName()) {
+                               return $actionIndex;
+                       }
+               }
+       }
+
+       /**
+        * @param $actionName
+        * @return Tx_LwEnetMultipleActionForms_MVC_Controller_Action
+        */
+       public function getActionByActionName($actionName) {
+               /** @var $action Tx_LwEnetMultipleActionForms_MVC_Controller_Action */
+               foreach ($this->sequence as $actionIndex => $action) {
+                       if ($actionName == $action->getName()) {
+                               return $action;
+                       }
+               }
+       }
+
+       /**
+        * persist
+        *
+        * @return void
+        */
+       public function persistOmittedActions() {
+               $omittedActions = array();
+               /** @var $action Tx_LwEnetMultipleActionForms_MVC_Controller_Action */
+               foreach ($this->sequence as $action) {
+                       if ($action->getOmitted() === TRUE) {
+                               $omittedActions[$action->getIndex()] = $action->getName();
+                       }
+               }
+               $this->storeOmittedActionsInSession($omittedActions);
+       }
+
+       /**
+        * @param array $omittedActions
+        * @return void
+        */
+       public function updateSequence(array $omittedActions) {
+               /** @var $action Tx_LwEnetMultipleActionForms_MVC_Controller_Action */
+               foreach ($this->sequence as $actionIndex => $action) {
+                       if (in_array($action->getName(), $omittedActions)) {
+                               $action->setOmitted(TRUE);
+                       } else {
+                               $action->setOmitted(FALSE);
+                       }
+               }
+       }
+
+       /**
+        * persist
+        *
+        * @return void
+        */
+       public function resetOmittedActions() {
+               $sessionData = $this->sessionAdapter->load($this->request->getControllerObjectName());
+               if (is_array($sessionData['OmittedActions'])) {
+                       foreach ($sessionData['OmittedActions'] as $actionIndex => $omittedActionName) {
+                               if ($this->getActionIndexByActionName($omittedActionName) >= $this->getCurrentActionIndex()) {
+                                       unset($sessionData['OmittedActions'][$actionIndex]);
+                               }
+                       }
+               } else {
+                       $sessionData['OmittedActions'] = array();
+               }
+               $this->storeOmittedActionsInSession($sessionData['OmittedActions'], FALSE);
+       }
+
+       /**
+        * persist
+        *
+        * @return array
+        */
+       public function getOmittedActions() {
+               $sessionData = $this->sessionAdapter->load($this->request->getControllerObjectName());
+               $omittedActions = array();
+               if (is_array($sessionData['OmittedActions'])) {
+                       $omittedActions = $sessionData['OmittedActions'];
+               }
+               $this->updateSequence($omittedActions);
+               return $omittedActions;
+       }
+
+       /**
+        * @param array $omittedActions
+        * @param boolean $attachData
+        * @return void
+        */
+       protected function storeOmittedActionsInSession(array $omittedActions, $attachData = TRUE) {
+               $sessionData = $this->sessionAdapter->load($this->request->getControllerObjectName());
+               $key = 'OmittedActions';
+
+               if (!is_array($sessionData[$key])) {
+                       $sessionData[$key] = array();
+               }
+               if ($attachData === TRUE) {
+                       $sessionData[$key] += $omittedActions;
+               } else {
+                       $sessionData[$key] = $omittedActions;
+               }
+               $this->updateSequence($sessionData[$key]);
+               $this->sessionAdapter->store($this->request->getControllerObjectName(), $sessionData);
+       }
+
+
+       /**
+        * @param array $constraints
+        * @return boolean
+        */
+       public function isPropertyValidationRequired(array $constraints) {
+               $result = TRUE;
+               $parsedValidatorConstraintAnnotations = Tx_LwEnetMultipleActionForms_Utility_AnnotationParser::parseAnnotations(
+                       $constraints
+               );
+
+               $propertyValidationActionIndex = NULL;
+               foreach ($parsedValidatorConstraintAnnotations as $parsedAnnotation) {
+                       if (class_exists($parsedAnnotation['className'])) {
+                               $controllerObject = $this->objectManager->get($this->getRequest()->getControllerObjectName());
+                               if ($controllerObject instanceof $parsedAnnotation['className']) {
+                                       if (!isset($parsedAnnotation['options']['actionIndex'])) {
+                                               $propertyValidationActionIndex = $this->getActionIndexByActionName(
+                                                       $parsedAnnotation['options']['actionName']
+                                               );
+                                       } else {
+                                               $propertyValidationActionIndex = (int)$parsedAnnotation['options']['actionIndex'];
+                                       }
+                                       break 1;
+                               }
+                       }
+               }
+
+               /**
+                * If property validation index is null, set to second action index.
+                * so the @dontvalidate annotation is redundant in the first action
+                */
+               if (is_null($propertyValidationActionIndex)) {
+                       $propertyValidationActionIndex = 1;
+               }
+
+               /**
+                * Check if action before property validation action is omitted,
+                * if true no validation is required for this validation action
+                */
+               $isActionBeforePropertyValidationActionOmitted = array_key_exists(
+                       $propertyValidationActionIndex - 1,
+                       $this->getOmittedActions()
+               );
+
+               /**
+                * If current action is before property validation action in action sequence,
+                * no validation is required
+                * although if $isActionBeforePropertyValidationActionOmitted is TRUE no validation is required
+                */
+               if ($this->getCurrentAction()->getIndex() < $propertyValidationActionIndex || $isActionBeforePropertyValidationActionOmitted === TRUE) {
+                       $result = FALSE;
+               }
+               return $result;
+       }
+}
+?>
\ No newline at end of file
diff --git a/Classes/Service/Reflection.php b/Classes/Service/Reflection.php
new file mode 100644 (file)
index 0000000..7ae51a1
--- /dev/null
@@ -0,0 +1,73 @@
+<?php
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Helge Funk <helge.funk@e-net.info>
+ *
+ *  All rights reserved
+ *
+ *  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 3 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!
+ ***************************************************************/
+
+
+/**
+ *
+ *
+ * @package lw_enet_multiple_action_forms
+ * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License, version 3 or later
+ *
+ */
+class Tx_LwEnetMultipleActionForms_Service_Reflection {
+
+       /**
+        * @var Tx_Extbase_Reflection_Service
+        */
+       protected $reflectionService;
+
+       /**
+        * Injects the reflection service
+        *
+        * @param Tx_Extbase_Reflection_Service $reflectionService
+        * @return void
+        */
+       public function injectReflectionService(Tx_Extbase_Reflection_Service $reflectionService) {
+               $this->reflectionService = $reflectionService;
+       }
+
+       /**
+        * @param Tx_LwEnetMultipleActionForms_Session_PersistenceInterface $sessionPersistenceObject
+        * @return array
+        */
+       public function getClassPropertiesToPersistInSession(Tx_LwEnetMultipleActionForms_Session_PersistenceInterface $sessionPersistenceObject) {
+               $objectName = get_class($sessionPersistenceObject);
+               $persistentProperties = array();
+               foreach ($this->reflectionService->getClassPropertyNames($objectName) as $propertyName) {
+                       $isPropertyToPersist = $this->reflectionService->isPropertyTaggedWith(
+                               $objectName,
+                               $propertyName,
+                               'sessionPersist'
+                       );
+                       if ($isPropertyToPersist === TRUE) {
+                               $persistentProperties[] = $propertyName;
+                       }
+               }
+               return $persistentProperties;
+       }
+
+}
+?>
\ No newline at end of file
diff --git a/Classes/Session/AdapterInterface.php b/Classes/Session/AdapterInterface.php
new file mode 100644 (file)
index 0000000..a54f936
--- /dev/null
@@ -0,0 +1,58 @@
+<?php
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Helge Funk <helge.funk@e-net.info>
+ *
+ *  All rights reserved
+ *
+ *  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 3 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!
+ ***************************************************************/
+
+
+/**
+ *
+ * @package LwEnetMultipleActionForms
+ * @subpackage Session
+ *
+ */
+interface Tx_LwEnetMultipleActionForms_Session_AdapterInterface {
+
+       const SESSION_PERSISTENCE_INTERFACE = 'Tx_LwEnetMultipleActionForms_Session_PersistenceInterface';
+
+       /**
+        * @abstract
+        * @param $key
+        * @param $data
+        * @return void
+        */
+       public function store($key, $data);
+
+       /**
+        * @abstract
+        * @param mixed $key
+        * @return array
+        */
+       public function load($key = NULL);
+
+       /**
+        * @abstract
+        * @return void
+        */
+       public function clear();
+}
diff --git a/Classes/Session/PersistenceInterface.php b/Classes/Session/PersistenceInterface.php
new file mode 100644 (file)
index 0000000..bb69ad4
--- /dev/null
@@ -0,0 +1,38 @@
+<?php
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Helge Funk <helge.funk@e-net.info>
+ *
+ *  All rights reserved
+ *
+ *  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 3 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!
+ ***************************************************************/
+
+
+/**
+ *
+ *
+ * @package lw_enet_multiple_action_forms
+ * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License, version 3 or later
+ *
+ */
+interface Tx_LwEnetMultipleActionForms_Session_PersistenceInterface {
+
+}
+?>
\ No newline at end of file
diff --git a/Classes/Session/Typo3SessionAdapter.php b/Classes/Session/Typo3SessionAdapter.php
new file mode 100644 (file)
index 0000000..f2e6278
--- /dev/null
@@ -0,0 +1,169 @@
+<?php
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Helge Funk <helge.funk@e-net.info>
+ *
+ *  All rights reserved
+ *
+ *  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 3 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!
+ ***************************************************************/
+
+
+/**
+ *
+ *
+ * @package lw_enet_multiple_action_forms
+ * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License, version 3 or later
+ *
+ */
+class Tx_LwEnetMultipleActionForms_Session_Typo3SessionAdapter implements Tx_LwEnetMultipleActionForms_Session_AdapterInterface {
+
+       /**
+        * @var Tx_Extbase_Object_ObjectManagerInterface
+        */
+       protected $objectManager;
+
+       /**
+        * @var Tx_Extbase_Configuration_ConfigurationManagerInterface
+        */
+       protected $configurationManager;
+
+       /**
+        * @var array
+        */
+       protected $sessionData;
+
+       /**
+        * @var string
+        */
+       protected $sessionKey;
+
+       /**
+        * @var string
+        */
+       protected $sessionContext;
+
+       /**
+        * Injects the object manager
+        *
+        * @param Tx_Extbase_Object_ObjectManagerInterface $objectManager
+        * @return void
+        */
+       public function injectObjectManager(Tx_Extbase_Object_ObjectManagerInterface $objectManager) {
+               $this->objectManager = $objectManager;
+       }
+
+       /**
+        * Injects the configuration manager
+        *
+        * @param Tx_Extbase_Configuration_ConfigurationManagerInterface $configurationManager
+        * @return void
+        */
+       public function injectConfigurationManager(Tx_Extbase_Configuration_ConfigurationManagerInterface $configurationManager) {
+               $this->configurationManager = $configurationManager;
+       }
+
+       /**
+        * initializeObject
+        *
+        * @return void
+        */
+       public function initializeObject() {
+               $frameworkConfiguration = $this->configurationManager->getConfiguration(
+                       Tx_Extbase_Configuration_ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK
+               );
+               if (strlen($frameworkConfiguration['extensionName']) < 1) {
+                       throw new Exception(
+                               'No extension name found',
+                               1323284654
+                       );
+               }
+               $this->sessionKey = $frameworkConfiguration['extensionName'];
+
+               if (TYPO3_MODE === 'BE' || TYPO3_MODE === 'FE') {
+                       $this->sessionContext = TYPO3_MODE;
+               } else {
+                       throw new Exception(
+                               'Not a valid TYPO3 mode set.',
+                               1325707890
+                       );
+               }
+       }
+
+       /**
+        * @param string $sessionKey
+        */
+       public function setSessionKey($sessionKey) {
+               $this->sessionKey = $sessionKey;
+       }
+
+       /**
+        * store
+        *
+        * @param string $key
+        * @param mixed $data
+        * @return void
+        */
+       public function store($key, $data) {
+               $this->sessionData[$key] = $data;
+               if ($this->sessionContext === 'BE') {
+                       $GLOBALS['BE_USER']->setAndSaveSessionData($this->sessionKey, $this->sessionData);
+               } else {
+                       $GLOBALS['TSFE']->fe_user->setKey('ses', $this->sessionKey, $this->sessionData);
+                       $GLOBALS['TSFE']->fe_user->storeSessionData();
+               }
+       }
+
+       /**
+        * load
+        *
+        * @param string $key
+        * @return array $this->sessionData
+        */
+       public function load($key = NULL) {
+               if ($this->sessionContext === 'BE') {
+                       $this->sessionData = $GLOBALS['BE_USER']->getSessionData($this->sessionKey);
+               } else {
+                       $this->sessionData = $GLOBALS['TSFE']->fe_user->getKey('ses', $this->sessionKey);
+               }
+
+               if (!is_null($key)) {
+                       $data = $this->sessionData[$key];
+               } else {
+                       $data = $this->sessionData;
+               }
+               return $data;
+       }
+
+       /**
+        * clear
+        *
+        * @return void
+        */
+       public function clear() {
+               $this->sessionData = array();
+               if ($this->sessionContext === 'BE') {
+                       $GLOBALS['BE_USER']->setAndSaveSessionData($this->sessionKey, $this->sessionData);
+               } else {
+                       $GLOBALS['TSFE']->fe_user->setKey('ses', $this->sessionKey, $this->sessionData);
+                       $GLOBALS['TSFE']->fe_user->storeSessionData();
+               }
+       }
+
+}
diff --git a/Classes/Utility/AnnotationParser.php b/Classes/Utility/AnnotationParser.php
new file mode 100644 (file)
index 0000000..3b1b6de
--- /dev/null
@@ -0,0 +1,175 @@
+<?php
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Helge Funk <helge.funk@e-net.info>
+ *
+ *  All rights reserved
+ *
+ *  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 3 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!
+ ***************************************************************/
+
+
+/**
+ *
+ *
+ * @package lw_enet_multiple_action_forms
+ * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License, version 3 or later
+ *
+ */
+class Tx_LwEnetMultipleActionForms_Utility_AnnotationParser {
+
+       /**
+        * Match validator names and options
+        * @var string
+        */
+       const PATTERN_MATCH_CLASS = '/
+                       (?:^|,\s*)
+                       (?P<className>[a-z0-9_]+)
+                       \s*
+                       (?:\(
+                               (?P<options>(?:\s*[a-z0-9]+\s*=\s*(?:
+                                       "(?:\\\\"|[^"])*"
+                                       |\'(?:\\\\\'|[^\'])*\'
+                                       |(?:\s|[^,"\']*)
+                               )(?:\s|,)*)*)
+                       \))?
+               /ixS';
+
+       /**
+        * Match validator options (to parse actual options)
+        * @var string
+        */
+       const PATTERN_MATCH_OPTIONS = '/
+                       \s*
+                       (?P<optionName>[a-z0-9]+)
+                       \s*=\s*
+                       (?P<optionValue>
+                               "(?:\\\\"|[^"])*"
+                               |\'(?:\\\\\'|[^\'])*\'
+                               |(?:\s|[^,"\']*)
+                       )
+               /ixS';
+
+       /**
+        * Parses the validator options given in @validate annotations.
+        *
+        * @param array $annotations
+        * @return array
+        */
+       public static function parseAnnotations(array $annotations) {
+               $annotationConfigurations = array();
+               foreach ($annotations as $annotation) {
+                       $annotationConfigurations[] = self::parseAnnotation($annotation);
+               }
+               return $annotationConfigurations;
+       }
+
+       /**
+        * Parses the validator options given in @validate annotations.
+        *
+        * @param string $annotation
+        * @return array
+        */
+       public static function parseAnnotation($annotation) {
+               $matches = array();
+               if ($annotation[0] === '$') {
+                       $parts = t3lib_div::trimExplode(' ', $annotation, FALSE, 2);
+                       $annotationConfiguration = array(
+                               'argumentName' => ltrim($parts[0], '$'),
+                       );
+                       if (strpos($parts[1], '->')) {
+                               $parts = t3lib_div::trimExplode('->', $parts[1]);
+                               $classAnnotation = $parts[0];
+                               $annotationConfiguration['validatorAnnotations'] = t3lib_div::trimExplode(',', $parts[1]);
+                       } else {
+                               $classAnnotation = $parts[1];
+                       }
+                       preg_match_all(
+                               self::PATTERN_MATCH_CLASS,
+                               $classAnnotation,
+                               $matches,
+                               PREG_SET_ORDER
+                       );
+               } else {
+                       $annotationConfiguration = array();
+                       preg_match_all(
+                               self::PATTERN_MATCH_CLASS,
+                               $annotation,
+                               $matches,
+                               PREG_SET_ORDER
+                       );
+               }
+
+               foreach ($matches as $match) {
+                       if (isset($match['options'])) {
+                               $annotationConfiguration['options'] = self::parseOptions($match['options']);
+                       }
+                       $annotationConfiguration['className'] = $match['className'];
+               }
+               return $annotationConfiguration;
+       }
+
+       /**
+        * Parses $rawValidatorOptions not containing quoted option values.
+        * $rawValidatorOptions will be an empty string afterwards (pass by ref!).
+        *
+        * @param string &$rawValidatorOptions
+        * @return array An array of optionName/optionValue pairs
+        */
+       protected static function parseOptions($rawOptions) {
+               $options = array();
+               $parsedOptions = array();
+               preg_match_all(
+                       self::PATTERN_MATCH_OPTIONS     ,
+                       $rawOptions,
+                       $options,
+                       PREG_SET_ORDER
+               );
+               foreach ($options as $option) {
+                       $parsedOptions[trim($option['optionName'])] = trim($option['optionValue']);
+               }
+               array_walk(
+                       $parsedOptions,
+                       array('Tx_LwEnetMultipleActionForms_Utility_AnnotationParser', 'unquoteString')
+               );
+               return $parsedOptions;
+       }
+
+       /**
+        * Removes escapings from a given argument string and trims the outermost
+        * quotes.
+        *
+        * This method is meant as a helper for regular expression results.
+        *
+        * @param string &$quotedValue Value to unquote
+        */
+       protected static function unquoteString(&$quotedValue) {
+               switch ($quotedValue[0]) {
+                       case '"':
+                               $quotedValue = str_replace('\"', '"', trim($quotedValue, '"'));
+                       break;
+                       case '\'':
+                               $quotedValue = str_replace('\\\'', '\'', trim($quotedValue, '\''));
+                       break;
+               }
+               $quotedValue = str_replace('\\\\', '\\', $quotedValue);
+       }
+
+}
+?>
\ No newline at end of file
diff --git a/Classes/Utility/Annotations/ConstraintParser.php b/Classes/Utility/Annotations/ConstraintParser.php
new file mode 100644 (file)
index 0000000..0e90f85
--- /dev/null
@@ -0,0 +1,159 @@
+<?php
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Helge Funk <helge.funk@e-net.info>
+ *
+ *  All rights reserved
+ *
+ *  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 3 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!
+ ***************************************************************/
+
+
+/**
+ *
+ * @package LwEnetMultipleActionForms
+ * @subpackage Utility|Annotations
+ *
+ */
+class Tx_LwEnetMultipleActionForms_Utility_Annotations_ConstraintParser {
+
+       /**
+        * Match validator names and options
+        * @var string
+        */
+       const PATTERN_MATCH_CONSTRAINTS = '/
+                       (?:^|,\s*)
+                       (?P<constraintName>[a-z0-9_]+)
+                       \s*
+                       (?:\(
+                               (?P<constraintOptions>(?:\s*[a-z0-9]+\s*=\s*(?:
+                                       "(?:\\\\"|[^"])*"
+                                       |\'(?:\\\\\'|[^\'])*\'
+                                       |(?:\s|[^,"\']*)
+                               )(?:\s|,)*)*)
+                       \))?
+               /ixS';
+
+       /**
+        * Match validator options (to parse actual options)
+        * @var string
+        */
+       const PATTERN_MATCH_CONSTRAINT_OPTIONS = '/
+                       \s*
+                       (?P<optionName>[a-z0-9]+)
+                       \s*=\s*
+                       (?P<optionValue>
+                               "(?:\\\\"|[^"])*"
+                               |\'(?:\\\\\'|[^\'])*\'
+                               |(?:\s|[^,"\']*)
+                       )
+               /ixS';
+
+       /**
+        * Parses the validator options given in @validate annotations.
+        *
+        * @param array $constraintAnnotations
+        * @return array
+        */
+       public static function parseConstraintAnnotations(array $constraintAnnotations) {
+               $constraintConfigurations = array();
+               foreach ($constraintAnnotations as $constraintAnnotation) {
+                       $constraintConfigurations[] = self::parseConstraint($constraintAnnotation);
+               }
+               return $constraintConfigurations;
+       }
+
+       /**
+        * Parses the validator options given in @validate annotations.
+        *
+        * @param string $constraint
+        * @return array
+        */
+       public static function parseConstraint($constraint) {
+               $matches = array();
+               if ($constraint[0] === '$') {
+                       $parts = t3lib_div::trimExplode(' ', $constraint, FALSE, 2);
+                       $constraintConfiguration = array(
+                               'constraintProperty' => ltrim($parts[0], '$'),
+                       );
+                       if (strpos($parts[1], '->')) {
+                               $parts = t3lib_div::trimExplode('->', $parts[1]);
+                               $constraintAnnotation = $parts[0];
+                                       // @todo: create regex to split validators
+                               $validators = t3lib_div::trimExplode('|', $parts[1]);
+                               $parsedValidators = Tx_LwEnetMultipleActionForms_Utility_Annotations_ValidatorParser::parseValidators($validators);
+                               $constraintConfiguration['constraintValidators'] = $parsedValidators;
+                       } else {
+                               $constraintAnnotation = $parts[1];
+                       }
+                       preg_match_all(
+                               self::PATTERN_MATCH_CONSTRAINTS,
+                               $constraintAnnotation,
+                               $matches,
+                               PREG_SET_ORDER
+                       );
+               } else {
+                       $constraintConfiguration = array();
+                       preg_match_all(
+                               self::PATTERN_MATCH_CONSTRAINTS,
+                               $constraint,
+                               $matches,
+                               PREG_SET_ORDER
+                       );
+               }
+
+               $match = array_shift($matches);
+               $constraintConfiguration['constraintName'] = $match['constraintName'];
+               if (isset($match['constraintOptions'])) {
+                       $constraintConfiguration['constraintOptions'] = self::parseConstraintOptions(
+                               $match['constraintOptions']
+                       );
+               }
+
+               return $constraintConfiguration;
+       }
+
+       /**
+        * Parses $rawValidatorOptions not containing quoted option values.
+        * $rawValidatorOptions will be an empty string afterwards (pass by ref!).
+        *
+        * @param string $rawConstraintOptions
+        * @return array An array of optionName/optionValue pairs
+        */
+       protected static function parseConstraintOptions($rawConstraintOptions) {
+               $options = array();
+               $parsedOptions = array();
+               preg_match_all(
+                       self::PATTERN_MATCH_CONSTRAINT_OPTIONS,
+                       $rawConstraintOptions,
+                       $options,
+                       PREG_SET_ORDER
+               );
+               foreach ($options as $option) {
+                       $parsedOptions[trim($option['optionName'])] = trim($option['optionValue']);
+               }
+               array_walk(
+                       $parsedOptions,
+                       array('Tx_LwEnetMultipleActionForms_Utility_String', 'unquoteString')
+               );
+               return $parsedOptions;
+       }
+
+}
+?>
\ No newline at end of file
diff --git a/Classes/Utility/Annotations/ValidatorParser.php b/Classes/Utility/Annotations/ValidatorParser.php
new file mode 100644 (file)
index 0000000..488ade1
--- /dev/null
@@ -0,0 +1,165 @@
+<?php
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Helge Funk <helge.funk@e-net.info>
+ *
+ *  All rights reserved
+ *
+ *  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 3 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!
+ ***************************************************************/
+
+
+/**
+ *
+ * @package LwEnetMultipleActionForms
+ * @subpackage Utility|Annotations
+ *
+ */
+class Tx_LwEnetMultipleActionForms_Utility_Annotations_ValidatorParser {
+
+       /**
+        * Match validator names and options
+        * @var string
+        */
+       const PATTERN_MATCH_VALIDATORS = '/
+                       (?:^|,\s*)
+                       (?P<validatorName>[a-z0-9_]+)
+                       \s*
+                       (?:\(
+                               (?P<validatorOptions>(?:\s*[a-z0-9]+\s*=\s*(?:
+                                       "(?:\\\\"|[^"])*"
+                                       |\'(?:\\\\\'|[^\'])*\'
+                                       |(?:\s|[^,"\']*)
+                               )(?:\s|,)*)*)
+                       \))?
+               /ixS';
+
+       /**
+        * Match validator options (to parse actual options)
+        * @var string
+        */
+       const PATTERN_MATCH_VALIDATOR_OPTIONS = '/
+                       \s*
+                       (?P<optionName>[a-z0-9]+)
+                       \s*=\s*
+                       (?P<optionValue>
+                               "(?:\\\\"|[^"])*"
+                               |\'(?:\\\\\'|[^\'])*\'
+                               |(?:\s|[^,"\']*)
+                       )
+               /ixS';
+
+       /**
+        * Parses the validator options given in @validate annotations.
+        *
+        * @param array $validatorAnnotations
+        * @return array
+        */
+       public static function parseValidators(array $validatorAnnotations) {
+               $validatorConfigurations = array();
+               foreach ($validatorAnnotations as $validatorAnnotation) {
+                       $validatorConfigurations[] = self::parseValidatorAnnotation($validatorAnnotation);
+               }
+               return $validatorConfigurations;
+       }
+
+       /**
+        * Parses the validator options given in @validate annotations.
+        *
+        * @param string $validateValue
+        * @return array
+        */
+       public static function parseValidatorAnnotation($validateValue) {
+               $matches = array();
+               $validatorConfiguration = array();
+               if ($validateValue[0] === '$') {
+                       $parts = explode(' ', $validateValue, 2);
+                       $validatorConfiguration['argumentName'] = ltrim($parts[0], '$');
+                       preg_match_all(
+                               self::PATTERN_MATCH_VALIDATORS,
+                               $parts[1],
+                               $matches,
+                               PREG_SET_ORDER
+                       );
+               } else {
+                       preg_match_all(
+                               self::PATTERN_MATCH_VALIDATORS,
+                               $validateValue,
+                               $matches,
+                               PREG_SET_ORDER
+                       );
+               }
+               $match = array_shift($matches);
+
+               $validatorConfiguration['validatorName'] = $match['validatorName'];
+               if (isset($match['validatorOptions'])) {
+                       $validatorConfiguration['validatorOptions'] = self::parseValidatorOptions($match['validatorOptions']);
+               }
+
+               return $validatorConfiguration;
+       }
+
+       /**
+        * Parses $rawValidatorOptions not containing quoted option values.
+        * $rawValidatorOptions will be an empty string afterwards (pass by ref!).
+        *
+        * @param string &$rawValidatorOptions
+        * @return array An array of optionName/optionValue pairs
+        */
+       protected static function parseValidatorOptions($rawValidatorOptions) {
+               $validatorOptions = array();
+               $parsedValidatorOptions = array();
+               preg_match_all(
+                       self::PATTERN_MATCH_VALIDATOR_OPTIONS,
+                       $rawValidatorOptions,
+                       $validatorOptions,
+                       PREG_SET_ORDER
+               );
+               foreach ($validatorOptions as $validatorOption) {
+                       $parsedValidatorOptions[trim($validatorOption['optionName'])] = trim($validatorOption['optionValue']);
+               }
+               array_walk(
+                       $parsedValidatorOptions,
+                       array('Tx_LwEnetMultipleActionForms_Utility_Annotations_ValidatorParser', 'unquoteString')
+               );
+               return $parsedValidatorOptions;
+       }
+
+       /**
+        * Removes escapings from a given argument string and trims the outermost
+        * quotes.
+        *
+        * This method is meant as a helper for regular expression results.
+        *
+        * @param string &$quotedValue Value to unquote
+        */
+       protected static function unquoteString(&$quotedValue) {
+               switch ($quotedValue[0]) {
+                       case '"':
+                               $quotedValue = str_replace('\"', '"', trim($quotedValue, '"'));
+                       break;
+                       case '\'':
+                               $quotedValue = str_replace('\\\'', '\'', trim($quotedValue, '\''));
+                       break;
+               }
+               $quotedValue = str_replace('\\\\', '\\', $quotedValue);
+       }
+
+}
+?>
\ No newline at end of file
diff --git a/Classes/Utility/Controller.php b/Classes/Utility/Controller.php
new file mode 100644 (file)
index 0000000..eb4d8ab
--- /dev/null
@@ -0,0 +1,112 @@
+<?php
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Helge Funk <helge.funk@e-net.info>
+ *
+ *  All rights reserved
+ *
+ *  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 3 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!
+ ***************************************************************/
+
+
+/**
+ *
+ *
+ * @package lw_enet_multiple_action_forms
+ * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License, version 3 or later
+ *
+ */
+class Tx_LwEnetMultipleActionForms_Utility_Controller {
+
+       /**
+        * Initializes the autoload mechanism of Extbase. This is supplement to the core autoloader.
+        *
+        * @return void
+        * @see initialize()
+        */
+       protected static function initializeClassLoader() {
+               if (!class_exists('Tx_Extbase_Utility_ClassLoader', FALSE)) {
+                       require(t3lib_extmgm::extPath('extbase') . 'Classes/Utility/ClassLoader.php');
+               }
+               $classLoader = new Tx_Extbase_Utility_ClassLoader();
+               spl_autoload_register(array($classLoader, 'loadClass'));
+               return $classLoader;
+       }
+
+       /**
+        * @static
+        * @param array $controllerClassNames
+        * @return array
+        */
+       public static function getControllerActions($controllerClassNames) {
+               /** @var $classLoader Tx_Extbase_Utility_ClassLoader */
+               $classLoader = self::initializeClassLoader();
+               $classLoader->loadClass('Tx_LwEnetMultipleActionForms_MVC_Controller_AbstractController');
+
+               $actions = array();
+               foreach ($controllerClassNames as $controllerClassName) {
+                       $classLoader->loadClass($controllerClassName);
+                       /** @var $classReflection Tx_Extbase_Reflection_ClassReflection */
+                       $controllerReflection = t3lib_div::makeInstance(
+                               'Tx_Extbase_Reflection_ClassReflection',
+                               $controllerClassName
+                       );
+                       if ($controllerReflection->isTaggedWith('actionSequence')) {
+                                       // Get action sequence from first annotation
+                               $actionSequenceAnnotations = $controllerReflection->getTagValues('actionSequence');
+                               $actionNames = t3lib_div::trimExplode(
+                                       ',',
+                                       array_shift($actionSequenceAnnotations),
+                                       TRUE
+                               );
+
+                               if ($controllerReflection->isTaggedWith('additionalActions')) {
+                                               // Get additional actions from first annotation
+                                       $additionalActionAnnotations = $controllerReflection->getTagValues('additionalActions');
+                                       $additionalActionNames = t3lib_div::trimExplode(
+                                               ',',
+                                               array_shift($additionalActionAnnotations),
+                                               TRUE
+                                       );
+                                       $actionNames = array_merge(
+                                               $actionNames,
+                                               $additionalActionNames
+                                       );
+                               }
+
+                               $actions[$controllerClassName] = implode(',', $actionNames);
+                       }
+               }
+               return $actions;
+       }
+
+       /**
+        * @static
+        * @param array $classes
+        * @return void
+        */
+       protected static function loadClasses(array $classes) {
+               foreach ($classes as $className => $classPath) {
+                       if (!class_exists($className)) {
+                               require_once($classPath);
+                       }
+               }
+       }
+}
+?>
\ No newline at end of file
diff --git a/Classes/Utility/String.php b/Classes/Utility/String.php
new file mode 100644 (file)
index 0000000..920aa94
--- /dev/null
@@ -0,0 +1,57 @@
+<?php
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Helge Funk <helge.funk@e-net.info>
+ *
+ *  All rights reserved
+ *
+ *  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 3 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!
+ ***************************************************************/
+
+
+/**
+ *
+ * @package LwEnetMultipleActionForms
+ * @subpackage Utility
+ *
+ */
+class Tx_LwEnetMultipleActionForms_Utility_String {
+
+       /**
+        * Removes escapings from a given argument string and trims the outermost
+        * quotes.
+        *
+        * This method is meant as a helper for regular expression results.
+        *
+        * @param string &$quotedValue Value to unquote
+        */
+       public static function unquoteString(&$quotedValue) {
+               switch ($quotedValue[0]) {
+                       case '"':
+                               $quotedValue = str_replace('\"', '"', trim($quotedValue, '"'));
+                       break;
+                       case '\'':
+                               $quotedValue = str_replace('\\\'', '\'', trim($quotedValue, '\''));
+                       break;
+               }
+               $quotedValue = str_replace('\\\\', '\\', $quotedValue);
+       }
+
+}
+?>
\ No newline at end of file
diff --git a/Classes/Validation/NestedObjectValidatorResolver.php b/Classes/Validation/NestedObjectValidatorResolver.php
new file mode 100644 (file)
index 0000000..3f627bc
--- /dev/null
@@ -0,0 +1,132 @@
+<?php
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Helge Funk <helge.funk@e-net.info>
+ *
+ *  All rights reserved
+ *
+ *  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 3 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!
+ ***************************************************************/
+
+
+/**
+ *
+ * @package LwEnetMultipleActionForms
+ * @subpackage Validation
+ *
+ */
+class Tx_LwEnetMultipleActionForms_Validation_NestedObjectValidatorResolver extends Tx_Extbase_Validation_ValidatorResolver {
+
+       /**
+        * @var Tx_Extbase_Object_ObjectManagerInterface
+        */
+       protected $objectManager;
+
+       /**
+        * @var Tx_Extbase_Reflection_Service
+        */
+       protected $reflectionService;
+
+       /**
+        * @var Tx_Extbase_Validation_ValidatorResolver
+        */
+       protected $validatorResolver;
+
+       /**
+        * Injects the object manager
+        *
+        * @param Tx_Extbase_Object_ObjectManagerInterface $objectManager A reference to the object manager
+        * @return void
+        */
+       public function injectObjectManager(Tx_Extbase_Object_ObjectManagerInterface $objectManager) {
+               $this->objectManager = $objectManager;
+       }
+
+       /**
+        * Injects the reflection service
+        *
+        * @param Tx_Extbase_Reflection_Service $reflectionService
+        * @return void
+        */
+       public function injectReflectionService(Tx_Extbase_Reflection_Service $reflectionService) {
+               $this->reflectionService = $reflectionService;
+       }
+
+       /**
+        * Injects the validator resolver of Tx_LwEnetMultipleActionForms
+        *
+        * @param Tx_LwEnetMultipleActionForms_Validation_ValidatorResolver $validatorResolver
+        * @return void
+        */
+       public function injectValidatorResolver(Tx_LwEnetMultipleActionForms_Validation_ValidatorResolver $validatorResolver) {
+               $this->validatorResolver = $validatorResolver;
+       }
+
+       /**
+        * @param string $dataType
+        * @param Tx_LwEnetMultipleActionForms_Validation_Validator_GenericObjectValidator $genericValidator
+        * @param string $propertyName
+        * @return Tx_Extbase_Validation_Validator_ValidatorInterface
+        */
+       public function buildNestedObjectsBaseValidators($dataType, Tx_LwEnetMultipleActionForms_Validation_Validator_GenericObjectValidator $genericValidator, $propertyName) {
+                       // Early return if dataType is not an object
+               /** @var $classSchema Tx_Extbase_Reflection_ClassSchema */
+               $classSchema = $this->reflectionService->getClassSchema($dataType);
+               if (is_null($classSchema)) {
+                       return;
+               }
+
+               $propertyInformation = array_merge(
+                       $this->reflectionService->getPropertyTagsValues($dataType, $propertyName),
+                       $classSchema->getProperty($propertyName)
+               );
+
+               $isTraversableObjectType = in_array(
+                       $propertyInformation['type'],
+                       array('array', 'ArrayObject', 'SplObjectStorage', 'Tx_Extbase_Persistence_ObjectStorage')
+               );
+
+                       // @todo: verify if condition for traverable object is correct
+               if ($isTraversableObjectType === TRUE && class_exists($propertyInformation['elementType'])) {
+                               // @todo: Implement traversable object validator
+                       $traversableObjectValidator = $this->validatorResolver->createValidator('TraversableObject');
+                               // redirect the propertyName to the traversable validator
+                       $traversableObjectValidator->setPropertyName($propertyName);
+                       $genericValidator->addPropertyValidator($propertyName, $traversableObjectValidator);
+
+               } elseif (isset($propertyInformation['type']) && class_exists($propertyInformation['type'])) {
+
+                       /**
+                        * Temporary workaround to fix "Fatal error: Maximum function nesting level of '200' reached, aborting!"
+                        * in Tx_LwEnetMultipleActionForms_Validation_NestedObjectValidatorResolver->buildNestedObjectsBaseValidators( )
+                        * @todo: investigate validation behaviour of broken objects
+                        */
+                       $validationChainBrokenObjects = array(
+                               'Tx_LwSmaLogin_Domain_Model_User',
+                               'Tx_LwSmaLogin_Domain_Model_Address'
+                       );
+                       if (!in_array($propertyInformation['type'], $validationChainBrokenObjects)) {
+                                       // Build base validator conjunction for type
+                               $genericValidator->addPropertyValidator($propertyName, $this->validatorResolver->getBaseValidatorConjunction($propertyInformation['type']));
+                       }
+               }
+       }
+
+}
+
diff --git a/Classes/Validation/Validator/AbstractObjectValidator.php b/Classes/Validation/Validator/AbstractObjectValidator.php
new file mode 100644 (file)
index 0000000..c15da93
--- /dev/null
@@ -0,0 +1,214 @@
+<?php
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Helge Funk <helge.funk@e-net.info>
+ *
+ *  All rights reserved
+ *
+ *  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 3 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!
+ ***************************************************************/
+
+
+/**
+ *
+ * @package LwEnetMultipleActionForms
+ * @subpackage Validation|Validator
+ *
+ */
+abstract class Tx_LwEnetMultipleActionForms_Validation_Validator_AbstractObjectValidator extends Tx_Extbase_Validation_Validator_GenericObjectValidator {
+
+       /**
+        * @var Tx_Extbase_Object_ObjectManagerInterface
+        */
+       protected $objectManager;
+
+       /**
+        * @var Tx_LwEnetMultipleActionForms_Service_ActionSequence
+        */
+       protected $actionSequenceService;
+
+       /**
+        * @var object
+        */
+       protected $object;
+
+       /**
+        * @var Tx_LwEnetMultipleActionForms_Comparison_ConstraintResolver
+        */
+       protected $constraintResolver;
+
+       /**
+        * @var Tx_LwEnetMultipleActionForms_Validation_ValidatorResolver
+        */
+       protected $validatorResolver;
+
+       /**
+        * @var Tx_Extbase_Reflection_Service
+        */
+       protected $reflectionService;
+
+       /**
+        * Injects the object manager
+        *
+        * @param Tx_Extbase_Object_ObjectManagerInterface $objectManager
+        * @return void
+        */
+       public function injectObjectManager(Tx_Extbase_Object_ObjectManagerInterface $objectManager) {
+               $this->objectManager = $objectManager;
+       }
+
+       /**
+        * @param Tx_LwEnetMultipleActionForms_Comparison_ConstraintResolver $constraintResolver
+        */
+       public function injectConstraintResolver(Tx_LwEnetMultipleActionForms_Comparison_ConstraintResolver $constraintResolver) {
+               $this->constraintResolver = $constraintResolver;
+       }
+
+       /**
+        * @param Tx_LwEnetMultipleActionForms_Validation_ValidatorResolver $validatorResolver
+        */
+       public function injectValidatorResolver(Tx_LwEnetMultipleActionForms_Validation_ValidatorResolver $validatorResolver) {
+               $this->validatorResolver = $validatorResolver;
+       }
+
+       /**
+        * Injects the reflection service
+        *
+        * @param Tx_Extbase_Reflection_Service $reflectionService
+        * @return void
+        */
+       public function injectReflectionService(Tx_Extbase_Reflection_Service $reflectionService) {
+               $this->reflectionService = $reflectionService;
+       }
+
+       /**
+        * @throws Exception
+        */
+       protected function initializeActionSequenceService() {
+               /** @var $actionFlowService Tx_LwEnetMultipleActionForms_Service_ActionSequence */
+               $this->actionSequenceService = t3lib_div::makeInstance(
+                       'Tx_LwEnetMultipleActionForms_Service_ActionSequence'
+               );
+       }
+
+       /**
+        * @param string $propertyName
+        * @param array $constraints
+        */
+       protected function buildValidatePropertyConstraintValidators($propertyName, array $constraints) {
+                       /** @var $objectAccess Tx_Extbase_Reflection_ObjectAccess */
+               $objectAccess = $this->objectManager->get('Tx_Extbase_Reflection_ObjectAccess');
+
+               $parsedConstraints = Tx_LwEnetMultipleActionForms_Utility_Annotations_ConstraintParser::parseConstraintAnnotations($constraints);
+               foreach ($parsedConstraints as $parsedConstraint) {
+                       if ($objectAccess->isPropertyGettable($this->object, $parsedConstraint['constraintProperty']) === FALSE) {
+                               throw new Exception(
+                                       'validatePropertyConstraint defined for non accessible property: ' . $parsedConstraint['constraintProperty'],
+                                       1330431613
+                               );
+                       }
+
+                       $constraintPropertyValue = call_user_func(
+                               array($this->object, 'get' . ucfirst($parsedConstraint['constraintProperty']))
+                       );
+
+                               // @todo: add boolean logic to solve complex cases like:
+                               // a property must validate if:
+                               //              prop a is foo AND prop b is bar
+                               //                      OR
+                               //              prop c is foobar AND prop b is bar
+                               // We have this case with serialnumber, that must only validate if
+                               // type is not "customer care" and context is public,
+                               // OR
+                               // type is not "customer care" and conetx ist authenticated
+                               // for now we solved this by adding the otherwise mising serialnumber
+                               // property as hidden field
+                       $constraint = $this->createConstraint($parsedConstraint);
+                       $constraintIsComplied = $constraint->isComplied($constraintPropertyValue);
+
+                       if ($constraintIsComplied === TRUE && is_array($parsedConstraint['constraintValidators'])) {
+                               foreach ($parsedConstraint['constraintValidators'] as $validatorConfiguration) {
+                                       $validator = $this->createValidator($validatorConfiguration);
+                                       $this->addPropertyValidator($propertyName, $validator);
+                               }
+                       }
+               }
+       }
+
+       /**
+        * @param array $constraintConfiguration
+        * @return Tx_LwEnetMultipleActionForms_Comparison_Constraint_ConstraintInterface
+        */
+       protected function createConstraint(array $constraintConfiguration) {
+               if (is_array($constraintConfiguration['constraintOptions'])) {
+                       /** @var $constraint Tx_LwEnetMultipleActionForms_Comparison_Constraint_ConstraintInterface */
+                       $constraint = $this->constraintResolver->createConstraint(
+                               $constraintConfiguration['constraintName'],
+                               $constraintConfiguration['constraintOptions']
+                       );
+               } else {
+                       /** @var $constraint Tx_LwEnetMultipleActionForms_Comparison_Constraint_ConstraintInterface */
+                       $constraint = $this->constraintResolver->createConstraint(
+                               $constraintConfiguration['constraintName']
+                       );
+               }
+               if (is_null($constraint)) {
+                       throw new Tx_LwEnetMultipleActionForms_Comparison_Exception_NoSuchConstraint(
+                               'Failed to create constraint: ' . $constraintConfiguration['constraintName'],
+                               1323094815
+                       );
+               }
+               return $constraint;
+       }
+
+       /**
+        * @param array $validatorConfiguration
+        * @return Tx_Extbase_Validation_Validator_ValidatorInterface
+        */
+       protected function createValidator(array $validatorConfiguration) {
+               if (is_array($validatorConfiguration['validatorOptions'])) {
+                       /** @var $validator Tx_Extbase_Validation_Validator_ValidatorInterface */
+                       $validator = $this->validatorResolver->createValidator(
+                               $validatorConfiguration['validatorName'],
+                               $validatorConfiguration['validatorOptions']
+                       );
+               } else {
+                       /** @var $validator Tx_Extbase_Validation_Validator_ValidatorInterface */
+                       $validator = $this->validatorResolver->createValidator(
+                               $validatorConfiguration['validatorName']
+                       );
+               }
+               if (is_null($validator)) {
+                       throw new Tx_Extbase_Validation_Exception_NoSuchValidator(
+                               'Failed to create validator: ' . $validatorConfiguration['validatorName'],
+                               1323085308
+                       );
+               }
+               return $validator;
+       }
+
+       /**
+        * @return int
+        */
+       public function getPropertyValidatorCount() {
+               return count($this->propertyValidators);
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/Classes/Validation/Validator/GenericObjectValidator.php b/Classes/Validation/Validator/GenericObjectValidator.php
new file mode 100644 (file)
index 0000000..e31863e
--- /dev/null
@@ -0,0 +1,89 @@
+<?php
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Helge Funk <helge.funk@e-net.info>
+ *
+ *  All rights reserved
+ *
+ *  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 3 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!
+ ***************************************************************/
+
+
+/**
+ *
+ * @package LwEnetMultipleActionForms
+ * @subpackage Validation|Validator
+ *
+ */
+class Tx_LwEnetMultipleActionForms_Validation_Validator_GenericObjectValidator extends Tx_LwEnetMultipleActionForms_Validation_Validator_AbstractObjectValidator {
+
+       /**
+        * Checks if the given value is valid according to the property validators
+        *
+        * If at least one error occurred, the result is FALSE.
+        *
+        * @param mixed $value The value that should be validated
+        * @return boolean TRUE if the value is valid, FALSE if an error occured
+        * @api
+        */
+       public function isValid($value) {
+               if (is_null($value)) {
+                       return TRUE;
+               }
+               if (!is_object($value)) {
+                       $this->addError('Value is no object.', 1324568051);
+                       return FALSE;
+               }
+               $this->object = $value;
+               $objectClassName = get_class($this->object);
+               $this->initializeActionSequenceService();
+
+               foreach ($this->reflectionService->getClassPropertyNames($objectClassName) as $propertyName) {
+                       $propertyTagsValues = $this->reflectionService->getPropertyTagsValues(
+                               get_class($this->object),
+                               $propertyName
+                       );
+
+                       $isPropertyValidationRequired = TRUE;
+                       if (is_array($propertyTagsValues['validateControllerConstraint'])) {
+                               $isPropertyValidationRequired = $this->actionSequenceService->isPropertyValidationRequired(
+                                       $propertyTagsValues['validateControllerConstraint']
+                               );
+                       }
+
+                       if (is_array($propertyTagsValues['validatePropertyConstraint']) &&  $isPropertyValidationRequired === TRUE) {
+                               $this->buildValidatePropertyConstraintValidators(
+                                       $propertyName,
+                                       $propertyTagsValues['validatePropertyConstraint']
+                               );
+                       }
+               }
+
+               $result = TRUE;
+               foreach (array_keys($this->propertyValidators) as $propertyName) {
+                       if ($this->isPropertyValid($this->object, $propertyName) === FALSE) {
+                               $result = FALSE;
+                       }
+               }
+               return $result;
+       }
+
+}
+
+?>
\ No newline at end of file
diff --git a/Classes/Validation/Validator/TraversableObjectValidator.php b/Classes/Validation/Validator/TraversableObjectValidator.php
new file mode 100644 (file)
index 0000000..bf7d96b
--- /dev/null
@@ -0,0 +1,157 @@
+<?php
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Helge Funk <helge.funk@e-net.info>
+ *
+ *  All rights reserved
+ *
+ *  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 3 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!
+ ***************************************************************/
+
+
+/**
+ *
+ * @package LwEnetMultipleActionForms
+ * @subpackage Validation|Validator
+ *
+ */
+class Tx_LwEnetMultipleActionForms_Validation_Validator_TraversableObjectValidator extends Tx_LwEnetMultipleActionForms_Validation_Validator_AbstractObjectValidator {
+
+       /**
+       * @var Tx_LwEnetMultipleActionForms_Validation_ValidatorResolver
+       */
+       protected $validatorResolver;
+
+       /**
+       * property name
+       *
+       * @var string
+       */
+       protected $propertyName;
+
+       /**
+       * Injects the validator resolver
+       *
+       * @param Tx_LwEnetMultipleActionForms_Validation_ValidatorResolver $validatorResolver
+       * @return void
+       */
+       public function injectValidatorResolver(Tx_LwEnetMultipleActionForms_Validation_ValidatorResolver $validatorResolver) {
+               $this->validatorResolver = $validatorResolver;
+       }
+
+       /**
+        * Checks if the given value is valid according to the property validators
+        *
+        * If at least one error occurred, the result is FALSE.
+        *
+        * @param mixed $value The value that should be validated
+        * @return boolean TRUE if the value is valid, FALSE if an error occured
+        * @api
+        */
+       public function isValid($value) {
+               if (!is_object($value)) {
+                       $this->addError('Value is no object.', 1337075085);
+                       return FALSE;
+               }
+               $count = 0;
+
+                       // check if $value is a traversable object and valdidate the subobjects
+               if ($this->isObjectTraversable($value)) {
+                       foreach ($value->toArray() as $index => $element) {
+                               $index++;
+                               $elementClassName = get_class($element);
+
+                               /** @var $validator Tx_Extbase_Validation_Validator_ConjunctionValidator */
+                               $validator = $this->validatorResolver->getBaseValidatorConjunction($elementClassName);
+
+                               if ($validator->isValid($element) === FALSE) {
+                                       $errors = $validator->getErrors();
+                                       $this->addErrorsForProperty($errors, $this->propertyName . '-' . $index);
+                                       $count++;
+                               }
+                       }
+               }
+
+               $result = FALSE;
+               if ($count === 0) {
+                       $result = TRUE;
+               }
+
+               return $result;
+       }
+
+       /**
+       * @param array $errors Array of Tx_Extbase_Validation_Error
+       * @param string $propertyName Name of the property to add errors
+       * @return void
+       */
+       protected function addErrorsForProperty($errors, $propertyName) {
+               if (!isset($this->errors[$propertyName])) {
+                       $this->errors[$propertyName] = new Tx_Extbase_Validation_PropertyError($propertyName);
+               }
+               $this->errors[$propertyName]->addErrors($errors);
+       }
+
+       /**
+        * Method checks if the object that has to be validated is traversable. If the propertyName
+        * and the dataType of the TraversableObjectValidator is not set the method returns FALSE.
+        * Without propertyName and dataType it is not possible to get the property informations.
+        *
+        * If the value of $propertyInformation['type'] is an array, ArrayObject, SplObjectStorage
+        * or a Tx_Extbase_Persistence_ObjectStorage the method returns TRUE, otherwise FALSE.
+        *
+        * @param mixed $object
+        * @return boolean
+        */
+       protected function isObjectTraversable($object) {
+               $result = FALSE;
+
+                       // array with the implemented classes or FALSE
+               $implementedClasses = class_implements($object);
+               if (is_array($implementedClasses)) {
+                       foreach ($implementedClasses as $implementedClass) {
+                               if (is_array($object) || in_array($implementedClass, array('ArrayObject', 'SplObjectStorage', 'Tx_Extbase_Persistence_ObjectStorage', 'Traversable'))) {
+                                       $result = TRUE;
+                                       break;
+                               }
+                       }
+               }
+
+               return $result;
+       }
+
+       /**
+        * Get propertyName
+        *
+        * @return $propertyName
+        */
+       public function getPropertyName() {
+               return $this->propertyName;
+       }
+
+       /**
+        * Set propertyName
+        *
+        * @param string $propertyName
+        */
+       public function setPropertyName($propertyName) {
+               $this->propertyName = $propertyName;
+       }
+}
+?>
\ No newline at end of file
diff --git a/Classes/Validation/ValidatorResolver.php b/Classes/Validation/ValidatorResolver.php
new file mode 100644 (file)
index 0000000..12f981e
--- /dev/null
@@ -0,0 +1,190 @@
+<?php
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2011 Helge Funk <helge.funk@e-net.info>
+ *
+ *  All rights reserved
+ *
+ *  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 3 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!
+ ***************************************************************/
+
+
+/**
+ *
+ * @package LwEnetMultipleActionForms
+ * @subpackage Validation
+ *
+ */
+class Tx_LwEnetMultipleActionForms_Validation_ValidatorResolver extends Tx_Extbase_Validation_ValidatorResolver {
+
+       /**
+        * @var Tx_LwEnetMultipleActionForms_Service_ActionSequence
+        */
+       protected $actionSequenceService;
+
+       /**
+        * Resolves and returns the base validator conjunction for the given data type.
+        *
+        * If no validator could be resolved (which usually means that no validation is necessary),
+        * NULL is returned.
+        *
+        * @param string $dataType The data type to search a validator for. Usually the fully qualified object name
+        * @return Tx_Extbase_Validation_Validator_ConjunctionValidator The validator conjunction or NULL
+        */
+       public function getBaseValidatorConjunction($dataType) {
+               $this->actionSequenceService = t3lib_div::makeInstance(
+                       'Tx_LwEnetMultipleActionForms_Service_ActionSequence'
+               );
+               $isActionSequenceController = FALSE;
+               if ($this->actionSequenceService->getRequest() instanceof Tx_Extbase_MVC_RequestInterface) {
+                       $isActionSequenceController = in_array(
+                               'Tx_LwEnetMultipleActionForms_MVC_Controller_AbstractController',
+                               class_parents(
+                                       $this->actionSequenceService->getRequest()->getControllerObjectName()
+                               )
+                       );
+               }
+               if ($isActionSequenceController === TRUE) {
+                       $this->baseValidatorConjunctions[$dataType] = $this->buildBaseValidatorConjunction($dataType);
+               } else {
+                       if (!isset($this->baseValidatorConjunctions[$dataType])) {
+                               $this->baseValidatorConjunctions[$dataType] = parent::buildBaseValidatorConjunction($dataType);
+                       }
+               }
+               return $this->baseValidatorConjunctions[$dataType];
+       }
+
+       /**
+        * Builds a base validator conjunction for the given data type.
+        *
+        * The base validation rules are those which were declared directly in a class (typically
+        * a model) through some @validate annotations on properties.
+        *
+        * Additionally, if a custom validator was defined for the class in question, it will be added
+        * to the end of the conjunction. A custom validator is found if it follows the naming convention
+        * "Replace '\Model\' by '\Validator\' and append "Validator".
+        *
+        * Example: $dataType is F3\Foo\Domain\Model\Quux, then the Validator will be found if it has the
+        * name F3\Foo\Domain\Validator\QuuxValidator
+        *
+        * @param string $dataType The data type to build the validation conjunction for. Needs to be the fully qualified object name.
+        * @return Tx_Extbase_Validation_Validator_ConjunctionValidator The validator conjunction or NULL
+        */
+       protected function buildBaseValidatorConjunction($dataType) {
+
+               /** @var $validatorConjunction Tx_Extbase_Validation_Validator_ConjunctionValidator */
+               $validatorConjunction = $this->objectManager->get('Tx_Extbase_Validation_Validator_ConjunctionValidator');
+
+               // Model based validator
+               if (strstr($dataType, '_') !== FALSE && class_exists($dataType)) {
+                       $validatorCount = 0;
+
+                       /** @var $objectValidator Tx_LwEnetMultipleActionForms_Validation_Validator_GenericObjectValidator */
+                       $objectValidator = $this->createValidator('GenericObject');
+
+                       foreach ($this->reflectionService->getClassPropertyNames($dataType) as $propertyName) {
+                               $classPropertyTagsValues = $this->reflectionService->getPropertyTagsValues($dataType, $propertyName);
+
+                               if (isset($classPropertyTagsValues['validateControllerConstraint'])) {
+                                       $isPropertyValidationRequired = $this->actionSequenceService->isPropertyValidationRequired(
+                                               $classPropertyTagsValues['validateControllerConstraint']
+                                       );
+                                       if ($isPropertyValidationRequired === FALSE) {
+                                               continue;
+                                       }
+                               }
+
+                               /** @var $nestedObjectValidatorResolver Tx_LwEnetMultipleActionForms_Validation_NestedObjectValidatorResolver */
+                               $nestedObjectValidatorResolver = $this->objectManager->get('Tx_LwEnetMultipleActionForms_Validation_NestedObjectValidatorResolver');
+                               $nestedObjectValidatorResolver->buildNestedObjectsBaseValidators($dataType, $objectValidator, $propertyName);
+
+                                       // Add @validate annotation property validators
+                               $this->addPropertyValidators($objectValidator, $propertyName, $classPropertyTagsValues);
+                       }
+                       /**
+                        * Removed validator count check to add property related validators
+                        * in GenericObjectValidator -> @validatePropertyConstraint
+                        */
+                       $validatorConjunction->addValidator($objectValidator);
+               }
+
+               // Custom validator for the class
+               $possibleValidatorClassName = str_replace('_Model_', '_Validator_', $dataType) . 'Validator';
+               $customValidator = $this->createValidator($possibleValidatorClassName);
+               if ($customValidator !== NULL) {
+                       $validatorConjunction->addValidator($customValidator);
+               }
+
+               return $validatorConjunction;
+       }
+
+       /**
+        * Adds all property validators from the property information stack to the given generic validator
+        *
+        * @param Tx_Extbase_Validation_Validator_GenericObjectValidator $genericValidator The generic validator target
+        * @param string $propertyName The name of the property
+        * @param array $propertyInformation The property informations
+        * @return int
+        */
+       protected function addPropertyValidators($genericValidator, $propertyName, $propertyInformation) {
+               if(!isset($propertyInformation['validate'])) {
+                       return;
+               }
+               $validatorCount = 0;
+               foreach($propertyInformation['validate'] as $validateValue) {
+                       $parsedAnnotation = $this->parseValidatorAnnotation($validateValue);
+                       foreach($parsedAnnotation['validators'] as $validatorConfiguration) {
+                               $validator = $this->createValidator($validatorConfiguration['validatorName'], $validatorConfiguration['validatorOptions']);
+                               if($validator === null) {
+                                       continue;
+                               }
+                               $genericValidator->addPropertyValidator($propertyName, $validator);
+                               $validatorCount++;
+                       }
+               }
+               return $validatorCount;
+       }
+
+       /**
+       * Returns an object of an appropriate validator for the given class. In $possibleClassNames
+       * is the class name defined with the Namespace of Tx_LwEnetMultipleActionForms and
+       * of the default Tx_Extbase. If no validator is available FALSE is returned
+       *
+       * @param string $validatorName Either the fully qualified class name of the validator or the short name of a built-in validator
+       * @return string Name of the validator object or FALSE
+       */
+       protected function resolveValidatorObjectName($validatorName) {
+               if (strstr($validatorName, '_') !== FALSE && class_exists($validatorName)) return $validatorName;
+
+               $possibleClassNames = array(
+                       'Tx_LwEnetMultipleActionForms_Validation_Validator_' . $this->unifyDataType($validatorName) . 'Validator',
+                       'Tx_Extbase_Validation_Validator_' . $this->unifyDataType($validatorName) . 'Validator'
+               );
+
+               foreach ($possibleClassNames as $possibleClassName) {
+                       if (class_exists($possibleClassName)) {
+                               return $possibleClassName;
+                       }
+               }
+
+               return FALSE;
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/Configuration/TypoScript/constants.txt b/Configuration/TypoScript/constants.txt
new file mode 100644 (file)
index 0000000..4195b16
--- /dev/null
@@ -0,0 +1,10 @@
+plugin.tx_lwenetmultipleactionforms {
+       view {
+               # cat=plugin.tx_lwenetmultipleactionforms/file; type=string; label=Path to template root (FE)
+               templateRootPath = EXT:lw_enet_multiple_action_forms/Resources/Private/Templates/
+               # cat=plugin.tx_lwenetmultipleactionforms/file; type=string; label=Path to template partials (FE)
+               partialRootPath = EXT:lw_enet_multiple_action_forms/Resources/Private/Partials/
+               # cat=plugin.tx_lwenetmultipleactionforms/file; type=string; label=Path to template layouts (FE)
+               layoutRootPath = EXT:lw_enet_multiple_action_forms/Resources/Private/Layouts/
+       }
+}
\ No newline at end of file
diff --git a/Configuration/TypoScript/setup.txt b/Configuration/TypoScript/setup.txt
new file mode 100644 (file)
index 0000000..244621d
--- /dev/null
@@ -0,0 +1,34 @@
+config.tx_extbase {
+       objects {
+               Tx_LwEnetMultipleActionForms_Session_AdapterInterface {
+                       className = Tx_LwEnetMultipleActionForms_Session_Typo3SessionAdapter
+               }
+               Tx_Extbase_Validation_ValidatorResolver {
+                       className = Tx_LwEnetMultipleActionForms_Validation_ValidatorResolver
+               }
+               Tx_Extbase_Validation_Validator_GenericObjectValidator {
+                       className = Tx_LwEnetMultipleActionForms_Validation_Validator_GenericObjectValidator
+               }
+       }
+       mvc {
+               requestHandlers {
+                       Tx_LwEnetMultipleActionForms_MVC_Web_FrontendRequestHandler = Tx_LwEnetMultipleActionForms_MVC_Web_FrontendRequestHandler
+                       Tx_LwEnetMultipleActionForms_MVC_Web_BackendRequestHandler = Tx_LwEnetMultipleActionForms_MVC_Web_BackendRequestHandler
+               }
+       }
+}
+
+plugin.tx_lwenetmultipleactionforms {
+       view {
+               templateRootPath = {$plugin.tx_lwenetmultipleactionforms.view.templateRootPath}
+               partialRootPath = {$plugin.tx_lwenetmultipleactionforms.view.partialRootPath}
+               layoutRootPath = {$plugin.tx_lwenetmultipleactionforms.view.layoutRootPath}
+       }
+       persistence {
+
+       }
+       settings {
+               persistOnActionBack = 0
+       }
+}
+
diff --git a/Documentation/manual.sxw b/Documentation/manual.sxw
new file mode 100644 (file)
index 0000000..daeef83
Binary files /dev/null and b/Documentation/manual.sxw differ
diff --git a/Resources/Private/.htaccess b/Resources/Private/.htaccess
new file mode 100644 (file)
index 0000000..dfc0272
--- /dev/null
@@ -0,0 +1 @@
+deny  from all
\ No newline at end of file
diff --git a/Resources/Private/Language/locallang.xml b/Resources/Private/Language/locallang.xml
new file mode 100644 (file)
index 0000000..6add511
--- /dev/null
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<T3locallang>
+       <meta type="array">
+               <type>module</type>
+               <description>Language labels for the Multiple Action Forms extension in the FRONTEND</description>
+       </meta>
+       <data type="array">
+               <languageKey index="default" type="array">
+                       <label index="errorAction.sessionError.message">Ihre Sitzung ist abgelaufen. Bitte stellen Sie die Anfrage erneut.</label>
+                       <label index="errorAction.sessionError.title">Warnung</label>
+               </languageKey>
+       </data>
+</T3locallang>
\ No newline at end of file
diff --git a/Resources/Private/Language/locallang_db.xml b/Resources/Private/Language/locallang_db.xml
new file mode 100644 (file)
index 0000000..9da8064
--- /dev/null
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<T3locallang>
+       <meta type="array">
+               <type>database</type>
+               <description>Language labels for database tables/fields belonging to extension 'lw_enet_multiple_action_forms'</description>
+       </meta>
+       <data type="array">
+               <languageKey index="default" type="array">
+               </languageKey>
+       </data>
+</T3locallang>
\ No newline at end of file
diff --git a/Resources/Public/JavaScript/LwEnetMultipleActionForms.js b/Resources/Public/JavaScript/LwEnetMultipleActionForms.js
new file mode 100644 (file)
index 0000000..10629f1
--- /dev/null
@@ -0,0 +1,54 @@
+LwEnetMultipleActionForms = {
+       previousActionUrl: null,
+       formName: null,
+
+       getForm: function() {
+               var form = null;
+               try {
+                       if (LwEnetMultipleActionForms.formName === null) {
+                               throw 'formName must be set.'
+                       }
+                       for (i = 0; i < document.forms.length; i++) {
+                               if (document.forms[i].name === LwEnetMultipleActionForms.formName) {
+                                       form = document.forms[i];
+                               }
+                       }
+                       if (form === null) {
+                               throw 'No form with given formName: ' + LwEnetMultipleActionForms.formName + ' found.'
+                       }
+               } catch (error) {
+                       LwEnetMultipleActionForms.showError(error);
+               }
+               return form;
+       },
+
+       triggerFormSubmit: function(element) {
+               try {
+                       if (element.href.length === 0) {
+                               throw 'href must be set.'
+                       }
+                       var form = LwEnetMultipleActionForms.getForm();
+                       form.action = element.href;
+                       form.submit();
+               } catch (error) {
+                       LwEnetMultipleActionForms.showError(error);
+               }
+       },
+
+       setPreviousActionUrl: function () {
+               try {
+                       if (LwEnetMultipleActionForms.previousActionUrl === null) {
+                               throw 'previousActionUrl must be set.'
+                       }
+                       var form = LwEnetMultipleActionForms.getForm();
+                       form.action = LwEnetMultipleActionForms.previousActionUrl;
+               } catch (error) {
+                       LwEnetMultipleActionForms.showError(error);
+               }
+       },
+
+       showError: function(error) {
+               alert(error);
+       }
+};
+
diff --git a/ext_autoload.php b/ext_autoload.php
new file mode 100644 (file)
index 0000000..eea48ff
--- /dev/null
@@ -0,0 +1,7 @@
+<?php
+
+$extensionClassesPath = t3lib_extMgm::extPath('lw_enet_multiple_action_forms') . 'Classes/';
+return array(
+       'tx_enetmultistepforms_utility_plugin' => $extensionClassesPath . 'Utility/Plugin.php',
+);
+?>
\ No newline at end of file
diff --git a/ext_emconf.php b/ext_emconf.php
new file mode 100644 (file)
index 0000000..33aedaf
--- /dev/null
@@ -0,0 +1,45 @@
+<?php
+
+########################################################################
+# Extension Manager/Repository config file for ext: "lw_enet_multiple_action_forms"
+#
+# Auto generated by Extension Builder 2011-11-25
+#
+# Manual updates:
+# Only the data in the array - anything else is removed by next write.
+# "version" and "dependencies" must not be touched!
+########################################################################
+
+$EM_CONF[$_EXTKEY] = array(
+       'title' => 'Multiple Action Forms',
+       'description' => '',
+       'category' => 'Lightwerk',
+       'author' => 'Helge Funk',
+       'author_email' => 'helge.funk@e-net.info',
+       'author_company' => '',
+       'shy' => '',
+       'dependencies' => 'cms,extbase,fluid',
+       'priority' => '',
+       'module' => '',
+       'state' => 'stable',
+       'internal' => '',
+       'uploadfolder' => '0',
+       'createDirs' => '',
+       'modify_tables' => '',
+       'clearCacheOnLoad' => 0,
+       'lockType' => '',
+       'version' => '1.0.0',
+       'constraints' => array(
+               'depends' => array(
+                       'cms' => '',
+                       'extbase' => '',
+                       'fluid' => '',
+               ),
+               'conflicts' => array(
+               ),
+               'suggests' => array(
+               ),
+       ),
+);
+
+?>
\ No newline at end of file
diff --git a/ext_icon.gif b/ext_icon.gif
new file mode 100644 (file)
index 0000000..da48742
Binary files /dev/null and b/ext_icon.gif differ
diff --git a/ext_localconf.php b/ext_localconf.php
new file mode 100644 (file)
index 0000000..b0340b2
--- /dev/null
@@ -0,0 +1,7 @@
+<?php
+if (!defined('TYPO3_MODE')) {
+       die ('Access denied.');
+}
+
+
+?>
\ No newline at end of file
diff --git a/ext_tables.php b/ext_tables.php
new file mode 100644 (file)
index 0000000..f202c6f
--- /dev/null
@@ -0,0 +1,9 @@
+<?php
+if (!defined('TYPO3_MODE')) {
+       die ('Access denied.');
+}
+
+//t3lib_extMgm::addStaticFile($_EXTKEY, 'Configuration/TypoScript', 'Multiple Action Forms');
+//t3lib_extMgm::addStaticFile($_EXTKEY, 'Configuration/TypoScript', 'lw_enet_multiple_action_forms');
+
+?>
\ No newline at end of file