Sidebar

Using iTop

Creating your iTop

iTop Customization

"How to" examples
DataModel

User Interface

Automation & Ticket management

Portal Customization

iTop objects CRUD stack

Overview

This is a map of the methods called in the iTop ORM CRUD stack (Create, Update, Delete operations).

To learn more about extensibility, see Extensibility API

Objects hierarchy

There are 3 classes in iTop core that can be extended for a new iTop object :

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

All default datamodel objects are children of cmdbAbstractObject.

Stack modification history

  • 2.7.0 : transactions (see :N°679, N°2456)
  • 3.1.0 : Events (N°4756, N°5906)

Caption

In bold : overridable callbacks (in the code they are marked with a overwritable-hook PHPDoc tag).
In red : calls that has action directly on the DB.
In blue : parent methods.
In green : event.
In purple : object access modification.

DBInsert

Starting from DBObject::DBInsert :

  • cmdbAbstractObject::DBInsertNoReload
    • DBObject::DBInsertNoReload
      • DBObject::DoComputeValues
        • cmdbAbstractObject::FireEventComputeValues
          • EventService::FireEvent(EVENT_DB_COMPUTE_VALUES) Since 3.1.0 N°4756
        • DBObject::ComputeValues
      • DBObject::OnInsert
      • cmdbAbstractObject::FireEventBeforeWrite
        • EventService::FireEvent(EVENT_DB_BEFORE_WRITE, ['is_new' => true]) Since 3.1.0 N°6324
      • DBObject::CheckToWrite
        • if MetaModel::SkipCheckToWrite return
        • DBObject::SetReadOnly : No DBObject::Set allowed from here Since 3.1.0 N°4756
        • cmdbAbstractObject::FireEventCheckToWrite
          • EventService::FireEvent(EVENT_DB_CHECK_TO_WRITE, ['is_new' => true]) Since 3.1.0 N°4756
        • DBObject::SetReadWrite : DBObject::Set are allowed from here Since 3.1.0 N°4756
        • cmdbAbstractObject::DoCheckToWrite : see dedicated chapter below
        • 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
        • \AttributeCustomFields::WriteExternalValues
      • 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
      • CMDBSource::Query('COMMIT'); ROLLBACK if exception occurs
      • reset meta informations : m_bIsInDB = true, m_bDirty = false, sets m_aOrigValues[$sAttCode]
      • MetaModel::StartReentranceProtection() Since 3.1.0 N°4756
      • cmdbAbstractObject::PostInsertActions
        • DBObject::PostInsertActions
          • cmdbAbstractObject::FireEventAfterWrite
            • \cmdbAbstractObject::NotifyAttachedObjectsOnLinkClassModification since 3.1.0 N°5906
            • \cmdbAbstractObject::FireEventDbLinksChangedForCurrentObject EVENT_DB_LINKS_CHANGED since 3.1.0 N°5906
            • EventService::FireEvent(EVENT_DB_AFTER_WRITE, ['changes' => [], 'is_new' => true]) Since 3.1.0 N°6324
          • DBObject::AfterInsert
          • search for triggers :
            • $sClassList = MetaModel::EnumParentClasses
            • SELECT TriggerOnObjectCreate AS t WHERE t.target_class IN ('$sClassList')
            • loop on query results
              • Trigger::DoActivate
          • DBObject::ActivateOnMentionTriggers
        • foreach iApplicationObjectExtension (dans cmdbAbstractObject::DBInsert)
          • iApplicationObjectExtension::OnDBInsert
      • MetaModel::StopReentranceProtection(REENTRANCE_TYPE_UPDATE) Since 3.1.0 N°4756
      • if the object is modified DBObject::DBUpdate Since 3.1.0 N°4756
    • finally
      • if (static::IsCrudStackEmpty())
        • \cmdbAbstractObject::FireEventDbLinksChangedForAllObjects EVENT_DB_LINKS_CHANGED since 3.1.0 N°5906
  • return DBObject::$m_iKey

