[BUGFIX] DataHandler: Assign reference default values 50/42550/8
authorMorton Jonuschat <m.jonuschat@mojocode.de>
Wed, 12 Aug 2015 20:55:59 +0000 (22:55 +0200)
committerOliver Hader <oliver.hader@typo3.org>
Wed, 19 Aug 2015 10:06:06 +0000 (12:06 +0200)
In MySQL stric mode scenarios, relation types not using MM tables
or the foreign_field definition (IRRE) might end up in no
references at all, which is only the trigger for the actual
problem. These references result in a blank string ("") that
is casted in non-strict modes to the accordant field type
defined by the DMBS schema.

In strict mode this has to be handled more specific. Since the
system cannot determine the real meaning automatically, values
for reference that are produced in the mentioned scenario are
now casted to zero (0) or to the default value defined in the
accordant TCA configuration of the field.

Resolves: #69004
Releases: master
Change-Id: I6608f1fe0f63a99caa1208b1d3d76354b6f659cf
Reviewed-on: http://review.typo3.org/42550
Reviewed-by: Oliver Hader <oliver.hader@typo3.org>
Tested-by: Oliver Hader <oliver.hader@typo3.org>
30 files changed:
typo3/sysext/core/Classes/DataHandling/DataHandler.php
typo3/sysext/core/Configuration/TCA/sys_category.php
typo3/sysext/core/Configuration/TCA/sys_collection.php
typo3/sysext/core/Configuration/TCA/sys_file_collection.php
typo3/sysext/core/Configuration/TCA/sys_file_metadata.php
typo3/sysext/core/Configuration/TCA/sys_file_reference.php
typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Configuration/TCA/tx_irretutorial_1ncsv_offer.php
typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Configuration/TCA/tx_irretutorial_1ncsv_price.php
typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Configuration/TCA/tx_irretutorial_1nff_hotel.php
typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Configuration/TCA/tx_irretutorial_1nff_offer.php
typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Configuration/TCA/tx_irretutorial_1nff_price.php
typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Configuration/TCA/tx_irretutorial_mnasym_hotel.php
typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Configuration/TCA/tx_irretutorial_mnasym_hotel_offer_rel.php
typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Configuration/TCA/tx_irretutorial_mnasym_offer.php
typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Configuration/TCA/tx_irretutorial_mnasym_price.php
typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Configuration/TCA/tx_irretutorial_mnattr_hotel.php
typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Configuration/TCA/tx_irretutorial_mnattr_hotel_offer_rel.php
typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Configuration/TCA/tx_irretutorial_mnattr_offer.php
typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Configuration/TCA/tx_irretutorial_mnmmasym_hotel.php
typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Configuration/TCA/tx_irretutorial_mnmmasym_offer.php
typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Configuration/TCA/tx_irretutorial_mnmmasym_price.php
typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Configuration/TCA/tx_irretutorial_mnsym_hotel.php
typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Configuration/TCA/tx_irretutorial_mnsym_hotel_rel.php
typo3/sysext/core/Tests/Functional/Fixtures/Extensions/test_datahandler/Configuration/TCA/tx_testdatahandler_element.php
typo3/sysext/core/Tests/Unit/DataHandling/DataHandlerTest.php
typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/blog_example/Configuration/TCA/Blog.php
typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/blog_example/Configuration/TCA/Post.php
typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/blog_example/Configuration/TCA/Tag.php
typo3/sysext/frontend/Configuration/TCA/tt_content.php
typo3/sysext/rtehtmlarea/Configuration/TCA/tx_rtehtmlarea_acronym.php

index e1b755d..99b3c8a 100644 (file)
@@ -2079,7 +2079,7 @@ class DataHandler {
                }
                if (!$unsetResult) {
                        $newVal = $this->checkValue_checkMax($tcaFieldConf, $valueArray);
-                       $res['value'] = implode(',', $newVal);
+                       $res['value'] = $this->castReferenceValue(implode(',', $newVal), $tcaFieldConf);
                } else {
                        unset($res['value']);
                }
