:: Version 2.7.0 ::

CRUD methods sequentiallity

Call sequence of hookable/customizable methods during CRUD operations. This was made on the 2.6.0 code base, updated with 2.7.0 codebase.

In bold : overridable callbacks (in the code they are marked with a @api PHPDoc annotation).
In red : calls that has action directly on the DB.
In blue : parent methods.

Objects hierarchy

  • DBObject : persistent objects in DB
    • CMDBObject : adds history tracking
      • cmdbAbstractObject : editable objects

All default datamodel objects inherit from cmdbAbstractObject.

CRUD operations

Transactions were implemented in 2.7.0 with a try/retry mechanism. See :

  • N°679
  • N°2456

DBInsert

Starting from cmdbAbstractObject::DBInsert :

  • cmdbAbstractObject::DBInsertNoReload
    • DBObject::DBInsertNoReload
      • DBObject::DoComputeValues
        • DBObject::ComputeValues
      • DBObject::OnInsert
      • DBObject::CheckToWrite
        • if MetaModel::SkipCheckToWrite return
        • cmdbAbstractObject::DoCheckToWrite : see dedicated chapter below
        • ExecutionKPI::ComputeStats
      • if CheckToWrite returned false then throw CoreCannotSaveObjectException
      • DBObject::GetState
      • foreach MetaModel::ListAttributeDefs, if ($oAttDef instanceof AttributeStopWatch)
        • ormStopWatch::Start
        • ormStopWatch::ComputeDeadlines
        • DBObject::Set : set attdef with the modified value
      • CMDBSource::Query('START TRANSACTION'); : since 2.7.0 (N°679)
      • DBObject::DBInsertSingleTable($sRootClass)
      • DBObject::DBInsertSingleTable($sClass) : calls insert on leaf class
      • foreach MetaModel::EnumParentClasses
        • DBObject::DBInsertSingleTable($sParentClass) : calls insert on class hierarchy
      • cmdbAbstractObject::OnObjectKeyReady
        • InlineImage::FinalizeInlineImages
      • DBObject::DBWriteLinks
        • for each modified linkset
          • ormLinkSet::DBWrite
      • DBObject::WriteExternalAttributes
      • CMDBSource::Query('COMMIT'); ROLLBACK if exception occurs
      • reset meta informations : m_bIsInDB = true, m_bDirty = false, sets m_aOrigValues[$sAttCode]
      • DBObject::AfterInsert
      • search for triggers :
        • $sClassList = MetaModel::EnumParentClasses
        • SELECT TriggerOnObjectCreate AS t WHERE t.target_class IN ('$sClassList')
        • loop on query results
          • Trigger::DoActivate
      • CMDBObject::RecordObjCreation
        • remove the deletion record(s)
        • any other change tracking information left prior to 2.0.3
        • DBObject::RecordObjCreation
          • DBObject::RecordLinkSetListChange
        • create a new CMDBChangeOpCreate
    • foreach iApplicationObjectExtension (dans cmdbAbstractObject::DBInsert)
      • iApplicationObjectExtension::OnDBInsert
  • DBObject::Reload
    • MetaModel::MakeSingleRow : get persisted values
    • DBObject::FromRow : fill object with rom from DB
    • reset meta informations : m_bFullyLoaded (set to true), m_aTouchedAtt, m_aModifiedAtt
  • return DBObject::$m_iKey

