diff --git a/application/cmdbabstract.class.inc.php b/application/cmdbabstract.class.inc.php index ff0967cf6..0602dfd4f 100644 --- a/application/cmdbabstract.class.inc.php +++ b/application/cmdbabstract.class.inc.php @@ -5740,7 +5740,7 @@ JS if ($sClass == 'UserRequest') { IssueLog::Debug("CRUD: DBInsert $sClass::0 About to write in DB", LogChannels::DM_CRUD); } - $this->FireEvent(EVENT_SERVICE_DB_BEFORE_INSERT); + $this->FireEvent(EVENT_SERVICE_DB_ABOUT_TO_INSERT); } /** @@ -5754,7 +5754,7 @@ JS IssueLog::Debug("CRUD: $sClass::{$this->m_iKey} Inserted in DB", LogChannels::DM_CRUD); } - $this->FireEvent(EVENT_SERVICE_DB_AFTER_INSERT); + $this->FireEvent(EVENT_SERVICE_DB_INSERT_DONE); } /** @@ -5805,7 +5805,7 @@ JS $sKey = $sClass.'::'.$this->GetKey(); IssueLog::Debug("CRUD: DBUpdate $sClass::$sKey About to be written in DB", LogChannels::DM_CRUD); } - $this->FireEvent(EVENT_SERVICE_DB_BEFORE_UPDATE); + $this->FireEvent(EVENT_SERVICE_DB_ABOUT_TO_UPDATE); } /** @@ -5821,7 +5821,7 @@ JS $sKey = $sClass.'::'.$this->GetKey(); IssueLog::Debug("CRUD: DBUpdate $sClass::$sKey Updated", LogChannels::DM_CRUD); } - $this->FireEvent(EVENT_SERVICE_DB_AFTER_UPDATE, $aEventData); + $this->FireEvent(EVENT_SERVICE_DB_UPDATE_DONE, $aEventData); } /** @@ -5830,7 +5830,7 @@ JS */ final protected function EventDeleteBefore() { - $this->FireEvent(EVENT_SERVICE_DB_BEFORE_DELETE); + $this->FireEvent(EVENT_SERVICE_DB_ABOUT_TO_DELETE); } /** @@ -5839,7 +5839,7 @@ JS */ final protected function EventDeleteAfter() { - $this->FireEvent(EVENT_SERVICE_DB_AFTER_DELETE); + $this->FireEvent(EVENT_SERVICE_DB_DELETE_DONE); } } diff --git a/application/datamodel.application.xml b/application/datamodel.application.xml index 1fc532c58..25653c760 100644 --- a/application/datamodel.application.xml +++ b/application/datamodel.application.xml @@ -200,7 +200,7 @@ - + An object is about to be inserted in the database (no change possible) DBObject::OnInsert @@ -214,7 +214,7 @@ - + An object has been inserted into the database (but not reloaded). All changes to the object will be persisted automatically. DBObject::AfterInsert @@ -242,7 +242,7 @@ - + An object is about to be updated in the database (no change possible) DBObject::OnUpdate @@ -256,7 +256,7 @@ - + An object has been updated into the database and reloaded. All changes to the object will be persisted automatically. DBObject::AfterUpdate @@ -270,7 +270,7 @@ - + An object is about to be deleted in the database DBObject::OnDelete @@ -284,7 +284,7 @@ - + An object has been deleted into the database DBObject::AfterDelete @@ -302,13 +302,25 @@ A stimulus is about to be applied to an object - The object where the stimulus is to be applied + The object where the stimulus is targeted DBObject Current stimulus applied string + + Object previous state + string + + + Object new state + string + + + The object must be saved in the database + boolean + Debug string string @@ -319,13 +331,58 @@ A stimulus has been applied to an object - The object where the stimulus has been applied + The object where the stimulus is targeted DBObject Current stimulus applied string + + Object previous state + string + + + Object new state + string + + + The object is asked to be saved in the database + boolean + + + Debug string + string + + + + + A stimulus has failed + + + The action that failed to apply the stimulus + string + + + The object where the stimulus is targeted + DBObject + + + Current stimulus applied + string + + + Object previous state + string + + + Object new state + string + + + The object must be saved in the database + boolean + Debug string string diff --git a/core/attributedef.class.inc.php b/core/attributedef.class.inc.php index 2f645eaed..7b0c34c57 100644 --- a/core/attributedef.class.inc.php +++ b/core/attributedef.class.inc.php @@ -6015,7 +6015,9 @@ class AttributeDateTime extends AttributeDBField public function GetDefaultValue(DBObject $oHostObject = null) { - // null value will be replaced by the current date, if not already set, in DoComputeValues + if (!$this->IsNullAllowed()) { + return date($this->GetInternalFormat()); + } return $this->GetNullValue(); } @@ -7805,7 +7807,7 @@ class AttributeBlob extends AttributeDefinition public function GetDefaultValue(DBObject $oHostObject = null) { - return ""; + return new ormDocument('', '', ''); } public function IsNullAllowed(DBObject $oHostObject = null) @@ -11350,6 +11352,13 @@ class AttributeTagSet extends AttributeSet return new ormTagSet(MetaModel::GetAttributeOrigin($this->GetHostClass(), $this->GetCode()), $this->GetCode(), $this->GetMaxItems()); } + public function GetDefaultValue(DBObject $oHostObject = null) + { + $oTagSet = new ormTagSet(MetaModel::GetAttributeOrigin($this->GetHostClass(), $this->GetCode()), $this->GetCode(), $this->GetMaxItems()); + $oTagSet->SetValues([]); + return $oTagSet; + } + public function IsNull($proposedValue) { if (is_null($proposedValue)) diff --git a/core/cmdbobject.class.inc.php b/core/cmdbobject.class.inc.php index c467c8c5c..44a22c865 100644 --- a/core/cmdbobject.class.inc.php +++ b/core/cmdbobject.class.inc.php @@ -491,7 +491,7 @@ abstract class CMDBObject extends DBObject $oMyChangeOp->Set("objkey", $this->GetKey()); $oMyChangeOp->Set("attcode", $sAttCode); $oMyChangeOp->Set("oldvalue", $original); - $oMyChangeOp->Set("newvalue", $value[$sAttCode]); + $oMyChangeOp->Set("newvalue", $value); $iId = $oMyChangeOp->DBInsertNoReload(); } elseif ($oAttDef instanceOf AttributeCustomFields) diff --git a/core/dbobject.class.php b/core/dbobject.class.php index 1b141ae36..90a484b51 100644 --- a/core/dbobject.class.php +++ b/core/dbobject.class.php @@ -1034,13 +1034,11 @@ abstract class DBObject implements iDisplay /** * Compute scalar attributes that depend on any other type of attribute - * - * if you want to customize this behaviour, overwrite @see ComputeValues() * - * @throws \CoreException - * @throws \CoreUnexpectedValue + * if you want to customize this behaviour, overwrite @internal + * + * @see ComputeValues() * - * @internal */ final public function DoComputeValues() { @@ -1055,17 +1053,7 @@ abstract class DBObject implements iDisplay if ($aCallInfo["function"] != "ComputeValues") continue; return; //skip! } - - // Set the "null-not-allowed" datetimes (and dates) whose value is not initialized - foreach(MetaModel::ListAttributeDefs(get_class($this)) as $sAttCode => $oAttDef) - { - // AttributeDate is derived from AttributeDateTime - if (($oAttDef instanceof AttributeDateTime) && (!$oAttDef->IsNullAllowed()) && ($this->Get($sAttCode) == $oAttDef->GetNullValue())) - { - $this->Set($sAttCode, date($oAttDef->GetInternalFormat())); - } - } - + $this->ComputeValues(); } @@ -2255,8 +2243,6 @@ abstract class DBObject implements iDisplay */ public function DoCheckToWrite() { - $this->DoComputeValues(); - $this->DoCheckUniqueness(); $aChanges = $this->ListChanges(); @@ -2323,7 +2309,7 @@ abstract class DBObject implements iDisplay * @throws \OQLException * */ - final public function CheckToWrite() + final public function CheckToWrite($bDoComputeValues = true) { if (MetaModel::SkipCheckToWrite()) { @@ -2334,6 +2320,9 @@ abstract class DBObject implements iDisplay $this->m_aCheckIssues = array(); $oKPI = new ExecutionKPI(); + if ($bDoComputeValues) { + $this->DoComputeValues(); + } $this->DoCheckToWrite(); $this->EventCheckToWrite(['error_messages' => &$this->m_aCheckIssues]); $oKPI->ComputeStats('CheckToWrite', get_class($this)); @@ -2961,7 +2950,7 @@ abstract class DBObject implements iDisplay // Ultimate check - ensure DB integrity $this->SetReadOnly('No modification allowed during CheckToWrite'); - list($bRes, $aIssues) = $this->CheckToWrite(); + list($bRes, $aIssues) = $this->CheckToWrite(false); $this->SetReadWrite(); if (!$bRes) { throw new CoreCannotSaveObjectException(array('issues' => $aIssues, 'class' => get_class($this), 'id' => $this->GetKey())); @@ -2984,7 +2973,7 @@ abstract class DBObject implements iDisplay } } - $this->SetReadOnly('No modification allowed during The Event :'.EVENT_SERVICE_DB_BEFORE_INSERT); + $this->SetReadOnly('No modification allowed during The Event :'.EVENT_SERVICE_DB_ABOUT_TO_INSERT); $this->EventInsertBefore(); $this->SetReadWrite(); @@ -3203,7 +3192,7 @@ abstract class DBObject implements iDisplay // Ultimate check - ensure DB integrity $this->SetReadOnly('No modification allowed during CheckToWrite'); - list($bRes, $aIssues) = $this->CheckToWrite(); + list($bRes, $aIssues) = $this->CheckToWrite(false); $this->SetReadWrite(); if (!$bRes) { @@ -3238,7 +3227,7 @@ abstract class DBObject implements iDisplay $iIsTransactionRetryDelay = MetaModel::GetConfig()->Get('db_core_transactions_retry_delay_ms'); $iTransactionRetry = $iTransactionRetryCount; } - $this->SetReadOnly('No modification allowed during The Event :'.EVENT_SERVICE_DB_BEFORE_UPDATE); + $this->SetReadOnly('No modification allowed during The Event :'.EVENT_SERVICE_DB_ABOUT_TO_UPDATE); $this->EventUpdateBefore(); $this->SetReadWrite(); @@ -3380,6 +3369,10 @@ abstract class DBObject implements iDisplay } } + $this->AfterUpdate(); + + $this->EventUpdateAfter(['changes' => $aChanges]); + // - TriggerOnObjectUpdate $aParams = array('class_list' => MetaModel::EnumParentClasses($sClass, ENUM_PARENT_CLASSES_ALL)); $oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT TriggerOnObjectUpdate AS t WHERE t.target_class IN (:class_list)"), @@ -3398,10 +3391,6 @@ abstract class DBObject implements iDisplay // - TriggerOnObjectMention // Forgotten by the fix of N°3245 $this->ActivateOnMentionTriggers(false); - - $this->AfterUpdate(); - - $this->EventUpdateAfter(['changes' => $aChanges]); } catch (Exception $e) { @@ -3928,18 +3917,25 @@ abstract class DBObject implements iDisplay $aTransitionDef = $aStateTransitions[$sStimulusCode]; - $this->FireEvent(EVENT_SERVICE_DB_BEFORE_APPLY_STIMULUS, ['stimulus' => $sStimulusCode]); - // Change the state before proceeding to the actions, this is necessary because an action might // trigger another stimuli (alternative: push the stimuli into a queue) $sPreviousState = $this->Get($sStateAttCode); $sNewState = $aTransitionDef['target_state']; $this->Set($sStateAttCode, $sNewState); + $aEventData = [ + 'stimulus' => $sStimulusCode, + 'previous_state' => $sPreviousState, + 'new_state' => $sNewState, + 'save_object' => !$bDoNotWrite, + ]; + $this->FireEvent(EVENT_SERVICE_DB_BEFORE_APPLY_STIMULUS, $aEventData); + // $aTransitionDef is an // array('target_state'=>..., 'actions'=>array of handlers procs, 'user_restriction'=>TBD $bSuccess = true; + $sActionDesc = ''; foreach ($aTransitionDef['actions'] as $actionHandler) { if (is_string($actionHandler)) @@ -4048,7 +4044,7 @@ abstract class DBObject implements iDisplay } } - $this->FireEvent(EVENT_SERVICE_DB_AFTER_APPLY_STIMULUS, ['stimulus' => $sStimulusCode]); + $this->FireEvent(EVENT_SERVICE_DB_AFTER_APPLY_STIMULUS, $aEventData); } else { @@ -4057,6 +4053,8 @@ abstract class DBObject implements iDisplay { $this->m_aCurrValues[$sAttCode] = $aBackupValues[$sAttCode]; } + $aEventData['action'] = $sActionDesc; + $this->FireEvent(EVENT_SERVICE_DB_APPLY_STIMULUS_FAILED, $aEventData); } if ($sClass == 'UserRequest') { IssueLog::Debug("CRUD: ApplyStimulus $sStimulusCode $sClass::{$this->m_iKey} Ending", LogChannels::DM_CRUD); diff --git a/datamodels/2.x/itop-request-mgmt-itil/datamodel.itop-request-mgmt-itil.xml b/datamodels/2.x/itop-request-mgmt-itil/datamodel.itop-request-mgmt-itil.xml index b860a3ef4..ca577e455 100755 --- a/datamodels/2.x/itop-request-mgmt-itil/datamodel.itop-request-mgmt-itil.xml +++ b/datamodels/2.x/itop-request-mgmt-itil/datamodel.itop-request-mgmt-itil.xml @@ -1198,7 +1198,19 @@ - + + + EVENT_SERVICE_DB_INSERT_REQUESTED + OnInsertRequested + 0 + + + EVENT_SERVICE_DB_UPDATE_REQUESTED + OnUpdateRequested + 0 + + + true public @@ -1537,27 +1549,25 @@ $this->UpdateImpactedItems(); }]]> - + false protected Overload-DBObject ComputeImpactedItems(); $this->SetIfNull('last_update', time()); $this->SetIfNull('start_date', time()); }]]> - + false protected Overload-DBObject ListChanges(); if (array_key_exists('functionalcis_list', $aChanges)) { diff --git a/datamodels/2.x/itop-request-mgmt/datamodel.itop-request-mgmt.xml b/datamodels/2.x/itop-request-mgmt/datamodel.itop-request-mgmt.xml index 96392194a..993a8422c 100755 --- a/datamodels/2.x/itop-request-mgmt/datamodel.itop-request-mgmt.xml +++ b/datamodels/2.x/itop-request-mgmt/datamodel.itop-request-mgmt.xml @@ -1232,14 +1232,14 @@ - - BeforeInsert - OnBeforeInsertEvent + + EVENT_SERVICE_DB_INSERT_REQUESTED + OnInsertRequested 0 - - BeforeUpdate - OnBeforeUpdateEvent + + EVENT_SERVICE_DB_UPDATE_REQUESTED + OnUpdateRequested 0 @@ -1594,12 +1594,12 @@ $this->UpdateImpactedItems(); }]]> - + false public Internal ComputeImpactedItems(); @@ -1607,12 +1607,12 @@ $this->SetIfNull('start_date', time()); }]]> - + false public Internal ListChanges(); if (array_key_exists('functionalcis_list', $aChanges)) diff --git a/setup/compiler.class.inc.php b/setup/compiler.class.inc.php index 261f854db..417c2f064 100644 --- a/setup/compiler.class.inc.php +++ b/setup/compiler.class.inc.php @@ -1080,11 +1080,21 @@ EOF $sName = $oEvent->getAttribute('id'); $oDescription = $oEvent->GetOptionalElement('description'); $sDescription = empty($oDescription) ? '' : $oDescription->GetText(''); - + $aArguments = []; + foreach ($oEvent->GetNodes('./arguments/argument') as $oArgumentNode) { + $aArg = []; + $sArgId = $oArgumentNode->getAttribute('id'); + $oArgDesc = $oArgumentNode->GetOptionalElement('description'); + $aArg['description'] = empty($oArgDesc) ? '' : $oArgDesc->GetText(''); + $oArgType = $oArgumentNode->GetOptionalElement('type'); + $aArg['type'] = empty($oArgType) ? '' : $oArgType->GetText(''); + $aArguments[$sArgId] = $aArg; + } + $sArguments = var_export($aArguments, true); $sConstant = $sName; $sOutput = "define('$sConstant', '$sName');\n"; - $sOutput .= "Combodo\iTop\Service\EventService::RegisterEvent('$sName', '$sDescription', '$sModuleName');\n"; + $sOutput .= "Combodo\iTop\Service\EventService::RegisterEvent('$sName', '$sDescription', $sArguments, '$sModuleName');\n"; return $sOutput; }