[BUGFIX] Extbase: Use fully populated records in Backend::insertObject() 56/42656/3
authorMorton Jonuschat <m.jonuschat@mojocode.de>
Sat, 15 Aug 2015 20:05:47 +0000 (22:05 +0200)
committerMarkus Klein <markus.klein@typo3.org>
Mon, 17 Aug 2015 20:28:17 +0000 (22:28 +0200)
To successfully insert new records into a database that does not
silently convert NULL values being inserted into NOT NULL columns (MySQL
in strict mode, PostgreSQL) it is necessary to use a fully
populated record, even if it contains only placeholders for some fields
like relations or reference counters.

Resolves: #69084
Releases: master
Change-Id: I89e79d59ad53666432e73c3b1651323d0d506ac3
Reviewed-on: http://review.typo3.org/42656
Reviewed-by: Stefan Neufeind <typo3.neufeind@speedpartner.de>
Tested-by: Stefan Neufeind <typo3.neufeind@speedpartner.de>
Reviewed-by: Alexander Schnitzler <typo3@alexanderschnitzler.de>
Reviewed-by: Daniel Goerz <ervaude@gmail.com>
Reviewed-by: Markus Klein <markus.klein@typo3.org>
Tested-by: Markus Klein <markus.klein@typo3.org>
typo3/sysext/extbase/Classes/Persistence/Generic/Backend.php

index b3b4956..eb008da 100644 (file)
@@ -15,6 +15,7 @@ namespace TYPO3\CMS\Extbase\Persistence\Generic;
  */
 
 use TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface;
+use TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap;
 use TYPO3\CMS\Extbase\Persistence\ObjectMonitoringInterface;
 
 /**
@@ -640,10 +641,36 @@ class Backend implements \TYPO3\CMS\Extbase\Persistence\Generic\BackendInterface
                }
                $dataMap = $this->dataMapper->getDataMap(get_class($object));
                $row = array();
+               $properties = $object->_getProperties();
+               foreach ($properties as $propertyName => $propertyValue) {
+                       if (!$dataMap->isPersistableProperty($propertyName) || $this->propertyValueIsLazyLoaded($propertyValue)) {
+                               continue;
+                       }
+                       $columnMap = $dataMap->getColumnMap($propertyName);
+                       if ($columnMap->getTypeOfRelation() === ColumnMap::RELATION_HAS_ONE) {
+                               $row[$columnMap->getColumnName()] = 0;
+                       } elseif ($columnMap->getTypeOfRelation() !== ColumnMap::RELATION_NONE) {
+                               if ($columnMap->getParentKeyFieldName() === NULL) {
+                                       // CSV type relation
+                                       $row[$columnMap->getColumnName()] = '';
+                               } else {
+                                       // MM type relation
+                                       $row[$columnMap->getColumnName()] = 0;
+                               }
+                       } else {
+                               // Check explicitly for NULL, as getPlainValue would convert this to 'NULL'
+                               $row[$columnMap->getColumnName()] = $propertyValue !== NULL
+                                       ? $this->dataMapper->getPlainValue($propertyValue)
+                                       : NULL;
+                       }
+               }
                $this->addCommonFieldsToRow($object, $row);
                if ($dataMap->getLanguageIdColumnName() !== NULL) {
                        $row[$dataMap->getLanguageIdColumnName()] = -1;
                }
+               if ($dataMap->getTranslationOriginColumnName() !== NULL) {
+                       $row[$dataMap->getTranslationOriginColumnName()] = 0;
+               }
                if ($parentObject !== NULL && $parentPropertyName) {
                        $parentColumnDataMap = $this->dataMapper->getDataMap(get_class($parentObject))->getColumnMap($parentPropertyName);
                        $relationTableMatchFields = $parentColumnDataMap->getRelationTableMatchFields();