[BUGFIX] isOnSymetricSide must be set by dataprovider 35/44435/6
authorSebastian Fischer <typo3@evoweb.de>
Sat, 31 Oct 2015 09:52:44 +0000 (10:52 +0100)
committerMorton Jonuschat <m.jonuschat@mojocode.de>
Sat, 31 Oct 2015 17:02:02 +0000 (18:02 +0100)
Add a data provider to set isOnSymetricSide on data aggregation
and change all calculations to use the new flag in result array.

Add parent and topmost parent uid, field and table to result
to replace as many InlineStackProcessor calls as possible.

Resolves: #71193
Releases: master
Change-Id: I8d4ec0b2c855cc42b0d03cb34f0b87f5a08a256a
Reviewed-on: https://review.typo3.org/44435
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
Reviewed-by: Morton Jonuschat <m.jonuschat@mojocode.de>
Tested-by: Morton Jonuschat <m.jonuschat@mojocode.de>
typo3/sysext/backend/Classes/Controller/FormInlineAjaxController.php
typo3/sysext/backend/Classes/Form/Container/InlineRecordContainer.php
typo3/sysext/backend/Classes/Form/Container/SingleFieldContainer.php
typo3/sysext/backend/Classes/Form/Element/AbstractFormElement.php
typo3/sysext/backend/Classes/Form/Element/SelectSingleElement.php
typo3/sysext/backend/Classes/Form/FormDataCompiler.php
typo3/sysext/backend/Classes/Form/FormDataProvider/TcaInline.php
typo3/sysext/backend/Classes/Form/FormDataProvider/TcaInlineIsOnSymmetricSide.php [new file with mode: 0644]
typo3/sysext/backend/Tests/Unit/Form/FormDataProvider/TcaInlineIsOnSymmetricSideTest.php [new file with mode: 0644]
typo3/sysext/core/Configuration/DefaultConfiguration.php

index f685c3f..c31d769 100644 (file)
@@ -486,6 +486,12 @@ class FormInlineAjaxController
     {
         $parentConfig = $parentData['processedTca']['columns'][$parentFieldName]['config'];
         $childTableName = $parentConfig['foreign_table'];
+
+        /** @var InlineStackProcessor $inlineStackProcessor */
+        $inlineStackProcessor = GeneralUtility::makeInstance(InlineStackProcessor::class);
+        $inlineStackProcessor->initializeByGivenStructure($inlineStructure);
+        $inlineTopMostParent = $inlineStackProcessor->getStructureLevel(0);
+
         /** @var TcaDatabaseRecord $formDataGroup */
         $formDataGroup = GeneralUtility::makeInstance(TcaDatabaseRecord::class);
         /** @var FormDataCompiler $formDataCompiler */
@@ -499,6 +505,17 @@ class FormInlineAjaxController
             'inlineFirstPid' => $parentData['inlineFirstPid'],
             'inlineParentConfig' => $parentConfig,
             'isInlineAjaxOpeningContext' => true,
+
+            // values of the current parent element
+            // it is always a string either an id or new...
+            'inlineParentUid' => $parentData['databaseRow']['uid'],
+            'inlineParentTableName' => $parentData['tableName'],
+            'inlineParentFieldName' => $parentFieldName,
+
+             // values of the top most parent element set on first level and not overridden on following levels
+            'inlineTopMostParentUid' => $parentData['inlineTopMostParentUid'] ?: $inlineTopMostParent['uid'],
+            'inlineTopMostParentTableName' => $parentData['inlineTopMostParentTableName'] ?: $inlineTopMostParent['table'],
+            'inlineTopMostParentFieldName' => $parentData['inlineTopMostParentFieldName'] ?: $inlineTopMostParent['field'],
         ];
         // For foreign_selector with useCombination $mainChild is the mm record
         // and $combinationChild is the child-child. For "normal" relations, $mainChild
index 210c2e2..808322e 100644 (file)
@@ -303,9 +303,8 @@ class InlineRecordContainer extends AbstractContainer
         $objectId = $domObjectId . '-' . $foreign_table . '-' . $rec['uid'];
         // We need the returnUrl of the main script when loading the fields via AJAX-call (to correct wizard code, so include it as 3rd parameter)
         // Pre-Processing:
-        $isOnSymmetricSide = RelationHandler::isOnSymmetricSide($parentUid, $config, $rec);
-        $hasForeignLabel = (bool)(!$isOnSymmetricSide && $config['foreign_label']);
-        $hasSymmetricLabel = (bool)$isOnSymmetricSide && $config['symmetric_label'];
+        $hasForeignLabel = (bool)(!$data['isOnSymmetricSide'] && $config['foreign_label']);
+        $hasSymmetricLabel = (bool)$data['isOnSymmetricSide'] && $config['symmetric_label'];
 
         // Get the record title/label for a record:
         // Try using a self-defined user function only for formatted labels
