diff --git a/application/cmdbabstract.class.inc.php b/application/cmdbabstract.class.inc.php index bef6e700e..3de2d210e 100644 --- a/application/cmdbabstract.class.inc.php +++ b/application/cmdbabstract.class.inc.php @@ -125,27 +125,29 @@ abstract class cmdbAbstractObject extends CMDBObject implements iDisplay // Master data sources $sSynchroIcon = ''; - $oReplicaSet = $this->GetMasterReplica(); $bSynchronized = false; $oCreatorTask = null; $bCanBeDeletedByTask = false; $bCanBeDeletedByUser = true; $aMasterSources = array(); - if ($oReplicaSet->Count() > 0) + $aSyncData = $this->GetSynchroData(); + if (count($aSyncData) > 0) { $bSynchronized = true; - while($aData = $oReplicaSet->FetchAssoc()) + foreach ($aSyncData as $iSourceId => $aSourceData) { - // Assumption: $aData['datasource'] will not be null because the data source id is always set... - $sApplicationURL = $aData['datasource']->GetApplicationUrl($this, $aData['replica']); - $sLink = $aData['datasource']->GetName(); + $oDataSource = $aSourceData['source']; + $oReplica = reset($aSourceData['replica']); // Take the first one! + + $sApplicationURL = $oDataSource->GetApplicationUrl($this, $oReplica); + $sLink = $oDataSource->GetName(); if (!empty($sApplicationURL)) { - $sLink = "".$aData['datasource']->GetName().""; + $sLink = "".$oDataSource->GetName().""; } - if ($aData['replica']->Get('status_dest_creator') == 1) + if ($oReplica->Get('status_dest_creator') == 1) { - $oCreatorTask = $aData['datasource']; + $oCreatorTask = $oDataSource; $bCreatedByTask = true; } else @@ -154,12 +156,12 @@ abstract class cmdbAbstractObject extends CMDBObject implements iDisplay } if ($bCreatedByTask) { - $sDeletePolicy = $aData['datasource']->Get('delete_policy'); + $sDeletePolicy = $oDataSource->Get('delete_policy'); if (($sDeletePolicy == 'delete') || ($sDeletePolicy == 'update_then_delete')) { $bCanBeDeletedByTask = true; } - $sUserDeletePolicy = $aData['datasource']->Get('user_delete_policy'); + $sUserDeletePolicy = $oDataSource->Get('user_delete_policy'); if ($sUserDeletePolicy == 'nobody') { $bCanBeDeletedByUser = false; @@ -172,9 +174,9 @@ abstract class cmdbAbstractObject extends CMDBObject implements iDisplay { } } - $aMasterSources[$aData['datasource']->GetKey()]['datasource'] = $aData['datasource']; - $aMasterSources[$aData['datasource']->GetKey()]['url'] = $sLink; - $aMasterSources[$aData['datasource']->GetKey()]['last_synchro'] = $aData['replica']->Get('status_last_seen'); + $aMasterSources[$iSourceId]['datasource'] = $oDataSource; + $aMasterSources[$iSourceId]['url'] = $sLink; + $aMasterSources[$iSourceId]['last_synchro'] = $oReplica->Get('status_last_seen'); } if (is_object($oCreatorTask)) @@ -1402,6 +1404,8 @@ abstract class cmdbAbstractObject extends CMDBObject implements iDisplay $sHtml .= "

