mirror of
https://github.com/Combodo/iTop.git
synced 2026-02-13 07:24:13 +01:00
Synchro Data Sources Implementation on going...
SVN:trunk[1100]
This commit is contained in:
@@ -1068,6 +1068,22 @@ EOF
|
||||
$aEventsList[] ='change';
|
||||
$sHTMLValue = "<input title=\"$sHelpText\" class=\"date-pick\" type=\"text\" size=\"20\" name=\"attr_{$sFieldPrefix}{$sAttCode}{$sNameSuffix}\" value=\"$value\" id=\"$iId\"/> {$sValidationField}";
|
||||
break;
|
||||
|
||||
case 'Duration':
|
||||
$aEventsList[] ='validate';
|
||||
$aEventsList[] ='change';
|
||||
$oPage->add_ready_script("$('#{$iId}_d').bind('keyup change', function(evt, sFormId) { return UpdateDuration('$iId'); });");
|
||||
$oPage->add_ready_script("$('#{$iId}_h').bind('keyup change', function(evt, sFormId) { return UpdateDuration('$iId'); });");
|
||||
$oPage->add_ready_script("$('#{$iId}_m').bind('keyup change', function(evt, sFormId) { return UpdateDuration('$iId'); });");
|
||||
$oPage->add_ready_script("$('#{$iId}_s').bind('keyup change', function(evt, sFormId) { return UpdateDuration('$iId'); });");
|
||||
$aVal = AttributeDuration::SplitDuration($value);
|
||||
$sDays = "<input title=\"$sHelpText\" type=\"text\" size=\"3\" name=\"attr_{$sFieldPrefix}{$sAttCode}[d]{$sNameSuffix}\" value=\"{$aVal['days']}\" id=\"{$iId}_d\"/>";
|
||||
$sHours = "<input title=\"$sHelpText\" type=\"text\" size=\"2\" name=\"attr_{$sFieldPrefix}{$sAttCode}[h]{$sNameSuffix}\" value=\"{$aVal['hours']}\" id=\"{$iId}_h\"/>";
|
||||
$sMinutes = "<input title=\"$sHelpText\" type=\"text\" size=\"2\" name=\"attr_{$sFieldPrefix}{$sAttCode}[m]{$sNameSuffix}\" value=\"{$aVal['minutes']}\" id=\"{$iId}_m\"/>";
|
||||
$sSeconds = "<input title=\"$sHelpText\" type=\"text\" size=\"2\" name=\"attr_{$sFieldPrefix}{$sAttCode}[s]{$sNameSuffix}\" value=\"{$aVal['seconds']}\" id=\"{$iId}_s\"/>";
|
||||
$sHidden = "<input type=\"hidden\" id=\"{$iId}\" value=\"$value\"/>";
|
||||
$sHTMLValue = Dict::Format('UI:DurationForm_Days_Hours_Minutes_Seconds', $sDays, $sHours, $sMinutes, $sSeconds).$sHidden." ".$sValidationField;
|
||||
break;
|
||||
|
||||
case 'Password':
|
||||
$aEventsList[] ='validate';
|
||||
@@ -1170,7 +1186,7 @@ EOF
|
||||
}
|
||||
break;
|
||||
}
|
||||
$sPattern = addslashes($oAttDef->GetValidationPattern()); //'^([0-9]+)$';
|
||||
$sPattern = addslashes($oAttDef->GetValidationPattern()); //'^([0-9]+)$';
|
||||
if (!empty($aEventsList))
|
||||
{
|
||||
$sNullValue = $oAttDef->GetNullValue();
|
||||
@@ -1768,6 +1784,24 @@ EOF
|
||||
$this->Set($sAttCode, $rawValue);
|
||||
}
|
||||
}
|
||||
elseif ($oAttDef->GetEditClass() == 'Duration')
|
||||
{
|
||||
$rawValue = utils::ReadPostedParam("attr_{$sFormPrefix}{$sAttCode}", null);
|
||||
if (!is_array($rawValue))
|
||||
{
|
||||
$iValue = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
$iValue = (((24*$rawValue['d'])+$rawValue['h'])*60 +$rawValue['m'])*60 + $rawValue['s'];
|
||||
}
|
||||
$this->Set($sAttCode, $iValue);
|
||||
$previousValue = $this->Get($sAttCode);
|
||||
if ($previousValue !== $iValue)
|
||||
{
|
||||
$this->Set($sAttCode, $iValue);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$rawValue = utils::ReadPostedParam("attr_{$sFormPrefix}{$sAttCode}", null);
|
||||
|
||||
@@ -1619,6 +1619,82 @@ class AttributeDateTime extends AttributeDBField
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a duration as a number of seconds
|
||||
*
|
||||
* @package iTopORM
|
||||
*/
|
||||
class AttributeDuration extends AttributeInteger
|
||||
{
|
||||
public function GetEditClass() {return "Duration";}
|
||||
protected function GetSQLCol() {return "INT(11) UNSIGNED";}
|
||||
|
||||
public function GetNullValue() {return '0';}
|
||||
public function GetDefaultValue()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function MakeRealValue($proposedValue)
|
||||
{
|
||||
if (is_null($proposedValue)) return null;
|
||||
if (!is_numeric($proposedValue)) return null;
|
||||
if ( ((int)$proposedValue) < 0) return null;
|
||||
|
||||
return (int)$proposedValue;
|
||||
}
|
||||
|
||||
public function ScalarToSQL($value)
|
||||
{
|
||||
if (is_null($value))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function GetAsHTML($value)
|
||||
{
|
||||
return Str::pure2html(self::FormatDuration($value));
|
||||
}
|
||||
|
||||
static function FormatDuration($duration)
|
||||
{
|
||||
$aDuration = self::SplitDuration($duration);
|
||||
$sResult = '';
|
||||
|
||||
if ($duration < 60)
|
||||
{
|
||||
// Less than 1 min
|
||||
$sResult = Dict::Format('Core:Duration_Seconds', $aDuration['seconds']);
|
||||
}
|
||||
else if ($duration < 3600)
|
||||
{
|
||||
// less than 1 hour, display it in minutes/seconds
|
||||
$sResult = Dict::Format('Core:Duration_Minutes_Seconds', $aDuration['minutes'], $aDuration['seconds']);
|
||||
}
|
||||
else if ($duration < 86400)
|
||||
{
|
||||
// Less than 1 day, display it in hours/minutes/seconds
|
||||
$sResult = Dict::Format('Core:Duration_Hours_Minutes_Seconds', $aDuration['hours'], $aDuration['minutes'], $aDuration['seconds']);
|
||||
}
|
||||
else
|
||||
{
|
||||
// more than 1 day, display it in days/hours/minutes/seconds
|
||||
$sResult = Dict::Format('Core:Duration_Days_Hours_Minutes_Seconds', $aDuration['days'], $aDuration['hours'], $aDuration['minutes'], $aDuration['seconds']);
|
||||
}
|
||||
return $sResult;
|
||||
}
|
||||
|
||||
static function SplitDuration($duration)
|
||||
{
|
||||
$days = floor($duration / 86400);
|
||||
$hours = floor(($duration - (86400*$days)) / 3600);
|
||||
$minutes = floor(($duration - (86400*$days + 3600*$hours)) / 60);
|
||||
$seconds = ($duration % 60); // modulo
|
||||
return array( 'days' => $days, 'hours' => $hours, 'minutes' => $minutes, 'seconds' => $seconds );
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Map a date+time column to an attribute
|
||||
*
|
||||
|
||||
@@ -349,7 +349,12 @@ abstract class DBObject
|
||||
// #@# non-scalar attributes.... handle that differently
|
||||
$this->Reload();
|
||||
}
|
||||
return $this->m_aCurrValues[$sAttCode];
|
||||
$value = $this->m_aCurrValues[$sAttCode];
|
||||
if ($value instanceof DBObjectSet)
|
||||
{
|
||||
$value->Rewind();
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function GetOriginal($sAttCode)
|
||||
|
||||
@@ -537,5 +537,19 @@ Dict::Add('EN US', 'English', 'English', array(
|
||||
'Core:SynchroLogTitle' => '%1$s - %2$s',
|
||||
'Core:Synchro:Nb_Replica' => 'Replica processed: %1$s',
|
||||
'Core:Synchro:Nb_Class:Objects' => '%1$s: %2$s',
|
||||
'Class:SynchroDataSource/Error:AtLeastOneReconciliationKeyMustBeSpecified' => 'At Least one reconciliation key must be specified.',
|
||||
'Class:SynchroDataSource/Error:DeleteRetentionDurationMustBeSpecified' => 'A delete retention period must be specified, since objects are to be deleted after being marked as obsolete',
|
||||
'Class:SynchroDataSource/Error:DeletePolicyUpdateMustBeSpecified' => 'Obsolete objects are to be updated, but no update is specified.',
|
||||
));
|
||||
|
||||
//
|
||||
// Attribute Duration
|
||||
//
|
||||
Dict::Add('EN US', 'English', 'English', array(
|
||||
'Core:Duration_Seconds' => '%1$ds',
|
||||
'Core:Duration_Minutes_Seconds' =>'%1$dmin %2$ds',
|
||||
'Core:Duration_Hours_Minutes_Seconds' => '%1$dh %2$dmin %3$ds',
|
||||
'Core:Duration_Days_Hours_Minutes_Seconds' => '%1$sd %2$dh %3$dmin %4$ds',
|
||||
));
|
||||
|
||||
?>
|
||||
|
||||
@@ -400,7 +400,7 @@ Dict::Add('EN US', 'English', 'English', array(
|
||||
'UI:HistoryTab' => 'History',
|
||||
'UI:NotificationsTab' => 'Notifications',
|
||||
'UI:History:BulkImports' => 'History',
|
||||
'UI:History:BulkImports+' => 'List of CSV imports (last first)',
|
||||
'UI:History:BulkImports+' => 'List of CSV imports (latest import first)',
|
||||
'UI:History:BulkImportDetails' => 'Changes resulting from the CSV import performed on %1$s (by %2$s)',
|
||||
'UI:History:Date' => 'Date',
|
||||
'UI:History:Date+' => 'Date of the change',
|
||||
@@ -879,9 +879,7 @@ When associated with a trigger, each action is given an "order" number, specifyi
|
||||
'Portal:AddAttachment' => ' Add Attachment ',
|
||||
'Portal:RemoveAttachment' => ' Remove Attachment ',
|
||||
'Portal:Attachment_No_To_Ticket_Name' => 'Attachment #%1$d to %2$s (%3$s)',
|
||||
'Enum:Undefined' => 'Undefined',
|
||||
'Enum:Undefined' => 'Undefined',
|
||||
'UI:DurationForm_Days_Hours_Minutes_Seconds' => '%1$s Days %2$s Hours %3$s Minutes %4$s Seconds',
|
||||
));
|
||||
|
||||
|
||||
|
||||
?>
|
||||
|
||||
@@ -292,6 +292,20 @@ function ValidatePasswordField(id, sFormId)
|
||||
return true;
|
||||
}
|
||||
|
||||
// Manage a 'duration' field
|
||||
function UpdateDuration(iId)
|
||||
{
|
||||
var iDays = parseInt($('#'+iId+'_d').val(), 10);
|
||||
var iHours = parseInt($('#'+iId+'_h').val(), 10);
|
||||
var iMinutes = parseInt($('#'+iId+'_m').val(), 10);
|
||||
var iSeconds = parseInt($('#'+iId+'_s').val(), 10);
|
||||
|
||||
var iDuration = (((iDays*24)+ iHours)*60+ iMinutes)*60 + iSeconds;
|
||||
$('#'+iId).val(iDuration);
|
||||
$('#'+iId).trigger('change');
|
||||
return true;
|
||||
}
|
||||
|
||||
// Called when filling an autocomplete field
|
||||
function OnAutoComplete(id, event, data, formatted)
|
||||
{
|
||||
|
||||
@@ -57,8 +57,8 @@ class SynchroDataSource extends cmdbAbstractObject
|
||||
|
||||
//MetaModel::Init_AddAttribute(new AttributeDateTime("last_synchro_date", array("allowed_values"=>null, "sql"=>"last_synchro_date", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
|
||||
|
||||
// Format: '1 hour', '2 weeks', '3 hoursABCDEF'... Cf DateTime->Modify()
|
||||
MetaModel::Init_AddAttribute(new AttributeString("full_load_periodicity", array("allowed_values"=>null, "sql"=>"full_load_periodicity", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
|
||||
// Format: seconds (int)
|
||||
MetaModel::Init_AddAttribute(new AttributeDuration("full_load_periodicity", array("allowed_values"=>null, "sql"=>"full_load_periodicity", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
|
||||
|
||||
// MetaModel::Init_AddAttribute(new AttributeString("reconciliation_list", array("allowed_values"=>null, "sql"=>"reconciliation_list", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeEnum("reconciliation_policy", array("allowed_values"=>new ValueSetEnum('use_primary_key,use_attributes'), "sql"=>"reconciliation_policy", "default_value"=>"use_attributes", "is_null_allowed"=>false, "depends_on"=>array())));
|
||||
@@ -69,8 +69,8 @@ class SynchroDataSource extends cmdbAbstractObject
|
||||
MetaModel::Init_AddAttribute(new AttributeEnum("delete_policy", array("allowed_values"=>new ValueSetEnum('ignore,delete,update,update_then_delete'), "sql"=>"delete_policy", "default_value"=>"ignore", "is_null_allowed"=>false, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeString("delete_policy_update", array("allowed_values"=>null, "sql"=>"delete_policy_update", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
|
||||
|
||||
// Format: '1 hour', '2 weeks', '3 hoursABCDEF'... Cf DateTime->Modify()
|
||||
MetaModel::Init_AddAttribute(new AttributeString("delete_policy_retention", array("allowed_values"=>null, "sql"=>"delete_policy_retention", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
|
||||
// Format: seconds (unsigned int)
|
||||
MetaModel::Init_AddAttribute(new AttributeDuration("delete_policy_retention", array("allowed_values"=>null, "sql"=>"delete_policy_retention", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
|
||||
|
||||
MetaModel::Init_AddAttribute(new AttributeLinkedSet("attribute_list", array("linked_class"=>"SynchroAttribute", "ext_key_to_me"=>"sync_source_id", "allowed_values"=>null, "count_min"=>0, "count_max"=>0, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeLinkedSet("status_list", array("linked_class"=>"SynchroLog", "ext_key_to_me"=>"sync_source_id", "allowed_values"=>null, "count_min"=>0, "count_max"=>0, "depends_on"=>array())));
|
||||
@@ -90,6 +90,7 @@ class SynchroDataSource extends cmdbAbstractObject
|
||||
$oPage->SetCurrentTab(Dict::S('Core:SynchroAttributes'));
|
||||
$oAttributeSet = $this->Get('attribute_list');
|
||||
$aAttributes = array();
|
||||
|
||||
while($oAttribute = $oAttributeSet->Fetch())
|
||||
{
|
||||
$aAttributes[$oAttribute->Get('attcode')] = $oAttribute;
|
||||
@@ -351,6 +352,47 @@ EOF
|
||||
}
|
||||
$this->Set('attribute_list', $oAttributeSet);
|
||||
}
|
||||
|
||||
/*
|
||||
* Overload the standard behavior
|
||||
*/
|
||||
public function DoCheckToWrite()
|
||||
{
|
||||
parent::DoCheckToWrite();
|
||||
|
||||
// Check that there is at least one reconciliation key defined
|
||||
if ($this->Get('reconciliation_policy') == 'use_attributes')
|
||||
{
|
||||
$oSet = $this->Get('attribute_list');
|
||||
$oSynchroAttributeList = $oSet->ToArray();
|
||||
$bReconciliationKey = false;
|
||||
foreach($oSynchroAttributeList as $oSynchroAttribute)
|
||||
{
|
||||
if ($oSynchroAttribute->Get('reconcile') == 1)
|
||||
{
|
||||
$bReconciliationKey = true; // At least one key is defined
|
||||
}
|
||||
}
|
||||
if (!$bReconciliationKey)
|
||||
{
|
||||
$this->m_aCheckIssues[] = Dict::Format('Class:SynchroDataSource/Error:AtLeastOneReconciliationKeyMustBeSpecified');
|
||||
}
|
||||
}
|
||||
|
||||
// If 'update_then_delete' is specified there must be a delete_retention_period
|
||||
if (($this->Get('delete_policy') == 'update_then_delete') && ($this->Get('delete_policy_retention') == 0))
|
||||
{
|
||||
$this->m_aCheckIssues[] = Dict::Format('Class:SynchroDataSource/Error:DeleteRetentionDurationMustBeSpecified');
|
||||
}
|
||||
|
||||
// If update is specified, then something to update must be defined
|
||||
if ((($this->Get('delete_policy') == 'update_then_delete') || ($this->Get('delete_policy') == 'update'))
|
||||
&& ($this->Get('delete_policy_update') == ''))
|
||||
{
|
||||
$this->m_aCheckIssues[] = Dict::Format('Class:SynchroDataSource/Error:DeletePolicyUpdateMustBeSpecified');
|
||||
}
|
||||
}
|
||||
|
||||
public function GetTargetClass()
|
||||
{
|
||||
return $this->Get('scope_class');
|
||||
@@ -562,22 +604,11 @@ EOF
|
||||
{
|
||||
// No previous import known, use the full_load_periodicity value... and the current date
|
||||
$oLastFullLoadStartDate = new DateTime(); // Now
|
||||
// TO DO: how do we support localization here ??
|
||||
$sLoadPeriodicity = trim($this->Get('full_load_periodicity'));
|
||||
if (strlen($sLoadPeriodicity) > 0)
|
||||
$iLoadPeriodicity = $this->Get('full_load_periodicity'); // Duration in seconds
|
||||
if ($iLoadPeriodicity > 0)
|
||||
{
|
||||
$sInterval = '-'.$sLoadPeriodicity;
|
||||
// Note: the PHP doc states that Modify return FALSE in case of error
|
||||
// but, this is actually NOT the case
|
||||
// Therefore, I do compare before and after, considering that the
|
||||
// format is incorrect when the datetime remains unchanged
|
||||
$sBefore = $oLastFullLoadStartDate->Format('Y-m-d H:i:s');
|
||||
$sInterval = "-$iLoadPeriodicity seconds";
|
||||
$oLastFullLoadStartDate->Modify($sInterval);
|
||||
$sAfter = $oLastFullLoadStartDate->Format('Y-m-d H:i:s');
|
||||
if ($sBefore == $sAfter)
|
||||
{
|
||||
throw new SynchroExceptionNotStarted("Data exchange: Wrong interval specification", array('interval' => $sInterval, 'source_id' => $this->GetKey()));
|
||||
}
|
||||
}
|
||||
}
|
||||
$sLimitDate = $oLastFullLoadStartDate->Format('Y-m-d H:i:s');
|
||||
@@ -689,21 +720,11 @@ EOF
|
||||
if ($sDeletePolicy == 'update_then_delete')
|
||||
{
|
||||
$oDeletionDate = $oLastFullLoadStartDate;
|
||||
$sDeleteRetention = trim($this->Get('delete_policy_retention')); // MUST NOT BE NULL
|
||||
if (strlen($sDeleteRetention) > 0)
|
||||
$iDeleteRetention = $this->Get('delete_policy_retention'); // Duration in seconds
|
||||
if ($iDeleteRetention > 0)
|
||||
{
|
||||
$sInterval = '-'.$sDeleteRetention;
|
||||
// Note: the PHP doc states that Modify return FALSE in case of error
|
||||
// but, this is actually NOT the case
|
||||
// Therefore, I do compare before and after, considering that the
|
||||
// format is incorrect when the datetime remains unchanged
|
||||
$sBefore = $oDeletionDate->Format('Y-m-d H:i:s');
|
||||
$sInterval = "-$iDeleteRetention seconds";
|
||||
$oDeletionDate->Modify($sInterval);
|
||||
$sAfter = $oDeletionDate->Format('Y-m-d H:i:s');
|
||||
if ($sBefore == $sAfter)
|
||||
{
|
||||
throw new SynchroExceptionNotStarted("Data exchange: Wrong interval specification", array('interval' => $sInterval, 'source_id' => $this->GetKey()));
|
||||
}
|
||||
}
|
||||
$sDeletionDate = $oDeletionDate->Format('Y-m-d H:i:s');
|
||||
$aTraces[] = "Deletion date: $sDeletionDate";
|
||||
@@ -982,7 +1003,7 @@ class SynchroReplica extends DBObject
|
||||
|
||||
MetaModel::Init_AddAttribute(new AttributeExternalKey("sync_source_id", array("targetclass"=>"SynchroDataSource", "jointype"=> "", "allowed_values"=>null, "sql"=>"sync_source_id", "is_null_allowed"=>false, "on_target_delete"=>DEL_AUTO, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeInteger("dest_id", array("allowed_values"=>null, "sql"=>"dest_id", "default_value"=>0, "is_null_allowed"=>true, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeClass("dest_class", array("class_category"=>"bizmodel", "more_values"=>"", "sql"=>"dest_class", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeClass("dest_class", array("class_category"=>"bizmodel", "more_values"=>"", "sql"=>"dest_class", "default_value"=>'Organization', "is_null_allowed"=>true, "depends_on"=>array())));
|
||||
|
||||
MetaModel::Init_AddAttribute(new AttributeDateTime("status_last_seen", array("allowed_values"=>null, "sql"=>"status_last_seen", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
|
||||
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())));
|
||||
|
||||
Reference in New Issue
Block a user