public function update()
{
parent::update();
// get fields which shouldn't be updated
$fieldDefinitions = $this->model->getClass()->getFieldDefinitions();
$untouchable = [];
foreach ($fieldDefinitions as $key => $fd) {
if (method_exists($fd, "getLazyLoading") && $fd->getLazyLoading()) {
if (!in_array($key, $this->model->getLazyLoadedFields())) {
//this is a relation subject to lazy loading - it has not been loaded
$untouchable[] = $key;
}
}
}
// empty relation table except the untouchable fields (eg. lazy loading fields)
if (count($untouchable) > 0) {
$untouchables = "'" . implode("','", $untouchable) . "'";
$this->db->delete("object_relations_" . $this->model->getClassId(), $this->db->quoteInto("src_id = ? AND fieldname not in (" . $untouchables . ") AND ownertype = 'object'", $this->model->getId()));
} else {
$this->db->delete("object_relations_" . $this->model->getClassId(), $this->db->quoteInto("src_id = ? AND ownertype = 'object'", $this->model->getId()));
}
$inheritedValues = Object\AbstractObject::doGetInheritedValues();
Object\AbstractObject::setGetInheritedValues(false);
$data = [];
$data["oo_id"] = $this->model->getId();
foreach ($fieldDefinitions as $key => $fd) {
$getter = "get" . ucfirst($key);
if (method_exists($fd, "save")) {
// for fieldtypes which have their own save algorithm eg. fieldcollections, objects, multihref, ...
$fd->save($this->model);
} elseif ($fd->getColumnType()) {
// pimcore saves the values with getDataForResource
if (is_array($fd->getColumnType())) {
$insertDataArray = $fd->getDataForResource($this->model->{$getter}(), $this->model);
if (is_array($insertDataArray)) {
$data = array_merge($data, $insertDataArray);
}
} else {
$insertData = $fd->getDataForResource($this->model->{$getter}(), $this->model);
$data[$key] = $insertData;
}
}
}
$this->db->insertOrUpdate("object_store_" . $this->model->getClassId(), $data);
// get data for query table
$data = [];
$this->inheritanceHelper->resetFieldsToCheck();
$oldData = $this->db->fetchRow("SELECT * FROM object_query_" . $this->model->getClassId() . " WHERE oo_id = ?", $this->model->getId());
$inheritanceEnabled = $this->model->getClass()->getAllowInherit();
$parentData = null;
if ($inheritanceEnabled) {
// get the next suitable parent for inheritance
$parentForInheritance = $this->model->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->$method();
// 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 object_query_" . $this->model->getClassId() . " WHERE oo_id = ? FOR UPDATE", $parentForInheritance->getId());
}
}
foreach ($fieldDefinitions as $key => $fd) {
if ($fd->getQueryColumnType()) {
//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}))) {
$method = "get" . $key;
$fieldValue = $this->model->{$method}();
$insertData = $fd->getDataForQueryResource($fieldValue, $this->model);
$isEmpty = $fd->isEmpty($fieldValue);
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");
}
}
}
$data["oo_id"] = $this->model->getId();
$this->db->insertOrUpdate("object_query_" . $this->model->getClassId(), $data);
Object\AbstractObject::setGetInheritedValues($inheritedValues);
}