DBUpdate

  • cmdbAbstractObject::DBUpdate
    • if no change return
    • DBObject::DBUpdate
      • MetaModel::StartReentranceProtection exit if already in update ( Since 3.1.0 N°4756 )
      • DBObject::DoComputeValues
        • cmdbAbstractObject::FireEventComputeValues
          • EventService::FireEvent(EVENT_DB_COMPUTE_VALUES) Since 3.1.0 N°4756
        • DBObject::ComputeValues
      • DBObject::GetState
      • if ($sState != '')
        • foreach(MetaModel::ListAttributeDefs)
          • if ($oAttDef instanceof AttributeStopWatch)
            • ormStopWatch::ComputeDeadlines
      • DBObject::OnUpdate
      • cmdbAbstractObject::FireEventBeforeWrite
        • EventService::FireEvent(EVENT_DB_BEFORE_WRITE, ['is_new' => false]) Since 3.1.0 N°6324
      • DBObject::InitPreviousValuesForUpdatedAttributes : since 2.7.0 N°2293, set data for DBObject::ListPreviousValuesForUpdatedAttributes
      • save $this→ListChanges() to $aChanges Freeze changes
      • if (count($this→ListChanges()) == 0)
        • MetaModel::StopReentranceProtection(REENTRANCE_TYPE_UPDATE) Since 3.1.0 N°4756
        • return DBObject::$m_iKey;
      • DBObject::CheckToWrite
        • if MetaModel::SkipCheckToWrite return
        • DBObject::SetReadOnly : No DBObject::Set allowed from here ( Since 3.1.0 N°4756 )
          • cmdbAbstractObject::FireEventCheckToWrite
            • EventService::FireEvent(EVENT_DB_CHECK_TO_WRITE, ['is_new' => false]) Since 3.1.0 N°4756
        • DBObject::SetReadWrite : DBObject::Set are allowed from here ( Since 3.1.0 N°4756 )
        • cmdbAbstractObject::DoCheckToWrite : see dedicated chapter below
      • if returns false then throws a CoreCannotSaveObjectException
      • save original values : DBObject::$m_aOrigValues into $aOriginalValues variable
      • set $aDBChanges from $aChanges for fields having \AttributeDefinition::IsBasedOnDBColumns == true
      • 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 using $aDBChanges
          • \CMDBSource::Query execute the update query
      • DBObject::DBWriteLinks
      • DBObject::WriteExternalAttributes
        • \AttributeCustomFields::WriteExternalValues
      • attributes reset : m_bDirty (to false), m_aTouchedAtt, m_aModifiedAtt ⇒ this leads to ListChanges() returning an empty array
      • DBObject::RecordAttChanges using $aChanges
      • CMDBSource::Query('COMMIT'); ROLLBACK if exception
      • cmdbAbstractObject::PostUpdateActions
        • DBObject::PostUpdateActions
          • cmdbAbstractObject::FireEventAfterWrite
            • \cmdbAbstractObject::NotifyAttachedObjectsOnLinkClassModification since 3.1.0 N°5906
            • \cmdbAbstractObject::FireEventDbLinksChangedForCurrentObject EVENT_DB_LINKS_CHANGED since 3.1.0 N°5906
            • EventService::FireEvent(EVENT_DB_AFTER_WRITE, ['changes' => $aChanges, 'is_new' => false]) Since 3.1.0 N°6324
          • DBObject::AfterUpdate : since 2.7.0 N°2293 changes can be accessed using DBObject::ListPreviousValuesForUpdatedAttributes
          • reset DBObject::$m_aOrigValues
          • TriggerOnObjectUpdate : for all triggers using current class or one of its parent
            • TriggerOnObjectUpdate::DoActivate : Since 3.0.0 N°3245 & 3.0.2 N°5389 TriggerOnObjectUpdate is moved AFTER the database update
          • re-entrant call (N°1073) : unset(DBObject.aUpdateReentrance[$sKey]);
          • DBObject::ActivateOnMentionTriggers
        • search for iApplicationObjectExtension implementations
          • iApplicationObjectExtension::OnDBUpdate : since 2.7.0 N°2293 changes can be accessed using DBObject::ListPreviousValuesForUpdatedAttributes
      • MetaModel::StopReentranceProtection() Since 3.1.0 N°4756
      • if the object is modified and not an infinite loop Since 3.1.0
        • DBObject::DBUpdate Since 3.1.0 N°4756
      • return $this→m_iKey;
    • $this→SetWarningsAsSessionMessages('update');
    • finally
      • if (static::IsCrudStackEmpty())
        • \cmdbAbstractObject::FireEventDbLinksChangedForAllObjects EVENT_DB_LINKS_CHANGED since 3.1.0 N°5906
    • return $res;

DBDelete

  • cmdbAbstractObject::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
            • EventService::FireEvent(EVENT_DB_CHECK_TO_DELETE, ['deletion_plan' => $oDeletionPlan]) Since 3.1.0 N°4756
            • 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())
            • EventService::FireEvent(EVENT_DB_CHECK_TO_DELETE_FAILED) Since 3.1.0 N°4756
            • 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
              • cmdbAbstractObject::FireEventAfterDelete
                • \cmdbAbstractObject::NotifyAttachedObjectsOnLinkClassModification since 3.1.0 N°5906
                • \cmdbAbstractObject::FireEventDbLinksChangedForCurrentObject EVENT_DB_LINKS_CHANGED since 3.1.0 N°5906
                • EventService::FireEvent(EVENT_DB_AFTER_DELETE) Since 3.1.0 N°6324
              • DBObject::AfterDelete
          • foreach ($oDeletionPlan→ListUpdates() as $sClass ⇒ $aToUpdate)
            • DBObject::Set : reset ext key
            • DBObject::DBUpdate
    • finally
      • if (static::IsCrudStackEmpty())
        • \cmdbAbstractObject::FireEventDbLinksChangedForAllObjects EVENT_DB_LINKS_CHANGED since 3.1.0 N°5906

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
    • EventService::FireEvent(EVENT_DB_BEFORE_APPLY_STIMULUS) Since 3.1.0 N°4756
    • 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
      • if Ok then EventService::FireEvent(EVENT_DB_AFTER_APPLY_STIMULUS) Since 3.1.0 N°4756
      • if not Ok then EventService::FireEvent(EVENT_DB_APPLY_STIMULUS_FAILED) Since 3.1.0 N°4756
    • return $bSuccess;

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
latest/customization/sequence_crud.txt · Last modified: 2023/07/21 10:19 (external edit)
Back to top
Contact us