[BUGFIX] Additional Identity Properties not set on mapping error 02/30502/6
authorAnja Leichsenring <aleichsenring@ab-softlab.de>
Sun, 1 Jun 2014 08:36:24 +0000 (10:36 +0200)
committerMarkus Klein <klein.t3@reelworx.at>
Mon, 3 Nov 2014 17:59:39 +0000 (18:59 +0100)
When binding Fluid forms to nested objects, Fluid automatically adds
hidden fields with the identifiers of all affected objects so that
the persistence layer can update all objects correctly.

When a form was redisplayed due to property mapping errors, the
identity fields for the nested sub objects were no longer created.

This change fixes this by making sure all identity fields are rendered
recursively also after property mapping errors.

Backport from #29290
Resolves: #59253
Releases: master
Change-Id: Ib4b2a065d967e87aa42bdc889fef3f0b727b748b
Reviewed-on: http://review.typo3.org/30502
Reviewed-by: Stefan Froemken <froemken@gmail.com>
Tested-by: Stefan Froemken <froemken@gmail.com>
Reviewed-by: Markus Klein <klein.t3@reelworx.at>
Tested-by: Markus Klein <klein.t3@reelworx.at>
typo3/sysext/fluid/Classes/ViewHelpers/Form/AbstractFormFieldViewHelper.php
typo3/sysext/fluid/Tests/Unit/ViewHelpers/Form/AbstractFormFieldViewHelperTest.php

index ab2d4c4..19cb9bc 100644 (file)
@@ -65,6 +65,15 @@ abstract class AbstractFormFieldViewHelper extends AbstractFormViewHelper {
        }
 
        /**
+        * Shortcut for retrieving the request from the controller context
+        *
+        * @return \TYPO3\CMS\Extbase\Mvc\Request
+        */
+       protected function getRequest() {
+               return $this->controllerContext->getRequest();
+       }
+
+       /**
         * Get the name of this form element, without prefix.
         *
         * @return string name
@@ -130,7 +139,7 @@ abstract class AbstractFormFieldViewHelper extends AbstractFormViewHelper {
         * @return bool TRUE if a mapping error occurred, FALSE otherwise
         */
        protected function hasMappingErrorOccurred() {
-               return $this->controllerContext->getRequest()->getOriginalRequest() !== NULL;
+               return $this->getRequest()->getOriginalRequest() !== NULL;
        }
 
        /**
@@ -152,21 +161,25 @@ abstract class AbstractFormFieldViewHelper extends AbstractFormViewHelper {
         * @return void
         */
        protected function addAdditionalIdentityPropertiesIfNeeded() {
+               if (!$this->viewHelperVariableContainer->exists('TYPO3\\CMS\\Fluid\\ViewHelpers\\FormViewHelper', 'formObject')) {
+                       return;
+               }
                $propertySegments = explode('.', $this->arguments['property']);
-               if (count($propertySegments) >= 2) {
-                       // hierarchical property. If there is no "." inside (thus $propertySegments == 1), we do not need to do anything
-                       $formObject = $this->viewHelperVariableContainer->get('TYPO3\\CMS\\Fluid\\ViewHelpers\\FormViewHelper', 'formObject');
-                       $objectName = $this->viewHelperVariableContainer->get('TYPO3\\CMS\\Fluid\\ViewHelpers\\FormViewHelper', 'formObjectName');
-                       // If Count == 2 -> we need to go through the for-loop exactly once
-                       for ($i = 1; $i < count($propertySegments); $i++) {
-                               $object = ObjectAccess::getPropertyPath($formObject, implode('.', array_slice($propertySegments, 0, $i)));
-                               $objectName .= '[' . $propertySegments[($i - 1)] . ']';
-                               $hiddenIdentityField = $this->renderHiddenIdentityField($object, $objectName);
-                               // Add the hidden identity field to the ViewHelperVariableContainer
-                               $additionalIdentityProperties = $this->viewHelperVariableContainer->get('TYPO3\\CMS\\Fluid\\ViewHelpers\\FormViewHelper', 'additionalIdentityProperties');
-                               $additionalIdentityProperties[$objectName] = $hiddenIdentityField;
-                               $this->viewHelperVariableContainer->addOrUpdate('TYPO3\\CMS\\Fluid\\ViewHelpers\\FormViewHelper', 'additionalIdentityProperties', $additionalIdentityProperties);
-                       }
+               // hierarchical property. If there is no "." inside (thus $propertySegments == 1), we do not need to do anything
+               if (count($propertySegments) < 2) {
+                       return;
+               }
+               $formObject = $this->viewHelperVariableContainer->get('TYPO3\\CMS\\Fluid\\ViewHelpers\\FormViewHelper', 'formObject');
+               $objectName = $this->viewHelperVariableContainer->get('TYPO3\\CMS\\Fluid\\ViewHelpers\\FormViewHelper', 'formObjectName');
+               // If count == 2 -> we need to go through the for-loop exactly once
+               for ($i = 1; $i < count($propertySegments); $i++) {
+                       $object = ObjectAccess::getPropertyPath($formObject, implode('.', array_slice($propertySegments, 0, $i)));
+                       $objectName .= '[' . $propertySegments[($i - 1)] . ']';
+                       $hiddenIdentityField = $this->renderHiddenIdentityField($object, $objectName);
+                       // Add the hidden identity field to the ViewHelperVariableContainer
+                       $additionalIdentityProperties = $this->viewHelperVariableContainer->get('TYPO3\\CMS\\Fluid\\ViewHelpers\\FormViewHelper', 'additionalIdentityProperties');
+                       $additionalIdentityProperties[$objectName] = $hiddenIdentityField;
+                       $this->viewHelperVariableContainer->addOrUpdate('TYPO3\\CMS\\Fluid\\ViewHelpers\\FormViewHelper', 'additionalIdentityProperties', $additionalIdentityProperties);
                }
        }
 
@@ -228,7 +241,7 @@ abstract class AbstractFormFieldViewHelper extends AbstractFormViewHelper {
                if (!$this->isObjectAccessorMode()) {
                        return new \TYPO3\CMS\Extbase\Error\Result();
                }
-               $originalRequestMappingResults = $this->controllerContext->getRequest()->getOriginalRequestMappingResults();
+               $originalRequestMappingResults = $this->getRequest()->getOriginalRequestMappingResults();
                $formObjectName = $this->viewHelperVariableContainer->get('TYPO3\\CMS\\Fluid\\ViewHelpers\\FormViewHelper', 'formObjectName');
                return $originalRequestMappingResults->forProperty($formObjectName)->forProperty($this->arguments['property']);
        }
@@ -255,4 +268,4 @@ abstract class AbstractFormFieldViewHelper extends AbstractFormViewHelper {
                }
                return '';
        }