@@ -314,7 +313,7 @@ class InlineRecordContainer extends AbstractContainer
                 'table' => $foreign_table,
                 'row' => $rec,
                 'title' => '',
-                'isOnSymmetricSide' => $isOnSymmetricSide,
+                'isOnSymmetricSide' => $data['isOnSymmetricSide'],
                 'options' => isset($GLOBALS['TCA'][$foreign_table]['ctrl']['formattedLabel_userFunc_options'])
                     ? $GLOBALS['TCA'][$foreign_table]['ctrl']['formattedLabel_userFunc_options']
                     : array(),
@@ -432,8 +431,8 @@ class InlineRecordContainer extends AbstractContainer
         $tcaTableCols = &$GLOBALS['TCA'][$foreign_table]['columns'];
         $isPagesTable = $foreign_table === 'pages';
         $isSysFileReferenceTable = $foreign_table === 'sys_file_reference';
-        $isOnSymmetricSide = RelationHandler::isOnSymmetricSide($parentUid, $config, $rec);
-        $enableManualSorting = $tcaTableCtrl['sortby'] || $config['MM'] || !$isOnSymmetricSide && $config['foreign_sortby'] || $isOnSymmetricSide && $config['symmetric_sortby'];
+        $enableManualSorting = $tcaTableCtrl['sortby'] || $config['MM'] || !$data['isOnSymmetricSide']
+            && $config['foreign_sortby'] || $data['isOnSymmetricSide'] && $config['symmetric_sortby'];
         $nameObject = $this->inlineStackProcessor->getCurrentStructureDomObjectIdPrefix($this->data['inlineFirstPid']);
         $nameObjectFt = $nameObject . '-' . $foreign_table;
         $nameObjectFtId = $nameObjectFt . '-' . $rec['uid'];
index 27e1c22..a875b25 100644 (file)
@@ -486,7 +486,7 @@ class SingleFieldContainer extends AbstractContainer
             // Get the parent record from structure stack
             $level = $inlineStackProcessor->getStructureLevel(-1);
             // If we have symmetric fields, check on which side we are and hide fields, that are set automatically:
-            if (RelationHandler::isOnSymmetricSide($level['uid'], $level['config'], $row)) {
+            if ($this->data['isOnSymmetricSide']) {
                 $searchArray['%OR']['config'][0]['%AND']['%OR']['symmetric_field'] = $fieldName;
                 $searchArray['%OR']['config'][0]['%AND']['%OR']['symmetric_sortby'] = $fieldName;
             } else {
index 94484ff..06854d5 100644 (file)
@@ -564,10 +564,11 @@ abstract class AbstractFormElement extends AbstractNode
                 /** @var InlineStackProcessor $inlineStackProcessor */
                 $inlineStackProcessor = GeneralUtility::makeInstance(InlineStackProcessor::class);
                 $inlineStackProcessor->initializeByGivenStructure($this->data['inlineStructure']);
-                $inlineParent = $inlineStackProcessor->getStructureLevel(-1);
                 $aOnClickInline = '';
-                if (is_array($inlineParent) && $inlineParent['uid']) {
-                    if ($inlineParent['config']['foreign_table'] == $table && $inlineParent['config']['foreign_unique'] == $field) {
+                if ($this->data['isInlineChild'] && $this->data['inlineParentUid']) {
+                    if ($this->data['inlineParentConfig']['foreign_table'] === $table
+                        && $this->data['inlineParentConfig']['foreign_unique'] === $field
+                    ) {
                         $objectPrefix = $inlineStackProcessor->getCurrentStructureDomObjectIdPrefix($this->data['inlineFirstPid']) . '-' . $table;
                         $aOnClickInline = $objectPrefix . '|inline.checkUniqueElement|inline.setUniqueElement';
                         $rOnClickInline = 'inline.revertUnique(' . GeneralUtility::quoteJSvalue($objectPrefix) . ',null,' . GeneralUtility::quoteJSvalue($uid) . ');';
index c394d4f..a9d33a6 100644 (file)
@@ -52,12 +52,13 @@ class SelectSingleElement extends AbstractFormElement
         /** @var InlineStackProcessor $inlineStackProcessor */
         $inlineStackProcessor = GeneralUtility::makeInstance(InlineStackProcessor::class);
         $inlineStackProcessor->initializeByGivenStructure($this->data['inlineStructure']);
-        $inlineParent = $inlineStackProcessor->getStructureLevel(-1);
         $uniqueIds = null;
-        if (is_array($inlineParent) && $inlineParent['uid']) {
+        if ($this->data['isInlineChild'] && $this->data['inlineParentUid']) {
             $inlineObjectName = $inlineStackProcessor->getCurrentStructureDomObjectIdPrefix($this->data['inlineFirstPid']);
             $inlineFormName = $inlineStackProcessor->getCurrentStructureFormPrefix();
-            if ($inlineParent['config']['foreign_table'] == $table && $inlineParent['config']['foreign_unique'] == $field) {
+            if ($this->data['inlineParentConfig']['foreign_table'] === $table
+                && $this->data['inlineParentConfig']['foreign_unique'] === $field
+            ) {
                 $uniqueIds = $this->data['inlineData']['unique'][$inlineObjectName . '-' . $table]['used'];
                 $parameterArray['fieldChangeFunc']['inlineUnique'] = 'inline.updateUnique(this,'
                     . GeneralUtility::quoteJSvalue($inlineObjectName . '-' . $table) . ','
@@ -65,11 +66,13 @@ class SelectSingleElement extends AbstractFormElement
                     . GeneralUtility::quoteJSvalue($row['uid']) . ');';
             }
             // hide uid of parent record for symmetric relations
-            if (
-                $inlineParent['config']['foreign_table'] == $table
-                && ($inlineParent['config']['foreign_field'] == $field || $inlineParent['config']['symmetric_field'] == $field)
+            if ($this->data['inlineParentConfig']['foreign_table'] === $table
+                && (
+                    $this->data['inlineParentConfig']['foreign_field'] === $field
+                    || $this->data['inlineParentConfig']['symmetric_field'] === $field
+                )
             ) {
-                $uniqueIds[] = $inlineParent['uid'];
+                $uniqueIds[] = $this->data['inlineParentUid'];
             }
         }
 
index 01fa832..7438a49 100644 (file)
@@ -207,6 +207,25 @@ class FormDataCompiler
             'isInlineChildExpanded' => false,
             // Flag if the inline is in an ajax context that wants to expand the element
             'isInlineAjaxOpeningContext' => false,
+            // Uid of the direct parent of the inline element. Handled as string since it may be a "NEW123" string
+            'inlineParentUid' => '',
+            // Table name of the direct parent of the inline element
+            'inlineParentTableName' => '',
+            // Field name of the direct parent of the inline element
+            'inlineParentFieldName' => '',
+            // Uid of the top most parent element. Handled as string since it may be a "NEW123" string
+            'inlineTopMostParentUid' => '',
+            // Table name of the top most parent element
+            'inlineTopMostParentTableName' => '',
+            // Field name of the top most parent element
+            'inlineTopMostParentFieldName' => '',
+
+            // If is on symetric side of an inline child parent reference.
+            // symmetric side can be achieved in case of an mm relation to the same table. If record A has a relation
+            // to record B, the symmetric side is set in case that record B gets edited.
+            // Record A (table1) <=> mm <=> Record B (table1)
+            'isOnSymmetricSide' => false,
+
             // Uid of a "child-child" if a new record of an intermediate table is compiled to an existing child. This
             // happens if foreign_selector in parent inline config is set. It will be used by default database row
             // data providers to set this as value for the foreign_selector field on the intermediate table. One use
index 0f3b39a..998680c 100644 (file)
@@ -23,6 +23,7 @@ use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
 use TYPO3\CMS\Core\Database\RelationHandler;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Core\Versioning\VersionState;
+use TYPO3\CMS\Backend\Form\InlineStackProcessor;
 
 /**
  * Resolve and prepare inline data.
@@ -258,6 +259,12 @@ class TcaInline extends AbstractDatabaseRecordProvider implements FormDataProvid
     {
         $parentConfig = $result['processedTca']['columns'][$parentFieldName]['config'];
         $childTableName = $parentConfig['foreign_table'];
+
+        /** @var InlineStackProcessor $inlineStackProcessor */
+        $inlineStackProcessor = GeneralUtility::makeInstance(InlineStackProcessor::class);
+        $inlineStackProcessor->initializeByGivenStructure($result['inlineStructure']);
+        $inlineTopMostParent = $inlineStackProcessor->getStructureLevel(0);
+
         /** @var TcaDatabaseRecord $formDataGroup */
         $formDataGroup = GeneralUtility::makeInstance(TcaDatabaseRecord::class);
         /** @var FormDataCompiler $formDataCompiler */
@@ -271,7 +278,19 @@ class TcaInline extends AbstractDatabaseRecordProvider implements FormDataProvid
             'inlineExpandCollapseStateArray' => $result['inlineExpandCollapseStateArray'],
             'inlineFirstPid' => $result['inlineFirstPid'],
             'inlineParentConfig' => $parentConfig,
+
+            // values of the current parent element
+            // it is always a string either an id or new...
+            'inlineParentUid' => $result['databaseRow']['uid'],
+            'inlineParentTableName' => $result['tableName'],
+            'inlineParentFieldName' => $parentFieldName,
+
+            // values of the top most parent element set on first level and not overridden on following levels
+            'inlineTopMostParentUid' => $result['inlineTopMostParentUid'] ?: $inlineTopMostParent['uid'],
+            'inlineTopMostParentTableName' => $result['inlineTopMostParentTableName'] ?: $inlineTopMostParent['table'],
+            'inlineTopMostParentFieldName' => $result['inlineTopMostParentFieldName'] ?: $inlineTopMostParent['field'],
         ];
+
         // For foreign_selector with useCombination $mainChild is the mm record
         // and $combinationChild is the child-child. For "normal" relations, $mainChild
         // is just the normal child record and $combinationChild is empty.
diff --git a/typo3/sysext/backend/Classes/Form/FormDataProvider/TcaInlineIsOnSymmetricSide.php b/typo3/sysext/backend/Classes/Form/FormDataProvider/TcaInlineIsOnSymmetricSide.php
new file mode 100644 (file)
index 0000000..c5a0075
--- /dev/null
@@ -0,0 +1,47 @@
+<?php
+namespace TYPO3\CMS\Backend\Form\FormDataProvider;
+
+/*
+ * 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\FormDataProviderInterface;
+use TYPO3\CMS\Core\Utility\MathUtility;
+
+/**
+ * Determine the wether the child is on symmetric side or not.
+ *
+ * TCA ctrl fields like label and label_alt are evaluated and their
+ * current values from databaseRow used to create the title.
+ */
+class TcaInlineIsOnSymmetricSide implements FormDataProviderInterface
+{
+    /**
+     * Enrich the processed record information with the resolved title
+     *
+     * @param array $result Incoming result array
+     * @return array Modified array
+     */
+    public function addData(array $result)
+    {
+        if (!$result['isInlineChild']) {
+            return $result;
+        }
+
+        $result['isOnSymmetricSide'] = MathUtility::canBeInterpretedAsInteger($result['databaseRow']['uid'])
+            && $result['inlineParentConfig']['symmetric_field']
+            // non-strict comparison by intention
+            && $result['inlineParentUid'] == $result['databaseRow'][$result['inlineParentConfig']['symmetric_field']][0];
+
+        return $result;
+    }
+}
diff --git a/typo3/sysext/backend/Tests/Unit/Form/FormDataProvider/TcaInlineIsOnSymmetricSideTest.php b/typo3/sysext/backend/Tests/Unit/Form/FormDataProvider/TcaInlineIsOnSymmetricSideTest.php
new file mode 100644 (file)
index 0000000..571ae04
--- /dev/null
@@ -0,0 +1,61 @@
+<?php
+namespace TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider;
+
+/*
+ * 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\FormDataProvider\TcaInlineIsOnSymmetricSide;
+use TYPO3\CMS\Core\Tests\UnitTestCase;
+
+/**
+ * Test case
+ */
+class TcaInlineIsOnSymmetricSideTest extends UnitTestCase
+{
+
+    /**
+     * @var TcaInlineIsOnSymmetricSide
+     */
+    protected $subject;
+
+    /**
+     * Initializes the mock object.
+     */
+    public function setUp()
+    {
+        $this->subject = new TcaInlineIsOnSymmetricSide();
+    }
+
+    /**
+     * @test
+     */
+    public function addDataSetsIsOnSymmetricSideToTrue()
+    {
+        $input = [
+            'databaseRow' => [
+                'uid' => 5,
+                'theSymmetricField' => [
+                    23,
+                ],
+            ],
+            'isInlineChild' => true,
+            'inlineParentUid' => 23,
+            'inlineParentConfig' => [
+                'symmetric_field' => 'theSymmetricField',
+            ],
+        ];
+        $expected = $input;
+        $expected['isOnSymmetricSide'] = true;
+        $this->assertEquals($expected, $this->subject->addData($input));
+    }
+}
index 2b6a6b7..ee8f197 100644 (file)
@@ -513,9 +513,15 @@ return array(
                             \TYPO3\CMS\Backend\Form\FormDataProvider\TcaInlineConfiguration::class,
                         ),
                     ),
+                    \TYPO3\CMS\Backend\Form\FormDataProvider\TcaInlineIsOnSymmetricSide::class => array(
+                        'depends' => array(
+                            \TYPO3\CMS\Backend\Form\FormDataProvider\TcaInputPlaceholders::class,
+                        ),
+                    ),
                     \TYPO3\CMS\Backend\Form\FormDataProvider\TcaRecordTitle::class => array(
                         'depends' => array(
                             \TYPO3\CMS\Backend\Form\FormDataProvider\TcaInline::class,
+                            \TYPO3\CMS\Backend\Form\FormDataProvider\TcaInlineIsOnSymmetricSide::class,
                         ),
                     ),
                     \TYPO3\CMS\Backend\Form\FormDataProvider\EvaluateDisplayConditions::class => array(