DBUpdate

  • cmdbAbstractObject::DBUpdate
    • CMDBObject::DBUpdate
      • if no change, return
      • DBObject::DBUpdate
        • re-entrant call (N°1073) : check if array_key_exists($sKey, $aUpdateReentrance) with $sKey initialized from the GetKey() method, if true return
        • re-entrant call (N°1073) : set $aUpdateReentrance[$sKey] = true
        • DBObject::InitPreviousValuesForUpdatedAttributes : since 2.7.0 N°2293, set data for DBObject::ListPreviousValuesForUpdatedAttributes
        • DBObject::DoComputeValues
          • DBObject::ComputeValues
        • DBObject::GetState
        • if ($sState != '')
          • foreach(MetaModel::ListAttributeDefs)
            • if ($oAttDef instanceof AttributeStopWatch)
              • ormStopWatch::ComputeDeadlines
        • DBObject::OnUpdate
        • if (count($this→ListChanges()) ==0)
          • re-entrant call (N°1073) : unset($aUpdateReentrance[$sKey]);
          • return;
        • DBObject::CheckToWrite
          • return if MetaModel::SkipCheckToWrite
          • cmdbAbstractObject::DoCheckToWrite : see dedicated chapter below
          • ExecutionKPI::ComputeStats
        • if returns false then throws a CoreCannotSaveObjectException
        • save original values : DBObject::$m_aOrigValues into $aOriginalValues variable
        • TriggerOnObjectUpdate : for all triggers using current class or one of its parent
          • TriggerOnObjectUpdate::DoActivate
        • CMDBSource::Query('START TRANSACTION'); since 2.7.0 (N°679)
        • if (!MetaModel::DBIsReadOnly())
          • Update the left & right indexes for each hierarchical key
          • Update scalar attributes
            • new DBObjectSearch with current class name and id, and AllowAllData()
            • DBObjectSearch::MakeUpdateQuery ! changes list is passed as parameters
            • \CMDBSource::Query execute the update query
        • DBObject::DBWriteLinks
        • DBObject::WriteExternalAttributes
        • attributes reset : m_bDirty (to false), m_aTouchedAtt, m_aModifiedAtt ⇒ this leads to ListChanges() returning an empty array
        • DBObject::RecordAttChanges
        • CMDBSource::Query('COMMIT'); ROLLBACK if exception
        • DBObject::AfterUpdate : since 2.7.0 N°2293 changes can be accessed using DBObject::ListPreviousValuesForUpdatedAttributes
        • if ($bHasANewExternalKeyValue)
          • DBObject::Reload
            • MetaModel::MakeSingleRow
            • DBObject::FromRow
            • foreach MetaModel::ListAttributeDefs
              • reset \DBObject::$m_aCurrValues
              • reset \DBObject::$m_aOrigValues
              • reset \DBObject::$m_aLoadedAtt
            • set \DBObject::$m_bFullyLoaded to true
            • reset \DBObject::$m_aTouchedAtt
            • reset \DBObject::$m_aModifiedAtt
        • else
          • reset DBObject::$m_aOrigValues
        • re-entrant call (N°1073) : unset($aUpdateReentrance[$sKey]);
        • return $this→m_iKey;
    • $this→SetWarningsAsSessionMessages('update');
    • re-entrant call (N°1073) : check if array_key_exists($sKey, $aUpdateReentrance) with $sKey initialized from the GetKey() method, if true return
    • re-entrant call (N°1073) : set $aUpdateReentrance[$sKey] = true
    • search for iApplicationObjectExtension implementations
      • iApplicationObjectExtension::OnDBUpdate : since 2.7.0 N°2293 changes can be accessed using DBObject::ListPreviousValuesForUpdatedAttributes
    • re-entrant call (N°1073) : unset($aUpdateReentrance[$sKey]);
    • return $res;

DBDelete

No cmdbAbstractObject::DBDelete. So the stack begins in CMDBObject::DBDelete :

  • CMDBObject::DBDelete
    • cmdbAbstractObject::DBDeleteTracked_Internal
      • search for iApplicationObjectExtension implementations
        • iApplicationObjectExtension::OnDBDelete
      • CMDBObject::DBDeleteTracked_Internal
        • DBObject::DBDelete
          • DBObject::MakeDeletionPlan
            • DeletionPlan::AddToDelete : add current object to objects to delete list
            • cmdbAbstractObject::DoCheckToDelete
              • DBObject::DoCheckToDelete : @internal but has the DeletionPlan as parameter
                • Some actions if $this→InSyncScope()
              • iApplicationObjectExtension::OnCheckToDelete : overridable hook but we can't access the DeletionPlan instance :(
              • UserRights::IsActionAllowed
            • DeletionPlan::SetDeletionIssues
            • DBObject::GetReferencingObjects
            • foreach ($aDependentObjects as $sRemoteClass ⇒ $aPotentialDeletes)
              • DeletionPlan::AddToUpdate : if ext key has is_null_allowed=true parameter
              • DBObject::MakeDeletionPlan : else
          • DeletionPlan::ComputeResults
          • if ($oDeletionPlan→FoundStopper()) : throw throw new DeleteException
          • foreach ($oDeletionPlan→ListDeletes() as $sClass ⇒ $aToDelete)
            • DBObject::DBDeleteSingleObject
              • DBObject::OnDelete
              • $aParams = array('class_list' ⇒ MetaModel::EnumParentClasses($sClass, ENUM_PARENT_CLASSES_ALL));
              • SELECT TriggerOnObjectDelete AS t WHERE t.target_class IN (:class_list)
                • Trigger::DoActivate
              • CMDBObject::RecordObjDeletion
                • Remove CMDBChangeOp objects
                • DBObject::RecordObjDeletion
                  • \DBObject::RecordLinkSetListChange
                • Create and persist new CMDBChangeOpDelete
              • foreach (MetaModel::ListAttributeDefs(get_class($this)) as $sAttCode ⇒ $oAttDef)
                • if ($oAttDef→IsHierarchicalKey())
                  • Update the left & right indexes for each hierarchical key
                • elseif (!$oAttDef→LoadFromDB())
                  • AttributeCustomFields::DeleteValue
                    • TemplateFieldsHandler::DeleteValues
                      • DBObject::DBDelete
              • CMDBSource::Query('START TRANSACTION'); since 2.7.0 (N°679)
              • foreach (MetaModel::EnumParentClasses(get_class($this), ENUM_PARENT_CLASSES_ALL) as $sParentClass)
                • DBObject::DBDeleteSingleTable
              • CMDBSource::Query('COMMIT'); ROLLBACK if exception
              • DBObject::AfterDelete
          • foreach ($oDeletionPlan→ListUpdates() as $sClass ⇒ $aToUpdate)
            • DBObject::Set : reset ext key
            • DBObject::DBUpdate

