diff --git a/synchro/replica.php b/synchro/replica.php index 5c1836951..d4fa4f376 100644 --- a/synchro/replica.php +++ b/synchro/replica.php @@ -53,6 +53,9 @@ try { throw new ApplicationException(Dict::Format('UI:Error:1ParametersMissing', 'oql')); } + $oFilter = DBObjectSearch::FromOQL($sOQL); + $oBlock1 = new DisplayBlock($oFilter, 'search', false, array('menu'=>false)); + $oBlock1->Display($oP, 0); $oP->add('
'.MetaModel::GetClassIcon('SynchroReplica').Dict::S('Core:SynchroReplica:ListOfReplicas').'
'); $iSourceId = utils::ReadParam('datasource', null); if ($iSourceId != null) @@ -60,7 +63,6 @@ try $oSource = MetaModel::GetObject('SynchroDataSource', $iSourceId); $oP->p(Dict::Format('Core:SynchroReplica:BackToDataSource', $oSource->GetHyperlink()).''); } - $oFilter = DBObjectSearch::FromOQL($sOQL); $oBlock = new DisplayBlock($oFilter, 'list', false, array('menu'=>false)); $oBlock->Display($oP, 1); break; diff --git a/synchro/synchro_exec.php b/synchro/synchro_exec.php index 636dae5f1..ad732da3a 100644 --- a/synchro/synchro_exec.php +++ b/synchro/synchro_exec.php @@ -166,12 +166,12 @@ foreach(explode(',', $sDataSourcesList) as $iSDS) $oP->p("Objects deletion errors: ".$oStatLog->Get('stats_nb_obj_deleted_errors')); $oP->p("Objects obsoleted: ".$oStatLog->Get('stats_nb_obj_obsoleted')); $oP->p("Objects obsolescence errors: ".$oStatLog->Get('stats_nb_obj_obsoleted_errors')); - $oP->p("Objects created: ".$oStatLog->Get('stats_nb_obj_created')); + $oP->p("Objects created: ".$oStatLog->Get('stats_nb_obj_created')." (".$oStatLog->Get('stats_nb_obj_created_warnings')." warnings)"); $oP->p("Objects creation errors: ".$oStatLog->Get('stats_nb_obj_created_errors')); - $oP->p("Objects updated: ".$oStatLog->Get('stats_nb_obj_updated')); + $oP->p("Objects updated: ".$oStatLog->Get('stats_nb_obj_updated')." (".$oStatLog->Get('stats_nb_obj_updated_warnings')." warnings)"); $oP->p("Objects update errors: ".$oStatLog->Get('stats_nb_obj_updated_errors')); - $oP->p("Objects reconciled (updated): ".$oStatLog->Get('stats_nb_obj_new_updated')); - $oP->p("Objects reconciled (unchanged): ".$oStatLog->Get('stats_nb_obj_new_unchanged')); + $oP->p("Objects reconciled (updated): ".$oStatLog->Get('stats_nb_obj_new_updated')." (".$oStatLog->Get('stats_nb_obj_new_updated_warnings')." warnings)"); + $oP->p("Objects reconciled (unchanged): ".$oStatLog->Get('stats_nb_obj_new_unchanged')." (".$oStatLog->Get('stats_nb_obj_new_updated_warnings')." warnings)"); $oP->p("Objects reconciliation errors: ".$oStatLog->Get('stats_nb_replica_reconciled_errors')); $oP->p("Replica disappeared, no action taken: ".$oStatLog->Get('stats_nb_replica_disappeared_no_action')); } diff --git a/synchro/synchro_import.php b/synchro/synchro_import.php index f3a33b333..4dfb1ed8d 100644 --- a/synchro/synchro_import.php +++ b/synchro/synchro_import.php @@ -641,12 +641,12 @@ try $oP->add_comment("Objects deletion errors: ".$oStatLog->Get('stats_nb_obj_deleted_errors')); $oP->add_comment("Objects obsoleted: ".$oStatLog->Get('stats_nb_obj_obsoleted')); $oP->add_comment("Objects obsolescence errors: ".$oStatLog->Get('stats_nb_obj_obsoleted_errors')); - $oP->add_comment("Objects created: ".$oStatLog->Get('stats_nb_obj_created')); + $oP->add_comment("Objects created: ".$oStatLog->Get('stats_nb_obj_created')." (".$oStatLog->Get('stats_nb_obj_created_warnings')." warnings)"); $oP->add_comment("Objects creation errors: ".$oStatLog->Get('stats_nb_obj_created_errors')); - $oP->add_comment("Objects updated: ".$oStatLog->Get('stats_nb_obj_updated')); + $oP->add_comment("Objects updated: ".$oStatLog->Get('stats_nb_obj_updated')." (".$oStatLog->Get('stats_nb_obj_updated_warnings')." warnings)"); $oP->add_comment("Objects update errors: ".$oStatLog->Get('stats_nb_obj_updated_errors')); - $oP->add_comment("Objects reconciled (updated): ".$oStatLog->Get('stats_nb_obj_new_updated')); - $oP->add_comment("Objects reconciled (unchanged): ".$oStatLog->Get('stats_nb_obj_new_unchanged')); + $oP->add_comment("Objects reconciled (updated): ".$oStatLog->Get('stats_nb_obj_new_updated')." (".$oStatLog->Get('stats_nb_obj_new_updated_warnings')." warnings)"); + $oP->add_comment("Objects reconciled (unchanged): ".$oStatLog->Get('stats_nb_obj_new_unchanged')." (".$oStatLog->Get('stats_nb_obj_new_updated_warnings')." warnings)"); $oP->add_comment("Objects reconciliation errors: ".$oStatLog->Get('stats_nb_replica_reconciled_errors')); $oP->add_comment("Replica disappeared, no action taken: ".$oStatLog->Get('stats_nb_replica_disappeared_no_action')); } diff --git a/synchro/synchrodatasource.class.inc.php b/synchro/synchrodatasource.class.inc.php index b569f090a..12ee36932 100644 --- a/synchro/synchrodatasource.class.inc.php +++ b/synchro/synchrodatasource.class.inc.php @@ -251,6 +251,19 @@ class SynchroDataSource extends cmdbAbstractObject $sEndDate = $oLastLog->Get('end_date'); $iLastLog = $oLastLog->GetKey(); $oPage->p('');
@@ -273,6 +286,18 @@ class SynchroDataSource extends cmdbAbstractObject
$sScript .= "};\n";
$sScript .= << (".$aData[$sId.'_warnings'].")";
+ }
return "{$sLabel}{$sErrorLink} | ";
}
@@ -387,11 +422,15 @@ EOF
'obj_disappeared_errors' => $oLastLog->Get('stats_nb_obj_obsoleted_errors') + $oLastLog->Get('stats_nb_obj_deleted_errors'),
'obj_disappeared_no_action' => $oLastLog->Get('stats_nb_replica_disappeared_no_action'),
'obj_updated' => $oLastLog->Get('stats_nb_obj_updated'),
+ 'obj_updated_warnings' => $oLastLog->Get('stats_nb_obj_updated_warnings'),
'obj_updated_errors' => $oLastLog->Get('stats_nb_obj_updated_errors'),
'obj_new_updated' => $oLastLog->Get('stats_nb_obj_new_updated'),
+ 'obj_new_updated_warnings' => $oLastLog->Get('stats_nb_obj_new_updated_warnings'),
'obj_new_unchanged' => $oLastLog->Get('stats_nb_obj_new_unchanged'),
'obj_created' => $oLastLog->Get('stats_nb_obj_created'),
+ 'obj_created_warnings' => $oLastLog->Get('stats_nb_obj_created_warnings'),
'obj_created_errors' => $oLastLog->Get('stats_nb_obj_created_errors'),
+ 'obj_unchanged_warnings' => $oLastLog->Get('stats_nb_obj_unchanged_warnings'),
);
$iReconciledErrors = $oLastLog->Get('stats_nb_replica_reconciled_errors');
$iDisappeared = $aData['obj_disappeared_errors'] + $aData['obj_obsoleted'] + $aData['obj_deleted'] + $aData['obj_disappeared_no_action'];
@@ -949,13 +988,18 @@ EOF
$oStatLog->Set('stats_nb_obj_obsoleted_errors', 0);
$oStatLog->Set('stats_nb_obj_created', 0);
$oStatLog->Set('stats_nb_obj_created_errors', 0);
+ $oStatLog->Set('stats_nb_obj_created_warnings', 0);
$oStatLog->Set('stats_nb_obj_updated', 0);
+ $oStatLog->Set('stats_nb_obj_updated_warnings', 0);
$oStatLog->Set('stats_nb_obj_updated_errors', 0);
-// $oStatLog->Set('stats_nb_replica_reconciled', 0);
+ $oStatLog->Set('stats_nb_obj_unchanged_warnings', 0);
+ // $oStatLog->Set('stats_nb_replica_reconciled', 0);
$oStatLog->Set('stats_nb_replica_reconciled_errors', 0);
$oStatLog->Set('stats_nb_replica_disappeared_no_action', 0);
$oStatLog->Set('stats_nb_obj_new_updated', 0);
+ $oStatLog->Set('stats_nb_obj_new_updated_warnings', 0);
$oStatLog->Set('stats_nb_obj_new_unchanged',0);
+ $oStatLog->Set('stats_nb_obj_new_unchanged_warnings',0);
$sSelectTotal = "SELECT SynchroReplica WHERE sync_source_id = :source_id";
$oSetTotal = new DBObjectSet(DBObjectSearch::FromOQL($sSelectTotal), array() /* order by*/, array('source_id' => $this->GetKey()));
@@ -989,14 +1033,14 @@ EOF
$sStatistics .= "The synchronization has been executed, $iErrors errors have been encountered. Click here to see the records being currently in error. ".$sStatistics); @@ -1188,9 +1232,9 @@ EOF $oSetSeen = new DBObjectSet(DBObjectSearch::FromOQL($sSelectSeen), array() /* order by*/, array('source_id' => $this->GetKey(), 'last_import' => $sLimitDate)); $oStatLog->Set('stats_nb_replica_seen', $oSetSeen->Count()); - // Get all the replicas that are 'new' or modified + // Get all the replicas that are 'new' or modified or synchronized with a warning // - $sSelectToSync = "SELECT SynchroReplica WHERE (status = 'new' OR status = 'modified') AND sync_source_id = :source_id AND status_last_seen >= :last_import"; + $sSelectToSync = "SELECT SynchroReplica WHERE (status = 'new' OR status = 'modified' OR (status = 'synchronized' AND status_last_warning != '')) AND sync_source_id = :source_id AND status_last_seen >= :last_import"; $oSetToSync = new DBObjectSet(DBObjectSearch::FromOQL($sSelectToSync), array() /* order by*/, array('source_id' => $this->GetKey(), 'last_import' => $sLimitDate) /* aArgs */, $aExtDataSpec, 0 /* limitCount */, 0 /* limitStart */); while($oReplica = $oSetToSync->Fetch()) @@ -1492,15 +1536,20 @@ class SynchroLog extends DBObject MetaModel::Init_AddAttribute(new AttributeInteger("stats_nb_obj_obsoleted_errors", array("allowed_values"=>null, "sql"=>"stats_nb_obj_obsoleted_errors", "default_value"=>0, "is_null_allowed"=>false, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeInteger("stats_nb_obj_created", array("allowed_values"=>null, "sql"=>"stats_nb_obj_created", "default_value"=>0, "is_null_allowed"=>false, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeInteger("stats_nb_obj_created_errors", array("allowed_values"=>null, "sql"=>"stats_nb_obj_created_errors", "default_value"=>0, "is_null_allowed"=>false, "depends_on"=>array()))); + MetaModel::Init_AddAttribute(new AttributeInteger("stats_nb_obj_created_warnings", array("allowed_values"=>null, "sql"=>"stats_nb_obj_created_warnings", "default_value"=>0, "is_null_allowed"=>false, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeInteger("stats_nb_obj_updated", array("allowed_values"=>null, "sql"=>"stats_nb_obj_updated", "default_value"=>0, "is_null_allowed"=>false, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeInteger("stats_nb_obj_updated_errors", array("allowed_values"=>null, "sql"=>"stats_nb_obj_updated_errors", "default_value"=>0, "is_null_allowed"=>false, "depends_on"=>array()))); -// MetaModel::Init_AddAttribute(new AttributeInteger("stats_nb_replica_reconciled", array("allowed_values"=>null, "sql"=>"stats_nb_replica_reconciled", "default_value"=>0, "is_null_allowed"=>false, "depends_on"=>array()))); + MetaModel::Init_AddAttribute(new AttributeInteger("stats_nb_obj_updated_warnings", array("allowed_values"=>null, "sql"=>"stats_nb_obj_updated_warnings", "default_value"=>0, "is_null_allowed"=>false, "depends_on"=>array()))); + MetaModel::Init_AddAttribute(new AttributeInteger("stats_nb_obj_unchanged_warnings", array("allowed_values"=>null, "sql"=>"stats_nb_obj_unchanged_warnings", "default_value"=>0, "is_null_allowed"=>false, "depends_on"=>array()))); + // MetaModel::Init_AddAttribute(new AttributeInteger("stats_nb_replica_reconciled", array("allowed_values"=>null, "sql"=>"stats_nb_replica_reconciled", "default_value"=>0, "is_null_allowed"=>false, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeInteger("stats_nb_replica_reconciled_errors", array("allowed_values"=>null, "sql"=>"stats_nb_replica_reconciled_errors", "default_value"=>0, "is_null_allowed"=>false, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeInteger("stats_nb_replica_disappeared_no_action", array("allowed_values"=>null, "sql"=>"stats_nb_replica_disappeared_no_action", "default_value"=>0, "is_null_allowed"=>false, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeInteger("stats_nb_obj_new_updated", array("allowed_values"=>null, "sql"=>"stats_nb_obj_new_updated", "default_value"=>0, "is_null_allowed"=>false, "depends_on"=>array()))); + MetaModel::Init_AddAttribute(new AttributeInteger("stats_nb_obj_new_updated_warnings", array("allowed_values"=>null, "sql"=>"stats_nb_obj_new_updated_warnings", "default_value"=>0, "is_null_allowed"=>false, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeInteger("stats_nb_obj_new_unchanged", array("allowed_values"=>null, "sql"=>"stats_nb_obj_new_unchanged", "default_value"=>0, "is_null_allowed"=>false, "depends_on"=>array()))); - + MetaModel::Init_AddAttribute(new AttributeInteger("stats_nb_obj_new_unchanged_warnings", array("allowed_values"=>null, "sql"=>"stats_nb_obj_new_unchanged_warnings", "default_value"=>0, "is_null_allowed"=>false, "depends_on"=>array()))); + MetaModel::Init_AddAttribute(new AttributeText("last_error", array("allowed_values"=>null, "sql"=>"last_error", "default_value"=>'', "is_null_allowed"=>true, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeLongText("traces", array("allowed_values"=>null, "sql"=>"traces", "default_value"=>'', "is_null_allowed"=>true, "depends_on"=>array()))); @@ -1604,6 +1653,7 @@ class SynchroLog extends DBObject class SynchroReplica extends DBObject implements iDisplay { static $aSearches = array(); // Cache of OQL queries used for reconciliation (per data source) + protected $aWarnings; public static function Init() { @@ -1632,7 +1682,8 @@ class SynchroReplica extends DBObject implements iDisplay MetaModel::Init_AddAttribute(new AttributeEnum("status", array("allowed_values"=>new ValueSetEnum('new,synchronized,modified,orphan,obsolete'), "sql"=>"status", "default_value"=>"new", "is_null_allowed"=>false, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeBoolean("status_dest_creator", array("allowed_values"=>null, "sql"=>"status_dest_creator", "default_value"=>0, "is_null_allowed"=>true, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeString("status_last_error", array("allowed_values"=>null, "sql"=>"status_last_error", "default_value"=>'', "is_null_allowed"=>true, "depends_on"=>array()))); - + MetaModel::Init_AddAttribute(new AttributeString("status_last_warning", array("allowed_values"=>null, "sql"=>"status_last_warning", "default_value"=>'', "is_null_allowed"=>true, "depends_on"=>array()))); + MetaModel::Init_AddAttribute(new AttributeDateTime("info_creation_date", array("allowed_values"=>null, "sql"=>"info_creation_date", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeDateTime("info_last_modified", array("allowed_values"=>null, "sql"=>"info_last_modified", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array()))); @@ -1640,17 +1691,65 @@ class SynchroReplica extends DBObject implements iDisplay MetaModel::Init_SetZListItems('details', array('' . 'col:0'=> array( 'fieldset:SynchroDataSource:Definition' => array('sync_source_id','dest_id','dest_class'), - 'fieldset:SynchroDataSource:Status' => array('status','status_last_seen','status_dest_creator','status_last_error'), + 'fieldset:SynchroDataSource:Status' => array('status','status_last_seen','status_dest_creator','status_last_error','status_last_warning'), 'fieldset:SynchroDataSource:Information' => array('info_creation_date','info_last_modified')) ) ); - MetaModel::Init_SetZListItems('list', array('sync_source_id', 'dest_id', 'dest_class', 'status_last_seen', 'status', 'status_dest_creator', 'status_last_error')); // Attributes to be displayed for a list + MetaModel::Init_SetZListItems('list', array('sync_source_id', 'dest_id', 'dest_class', 'status_last_seen', 'status', 'status_dest_creator', 'status_last_error', 'status_last_warning')); // Attributes to be displayed for a list // Search criteria - MetaModel::Init_SetZListItems('standard_search', array('sync_source_id', 'status_last_seen', 'status', 'status_dest_creator', 'dest_class', 'dest_id', 'status_last_error')); // Criteria of the std search form + MetaModel::Init_SetZListItems('standard_search', array('sync_source_id', 'status_last_seen', 'status', 'status_dest_creator', 'dest_class', 'dest_id', 'status_last_error', 'status_last_warning')); // Criteria of the std search form // MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form } + + public function __construct($aRow = null, $sClassAlias = '', $aAttToLoad = null, $aExtendedDataSpec = null) + { + parent::__construct($aRow, $sClassAlias, $aAttToLoad, $aExtendedDataSpec); + $this->aWarnings = array(); + } - public function DBInsert() + protected function AddWarning($sWarningMessage) + { + $this->aWarnings[] = $sWarningMessage; + } + + protected function ResetWarnings() + { + $this->aWarnings = array(); + } + + protected function HasWarnings() + { + return (count($this->aWarnings) > 0); + } + + protected function RecordWarnings() + { + $sWarningMessage = ''; + $MAX_WARNING_LENGTH = 255; + switch(count($this->aWarnings)) + { + case 0: + $sWarningMessage = ''; + break; + + case 1: + $sWarningMessage = $this->aWarnings[0]; + break; + + default: + $sWarningMessage = count($this->aWarnings)." warnings: ".implode(' '.$this->aWarnings); + break; + } + + if (strlen($sWarningMessage) > $MAX_WARNING_LENGTH) + { + $sWarningMessage = substr($sWarningMessage, 0, $MAX_WARNING_LENGTH - 3).'...'; + } + + $this->Set('status_last_warning', $sWarningMessage); + } + + public function DBInsert() { throw new CoreException('A synchronization replica must be created only by the mean of triggers'); } @@ -1696,6 +1795,7 @@ class SynchroReplica extends DBObject implements iDisplay public function Synchro($oDataSource, $aReconciliationKeys, $aAttributes, $oChange, &$oStatLog) { + $this->ResetWarnings(); switch($this->Get('status')) { case 'new': @@ -1722,6 +1822,7 @@ class SynchroReplica extends DBObject implements iDisplay } else { + // TO DO: can we retry this ?? // Reconciliation could not be performed - log and EXIT $oStatLog->AddTrace("Could not reconcile on null value for attribute '$sFilterCode'", $this); $this->SetLastError("Could not reconcile on null value for attribute '$sFilterCode'"); @@ -1745,6 +1846,10 @@ class SynchroReplica extends DBObject implements iDisplay if ($oDataSource->Get('action_on_zero') == 'create') { $this->CreateObjectFromReplica($oDataSource->GetTargetClass(), $aAttributes, $oChange, $oStatLog); + if ($this->HasWarnings()) + { + $oStatLog->Inc('stats_nb_obj_created_warnings'); + } } else // assumed to be 'error' { @@ -1760,9 +1865,20 @@ class SynchroReplica extends DBObject implements iDisplay if ($oDataSource->Get('action_on_one') == 'update') { $oDestObj = $oDestSet->Fetch(); - $this->UpdateObjectFromReplica($oDestObj, $aAttributes, $oChange, $oStatLog, 'stats_nb_obj_new', 'stats_nb_replica_reconciled_errors'); + $bModified = $this->UpdateObjectFromReplica($oDestObj, $aAttributes, $oChange, $oStatLog, 'stats_nb_obj_new', 'stats_nb_replica_reconciled_errors'); $this->Set('dest_id', $oDestObj->GetKey()); $this->Set('dest_class', get_class($oDestObj)); + if ($this->HasWarnings()) + { + if ($bModified) + { + $oStatLog->Inc('stats_nb_obj_new_updated_warnings'); + } + else + { + $oStatLog->Inc('stats_nb_obj_new_unchanged_warnings'); + } + } } else { @@ -1786,20 +1902,37 @@ class SynchroReplica extends DBObject implements iDisplay elseif ($oDataSource->Get('action_on_multiple') == 'create') { $this->CreateObjectFromReplica($oDataSource->GetTargetClass(), $aAttributes, $oChange, $oStatLog); + if ($this->HasWarnings()) + { + $oStatLog->Inc('stats_nb_obj_created_warnings'); + } } else { // assumed to be 'take_first' $oDestObj = $oDestSet->Fetch(); - $this->UpdateObjectFromReplica($oDestObj, $aAttributes, $oChange, $oStatLog, 'stats_nb_obj_new', 'stats_nb_replica_reconciled_errors'); + $bModified = $this->UpdateObjectFromReplica($oDestObj, $aAttributes, $oChange, $oStatLog, 'stats_nb_obj_new', 'stats_nb_replica_reconciled_errors'); $this->Set('dest_id', $oDestObj->GetKey()); $this->Set('dest_class', get_class($oDestObj)); + if ($this->HasWarnings()) + { + if ($bModified) + { + $oStatLog->Inc('stats_nb_obj_new_updated_warnings'); + } + else + { + $oStatLog->Inc('stats_nb_obj_new_unchanged_warnings'); + } + } } } + $this->RecordWarnings(); break; + case 'synchronized': // try to recover synchronized replicas with warnings case 'modified': - $oDestObj = MetaModel::GetObject($oDataSource->GetTargetClass(), $this->Get('dest_id')); + $oDestObj = MetaModel::GetObject($oDataSource->GetTargetClass(), $this->Get('dest_id')); if ($oDestObj == null) { $this->Set('status', 'orphan'); // The destination object has been deleted ! @@ -1808,8 +1941,20 @@ class SynchroReplica extends DBObject implements iDisplay } else { - $this->UpdateObjectFromReplica($oDestObj, $aAttributes, $oChange, $oStatLog, 'stats_nb_obj', 'stats_nb_obj_updated_errors'); + $bModified = $this->UpdateObjectFromReplica($oDestObj, $aAttributes, $oChange, $oStatLog, 'stats_nb_obj', 'stats_nb_obj_updated_errors'); + if ($this->HasWarnings()) + { + if ($bModified) + { + $oStatLog->Inc('stats_nb_obj_updated_warnings'); + } + else + { + $oStatLog->Inc('stats_nb_obj_unchanged_warnings'); + } + } } + $this->RecordWarnings(); break; default: // Do nothing in all other cases @@ -1822,6 +1967,7 @@ class SynchroReplica extends DBObject implements iDisplay protected function UpdateObjectFromReplica($oDestObj, $aAttributes, $oChange, &$oStatLog, $sStatsCode, $sStatsCodeError) { $aValueTrace = array(); + $bModified = false; try { foreach($aAttributes as $sAttCode => $oSyncAtt) @@ -1837,6 +1983,7 @@ class SynchroReplica extends DBObject implements iDisplay if ($oDestObj->IsModified()) { $oDestObj->DBUpdateTracked($oChange); + $bModified = true; $oStatLog->AddTrace('Updated object - Values: {'.implode(', ', $aValueTrace).'}', $this); if (($sStatsCode != '') &&(MetaModel::IsValidAttCode(get_class($oStatLog), $sStatsCode.'_updated'))) { @@ -1862,6 +2009,7 @@ class SynchroReplica extends DBObject implements iDisplay $this->SetLastError('Unable to update destination object: ', $e); $oStatLog->Inc($sStatsCodeError); } + return $bModified; } /** @@ -1994,6 +2142,7 @@ class SynchroReplica extends DBObject implements iDisplay // $sExtAttCode is a valid attribute code // $sClass = $this->Get('base_class'); + $oAttDef = MetaModel::GetAttributeDef($sClass, $sExtAttCode); if (!is_null($oSyncAtt) && ($oSyncAtt instanceof SynchroAttExtKey)) @@ -2018,6 +2167,7 @@ class SynchroReplica extends DBObject implements iDisplay { // Note: differs from null (in which case the value would be left unchanged) $oStatLog->AddTrace("Could not find [unique] object for '$sExtAttCode': searched on $sReconcAttCode = '$rawValue'", $this); + $this->AddWarning("Could not find [unique] object for '$sExtAttCode': searched on $sReconcAttCode = '$rawValue'"); $retValue = 0; } } @@ -2119,6 +2269,14 @@ class SynchroReplica extends DBObject implements iDisplay } $oPage->Details($aDetails); $oPage->add(''); + $oDestObj = MetaModel::GetObject($this->Get('dest_class'), $this->Get('dest_id'), false); + if (is_object($oDestObj)) + { + $oPage->add(' | ');
$oPage->add(' |