-}
+}
\ No newline at end of file
index daefaa2..43b75ef 100644 (file)
@@ -270,8 +270,9 @@ class AbstractFormFieldViewHelperTest extends \TYPO3\CMS\Fluid\Tests\Unit\ViewHe
                $this->injectDependenciesIntoViewHelper($formFieldViewHelper);
                $arguments = array('property' => $property);
                $formFieldViewHelper->_set('arguments', $arguments);
-               $this->viewHelperVariableContainer->expects($this->at(0))->method('get')->with('TYPO3\\CMS\\Fluid\\ViewHelpers\\FormViewHelper', 'formObject')->will($this->returnValue($mockFormObject));
-               $this->viewHelperVariableContainer->expects($this->at(1))->method('get')->with('TYPO3\\CMS\\Fluid\\ViewHelpers\\FormViewHelper', 'formObjectName')->will($this->returnValue($objectName));
+               $this->viewHelperVariableContainer->expects($this->at(0))->method('exists')->with('TYPO3\\CMS\\Fluid\\ViewHelpers\\FormViewHelper', 'formObject')->will($this->returnValue(TRUE));
+               $this->viewHelperVariableContainer->expects($this->at(1))->method('get')->with('TYPO3\\CMS\\Fluid\\ViewHelpers\\FormViewHelper', 'formObject')->will($this->returnValue($mockFormObject));
+               $this->viewHelperVariableContainer->expects($this->at(2))->method('get')->with('TYPO3\\CMS\\Fluid\\ViewHelpers\\FormViewHelper', 'formObjectName')->will($this->returnValue($objectName));
 
                $formFieldViewHelper->expects($this->once())->method('renderHiddenIdentityField')->with($mockFormObject, $expectedProperty);
 
@@ -303,8 +304,9 @@ class AbstractFormFieldViewHelperTest extends \TYPO3\CMS\Fluid\Tests\Unit\ViewHe
                $this->injectDependenciesIntoViewHelper($formFieldViewHelper);
                $arguments = array('property' => $property);
                $formFieldViewHelper->_set('arguments', $arguments);
-               $this->viewHelperVariableContainer->expects($this->at(0))->method('get')->with('TYPO3\\CMS\\Fluid\\ViewHelpers\\FormViewHelper', 'formObject')->will($this->returnValue($mockFormObject));
-               $this->viewHelperVariableContainer->expects($this->at(1))->method('get')->with('TYPO3\\CMS\\Fluid\\ViewHelpers\\FormViewHelper', 'formObjectName')->will($this->returnValue($objectName));
+               $this->viewHelperVariableContainer->expects($this->at(0))->method('exists')->with('TYPO3\\CMS\\Fluid\\ViewHelpers\\FormViewHelper', 'formObject')->will($this->returnValue(TRUE));
+               $this->viewHelperVariableContainer->expects($this->at(1))->method('get')->with('TYPO3\\CMS\\Fluid\\ViewHelpers\\FormViewHelper', 'formObject')->will($this->returnValue($mockFormObject));
+               $this->viewHelperVariableContainer->expects($this->at(2))->method('get')->with('TYPO3\\CMS\\Fluid\\ViewHelpers\\FormViewHelper', 'formObjectName')->will($this->returnValue($objectName));
 
                $formFieldViewHelper->expects($this->at(0))->method('renderHiddenIdentityField')->with($mockFormObject, $expectedProperty1);
                $formFieldViewHelper->expects($this->at(1))->method('renderHiddenIdentityField')->with($mockFormObject, $expectedProperty2);