/** * Saves the current object to the database. Determines, whether the current object has to be inserted * or updated to the database. * In case of an update, the objects' updateStateToDb() method is being called (as required by class_model). * In the case of a new object, a blank record is being created. Therefore, all tables returned by class' doc comment * will be filled with a new record (using the same new systemid as the primary key). * The newly created systemid is being set as the current objects' one and can be used in the afterwards * called updateStateToDb() method to reference the correct rows. * * @param string|bool $strPrevId The prev-id of the records, either to be used for the insert or to be used during the update of the record * @return bool * @since 3.3.0 * @throws class_exception * @see interface_model * * @todo move to class_orm_objectupdate completely */ public function updateObjectToDb($strPrevId = false) { $bitCommit = true; /** @var $this class_root|interface_model */ if (!$this instanceof interface_model) { throw new class_exception("current object must implemented interface_model", class_exception::$level_FATALERROR); } if (!$this->getLockManager()->isAccessibleForCurrentUser()) { $objUser = new class_module_user_user($this->getLockManager()->getLockId()); throw new class_exception("current object is locked by user " . $objUser->getStrDisplayName(), class_exception::$level_ERROR); } if (is_object($strPrevId) && $strPrevId instanceof class_root) { $strPrevId = $strPrevId->getSystemid(); } $this->objDB->transactionBegin(); //current systemid given? if not, create a new record. $bitRecordCreated = false; if (!validateSystemid($this->getSystemid())) { $bitRecordCreated = true; if ($strPrevId === false || $strPrevId === "" || $strPrevId === null) { //try to find the current modules-one if (isset($this->arrModule["modul"])) { $strPrevId = class_module_system_module::getModuleByName($this->getArrModule("modul"), true)->getSystemid(); if (!validateSystemid($strPrevId)) { throw new class_exception("automatic determination of module-id failed ", class_exception::$level_FATALERROR); } } else { throw new class_exception("insert with no previd ", class_exception::$level_FATALERROR); } } if (!validateSystemid($strPrevId) && $strPrevId !== "0") { throw new class_exception("insert with erroneous prev-id ", class_exception::$level_FATALERROR); } //create the new systemrecord //store date-bit temporary $bitDates = $this->bitDatesChanges; $this->createSystemRecord($strPrevId, $this->getStrDisplayName()); $this->bitDatesChanges = $bitDates; if (validateSystemid($this->getStrSystemid())) { //Create the foreign records $objAnnotations = new class_reflection($this); $arrTargetTables = $objAnnotations->getAnnotationValuesFromClass("@targetTable"); if (count($arrTargetTables) > 0) { foreach ($arrTargetTables as $strOneConfig) { $arrSingleTable = explode(".", $strOneConfig); $strQuery = "INSERT INTO " . $this->objDB->encloseTableName(_dbprefix_ . $arrSingleTable[0]) . "\n (" . $this->objDB->encloseColumnName($arrSingleTable[1]) . ") VALUES\n (?) "; if (!$this->objDB->_pQuery($strQuery, array($this->getStrSystemid()))) { $bitCommit = false; } } } if (!$this->onInsertToDb()) { $bitCommit = false; } } else { throw new class_exception("creation of systemrecord failed", class_exception::$level_FATALERROR); } //all updates are done, start the "real" update class_carrier::getInstance()->flushCache(class_carrier::INT_CACHE_TYPE_DBQUERIES); } //new prev-id? if ($strPrevId !== false && $this->getSystemid() != $strPrevId && (validateSystemid($strPrevId) || $strPrevId == "0")) { //validate the new prev id - it is not allowed to set a parent-node as a sub-node of its own child if (!$this->isSystemidChildNode($this->getSystemid(), $strPrevId)) { $this->setStrPrevId($strPrevId); } } //new comment? $this->setStrRecordComment($this->getStrDisplayName()); //Keep old and new status here, status changed event is being fired after record is completely updated (so after updateStateToDb()) $intOldStatus = $this->intOldRecordStatus; $intNewStatus = $this->intRecordStatus; //save back to the database $bitCommit = $bitCommit && $this->updateSystemrecord(); //update ourselves to the database if ($bitCommit && !$this->updateStateToDb()) { $bitCommit = false; } //now fire the status changed event if ($intOldStatus != $intNewStatus && $intOldStatus != -1) { class_core_eventdispatcher::getInstance()->notifyGenericListeners(class_system_eventidentifier::EVENT_SYSTEM_STATUSCHANGED, array($this->getSystemid(), $this, $intOldStatus, $intNewStatus)); } if ($bitCommit) { $this->objDB->transactionCommit(); //unlock the record $this->getLockManager()->unlockRecord(); class_logger::getInstance()->addLogRow("updateObjectToDb() succeeded for systemid " . $this->getSystemid() . " (" . $this->getRecordComment() . ")", class_logger::$levelInfo); } else { $this->objDB->transactionRollback(); class_logger::getInstance()->addLogRow("updateObjectToDb() failed for systemid " . $this->getSystemid() . " (" . $this->getRecordComment() . ")", class_logger::$levelWarning); } //call the recordUpdated-Listeners class_core_eventdispatcher::getInstance()->notifyGenericListeners(class_system_eventidentifier::EVENT_SYSTEM_RECORDUPDATED, array($this, $bitRecordCreated)); class_carrier::getInstance()->flushCache(class_carrier::INT_CACHE_TYPE_DBQUERIES); return $bitCommit; }