@@ -3151,11 +3151,12 @@ class DataHandler {
                                $valueArray = $dbAnalysis->getValueArray();
                                // Checking that the number of items is correct:
                                $valueArray = $this->checkValue_checkMax($tcaFieldConf, $valueArray);
+                               $valueData = $this->castReferenceValue(implode(',', $valueArray), $tcaFieldConf);
                                // If a valid translation of the 'keep' mode is active, update relations in the original(!) record:
                                if ($keepTranslation) {
-                                       $this->updateDB($table, $transOrigPointer, array($field => implode(',', $valueArray)));
+                                       $this->updateDB($table, $transOrigPointer, array($field => $valueData));
                                } else {
-                                       $newValue = implode(',', $valueArray);
+                                       $newValue = $valueData;
                                }
                        }
                }
@@ -5708,6 +5709,9 @@ class DataHandler {
                                // If array is returned, check for maxitems condition, if string is returned this was already done:
                                if (is_array($newValue)) {
                                        $newValue = implode(',', $this->checkValue_checkMax($tcaFieldConf, $newValue));
+                                       // The reference casting is only required if
+                                       // checkValue_group_select_processDBdata() returns an array
+                                       $newValue = $this->castReferenceValue($newValue, $tcaFieldConf);
                                }
                                // Update in database (list of children (csv) or number of relations (foreign_field)):
                                if (!empty($field)) {
@@ -7216,6 +7220,34 @@ class DataHandler {
        }
 
        /**
+        * Casts a reference value. In case MM relations or foreign_field
+        * references are used. All other configurations, as well as
+        * foreign_table(!) could be stored as comma-separated-values
+        * as well. Since the system is not able to determine the default
+        * value automatically then, the TCA default value is used if
+        * it has been defined.
+        *
+        * @param int|string $value The value to be casted (e.g. '', '0', '1,2,3')
+        * @param array $configuration The TCA configuration of the accordant field
+        * @return int|string
+        */
+       protected function castReferenceValue($value, array $configuration) {
+               if ((string)$value !== '') {
+                       return $value;
+               }
+
+               if (!empty($configuration['MM']) || !empty($configuration['foreign_field'])) {
+                       return 0;
+               }
+
+               if (array_key_exists('default', $configuration)) {
+                       return $configuration['default'];
+               }
+
+               return $value;
+       }
+
+       /**
         * Returns TRUE if the TCA/columns field type is a DB reference field
         *
         * @param array $conf Config array for TCA/columns field
index 5869673..e6ad5da 100644 (file)
@@ -61,7 +61,8 @@ return array(
                                'items' => array(
                                        array('LLL:EXT:lang/locallang_general.xlf:LGL.allLanguages', -1),
                                        array('LLL:EXT:lang/locallang_general.xlf:LGL.default_value', 0)
-                               )
+                               ),
+                               'default' => 0
                        )
                ),
                'l10n_parent' => array(
index dc364c9..efaa53a 100644 (file)
@@ -51,7 +51,8 @@ return array(
                                'items' => array(
                                        array('LLL:EXT:lang/locallang_general.xlf:LGL.allLanguages', -1),
                                        array('LLL:EXT:lang/locallang_general.xlf:LGL.default_value', 0)
-                               )
+                               ),
+                               'default' => 0
                        )
                ),
                'l10n_parent' => array(
index 06e04aa..993b8b9 100644 (file)
@@ -50,7 +50,8 @@ return array(
                                'items' => array(
                                        array('LLL:EXT:lang/locallang_general.xlf:LGL.allLanguages', -1),
                                        array('LLL:EXT:lang/locallang_general.xlf:LGL.default_value', 0)
-                               )
+                               ),
+                               'default' => 0
                        )
                ),
                'l10n_parent' => array(
index 38ec78d..b30a36e 100644 (file)
@@ -38,7 +38,8 @@ return array(
                                'items' => array(
                                        array('LLL:EXT:lang/locallang_general.xlf:LGL.allLanguages', -1),
                                        array('LLL:EXT:lang/locallang_general.xlf:LGL.default_value', 0)
-                               )
+                               ),
+                               'default' => 0
                        )
                ),
                'l10n_parent' => array(
index aff10ff..8ea5d65 100644 (file)
@@ -59,7 +59,8 @@ return array(
                                'items' => array(
                                        array('LLL:EXT:lang/locallang_general.xlf:LGL.allLanguages', -1),
                                        array('LLL:EXT:lang/locallang_general.xlf:LGL.default_value', 0)
-                               )
+                               ),
+                               'default' => 0
                        )
                ),
                'l10n_parent' => array(
index 3c88fdf..d4ea23d 100644 (file)
@@ -34,7 +34,8 @@ return array(
                                'items' => array(
                                        array('LLL:EXT:lang/locallang_general.xml:LGL.allLanguages', -1),
                                        array('LLL:EXT:lang/locallang_general.xml:LGL.default_value', 0)
-                               )
+                               ),
+                               'default' => 0
                        )
                ),
                'l18n_parent' => array(
index 2210266..779b699 100644 (file)
@@ -32,7 +32,8 @@ return array(
                                'items' => array(
                                        array('LLL:EXT:lang/locallang_general.xml:LGL.allLanguages', -1),
                                        array('LLL:EXT:lang/locallang_general.xml:LGL.default_value', 0)
-                               )
+                               ),
+                               'default' => 0
                        )
                ),
                'l18n_parent' => array(
index c2b6a77..585e291 100644 (file)
@@ -35,7 +35,8 @@ return array(
                                'items' => array(
                                        array('LLL:EXT:lang/locallang_general.xml:LGL.allLanguages', -1),
                                        array('LLL:EXT:lang/locallang_general.xml:LGL.default_value', 0)
-                               )
+                               ),
+                               'default' => 0
                        )
                ),
                'l18n_parent' => array(
index 825daa7..9b28b45 100644 (file)
@@ -35,7 +35,8 @@ return array(
                                'items' => array(
                                        array('LLL:EXT:lang/locallang_general.xml:LGL.allLanguages', -1),
                                        array('LLL:EXT:lang/locallang_general.xml:LGL.default_value', 0)
-                               )
+                               ),
+                               'default' => 0
                        )
                ),
                'l18n_parent' => array(
index d7ed87a..690980f 100644 (file)
@@ -35,7 +35,8 @@ return array(
                                'items' => array(
                                        array('LLL:EXT:lang/locallang_general.xml:LGL.allLanguages', -1),
                                        array('LLL:EXT:lang/locallang_general.xml:LGL.default_value', 0)
-                               )
+                               ),
+                               'default' => 0
                        )
                ),
                'l18n_parent' => array(
index 3892976..aa0e6f0 100644 (file)
@@ -32,7 +32,8 @@ return array(
                                'items' => array(
                                        array('LLL:EXT:lang/locallang_general.xml:LGL.allLanguages', -1),
                                        array('LLL:EXT:lang/locallang_general.xml:LGL.default_value', 0)
-                               )
+                               ),
+                               'default' => 0
                        )
                ),
                'l18n_parent' => array(
index 2c94ab3..f54567b 100644 (file)
@@ -33,7 +33,8 @@ return array(
                                'items' => array(
                                        array('LLL:EXT:lang/locallang_general.xml:LGL.allLanguages', -1),
                                        array('LLL:EXT:lang/locallang_general.xml:LGL.default_value', 0)
-                               )
+                               ),
+                               'default' => 0
                        )
                ),
                'l18n_parent' => array(
index 8d57a6a..3871904 100644 (file)
@@ -32,7 +32,8 @@ return array(
                                'items' => array(
                                        array('LLL:EXT:lang/locallang_general.xml:LGL.allLanguages', -1),
                                        array('LLL:EXT:lang/locallang_general.xml:LGL.default_value', 0)
-                               )
+                               ),
+                               'default' => 0
                        )
                ),
                'l18n_parent' => array(
index 64e12bf..2543e3c 100644 (file)
@@ -34,7 +34,8 @@ return array(
                                'items' => array(
                                        array('LLL:EXT:lang/locallang_general.xml:LGL.allLanguages', -1),
                                        array('LLL:EXT:lang/locallang_general.xml:LGL.default_value', 0)
-                               )
+                               ),
+                               'default' => 0
                        )
                ),
                'l18n_parent' => array(
index 041b3b5..4a10036 100644 (file)
@@ -32,7 +32,8 @@ return array(
                                'items' => array(
                                        array('LLL:EXT:lang/locallang_general.xml:LGL.allLanguages', -1),
                                        array('LLL:EXT:lang/locallang_general.xml:LGL.default_value', 0)
-                               )
+                               ),
+                               'default' => 0
                        )
                ),
                'l18n_parent' => array(
index 306b803..f8008de 100644 (file)
@@ -33,7 +33,8 @@ return array(
                                'items' => array(
                                        array('LLL:EXT:lang/locallang_general.xml:LGL.allLanguages', -1),
                                        array('LLL:EXT:lang/locallang_general.xml:LGL.default_value', 0)
-                               )
+                               ),
+                               'default' => 0
                        )
                ),
                'l18n_parent' => array(
index 7768542..c6c4451 100644 (file)
@@ -32,7 +32,8 @@ return array(
                                'items' => array(
                                        array('LLL:EXT:lang/locallang_general.xml:LGL.allLanguages', -1),
                                        array('LLL:EXT:lang/locallang_general.xml:LGL.default_value', 0)
-                               )
+                               ),
+                               'default' => 0
                        )
                ),
                'l18n_parent' => array(
index 8af75e6..99da948 100644 (file)
@@ -32,7 +32,8 @@ return array(
                                'items' => array(
                                        array('LLL:EXT:lang/locallang_general.xml:LGL.allLanguages', -1),
                                        array('LLL:EXT:lang/locallang_general.xml:LGL.default_value', 0)
-                               )
+                               ),
+                               'default' => 0
                        )
                ),
                'l18n_parent' => array(
index 5b93c42..15eb607 100644 (file)
@@ -32,7 +32,8 @@ return array(
                                'items' => array(
                                        array('LLL:EXT:lang/locallang_general.xml:LGL.allLanguages', -1),
                                        array('LLL:EXT:lang/locallang_general.xml:LGL.default_value', 0)
-                               )
+                               ),
+                               'default' => 0
                        )
                ),
                'l18n_parent' => array(
index d43a2c8..a849a24 100644 (file)
@@ -32,7 +32,8 @@ return array(
                                'items' => array(
                                        array('LLL:EXT:lang/locallang_general.xml:LGL.allLanguages', -1),
                                        array('LLL:EXT:lang/locallang_general.xml:LGL.default_value', 0)
-                               )
+                               ),
+                               'default' => 0
                        )
                ),
                'l18n_parent' => array(
index 4bfd84e..4f4a57d 100644 (file)
@@ -32,7 +32,8 @@ return array(
                                'items' => array(
                                        array('LLL:EXT:lang/locallang_general.xml:LGL.allLanguages', -1),
                                        array('LLL:EXT:lang/locallang_general.xml:LGL.default_value', 0)
-                               )
+                               ),
+                               'default' => 0
                        )
                ),
                'l18n_parent' => array(
index 2ee1fa8..511ae44 100644 (file)
@@ -33,7 +33,8 @@ return array(
                                'items' => array(
                                        array('LLL:EXT:lang/locallang_general.xml:LGL.allLanguages', -1),
                                        array('LLL:EXT:lang/locallang_general.xml:LGL.default_value', 0)
-                               )
+                               ),
+                               'default' => 0
                        )
                ),
                'l18n_parent' => array(
index 34b8120..2e6f4f4 100644 (file)
@@ -32,7 +32,8 @@ return array(
                                'items' => array(
                                        array('LLL:EXT:lang/locallang_general.xml:LGL.allLanguages', -1),
                                        array('LLL:EXT:lang/locallang_general.xml:LGL.default_value', 0)
-                               )
+                               ),
+                               'default' => 0
                        )
                ),
                'l10n_parent' => array(
index 6630df3..eef7ec2 100644 (file)
@@ -775,4 +775,50 @@ class DataHandlerTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
                $GLOBALS['LANG'] = $previousLanguageService;
        }
 
+       /**
+        * @param mixed $value
+        * @param array $configuration
+        * @param int|string $expected
+        * @test
+        * @dataProvider referenceValuesAreCastedDataProvider
+        */
+       public function referenceValuesAreCasted($value, array $configuration, $expected) {
+               $this->assertEquals(
+                       $expected,
+                       $this->subject->_call('castReferenceValue', $value, $configuration)
+               );
+       }
+
+       /**
+        * @return array
+        */
+       public function referenceValuesAreCastedDataProvider() {
+               return array(
+                       'all empty' => array(
+                               '', array(), ''
+                       ),
+                       'cast zero with MM table' => array(
+                               '', array('MM' => 'table'), 0
+                       ),
+                       'cast zero with MM table with default value' => array(
+                               '', array('MM' => 'table', 'default' => 13), 0
+                       ),
+                       'cast zero with foreign field' => array(
+                               '', array('foreign_field' => 'table', 'default' => 13), 0
+                       ),
+                       'cast zero with foreign field with default value' => array(
+                               '', array('foreign_field' => 'table'), 0
+                       ),
+                       'pass zero' => array(
+                               '0', array(), '0'
+                       ),
+                       'pass value' => array(
+                               '1', array('default' => 13), '1'
+                       ),
+                       'use default value' => array(
+                               '', array('default' => 13), 13
+                       ),
+               );
+       }
+
 }
index 21d82f4..f73bbf8 100644 (file)
@@ -17,7 +17,8 @@ $TCA['tx_blogexample_domain_model_blog'] = array(
                                'items' => Array(
                                        Array('LLL:EXT:lang/locallang_general.php:LGL.allLanguages',-1),
                                        Array('LLL:EXT:lang/locallang_general.php:LGL.default_value',0)
-                               )
+                               ),
+                               'default' => 0
                        )
                ),
                'l18n_parent' => Array (
index 58e85a6..81fdcf0 100644 (file)
@@ -22,7 +22,8 @@ $TCA['tx_blogexample_domain_model_post'] = array(
                                'items' => Array(
                                        Array('LLL:EXT:lang/locallang_general.php:LGL.allLanguages',-1),
                                        Array('LLL:EXT:lang/locallang_general.php:LGL.default_value',0)
-                               )
+                               ),
+                               'default' => 0
                        )
                ),
                'l18n_parent' => Array (
index 0d3097a..f6fdef0 100644 (file)
@@ -17,7 +17,8 @@ $TCA['tx_blogexample_domain_model_tag'] = array(
                                'items' => Array(
                                        Array('LLL:EXT:lang/locallang_general.php:LGL.allLanguages',-1),
                                        Array('LLL:EXT:lang/locallang_general.php:LGL.default_value',0)
-                               )
+                               ),
+                               'default' => 0
                        )
                ),
                'l18n_parent' => Array (
index f96f5d1..6a5afa8 100644 (file)
@@ -229,7 +229,8 @@ return array(
                                                'LLL:EXT:lang/locallang_general.xlf:LGL.default_value',
                                                0
                                        )
-                               )
+                               ),
+                               'default' => 0
                        )
                ),
                'l18n_parent' => array(
index 5303cdc..3aecab6 100644 (file)
@@ -63,7 +63,8 @@ return array(
                                'items' => array(
                                        array('LLL:EXT:lang/locallang_general.xlf:LGL.allLanguages', '-1'),
                                        array('LLL:EXT:lang/locallang_general.xlf:LGL.default_value', '0')
-                               )
+                               ),
+                               'default' => 0
                        )
                ),
                'type' => array(