Pimcore\Model\Object\Localizedfield\Dao::save PHP Method

save() public method

public save ( )
    public function save()
    {
        $this->delete(false);
        $object = $this->model->getObject();
        $validLanguages = Tool::getValidLanguages();
        $context = $this->model->getContext();
        if ($context && $context["containerType"] == "fieldcollection") {
            $containerKey = $context["containerKey"];
            $container = Object\Fieldcollection\Definition::getByKey($containerKey);
        } else {
            $container = $this->model->getClass();
        }
        $fieldDefinitions = $container->getFielddefinition("localizedfields")->getFielddefinitions();
        foreach ($validLanguages as $language) {
            $inheritedValues = Object\AbstractObject::doGetInheritedValues();
            Object\AbstractObject::setGetInheritedValues(false);
            $insertData = ["ooo_id" => $this->model->getObject()->getId(), "language" => $language];
            if ($container instanceof Object\Fieldcollection\Definition) {
                $insertData["fieldname"] = $context["fieldname"];
                $insertData["index"] = $context["index"];
            }
            foreach ($fieldDefinitions as $fd) {
                if (method_exists($fd, "save")) {
                    // for fieldtypes which have their own save algorithm eg. objects, multihref, ...
                    $context = $this->model->getContext() ? $this->model->getContext() : [];
                    if ($context["containerType"] == "fieldcollection") {
                        $context["subContainerType"] = "localizedfield";
                    }
                    $childParams = ["context" => $context, "language" => $language];
                    $fd->save($this->model, $childParams);
                } else {
                    if (is_array($fd->getColumnType())) {
                        $insertDataArray = $fd->getDataForResource($this->model->getLocalizedValue($fd->getName(), $language, true), $object);
                        $insertData = array_merge($insertData, $insertDataArray);
                    } else {
                        $insertData[$fd->getName()] = $fd->getDataForResource($this->model->getLocalizedValue($fd->getName(), $language, true), $object);
                    }
                }
            }
            $storeTable = $this->getTableName();
            $queryTable = $this->getQueryTableName() . "_" . $language;
            $this->db->insertOrUpdate($storeTable, $insertData);
            if ($container instanceof Object\ClassDefinition) {
                // query table
                $data = [];
                $data["ooo_id"] = $this->model->getObject()->getId();
                $data["language"] = $language;
                $this->inheritanceHelper = new Object\Concrete\Dao\InheritanceHelper($object->getClassId(), "ooo_id", $storeTable, $queryTable);
                $this->inheritanceHelper->resetFieldsToCheck();
                $sql = "SELECT * FROM " . $queryTable . " WHERE ooo_id = " . $object->getId() . " AND language = '" . $language . "'";
                $oldData = [];
                try {
                    $oldData = $this->db->fetchRow($sql);
                } catch (\Exception $e) {
                    // if the table doesn't exist -> create it!
                    if (strpos($e->getMessage(), "exist")) {
                        // the following is to ensure consistent data and atomic transactions, while having the flexibility
                        // to add new languages on the fly without saving all classes having localized fields
                        // first we need to roll back all modifications, because otherwise they would be implicitly committed
                        // by the following DDL
                        $this->db->rollBack();
                        // this creates the missing table
                        $this->createUpdateTable();
                        // at this point we throw an exception so that the transaction gets repeated in Object::save()
                        throw new \Exception("missing table created, start next run ... ;-)");
                    }
                }
                // get fields which shouldn't be updated
                $untouchable = [];
                // @TODO: currently we do not support lazyloading in localized fields
                $inheritanceEnabled = $object->getClass()->getAllowInherit();
                $parentData = null;
                if ($inheritanceEnabled) {
                    // get the next suitable parent for inheritance
                    $parentForInheritance = $object->getNextParentForInheritance();
                    if ($parentForInheritance) {
                        // we don't use the getter (built in functionality to get inherited values) because we need to avoid race conditions
                        // we cannot Object\AbstractObject::setGetInheritedValues(true); and then $this->model->getLocalizedValue($key, $language)
                        // so we select the data from the parent object using FOR UPDATE, which causes a lock on this row
                        // so the data of the parent cannot be changed while this transaction is on progress
                        $parentData = $this->db->fetchRow("SELECT * FROM " . $queryTable . " WHERE ooo_id = ? AND language = ? FOR UPDATE", [$parentForInheritance->getId(), $language]);
                    }
                }
                foreach ($fieldDefinitions as $fd) {
                    if ($fd->getQueryColumnType()) {
                        $key = $fd->getName();
                        // exclude untouchables if value is not an array - this means data has not been loaded
                        if (!(in_array($key, $untouchable) and !is_array($this->model->{$key}))) {
                            $localizedValue = $this->model->getLocalizedValue($key, $language);
                            $insertData = $fd->getDataForQueryResource($localizedValue, $object);
                            $isEmpty = $fd->isEmpty($localizedValue);
                            if (is_array($insertData)) {
                                $columnNames = array_keys($insertData);
                                $data = array_merge($data, $insertData);
                            } else {
                                $columnNames = [$key];
                                $data[$key] = $insertData;
                            }
                            // if the current value is empty and we have data from the parent, we just use it
                            if ($isEmpty && $parentData) {
                                foreach ($columnNames as $columnName) {
                                    if (array_key_exists($columnName, $parentData)) {
                                        $data[$columnName] = $parentData[$columnName];
                                        if (is_array($insertData)) {
                                            $insertData[$columnName] = $parentData[$columnName];
                                        } else {
                                            $insertData = $parentData[$columnName];
                                        }
                                    }
                                }
                            }
                            if ($inheritanceEnabled && $fd->getFieldType() != "calculatedValue") {
                                //get changed fields for inheritance
                                if ($fd->isRelationType()) {
                                    if (is_array($insertData)) {
                                        $doInsert = false;
                                        foreach ($insertData as $insertDataKey => $insertDataValue) {
                                            if ($isEmpty && $oldData[$insertDataKey] == $parentData[$insertDataKey]) {
                                                // do nothing, ... value is still empty and parent data is equal to current data in query table
                                            } elseif ($oldData[$insertDataKey] != $insertDataValue) {
                                                $doInsert = true;
                                                break;
                                            }
                                        }
                                        if ($doInsert) {
                                            $this->inheritanceHelper->addRelationToCheck($key, $fd, array_keys($insertData));
                                        }
                                    } else {
                                        if ($isEmpty && $oldData[$key] == $parentData[$key]) {
                                            // do nothing, ... value is still empty and parent data is equal to current data in query table
                                        } elseif ($oldData[$key] != $insertData) {
                                            $this->inheritanceHelper->addRelationToCheck($key, $fd);
                                        }
                                    }
                                } else {
                                    if (is_array($insertData)) {
                                        foreach ($insertData as $insertDataKey => $insertDataValue) {
                                            if ($isEmpty && $oldData[$insertDataKey] == $parentData[$insertDataKey]) {
                                                // do nothing, ... value is still empty and parent data is equal to current data in query table
                                            } elseif ($oldData[$insertDataKey] != $insertDataValue) {
                                                $this->inheritanceHelper->addFieldToCheck($insertDataKey, $fd);
                                            }
                                        }
                                    } else {
                                        if ($isEmpty && $oldData[$key] == $parentData[$key]) {
                                            // do nothing, ... value is still empty and parent data is equal to current data in query table
                                        } elseif ($oldData[$key] != $insertData) {
                                            // data changed, do check and update
                                            $this->inheritanceHelper->addFieldToCheck($key, $fd);
                                        }
                                    }
                                }
                            }
                        } else {
                            Logger::debug("Excluding untouchable query value for object [ " . $this->model->getId() . " ]  key [ {$key} ] because it has not been loaded");
                        }
                    }
                }
                $queryTable = $this->getQueryTableName() . "_" . $language;
                $this->db->insertOrUpdate($queryTable, $data);
                if ($inheritanceEnabled) {
                    $this->inheritanceHelper->doUpdate($object->getId(), true);
                }
                $this->inheritanceHelper->resetFieldsToCheck();
            }
            Object\AbstractObject::setGetInheritedValues($inheritedValues);
        }
        // foreach language
    }