\n"; $aFilterCriteria = $oSet->GetFilter()->GetCriteria(); $aMapCriteria = array(); + // Todo: Investigate... The search criteria is an expression, i.e. a tree! + // I wonder if that code could work... cleanup required/recommended foreach($aFilterCriteria as $aCriteria) { $aMapCriteria[$aCriteria['filtercode']][] = array('value' => $aCriteria['value'], 'opcode' => $aCriteria['opcode']); @@ -1429,6 +1433,7 @@ abstract class cmdbAbstractObject extends CMDBObject implements iDisplay $sFilterValue = $aMapCriteria[$sFilterCode][0]['value']; $sFilterOpCode = $aMapCriteria[$sFilterCode][0]['opcode']; } + // Todo: Investigate... if ($sFilterCode != 'company') { $oUnlimitedFilter->AddCondition($sFilterCode, $sFilterValue, $sFilterOpCode); diff --git a/core/dbobject.class.php b/core/dbobject.class.php index 9eee7fb77..089031fe5 100644 --- a/core/dbobject.class.php +++ b/core/dbobject.class.php @@ -94,7 +94,7 @@ abstract class DBObject implements iDisplay private $m_bFullyLoaded = false; // Compound objects can be partially loaded private $m_aLoadedAtt = array(); // Compound objects can be partially loaded, array of sAttCode protected $m_aModifiedAtt = array(); // list of (potentially) modified sAttCodes - protected $m_oMasterReplicaSet = null; // Set of SynchroReplica related to this object + protected $m_aSynchroData = null; // Set of Synch data related to this object protected $m_sHighlightCode = null; // Use the MetaModel::NewObject to build an object (do we have to force it?) @@ -1178,48 +1178,45 @@ abstract class DBObject implements iDisplay if ($this->InSyncScope()) { - $oReplicaSet = $this->GetMasterReplica(); - if ($oReplicaSet->Count() > 0) + + foreach ($this->GetSynchroData() as $iSourceId => $aSourceData) { - while($aData = $oReplicaSet->FetchAssoc()) + foreach ($aSourceData['replica'] as $oReplica) { - $oDataSource = $aData['datasource']; - $oReplica = $aData['replica']; - $oDeletionPlan->AddToDelete($oReplica, DEL_SILENT); + } + $oDataSource = $aSourceData['source']; + if ($oDataSource->GetKey() == SynchroExecution::GetCurrentTaskId()) + { + // The current task has the right to delete the object + continue; + } + $oReplica = reset($aSourceData['replica']); // Take the first one + if ($oReplica->Get('status_dest_creator') != 1) + { + // The object is not owned by the task + continue; + } - if ($oDataSource->GetKey() == SynchroExecution::GetCurrentTaskId()) - { - // The current task has the right to delete the object - continue; - } - - if ($oReplica->Get('status_dest_creator') != 1) - { - // The object is not owned by the task - continue; - } + $sLink = $oDataSource->GetName(); + $sUserDeletePolicy = $oDataSource->Get('user_delete_policy'); + switch($sUserDeletePolicy) + { + case 'nobody': + $this->m_aDeleteIssues[] = Dict::Format('Core:Synchro:TheObjectCannotBeDeletedByUser_Source', $sLink); + break; - $sLink = $oDataSource->GetName(); - $sUserDeletePolicy = $oDataSource->Get('user_delete_policy'); - switch($sUserDeletePolicy) + case 'administrators': + if (!UserRights::IsAdministrator()) { - case 'nobody': $this->m_aDeleteIssues[] = Dict::Format('Core:Synchro:TheObjectCannotBeDeletedByUser_Source', $sLink); - break; - - case 'administrators': - if (!UserRights::IsAdministrator()) - { - $this->m_aDeleteIssues[] = Dict::Format('Core:Synchro:TheObjectCannotBeDeletedByUser_Source', $sLink); - } - break; - - case 'everybody': - default: - // Ok - break; } + break; + + case 'everybody': + default: + // Ok + break; } } } @@ -2588,45 +2585,77 @@ abstract class DBObject implements iDisplay } /** + * WILL DEPRECATED SOON + * Caching relying on an object set is not efficient since 2.0.3 + * Use GetSynchroData instead + * * Get all the synchro replica related to this object * @param none * @return DBObjectSet Set with two columns: R=SynchroReplica S=SynchroDataSource */ public function GetMasterReplica() { - if ($this->m_oMasterReplicaSet == null) + $sOQL = "SELECT replica,datasource FROM SynchroReplica AS replica JOIN SynchroDataSource AS datasource ON replica.sync_source_id=datasource.id WHERE replica.dest_class = :dest_class AND replica.dest_id = :dest_id"; + $oReplicaSet = new DBObjectSet(DBObjectSearch::FromOQL($sOQL), array() /* order by*/, array('dest_class' => get_class($this), 'dest_id' => $this->GetKey())); + return $oReplicaSet; + } + + /** + * Get all the synchro data related to this object + * @param none + * @return array of data_source_id => array + * 'source' => $oSource, + * 'attributes' => array of $oSynchroAttribute + * 'replica' => array of $oReplica (though only one should exist, misuse of the data sync can have this consequence) + */ + public function GetSynchroData() + { + if ($this->m_aSynchroData == null) { - //$aParentClasses = MetaModel::EnumParentClasses(get_class($this), ENUM_PARENT_CLASSES_ALL); - //$sClassesList = "'".implode("','", $aParentClasses)."'"; $sOQL = "SELECT replica,datasource FROM SynchroReplica AS replica JOIN SynchroDataSource AS datasource ON replica.sync_source_id=datasource.id WHERE replica.dest_class = :dest_class AND replica.dest_id = :dest_id"; $oReplicaSet = new DBObjectSet(DBObjectSearch::FromOQL($sOQL), array() /* order by*/, array('dest_class' => get_class($this), 'dest_id' => $this->GetKey())); - $this->m_oMasterReplicaSet = $oReplicaSet; + $this->m_aSynchroData = array(); + while($aData = $oReplicaSet->FetchAssoc()) + { + $iSourceId = $aData['datasource']->GetKey(); + if (!array_key_exists($iSourceId, $this->m_aSynchroData)) + { + $aAttributes = array(); + $oAttrSet = $aData['datasource']->Get('attribute_list'); + while($oSyncAttr = $oAttrSet->Fetch()) + { + $aAttributes[$oSyncAttr->Get('attcode')] = $oSyncAttr; + } + $this->m_aSynchroData[$iSourceId] = array( + 'source' => $aData['datasource'], + 'attributes' => $aAttributes, + 'replica' => array() + ); + } + // Assumption: $aData['datasource'] will not be null because the data source id is always set... + $this->m_aSynchroData[$iSourceId]['replica'][] = $aData['replica']; + } } - else - { - $this->m_oMasterReplicaSet->Rewind(); - } - return $this->m_oMasterReplicaSet; + return $this->m_aSynchroData; } public function GetSynchroReplicaFlags($sAttCode, &$aReason) { $iFlags = OPT_ATT_NORMAL; - $oSet = $this->GetMasterReplica(); - while($aData = $oSet->FetchAssoc()) + foreach ($this->GetSynchroData() as $iSourceId => $aSourceData) { - if ($aData['datasource']->GetKey() == SynchroExecution::GetCurrentTaskId()) + if ($iSourceId == SynchroExecution::GetCurrentTaskId()) { // Ignore the current task (check to write => ok) continue; } - // Assumption: $aData['datasource'] will not be null because the data source id is always set... - $oReplica = $aData['replica']; - $oSource = $aData['datasource']; - $oAttrSet = $oSource->Get('attribute_list'); - while($oSyncAttr = $oAttrSet->Fetch()) + // Assumption: one replica - take the first one! + $oReplica = reset($aSourceData['replica']); + $oSource = $aSourceData['source']; + if (array_key_exists($sAttCode, $aSourceData['attributes'])) { - if (($oSyncAttr->Get('attcode') == $sAttCode) && ($oSyncAttr->Get('update') == 1) && ($oSyncAttr->Get('update_policy') == 'master_locked')) + $oSyncAttr = $aSourceData['attributes'][$sAttCode]; + if (($oSyncAttr->Get('update') == 1) && ($oSyncAttr->Get('update_policy') == 'master_locked')) { $iFlags |= OPT_ATT_SLAVE; $sUrl = $oSource->GetApplicationUrl($this, $oReplica);