ApplyStimulus

There are no overloads, the start is in DBObject

  • DBObject::ApplyStimulus
    • if stimulus has no effect in the current state : return true
    • DBObject::Set : set the new state
    • foreach ($aTransitionDef['actions'] as $actionHandler)
      • if (is_string($actionHandler))
        • call_user_func($aActionCallSpec, $sStimulusCode); : pref 2.1.0 module : call method directly
      • else
        • foreach($actionHandler['params'] as $aDefinition)
          • set $value depending of parameter type
          • $bRet = call_user_func_array($aCallSpec, $aParams);
          • if ($bRet === false) IssueLog::Info + $bSuccess = false
    • if ($bSuccess)
      • Stop watches : start or stop
      • if (!$bDoNotWrite) DBObject::DBWrite
        • if ($this->m_bIsInDB) DBObject::DBUpdate
        • else DBObject::DBInsert
      • Search all TriggerOnStateLeave for current class and its parent
        • Trigger::DoActivate
      • Search all TriggerOnStateEnter for current class and its parent
        • Trigger::DoActivate
    • return $bSuccess;

Generic methods

DoCheckToWrite

  • cmdbAbstractObject::DoCheckToWrite : warning not empty, do not forget to call parent when overriding !
    • \DBObject::DoCheckToWrite
      • DBObject::DoComputeValues
        • Set the “null-not-allowed” datetimes (and dates) whose value is not initialized
        • DBObject::ComputeValues
      • DBObject::DoCheckUniqueness : see dedicated chapter below
      • DBObject::ListChanges
      • foreach $aChanges
        • DBObject::CheckValue
      • DBObject::CheckConsistency
      • if DBObject::$m_bIsInDB && DBObject::InSyncScope && (count($aChanges) > 0)
        • add error in DBObject::$m_aCheckIssues for each attribute locked because of datasynchro (OPT_ATT_SLAVE)
    • foreach iApplicationObjectExtension
      • iApplicationObjectExtension::OnCheckToWrite
    • if (!$this→bAllowWrite)
      • UserRights::IsActionAllowedOnAttribute : for each change check if it is allowed (if not add error to DBObject::$m_aCheckIssues)
  • ExecutionKPI::ComputeStats

DoCheckUniqueness call hierarchy

Uniqueness rules were added in 2.6.0 with N°659.

Documentation in the XML reference

  • DBObject::DoCheckToWrite
    • DBObject::DoCheckUniqueness
      • MetaModel::GetUniquenessRules
      • foreach $aUniquenessRules
        • DBObject::HasObjectsInDbForUniquenessRule
          • DBObject::GetSearchForUniquenessRule
        • if ($bHasDuplicates)
          • DBObject::GetUniquenessRuleMessage
2_7_0/customization/sequence_crud.txt · Last modified: 2020/04/15 15:23 (external edit)
Back to top
Contact us