[BUGFIX] FormEngine warning 21/41521/5
authorChristian Kuhn <lolli@schwarzbu.ch>
Thu, 16 Jul 2015 21:37:09 +0000 (23:37 +0200)
committerWouter Wolters <typo3@wouterwolters.nl>
Fri, 17 Jul 2015 11:12:50 +0000 (13:12 +0200)
The patch fixes a todo that was marked as code smell already.
The FormEngine class construct relies on a defined return structure
for child nodes. This must not be violated and may throw all kind
of warnings.
An edge case is fixed, where the InlineRecordContainer is called
by FormEngine ajax inline "extend" or by the InlineControlContainer,
those parents must react differently, so this communcation is now
done with an exception.

Resolves: #68262
Resolves: #67592
Releases: master
Change-Id: I32996e31d27be3d0556b9b68c7291624e0d289d2
Reviewed-on: http://review.typo3.org/41521
Reviewed-by: Susanne Moog <typo3@susannemoog.de>
Tested-by: Susanne Moog <typo3@susannemoog.de>
Reviewed-by: Wouter Wolters <typo3@wouterwolters.nl>
Tested-by: Wouter Wolters <typo3@wouterwolters.nl>
typo3/sysext/backend/Classes/Form/Container/InlineControlContainer.php
typo3/sysext/backend/Classes/Form/Container/InlineRecordContainer.php
typo3/sysext/backend/Classes/Form/Exception/AccessDeniedException.php [new file with mode: 0644]
typo3/sysext/backend/Classes/Form/FormEngine.php

index 87b6994..5485ef8 100644 (file)
@@ -26,6 +26,7 @@ use TYPO3\CMS\Backend\Form\Utility\FormEngineUtility;
 use TYPO3\CMS\Backend\Utility\IconUtility;
 use TYPO3\CMS\Backend\Form\InlineStackProcessor;
 use TYPO3\CMS\Backend\Form\InlineRelatedRecordResolver;
+use TYPO3\CMS\Backend\Form\Exception\AccessDeniedException;
 use TYPO3\CMS\Backend\Form\NodeFactory;
 
 /**
@@ -224,7 +225,13 @@ class InlineControlContainer extends AbstractContainer {
                                $options['renderType'] = 'inlineRecordContainer';
                                /** @var NodeFactory $nodeFactory */
                                $nodeFactory = $this->globalOptions['nodeFactory'];
-                               $childArray = $nodeFactory->create($options)->render();
+                               try {
+                                       // This container may raise an access denied exception, to not kill further processing,
+                                       // just a simple "empty" return is created here to ignore this field.
+                                       $childArray = $nodeFactory->create($options)->render();
+                               } catch (AccessDeniedException $e) {
+                                       $childArray = $this->initializeResultArray();
+                               }
                                $html .= $childArray['html'];
                                $childArray['html'] = '';
                                $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $childArray);
index 87647c5..3bcefbf 100644 (file)
@@ -30,6 +30,7 @@ use TYPO3\CMS\Core\Database\RelationHandler;
 use TYPO3\CMS\Core\Database\DatabaseConnection;
 use TYPO3\CMS\Backend\Form\InlineStackProcessor;
 use TYPO3\CMS\Backend\Form\InlineRelatedRecordResolver;
+use TYPO3\CMS\Backend\Form\Exception\AccessDeniedException;
 use TYPO3\CMS\Backend\Form\NodeFactory;
 
 /**
@@ -105,9 +106,8 @@ class InlineRecordContainer extends AbstractContainer {
                        $record[$foreign_selector] = $this->normalizeUid($record[$foreign_selector]);
                }
                if (!$this->checkAccess(($isNewRecord ? 'new' : 'edit'), $foreign_table, $record['uid'])) {
-                       // @todo: Suddenly returning something different than the usual return array is not a cool thing ...
-                       // @todo: Inline ajax relies on this at the moment, though.
-                       return FALSE;
+                       // This is caught by InlineControlContainer or FormEngine, they need to handle this case differently
+                       throw new AccessDeniedException('Access denied', 1437081986);
                }
                // Get the current naming scheme for DOM name/id attributes:
                $appendFormFieldNames = '[' . $foreign_table . '][' . $record['uid'] . ']';
diff --git a/typo3/sysext/backend/Classes/Form/Exception/AccessDeniedException.php b/typo3/sysext/backend/Classes/Form/Exception/AccessDeniedException.php
new file mode 100644 (file)
index 0000000..b6ca1c1
--- /dev/null
@@ -0,0 +1,24 @@
+<?php
+namespace TYPO3\CMS\Backend\Form\Exception;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use TYPO3\CMS\Backend\Form\Exception;
+
+/**
+ * Access denied form exception for container or elements
+ */
+class AccessDeniedException extends Exception {
+
+}
\ No newline at end of file
index 85daa88..08204e5 100644 (file)
@@ -14,6 +14,7 @@ namespace TYPO3\CMS\Backend\Form;
  * The TYPO3 project - inspiring people to share!
  */
 
+use TYPO3\CMS\Backend\Form\Exception\AccessDeniedException;
 use TYPO3\CMS\Backend\Form\Utility\FormEngineUtility;
 use TYPO3\CMS\Backend\Template\DocumentTemplate;
 use TYPO3\CMS\Backend\Utility\BackendUtility;
@@ -536,9 +537,11 @@ class FormEngine {
                $options['inlineStructure'] = $this->inlineStackProcessor->getStructure();
 
                $options['renderType'] = 'inlineRecordContainer';
-               $childArray = $this->nodeFactory->create($options)->render();
 
-               if ($childArray === FALSE) {
+               try {
+                       // Access to this record my be denied, create an according error message in this case
+                       $childArray = $this->nodeFactory->create($options)->render();
+               } catch (AccessDeniedException $e) {
                        return $this->getErrorMessageForAJAX('Access denied');
                }
 
@@ -657,9 +660,11 @@ class FormEngine {
                $options['inlineStructure'] = $this->inlineStackProcessor->getStructure();
 
                $options['renderType'] = 'inlineRecordContainer';
-               $childArray = $this->nodeFactory->create($options)->render();
 
-               if ($childArray === FALSE) {
+               try {
+                       // Access to this record my be denied, create an according error message in this case
+                       $childArray = $this->nodeFactory->create($options)->render();
+               } catch (AccessDeniedException $e) {
                        return $this->getErrorMessageForAJAX('Access denied');
                }
 
@@ -755,7 +760,13 @@ class FormEngine {
                                $options['inlineStructure'] = $this->inlineStackProcessor->getStructure();
 
                                $options['renderType'] = 'inlineRecordContainer';
-                               $childArray = $this->nodeFactory->create($options)->render();
+                               try {
+                                       // Access to this record my be denied, create an according error message in this case
+                                       $childArray = $this->nodeFactory->create($options)->render();
+                               } catch (AccessDeniedException $e) {
+                                       return $this->getErrorMessageForAJAX('Access denied');
+                               }
+
                                $html .= $childArray['html'];
                                $childArray['html'] = '';