mirror of
https://github.com/Combodo/iTop.git
synced 2026-02-17 01:14:14 +01:00
Compare commits
94 Commits
2.0.3
...
2.1.0-beta
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1bde9def1d | ||
|
|
f62934829d | ||
|
|
dee7f7b7aa | ||
|
|
1d0bfa7c92 | ||
|
|
8922c435b4 | ||
|
|
ec1ec854fb | ||
|
|
dfc248b836 | ||
|
|
481d05d082 | ||
|
|
4e4d3cf3da | ||
|
|
5fc68557dc | ||
|
|
7482a52fd9 | ||
|
|
50ca6cdd0f | ||
|
|
e83e1262a5 | ||
|
|
51bd403638 | ||
|
|
c786e8308a | ||
|
|
a7d3a5a488 | ||
|
|
2c70c60d2b | ||
|
|
96f02d1557 | ||
|
|
de6ddffe65 | ||
|
|
2c59fb894f | ||
|
|
77cf399c72 | ||
|
|
19a2180c2b | ||
|
|
18b73de512 | ||
|
|
bb741c39f4 | ||
|
|
c73ef6ae72 | ||
|
|
5abd9c6dad | ||
|
|
a6db04bafd | ||
|
|
04f46f4798 | ||
|
|
5ecf6b9e9d | ||
|
|
0135573956 | ||
|
|
a59915e5ee | ||
|
|
ebb3767ee4 | ||
|
|
047166f002 | ||
|
|
f45c783396 | ||
|
|
72f516685e | ||
|
|
2b4400c55d | ||
|
|
1df87b6331 | ||
|
|
cd7490472e | ||
|
|
b65131e4f5 | ||
|
|
fac8604cc6 | ||
|
|
e25da2a7c4 | ||
|
|
6d9e7f690f | ||
|
|
9c62952743 | ||
|
|
03c4964072 | ||
|
|
711949414d | ||
|
|
055a87306e | ||
|
|
37ebb51a2b | ||
|
|
1f8d4d379f | ||
|
|
1300811007 | ||
|
|
fbdd0dfd57 | ||
|
|
bc79663a3e | ||
|
|
570e4f8589 | ||
|
|
472802e11b | ||
|
|
f794d0222e | ||
|
|
b42a43d47b | ||
|
|
110aace270 | ||
|
|
68dd0513c6 | ||
|
|
08e757a08a | ||
|
|
996c590793 | ||
|
|
c93cc3a5bf | ||
|
|
bdccf6ea72 | ||
|
|
ed60346ae6 | ||
|
|
4953ea7701 | ||
|
|
82a8a0bba7 | ||
|
|
55c818b6b7 | ||
|
|
372c0835f7 | ||
|
|
52a028301f | ||
|
|
61b88d2689 | ||
|
|
fa856c32cd | ||
|
|
6d693bbfc7 | ||
|
|
7117b751b3 | ||
|
|
c30a88c9ef | ||
|
|
c1085fc398 | ||
|
|
42ac871f8e | ||
|
|
b1a404d909 | ||
|
|
ba82031a59 | ||
|
|
c8568af43b | ||
|
|
7ed60f711c | ||
|
|
e831b1a486 | ||
|
|
b5db86472d | ||
|
|
ed9ba815ab | ||
|
|
7b47e8c480 | ||
|
|
d2cd758ecc | ||
|
|
d2ea4023c2 | ||
|
|
f0ee5112b9 | ||
|
|
ada70b97d4 | ||
|
|
a546b39301 | ||
|
|
8f2cd66bf6 | ||
|
|
868d0d1b19 | ||
|
|
7d619f278e | ||
|
|
fd9008a163 | ||
|
|
357ae4abb1 | ||
|
|
2108a74f87 | ||
|
|
165d01e2a2 |
@@ -430,7 +430,7 @@ class URP_ActionGrant extends UserRightsBaseClass
|
||||
//MetaModel::Init_InheritAttributes();
|
||||
|
||||
// Common to all grant classes (could be factorized by class inheritence, but this has to be benchmarked)
|
||||
MetaModel::Init_AddAttribute(new AttributeExternalKey("profileid", array("targetclass"=>"URP_Profiles", "jointype"=> "", "allowed_values"=>null, "sql"=>"profileid", "is_null_allowed"=>false, "on_target_delete"=>DEL_MANUAL, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeExternalKey("profileid", array("targetclass"=>"URP_Profiles", "jointype"=> "", "allowed_values"=>null, "sql"=>"profileid", "is_null_allowed"=>false, "on_target_delete"=>DEL_SILENT, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeExternalField("profile", array("allowed_values"=>null, "extkey_attcode"=> 'profileid', "target_attcode"=>"name")));
|
||||
MetaModel::Init_AddAttribute(new AttributeClass("class", array("class_category"=>"", "more_values"=>"", "sql"=>"class", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeEnum("permission", array("allowed_values"=>new ValueSetEnum('yes,no'), "sql"=>"permission", "default_value"=>"yes", "is_null_allowed"=>false, "depends_on"=>array())));
|
||||
@@ -467,7 +467,7 @@ class URP_StimulusGrant extends UserRightsBaseClass
|
||||
//MetaModel::Init_InheritAttributes();
|
||||
|
||||
// Common to all grant classes (could be factorized by class inheritence, but this has to be benchmarked)
|
||||
MetaModel::Init_AddAttribute(new AttributeExternalKey("profileid", array("targetclass"=>"URP_Profiles", "jointype"=> "", "allowed_values"=>null, "sql"=>"profileid", "is_null_allowed"=>false, "on_target_delete"=>DEL_MANUAL, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeExternalKey("profileid", array("targetclass"=>"URP_Profiles", "jointype"=> "", "allowed_values"=>null, "sql"=>"profileid", "is_null_allowed"=>false, "on_target_delete"=>DEL_SILENT, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeExternalField("profile", array("allowed_values"=>null, "extkey_attcode"=> 'profileid', "target_attcode"=>"name")));
|
||||
MetaModel::Init_AddAttribute(new AttributeClass("class", array("class_category"=>"", "more_values"=>"", "sql"=>"class", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeEnum("permission", array("allowed_values"=>new ValueSetEnum('yes,no'), "sql"=>"permission", "default_value"=>"yes", "is_null_allowed"=>false, "depends_on"=>array())));
|
||||
@@ -503,7 +503,7 @@ class URP_AttributeGrant extends UserRightsBaseClass
|
||||
MetaModel::Init_Params($aParams);
|
||||
//MetaModel::Init_InheritAttributes();
|
||||
|
||||
MetaModel::Init_AddAttribute(new AttributeExternalKey("actiongrantid", array("targetclass"=>"URP_ActionGrant", "jointype"=> "", "allowed_values"=>null, "sql"=>"actiongrantid", "is_null_allowed"=>false, "on_target_delete"=>DEL_MANUAL, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeExternalKey("actiongrantid", array("targetclass"=>"URP_ActionGrant", "jointype"=> "", "allowed_values"=>null, "sql"=>"actiongrantid", "is_null_allowed"=>false, "on_target_delete"=>DEL_SILENT, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeString("attcode", array("allowed_values"=>null, "sql"=>"attcode", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
|
||||
|
||||
// Display lists
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
// Copyright (C) 2010-2012 Combodo SARL
|
||||
// Copyright (C) 2010-2014 Combodo SARL
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
@@ -225,9 +225,8 @@ EOF
|
||||
EOF
|
||||
);
|
||||
}
|
||||
$s_captured_output = ob_get_contents();
|
||||
ob_end_clean();
|
||||
if (($this->sContentType == 'text/html') && ($this->sContentDisposition == 'inline'))
|
||||
$s_captured_output = $this->ob_get_clean_safe();
|
||||
if (($this->sContentType == 'text/html') && ($this->sContentDisposition == 'inline'))
|
||||
{
|
||||
// inline content != attachment && html => filter all scripts for malicious XSS scripts
|
||||
echo self::FilterXSS($this->s_content);
|
||||
@@ -393,4 +392,3 @@ EOF
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
@@ -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 = "<a href=\"$sApplicationURL\" target=\"_blank\">".$aData['datasource']->GetName()."</a>";
|
||||
$sLink = "<a href=\"$sApplicationURL\" target=\"_blank\">".$oDataSource->GetName()."</a>";
|
||||
}
|
||||
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))
|
||||
@@ -941,12 +943,12 @@ abstract class cmdbAbstractObject extends CMDBObject implements iDisplay
|
||||
return $oDataTable->Display($oPage, $oSettings, $bDisplayMenu, $sSelectMode, $bViewLink, $aExtraParams);
|
||||
}
|
||||
|
||||
static function DisplaySetAsCSV(WebPage $oPage, CMDBObjectSet $oSet, $aParams = array())
|
||||
static function DisplaySetAsCSV(WebPage $oPage, CMDBObjectSet $oSet, $aParams = array(), $sCharset = 'UTF-8')
|
||||
{
|
||||
$oPage->add(self::GetSetAsCSV($oSet, $aParams));
|
||||
$oPage->add(self::GetSetAsCSV($oSet, $aParams, $sCharset));
|
||||
}
|
||||
|
||||
static function GetSetAsCSV(DBObjectSet $oSet, $aParams = array())
|
||||
static function GetSetAsCSV(DBObjectSet $oSet, $aParams = array(), $sCharset = 'UTF-8')
|
||||
{
|
||||
$sSeparator = isset($aParams['separator']) ? $aParams['separator'] : ','; // default separator is comma
|
||||
$sTextQualifier = isset($aParams['text_qualifier']) ? $aParams['text_qualifier'] : '"'; // default text qualifier is double quote
|
||||
@@ -1064,7 +1066,8 @@ abstract class cmdbAbstractObject extends CMDBObject implements iDisplay
|
||||
else
|
||||
{
|
||||
$value = $oObj->Get($sAttCodeEx);
|
||||
$aRow[] = $oAttDef->GetAsCSV($value, $sSeparator, $sTextQualifier, $oObj, $bLocalize);
|
||||
$sCSVValue = $oAttDef->GetAsCSV($value, $sSeparator, $sTextQualifier, $oObj, $bLocalize);
|
||||
$aRow[] = iconv('UTF-8', $sCharset.'//IGNORE//TRANSLIT', $sCSVValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1401,6 +1404,8 @@ abstract class cmdbAbstractObject extends CMDBObject implements iDisplay
|
||||
$sHtml .= "<p>\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']);
|
||||
@@ -1428,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);
|
||||
@@ -1436,20 +1442,24 @@ abstract class cmdbAbstractObject extends CMDBObject implements iDisplay
|
||||
}
|
||||
|
||||
$oAttDef = MetaModel::GetAttributeDef($sClassName, $sFilterCode);
|
||||
if ($oAttDef->IsExternalKey())
|
||||
if ($oAttDef->IsExternalKey(EXTKEY_ABSOLUTE))
|
||||
{
|
||||
$sTargetClass = $oAttDef->GetTargetClass();
|
||||
$oKeyAttDef = $oAttDef->GetFinalAttDef();
|
||||
$sKeyAttClass = $oKeyAttDef->GetHostClass();
|
||||
$sKeyAttCode = $oKeyAttDef->GetCode();
|
||||
|
||||
$sTargetClass = $oKeyAttDef->GetTargetClass();
|
||||
$oSearch = new DBObjectSearch($sTargetClass);
|
||||
$oSearch->SetModifierProperty('UserRightsGetSelectFilter', 'bSearchMode', true);
|
||||
$oAllowedValues = new DBObjectSet($oSearch);
|
||||
|
||||
$iFieldSize = $oAttDef->GetMaxSize();
|
||||
$iMaxComboLength = $oAttDef->GetMaximumComboLength();
|
||||
$sHtml .= "<label>".MetaModel::GetFilterLabel($sClassName, $sFilterCode).":</label> ";
|
||||
$iFieldSize = $oKeyAttDef->GetMaxSize();
|
||||
$iMaxComboLength = $oKeyAttDef->GetMaximumComboLength();
|
||||
$sHtml .= "<label>".MetaModel::GetFilterLabel($sKeyAttClass, $sKeyAttCode).":</label> ";
|
||||
$aExtKeyParams = $aExtraParams;
|
||||
$aExtKeyParams['iFieldSize'] = $oAttDef->GetMaxSize();
|
||||
$aExtKeyParams['iMinChars'] = $oAttDef->GetMinAutoCompleteChars();
|
||||
$sHtml .= UIExtKeyWidget::DisplayFromAttCode($oPage, $sFilterCode, $sClassName, $oAttDef->GetLabel(), $oAllowedValues, $sFilterValue, $sSearchFormId.'search_'.$sFilterCode, false, $sFilterCode, '', $aExtKeyParams, true);
|
||||
$aExtKeyParams['iFieldSize'] = $oKeyAttDef->GetMaxSize();
|
||||
$aExtKeyParams['iMinChars'] = $oKeyAttDef->GetMinAutoCompleteChars();
|
||||
$sHtml .= UIExtKeyWidget::DisplayFromAttCode($oPage, $sKeyAttCode, $sKeyAttClass, $oAttDef->GetLabel(), $oAllowedValues, $sFilterValue, $sSearchFormId.'search_'.$sFilterCode, false, $sFilterCode, '', $aExtKeyParams, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1844,14 +1854,19 @@ abstract class cmdbAbstractObject extends CMDBObject implements iDisplay
|
||||
{
|
||||
$sNullValue = "'$sNullValue'"; // Add quotes to turn this into a JS string if it's not a number
|
||||
}
|
||||
$oPage->add_ready_script("$('#$iId').bind('".implode(' ', $aEventsList)."', function(evt, sFormId) { return ValidateField('$iId', '$sPattern', $bMandatory, sFormId, $sNullValue) } );\n"); // Bind to a custom event: validate
|
||||
$sOriginalValue = ($iFlags & OPT_ATT_MUSTCHANGE) ? "'".addslashes($value)."'" : 'undefined';
|
||||
$oPage->add_ready_script("$('#$iId').bind('".implode(' ', $aEventsList)."', function(evt, sFormId) { return ValidateField('$iId', '$sPattern', $bMandatory, sFormId, $sNullValue, $sOriginalValue) } );\n"); // Bind to a custom event: validate
|
||||
}
|
||||
$aDependencies = MetaModel::GetDependentAttributes($sClass, $sAttCode); // List of attributes that depend on the current one
|
||||
if (count($aDependencies) > 0)
|
||||
{
|
||||
$oPage->add_ready_script("$('#$iId').bind('change', function(evt, sFormId) { return oWizardHelper{$sFormPrefix}.UpdateDependentFields(['".implode("','", $aDependencies)."']) } );\n"); // Bind to a custom event: validate
|
||||
// Unbind first to avoid duplicate event handlers in case of reload of the whole (or part of the) form
|
||||
$oPage->add_ready_script("$('#$iId').unbind('change.dependencies').bind('change.dependencies', function(evt, sFormId) { return oWizardHelper{$sFormPrefix}.UpdateDependentFields(['".implode("','", $aDependencies)."']) } );\n"); // Bind to a custom event: validate
|
||||
}
|
||||
}
|
||||
$oPage->add_dict_entry('UI:ValueMustBeSet');
|
||||
$oPage->add_dict_entry('UI:ValueMustBeChanged');
|
||||
$oPage->add_dict_entry('UI:ValueInvalidFormat');
|
||||
return "<div>{$sHTMLValue}</div>";
|
||||
}
|
||||
|
||||
@@ -2460,7 +2475,7 @@ EOF
|
||||
{
|
||||
// Possible return values are:
|
||||
// HILIGHT_CLASS_CRITICAL, HILIGHT_CLASS_WARNING, HILIGHT_CLASS_OK, HILIGHT_CLASS_NONE
|
||||
$current = HILIGHT_CLASS_NONE; // Not hilighted by default
|
||||
$current = parent::GetHilightClass(); // Default computation
|
||||
|
||||
// Invoke extensions before the deletion (the deletion will do some cleanup and we might loose some information
|
||||
foreach (MetaModel::EnumPlugins('iApplicationUIExtension') as $oExtensionInstance)
|
||||
@@ -3074,7 +3089,7 @@ EOF
|
||||
|
||||
// Attribute is read-only
|
||||
$sHTMLValue = $this->GetAsHTML($sAttCode);
|
||||
$sHTMLValue .= '<input type="hidden" id="'.$sInputId.'" name="attr_'.$sPrefix.$sAttCode.'" value="'.htmlentities($this->Get($sAttCode), ENT_QUOTES, 'UTF-8').'"/>';
|
||||
$sHTMLValue .= '<input type="hidden" id="'.$sInputId.'" name="attr_'.$sPrefix.$sAttCode.'" value="'.htmlentities($this->GetEditValue($sAttCode), ENT_QUOTES, 'UTF-8').'"/>';
|
||||
$aFieldsMap[$sAttCode] = $sInputId;
|
||||
$sComment .= $sSynchroIcon;
|
||||
}
|
||||
@@ -3251,7 +3266,11 @@ EOF
|
||||
$currValue = $aKeys[0]; // The only value is the first key
|
||||
//echo "<p>current value for $sAttCode : $currValue</p>";
|
||||
$oDummyObj->Set($sAttCode, $currValue);
|
||||
$aComments[$sAttCode] = '<input type="checkbox" checked id="enable_'.$iFormId.'_'.$sAttCode.'" onClick="ToogleField(this.checked, \''.$iFormId.'_'.$sAttCode.'\')"/>';
|
||||
$aComments[$sAttCode] = '';
|
||||
if ($sAttCode != MetaModel::GetStateAttributeCode($sClass))
|
||||
{
|
||||
$aComments[$sAttCode] .= '<input type="checkbox" checked id="enable_'.$iFormId.'_'.$sAttCode.'" onClick="ToogleField(this.checked, \''.$iFormId.'_'.$sAttCode.'\')"/>';
|
||||
}
|
||||
$aComments[$sAttCode] .= '<div class="mono_value">1</div>';
|
||||
}
|
||||
else
|
||||
@@ -3278,7 +3297,11 @@ EOF
|
||||
$sReadyScript .= "$('#multi_values_$sAttCode').qtip( { content: '$sTip', show: 'mouseover', hide: 'mouseout', style: { name: 'dark', tip: 'leftTop' }, position: { corner: { target: 'rightMiddle', tooltip: 'leftTop' }} } );";
|
||||
|
||||
$oDummyObj->Set($sAttCode, null);
|
||||
$aComments[$sAttCode] = '<input type="checkbox" id="enable_'.$iFormId.'_'.$sAttCode.'" onClick="ToogleField(this.checked, \''.$iFormId.'_'.$sAttCode.'\')"/>';
|
||||
$aComments[$sAttCode] = '';
|
||||
if ($sAttCode != MetaModel::GetStateAttributeCode($sClass))
|
||||
{
|
||||
$aComments[$sAttCode] .= '<input type="checkbox" id="enable_'.$iFormId.'_'.$sAttCode.'" onClick="ToogleField(this.checked, \''.$iFormId.'_'.$sAttCode.'\')"/>';
|
||||
}
|
||||
$aComments[$sAttCode] .= '<div class="multi_values" id="multi_values_'.$sAttCode.'">'.$iCount.'</div>';
|
||||
}
|
||||
$sReadyScript .= 'ToogleField('.(($iCount == 1) ? 'true': 'false').', \''.$iFormId.'_'.$sAttCode.'\');'."\n";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
// Copyright (C) 2010-2012 Combodo SARL
|
||||
// Copyright (C) 2010-2014 Combodo SARL
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
@@ -39,7 +39,11 @@ class CSVPage extends WebPage
|
||||
|
||||
public function output()
|
||||
{
|
||||
$this->add_header("Content-Length: ".strlen(trim($this->s_content)));
|
||||
$this->add_header("Content-Length: ".strlen(trim($this->s_content)));
|
||||
|
||||
// Get the unexpected output but do nothing with it
|
||||
$sTrash = $this->ob_get_clean_safe();
|
||||
|
||||
foreach($this->a_headers as $s_header)
|
||||
{
|
||||
header($s_header);
|
||||
@@ -105,4 +109,3 @@ class CSVPage extends WebPage
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
@@ -506,11 +506,19 @@ abstract class DashletGroupBy extends Dashlet
|
||||
$sGroupBy = $this->aProperties['group_by'];
|
||||
$sStyle = $this->aProperties['style'];
|
||||
|
||||
// First perform the query - if the OQL is not ok, it will generate an exception : no need to go further
|
||||
$oQuery = $this->oModelReflection->GetQuery($sQuery);
|
||||
$sClass = $oQuery->GetClass();
|
||||
$sClassAlias = $oQuery->GetClassAlias();
|
||||
|
||||
// First perform the query - if the OQL is not ok, it will generate an exception : no need to go further
|
||||
try
|
||||
{
|
||||
$oQuery = $this->oModelReflection->GetQuery($sQuery);
|
||||
$sClass = $oQuery->GetClass();
|
||||
$sClassAlias = $oQuery->GetClassAlias();
|
||||
}
|
||||
catch(Exception $e)
|
||||
{
|
||||
// Invalid query, let the user edit the dashlet/dashboard anyhow
|
||||
$sClass = '';
|
||||
$sClassAlias = '';
|
||||
}
|
||||
// Check groupby... it can be wrong at this stage
|
||||
if (preg_match('/^(.*):(.*)$/', $sGroupBy, $aMatches))
|
||||
{
|
||||
|
||||
@@ -551,6 +551,7 @@ EOF;
|
||||
$oPage->add_ready_script(
|
||||
<<<EOF
|
||||
var oTable = $('#{$this->iListId} table.listResults');
|
||||
oTable.tableHover();
|
||||
oTable.tablesorter( { $sHeaders widgets: ['myZebra', 'truncatedList']} ).tablesorterPager({container: $('#pager{$this->iListId}'), totalRows:$iCount, size: $iPageSize, filter: '$sOQL', extra_params: '$sExtraParams', select_mode: '$sSelectModeJS', displayKey: $sDisplayKey, columns: $sJSColumns, class_aliases: $sJSClassAliases $sCssCount});
|
||||
EOF
|
||||
);
|
||||
|
||||
@@ -783,7 +783,8 @@ class DisplayBlock
|
||||
$sLinkToToggle = $sLinkToToggle.'&advanced=1';
|
||||
$sChecked = '';
|
||||
}
|
||||
|
||||
$sAjaxLink = $sDownloadLink.'&charset=UTF-8'; // Includes &fields_advanced=1 if in advanced mode
|
||||
|
||||
/*
|
||||
$sCSVData = cmdbAbstractObject::GetSetAsCSV($this->m_oSet, array('fields_advanced' => $bAdvancedMode));
|
||||
$sCharset = MetaModel::GetConfig()->Get('csv_file_default_charset');
|
||||
@@ -833,7 +834,7 @@ class DisplayBlock
|
||||
$sHtml .= "<div id=\"csv_content_loading\"><div style=\"width: 250px; height: 20px; background: url(../setup/orange-progress.gif); border: 1px #999 solid; margin-left:auto; margin-right: auto; text-align: center;\">".Dict::S('UI:Loading')."</div></div><textarea id=\"csv_content\" style=\"display:none;\">\n";
|
||||
//$sHtml .= htmlentities($sCSVData, ENT_QUOTES, 'UTF-8');
|
||||
$sHtml .= "</textarea>\n";
|
||||
$oPage->add_ready_script("$.post('$sDownloadLink', {}, function(data) { $('#csv_content').html(data); $('#csv_content_loading').hide(); $('#csv_content').show();} );");
|
||||
$oPage->add_ready_script("$.post('$sAjaxLink', {}, function(data) { $('#csv_content').html(data); $('#csv_content_loading').hide(); $('#csv_content').show();} );");
|
||||
break;
|
||||
|
||||
case 'modify':
|
||||
|
||||
536
application/excelexporter.class.inc.php
Normal file
536
application/excelexporter.class.inc.php
Normal file
@@ -0,0 +1,536 @@
|
||||
<?php
|
||||
require_once('xlsxwriter.class.php');
|
||||
|
||||
class ExcelExporter
|
||||
{
|
||||
protected $sToken;
|
||||
protected $aStatistics;
|
||||
protected $sState;
|
||||
protected $fStartTime;
|
||||
protected $oSearch;
|
||||
protected $aObjectsIDs;
|
||||
protected $aTableHeaders;
|
||||
protected $aAuthorizedClasses;
|
||||
protected $iChunkSize = 1000;
|
||||
protected $iPosition;
|
||||
protected $sOutputFilePath;
|
||||
protected $bAdvancedMode;
|
||||
|
||||
public function __construct($sToken = null)
|
||||
{
|
||||
$this->aStatistics = array(
|
||||
'objects_count' => 0,
|
||||
'total_duration' => 0,
|
||||
'data_retrieval_duration' => 0,
|
||||
'excel_build_duration' => 0,
|
||||
'excel_write_duration' => 0,
|
||||
'peak_memory_usage' => 0,
|
||||
);
|
||||
$this->fStartTime = microtime(true);
|
||||
$this->oSearch = null;
|
||||
|
||||
$this->sState = 'new';
|
||||
$this->aObjectsIDs = array();
|
||||
$this->iPosition = 0;
|
||||
$this->aAuthorizedClasses = null;
|
||||
$this->aTableHeaders = null;
|
||||
$this->sOutputFilePath = null;
|
||||
$this->bAdvancedMode = false;
|
||||
$this->CheckDataDir();
|
||||
if ($sToken == null)
|
||||
{
|
||||
$this->sToken = $this->GetNewToken();
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->sToken = $sToken;
|
||||
$this->ReloadState();
|
||||
}
|
||||
}
|
||||
|
||||
public function __destruct()
|
||||
{
|
||||
if (($this->sState != 'done') && ($this->sState != 'error') && ($this->sToken != null))
|
||||
{
|
||||
// Operation in progress, save the state
|
||||
$this->SaveState();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Operation completed, cleanup the temp files
|
||||
@unlink($this->GetStateFile());
|
||||
@unlink($this->GetDataFile());
|
||||
}
|
||||
self::CleanupOldFiles();
|
||||
}
|
||||
|
||||
public function SetChunkSize($iChunkSize)
|
||||
{
|
||||
$this->iChunkSize = $iChunkSize;
|
||||
}
|
||||
|
||||
public function SetOutputFilePath($sDestFilePath)
|
||||
{
|
||||
$this->sOutputFilePath = $sDestFilePath;
|
||||
}
|
||||
|
||||
public function SetAdvancedMode($bAdvanced)
|
||||
{
|
||||
$this->bAdvancedMode = $bAdvanced;
|
||||
}
|
||||
|
||||
public function SaveState()
|
||||
{
|
||||
$aState = array(
|
||||
'state' => $this->sState,
|
||||
'statistics' => $this->aStatistics,
|
||||
'filter' => $this->oSearch->serialize(),
|
||||
'position' => $this->iPosition,
|
||||
'chunk_size' => $this->iChunkSize,
|
||||
'object_ids' => $this->aObjectsIDs,
|
||||
'output_file_path' => $this->sOutputFilePath,
|
||||
'advanced_mode' => $this->bAdvancedMode,
|
||||
);
|
||||
|
||||
file_put_contents($this->GetStateFile(), json_encode($aState));
|
||||
|
||||
return $this->sToken;
|
||||
}
|
||||
|
||||
public function ReloadState()
|
||||
{
|
||||
if ($this->sToken == null)
|
||||
{
|
||||
throw new Exception('ExcelExporter not initialized with a token, cannot reload state');
|
||||
}
|
||||
|
||||
if (!file_exists($this->GetStateFile()))
|
||||
{
|
||||
throw new Exception("ExcelExporter: missing status file '".$this->GetStateFile()."', cannot reload state.");
|
||||
}
|
||||
$sJson = file_get_contents($this->GetStateFile());
|
||||
$aState = json_decode($sJson, true);
|
||||
if ($aState === null)
|
||||
{
|
||||
throw new Exception("ExcelExporter:corrupted status file '".$this->GetStateFile()."', not a JSON, cannot reload state.");
|
||||
}
|
||||
|
||||
$this->sState = $aState['state'];
|
||||
$this->aStatistics = $aState['statistics'];
|
||||
$this->oSearch = DBObjectSearch::unserialize($aState['filter']);
|
||||
$this->iPosition = $aState['position'];
|
||||
$this->iChunkSize = $aState['chunk_size'];
|
||||
$this->aObjectsIDs = $aState['object_ids'];
|
||||
$this->sOutputFilePath = $aState['output_file_path'];
|
||||
$this->bAdvancedMode = $aState['advanced_mode'];
|
||||
}
|
||||
|
||||
public function SetObjectList($oSearch)
|
||||
{
|
||||
$this->oSearch = $oSearch;
|
||||
}
|
||||
|
||||
public function Run()
|
||||
{
|
||||
$sCode = 'error';
|
||||
$iPercentage = 100;
|
||||
$sMessage = Dict::Format('ExcelExporter:ErrorUnexpected_State', $this->sState);
|
||||
$fTime = microtime(true);
|
||||
|
||||
try
|
||||
{
|
||||
switch($this->sState)
|
||||
{
|
||||
case 'new':
|
||||
$oIDSet = new DBObjectSet($this->oSearch);
|
||||
$oIDSet->OptimizeColumnLoad(array('id'));
|
||||
$this->aObjectsIDs = array();
|
||||
while($oObj = $oIDSet->Fetch())
|
||||
{
|
||||
$this->aObjectsIDs[] = $oObj->GetKey();
|
||||
}
|
||||
$sCode = 'retrieving-data';
|
||||
$iPercentage = 5;
|
||||
$sMessage = Dict::S('ExcelExporter:RetrievingData');
|
||||
$this->iPosition = 0;
|
||||
$this->aStatistics['objects_count'] = count($this->aObjectsIDs);
|
||||
$this->aStatistics['data_retrieval_duration'] += microtime(true) - $fTime;
|
||||
|
||||
// The first line of the file is the "headers" specifying the label and the type of each column
|
||||
$this->GetFieldsList($oIDSet, $this->bAdvancedMode);
|
||||
$sRow = json_encode($this->aTableHeaders);
|
||||
$hFile = @fopen($this->GetDataFile(), 'ab');
|
||||
if ($hFile === false)
|
||||
{
|
||||
throw new Exception('ExcelExporter: Failed to open temporary data file: "'.$this->GetDataFile().'" for writing.');
|
||||
}
|
||||
fwrite($hFile, $sRow."\n");
|
||||
fclose($hFile);
|
||||
|
||||
// Next state
|
||||
$this->sState = 'retrieving-data';
|
||||
break;
|
||||
|
||||
case 'retrieving-data':
|
||||
$oCurrentSearch = clone $this->oSearch;
|
||||
$aIDs = array_slice($this->aObjectsIDs, $this->iPosition, $this->iChunkSize);
|
||||
|
||||
$oCurrentSearch->AddCondition('id', $aIDs, 'IN');
|
||||
$hFile = @fopen($this->GetDataFile(), 'ab');
|
||||
if ($hFile === false)
|
||||
{
|
||||
throw new Exception('ExcelExporter: Failed to open temporary data file: "'.$this->GetDataFile().'" for writing.');
|
||||
}
|
||||
$oSet = new DBObjectSet($oCurrentSearch);
|
||||
$this->GetFieldsList($oSet, $this->bAdvancedMode);
|
||||
while($aObjects = $oSet->FetchAssoc())
|
||||
{
|
||||
$aRow = array();
|
||||
foreach($this->aAuthorizedClasses as $sAlias => $sClassName)
|
||||
{
|
||||
$oObj = $aObjects[$sAlias];
|
||||
if ($this->bAdvancedMode)
|
||||
{
|
||||
$aRow[] = $oObj->GetKey();
|
||||
}
|
||||
foreach($this->aFieldsList[$sAlias] as $sAttCodeEx => $oAttDef)
|
||||
{
|
||||
$value = $oObj->Get($sAttCodeEx);
|
||||
if ($value instanceOf ormCaseLog)
|
||||
{
|
||||
// Extract the case log as text and remove the "===" which make Excel think that the cell contains a formula the next time you edit it!
|
||||
$sExcelVal = trim(preg_replace('/========== ([^=]+) ============/', '********** $1 ************', $value->GetText()));
|
||||
}
|
||||
else
|
||||
{
|
||||
$sExcelVal = $oAttDef->GetEditValue($value, $oObj);
|
||||
}
|
||||
$aRow[] = $sExcelVal;
|
||||
}
|
||||
}
|
||||
$sRow = json_encode($aRow);
|
||||
fwrite($hFile, $sRow."\n");
|
||||
}
|
||||
fclose($hFile);
|
||||
|
||||
if (($this->iPosition + $this->iChunkSize) > count($this->aObjectsIDs))
|
||||
{
|
||||
// Next state
|
||||
$this->sState = 'building-excel';
|
||||
$sCode = 'building-excel';
|
||||
$iPercentage = 80;
|
||||
$sMessage = Dict::S('ExcelExporter:BuildingExcelFile');
|
||||
}
|
||||
else
|
||||
{
|
||||
$sCode = 'retrieving-data';
|
||||
$this->iPosition += $this->iChunkSize;
|
||||
$iPercentage = 5 + round(75 * ($this->iPosition / count($this->aObjectsIDs)));
|
||||
$sMessage = Dict::S('ExcelExporter:RetrievingData');
|
||||
}
|
||||
break;
|
||||
|
||||
case 'building-excel':
|
||||
$hFile = @fopen($this->GetDataFile(), 'rb');
|
||||
if ($hFile === false)
|
||||
{
|
||||
throw new Exception('ExcelExporter: Failed to open temporary data file: "'.$this->GetDataFile().'" for reading.');
|
||||
}
|
||||
$sHeaders = fgets($hFile);
|
||||
$aHeaders = json_decode($sHeaders, true);
|
||||
|
||||
$aData = array();
|
||||
while($sLine = fgets($hFile))
|
||||
{
|
||||
$aRow = json_decode($sLine);
|
||||
$aData[] = $aRow;
|
||||
}
|
||||
fclose($hFile);
|
||||
@unlink($this->GetDataFile());
|
||||
|
||||
$fStartExcel = microtime(true);
|
||||
$writer = new XLSXWriter();
|
||||
$writer->setAuthor(UserRights::GetUserFriendlyName());
|
||||
$writer->writeSheet($aData,'Sheet1', $aHeaders);
|
||||
$fExcelTime = microtime(true) - $fStartExcel;
|
||||
$this->aStatistics['excel_build_duration'] = $fExcelTime;
|
||||
|
||||
$fTime = microtime(true);
|
||||
$writer->writeToFile($this->GetExcelFilePath());
|
||||
$fExcelSaveTime = microtime(true) - $fTime;
|
||||
$this->aStatistics['excel_write_duration'] = $fExcelSaveTime;
|
||||
|
||||
// Next state
|
||||
$this->sState = 'done';
|
||||
$sCode = 'done';
|
||||
$iPercentage = 100;
|
||||
$sMessage = Dict::S('ExcelExporter:Done');
|
||||
break;
|
||||
|
||||
case 'done':
|
||||
$this->sState = 'done';
|
||||
$sCode = 'done';
|
||||
$iPercentage = 100;
|
||||
$sMessage = Dict::S('ExcelExporter:Done');
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch(Exception $e)
|
||||
{
|
||||
$sCode = 'error';
|
||||
$sMessage = $e->getMessage();
|
||||
}
|
||||
|
||||
$this->aStatistics['total_duration'] += microtime(true) - $fTime;
|
||||
$peak_memory = memory_get_peak_usage(true);
|
||||
if ($peak_memory > $this->aStatistics['peak_memory_usage'])
|
||||
{
|
||||
$this->aStatistics['peak_memory_usage'] = $peak_memory;
|
||||
}
|
||||
|
||||
return array(
|
||||
'code' => $sCode,
|
||||
'message' => $sMessage,
|
||||
'percentage' => $iPercentage,
|
||||
);
|
||||
}
|
||||
|
||||
public function GetExcelFilePath()
|
||||
{
|
||||
if ($this->sOutputFilePath == null)
|
||||
{
|
||||
return APPROOT.'data/bulk_export/'.$this->sToken.'.xlsx';
|
||||
}
|
||||
else
|
||||
{
|
||||
return $this->sOutputFilePath;
|
||||
}
|
||||
}
|
||||
|
||||
public static function GetExcelFileFromToken($sToken)
|
||||
{
|
||||
return @file_get_contents(APPROOT.'data/bulk_export/'.$sToken.'.xlsx');
|
||||
}
|
||||
|
||||
public static function CleanupFromToken($sToken)
|
||||
{
|
||||
@unlink(APPROOT.'data/bulk_export/'.$sToken.'.status');
|
||||
@unlink(APPROOT.'data/bulk_export/'.$sToken.'.data');
|
||||
@unlink(APPROOT.'data/bulk_export/'.$sToken.'.xlsx');
|
||||
}
|
||||
|
||||
public function Cleanup()
|
||||
{
|
||||
self::CleanupFromToken($this->sToken);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all files in the data/bulk_export directory which are older than 1 day
|
||||
* unless a different delay is configured.
|
||||
*/
|
||||
public static function CleanupOldFiles()
|
||||
{
|
||||
$aFiles = glob(APPROOT.'data/bulk_export/*.*');
|
||||
$iDelay = MetaModel::GetConfig()->Get('xlsx_exporter_cleanup_old_files_delay');
|
||||
|
||||
if($iDelay > 0)
|
||||
{
|
||||
foreach($aFiles as $sFile)
|
||||
{
|
||||
$iModificationTime = filemtime($sFile);
|
||||
|
||||
if($iModificationTime < (time() - $iDelay))
|
||||
{
|
||||
// Temporary files older than one day are deleted
|
||||
//echo "Supposed to delete: '".$sFile." (Unix Modification Time: $iModificationTime)'\n";
|
||||
@unlink($sFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function DisplayStatistics(Page $oPage)
|
||||
{
|
||||
$aStats = array(
|
||||
'Number of objects exported' => $this->aStatistics['objects_count'],
|
||||
'Total export duration' => sprintf('%.3f s', $this->aStatistics['total_duration']),
|
||||
'Data retrieval duration' => sprintf('%.3f s', $this->aStatistics['data_retrieval_duration']),
|
||||
'Excel build duration' => sprintf('%.3f s', $this->aStatistics['excel_build_duration']),
|
||||
'Excel write duration' => sprintf('%.3f s', $this->aStatistics['excel_write_duration']),
|
||||
'Peak memory usage' => self::HumanDisplay($this->aStatistics['peak_memory_usage']),
|
||||
);
|
||||
|
||||
if ($oPage instanceof CLIPage)
|
||||
{
|
||||
$oPage->add($this->GetStatistics('text'));
|
||||
}
|
||||
else
|
||||
{
|
||||
$oPage->add($this->GetStatistics('html'));
|
||||
}
|
||||
}
|
||||
|
||||
public function GetStatistics($sFormat = 'html')
|
||||
{
|
||||
$sStats = '';
|
||||
$aStats = array(
|
||||
'Number of objects exported' => $this->aStatistics['objects_count'],
|
||||
'Total export duration' => sprintf('%.3f s', $this->aStatistics['total_duration']),
|
||||
'Data retrieval duration' => sprintf('%.3f s', $this->aStatistics['data_retrieval_duration']),
|
||||
'Excel build duration' => sprintf('%.3f s', $this->aStatistics['excel_build_duration']),
|
||||
'Excel write duration' => sprintf('%.3f s', $this->aStatistics['excel_write_duration']),
|
||||
'Peak memory usage' => self::HumanDisplay($this->aStatistics['peak_memory_usage']),
|
||||
);
|
||||
|
||||
if ($sFormat == 'text')
|
||||
{
|
||||
foreach($aStats as $sLabel => $sValue)
|
||||
{
|
||||
$sStats .= "+------------------------------+----------+\n";
|
||||
$sStats .= sprintf("|%-30s|%10s|\n", $sLabel, $sValue);
|
||||
}
|
||||
$sStats .= "+------------------------------+----------+";
|
||||
}
|
||||
else
|
||||
{
|
||||
$sStats .= '<table><tbody>';
|
||||
foreach($aStats as $sLabel => $sValue)
|
||||
{
|
||||
$sStats .= "<tr><td>$sLabel</td><td>$sValue</td></tr>";
|
||||
}
|
||||
$sStats .= '</tbody></table>';
|
||||
|
||||
}
|
||||
return $sStats;
|
||||
}
|
||||
|
||||
public static function HumanDisplay($iSize)
|
||||
{
|
||||
$aUnits = array('B','KB','MB','GB','TB','PB');
|
||||
return @round($iSize/pow(1024,($i=floor(log($iSize,1024)))),2).' '.$aUnits[$i];
|
||||
}
|
||||
|
||||
protected function CheckDataDir()
|
||||
{
|
||||
if(!is_dir(APPROOT."data/bulk_export"))
|
||||
{
|
||||
@mkdir(APPROOT."data/bulk_export", 0777, true /* recursive */);
|
||||
clearstatcache();
|
||||
}
|
||||
if (!is_writable(APPROOT."data/bulk_export"))
|
||||
{
|
||||
throw new Exception('Data directory "'.APPROOT.'data/bulk_export" could not be written.');
|
||||
}
|
||||
}
|
||||
|
||||
protected function GetStateFile($sToken = null)
|
||||
{
|
||||
if ($sToken == null)
|
||||
{
|
||||
$sToken = $this->sToken;
|
||||
}
|
||||
return APPROOT."data/bulk_export/$sToken.status";
|
||||
}
|
||||
|
||||
protected function GetDataFile()
|
||||
{
|
||||
return APPROOT.'data/bulk_export/'.$this->sToken.'.data';
|
||||
}
|
||||
|
||||
protected function GetNewToken()
|
||||
{
|
||||
$iNum = rand();
|
||||
do
|
||||
{
|
||||
$iNum++;
|
||||
$sToken = sprintf("%08x", $iNum);
|
||||
$sFileName = $this->GetStateFile($sToken);
|
||||
$hFile = @fopen($sFileName, 'x');
|
||||
}
|
||||
while($hFile === false);
|
||||
|
||||
fclose($hFile);
|
||||
return $sToken;
|
||||
}
|
||||
|
||||
protected function GetFieldsList($oSet, $bFieldsAdvanced = false, $bLocalize = true, $aFields = null)
|
||||
{
|
||||
$this->aFieldsList = array();
|
||||
|
||||
$oAppContext = new ApplicationContext();
|
||||
$aClasses = $oSet->GetFilter()->GetSelectedClasses();
|
||||
$this->aAuthorizedClasses = array();
|
||||
foreach($aClasses as $sAlias => $sClassName)
|
||||
{
|
||||
if (UserRights::IsActionAllowed($sClassName, UR_ACTION_READ, $oSet) && (UR_ALLOWED_YES || UR_ALLOWED_DEPENDS))
|
||||
{
|
||||
$this->aAuthorizedClasses[$sAlias] = $sClassName;
|
||||
}
|
||||
}
|
||||
$aAttribs = array();
|
||||
$this->aTableHeaders = array();
|
||||
foreach($this->aAuthorizedClasses as $sAlias => $sClassName)
|
||||
{
|
||||
$aList[$sAlias] = array();
|
||||
|
||||
foreach(MetaModel::ListAttributeDefs($sClassName) as $sAttCode => $oAttDef)
|
||||
{
|
||||
if (is_null($aFields) || (count($aFields) == 0))
|
||||
{
|
||||
// Standard list of attributes (no link sets)
|
||||
if ($oAttDef->IsScalar() && ($oAttDef->IsWritable() || $oAttDef->IsExternalField()))
|
||||
{
|
||||
$sAttCodeEx = $oAttDef->IsExternalField() ? $oAttDef->GetKeyAttCode().'->'.$oAttDef->GetExtAttCode() : $sAttCode;
|
||||
|
||||
if ($oAttDef->IsExternalKey(EXTKEY_ABSOLUTE))
|
||||
{
|
||||
if ($bFieldsAdvanced)
|
||||
{
|
||||
$aList[$sAlias][$sAttCodeEx] = $oAttDef;
|
||||
|
||||
if ($oAttDef->IsExternalKey(EXTKEY_RELATIVE))
|
||||
{
|
||||
$sRemoteClass = $oAttDef->GetTargetClass();
|
||||
foreach(MetaModel::GetReconcKeys($sRemoteClass) as $sRemoteAttCode)
|
||||
{
|
||||
$this->aFieldsList[$sAlias][$sAttCode.'->'.$sRemoteAttCode] = MetaModel::GetAttributeDef($sRemoteClass, $sRemoteAttCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Any other attribute
|
||||
$this->aFieldsList[$sAlias][$sAttCodeEx] = $oAttDef;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// User defined list of attributes
|
||||
if (in_array($sAttCode, $aFields) || in_array($sAlias.'.'.$sAttCode, $aFields))
|
||||
{
|
||||
$this->aFieldsList[$sAlias][$sAttCode] = $oAttDef;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($bFieldsAdvanced)
|
||||
{
|
||||
$this->aTableHeaders['id'] = '0';
|
||||
}
|
||||
foreach($this->aFieldsList[$sAlias] as $sAttCodeEx => $oAttDef)
|
||||
{
|
||||
$sLabel = $bLocalize ? MetaModel::GetLabel($sClassName, $sAttCodeEx, isset($aParams['showMandatoryFields'])) : $sAttCodeEx;
|
||||
if($oAttDef instanceof AttributeDateTime)
|
||||
{
|
||||
$this->aTableHeaders[$sLabel] = 'datetime';
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->aTableHeaders[$sLabel] = 'string';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,10 @@ class DesignerForm
|
||||
protected $bReadOnly;
|
||||
protected $sHierarchyPath; // Needed to manage the visibility of nested subform
|
||||
protected $sHierarchyParent; // Needed to manage the visibility of nested subform
|
||||
protected $sHierarchySelector; // Needed to manage the visibility of nested subform
|
||||
protected $bDisplayed;
|
||||
protected $aDefaultValues;
|
||||
protected $sFieldsSuffix;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
@@ -47,14 +50,17 @@ class DesignerForm
|
||||
$this->sScript = '';
|
||||
$this->sReadyScript = '';
|
||||
$this->sFormPrefix = '';
|
||||
$this->sFieldsSuffix = '';
|
||||
$this->sParamsContainer = '';
|
||||
$this->sFormId = 'form_'.rand();
|
||||
$this->oParentForm = null;
|
||||
$this->bReadOnly = false;
|
||||
$this->sHierarchyPath = '';
|
||||
$this->sHierarchyParent = '';
|
||||
$this->sHierarchySelector = '';
|
||||
$this->StartFieldSet($this->sCurrentFieldSet);
|
||||
$this->bDisplayed = true;
|
||||
$this->aDefaultvalues = array();
|
||||
}
|
||||
|
||||
public function AddField(DesignerFormField $oField)
|
||||
@@ -140,6 +146,11 @@ class DesignerForm
|
||||
$oP->add($sReturn);
|
||||
}
|
||||
}
|
||||
|
||||
public function GetFieldSets()
|
||||
{
|
||||
return $this->aFieldSets;
|
||||
}
|
||||
|
||||
public function SetSubmitParams($sSubmitToUrl, $aSubmitParams)
|
||||
{
|
||||
@@ -153,6 +164,11 @@ class DesignerForm
|
||||
$this->aSubmitParams = $oParentForm->aSubmitParams;
|
||||
}
|
||||
|
||||
public function GetSubmitParams()
|
||||
{
|
||||
return array( 'url' => $this->sSubmitTo, 'params' => $this->aSubmitParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to handle subforms hide/show
|
||||
*/
|
||||
@@ -168,7 +184,7 @@ class DesignerForm
|
||||
{
|
||||
return $this->sHierarchyPath;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Helper to handle subforms hide/show
|
||||
*/
|
||||
@@ -208,7 +224,7 @@ class DesignerForm
|
||||
$aDetails = array();
|
||||
if ($sLabel != '')
|
||||
{
|
||||
$sReturn .= '<tr><th colspan="4">'.$sLabel.'</th></tr>';
|
||||
$sReturn .= $this->StartRow().'<th colspan="4">'.$sLabel.'</th>'.$this->EndRow();
|
||||
}
|
||||
|
||||
|
||||
@@ -219,17 +235,29 @@ class DesignerForm
|
||||
{
|
||||
$sFieldId = $this->GetFieldId($oField->GetCode());
|
||||
$sValidation = $this->GetValidationArea($oField->GetCode(), '<span title="Apply" class="ui-icon ui-icon-circle-check"/>');
|
||||
$sValidationFields = '</td><td class="prop_icon prop_apply">'.$sValidation.'</td><td class="prop_icon prop_cancel"><span title="Revert" class="ui-icon ui-icon-circle-close"/></td></tr>';
|
||||
$sReturn .= '<tr id="row_'.$sFieldId.'"><td class="prop_label">'.$aRow['label'].'</td><td class="prop_value">'.$aRow['value'];
|
||||
if (!($oField instanceof DesignerFormSelectorField))
|
||||
$sValidationFields = '</td><td class="prop_icon prop_apply">'.$sValidation.'</td><td class="prop_icon prop_cancel"><span title="Revert" class="ui-icon ui-icon-circle-close"/></td>'.$this->EndRow();
|
||||
|
||||
$sPath = $this->GetHierarchyPath().'/'.$oField->GetCode();
|
||||
|
||||
if (is_null($aRow['label']))
|
||||
{
|
||||
$sReturn .= $this->StartRow($sFieldId).'<td class="prop_value" colspan="2">'.$aRow['value'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$sReturn .= $this->StartRow($sFieldId).'<td class="prop_label">'.$aRow['label'].'</td><td class="prop_value">'.$aRow['value'];
|
||||
}
|
||||
if (!($oField instanceof DesignerFormSelectorField) && !($oField instanceof DesignerMultipleSubFormField))
|
||||
{
|
||||
$sReturn .= $sValidationFields;
|
||||
}
|
||||
$sNotifyParentSelectorJS = is_null($sNotifyParentSelector) ? 'null' : "'".addslashes($sNotifyParentSelector)."'";
|
||||
$sAutoApply = $oField->IsAutoApply() ? 'true' : 'false';
|
||||
$sHandlerEquals = $oField->GetHandlerEquals();
|
||||
$sHandlerGetValue = $oField->GetHandlerGetValue();
|
||||
$this->AddReadyScript(
|
||||
<<<EOF
|
||||
$('#row_$sFieldId').property_field({parent_selector: $sNotifyParentSelectorJS, field_id: '$sFieldId', auto_apply: $sAutoApply, value: '', submit_to: '$sActionUrl', submit_parameters: $sJSSubmitParams });
|
||||
$('#row_$sFieldId').property_field({parent_selector: $sNotifyParentSelectorJS, field_id: '$sFieldId', equals: $sHandlerEquals, get_field_value: $sHandlerGetValue, auto_apply: $sAutoApply, value: '', submit_to: '$sActionUrl', submit_parameters: $sJSSubmitParams });
|
||||
EOF
|
||||
);
|
||||
}
|
||||
@@ -247,7 +275,7 @@ EOF
|
||||
$sReturn .= '</table>';
|
||||
$sReturn .= $sHiddenFields;
|
||||
$sReturn .= '</form>';
|
||||
$sReturn .= '<div id="prop_submit_result"/>'; // for the return of the submit operation
|
||||
$sReturn .= '<div id="prop_submit_result"></div>'; // for the return of the submit operation
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -287,9 +315,26 @@ EOF
|
||||
{
|
||||
$oP->add($sReturn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function StartRow($sFieldId = null)
|
||||
{
|
||||
if ($sFieldId != null)
|
||||
{
|
||||
return '<tr id="row_'.$sFieldId.'" data-path="'.$this->GetHierarchyPath().'" data-selector="'.$this->GetHierarchyParent().'">';
|
||||
}
|
||||
return '<tr data-path="'.$this->GetHierarchyPath().'" data-selector="'.$this->GetHierarchyParent().'">';
|
||||
}
|
||||
|
||||
public function EndRow()
|
||||
{
|
||||
return '</tr>';
|
||||
}
|
||||
|
||||
public function RenderAsDialog($oPage, $sDialogId, $sDialogTitle, $iDialogWidth, $sOkButtonLabel, $sIntroduction = null)
|
||||
{
|
||||
$this->SetPrefix('dlg_'); // To make sure that the controls have different IDs that the property sheet which may be displayed at the same time
|
||||
|
||||
$sDialogTitle = addslashes($sDialogTitle);
|
||||
$sOkButtonLabel = addslashes($sOkButtonLabel);
|
||||
$sCancelButtonLabel = Dict::S('UI:Button:Cancel');
|
||||
@@ -306,7 +351,7 @@ EOF
|
||||
<<<EOF
|
||||
$('#$sDialogId').dialog({
|
||||
height: 'auto',
|
||||
width: 500,
|
||||
width: $iDialogWidth,
|
||||
modal: true,
|
||||
title: '$sDialogTitle',
|
||||
buttons: [
|
||||
@@ -344,9 +389,29 @@ EOF
|
||||
|
||||
public function GetPrefix()
|
||||
{
|
||||
return $this->sFormPrefix;
|
||||
$sPrefix = '';
|
||||
if ($this->oParentForm != null)
|
||||
{
|
||||
$sPrefix = $this->oParentForm->GetPrefix();
|
||||
}
|
||||
return $sPrefix.$this->sFormPrefix;
|
||||
}
|
||||
|
||||
public function SetSuffix($sSuffix)
|
||||
{
|
||||
$this->sFieldsSuffix = $sSuffix;
|
||||
}
|
||||
|
||||
public function GetSuffix()
|
||||
{
|
||||
$sSuffix = '';
|
||||
if ($this->oParentForm != null)
|
||||
{
|
||||
$sSuffix = $this->oParentForm->GetSuffix();
|
||||
}
|
||||
return $sSuffix.$this->sFieldsSuffix;
|
||||
}
|
||||
|
||||
public function SetReadOnly($bReadOnly = true)
|
||||
{
|
||||
$this->bReadOnly = $bReadOnly;
|
||||
@@ -386,6 +451,25 @@ EOF
|
||||
$this->oParentForm = $oParentForm;
|
||||
}
|
||||
|
||||
public function SetDefaultValues($aDefaultValues)
|
||||
{
|
||||
if (!is_array($aDefaultValues)) return;
|
||||
|
||||
foreach($this->aFieldSets as $sLabel => $aFields)
|
||||
{
|
||||
foreach($aFields as $oField)
|
||||
{
|
||||
$oField->SetDefaultValueFrom($aDefaultValues);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function GetDefaultValues()
|
||||
{
|
||||
return $this->aDefaultValues;
|
||||
}
|
||||
|
||||
|
||||
public function GetParentForm()
|
||||
{
|
||||
return $this->oParentForm;
|
||||
@@ -420,17 +504,17 @@ EOF
|
||||
|
||||
public function GetFieldId($sCode)
|
||||
{
|
||||
return $this->sFormPrefix.'attr_'.$sCode;
|
||||
return $this->GetPrefix().'attr_'.$sCode;
|
||||
}
|
||||
|
||||
public function GetFieldName($sCode)
|
||||
{
|
||||
return 'attr_'.$sCode;
|
||||
return 'attr_'.$sCode.$this->GetSuffix();
|
||||
}
|
||||
|
||||
public function GetParamName($sCode)
|
||||
{
|
||||
return 'attr_'.$sCode;
|
||||
return 'attr_'.$sCode.$this->GetSuffix();
|
||||
}
|
||||
|
||||
public function GetValidationArea($sCode, $sContent = '')
|
||||
@@ -441,6 +525,21 @@ EOF
|
||||
{
|
||||
return $this->sAsyncActionClass;
|
||||
}
|
||||
|
||||
public function FindField($sFieldCode)
|
||||
{
|
||||
$oFoundField = false;
|
||||
foreach($this->aFieldSets as $sLabel => $aFields)
|
||||
{
|
||||
foreach($aFields as $oField)
|
||||
{
|
||||
$oFoundField = $oField->FindField($sFieldCode);
|
||||
if ($oFoundField !== false) break;
|
||||
}
|
||||
if ($oFoundField !== false) break;
|
||||
}
|
||||
return $oFoundField;
|
||||
}
|
||||
}
|
||||
|
||||
class DesignerTabularForm extends DesignerForm
|
||||
@@ -456,6 +555,11 @@ class DesignerTabularForm extends DesignerForm
|
||||
{
|
||||
$this->aTable[] = $aRow;
|
||||
}
|
||||
|
||||
public function RenderAsPropertySheet($oP, $bReturnHTML = false, $sNotifyParentSelector = null)
|
||||
{
|
||||
return $this->Render($oP, $bReturnHTML);
|
||||
}
|
||||
|
||||
public function Render($oP, $bReturnHTML = false)
|
||||
{
|
||||
@@ -615,6 +719,11 @@ class DesignerFormField
|
||||
return $this->bDisplayed;
|
||||
}
|
||||
|
||||
public function GetFieldId()
|
||||
{
|
||||
return $this->oForm->GetFieldId($this->sCode);
|
||||
}
|
||||
|
||||
public function Render(WebPage $oP, $sFormId, $sRenderMode='dialog')
|
||||
{
|
||||
$sId = $this->oForm->GetFieldId($this->sCode);
|
||||
@@ -658,6 +767,36 @@ class DesignerFormField
|
||||
{
|
||||
$this->aCSSClasses[] = $sCSSClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* A way to set/change the default value after constructing the field
|
||||
*/
|
||||
public function SetDefaultValueFrom($aAllDefaultValue)
|
||||
{
|
||||
if (array_key_exists($this->GetCode(), $aAllDefaultValue))
|
||||
{
|
||||
$this->defaultValue = $aAllDefaultValue[$this->GetCode()];
|
||||
}
|
||||
}
|
||||
|
||||
public function FindField($sFieldCode)
|
||||
{
|
||||
if ($this->sCode == $sFieldCode)
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function GetHandlerEquals()
|
||||
{
|
||||
return 'null';
|
||||
}
|
||||
|
||||
public function GetHandlerGetValue()
|
||||
{
|
||||
return 'null';
|
||||
}
|
||||
}
|
||||
|
||||
class DesignerLabelField extends DesignerFormField
|
||||
@@ -674,7 +813,7 @@ class DesignerLabelField extends DesignerFormField
|
||||
{
|
||||
$sId = $this->oForm->GetFieldId($this->sCode);
|
||||
$sName = $this->oForm->GetFieldName($this->sCode);
|
||||
return array('label' => $this->sLabel, 'value' => $sDescription);
|
||||
return array('label' => $this->sLabel, 'value' => $this->sDescription);
|
||||
}
|
||||
|
||||
public function ReadParam(&$aValues)
|
||||
@@ -723,6 +862,7 @@ class DesignerTextField extends DesignerFormField
|
||||
public function Render(WebPage $oP, $sFormId, $sRenderMode='dialog')
|
||||
{
|
||||
$sId = $this->oForm->GetFieldId($this->sCode);
|
||||
|
||||
$sName = $this->oForm->GetFieldName($this->sCode);
|
||||
if ($this->IsReadOnly())
|
||||
{
|
||||
@@ -819,6 +959,7 @@ class DesignerComboField extends DesignerFormField
|
||||
protected $aAllowedValues;
|
||||
protected $bMultipleSelection;
|
||||
protected $bOtherChoices;
|
||||
protected $sNullLabel;
|
||||
|
||||
public function __construct($sCode, $sLabel = '', $defaultValue = '')
|
||||
{
|
||||
@@ -826,6 +967,7 @@ class DesignerComboField extends DesignerFormField
|
||||
$this->aAllowedValues = array();
|
||||
$this->bMultipleSelection = false;
|
||||
$this->bOtherChoices = false;
|
||||
$this->sNullLabel = Dict::S('UI:SelectOne');
|
||||
|
||||
$this->bAutoApply = true;
|
||||
}
|
||||
@@ -844,11 +986,17 @@ class DesignerComboField extends DesignerFormField
|
||||
{
|
||||
$this->bOtherChoices = $bOtherChoices;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* An empty label will disable the default empty value
|
||||
*/
|
||||
public function SetNullLabel($sLabel)
|
||||
{
|
||||
$this->sNullLabel = $sLabel;
|
||||
}
|
||||
|
||||
public function Render(WebPage $oP, $sFormId, $sRenderMode='dialog')
|
||||
{
|
||||
|
||||
$sId = $this->oForm->GetFieldId($this->sCode);
|
||||
$sName = $this->oForm->GetFieldName($this->sCode);
|
||||
$sChecked = $this->defaultValue ? 'checked' : '';
|
||||
@@ -893,7 +1041,10 @@ class DesignerComboField extends DesignerFormField
|
||||
else
|
||||
{
|
||||
$sHtml = "<select $sCSSClasses id=\"$sId\" name=\"$sName\">";
|
||||
$sHtml .= "<option value=\"\">".Dict::S('UI:SelectOne')."</option>";
|
||||
if ($this->sNullLabel != '')
|
||||
{
|
||||
$sHtml .= "<option value=\"\">".$this->sNullLabel."</option>";
|
||||
}
|
||||
}
|
||||
foreach($this->aAllowedValues as $sKey => $sDisplayValue)
|
||||
{
|
||||
@@ -993,7 +1144,6 @@ class DesignerBooleanField extends DesignerFormField
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class DesignerHiddenField extends DesignerFormField
|
||||
{
|
||||
public function __construct($sCode, $sLabel = '', $defaultValue = '')
|
||||
@@ -1192,6 +1342,8 @@ class DesignerFormSelectorField extends DesignerFormField
|
||||
$sName = $this->oForm->GetFieldName($this->sCode);
|
||||
$sReadOnly = $this->IsReadOnly() ? 'disabled="disabled"' : '';
|
||||
|
||||
$this->aCSSClasses[] = 'formSelector';
|
||||
|
||||
$sCSSClasses = '';
|
||||
if (count($this->aCSSClasses) > 0)
|
||||
{
|
||||
@@ -1205,12 +1357,12 @@ class DesignerFormSelectorField extends DesignerFormField
|
||||
$aHiddenValues = array();
|
||||
$sDisplayValue = '';
|
||||
$sHiddenValue = '';
|
||||
foreach($this->aSubForms as $sKey => $aFormData)
|
||||
foreach($this->aSubForms as $iKey => $aFormData)
|
||||
{
|
||||
if ($sKey == $this->defaultValue)
|
||||
if ($iKey == $this->defaultValue) // Default value is actually the index
|
||||
{
|
||||
$sDisplayValue = htmlentities($aFormData['label'], ENT_QUOTES, 'UTF-8');
|
||||
$sHiddenValue = "<input type=\"hidden\" id=\"$sId\" name=\"$sName\" value=\"".htmlentities($sKey, ENT_QUOTES, 'UTF-8')."\"/>";
|
||||
$sHiddenValue = "<input type=\"hidden\" id=\"$sId\" name=\"$sName\" value=\"".htmlentities($iKey, ENT_QUOTES, 'UTF-8')."\"/>";
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1221,11 +1373,11 @@ class DesignerFormSelectorField extends DesignerFormField
|
||||
|
||||
|
||||
$sHtml = "<select $sCSSClasses id=\"$sId\" name=\"$sName\" $sReadOnly>";
|
||||
foreach($this->aSubForms as $sKey => $aFormData)
|
||||
foreach($this->aSubForms as $iKey => $aFormData)
|
||||
{
|
||||
$sDisplayValue = htmlentities($aFormData['label'], ENT_QUOTES, 'UTF-8');;
|
||||
$sSelected = ($sKey == $this->defaultValue) ? 'selected' : '';
|
||||
$sHtml .= "<option value=\"".htmlentities($sKey, ENT_QUOTES, 'UTF-8')."\" $sSelected>".$sDisplayValue."</option>";
|
||||
$sSelected = ($iKey == $this->defaultValue) ? 'selected' : '';
|
||||
$sHtml .= "<option value=\"$iKey\" $sSelected>".$sDisplayValue."</option>";
|
||||
}
|
||||
$sHtml .= "</select>";
|
||||
}
|
||||
@@ -1254,19 +1406,21 @@ class DesignerFormSelectorField extends DesignerFormField
|
||||
// - data-path : uniquely identifies the combination of users choices that must be made to show the node
|
||||
// - data-state : records the state, depending on the user choice on the FormSelectorField just above the node, but indepentantly from the visibility in the page (can be visible in the form itself being in a hidden form)
|
||||
// Then a series of actions are performed to hide and show the relevant nodes, depending on the user choice
|
||||
$sSelector = $this->oForm->GetHierarchyPath().'/'.$this->sCode;
|
||||
$sSelector = $this->oForm->GetHierarchyPath().'/'.$this->sCode.$this->oForm->GetSuffix();
|
||||
$oSubForm->SetHierarchyParent($sSelector);
|
||||
$sPath = $this->oForm->GetHierarchyPath().'/'.$this->sCode.':'.$sKey;
|
||||
$sPath = $this->oForm->GetHierarchyPath().'/'.$this->sCode.$this->oForm->GetSuffix().'-'.$sKey;
|
||||
$oSubForm->SetHierarchyPath($sPath);
|
||||
|
||||
$oSubForm->SetDisplayed($sKey == $this->defaultValue);
|
||||
$sState = ($sKey == $this->defaultValue) ? 'visible' : 'hidden';
|
||||
$sHtml .= "</tbody><tbody data-selector=\"$sSelector\" data-path=\"$sPath\" data-state=\"$sState\" $sStyle>";
|
||||
//$sHtml .= "</tbody><tbody data-selector=\"$sSelector\" data-path=\"$sPath\" data-state=\"$sState\" $sStyle>";
|
||||
$sHtml .= $oSubForm->RenderAsPropertySheet($oP, true);
|
||||
|
||||
$sState = $this->oForm->IsDisplayed() ? 'visible' : 'hidden';
|
||||
$sParentStyle = '';
|
||||
if ($oParent = $this->oForm->GetParentForm())
|
||||
{
|
||||
$sParentStyle = ($oParent->IsDisplayed()) ? '' : 'style="display:none"';
|
||||
$sParentSelector = $oParent->GetHierarchyParent();
|
||||
$sParentPath = $oParent->GetHierarchyPath();
|
||||
}
|
||||
@@ -1275,7 +1429,8 @@ class DesignerFormSelectorField extends DesignerFormField
|
||||
$sParentSelector = '';
|
||||
$sParentPath = '';
|
||||
}
|
||||
$sHtml .= "</tbody><tbody data-selector=\"$sParentSelector\" data-path=\"$sParentPath\" data-state=\"$sState\" $sStyle>";
|
||||
|
||||
//$sHtml .= "</tbody><tbody data-selector=\"$sParentSelector\" data-path=\"$sParentPath\" data-state=\"$sState\" $sParentStyle>";
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1287,27 +1442,8 @@ class DesignerFormSelectorField extends DesignerFormField
|
||||
|
||||
if ($sRenderMode == 'property')
|
||||
{
|
||||
$sSelector = $this->oForm->GetHierarchyPath().'/'.$this->sCode;
|
||||
$oP->add_ready_script(
|
||||
<<<EOF
|
||||
$('#$sId').bind('change reverted', function() {
|
||||
// Mark all the direct children as hidden
|
||||
$('tbody[data-selector="$sSelector"]').attr('data-state', 'hidden');
|
||||
// Mark the selected one as visible
|
||||
var sSelectedHierarchy = '$sSelector:'+this.value;
|
||||
$('tbody[data-path="'+sSelectedHierarchy+'"]').attr('data-state', 'visible');
|
||||
|
||||
// Show all items behind the current one
|
||||
$('tbody[data-path^="$sSelector"]').show();
|
||||
// Hide items behind the current one as soon as it is behind a hidden node (or itself is marked as hidden)
|
||||
$('tbody[data-path^="$sSelector"][data-state="hidden"]').each(function(){
|
||||
$(this).hide();
|
||||
var sPath = $(this).attr('data-path');
|
||||
$('tbody[data-path^="'+sPath+'/"]').hide();
|
||||
});
|
||||
});
|
||||
EOF
|
||||
);
|
||||
$sSelector = $this->oForm->GetHierarchyPath().'/'.$this->sCode.$this->oForm->GetSuffix();
|
||||
$oP->add_ready_script("InitFormSelectorField('$sId', '$sSelector');");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1330,6 +1466,44 @@ EOF
|
||||
$this->aSubForms[$sKey]['form']->SetParentForm($this->oForm);
|
||||
$this->aSubForms[$sKey]['form']->ReadParams($aValues);
|
||||
}
|
||||
|
||||
public function SetDefaultValueFrom($aAllDefaultValues)
|
||||
{
|
||||
if (array_key_exists($this->GetCode(), $aAllDefaultValues))
|
||||
{
|
||||
$selectedValue = $aAllDefaultValues[$this->GetCode()];
|
||||
foreach($this->aSubForms as $iKey => $aFormData)
|
||||
{
|
||||
$sId = $this->oForm->GetFieldId($this->sCode);
|
||||
if ($selectedValue == $aFormData['value'])
|
||||
{
|
||||
$this->defaultValue =$iKey;
|
||||
$aDefaultValues = $this->oForm->GetDefaultValues();
|
||||
$oSubForm = $aFormData['form'];
|
||||
$oSubForm->SetDefaultValues($aAllDefaultValues);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function FindField($sFieldCode)
|
||||
{
|
||||
$oField = parent::FindField($sFieldCode);
|
||||
if ($oField === false)
|
||||
{
|
||||
// Look in the subforms
|
||||
foreach($this->aSubForms as $sKey => $aFormData)
|
||||
{
|
||||
$oSubForm = $aFormData['form'];
|
||||
$oField = $oSubForm->FindField($sFieldCode);
|
||||
if ($oField !== false)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $oField;
|
||||
}
|
||||
}
|
||||
|
||||
class DesignerSubFormField extends DesignerFormField
|
||||
@@ -1362,6 +1536,31 @@ class DesignerSubFormField extends DesignerFormField
|
||||
$this->oSubForm->SetParentForm($this->oForm);
|
||||
$this->oSubForm->ReadParams($aValues);
|
||||
}
|
||||
|
||||
public function FindField($sFieldCode)
|
||||
{
|
||||
$oField = parent::FindField($sFieldCode);
|
||||
if ($oField === false)
|
||||
{
|
||||
// Look in the subform
|
||||
$oField = $this->oSubForm->FindField($sFieldCode);
|
||||
}
|
||||
return $oField;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
class DesignerStaticTextField extends DesignerFormField
|
||||
{
|
||||
public function __construct($sCode, $sLabel = '', $defaultValue = '')
|
||||
{
|
||||
parent::__construct($sCode, $sLabel, $defaultValue);
|
||||
}
|
||||
|
||||
public function Render(WebPage $oP, $sFormId, $sRenderMode='dialog')
|
||||
{
|
||||
return array('label' => $this->sLabel, 'value' => $this->defaultValue);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -587,8 +587,7 @@ EOF
|
||||
header($s_header);
|
||||
}
|
||||
}
|
||||
$s_captured_output = ob_get_contents();
|
||||
ob_end_clean();
|
||||
$s_captured_output = $this->ob_get_clean_safe();
|
||||
$sHtml = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n";
|
||||
$sHtml .= "<html>\n";
|
||||
$sHtml .= "<head>\n";
|
||||
@@ -1039,4 +1038,3 @@ EOF
|
||||
$this->m_sMessage = $sMessage;
|
||||
}
|
||||
}
|
||||
?>
|
||||
@@ -239,7 +239,7 @@ EOF
|
||||
*/
|
||||
protected function DisplayFormTable(WebPage $oP, $aConfig, $aData)
|
||||
{
|
||||
$sHtml = '';
|
||||
$sHtml = "<input type=\"hidden\" name=\"attr_{$this->m_sAttCode}{$this->m_sNameSuffix}\" value=\"\">";
|
||||
$sHtml .= "<table class=\"listResults\">\n";
|
||||
// Header
|
||||
$sHtml .= "<thead>\n";
|
||||
@@ -259,11 +259,11 @@ EOF
|
||||
$sEmptyRowStyle = 'style="display:none;"';
|
||||
}
|
||||
|
||||
$sHtml .= "<tr $sEmptyRowStyle id=\"{$this->m_sAttCode}{$this->m_sNameSuffix}_empty_row\"><td colspan=\"".count($aConfig)."\" style=\"text-align:center;\">".Dict::S('UI:Message:EmptyList:UseAdd')."<input type=\"hidden\" name=\"attr_{$this->m_sAttCode}{$this->m_sNameSuffix}\" value=\"\"></td></td>";
|
||||
foreach($aData as $iRowId => $aRow)
|
||||
{
|
||||
$sHtml .= $this->DisplayFormRow($oP, $aConfig, $aRow, $iRowId);
|
||||
}
|
||||
$sHtml .= "<tr $sEmptyRowStyle id=\"{$this->m_sAttCode}{$this->m_sNameSuffix}_empty_row\"><td colspan=\"".count($aConfig)."\" style=\"text-align:center;\">".Dict::S('UI:Message:EmptyList:UseAdd')."</td></tr>";
|
||||
$sHtml .= "</tbody>\n";
|
||||
|
||||
// Footer
|
||||
|
||||
@@ -783,11 +783,16 @@ class utils
|
||||
$sOQL = addslashes($param->GetFilter()->ToOQL(true));
|
||||
$sFilter = urlencode($param->GetFilter()->serialize());
|
||||
$sUrl = utils::GetAbsoluteUrlAppRoot()."pages/$sUIPage?operation=search&filter=".$sFilter."&{$sContext}";
|
||||
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/xlsx-export.js');
|
||||
$sXlsxFilter = $param->GetFilter()->serialize();
|
||||
$sXlsxJSFilter = addslashes($sXlsxFilter);
|
||||
|
||||
$aResult = array(
|
||||
new SeparatorPopupMenuItem(),
|
||||
// Static menus: Email this page, CSV Export & Add to Dashboard
|
||||
new URLPopupMenuItem('UI:Menu:EMail', Dict::S('UI:Menu:EMail'), "mailto:?body=".urlencode($sUrl).' '), // Add an extra space to make it work in Outlook
|
||||
new URLPopupMenuItem('UI:Menu:CSVExport', Dict::S('UI:Menu:CSVExport'), $sUrl."&format=csv"),
|
||||
new JSPopupMenuItem('xlsx-export', Dict::S('ExcelExporter:ExportMenu'), "XlsxExportDialog('$sXlsxJSFilter');", array()),
|
||||
new JSPopupMenuItem('UI:Menu:AddToDashboard', Dict::S('UI:Menu:AddToDashboard'), "DashletCreationDlg('$sOQL')"),
|
||||
new JSPopupMenuItem('UI:Menu:ShortcutList', Dict::S('UI:Menu:ShortcutList'), "ShortcutListDlg('$sOQL', '$sDataTableId', '$sContext')"),
|
||||
);
|
||||
@@ -802,11 +807,14 @@ class utils
|
||||
$sUIPage = cmdbAbstractObject::ComputeStandardUIPage(get_class($oObj));
|
||||
$oAppContext = new ApplicationContext();
|
||||
$sContext = $oAppContext->GetForLink();
|
||||
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/xlsx-export.js');
|
||||
$sXlsxJSFilter = addslashes($sFilter);
|
||||
$aResult = array(
|
||||
new SeparatorPopupMenuItem(),
|
||||
// Static menus: Email this page & CSV Export
|
||||
new URLPopupMenuItem('UI:Menu:EMail', Dict::S('UI:Menu:EMail'), "mailto:?subject=".urlencode($oObj->GetRawName())."&body=".urlencode($sUrl).' '), // Add an extra space to make it work in Outlook
|
||||
new URLPopupMenuItem('UI:Menu:CSVExport', Dict::S('UI:Menu:CSVExport'), utils::GetAbsoluteUrlAppRoot()."pages/$sUIPage?operation=search&filter=".urlencode($sFilter)."&format=csv&{$sContext}"),
|
||||
new JSPopupMenuItem('xlsx-export', Dict::S('ExcelExporter:ExportMenu'), "XlsxExportDialog('$sXlsxJSFilter');", array()),
|
||||
);
|
||||
break;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
// Copyright (C) 2010-2013 Combodo SARL
|
||||
// Copyright (C) 2010-2014 Combodo SARL
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
@@ -68,6 +68,7 @@ class WebPage implements Page
|
||||
protected $sContentType;
|
||||
protected $sContentDisposition;
|
||||
protected $sContentFileName;
|
||||
protected $bTrashUnexpectedOutput;
|
||||
protected $s_sOutputFormat;
|
||||
protected $a_OutputOptions;
|
||||
|
||||
@@ -88,6 +89,7 @@ class WebPage implements Page
|
||||
$this->sContentType = '';
|
||||
$this->sContentDisposition = '';
|
||||
$this->sContentFileName = '';
|
||||
$this->bTrashUnexpectedOutput = false;
|
||||
$this->s_OutputFormat = utils::ReadParam('output_format', 'html');
|
||||
$this->a_OutputOptions = array();
|
||||
ob_start(); // Start capturing the output
|
||||
@@ -392,22 +394,55 @@ class WebPage implements Page
|
||||
}
|
||||
|
||||
/**
|
||||
* Discard unexpected output data
|
||||
* Discard unexpected output data (such as PHP warnings)
|
||||
* This is a MUST when the Page output is DATA (download of a document, download CSV export, download ...)
|
||||
*/
|
||||
public function TrashUnexpectedOutput()
|
||||
{
|
||||
// This protection is redundant with a protection implemented in MetaModel::IncludeModule
|
||||
// which detects such issues while loading module files
|
||||
// Here, the purpose is to detect and discard characters produced by the code execution (echo)
|
||||
$sPreviousContent = ob_get_clean();
|
||||
if (trim($sPreviousContent) != '')
|
||||
$this->bTrashUnexpectedOutput = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the output buffer and deal with its contents:
|
||||
* - trash unexpected output if the flag has been set
|
||||
* - report unexpected behaviors such as the output buffering being stopped
|
||||
*
|
||||
* Possible improvement: I've noticed that several output buffers are stacked,
|
||||
* if they are not empty, the output will be corrupted. The solution would
|
||||
* consist in unstacking all of them (and concatenate the contents).
|
||||
*/
|
||||
protected function ob_get_clean_safe()
|
||||
{
|
||||
$sOutput = ob_get_contents();
|
||||
if ($sOutput === false)
|
||||
{
|
||||
if (Utils::GetConfig() && Utils::GetConfig()->Get('debug_report_spurious_chars'))
|
||||
$sMsg = "Design/integration issue: No output buffer. Some piece of code has called ob_get_clean() or ob_end_clean() without calling ob_start()";
|
||||
if ($this->bTrashUnexpectedOutput)
|
||||
{
|
||||
IssueLog::Error("Output already started before downloading file:\nContent was:'$sPreviousContent'\n");
|
||||
IssueLog::Error($sMsg);
|
||||
$sOutput = '';
|
||||
}
|
||||
else
|
||||
{
|
||||
$sOutput = $sMsg;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ob_end_clean(); // on some versions of PHP doing so when the output buffering is stopped can cause a notice
|
||||
if ($this->bTrashUnexpectedOutput)
|
||||
{
|
||||
if (trim($sOutput) != '')
|
||||
{
|
||||
if (Utils::GetConfig() && Utils::GetConfig()->Get('debug_report_spurious_chars'))
|
||||
{
|
||||
IssueLog::Error("Trashing unexpected output:'$s_captured_output'\n");
|
||||
}
|
||||
}
|
||||
$sOutput = '';
|
||||
}
|
||||
}
|
||||
return $sOutput;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -419,8 +454,8 @@ class WebPage implements Page
|
||||
{
|
||||
header($s_header);
|
||||
}
|
||||
$s_captured_output = ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
$s_captured_output = $this->ob_get_clean_safe();
|
||||
echo "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n";
|
||||
echo "<html>\n";
|
||||
echo "<head>\n";
|
||||
|
||||
456
application/xlsxwriter.class.php
Normal file
456
application/xlsxwriter.class.php
Normal file
@@ -0,0 +1,456 @@
|
||||
<?php
|
||||
/* @author Mark Jones
|
||||
* @license MIT License
|
||||
* */
|
||||
|
||||
if (!class_exists('ZipArchive')) { throw new Exception('ZipArchive not found'); }
|
||||
|
||||
Class XLSXWriter
|
||||
{
|
||||
//------------------------------------------------------------------
|
||||
protected $author ='Doc Author';
|
||||
protected $sheets_meta = array();
|
||||
protected $shared_strings = array();//unique set
|
||||
protected $shared_string_count = 0;//count of non-unique references to the unique set
|
||||
protected $temp_files = array();
|
||||
|
||||
public function __construct(){}
|
||||
public function setAuthor($author='') { $this->author=$author; }
|
||||
|
||||
public function __destruct()
|
||||
{
|
||||
if (!empty($this->temp_files)) {
|
||||
foreach($this->temp_files as $temp_file) {
|
||||
@unlink($temp_file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function tempFilename()
|
||||
{
|
||||
$filename = tempnam("/tmp", "xlsx_writer_");
|
||||
$this->temp_files[] = $filename;
|
||||
return $filename;
|
||||
}
|
||||
|
||||
public function writeToStdOut()
|
||||
{
|
||||
$temp_file = $this->tempFilename();
|
||||
self::writeToFile($temp_file);
|
||||
readfile($temp_file);
|
||||
}
|
||||
|
||||
public function writeToString()
|
||||
{
|
||||
$temp_file = $this->tempFilename();
|
||||
self::writeToFile($temp_file);
|
||||
$string = file_get_contents($temp_file);
|
||||
return $string;
|
||||
}
|
||||
|
||||
public function writeToFile($filename)
|
||||
{
|
||||
@unlink($filename);//if the zip already exists, overwrite it
|
||||
$zip = new ZipArchive();
|
||||
if (empty($this->sheets_meta)) { self::log("Error in ".__CLASS__."::".__FUNCTION__.", no worksheets defined."); return; }
|
||||
if (!$zip->open($filename, ZipArchive::CREATE)) { self::log("Error in ".__CLASS__."::".__FUNCTION__.", unable to create zip."); return; }
|
||||
|
||||
$zip->addEmptyDir("docProps/");
|
||||
$zip->addFromString("docProps/app.xml" , self::buildAppXML() );
|
||||
$zip->addFromString("docProps/core.xml", self::buildCoreXML());
|
||||
|
||||
$zip->addEmptyDir("_rels/");
|
||||
$zip->addFromString("_rels/.rels", self::buildRelationshipsXML());
|
||||
|
||||
$zip->addEmptyDir("xl/worksheets/");
|
||||
foreach($this->sheets_meta as $sheet_meta) {
|
||||
$zip->addFile($sheet_meta['filename'], "xl/worksheets/".$sheet_meta['xmlname'] );
|
||||
}
|
||||
if (!empty($this->shared_strings)) {
|
||||
$zip->addFile($this->writeSharedStringsXML(), "xl/sharedStrings.xml" ); //$zip->addFromString("xl/sharedStrings.xml", self::buildSharedStringsXML() );
|
||||
}
|
||||
$zip->addFromString("xl/workbook.xml" , self::buildWorkbookXML() );
|
||||
$zip->addFile($this->writeStylesXML(), "xl/styles.xml" ); //$zip->addFromString("xl/styles.xml" , self::buildStylesXML() );
|
||||
$zip->addFromString("[Content_Types].xml" , self::buildContentTypesXML() );
|
||||
|
||||
$zip->addEmptyDir("xl/_rels/");
|
||||
$zip->addFromString("xl/_rels/workbook.xml.rels", self::buildWorkbookRelsXML() );
|
||||
$zip->close();
|
||||
}
|
||||
|
||||
|
||||
public function writeSheet(array $data, $sheet_name='', array $header_types=array() )
|
||||
{
|
||||
$data = empty($data) ? array( array('') ) : $data;
|
||||
|
||||
$sheet_filename = $this->tempFilename();
|
||||
$sheet_default = 'Sheet'.(count($this->sheets_meta)+1);
|
||||
$sheet_name = !empty($sheet_name) ? $sheet_name : $sheet_default;
|
||||
$this->sheets_meta[] = array('filename'=>$sheet_filename, 'sheetname'=>$sheet_name ,'xmlname'=>strtolower($sheet_default).".xml" );
|
||||
|
||||
$header_offset = empty($header_types) ? 0 : 1;
|
||||
$row_count = count($data) + $header_offset;
|
||||
$column_count = count($data[self::array_first_key($data)]);
|
||||
$max_cell = self::xlsCell( $row_count-1, $column_count-1 );
|
||||
|
||||
$tabselected = count($this->sheets_meta)==1 ? 'true' : 'false';//only first sheet is selected
|
||||
$cell_formats_arr = empty($header_types) ? array_fill(0, $column_count, 'string') : array_values($header_types);
|
||||
$header_row = empty($header_types) ? array() : array_keys($header_types);
|
||||
|
||||
$fd = fopen($sheet_filename, "w+");
|
||||
if ($fd===false) { self::log("write failed in ".__CLASS__."::".__FUNCTION__."."); return; }
|
||||
|
||||
fwrite($fd,'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'."\n");
|
||||
fwrite($fd,'<worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">');
|
||||
fwrite($fd, '<sheetPr filterMode="false">');
|
||||
fwrite($fd, '<pageSetUpPr fitToPage="false"/>');
|
||||
fwrite($fd, '</sheetPr>');
|
||||
fwrite($fd, '<dimension ref="A1:'.$max_cell.'"/>');
|
||||
fwrite($fd, '<sheetViews>');
|
||||
fwrite($fd, '<sheetView colorId="64" defaultGridColor="true" rightToLeft="false" showFormulas="false" showGridLines="true" showOutlineSymbols="true" showRowColHeaders="true" showZeros="true" tabSelected="'.$tabselected.'" topLeftCell="A1" view="normal" windowProtection="false" workbookViewId="0" zoomScale="100" zoomScaleNormal="100" zoomScalePageLayoutView="100">');
|
||||
fwrite($fd, '<selection activeCell="A1" activeCellId="0" pane="topLeft" sqref="A1"/>');
|
||||
fwrite($fd, '</sheetView>');
|
||||
fwrite($fd, '</sheetViews>');
|
||||
fwrite($fd, '<cols>');
|
||||
fwrite($fd, '<col collapsed="false" hidden="false" max="1025" min="1" style="0" width="19"/>');
|
||||
fwrite($fd, '</cols>');
|
||||
fwrite($fd, '<sheetData>');
|
||||
if (!empty($header_row))
|
||||
{
|
||||
fwrite($fd, '<row collapsed="false" customFormat="false" customHeight="false" hidden="false" ht="12.1" outlineLevel="0" r="'.(1).'">');
|
||||
foreach($header_row as $k=>$v)
|
||||
{
|
||||
$this->writeCell($fd, 0, $k, $v, $cell_format='string');
|
||||
}
|
||||
fwrite($fd, '</row>');
|
||||
}
|
||||
foreach($data as $i=>$row)
|
||||
{
|
||||
fwrite($fd, '<row collapsed="false" customFormat="false" customHeight="false" hidden="false" ht="12.1" outlineLevel="0" r="'.($i+$header_offset+1).'">');
|
||||
foreach($row as $k=>$v)
|
||||
{
|
||||
$this->writeCell($fd, $i+$header_offset, $k, $v, $cell_formats_arr[$k]);
|
||||
}
|
||||
fwrite($fd, '</row>');
|
||||
}
|
||||
fwrite($fd, '</sheetData>');
|
||||
fwrite($fd, '<printOptions headings="false" gridLines="false" gridLinesSet="true" horizontalCentered="false" verticalCentered="false"/>');
|
||||
fwrite($fd, '<pageMargins left="0.5" right="0.5" top="1.0" bottom="1.0" header="0.5" footer="0.5"/>');
|
||||
fwrite($fd, '<pageSetup blackAndWhite="false" cellComments="none" copies="1" draft="false" firstPageNumber="1" fitToHeight="1" fitToWidth="1" horizontalDpi="300" orientation="portrait" pageOrder="downThenOver" paperSize="1" scale="100" useFirstPageNumber="true" usePrinterDefaults="false" verticalDpi="300"/>');
|
||||
fwrite($fd, '<headerFooter differentFirst="false" differentOddEven="false">');
|
||||
fwrite($fd, '<oddHeader>&C&"Times New Roman,Regular"&12&A</oddHeader>');
|
||||
fwrite($fd, '<oddFooter>&C&"Times New Roman,Regular"&12Page &P</oddFooter>');
|
||||
fwrite($fd, '</headerFooter>');
|
||||
fwrite($fd,'</worksheet>');
|
||||
fclose($fd);
|
||||
}
|
||||
|
||||
protected function writeCell($fd, $row_number, $column_number, $value, $cell_format)
|
||||
{
|
||||
static $styles = array('money'=>1,'dollar'=>1,'datetime'=>2,'date'=>3,'string'=>0);
|
||||
$cell = self::xlsCell($row_number, $column_number);
|
||||
$s = isset($styles[$cell_format]) ? $styles[$cell_format] : '0';
|
||||
|
||||
if (is_numeric($value)) {
|
||||
fwrite($fd,'<c r="'.$cell.'" s="'.$s.'" t="n"><v>'.($value*1).'</v></c>');//int,float, etc
|
||||
} else if ($cell_format=='date') {
|
||||
fwrite($fd,'<c r="'.$cell.'" s="'.$s.'" t="n"><v>'.intval(self::convert_date_time($value)).'</v></c>');
|
||||
} else if ($cell_format=='datetime') {
|
||||
if ($value === '') {
|
||||
fwrite($fd,'<c r="'.$cell.'" s="0"/>');
|
||||
} else {
|
||||
fwrite($fd,'<c r="'.$cell.'" s="'.$s.'" t="n"><v>'.self::convert_date_time($value).'</v></c>');
|
||||
}
|
||||
} else if ($value==''){
|
||||
fwrite($fd,'<c r="'.$cell.'" s="'.$s.'"/>');
|
||||
} else if ($value{0}=='='){
|
||||
fwrite($fd,'<c r="'.$cell.'" s="'.$s.'" t="s"><f>'.self::xmlspecialchars($value).'</f></c>');
|
||||
} else if ($value!==''){
|
||||
fwrite($fd,'<c r="'.$cell.'" s="'.$s.'" t="s"><v>'.self::xmlspecialchars($this->setSharedString($value)).'</v></c>');
|
||||
}
|
||||
}
|
||||
|
||||
protected function writeStylesXML()
|
||||
{
|
||||
$tempfile = $this->tempFilename();
|
||||
$fd = fopen($tempfile, "w+");
|
||||
if ($fd===false) { self::log("write failed in ".__CLASS__."::".__FUNCTION__."."); return; }
|
||||
fwrite($fd, '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'."\n");
|
||||
fwrite($fd, '<styleSheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">');
|
||||
fwrite($fd, '<numFmts count="4">');
|
||||
fwrite($fd, '<numFmt formatCode="GENERAL" numFmtId="164"/>');
|
||||
fwrite($fd, '<numFmt formatCode="[$$-1009]#,##0.00;[RED]\-[$$-1009]#,##0.00" numFmtId="165"/>');
|
||||
fwrite($fd, '<numFmt formatCode="YYYY-MM-DD\ HH:MM:SS" numFmtId="166"/>');
|
||||
fwrite($fd, '<numFmt formatCode="YYYY-MM-DD" numFmtId="167"/>');
|
||||
fwrite($fd, '</numFmts>');
|
||||
fwrite($fd, '<fonts count="4">');
|
||||
fwrite($fd, '<font><name val="Arial"/><charset val="1"/><family val="2"/><sz val="10"/></font>');
|
||||
fwrite($fd, '<font><name val="Arial"/><family val="0"/><sz val="10"/></font>');
|
||||
fwrite($fd, '<font><name val="Arial"/><family val="0"/><sz val="10"/></font>');
|
||||
fwrite($fd, '<font><name val="Arial"/><family val="0"/><sz val="10"/></font>');
|
||||
fwrite($fd, '</fonts>');
|
||||
fwrite($fd, '<fills count="2"><fill><patternFill patternType="none"/></fill><fill><patternFill patternType="gray125"/></fill></fills>');
|
||||
fwrite($fd, '<borders count="1"><border diagonalDown="false" diagonalUp="false"><left/><right/><top/><bottom/><diagonal/></border></borders>');
|
||||
fwrite($fd, '<cellStyleXfs count="15">');
|
||||
fwrite($fd, '<xf applyAlignment="true" applyBorder="true" applyFont="true" applyProtection="true" borderId="0" fillId="0" fontId="0" numFmtId="164">');
|
||||
fwrite($fd, '<alignment horizontal="general" indent="0" shrinkToFit="false" textRotation="0" vertical="bottom" wrapText="false"/>');
|
||||
fwrite($fd, '<protection hidden="false" locked="true"/>');
|
||||
fwrite($fd, '</xf>');
|
||||
fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="1" numFmtId="0"/>');
|
||||
fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="1" numFmtId="0"/>');
|
||||
fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="2" numFmtId="0"/>');
|
||||
fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="2" numFmtId="0"/>');
|
||||
fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="0" numFmtId="0"/>');
|
||||
fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="0" numFmtId="0"/>');
|
||||
fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="0" numFmtId="0"/>');
|
||||
fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="0" numFmtId="0"/>');
|
||||
fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="0" numFmtId="0"/>');
|
||||
fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="0" numFmtId="0"/>');
|
||||
fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="0" numFmtId="0"/>');
|
||||
fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="0" numFmtId="0"/>');
|
||||
fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="0" numFmtId="0"/>');
|
||||
fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="0" numFmtId="0"/>');
|
||||
//fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="1" numFmtId="43"/>');
|
||||
//fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="1" numFmtId="41"/>');
|
||||
//fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="1" numFmtId="44"/>');
|
||||
//fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="1" numFmtId="42"/>');
|
||||
//fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="true" applyProtection="false" borderId="0" fillId="0" fontId="1" numFmtId="9"/>');
|
||||
fwrite($fd, '</cellStyleXfs>');
|
||||
fwrite($fd, '<cellXfs count="4">');
|
||||
fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="false" applyProtection="false" borderId="0" fillId="0" fontId="0" numFmtId="164" xfId="0"/>');
|
||||
fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="false" applyProtection="false" borderId="0" fillId="0" fontId="0" numFmtId="165" xfId="0"/>');
|
||||
fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="false" applyProtection="false" borderId="0" fillId="0" fontId="0" numFmtId="166" xfId="0"/>');
|
||||
fwrite($fd, '<xf applyAlignment="false" applyBorder="false" applyFont="false" applyProtection="false" borderId="0" fillId="0" fontId="0" numFmtId="167" xfId="0"/>');
|
||||
fwrite($fd, '</cellXfs>');
|
||||
fwrite($fd, '<cellStyles count="1">');
|
||||
fwrite($fd, '<cellStyle builtinId="0" customBuiltin="false" name="Normal" xfId="0"/>');
|
||||
//fwrite($fd, '<cellStyle builtinId="3" customBuiltin="false" name="Comma" xfId="15"/>');
|
||||
//fwrite($fd, '<cellStyle builtinId="6" customBuiltin="false" name="Comma [0]" xfId="16"/>');
|
||||
//fwrite($fd, '<cellStyle builtinId="4" customBuiltin="false" name="Currency" xfId="17"/>');
|
||||
//fwrite($fd, '<cellStyle builtinId="7" customBuiltin="false" name="Currency [0]" xfId="18"/>');
|
||||
//fwrite($fd, '<cellStyle builtinId="5" customBuiltin="false" name="Percent" xfId="19"/>');
|
||||
fwrite($fd, '</cellStyles>');
|
||||
fwrite($fd, '</styleSheet>');
|
||||
fclose($fd);
|
||||
return $tempfile;
|
||||
}
|
||||
|
||||
protected function setSharedString($v)
|
||||
{
|
||||
// Strip control characters which Excel does not seem to like...
|
||||
$v = preg_replace('/[\x00-\x09\x0B\x0C\x0E-\x1F]/u', '', $v);
|
||||
if (isset($this->shared_strings[$v]))
|
||||
{
|
||||
$string_value = $this->shared_strings[$v];
|
||||
}
|
||||
else
|
||||
{
|
||||
$string_value = count($this->shared_strings);
|
||||
$this->shared_strings[$v] = $string_value;
|
||||
}
|
||||
$this->shared_string_count++;//non-unique count
|
||||
return $string_value;
|
||||
}
|
||||
|
||||
protected function writeSharedStringsXML()
|
||||
{
|
||||
$tempfile = $this->tempFilename();
|
||||
$fd = fopen($tempfile, "w+");
|
||||
if ($fd===false) { self::log("write failed in ".__CLASS__."::".__FUNCTION__."."); return; }
|
||||
|
||||
fwrite($fd,'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'."\n");
|
||||
fwrite($fd,'<sst count="'.($this->shared_string_count).'" uniqueCount="'.count($this->shared_strings).'" xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">');
|
||||
foreach($this->shared_strings as $s=>$c)
|
||||
{
|
||||
fwrite($fd,'<si><t>'.self::xmlspecialchars($s).'</t></si>');
|
||||
}
|
||||
fwrite($fd, '</sst>');
|
||||
fclose($fd);
|
||||
return $tempfile;
|
||||
}
|
||||
|
||||
protected function buildAppXML()
|
||||
{
|
||||
$app_xml="";
|
||||
$app_xml.='<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'."\n";
|
||||
$app_xml.='<Properties xmlns="http://schemas.openxmlformats.org/officeDocument/2006/extended-properties" xmlns:vt="http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes"><TotalTime>0</TotalTime></Properties>';
|
||||
return $app_xml;
|
||||
}
|
||||
|
||||
protected function buildCoreXML()
|
||||
{
|
||||
$core_xml="";
|
||||
$core_xml.='<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'."\n";
|
||||
$core_xml.='<cp:coreProperties xmlns:cp="http://schemas.openxmlformats.org/package/2006/metadata/core-properties" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dcmitype="http://purl.org/dc/dcmitype/" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">';
|
||||
$core_xml.='<dcterms:created xsi:type="dcterms:W3CDTF">'.date("Y-m-d\TH:i:s.00\Z").'</dcterms:created>';//$date_time = '2013-07-25T15:54:37.00Z';
|
||||
$core_xml.='<dc:creator>'.self::xmlspecialchars($this->author).'</dc:creator>';
|
||||
$core_xml.='<cp:revision>0</cp:revision>';
|
||||
$core_xml.='</cp:coreProperties>';
|
||||
return $core_xml;
|
||||
}
|
||||
|
||||
protected function buildRelationshipsXML()
|
||||
{
|
||||
$rels_xml="";
|
||||
$rels_xml.='<?xml version="1.0" encoding="UTF-8"?>'."\n";
|
||||
$rels_xml.='<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">';
|
||||
$rels_xml.='<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="xl/workbook.xml"/>';
|
||||
$rels_xml.='<Relationship Id="rId2" Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties" Target="docProps/core.xml"/>';
|
||||
$rels_xml.='<Relationship Id="rId3" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties" Target="docProps/app.xml"/>';
|
||||
$rels_xml.="\n";
|
||||
$rels_xml.='</Relationships>';
|
||||
return $rels_xml;
|
||||
}
|
||||
|
||||
protected function buildWorkbookXML()
|
||||
{
|
||||
$workbook_xml="";
|
||||
$workbook_xml.='<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'."\n";
|
||||
$workbook_xml.='<workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">';
|
||||
$workbook_xml.='<fileVersion appName="Calc"/><workbookPr backupFile="false" showObjects="all" date1904="false"/><workbookProtection/>';
|
||||
$workbook_xml.='<bookViews><workbookView activeTab="0" firstSheet="0" showHorizontalScroll="true" showSheetTabs="true" showVerticalScroll="true" tabRatio="212" windowHeight="8192" windowWidth="16384" xWindow="0" yWindow="0"/></bookViews>';
|
||||
$workbook_xml.='<sheets>';
|
||||
foreach($this->sheets_meta as $i=>$sheet_meta) {
|
||||
$workbook_xml.='<sheet name="'.self::xmlspecialchars($sheet_meta['sheetname']).'" sheetId="'.($i+1).'" state="visible" r:id="rId'.($i+2).'"/>';
|
||||
}
|
||||
$workbook_xml.='</sheets>';
|
||||
$workbook_xml.='<calcPr iterateCount="100" refMode="A1" iterate="false" iterateDelta="0.001"/></workbook>';
|
||||
return $workbook_xml;
|
||||
}
|
||||
|
||||
protected function buildWorkbookRelsXML()
|
||||
{
|
||||
$wkbkrels_xml="";
|
||||
$wkbkrels_xml.='<?xml version="1.0" encoding="UTF-8"?>'."\n";
|
||||
$wkbkrels_xml.='<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">';
|
||||
$wkbkrels_xml.='<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" Target="styles.xml"/>';
|
||||
foreach($this->sheets_meta as $i=>$sheet_meta) {
|
||||
$wkbkrels_xml.='<Relationship Id="rId'.($i+2).'" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Target="worksheets/'.($sheet_meta['xmlname']).'"/>';
|
||||
}
|
||||
if (!empty($this->shared_strings)) {
|
||||
$wkbkrels_xml.='<Relationship Id="rId'.(count($this->sheets_meta)+2).'" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings" Target="sharedStrings.xml"/>';
|
||||
}
|
||||
$wkbkrels_xml.="\n";
|
||||
$wkbkrels_xml.='</Relationships>';
|
||||
return $wkbkrels_xml;
|
||||
}
|
||||
|
||||
protected function buildContentTypesXML()
|
||||
{
|
||||
$content_types_xml="";
|
||||
$content_types_xml.='<?xml version="1.0" encoding="UTF-8"?>'."\n";
|
||||
$content_types_xml.='<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">';
|
||||
$content_types_xml.='<Override PartName="/_rels/.rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>';
|
||||
$content_types_xml.='<Override PartName="/xl/_rels/workbook.xml.rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>';
|
||||
foreach($this->sheets_meta as $i=>$sheet_meta) {
|
||||
$content_types_xml.='<Override PartName="/xl/worksheets/'.($sheet_meta['xmlname']).'" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"/>';
|
||||
}
|
||||
if (!empty($this->shared_strings)) {
|
||||
$content_types_xml.='<Override PartName="/xl/sharedStrings.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml"/>';
|
||||
}
|
||||
$content_types_xml.='<Override PartName="/xl/workbook.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"/>';
|
||||
$content_types_xml.='<Override PartName="/xl/styles.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml"/>';
|
||||
$content_types_xml.='<Override PartName="/docProps/app.xml" ContentType="application/vnd.openxmlformats-officedocument.extended-properties+xml"/>';
|
||||
$content_types_xml.='<Override PartName="/docProps/core.xml" ContentType="application/vnd.openxmlformats-package.core-properties+xml"/>';
|
||||
$content_types_xml.="\n";
|
||||
$content_types_xml.='</Types>';
|
||||
return $content_types_xml;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/*
|
||||
* @param $row_number int, zero based
|
||||
* @param $column_number int, zero based
|
||||
* @return Cell label/coordinates, ex: A1, C3, AA42
|
||||
* */
|
||||
public static function xlsCell($row_number, $column_number)
|
||||
{
|
||||
$n = $column_number;
|
||||
for($r = ""; $n >= 0; $n = intval($n / 26) - 1) {
|
||||
$r = chr($n%26 + 0x41) . $r;
|
||||
}
|
||||
return $r . ($row_number+1);
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
public static function log($string)
|
||||
{
|
||||
file_put_contents("php://stderr", date("Y-m-d H:i:s:").rtrim(is_array($string) ? json_encode($string) : $string)."\n");
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
public static function xmlspecialchars($val)
|
||||
{
|
||||
return str_replace("'", "'", htmlspecialchars($val));
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
public static function array_first_key(array $arr)
|
||||
{
|
||||
reset($arr);
|
||||
$first_key = key($arr);
|
||||
return $first_key;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
public static function convert_date_time($date_input) //thanks to Excel::Writer::XLSX::Worksheet.pm (perl)
|
||||
{
|
||||
$days = 0; # Number of days since epoch
|
||||
$seconds = 0; # Time expressed as fraction of 24h hours in seconds
|
||||
$year=$month=$day=0;
|
||||
$hour=$min =$sec=0;
|
||||
|
||||
$date_time = $date_input;
|
||||
if (preg_match("/(\d{4})\-(\d{2})\-(\d{2})/", $date_time, $matches))
|
||||
{
|
||||
list($junk,$year,$month,$day) = $matches;
|
||||
}
|
||||
if (preg_match("/(\d{2}):(\d{2}):(\d{2})/", $date_time, $matches))
|
||||
{
|
||||
list($junk,$hour,$min,$sec) = $matches;
|
||||
$seconds = ( $hour * 60 * 60 + $min * 60 + $sec ) / ( 24 * 60 * 60 );
|
||||
}
|
||||
|
||||
//using 1900 as epoch, not 1904, ignoring 1904 special case
|
||||
|
||||
# Special cases for Excel.
|
||||
if ("$year-$month-$day"=='1899-12-31') return $seconds ; # Excel 1900 epoch
|
||||
if ("$year-$month-$day"=='1900-01-00') return $seconds ; # Excel 1900 epoch
|
||||
if ("$year-$month-$day"=='1900-02-29') return 60 + $seconds ; # Excel false leapday
|
||||
|
||||
# We calculate the date by calculating the number of days since the epoch
|
||||
# and adjust for the number of leap days. We calculate the number of leap
|
||||
# days by normalising the year in relation to the epoch. Thus the year 2000
|
||||
# becomes 100 for 4 and 100 year leapdays and 400 for 400 year leapdays.
|
||||
$epoch = 1900;
|
||||
$offset = 0;
|
||||
$norm = 300;
|
||||
$range = $year - $epoch;
|
||||
|
||||
# Set month days and check for leap year.
|
||||
$leap = (($year % 400 == 0) || (($year % 4 == 0) && ($year % 100)) ) ? 1 : 0;
|
||||
$mdays = array( 31, ($leap ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 );
|
||||
|
||||
# Some boundary checks
|
||||
if($year < $epoch || $year > 9999) return 0;
|
||||
if($month < 1 || $month > 12) return 0;
|
||||
if($day < 1 || $day > $mdays[ $month - 1 ]) return 0;
|
||||
|
||||
# Accumulate the number of days since the epoch.
|
||||
$days = $day; # Add days for current month
|
||||
$days += array_sum( array_slice($mdays, 0, $month-1 ) ); # Add days for past months
|
||||
$days += $range * 365; # Add days for past years
|
||||
$days += intval( ( $range ) / 4 ); # Add leapdays
|
||||
$days -= intval( ( $range + $offset ) / 100 ); # Subtract 100 year leapdays
|
||||
$days += intval( ( $range + $offset + $norm ) / 400 ); # Add 400 year leapdays
|
||||
$days -= $leap; # Already counted above
|
||||
|
||||
# Adjust for Excel erroneously treating 1900 as a leap year.
|
||||
if ($days > 59) { $days++;}
|
||||
|
||||
return $days + $seconds;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
// Copyright (C) 2010-2013 Combodo SARL
|
||||
// Copyright (C) 2010-2014 Combodo SARL
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
@@ -51,6 +51,9 @@ class XMLPage extends WebPage
|
||||
{
|
||||
if (!$this->m_bPassThrough)
|
||||
{
|
||||
// Get the unexpected output but do nothing with it
|
||||
$sTrash = $this->ob_get_clean_safe();
|
||||
|
||||
$this->s_content = "<?xml version=\"1.0\" encoding=\"UTF-8\"?".">\n".trim($this->s_content);
|
||||
$this->add_header("Content-Length: ".strlen($this->s_content));
|
||||
foreach($this->a_headers as $s_header)
|
||||
@@ -79,8 +82,7 @@ class XMLPage extends WebPage
|
||||
}
|
||||
else
|
||||
{
|
||||
$s_captured_output = ob_get_contents();
|
||||
ob_end_clean();
|
||||
$s_captured_output = $this->ob_get_clean_safe();
|
||||
foreach($this->a_headers as $s_header)
|
||||
{
|
||||
header($s_header);
|
||||
@@ -101,13 +103,4 @@ class XMLPage extends WebPage
|
||||
public function table($aConfig, $aData, $aParams = array())
|
||||
{
|
||||
}
|
||||
|
||||
public function TrashUnexpectedOutput()
|
||||
{
|
||||
if (!$this->m_bPassThrough)
|
||||
{
|
||||
parent::TrashUnexpectedOutput();
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -91,6 +91,9 @@ abstract class AsyncTask extends DBObject
|
||||
MetaModel::Init_AddAttribute(new AttributeExternalKey("event_id", array("targetclass"=>"Event", "jointype"=> "", "allowed_values"=>null, "sql"=>"event_id", "is_null_allowed"=>true, "on_target_delete"=>DEL_SILENT, "depends_on"=>array())));
|
||||
|
||||
MetaModel::Init_AddAttribute(new AttributeInteger("remaining_retries", array("allowed_values"=>null, "sql"=>"remaining_retries", "default_value"=>0, "is_null_allowed"=>true, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeInteger("last_error_code", array("allowed_values"=>null, "sql"=>"last_error_code", "default_value"=>0, "is_null_allowed"=>true, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeString("last_error", array("allowed_values"=>null, "sql"=>"last_error", "default_value"=>'', "is_null_allowed"=>true, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeDateTime("last_attempt", array("allowed_values"=>null, "sql"=>"last_attempt", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -117,27 +120,34 @@ abstract class AsyncTask extends DBObject
|
||||
{
|
||||
try
|
||||
{
|
||||
$this->Set('status', 'running');
|
||||
$this->Set('started', time());
|
||||
$this->DBUpdate();
|
||||
return self::OK;
|
||||
if ($this->Get('status') == 'running')
|
||||
{
|
||||
return self::ALREADY_RUNNING;
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->Set('status', 'running');
|
||||
$this->Set('started', time());
|
||||
$this->DBUpdate();
|
||||
return self::OK;
|
||||
}
|
||||
}
|
||||
catch(Exception $e)
|
||||
{
|
||||
// Corrupted task !! (for example: "Failed to reload object")
|
||||
IssueLog::Error('Failed to process async task #'.$this->GetKey().' - reason: '.$e->getMessage().' - fatal error, deleting the task.');
|
||||
if ($this->Get('event_id') != 0)
|
||||
{
|
||||
$oEventLog = MetaModel::GetObject('Event', $this->Get('event_id'));
|
||||
$oEventLog->Set('message', 'Failed, corrupted data: '.$e->getMessage());
|
||||
$oEventLog->DBUpdate();
|
||||
if ($this->Get('event_id') != 0)
|
||||
{
|
||||
$oEventLog = MetaModel::GetObject('Event', $this->Get('event_id'));
|
||||
$oEventLog->Set('message', 'Failed, corrupted data: '.$e->getMessage());
|
||||
$oEventLog->DBUpdate();
|
||||
}
|
||||
$this->DBDelete();
|
||||
return self::DELETED;
|
||||
}
|
||||
}
|
||||
|
||||
public function GetRetryDelay()
|
||||
public function GetRetryDelay($iErrorCode = null)
|
||||
{
|
||||
$iRetryDelay = 600;
|
||||
$aRetries = MetaModel::GetConfig()->Get('async_task_retries', array());
|
||||
@@ -149,7 +159,7 @@ abstract class AsyncTask extends DBObject
|
||||
return $iRetryDelay;
|
||||
}
|
||||
|
||||
public function GetMaxRetries()
|
||||
public function GetMaxRetries($iErrorCode = null)
|
||||
{
|
||||
$iMaxRetries = 0;
|
||||
$aRetries = MetaModel::GetConfig()->Get('async_task_retries', array());
|
||||
@@ -160,10 +170,16 @@ abstract class AsyncTask extends DBObject
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Override to notify people that a task cannot be performed
|
||||
*/
|
||||
protected function OnDefinitiveFailure()
|
||||
{
|
||||
}
|
||||
|
||||
protected function OnInsert()
|
||||
{
|
||||
$this->Set('created', time());
|
||||
$this->Set('remaining_retries', $this->GetMaxRetries());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -191,22 +207,7 @@ abstract class AsyncTask extends DBObject
|
||||
}
|
||||
catch(Exception $e)
|
||||
{
|
||||
$iRemaining = $this->Get('remaining_retries');
|
||||
if ($iRemaining > 0)
|
||||
{
|
||||
$iRetryDelay = $this->GetRetryDelay();
|
||||
IssueLog::Info('Failed to process async task #'.$this->GetKey().' - reason: '.$e->getMessage().' - remaining retries: '.$iRemaining.' - next retry in '.$iRetryDelay.'s');
|
||||
|
||||
$this->Set('remaining_retries', $iRemaining - 1);
|
||||
$this->Set('status', 'planned');
|
||||
$this->Set('started', null);
|
||||
$this->Set('planned', time() + $iRetryDelay);
|
||||
$this->DBUpdate();
|
||||
}
|
||||
else
|
||||
{
|
||||
IssueLog::Error('Failed to process async task #'.$this->GetKey().' - reason: '.$e->getMessage());
|
||||
}
|
||||
$this->HandleError($e->getMessage(), $e->getCode());
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -217,7 +218,56 @@ abstract class AsyncTask extends DBObject
|
||||
return $bRet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overridable to extend the behavior in case of error (logging)
|
||||
*/
|
||||
protected function HandleError($sErrorMessage, $iErrorCode)
|
||||
{
|
||||
if ($this->Get('last_attempt') == '')
|
||||
{
|
||||
// First attempt
|
||||
$this->Set('remaining_retries', $this->GetMaxRetries($iErrorCode));
|
||||
}
|
||||
|
||||
$this->Set('last_error', $sErrorMessage);
|
||||
$this->Set('last_error_code', $iErrorCode); // Note: can be ZERO !!!
|
||||
$this->Set('last_attempt', time());
|
||||
|
||||
$iRemaining = $this->Get('remaining_retries');
|
||||
if ($iRemaining > 0)
|
||||
{
|
||||
$iRetryDelay = $this->GetRetryDelay($iErrorCode);
|
||||
IssueLog::Info('Failed to process async task #'.$this->GetKey().' - reason: '.$sErrorMessage.' - remaining retries: '.$iRemaining.' - next retry in '.$iRetryDelay.'s');
|
||||
|
||||
$this->Set('remaining_retries', $iRemaining - 1);
|
||||
$this->Set('status', 'planned');
|
||||
$this->Set('started', null);
|
||||
$this->Set('planned', time() + $iRetryDelay);
|
||||
}
|
||||
else
|
||||
{
|
||||
IssueLog::Error('Failed to process async task #'.$this->GetKey().' - reason: '.$sErrorMessage);
|
||||
|
||||
$this->Set('status', 'error');
|
||||
$this->Set('started', null);
|
||||
$this->Set('planned', null);
|
||||
$this->OnDefinitiveFailure();
|
||||
}
|
||||
$this->DBUpdate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws an exception (message and code)
|
||||
*/
|
||||
abstract public function DoProcess();
|
||||
|
||||
/**
|
||||
* Describes the error codes that DoProcess can return by the mean of exceptions
|
||||
*/
|
||||
static public function EnumErrorCodes()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -3426,12 +3426,69 @@ class AttributeBlob extends AttributeDefinition
|
||||
}
|
||||
|
||||
|
||||
// Facilitate things: allow the user to Set the value from a string
|
||||
// Facilitate things: allow administrators to upload a document
|
||||
// from a CSV by specifying its path/URL
|
||||
public function MakeRealValue($proposedValue, $oHostObj)
|
||||
{
|
||||
if (!is_object($proposedValue))
|
||||
{
|
||||
return new ormDocument($proposedValue, 'text/plain');
|
||||
if (file_exists($proposedValue) && UserRights::IsAdministrator())
|
||||
{
|
||||
$sContent = file_get_contents($proposedValue);
|
||||
$sExtension = strtolower(pathinfo($proposedValue, PATHINFO_EXTENSION));
|
||||
$sMimeType = "application/x-octoet-stream";
|
||||
$aKnownExtensions = array(
|
||||
'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||
'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
|
||||
'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template',
|
||||
'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow',
|
||||
'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
|
||||
'sldx' => 'application/vnd.openxmlformats-officedocument.presentationml.slide',
|
||||
'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
||||
'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
|
||||
'xlam' => 'application/vnd.ms-excel.addin.macroEnabled.12',
|
||||
'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroEnabled.12.xlsx',
|
||||
'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
|
||||
'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template',
|
||||
'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow',
|
||||
'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
|
||||
'sldx' => 'application/vnd.openxmlformats-officedocument.presentationml.slide',
|
||||
'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
||||
'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
|
||||
'xlam' => 'application/vnd.ms-excel.addin.macroEnabled.12',
|
||||
'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroEnabled.12',
|
||||
'jpg' => 'image/jpeg',
|
||||
'jpeg' => 'image/jpeg',
|
||||
'gif' => 'image/gif',
|
||||
'png' => 'image/png',
|
||||
'pdf' => 'application/pdf',
|
||||
'doc' => 'application/msword',
|
||||
'dot' => 'application/msword',
|
||||
'xls' => 'application/vnd.ms-excel',
|
||||
'ppt' => 'application/vnd.ms-powerpoint',
|
||||
'vsd' => 'application/x-visio',
|
||||
'vdx' => 'application/visio.drawing',
|
||||
'odt' => 'application/vnd.oasis.opendocument.text',
|
||||
'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
|
||||
'odp' => 'application/vnd.oasis.opendocument.presentation',
|
||||
'zip' => 'application/zip',
|
||||
'txt' => 'text/plain',
|
||||
'htm' => 'text/html',
|
||||
'html' => 'text/html',
|
||||
'exe' => 'application/octet-stream'
|
||||
);
|
||||
|
||||
if (!array_key_exists($sExtension, $aKnownExtensions) && extension_loaded('fileinfo'))
|
||||
{
|
||||
$finfo = new finfo(FILEINFO_MIME);
|
||||
$sMimeType = $finfo->file($proposedValue);
|
||||
}
|
||||
return new ormDocument($sContent, $sMimeType);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new ormDocument($proposedValue, 'text/plain');
|
||||
}
|
||||
}
|
||||
return $proposedValue;
|
||||
}
|
||||
@@ -3717,7 +3774,7 @@ class AttributeStopWatch extends AttributeDefinition
|
||||
);
|
||||
|
||||
$aThresholds = array();
|
||||
foreach ($this->ListThresholds() as $iThreshold => $aFoo)
|
||||
foreach ($this->ListThresholds() as $iThreshold => $aDefinition)
|
||||
{
|
||||
$sThPrefix = '_'.$iThreshold;
|
||||
$value->DefineThreshold(
|
||||
@@ -3725,7 +3782,8 @@ class AttributeStopWatch extends AttributeDefinition
|
||||
self::DateToSeconds($aCols[$sPrefix.$sThPrefix.'_deadline']),
|
||||
(bool)($aCols[$sPrefix.$sThPrefix.'_passed'] == 1),
|
||||
(bool)($aCols[$sPrefix.$sThPrefix.'_triggered'] == 1),
|
||||
$aCols[$sPrefix.$sThPrefix.'_overrun']
|
||||
$aCols[$sPrefix.$sThPrefix.'_overrun'],
|
||||
array_key_exists('highlight', $aDefinition) ? $aDefinition['highlight'] : null
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -428,38 +428,38 @@ abstract class CMDBObject extends DBObject
|
||||
}
|
||||
|
||||
|
||||
public function DBInsert()
|
||||
{
|
||||
return $this->DBInsertTracked_Internal();
|
||||
}
|
||||
|
||||
public function DBInsertTracked(CMDBChange $oChange, $bSkipStrongSecurity = null)
|
||||
{
|
||||
self::SetCurrentChange($oChange);
|
||||
$this->CheckUserRights($bSkipStrongSecurity, UR_ACTION_MODIFY);
|
||||
|
||||
$ret = $this->DBInsertTracked_Internal();
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
public function DBInsertTrackedNoReload(CMDBChange $oChange, $bSkipStrongSecurity = null)
|
||||
{
|
||||
self::SetCurrentChange($oChange);
|
||||
$this->CheckUserRights($bSkipStrongSecurity, UR_ACTION_MODIFY);
|
||||
|
||||
$ret = $this->DBInsertTracked_Internal(true);
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* To Be Obsoleted: DO NOT rely on an overload of this method since
|
||||
* DBInsertTracked (resp. DBInsertTrackedNoReload) may call directly
|
||||
* DBInsert (resp. DBInsertNoReload) in future versions of iTop.
|
||||
* @param bool $bDoNotReload
|
||||
* @return integer Identifier of the created object
|
||||
*/
|
||||
protected function DBInsertTracked_Internal($bDoNotReload = false)
|
||||
{
|
||||
if ($bDoNotReload)
|
||||
{
|
||||
$ret = parent::DBInsertNoReload();
|
||||
$ret = $this->DBInsertNoReload();
|
||||
}
|
||||
else
|
||||
{
|
||||
$ret = parent::DBInsert();
|
||||
$ret = $this->DBInsert();
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ class CMDBSource
|
||||
// Override the default port
|
||||
$sServer = $aConnectInfo[0];
|
||||
$iPort = (int)$aConnectInfo[1];
|
||||
self::$m_oMysqli = new mysqli(self::$m_sDBHost, self::$m_sDBUser, self::$m_sDBPwd, '', $iPort);
|
||||
self::$m_oMysqli = new mysqli($sServer, self::$m_sDBUser, self::$m_sDBPwd, '', $iPort);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -769,6 +769,30 @@ class Config
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => false,
|
||||
),
|
||||
'user_rights_legacy' => array(
|
||||
'type' => 'bool',
|
||||
'description' => 'Set to true to restore the buggy algorithm for the computation of user rights (within the same profile, ALLOW on the class itself has precedence on DENY of a parent class)',
|
||||
'default' => false,
|
||||
'value' => '',
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => false,
|
||||
),
|
||||
'xlsx_exporter_cleanup_old_files_delay' => array(
|
||||
'type' => 'int',
|
||||
'description' => 'Delay (in seconds) for which to let the exported XLSX files on the server so that the user who initiated the export can download the result',
|
||||
'default' => 86400,
|
||||
'value' => '',
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => false,
|
||||
),
|
||||
'xlsx_exporter_memory_limit' => array(
|
||||
'type' => 'string',
|
||||
'description' => 'Memory limit to use when (interactively) exporting data to Excel',
|
||||
'default' => '2048M', // Huuuuuuge 2GB!
|
||||
'value' => '',
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => false,
|
||||
),
|
||||
);
|
||||
|
||||
public function IsProperty($sPropCode)
|
||||
|
||||
@@ -94,7 +94,8 @@ 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?)
|
||||
public function __construct($aRow = null, $sClassAlias = '', $aAttToLoad = null, $aExtendedDataSpec = null)
|
||||
@@ -557,6 +558,64 @@ abstract class DBObject implements iDisplay
|
||||
{
|
||||
return $this->m_aExtendedData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the HighlightCode if the given code has a greater rank than the current HilightCode
|
||||
* @param string $sCode
|
||||
* @return void
|
||||
*/
|
||||
protected function SetHighlightCode($sCode)
|
||||
{
|
||||
$aHighlightScale = MetaModel::GetHighlightScale(get_class($this));
|
||||
$fCurrentRank = 0.0;
|
||||
if (($this->m_sHighlightCode !== null) && array_key_exists($this->m_sHighlightCode, $aHighlightScale))
|
||||
{
|
||||
$fCurrentRank = $aHighlightScale[$this->m_sHighlightCode]['rank'];
|
||||
}
|
||||
|
||||
if (array_key_exists($sCode, $aHighlightScale))
|
||||
{
|
||||
$fRank = $aHighlightScale[$sCode]['rank'];
|
||||
if ($fRank > $fCurrentRank)
|
||||
{
|
||||
$this->m_sHighlightCode = $sCode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current HighlightCode
|
||||
* @return string The Hightlight code (null if none set, meaning rank = 0)
|
||||
*/
|
||||
protected function GetHighlightCode()
|
||||
{
|
||||
return $this->m_sHighlightCode;
|
||||
}
|
||||
|
||||
protected function ComputeHighlightCode()
|
||||
{
|
||||
// First if the state defines a HiglightCode, apply it
|
||||
$sState = $this->GetState();
|
||||
if ($sState != '')
|
||||
{
|
||||
$sCode = MetaModel::GetHighlightCode(get_class($this), $sState);
|
||||
$this->SetHighlightCode($sCode);
|
||||
}
|
||||
// The check for each StopWatch if a HighlightCode is effective
|
||||
foreach(MetaModel::ListAttributeDefs(get_class($this)) as $sAttCode => $oAttDef)
|
||||
{
|
||||
if ($oAttDef instanceof AttributeStopWatch)
|
||||
{
|
||||
$oStopWatch = $this->Get($sAttCode);
|
||||
$sCode = $oStopWatch->GetHighlightCode();
|
||||
if ($sCode !== '')
|
||||
{
|
||||
$this->SetHighlightCode($sCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $this->GetHighlightCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the value of an external field by (re)loading the object
|
||||
@@ -785,10 +844,27 @@ abstract class DBObject implements iDisplay
|
||||
/**
|
||||
* Get the icon representing this object
|
||||
* @param boolean $bImgTag If true the result is a full IMG tag (or an emtpy string if no icon is defined)
|
||||
* @return string Either the full IMG tag ($bImgTag == true) or just the path to the icon file
|
||||
* @return string Either the full IMG tag ($bImgTag == true) or just the URL to the icon file
|
||||
*/
|
||||
public function GetIcon($bImgTag = true)
|
||||
{
|
||||
$sCode = $this->ComputeHighlightCode();
|
||||
if($sCode != '')
|
||||
{
|
||||
$aHighlightScale = MetaModel::GetHighlightScale(get_class($this));
|
||||
if (array_key_exists($sCode, $aHighlightScale))
|
||||
{
|
||||
$sIconUrl = $aHighlightScale[$sCode]['icon'];
|
||||
if($bImgTag)
|
||||
{
|
||||
return "<img src=\"$sIconUrl\" style=\"vertical-align:middle\"/>";
|
||||
}
|
||||
else
|
||||
{
|
||||
return $sIconUrl;
|
||||
}
|
||||
}
|
||||
}
|
||||
return MetaModel::GetClassIcon(get_class($this), $bImgTag);
|
||||
}
|
||||
|
||||
@@ -1102,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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1998,17 +2071,55 @@ abstract class DBObject implements iDisplay
|
||||
// array('target_state'=>..., 'actions'=>array of handlers procs, 'user_restriction'=>TBD
|
||||
|
||||
$bSuccess = true;
|
||||
foreach ($aTransitionDef['actions'] as $sActionHandler)
|
||||
foreach ($aTransitionDef['actions'] as $actionHandler)
|
||||
{
|
||||
// std PHP spec
|
||||
$aActionCallSpec = array($this, $sActionHandler);
|
||||
|
||||
if (!is_callable($aActionCallSpec))
|
||||
if (is_string($actionHandler))
|
||||
{
|
||||
throw new CoreException("Unable to call action: ".get_class($this)."::$sActionHandler");
|
||||
return;
|
||||
// Old (pre-2.0.4) action definition without any parameter
|
||||
$aActionCallSpec = array($this, $sActionHandler);
|
||||
|
||||
if (!is_callable($aActionCallSpec))
|
||||
{
|
||||
throw new CoreException("Unable to call action: ".get_class($this)."::$sActionHandler");
|
||||
return;
|
||||
}
|
||||
$bRet = call_user_func($aActionCallSpec, $sStimulusCode);
|
||||
}
|
||||
else // if (is_array($actionHandler))
|
||||
{
|
||||
// New syntax: 'verb' and typed parameters
|
||||
$sAction = $actionHandler['verb'];
|
||||
$aParams = array();
|
||||
foreach($actionHandler['params'] as $aDefinition)
|
||||
{
|
||||
$sParamType = array_key_exists('type', $aDefinition) ? $aDefinition['type'] : 'string';
|
||||
switch($sParamType)
|
||||
{
|
||||
case 'int':
|
||||
$value = (int)$aDefinition['value'];
|
||||
break;
|
||||
|
||||
case 'float':
|
||||
$value = (float)$aDefinition['value'];
|
||||
break;
|
||||
|
||||
case 'bool':
|
||||
$value = (bool)$aDefinition['value'];
|
||||
break;
|
||||
|
||||
case 'reference':
|
||||
$value = ${$aDefinition['value']};
|
||||
break;
|
||||
|
||||
case 'string':
|
||||
default:
|
||||
$value = (string)$aDefinition['value'];
|
||||
}
|
||||
$aParams[] = $value;
|
||||
}
|
||||
$aCallSpec = array($this, $sAction);
|
||||
$bRet = call_user_func_array($aCallSpec, $aParams);
|
||||
}
|
||||
$bRet = call_user_func($aActionCallSpec, $sStimulusCode);
|
||||
// if one call fails, the whole is considered as failed
|
||||
if (!$bRet) $bSuccess = false;
|
||||
}
|
||||
@@ -2474,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);
|
||||
@@ -2563,6 +2706,15 @@ abstract class DBObject implements iDisplay
|
||||
|
||||
public function GetHilightClass()
|
||||
{
|
||||
$sCode = $this->ComputeHighlightCode();
|
||||
if($sCode != '')
|
||||
{
|
||||
$aHighlightScale = MetaModel::GetHighlightScale(get_class($this));
|
||||
if (array_key_exists($sCode, $aHighlightScale))
|
||||
{
|
||||
return $aHighlightScale[$sCode]['color'];
|
||||
}
|
||||
}
|
||||
return HILIGHT_CLASS_NONE;
|
||||
}
|
||||
|
||||
|
||||
@@ -972,6 +972,9 @@ class DBObjectSearch
|
||||
|
||||
// Alternative to object mapping: the data are transfered directly into an array
|
||||
// This is 10 times faster than creating a set of objects, and makes sense when optimization is required
|
||||
/**
|
||||
* @param hash $aOrderBy Array of '[<classalias>.]attcode' => bAscending
|
||||
*/
|
||||
public function ToDataArray($aColumns = array(), $aOrderBy = array(), $aArgs = array())
|
||||
{
|
||||
$sSQL = MetaModel::MakeSelectQuery($this, $aOrderBy, $aArgs);
|
||||
|
||||
@@ -48,7 +48,7 @@ class DBObjectSet
|
||||
* Create a new set based on a Search definition.
|
||||
*
|
||||
* @param DBObjectSearch $oFilter The search filter defining the objects which are part of the set (multiple columns/objects per row are supported)
|
||||
* @param hash $aOrderBy
|
||||
* @param hash $aOrderBy Array of '[<classalias>.]attcode' => bAscending
|
||||
* @param hash $aArgs Values to substitute for the search/query parameters (if any). Format: param_name => value
|
||||
* @param hash $aExtendedDataSpec
|
||||
* @param int $iLimitCount Maximum number of rows to load (i.e. equivalent to MySQL's LIMIT start, count)
|
||||
@@ -654,7 +654,11 @@ class DBObjectSet
|
||||
else
|
||||
{
|
||||
// Pick the row from the objects added *in memory*
|
||||
$oRetObj = $this->m_aAddedObjects[$this->m_iCurrRow - $this->m_iNumLoadedDBRows][$sRequestedClassAlias];
|
||||
$aRetObjects = array();
|
||||
foreach ($this->m_oFilter->GetSelectedClasses() as $sClassAlias => $sClass)
|
||||
{
|
||||
$aRetObjects[$sClassAlias] = $this->m_aAddedObjects[$this->m_iCurrRow - $this->m_iNumLoadedDBRows][$sClassAlias];
|
||||
}
|
||||
}
|
||||
$this->m_iCurrRow++;
|
||||
return $aRetObjects;
|
||||
@@ -1094,8 +1098,11 @@ class DBObjectSet
|
||||
{
|
||||
foreach($aVals as $sCode => $oExpr)
|
||||
{
|
||||
$oScalarExpr = $oExpr->GetAsScalar($aScalarArgs);
|
||||
$aConst[$sClassAlias][$sCode] = $oScalarExpr->GetValue();
|
||||
if (is_object($oExpr)) // Array_merge_recursive creates an array when the same key is present multiple times... ignore them
|
||||
{
|
||||
$oScalarExpr = $oExpr->GetAsScalar($aScalarArgs);
|
||||
$aConst[$sClassAlias][$sCode] = $oScalarExpr->GetValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
return $aConst;
|
||||
@@ -1149,5 +1156,3 @@ function HashCountComparison($a, $b) // Sort descending on 'count'
|
||||
}
|
||||
return ($a['count'] > $b['count']) ? -1 : 1;
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
@@ -177,6 +177,15 @@ class EMail
|
||||
}
|
||||
break;
|
||||
|
||||
case 'Null':
|
||||
$oTransport = Swift_NullTransport::newInstance();
|
||||
break;
|
||||
|
||||
case 'LogFile':
|
||||
$oTransport = Swift_LogFileTransport::newInstance();
|
||||
$oTransport->setLogFile(APPROOT.'log/mail.log');
|
||||
break;
|
||||
|
||||
case 'PHPMail':
|
||||
default:
|
||||
$oTransport = Swift_MailTransport::newInstance();
|
||||
@@ -396,4 +405,75 @@ class EMail
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Extension to SwiftMailer: "debug" transport that pretends messages have been sent,
|
||||
* but just log them to a file.
|
||||
*
|
||||
* @package Swift
|
||||
* @author Denis Flaven
|
||||
*/
|
||||
class Swift_Transport_LogFileTransport extends Swift_Transport_NullTransport
|
||||
{
|
||||
protected $sLogFile;
|
||||
|
||||
/**
|
||||
* Sends the given message.
|
||||
*
|
||||
* @param Swift_Mime_Message $message
|
||||
* @param string[] $failedRecipients An array of failures by-reference
|
||||
*
|
||||
* @return int The number of sent emails
|
||||
*/
|
||||
public function send(Swift_Mime_Message $message, &$failedRecipients = null)
|
||||
{
|
||||
$hFile = @fopen($this->sLogFile, 'a');
|
||||
if ($hFile)
|
||||
{
|
||||
$sTxt = "================== ".date('Y-m-d H:i:s')." ==================\n";
|
||||
$sTxt .= $message->toString()."\n";
|
||||
|
||||
@fwrite($hFile, $sTxt);
|
||||
@fclose($hFile);
|
||||
}
|
||||
|
||||
return parent::send($message, $failedRecipients);
|
||||
}
|
||||
|
||||
public function setLogFile($sFilename)
|
||||
{
|
||||
$this->sLogFile = $sFilename;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pretends messages have been sent, but just log them to a file.
|
||||
*
|
||||
* @package Swift
|
||||
* @author Denis Flaven
|
||||
*/
|
||||
class Swift_LogFileTransport extends Swift_Transport_LogFileTransport
|
||||
{
|
||||
/**
|
||||
* Create a new LogFileTransport.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
call_user_func_array(
|
||||
array($this, 'Swift_Transport_LogFileTransport::__construct'),
|
||||
Swift_DependencyContainer::getInstance()
|
||||
->createDependenciesFor('transport.null')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new LogFileTransport instance.
|
||||
*
|
||||
* @return Swift_LogFileTransport
|
||||
*/
|
||||
public static function newInstance()
|
||||
{
|
||||
return new self();
|
||||
}
|
||||
}
|
||||
@@ -351,7 +351,7 @@ class EventLoginUsage extends Event
|
||||
MetaModel::Init_Params($aParams);
|
||||
MetaModel::Init_InheritAttributes();
|
||||
|
||||
MetaModel::Init_AddAttribute(new AttributeExternalKey("user_id", array("targetclass"=>"User", "jointype"=> "", "allowed_values"=>null, "sql"=>"user_id", "is_null_allowed"=>false, "on_target_delete"=>DEL_MANUAL, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeExternalKey("user_id", array("targetclass"=>"User", "jointype"=> "", "allowed_values"=>null, "sql"=>"user_id", "is_null_allowed"=>false, "on_target_delete"=>DEL_SILENT, "depends_on"=>array())));
|
||||
$aZList = array('date', 'user_id');
|
||||
if (MetaModel::IsValidAttCode('Contact', 'name'))
|
||||
{
|
||||
|
||||
@@ -299,14 +299,11 @@ class BinaryExpression extends Expression
|
||||
{
|
||||
$aResult[$this->m_oRightExpr->GetParent()][$this->m_oRightExpr->GetName()] = $this->m_oLeftExpr;
|
||||
}
|
||||
else
|
||||
{
|
||||
$aResult = array_merge($this->m_oRightExpr->ListConstantFields(), $this->m_oLeftExpr->ListConstantFields()) ;
|
||||
}
|
||||
}
|
||||
else
|
||||
else if ($this->m_sOperator == 'AND')
|
||||
{
|
||||
$aResult = array_merge($this->m_oRightExpr->ListConstantFields(), $this->m_oLeftExpr->ListConstantFields()) ;
|
||||
// Strictly, this should be done only for the AND operator
|
||||
$aResult = array_merge_recursive($this->m_oRightExpr->ListConstantFields(), $this->m_oLeftExpr->ListConstantFields());
|
||||
}
|
||||
return $aResult;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
// Copyright (C) 2010-2013 Combodo SARL
|
||||
// Copyright (C) 2010-2014 Combodo SARL
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
@@ -279,6 +279,7 @@ abstract class MetaModel
|
||||
private static $m_aChildClasses = array(); // array of ("classname" => array of "childclass")
|
||||
|
||||
private static $m_aClassParams = array(); // array of ("classname" => array of class information)
|
||||
private static $m_aHighlightScales = array(); // array of ("classname" => array of highlightscale information)
|
||||
|
||||
static public function GetParentPersistentClass($sRefClass)
|
||||
{
|
||||
@@ -1908,6 +1909,50 @@ abstract class MetaModel
|
||||
self::$m_aTransitions[$sTargetClass][$sStateCode] = array();
|
||||
}
|
||||
|
||||
public static function Init_DefineHighlightScale($aHighlightScale)
|
||||
{
|
||||
$sTargetClass = self::GetCallersPHPClass("Init");
|
||||
self::$m_aHighlightScales[$sTargetClass] = $aHighlightScale;
|
||||
}
|
||||
|
||||
public static function GetHighlightScale($sTargetClass)
|
||||
{
|
||||
$aScale = array();
|
||||
$aParentScale = array();
|
||||
$sParentClass = self::GetParentPersistentClass($sTargetClass);
|
||||
if (!empty($sParentClass))
|
||||
{
|
||||
// inherit the scale from the parent class
|
||||
$aParentScale = self::GetHighlightScale($sParentClass);
|
||||
}
|
||||
if (array_key_exists($sTargetClass, self::$m_aHighlightScales))
|
||||
{
|
||||
$aScale = self::$m_aHighlightScales[$sTargetClass];
|
||||
}
|
||||
return array_merge($aParentScale, $aScale); // Merge both arrays, the values from the last one have precedence
|
||||
}
|
||||
|
||||
public static function GetHighlightCode($sTargetClass, $sStateCode)
|
||||
{
|
||||
$sCode = '';
|
||||
if ( array_key_exists($sTargetClass, self::$m_aStates)
|
||||
&& array_key_exists($sStateCode, self::$m_aStates[$sTargetClass])
|
||||
&& array_key_exists('highlight', self::$m_aStates[$sTargetClass][$sStateCode]) )
|
||||
{
|
||||
$sCode = self::$m_aStates[$sTargetClass][$sStateCode]['highlight']['code'];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check the parent's definition
|
||||
$sParentClass = self::GetParentPersistentClass($sTargetClass);
|
||||
if (!empty($sParentClass))
|
||||
{
|
||||
$sCode = self::GetHighlightCode($sParentClass, $sStateCode);
|
||||
}
|
||||
}
|
||||
return $sCode;
|
||||
}
|
||||
|
||||
public static function Init_OverloadStateAttribute($sStateCode, $sAttCode, $iFlags)
|
||||
{
|
||||
// Warning: this is not sufficient: the flags have to be copied to the states that are inheriting from this state
|
||||
@@ -2122,6 +2167,10 @@ abstract class MetaModel
|
||||
{
|
||||
$aScalarArgs[$sArgName] = (string) $value;
|
||||
}
|
||||
elseif (is_null($value))
|
||||
{
|
||||
$aScalarArgs[$sArgName] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Add standard contextual arguments
|
||||
@@ -2169,6 +2218,9 @@ abstract class MetaModel
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param hash $aOrderBy Array of '[<classalias>.]attcode' => bAscending
|
||||
*/
|
||||
public static function MakeSelectQuery(DBObjectSearch $oFilter, $aOrderBy = array(), $aArgs = array(), $aAttToLoad = null, $aExtendedDataSpec = null, $iLimitCount = 0, $iLimitStart = 0, $bGetCount = false)
|
||||
{
|
||||
// Check the order by specification, and prefix with the class alias
|
||||
@@ -2179,32 +2231,44 @@ abstract class MetaModel
|
||||
$aOrderSpec = array();
|
||||
foreach ($aOrderBy as $sFieldAlias => $bAscending)
|
||||
{
|
||||
if ($sFieldAlias != 'id')
|
||||
{
|
||||
MyHelpers::CheckValueInArray('field name in ORDER BY spec', $sFieldAlias, self::GetAttributesList($sClass));
|
||||
}
|
||||
if (!is_bool($bAscending))
|
||||
{
|
||||
throw new CoreException("Wrong direction in ORDER BY spec, found '$bAscending' and expecting a boolean value");
|
||||
}
|
||||
|
||||
if (self::IsValidAttCode($sClass, $sFieldAlias))
|
||||
|
||||
$iDotPos = strpos($sFieldAlias, '.');
|
||||
if ($iDotPos === false)
|
||||
{
|
||||
$oAttDef = self::GetAttributeDef($sClass, $sFieldAlias);
|
||||
foreach($oAttDef->GetOrderBySQLExpressions($sClassAlias) as $sSQLExpression)
|
||||
$sAttClass = $sClass;
|
||||
$sAttClassAlias = $sClassAlias;
|
||||
$sAttCode = $sFieldAlias;
|
||||
}
|
||||
else
|
||||
{
|
||||
$sAttClassAlias = substr($sFieldAlias, 0, $iDotPos);
|
||||
$sAttClass = $oFilter->GetClassName($sAttClassAlias);
|
||||
$sAttCode = substr($sFieldAlias, $iDotPos + 1);
|
||||
}
|
||||
|
||||
if ($sAttCode != 'id')
|
||||
{
|
||||
MyHelpers::CheckValueInArray('field name in ORDER BY spec', $sAttCode, self::GetAttributesList($sAttClass));
|
||||
|
||||
$oAttDef = self::GetAttributeDef($sAttClass, $sAttCode);
|
||||
foreach($oAttDef->GetOrderBySQLExpressions($sAttClassAlias) as $sSQLExpression)
|
||||
{
|
||||
$aOrderSpec[$sSQLExpression] = $bAscending;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$aOrderSpec['`'.$sClassAlias.$sFieldAlias.'`'] = $bAscending;
|
||||
$aOrderSpec['`'.$sAttClassAlias.$sAttCode.'`'] = $bAscending;
|
||||
}
|
||||
|
||||
// Make sure that the columns used for sorting are present in the loaded columns
|
||||
if (!is_null($aAttToLoad) && !isset($aAttToLoad[$sClassAlias][$sFieldAlias]))
|
||||
if (!is_null($aAttToLoad) && !isset($aAttToLoad[$sAttClassAlias][$sAttCode]))
|
||||
{
|
||||
$aAttToLoad[$sClassAlias][$sFieldAlias] = MetaModel::GetAttributeDef($sClass, $sFieldAlias);
|
||||
$aAttToLoad[$sAttClassAlias][$sAttCode] = MetaModel::GetAttributeDef($sAttClass, $sAttCode);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3386,6 +3450,33 @@ abstract class MetaModel
|
||||
{
|
||||
// Do nothing...
|
||||
}
|
||||
else if ($oAttDef instanceof AttributeStopWatch)
|
||||
{
|
||||
$aThresholds = $oAttDef->ListThresholds();
|
||||
if (is_array($aThresholds))
|
||||
{
|
||||
foreach($aThresholds as $iPercent => $aDef)
|
||||
{
|
||||
if (array_key_exists('highlight', $aDef))
|
||||
{
|
||||
if(!array_key_exists('code', $aDef['highlight']))
|
||||
{
|
||||
$aErrors[$sClass][] = "The 'code' element is missing for the 'highlight' property of the $iPercent% threshold in the attribute: '$sAttCode'.";
|
||||
$aSugFix[$sClass][] = "Add a 'code' entry specifying the value of the highlight code for this threshold.";
|
||||
}
|
||||
else
|
||||
{
|
||||
$aScale = self::GetHighlightScale($sClass);
|
||||
if (!array_key_exists($aDef['highlight']['code'], $aScale))
|
||||
{
|
||||
$aErrors[$sClass][] = "'{$aDef['highlight']['code']}' is not a valid value for the 'code' element of the $iPercent% threshold in the attribute: '$sAttCode'.";
|
||||
$aSugFix[$sClass][] = "The possible highlight codes for this class are: ".implode(', ', array_keys($aScale)).".";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else // standard attributes
|
||||
{
|
||||
// Check that the default values definition is a valid object!
|
||||
@@ -3483,17 +3574,46 @@ abstract class MetaModel
|
||||
}
|
||||
}
|
||||
|
||||
// Lifcycle - check that the action handlers are defined
|
||||
// Lifecycle - check that the action handlers are defined
|
||||
foreach (self::EnumStates($sClass) as $sStateCode => $aStateDef)
|
||||
{
|
||||
foreach(self::EnumTransitions($sClass, $sStateCode) as $sStimulusCode => $aTransitionDef)
|
||||
{
|
||||
foreach ($aTransitionDef['actions'] as $sActionHandler)
|
||||
foreach ($aTransitionDef['actions'] as $actionHandler)
|
||||
{
|
||||
if (!method_exists($sClass, $sActionHandler))
|
||||
if (is_string($actionHandler))
|
||||
{
|
||||
$aErrors[$sClass][] = "Unknown function '$sActionHandler' in transition [$sStateCode/$sStimulusCode] for state attribute '$sStateAttCode'";
|
||||
$aSugFix[$sClass][] = "Specify a function which prototype is in the form [public function $sActionHandler(\$sStimulusCode){return true;}]";
|
||||
if (!method_exists($sClass, $actionHandler))
|
||||
{
|
||||
$aErrors[$sClass][] = "Unknown function '$sActionHandler' in transition [$sStateCode/$sStimulusCode] for state attribute '$sStateAttCode'";
|
||||
$aSugFix[$sClass][] = "Specify a function which prototype is in the form [public function $sActionHandler(\$sStimulusCode){return true;}]";
|
||||
}
|
||||
}
|
||||
else // if(is_array($actionHandler))
|
||||
{
|
||||
$sActionHandler = $actionHandler['verb'];
|
||||
if (!method_exists($sClass, $sActionHandler))
|
||||
{
|
||||
$aErrors[$sClass][] = "Unknown function '$sActionHandler' in transition [$sStateCode/$sStimulusCode] for state attribute '$sStateAttCode'";
|
||||
$aSugFix[$sClass][] = "Specify a function which prototype is in the form [public function $sActionHandler(...){return true;}]";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (array_key_exists('highlight', $aStateDef))
|
||||
{
|
||||
if(!array_key_exists('code', $aStateDef['highlight']))
|
||||
{
|
||||
$aErrors[$sClass][] = "The 'code' element is missing for the 'highlight' property of state: '$sStateCode'.";
|
||||
$aSugFix[$sClass][] = "Add a 'code' entry specifying the value of the highlight code for this state.";
|
||||
}
|
||||
else
|
||||
{
|
||||
$aScale = self::GetHighlightScale($sClass);
|
||||
if (!array_key_exists($aStateDef['highlight']['code'], $aScale))
|
||||
{
|
||||
$aErrors[$sClass][] = "'{$aStateDef['highlight']['code']}' is not a valid value for the 'code' element in the 'highlight' property of state: '$sStateCode'.";
|
||||
$aSugFix[$sClass][] = "The possible highlight codes for this class are: ".implode(', ', array_keys($aScale)).".";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4718,6 +4838,7 @@ abstract class MetaModel
|
||||
self::$m_aStates = $result['m_aStates'];
|
||||
self::$m_aStimuli = $result['m_aStimuli'];
|
||||
self::$m_aTransitions = $result['m_aTransitions'];
|
||||
self::$m_aHighlightScales = $result['m_aHighlightScales'];
|
||||
}
|
||||
$oKPI->ComputeAndReport('Metamodel APC (fetch + read)');
|
||||
}
|
||||
@@ -4754,6 +4875,7 @@ abstract class MetaModel
|
||||
$aCache['m_aStates'] = self::$m_aStates; // array of ("classname" => array of "statecode"=>array('label'=>..., attribute_inherit=> attribute_list=>...))
|
||||
$aCache['m_aStimuli'] = self::$m_aStimuli; // array of ("classname" => array of ("stimuluscode"=>array('label'=>...)))
|
||||
$aCache['m_aTransitions'] = self::$m_aTransitions; // array of ("classname" => array of ("statcode_from"=>array of ("stimuluscode" => array('target_state'=>..., 'actions'=>array of handlers procs, 'user_restriction'=>TBD)))
|
||||
$aCache['m_aHighlightScales'] = self::$m_aHighlightScales; // array of ("classname" => array of higlightcodes)))
|
||||
apc_store($sOqlAPCCacheId, $aCache);
|
||||
$oKPI->ComputeAndReport('Metamodel APC (store)');
|
||||
}
|
||||
@@ -4815,7 +4937,15 @@ abstract class MetaModel
|
||||
if (!file_exists($sFile))
|
||||
{
|
||||
$sConfigFile = self::$m_oConfig->GetLoadedFile();
|
||||
throw new CoreException('Wrong filename in configuration file', array('file' => $sConfigFile, 'module' => $sModuleType, 'filename' => $sFile));
|
||||
if (strlen($sConfigFile) > 0)
|
||||
{
|
||||
throw new CoreException('Include: wrong file name in configuration file', array('config file' => $sConfigFile, 'section' => $sModuleType, 'filename' => $sFile));
|
||||
}
|
||||
else
|
||||
{
|
||||
// The configuration is in memory only
|
||||
throw new CoreException('Include: wrong file name in configuration file (in memory)', array('section' => $sModuleType, 'filename' => $sFile));
|
||||
}
|
||||
}
|
||||
|
||||
// Note: We do not expect the modules to output characters while loading them.
|
||||
@@ -5394,5 +5524,3 @@ MetaModel::RegisterZList("preview", array("description"=>"All attributes visible
|
||||
|
||||
MetaModel::RegisterZList("standard_search", array("description"=>"List of criteria for the standard search", "type"=>"filters"));
|
||||
MetaModel::RegisterZList("advanced_search", array("description"=>"List of criteria for the advanced search", "type"=>"filters"));
|
||||
|
||||
?>
|
||||
|
||||
@@ -62,12 +62,13 @@ class ormStopWatch
|
||||
return (string) $this->iTimeSpent;
|
||||
}
|
||||
|
||||
public function DefineThreshold($iPercent, $tDeadline = null, $bPassed = false, $bTriggered = false, $iOverrun = null)
|
||||
public function DefineThreshold($iPercent, $tDeadline = null, $bPassed = false, $bTriggered = false, $iOverrun = null, $aHighlightDef = null)
|
||||
{
|
||||
$this->aThresholds[$iPercent] = array(
|
||||
'deadline' => $tDeadline, // unix time (seconds)
|
||||
'triggered' => $bTriggered,
|
||||
'overrun' => $iOverrun
|
||||
'overrun' => $iOverrun,
|
||||
'highlight' => $aHighlightDef, // array('code' => string, 'persistent' => boolean)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -129,6 +130,10 @@ class ormStopWatch
|
||||
{
|
||||
$bRet = true;
|
||||
}
|
||||
if (isset($aThresholdData['overrun']) && ($aThresholdData['overrun'] > 0))
|
||||
{
|
||||
$bRet = true;
|
||||
}
|
||||
}
|
||||
return $bRet;
|
||||
}
|
||||
@@ -143,6 +148,31 @@ class ormStopWatch
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function GetHighlightCode()
|
||||
{
|
||||
$sCode = '';
|
||||
// Process the thresholds in ascending order
|
||||
$aPercents = array();
|
||||
foreach($this->aThresholds as $iPercent => $aDefs)
|
||||
{
|
||||
$aPercents[] = $iPercent;
|
||||
}
|
||||
sort($aPercents, SORT_NUMERIC);
|
||||
foreach($aPercents as $iPercent)
|
||||
{
|
||||
$aDefs = $this->aThresholds[$iPercent];
|
||||
if (array_key_exists('highlight', $aDefs) && is_array($aDefs['highlight']) && $this->IsThresholdPassed($iPercent))
|
||||
{
|
||||
// If persistant or SW running...
|
||||
if (($aDefs['highlight']['persistent'] == true) || (($aDefs['highlight']['persistent'] == false) && !is_null($this->iLastStart)))
|
||||
{
|
||||
$sCode = $aDefs['highlight']['code'];
|
||||
}
|
||||
}
|
||||
}
|
||||
return $sCode;
|
||||
}
|
||||
|
||||
public function GetAsHTML($oAttDef, $oHostObject = null)
|
||||
{
|
||||
@@ -424,9 +454,44 @@ class CheckStopWatchThresholds implements iBackgroundProcess
|
||||
{
|
||||
$sVerb = $aActionData['verb'];
|
||||
$aParams = $aActionData['params'];
|
||||
$sParams = implode(', ', $aParams);
|
||||
$aValues = array();
|
||||
foreach($aParams as $def)
|
||||
{
|
||||
if (is_string($def))
|
||||
{
|
||||
// Old method (pre-2.0.4) non typed parameters
|
||||
$aValues[] = $def;
|
||||
}
|
||||
else // if(is_array($def))
|
||||
{
|
||||
$sParamType = array_key_exists('type', $def) ? $def['type'] : 'string';
|
||||
switch($sParamType)
|
||||
{
|
||||
case 'int':
|
||||
$value = (int)$def['value'];
|
||||
break;
|
||||
|
||||
case 'float':
|
||||
$value = (float)$def['value'];
|
||||
break;
|
||||
|
||||
case 'bool':
|
||||
$value = (bool)$def['value'];
|
||||
break;
|
||||
|
||||
case 'reference':
|
||||
$value = ${$def['value']};
|
||||
break;
|
||||
|
||||
case 'string':
|
||||
default:
|
||||
$value = (string)$def['value'];
|
||||
}
|
||||
$aValues[] = $value;
|
||||
}
|
||||
}
|
||||
$aCallSpec = array($oObj, $sVerb);
|
||||
call_user_func_array($aCallSpec, $aParams);
|
||||
call_user_func_array($aCallSpec, $aValues);
|
||||
}
|
||||
|
||||
// Mark the threshold as "triggered"
|
||||
|
||||
@@ -342,6 +342,7 @@ class lnkTriggerAction extends cmdbAbstractObject
|
||||
"db_key_field" => "link_id",
|
||||
"db_finalclass_field" => "",
|
||||
"display_template" => "",
|
||||
"is_link" => true,
|
||||
);
|
||||
MetaModel::Init_Params($aParams);
|
||||
MetaModel::Init_AddAttribute(new AttributeExternalKey("action_id", array("targetclass"=>"Action", "jointype"=> '', "allowed_values"=>null, "sql"=>"action_id", "is_null_allowed"=>false, "on_target_delete"=>DEL_AUTO, "depends_on"=>array())));
|
||||
|
||||
@@ -234,12 +234,19 @@ abstract class User extends cmdbAbstractObject
|
||||
$aChanges = $this->ListChanges();
|
||||
if (array_key_exists('login', $aChanges))
|
||||
{
|
||||
$sNewLogin = $aChanges['login'];
|
||||
$oSearch = DBObjectSearch::FromOQL_AllData("SELECT User WHERE login = :newlogin");
|
||||
$oSet = new DBObjectSet($oSearch, array(), array('newlogin' => $sNewLogin));
|
||||
if ($oSet->Count() > 0)
|
||||
if (strcasecmp($this->Get('login'), $this->GetOriginal('login')) !== 0)
|
||||
{
|
||||
$this->m_aCheckIssues[] = Dict::Format('Class:User/Error:LoginMustBeUnique', $sNewLogin);
|
||||
$sNewLogin = $aChanges['login'];
|
||||
$oSearch = DBObjectSearch::FromOQL_AllData("SELECT User WHERE login = :newlogin");
|
||||
if (!$this->IsNew())
|
||||
{
|
||||
$oSearch->AddCondition('id', $this->GetKey(), '!=');
|
||||
}
|
||||
$oSet = new DBObjectSet($oSearch, array(), array('newlogin' => $sNewLogin));
|
||||
if ($oSet->Count() > 0)
|
||||
{
|
||||
$this->m_aCheckIssues[] = Dict::Format('Class:User/Error:LoginMustBeUnique', $sNewLogin);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Check that this user has at least one profile assigned
|
||||
@@ -248,7 +255,6 @@ abstract class User extends cmdbAbstractObject
|
||||
{
|
||||
$this->m_aCheckIssues[] = Dict::Format('Class:User/Error:AtLeastOneProfileIsNeeded');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function GetGrantAsHtml($sClass, $iAction)
|
||||
|
||||
@@ -100,6 +100,9 @@ class ValueSetObjects extends ValueSetDefinition
|
||||
private $m_bAllowAllData;
|
||||
private $m_aModifierProperties;
|
||||
|
||||
/**
|
||||
* @param hash $aOrderBy Array of '[<classalias>.]attcode' => bAscending
|
||||
*/
|
||||
public function __construct($sFilterExp, $sValueAttCode = '', $aOrderBy = array(), $bAllowAllData = false, $aModifierProperties = array())
|
||||
{
|
||||
$this->m_sContains = '';
|
||||
@@ -415,5 +418,3 @@ class ValueSetEnumClasses extends ValueSetEnum
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
@@ -1416,3 +1416,7 @@ div.ui-dialog-header {
|
||||
padding-bottom: 10px;
|
||||
padding-top: 7px;
|
||||
}
|
||||
.form_field_error {
|
||||
border: 1px solid #933;
|
||||
background: #fcc;
|
||||
}
|
||||
@@ -457,7 +457,7 @@
|
||||
<hidden/>
|
||||
</attribute>
|
||||
<attribute id="agent_id">
|
||||
<must_change/>
|
||||
<must_prompt/>
|
||||
</attribute>
|
||||
<attribute id="agent_email">
|
||||
<hidden/>
|
||||
@@ -466,13 +466,13 @@
|
||||
<mandatory/>
|
||||
</attribute>
|
||||
<attribute id="supervisor_id">
|
||||
<must_change/>
|
||||
<must_prompt/>
|
||||
</attribute>
|
||||
<attribute id="manager_group_id">
|
||||
<mandatory/>
|
||||
</attribute>
|
||||
<attribute id="manager_id">
|
||||
<must_change/>
|
||||
<must_prompt/>
|
||||
</attribute>
|
||||
<attribute id="outage">
|
||||
<hidden/>
|
||||
@@ -1306,7 +1306,7 @@
|
||||
</attribute>
|
||||
</flags>
|
||||
<transitions>
|
||||
<transition>
|
||||
<transition id="ev_assign">
|
||||
<stimulus>ev_assign</stimulus>
|
||||
<target>assigned</target>
|
||||
<actions/>
|
||||
@@ -1488,7 +1488,7 @@
|
||||
<hidden/>
|
||||
</attribute>
|
||||
<attribute id="agent_id">
|
||||
<must_change/>
|
||||
<must_prompt/>
|
||||
</attribute>
|
||||
<attribute id="agent_email">
|
||||
<hidden/>
|
||||
@@ -1497,13 +1497,13 @@
|
||||
<mandatory/>
|
||||
</attribute>
|
||||
<attribute id="supervisor_id">
|
||||
<must_change/>
|
||||
<must_prompt/>
|
||||
</attribute>
|
||||
<attribute id="manager_group_id">
|
||||
<mandatory/>
|
||||
</attribute>
|
||||
<attribute id="manager_id">
|
||||
<must_change/>
|
||||
<must_prompt/>
|
||||
</attribute>
|
||||
<attribute id="outage">
|
||||
<hidden/>
|
||||
@@ -1513,7 +1513,7 @@
|
||||
</attribute>
|
||||
</flags>
|
||||
<transitions>
|
||||
<transition>
|
||||
<transition id="ev_plan">
|
||||
<stimulus>ev_plan</stimulus>
|
||||
<target>plannedscheduled</target>
|
||||
<actions/>
|
||||
@@ -1589,7 +1589,7 @@
|
||||
</attribute>
|
||||
</flags>
|
||||
<transitions>
|
||||
<transition>
|
||||
<transition id="ev_implement">
|
||||
<stimulus>ev_implement</stimulus>
|
||||
<target>implemented</target>
|
||||
<actions/>
|
||||
@@ -1796,12 +1796,12 @@
|
||||
</attribute>
|
||||
</flags>
|
||||
<transitions>
|
||||
<transition>
|
||||
<transition id="ev_monitor">
|
||||
<stimulus>ev_monitor</stimulus>
|
||||
<target>monitored</target>
|
||||
<actions/>
|
||||
</transition>
|
||||
<transition>
|
||||
<transition id="ev_finish">
|
||||
<stimulus>ev_finish</stimulus>
|
||||
<target>closed</target>
|
||||
<actions>
|
||||
@@ -1879,7 +1879,7 @@
|
||||
</attribute>
|
||||
</flags>
|
||||
<transitions>
|
||||
<transition>
|
||||
<transition id="ev_finish">
|
||||
<stimulus>ev_finish</stimulus>
|
||||
<target>closed</target>
|
||||
<actions>
|
||||
@@ -2465,7 +2465,7 @@
|
||||
<hidden/>
|
||||
</attribute>
|
||||
<attribute id="agent_id">
|
||||
<must_change/>
|
||||
<must_prompt/>
|
||||
</attribute>
|
||||
<attribute id="agent_email">
|
||||
<hidden/>
|
||||
@@ -2474,13 +2474,13 @@
|
||||
<mandatory/>
|
||||
</attribute>
|
||||
<attribute id="supervisor_id">
|
||||
<must_change/>
|
||||
<must_prompt/>
|
||||
</attribute>
|
||||
<attribute id="manager_group_id">
|
||||
<mandatory/>
|
||||
</attribute>
|
||||
<attribute id="manager_id">
|
||||
<must_change/>
|
||||
<must_prompt/>
|
||||
</attribute>
|
||||
<attribute id="outage">
|
||||
<hidden/>
|
||||
@@ -3248,12 +3248,12 @@
|
||||
</attribute>
|
||||
</flags>
|
||||
<transitions>
|
||||
<transition>
|
||||
<transition id="ev_validate">
|
||||
<stimulus>ev_validate</stimulus>
|
||||
<target>validated</target>
|
||||
<actions/>
|
||||
</transition>
|
||||
<transition>
|
||||
<transition id="ev_reject">
|
||||
<stimulus>ev_reject</stimulus>
|
||||
<target>rejected</target>
|
||||
<actions/>
|
||||
@@ -3339,7 +3339,7 @@
|
||||
</attribute>
|
||||
</flags>
|
||||
<transitions>
|
||||
<transition>
|
||||
<transition id="ev_assign">
|
||||
<stimulus>ev_assign</stimulus>
|
||||
<target>assigned</target>
|
||||
<actions/>
|
||||
@@ -3422,7 +3422,7 @@
|
||||
</attribute>
|
||||
</flags>
|
||||
<transitions>
|
||||
<transition>
|
||||
<transition id="ev_reopen">
|
||||
<stimulus>ev_reopen</stimulus>
|
||||
<target>new</target>
|
||||
<actions/>
|
||||
@@ -3471,7 +3471,7 @@
|
||||
<hidden/>
|
||||
</attribute>
|
||||
<attribute id="agent_id">
|
||||
<must_change/>
|
||||
<must_prompt/>
|
||||
</attribute>
|
||||
<attribute id="agent_email">
|
||||
<hidden/>
|
||||
@@ -3480,13 +3480,13 @@
|
||||
<mandatory/>
|
||||
</attribute>
|
||||
<attribute id="supervisor_id">
|
||||
<must_change/>
|
||||
<must_prompt/>
|
||||
</attribute>
|
||||
<attribute id="manager_group_id">
|
||||
<mandatory/>
|
||||
</attribute>
|
||||
<attribute id="manager_id">
|
||||
<must_change/>
|
||||
<must_prompt/>
|
||||
</attribute>
|
||||
<attribute id="outage">
|
||||
<hidden/>
|
||||
@@ -3502,7 +3502,7 @@
|
||||
</attribute>
|
||||
</flags>
|
||||
<transitions>
|
||||
<transition>
|
||||
<transition id="ev_plan">
|
||||
<stimulus>ev_plan</stimulus>
|
||||
<target>plannedscheduled</target>
|
||||
<actions/>
|
||||
@@ -3589,12 +3589,12 @@
|
||||
</attribute>
|
||||
</flags>
|
||||
<transitions>
|
||||
<transition>
|
||||
<transition id="ev_approve">
|
||||
<stimulus>ev_approve</stimulus>
|
||||
<target>approved</target>
|
||||
<actions/>
|
||||
</transition>
|
||||
<transition>
|
||||
<transition id="ev_notapprove">
|
||||
<stimulus>ev_notapprove</stimulus>
|
||||
<target>notapproved</target>
|
||||
<actions/>
|
||||
@@ -3680,7 +3680,7 @@
|
||||
</attribute>
|
||||
</flags>
|
||||
<transitions>
|
||||
<transition>
|
||||
<transition id="ev_implement">
|
||||
<stimulus>ev_implement</stimulus>
|
||||
<target>implemented</target>
|
||||
<actions/>
|
||||
@@ -3763,7 +3763,7 @@
|
||||
</attribute>
|
||||
</flags>
|
||||
<transitions>
|
||||
<transition>
|
||||
<transition id="ev_replan">
|
||||
<stimulus>ev_replan</stimulus>
|
||||
<target>plannedscheduled</target>
|
||||
<actions/>
|
||||
@@ -3849,12 +3849,12 @@
|
||||
</attribute>
|
||||
</flags>
|
||||
<transitions>
|
||||
<transition>
|
||||
<transition id="ev_monitor">
|
||||
<stimulus>ev_monitor</stimulus>
|
||||
<target>monitored</target>
|
||||
<actions/>
|
||||
</transition>
|
||||
<transition>
|
||||
<transition id="ev_finish">
|
||||
<stimulus>ev_finish</stimulus>
|
||||
<target>closed</target>
|
||||
<actions>
|
||||
@@ -3944,7 +3944,7 @@
|
||||
</attribute>
|
||||
</flags>
|
||||
<transitions>
|
||||
<transition>
|
||||
<transition id="ev_finish">
|
||||
<stimulus>ev_finish</stimulus>
|
||||
<target>closed</target>
|
||||
<actions>
|
||||
@@ -4353,7 +4353,7 @@
|
||||
</attribute>
|
||||
</flags>
|
||||
<transitions>
|
||||
<transition>
|
||||
<transition id="ev_assign">
|
||||
<stimulus>ev_assign</stimulus>
|
||||
<target>assigned</target>
|
||||
<actions/>
|
||||
@@ -4547,7 +4547,7 @@
|
||||
<hidden/>
|
||||
</attribute>
|
||||
<attribute id="agent_id">
|
||||
<must_change/>
|
||||
<must_prompt/>
|
||||
</attribute>
|
||||
<attribute id="agent_email">
|
||||
<hidden/>
|
||||
@@ -4556,13 +4556,13 @@
|
||||
<mandatory/>
|
||||
</attribute>
|
||||
<attribute id="supervisor_id">
|
||||
<must_change/>
|
||||
<must_prompt/>
|
||||
</attribute>
|
||||
<attribute id="manager_group_id">
|
||||
<mandatory/>
|
||||
</attribute>
|
||||
<attribute id="manager_id">
|
||||
<must_change/>
|
||||
<must_prompt/>
|
||||
</attribute>
|
||||
<attribute id="outage">
|
||||
<hidden/>
|
||||
@@ -4578,7 +4578,7 @@
|
||||
</attribute>
|
||||
</flags>
|
||||
<transitions>
|
||||
<transition>
|
||||
<transition id="ev_plan">
|
||||
<stimulus>ev_plan</stimulus>
|
||||
<target>plannedscheduled</target>
|
||||
<actions/>
|
||||
@@ -4660,12 +4660,12 @@
|
||||
</attribute>
|
||||
</flags>
|
||||
<transitions>
|
||||
<transition>
|
||||
<transition id="ev_approve">
|
||||
<stimulus>ev_approve</stimulus>
|
||||
<target>approved</target>
|
||||
<actions/>
|
||||
</transition>
|
||||
<transition>
|
||||
<transition id="ev_notapprove">
|
||||
<stimulus>ev_notapprove</stimulus>
|
||||
<target>notapproved</target>
|
||||
<actions/>
|
||||
@@ -4746,7 +4746,7 @@
|
||||
</attribute>
|
||||
</flags>
|
||||
<transitions>
|
||||
<transition>
|
||||
<transition id="ev_implement">
|
||||
<stimulus>ev_implement</stimulus>
|
||||
<target>implemented</target>
|
||||
<actions/>
|
||||
@@ -4823,7 +4823,7 @@
|
||||
</attribute>
|
||||
</flags>
|
||||
<transitions>
|
||||
<transition>
|
||||
<transition id="ev_replan">
|
||||
<stimulus>ev_replan</stimulus>
|
||||
<target>plannedscheduled</target>
|
||||
<actions/>
|
||||
@@ -4903,12 +4903,12 @@
|
||||
</attribute>
|
||||
</flags>
|
||||
<transitions>
|
||||
<transition>
|
||||
<transition id="ev_monitor">
|
||||
<stimulus>ev_monitor</stimulus>
|
||||
<target>monitored</target>
|
||||
<actions/>
|
||||
</transition>
|
||||
<transition>
|
||||
<transition id="ev_finish">
|
||||
<stimulus>ev_finish</stimulus>
|
||||
<target>closed</target>
|
||||
<actions>
|
||||
@@ -4992,7 +4992,7 @@
|
||||
</attribute>
|
||||
</flags>
|
||||
<transitions>
|
||||
<transition>
|
||||
<transition id="ev_finish">
|
||||
<stimulus>ev_finish</stimulus>
|
||||
<target>closed</target>
|
||||
<actions>
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="description">
|
||||
<must_change/>
|
||||
<must_prompt/>
|
||||
</attribute>
|
||||
<attribute id="start_date">
|
||||
<read_only/>
|
||||
@@ -63,28 +63,28 @@
|
||||
<mandatory/>
|
||||
</attribute>
|
||||
<attribute id="org_id">
|
||||
<must_change/>
|
||||
<must_prompt/>
|
||||
</attribute>
|
||||
<attribute id="service_id">
|
||||
<must_change/>
|
||||
<must_prompt/>
|
||||
</attribute>
|
||||
<attribute id="servicesubcategory_id">
|
||||
<must_change/>
|
||||
<must_prompt/>
|
||||
</attribute>
|
||||
<attribute id="product">
|
||||
<must_prompt/>
|
||||
</attribute>
|
||||
<attribute id="impact">
|
||||
<must_change/>
|
||||
<must_prompt/>
|
||||
</attribute>
|
||||
<attribute id="urgency">
|
||||
<must_change/>
|
||||
<must_prompt/>
|
||||
</attribute>
|
||||
<attribute id="priority">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="workgroup_id">
|
||||
<must_change/>
|
||||
<must_prompt/>
|
||||
</attribute>
|
||||
<attribute id="agent_email">
|
||||
<hidden/>
|
||||
@@ -130,7 +130,7 @@
|
||||
</attribute>
|
||||
</flags>
|
||||
<transitions>
|
||||
<transition>
|
||||
<transition id="ev_assign">
|
||||
<stimulus>ev_assign</stimulus>
|
||||
<target>assigned</target>
|
||||
<actions>
|
||||
@@ -139,7 +139,7 @@
|
||||
</action>
|
||||
</actions>
|
||||
</transition>
|
||||
<transition>
|
||||
<transition id="ev_timeout">
|
||||
<stimulus>ev_timeout</stimulus>
|
||||
<target>escalated_tto</target>
|
||||
<actions/>
|
||||
@@ -204,7 +204,7 @@
|
||||
</attribute>
|
||||
</flags>
|
||||
<transitions>
|
||||
<transition>
|
||||
<transition id="ev_assign">
|
||||
<stimulus>ev_assign</stimulus>
|
||||
<target>assigned</target>
|
||||
<actions>
|
||||
@@ -284,17 +284,17 @@
|
||||
</attribute>
|
||||
</flags>
|
||||
<transitions>
|
||||
<transition>
|
||||
<transition id="ev_reassign">
|
||||
<stimulus>ev_reassign</stimulus>
|
||||
<target>assigned</target>
|
||||
<actions/>
|
||||
</transition>
|
||||
<transition>
|
||||
<transition id="ev_reassign">
|
||||
<stimulus>ev_timeout</stimulus>
|
||||
<target>escalated_ttr</target>
|
||||
<actions/>
|
||||
</transition>
|
||||
<transition>
|
||||
<transition id="ev_reassign">
|
||||
<stimulus>ev_resolve</stimulus>
|
||||
<target>resolved</target>
|
||||
<actions>
|
||||
@@ -377,12 +377,12 @@
|
||||
</attribute>
|
||||
</flags>
|
||||
<transitions>
|
||||
<transition>
|
||||
<transition id="ev_reassign">
|
||||
<stimulus>ev_reassign</stimulus>
|
||||
<target>escalated_ttr</target>
|
||||
<actions/>
|
||||
</transition>
|
||||
<transition>
|
||||
<transition id="ev_resolve">
|
||||
<stimulus>ev_resolve</stimulus>
|
||||
<target>resolved</target>
|
||||
<actions>
|
||||
@@ -546,12 +546,12 @@
|
||||
</attribute>
|
||||
</flags>
|
||||
<transitions>
|
||||
<transition>
|
||||
<transition id="ev_reassign">
|
||||
<stimulus>ev_reassign</stimulus>
|
||||
<target>assigned</target>
|
||||
<actions/>
|
||||
</transition>
|
||||
<transition>
|
||||
<transition id="ev_close">
|
||||
<stimulus>ev_close</stimulus>
|
||||
<target>closed</target>
|
||||
<actions>
|
||||
|
||||
@@ -213,7 +213,7 @@
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="description">
|
||||
<must_change/>
|
||||
<must_prompt/>
|
||||
</attribute>
|
||||
<attribute id="ticket_log">
|
||||
<hidden/>
|
||||
@@ -222,28 +222,28 @@
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="org_id">
|
||||
<must_change/>
|
||||
<must_prompt/>
|
||||
</attribute>
|
||||
<attribute id="service_id">
|
||||
<must_change/>
|
||||
<must_prompt/>
|
||||
</attribute>
|
||||
<attribute id="servicesubcategory_id">
|
||||
<must_change/>
|
||||
<must_prompt/>
|
||||
</attribute>
|
||||
<attribute id="product">
|
||||
<must_prompt/>
|
||||
</attribute>
|
||||
<attribute id="impact">
|
||||
<must_change/>
|
||||
<must_prompt/>
|
||||
</attribute>
|
||||
<attribute id="urgency">
|
||||
<must_change/>
|
||||
<must_prompt/>
|
||||
</attribute>
|
||||
<attribute id="priority">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="workgroup_id">
|
||||
<must_change/>
|
||||
<must_prompt/>
|
||||
</attribute>
|
||||
<attribute id="agent_id">
|
||||
<hidden/>
|
||||
@@ -268,7 +268,7 @@
|
||||
</attribute>
|
||||
</flags>
|
||||
<transitions>
|
||||
<transition>
|
||||
<transition id="ev_assign">
|
||||
<stimulus>ev_assign</stimulus>
|
||||
<target>assigned</target>
|
||||
<actions>
|
||||
@@ -324,12 +324,12 @@
|
||||
</attribute>
|
||||
</flags>
|
||||
<transitions>
|
||||
<transition>
|
||||
<transition id="ev_reassign">
|
||||
<stimulus>ev_reassign</stimulus>
|
||||
<target>assigned</target>
|
||||
<actions/>
|
||||
</transition>
|
||||
<transition>
|
||||
<transition id="ev_resolve">
|
||||
<stimulus>ev_resolve</stimulus>
|
||||
<target>resolved</target>
|
||||
<actions>
|
||||
@@ -398,12 +398,12 @@
|
||||
</attribute>
|
||||
</flags>
|
||||
<transitions>
|
||||
<transition>
|
||||
<transition id="ev_reassign">
|
||||
<stimulus>ev_reassign</stimulus>
|
||||
<target>assigned</target>
|
||||
<actions/>
|
||||
</transition>
|
||||
<transition>
|
||||
<transition id="ev_close">
|
||||
<stimulus>ev_close</stimulus>
|
||||
<target>closed</target>
|
||||
<actions>
|
||||
@@ -753,7 +753,7 @@
|
||||
<parent>ProblemManagement</parent>
|
||||
<definition>
|
||||
<layout>DashboardLayoutTwoCols</layout>
|
||||
<title></title>
|
||||
<title/>
|
||||
<cells>
|
||||
<cell id="0">
|
||||
<rank>0</rank>
|
||||
|
||||
@@ -91,7 +91,7 @@
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="description">
|
||||
<must_change/>
|
||||
<must_prompt/>
|
||||
</attribute>
|
||||
<attribute id="start_date">
|
||||
<read_only/>
|
||||
@@ -100,28 +100,28 @@
|
||||
<mandatory/>
|
||||
</attribute>
|
||||
<attribute id="org_id">
|
||||
<must_change/>
|
||||
<must_prompt/>
|
||||
</attribute>
|
||||
<attribute id="service_id">
|
||||
<must_change/>
|
||||
<must_prompt/>
|
||||
</attribute>
|
||||
<attribute id="servicesubcategory_id">
|
||||
<must_change/>
|
||||
<must_prompt/>
|
||||
</attribute>
|
||||
<attribute id="product">
|
||||
<must_prompt/>
|
||||
</attribute>
|
||||
<attribute id="impact">
|
||||
<must_change/>
|
||||
<must_prompt/>
|
||||
</attribute>
|
||||
<attribute id="urgency">
|
||||
<must_change/>
|
||||
<must_prompt/>
|
||||
</attribute>
|
||||
<attribute id="priority">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="workgroup_id">
|
||||
<must_change/>
|
||||
<must_prompt/>
|
||||
</attribute>
|
||||
<attribute id="agent_email">
|
||||
<hidden/>
|
||||
@@ -173,7 +173,7 @@
|
||||
</attribute>
|
||||
</flags>
|
||||
<transitions>
|
||||
<transition>
|
||||
<transition id="ev_assign">
|
||||
<stimulus>ev_assign</stimulus>
|
||||
<target>assigned</target>
|
||||
<actions>
|
||||
@@ -182,7 +182,7 @@
|
||||
</action>
|
||||
</actions>
|
||||
</transition>
|
||||
<transition>
|
||||
<transition id="ev_timeout">
|
||||
<stimulus>ev_timeout</stimulus>
|
||||
<target>escalated_tto</target>
|
||||
<actions/>
|
||||
@@ -253,7 +253,7 @@
|
||||
</attribute>
|
||||
</flags>
|
||||
<transitions>
|
||||
<transition>
|
||||
<transition id="ev_assign">
|
||||
<stimulus>ev_assign</stimulus>
|
||||
<target>assigned</target>
|
||||
<actions>
|
||||
@@ -339,17 +339,17 @@
|
||||
</attribute>
|
||||
</flags>
|
||||
<transitions>
|
||||
<transition>
|
||||
<transition id="ev_reassign">
|
||||
<stimulus>ev_reassign</stimulus>
|
||||
<target>assigned</target>
|
||||
<actions/>
|
||||
</transition>
|
||||
<transition>
|
||||
<transition id="ev_timeout">
|
||||
<stimulus>ev_timeout</stimulus>
|
||||
<target>escalated_ttr</target>
|
||||
<actions/>
|
||||
</transition>
|
||||
<transition>
|
||||
<transition id="ev_resolve">
|
||||
<stimulus>ev_resolve</stimulus>
|
||||
<target>resolved</target>
|
||||
<actions>
|
||||
@@ -361,7 +361,7 @@
|
||||
</action>
|
||||
</actions>
|
||||
</transition>
|
||||
<transition>
|
||||
<transition id="ev_freeze">
|
||||
<stimulus>ev_freeze</stimulus>
|
||||
<target>frozen</target>
|
||||
<actions/>
|
||||
@@ -443,12 +443,12 @@
|
||||
</attribute>
|
||||
</flags>
|
||||
<transitions>
|
||||
<transition>
|
||||
<transition id="ev_reassign">
|
||||
<stimulus>ev_reassign</stimulus>
|
||||
<target>escalated_ttr</target>
|
||||
<actions/>
|
||||
</transition>
|
||||
<transition>
|
||||
<transition id="ev_resolve">
|
||||
<stimulus>ev_resolve</stimulus>
|
||||
<target>resolved</target>
|
||||
<actions>
|
||||
@@ -536,17 +536,17 @@
|
||||
</attribute>
|
||||
</flags>
|
||||
<transitions>
|
||||
<transition>
|
||||
<transition id="ev_timeout">
|
||||
<stimulus>ev_timeout</stimulus>
|
||||
<target>escalated_ttr</target>
|
||||
<actions/>
|
||||
</transition>
|
||||
<transition>
|
||||
<transition id="ev_assign">
|
||||
<stimulus>ev_assign</stimulus>
|
||||
<target>assigned</target>
|
||||
<actions/>
|
||||
</transition>
|
||||
<transition>
|
||||
<transition id="ev_resolve">
|
||||
<stimulus>ev_resolve</stimulus>
|
||||
<target>resolved</target>
|
||||
<actions/>
|
||||
@@ -641,12 +641,12 @@
|
||||
</attribute>
|
||||
</flags>
|
||||
<transitions>
|
||||
<transition>
|
||||
<transition id="ev_reassign">
|
||||
<stimulus>ev_reassign</stimulus>
|
||||
<target>assigned</target>
|
||||
<actions/>
|
||||
</transition>
|
||||
<transition>
|
||||
<transition id="ev_close">
|
||||
<stimulus>ev_close</stimulus>
|
||||
<target>closed</target>
|
||||
<actions>
|
||||
|
||||
@@ -422,7 +422,7 @@
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="description">
|
||||
<must_change/>
|
||||
<must_prompt/>
|
||||
</attribute>
|
||||
<attribute id="start_date">
|
||||
<read_only/>
|
||||
@@ -431,28 +431,28 @@
|
||||
<mandatory/>
|
||||
</attribute>
|
||||
<attribute id="org_id">
|
||||
<must_change/>
|
||||
<must_prompt/>
|
||||
</attribute>
|
||||
<attribute id="service_id">
|
||||
<must_change/>
|
||||
<must_prompt/>
|
||||
</attribute>
|
||||
<attribute id="servicesubcategory_id">
|
||||
<must_change/>
|
||||
<must_prompt/>
|
||||
</attribute>
|
||||
<attribute id="product">
|
||||
<must_prompt/>
|
||||
</attribute>
|
||||
<attribute id="impact">
|
||||
<must_change/>
|
||||
<must_prompt/>
|
||||
</attribute>
|
||||
<attribute id="urgency">
|
||||
<must_change/>
|
||||
<must_prompt/>
|
||||
</attribute>
|
||||
<attribute id="priority">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="workgroup_id">
|
||||
<must_change/>
|
||||
<must_prompt/>
|
||||
</attribute>
|
||||
<attribute id="agent_email">
|
||||
<hidden/>
|
||||
@@ -498,7 +498,7 @@
|
||||
</attribute>
|
||||
</flags>
|
||||
<transitions>
|
||||
<transition>
|
||||
<transition id="ev_assign">
|
||||
<stimulus>ev_assign</stimulus>
|
||||
<target>assigned</target>
|
||||
<actions>
|
||||
@@ -507,7 +507,7 @@
|
||||
</action>
|
||||
</actions>
|
||||
</transition>
|
||||
<transition>
|
||||
<transition id="ev_timeout">
|
||||
<stimulus>ev_timeout</stimulus>
|
||||
<target>escalated_tto</target>
|
||||
<actions/>
|
||||
@@ -572,7 +572,7 @@
|
||||
</attribute>
|
||||
</flags>
|
||||
<transitions>
|
||||
<transition>
|
||||
<transition id="ev_assign">
|
||||
<stimulus>ev_assign</stimulus>
|
||||
<target>assigned</target>
|
||||
<actions>
|
||||
@@ -652,17 +652,17 @@
|
||||
</attribute>
|
||||
</flags>
|
||||
<transitions>
|
||||
<transition>
|
||||
<transition id="ev_reassign">
|
||||
<stimulus>ev_reassign</stimulus>
|
||||
<target>assigned</target>
|
||||
<actions/>
|
||||
</transition>
|
||||
<transition>
|
||||
<transition id="ev_timeout">
|
||||
<stimulus>ev_timeout</stimulus>
|
||||
<target>escalated_ttr</target>
|
||||
<actions/>
|
||||
</transition>
|
||||
<transition>
|
||||
<transition id="ev_resolve">
|
||||
<stimulus>ev_resolve</stimulus>
|
||||
<target>resolved</target>
|
||||
<actions>
|
||||
@@ -745,12 +745,12 @@
|
||||
</attribute>
|
||||
</flags>
|
||||
<transitions>
|
||||
<transition>
|
||||
<transition id="ev_reassign">
|
||||
<stimulus>ev_reassign</stimulus>
|
||||
<target>escalated_ttr</target>
|
||||
<actions/>
|
||||
</transition>
|
||||
<transition>
|
||||
<transition id="ev_resolve">
|
||||
<stimulus>ev_resolve</stimulus>
|
||||
<target>resolved</target>
|
||||
<actions>
|
||||
@@ -914,12 +914,12 @@
|
||||
</attribute>
|
||||
</flags>
|
||||
<transitions>
|
||||
<transition>
|
||||
<transition id="ev_reassign">
|
||||
<stimulus>ev_reassign</stimulus>
|
||||
<target>assigned</target>
|
||||
<actions/>
|
||||
</transition>
|
||||
<transition>
|
||||
<transition id="ev_close">
|
||||
<stimulus>ev_close</stimulus>
|
||||
<target>closed</target>
|
||||
<actions>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0">
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.1">
|
||||
<classes>
|
||||
<class id="Attachment" _delta="define">
|
||||
<parent>DBObject</parent>
|
||||
@@ -37,20 +37,20 @@
|
||||
</reconciliation>
|
||||
<indexes>
|
||||
<index id="1">
|
||||
<attributes>
|
||||
<attribute id="temp_id"/>
|
||||
</attributes>
|
||||
<attributes>
|
||||
<attribute id="temp_id"/>
|
||||
</attributes>
|
||||
</index>
|
||||
<index id="2">
|
||||
<attributes>
|
||||
<attribute id="item_class"/>
|
||||
<attribute id="item_id"/>
|
||||
</attributes>
|
||||
<attributes>
|
||||
<attribute id="item_class"/>
|
||||
<attribute id="item_id"/>
|
||||
</attributes>
|
||||
</index>
|
||||
<index id="3">
|
||||
<attributes>
|
||||
<attribute id="item_org_id"/>
|
||||
</attributes>
|
||||
<attributes>
|
||||
<attribute id="item_org_id"/>
|
||||
</attributes>
|
||||
</index>
|
||||
</indexes>
|
||||
</properties>
|
||||
|
||||
@@ -468,7 +468,8 @@ EOF
|
||||
}
|
||||
}
|
||||
$sPreviewNotAvailable = addslashes(Dict::S('Attachments:PreviewNotAvailable'));
|
||||
$oPage->add_ready_script("$(document).tooltip({ items: '.attachment a', position: { my: 'left top', at: 'right top', using: function( position, feedback ) { $( this ).css( position ); }}, content: function() { if ($(this).attr('data-preview') == 'true') { return('<img style=\"max-width:290px\" src=\"'+$(this).attr('href')+'\"></img>');} else { return '$sPreviewNotAvailable'; }}});");
|
||||
$iMaxWidth = MetaModel::GetModuleSetting('itop-attachments', 'preview_max_width', 290);
|
||||
$oPage->add_ready_script("$(document).tooltip({ items: '.attachment a', position: { my: 'left top', at: 'right top', using: function( position, feedback ) { $( this ).css( position ); }}, content: function() { if ($(this).attr('data-preview') == 'true') { return('<img style=\"max-width:{$iMaxWidth}px\" src=\"'+$(this).attr('href')+'\"></img>');} else { return '$sPreviewNotAvailable'; }}});");
|
||||
}
|
||||
|
||||
protected static function UpdateAttachments($oObject, $oChange = null)
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-attachments/1.0.0',
|
||||
'itop-attachments/2.1.0',
|
||||
array(
|
||||
// Identification
|
||||
//
|
||||
@@ -64,6 +64,7 @@ SetupWebPage::AddModule(
|
||||
'settings' => array(
|
||||
'allowed_classes' => array('Ticket'), // List of classes for which to manage "Attachments"
|
||||
'position' => 'relations', // Where to display the attachments: relations | properties
|
||||
'preview_max_width' => 290,
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
179
datamodels/2.x/itop-backup/ajax.backup.php
Normal file
179
datamodels/2.x/itop-backup/ajax.backup.php
Normal file
@@ -0,0 +1,179 @@
|
||||
<?php
|
||||
// Copyright (C) 2014 Combodo SARL
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// iTop is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
/**
|
||||
* Backup from an interactive session
|
||||
*
|
||||
* @copyright Copyright (C) 2013 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
if (!defined('__DIR__')) define('__DIR__', dirname(__FILE__));
|
||||
require_once(__DIR__.'/../../approot.inc.php');
|
||||
require_once(APPROOT.'/application/application.inc.php');
|
||||
require_once(APPROOT.'/application/webpage.class.inc.php');
|
||||
require_once(APPROOT.'/application/ajaxwebpage.class.inc.php');
|
||||
|
||||
require_once(APPROOT.'core/mutex.class.inc.php');
|
||||
|
||||
try
|
||||
{
|
||||
$sOperation = utils::ReadParam('operation', '');
|
||||
|
||||
switch($sOperation)
|
||||
{
|
||||
case 'backup':
|
||||
require_once(APPROOT.'/application/startup.inc.php');
|
||||
require_once(APPROOT.'/application/loginwebpage.class.inc.php');
|
||||
LoginWebPage::DoLogin(true); // Check user rights and prompt if needed (must be admin)
|
||||
|
||||
$oPage = new ajax_page("");
|
||||
$oPage->no_cache();
|
||||
$oPage->SetContentType('text/html');
|
||||
|
||||
if (utils::GetConfig()->Get('demo_mode'))
|
||||
{
|
||||
$oPage->add("<div data-error-stimulus=\"Error\">Sorry, iTop is in <b>demonstration mode</b>: the feature is disabled.</div>");
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
set_time_limit(0);
|
||||
$oBB = new BackupExec(APPROOT.'data/backups/manual/', 0 /*iRetentionCount*/);
|
||||
$sRes = $oBB->Process(time() + 36000); // 10 hours to complete should be sufficient!
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
$oPage->p('Error: '.$e->getMessage());
|
||||
}
|
||||
}
|
||||
$oPage->output();
|
||||
break;
|
||||
|
||||
case 'restore_get_token':
|
||||
require_once(APPROOT.'/application/startup.inc.php');
|
||||
require_once(APPROOT.'/application/loginwebpage.class.inc.php');
|
||||
LoginWebPage::DoLogin(true); // Check user rights and prompt if needed (must be admin)
|
||||
|
||||
$oPage = new ajax_page("");
|
||||
$oPage->no_cache();
|
||||
$oPage->SetContentType('text/html');
|
||||
|
||||
$sEnvironment = utils::ReadParam('environment', 'production', false, 'raw_data');
|
||||
$oRestoreMutex = new iTopMutex('restore.'.$sEnvironment);
|
||||
if ($oRestoreMutex->TryLock())
|
||||
{
|
||||
$oRestoreMutex->Unlock();
|
||||
$sFile = utils::ReadParam('file', '', false, 'raw_data');
|
||||
$sToken = str_replace(' ', '', (string)microtime());
|
||||
$sTokenFile = APPROOT.'/data/restore.'.$sToken.'.tok';
|
||||
file_put_contents($sTokenFile, $sFile);
|
||||
|
||||
$oPage->add_ready_script(
|
||||
<<<EOF
|
||||
$("#restore_token").val('$sToken');
|
||||
EOF
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
$oPage->p(Dict::S('bkp-restore-running'));
|
||||
}
|
||||
$oPage->output();
|
||||
break;
|
||||
|
||||
|
||||
case 'restore_exec':
|
||||
require_once(APPROOT."setup/runtimeenv.class.inc.php");
|
||||
require_once(APPROOT.'/application/utils.inc.php');
|
||||
require_once(APPROOT.'/setup/backup.class.inc.php');
|
||||
require_once(dirname(__FILE__).'/dbrestore.class.inc.php');
|
||||
|
||||
IssueLog::Enable(APPROOT.'log/error.log');
|
||||
|
||||
$oPage = new ajax_page("");
|
||||
$oPage->no_cache();
|
||||
$oPage->SetContentType('text/html');
|
||||
|
||||
if (utils::GetConfig()->Get('demo_mode'))
|
||||
{
|
||||
$oPage->add("<div data-error-stimulus=\"Error\">Sorry, iTop is in <b>demonstration mode</b>: the feature is disabled.</div>");
|
||||
}
|
||||
else
|
||||
{
|
||||
$sEnvironment = utils::ReadParam('environment', 'production', false, 'raw_data');
|
||||
$oRestoreMutex = new iTopMutex('restore.'.$sEnvironment);
|
||||
$oRestoreMutex->Lock();
|
||||
try
|
||||
{
|
||||
set_time_limit(0);
|
||||
|
||||
// Get the file and destroy the token (single usage)
|
||||
$sToken = utils::ReadParam('token', '', false, 'raw_data');
|
||||
$sTokenFile = APPROOT.'/data/restore.'.$sToken.'.tok';
|
||||
$sFile = file_get_contents($sTokenFile);
|
||||
unlink($sTokenFile);
|
||||
|
||||
$sMySQLBinDir = utils::ReadParam('mysql_bindir', '', false, 'raw_data');
|
||||
$sDBHost = utils::ReadParam('db_host', '', false, 'raw_data');
|
||||
$sDBUser = utils::ReadParam('db_user', '', false, 'raw_data');
|
||||
$sDBPwd = utils::ReadParam('db_pwd', '', false, 'raw_data');
|
||||
$sDBName = utils::ReadParam('db_name', '', false, 'raw_data');
|
||||
$sDBSubName = utils::ReadParam('db_subname', '', false, 'raw_data');
|
||||
|
||||
$oDBRS = new DBRestore($sDBHost, $sDBUser, $sDBPwd, $sDBName, $sDBSubName);
|
||||
$oDBRS->SetMySQLBinDir($sMySQLBinDir);
|
||||
|
||||
$sBackupDir = APPROOT.'data/backups/';
|
||||
$sBackupFile = $sBackupDir.$sFile;
|
||||
$sRes = $oDBRS->RestoreFromZip($sBackupFile, $sEnvironment);
|
||||
|
||||
$oRestoreMutex->Unlock();
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
$oRestoreMutex->Unlock();
|
||||
$oPage->p('Error: '.$e->getMessage());
|
||||
}
|
||||
}
|
||||
$oPage->output();
|
||||
break;
|
||||
|
||||
case 'download':
|
||||
require_once(APPROOT.'/application/startup.inc.php');
|
||||
require_once(APPROOT.'/application/loginwebpage.class.inc.php');
|
||||
LoginWebPage::DoLogin(true); // Check user rights and prompt if needed (must be admin)
|
||||
|
||||
if (utils::GetConfig()->Get('demo_mode'))
|
||||
{
|
||||
throw new Exception('iTop is in demonstration mode: the feature is disabled');
|
||||
}
|
||||
$sFile = utils::ReadParam('file', '', false, 'raw_data');
|
||||
$oBackup = new DBBackupScheduled();
|
||||
$sBackupDir = APPROOT.'data/backups/';
|
||||
$oBackup->DownloadBackup($sBackupDir.$sFile);
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
IssueLog::Error($e->getMessage());
|
||||
}
|
||||
|
||||
?>
|
||||
54
datamodels/2.x/itop-backup/backup.params.distrib
Normal file
54
datamodels/2.x/itop-backup/backup.params.distrib
Normal file
@@ -0,0 +1,54 @@
|
||||
# Parameters file for backup.php and check-backup.php
|
||||
#
|
||||
# Usage:
|
||||
# backup.php --param_file=<this file>[,<another one>]
|
||||
# or
|
||||
# http://.../itop-backup/backup.php?param_file=<this file>[,<another one>]
|
||||
#
|
||||
# If a parameter is given both in the file and in the arguments,
|
||||
# then the value given as argument is retained
|
||||
#
|
||||
# Note: most of the default values provided here should work fine
|
||||
# if you have created sample data with the setup program
|
||||
|
||||
# MySQL coming with Easy PHP (Windows)
|
||||
mysql_bindir = C:\Program Files\EasyPHP-5.3.6.0\mysql\bin
|
||||
|
||||
|
||||
# Authentication
|
||||
auth_user = admin
|
||||
auth_pwd = admin
|
||||
|
||||
# Target file - path and filename (optional)
|
||||
#
|
||||
# Formatting rules:
|
||||
# %Y-%m-%d => 2011-01-25... see PHP documentation of strftime()
|
||||
# Placeholders:
|
||||
# __HOST__ MySQL server
|
||||
# __DB__ Database name
|
||||
# __SUBNAME__ Tables prefix
|
||||
#
|
||||
backup_file = /var/log/__DB__-%Y-%m-%d
|
||||
|
||||
# Check thresholds (check-backup.php)
|
||||
#
|
||||
check_size_min = 20000 # bytes
|
||||
check_size_reduction_max = 10 # percentage
|
||||
|
||||
# Ticket creation (check-backup.php)
|
||||
#
|
||||
# If the backup has failed, a ticket will be created
|
||||
# This process relies on the SOAP service "CreateIncident"
|
||||
#
|
||||
# Root URL of an instance of iTop, into which the ticket will be created
|
||||
check_ticket_itop = http://localhost/myiTop
|
||||
# Any of the above paramaters are mandatory
|
||||
check_ticket_login = admin # must have the right to create an Incident Ticket
|
||||
check_ticket_pwd = admin
|
||||
check_ticket_title = Backup check failed
|
||||
check_ticket_customer = Demo
|
||||
check_ticket_service = Computers and peripherals
|
||||
check_ticket_service_subcategory = Repair
|
||||
check_ticket_workgroup = Hardware support
|
||||
check_ticket_impacted_server = dbserver1.demo.com
|
||||
|
||||
200
datamodels/2.x/itop-backup/backup.php
Normal file
200
datamodels/2.x/itop-backup/backup.php
Normal file
@@ -0,0 +1,200 @@
|
||||
<?php
|
||||
// Copyright (C) 2014 Combodo SARL
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; version 3 of the License.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
if (!defined('__DIR__')) define('__DIR__', dirname(__FILE__));
|
||||
require_once(__DIR__.'/../../approot.inc.php');
|
||||
require_once(APPROOT.'application/application.inc.php');
|
||||
require_once(APPROOT.'application/webpage.class.inc.php');
|
||||
require_once(APPROOT.'application/csvpage.class.inc.php');
|
||||
require_once(APPROOT.'application/clipage.class.inc.php');
|
||||
require_once(APPROOT.'application/ajaxwebpage.class.inc.php');
|
||||
|
||||
require_once(APPROOT.'core/log.class.inc.php');
|
||||
|
||||
require_once(APPROOT.'application/startup.inc.php');
|
||||
|
||||
class MyDBBackup extends DBBackup
|
||||
{
|
||||
protected function LogInfo($sMsg)
|
||||
{
|
||||
$this->oPage->p($sMsg);
|
||||
}
|
||||
|
||||
protected function LogError($sMsg)
|
||||
{
|
||||
$this->oPage->p('Error: '.$sMsg);
|
||||
ToolsLog::Error($sMsg);
|
||||
}
|
||||
|
||||
protected $oPage;
|
||||
public function __construct($oPage)
|
||||
{
|
||||
$this->oPage = $oPage;
|
||||
parent::__construct();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks if a parameter (possibly empty) was specified when calling this page
|
||||
*/
|
||||
function CheckParam($sParamName)
|
||||
{
|
||||
global $argv;
|
||||
|
||||
if (isset($_REQUEST[$sParamName])) return true; // HTTP parameter either GET or POST
|
||||
if (!is_array($argv)) return false;
|
||||
foreach($argv as $sArg)
|
||||
{
|
||||
if ($sArg == '--'.$sParamName) return true; // Empty command line parameter, long unix style
|
||||
if ($sArg == $sParamName) return true; // Empty command line parameter, Windows style
|
||||
if ($sArg == '-'.$sParamName) return true; // Empty command line parameter, short unix style
|
||||
if (preg_match('/^--'.$sParamName.'=(.*)$/', $sArg, $aMatches)) return true; // Command parameter with a value
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function Usage($oP)
|
||||
{
|
||||
$oP->p('Perform a backup of the iTop database by running mysqldump');
|
||||
$oP->p('Parameters:');
|
||||
if (utils::IsModeCLI())
|
||||
{
|
||||
$oP->p('auth_user: login, must be administrator');
|
||||
$oP->p('auth_pwd: ...');
|
||||
}
|
||||
$oP->p('backup_file [optional]: name of the file to store the backup into. Follows the PHP strftime format spec. The following placeholders are available: __HOST__, __DB__, __SUBNAME__');
|
||||
$oP->p('simulate [optional]: set to check the name of the file that would be created');
|
||||
$oP->p('mysql_bindir [optional]: specify the path for mysqldump');
|
||||
|
||||
if (utils::IsModeCLI())
|
||||
{
|
||||
$oP->p('Example: php -q backup.php --auth_user=admin --auth_pwd=myPassw0rd');
|
||||
$oP->p('Known limitation: the current directory must be the directory of backup.php');
|
||||
}
|
||||
else
|
||||
{
|
||||
$oP->p('Example: .../backup.php?backup_file=/tmp/backup.__DB__-__SUBNAME__.%Y-%m');
|
||||
}
|
||||
}
|
||||
|
||||
function ExitError($oP, $sMessage)
|
||||
{
|
||||
ToolsLog::Error($sMessage);
|
||||
$oP->p($sMessage);
|
||||
$oP->output();
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
function ReadMandatoryParam($oP, $sParam)
|
||||
{
|
||||
$sValue = utils::ReadParam($sParam, null, true /* Allow CLI */, 'raw_data');
|
||||
if (is_null($sValue))
|
||||
{
|
||||
ExitError($oP, "ERROR: Missing argument '$sParam'");
|
||||
}
|
||||
return trim($sValue);
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////
|
||||
// Main program
|
||||
|
||||
set_time_limit(0);
|
||||
|
||||
if (utils::IsModeCLI())
|
||||
{
|
||||
$oP = new CLIPage("iTop - Database Backup");
|
||||
}
|
||||
else
|
||||
{
|
||||
$oP = new WebPage("iTop - Database Backup");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
utils::UseParamFile();
|
||||
}
|
||||
catch(Exception $e)
|
||||
{
|
||||
ExitError($oP, $e->GetMessage());
|
||||
}
|
||||
|
||||
if (utils::IsModeCLI())
|
||||
{
|
||||
$oP->p(date('Y-m-d H:i:s')." - running backup utility");
|
||||
$sAuthUser = ReadMandatoryParam($oP, 'auth_user');
|
||||
$sAuthPwd = ReadMandatoryParam($oP, 'auth_pwd');
|
||||
$bDownloadBackup = false;
|
||||
if (UserRights::CheckCredentials($sAuthUser, $sAuthPwd))
|
||||
{
|
||||
UserRights::Login($sAuthUser); // Login & set the user's language
|
||||
}
|
||||
else
|
||||
{
|
||||
ExitError($oP, "Access restricted or wrong credentials ('$sAuthUser')");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
require_once(APPROOT.'application/loginwebpage.class.inc.php');
|
||||
LoginWebPage::DoLogin(); // Check user rights and prompt if needed
|
||||
$bDownloadBackup = utils::ReadParam('download', false);
|
||||
}
|
||||
|
||||
if (!UserRights::IsAdministrator())
|
||||
{
|
||||
ExitError($oP, "Access restricted to administors");
|
||||
}
|
||||
|
||||
if (CheckParam('?') || CheckParam('h') || CheckParam('help'))
|
||||
{
|
||||
Usage($oP);
|
||||
$oP->output();
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
$sDefaultBackupFileName = SetupUtils::GetTmpDir().'/'."__DB__-%Y-%m-%d";
|
||||
$sBackupFile = utils::ReadParam('backup_file', $sDefaultBackupFileName, true, 'raw_data');
|
||||
|
||||
// Interpret strftime specifications (like %Y) and database placeholders
|
||||
$oBackup = new MyDBBackup($oP);
|
||||
$oBackup->SetMySQLBinDir(MetaModel::GetConfig()->GetModuleSetting('itop-backup', 'mysql_bindir', ''));
|
||||
$sBackupFile = $oBackup->MakeName($sBackupFile);
|
||||
$sZipArchiveFile = $sBackupFile.'.zip';
|
||||
|
||||
$bSimulate = utils::ReadParam('simulate', false, true);
|
||||
$res = false;
|
||||
if ($bSimulate)
|
||||
{
|
||||
$oP->p("Simulate: would create file '$sZipArchiveFile'");
|
||||
}
|
||||
elseif (MetaModel::GetConfig()->Get('demo_mode'))
|
||||
{
|
||||
$oP->p("Sorry, iTop is in demonstration mode: the feature is disabled");
|
||||
}
|
||||
else
|
||||
{
|
||||
$oBackup->CreateZip($sZipArchiveFile);
|
||||
}
|
||||
if ($res && $bDownloadBackup)
|
||||
{
|
||||
$oBackup->DownloadBackup($sZipArchiveFile);
|
||||
}
|
||||
$oP->output();
|
||||
?>
|
||||
267
datamodels/2.x/itop-backup/check-backup.php
Normal file
267
datamodels/2.x/itop-backup/check-backup.php
Normal file
@@ -0,0 +1,267 @@
|
||||
<?php
|
||||
// Copyright (C) 2014 Combodo SARL
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; version 3 of the License.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
// Purpose: check that the backup has been successfully executed
|
||||
// this script is aimed at being invoked in CLI mode only
|
||||
|
||||
// Developer's notes:
|
||||
// Duplicated code: sys_get_temp_dir, the computation of the target filename, etc.
|
||||
|
||||
// Recommended usage in CRON
|
||||
// /usr/bin/php -q /var/www/combodo/modules/itop-backup/backup.php --backup_file=/home/backups/combodo-crm-%Y-%m-%d
|
||||
|
||||
if (!defined('__DIR__')) define('__DIR__', dirname(__FILE__));
|
||||
require_once(__DIR__.'/../../approot.inc.php');
|
||||
require_once(APPROOT.'/application/utils.inc.php');
|
||||
require_once(APPROOT.'/core/config.class.inc.php');
|
||||
|
||||
|
||||
function ReadMandatoryParam($sParam)
|
||||
{
|
||||
$value = utils::ReadParam($sParam, null, true /* Allow CLI */, 'raw_data');
|
||||
if (is_null($value))
|
||||
{
|
||||
throw new Exception("Missing argument '$sParam'");
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
if (!function_exists('sys_get_temp_dir'))
|
||||
{
|
||||
// Based on http://www.phpit.net/
|
||||
// article/creating-zip-tar-archives-dynamically-php/2/
|
||||
function sys_get_temp_dir()
|
||||
{
|
||||
// Try to get from environment variable
|
||||
if (!empty($_ENV['TMP']))
|
||||
{
|
||||
return realpath($_ENV['TMP']);
|
||||
}
|
||||
else if (!empty($_ENV['TMPDIR']))
|
||||
{
|
||||
return realpath($_ENV['TMPDIR']);
|
||||
}
|
||||
else if (!empty($_ENV['TEMP']))
|
||||
{
|
||||
return realpath($_ENV['TEMP']);
|
||||
}
|
||||
// Detect by creating a temporary file
|
||||
else
|
||||
{
|
||||
// Try to use system's temporary directory
|
||||
// as random name shouldn't exist
|
||||
$temp_file = tempnam(md5(uniqid(rand(), TRUE)), '');
|
||||
if ($temp_file)
|
||||
{
|
||||
$temp_dir = realpath(dirname($temp_file));
|
||||
unlink($temp_file);
|
||||
return $temp_dir;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function MakeArchiveFileName($iRefTime = null)
|
||||
{
|
||||
$sDefaultBackupFileName = sys_get_temp_dir().'/'."__DB__-%Y-%m-%d";
|
||||
$sBackupFile = utils::ReadParam('backup_file', $sDefaultBackupFileName, true, 'raw_data');
|
||||
|
||||
$oConfig = new Config(APPCONF.'production/config-itop.php');
|
||||
|
||||
$sBackupFile = str_replace('__HOST__', $oConfig->GetDBHost(), $sBackupFile);
|
||||
$sBackupFile = str_replace('__DB__', $oConfig->GetDBName(), $sBackupFile);
|
||||
$sBackupFile = str_replace('__SUBNAME__', $oConfig->GetDBSubName(), $sBackupFile);
|
||||
|
||||
if (is_null($iRefTime))
|
||||
{
|
||||
$sBackupFile = strftime($sBackupFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
$sBackupFile = strftime($sBackupFile, $iRefTime);
|
||||
}
|
||||
|
||||
return $sBackupFile.'.zip';
|
||||
}
|
||||
|
||||
|
||||
|
||||
function RaiseAlarm($sMessage)
|
||||
{
|
||||
echo "$sMessage\n";
|
||||
|
||||
try
|
||||
{
|
||||
$sTicketLogin = ReadMandatoryParam('check_ticket_login');
|
||||
$sTicketPwd = ReadMandatoryParam('check_ticket_pwd');
|
||||
$sTicketTitle = ReadMandatoryParam('check_ticket_title');
|
||||
$sTicketCustomer = ReadMandatoryParam('check_ticket_customer');
|
||||
$sTicketService = ReadMandatoryParam('check_ticket_service');
|
||||
$sTicketSubcategory = ReadMandatoryParam('check_ticket_service_subcategory');
|
||||
$sTicketWorkgroup = ReadMandatoryParam('check_ticket_workgroup');
|
||||
$sTicketImpactedServer = ReadMandatoryParam('check_ticket_impacted_server');
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
echo "The ticket could not be created: ".$e->GetMessage()."\n";
|
||||
return;
|
||||
}
|
||||
|
||||
$sMessage = "Server: [[Server:".$sTicketImpactedServer."]]\n".$sMessage;
|
||||
|
||||
require_once(APPROOT.'webservices/itopsoaptypes.class.inc.php');
|
||||
|
||||
//$sItopRootDefault = 'http'.((isset($_SERVER['HTTPS']) && ($_SERVER['HTTPS']!='off')) ? 's' : '').'://'.$_SERVER['SERVER_NAME'].':'.$_SERVER['SERVER_PORT'].dirname($_SERVER['SCRIPT_NAME']).'/../..';
|
||||
//$sItopRoot = utils::ReadParam('check_ticket_itop', $sItopRootDefault);
|
||||
$sItopRoot = ReadMandatoryParam('check_ticket_itop');
|
||||
|
||||
$sWsdlUri = $sItopRoot.'/webservices/itop.wsdl.php';
|
||||
//$sWsdlUri .= '?service_category=';
|
||||
|
||||
$aSOAPMapping = SOAPMapping::GetMapping();
|
||||
|
||||
ini_set("soap.wsdl_cache_enabled","0");
|
||||
$oSoapClient = new SoapClient(
|
||||
$sWsdlUri,
|
||||
array(
|
||||
'trace' => 1,
|
||||
'classmap' => $aSOAPMapping, // defined in itopsoaptypes.class.inc.php
|
||||
)
|
||||
);
|
||||
|
||||
try
|
||||
{
|
||||
$oRes = $oSoapClient->CreateIncidentTicket
|
||||
(
|
||||
$sTicketLogin, /* login */
|
||||
$sTicketPwd, /* password */
|
||||
$sTicketTitle, /* title */
|
||||
$sMessage, /* description */
|
||||
null, /* caller */
|
||||
new SOAPExternalKeySearch(array(new SOAPSearchCondition('name', $sTicketCustomer))), /* customer */
|
||||
new SOAPExternalKeySearch(array(new SOAPSearchCondition('name', $sTicketService))), /* service */
|
||||
new SOAPExternalKeySearch(array(new SOAPSearchCondition('name', $sTicketSubcategory))), /* service subcategory */
|
||||
'', /* product */
|
||||
new SOAPExternalKeySearch(array(new SOAPSearchCondition('name', $sTicketWorkgroup))), /* workgroup */
|
||||
array(
|
||||
new SOAPLinkCreationSpec(
|
||||
'Server',
|
||||
array(new SOAPSearchCondition('name', $sTicketImpactedServer)),
|
||||
array()
|
||||
),
|
||||
), /* impacted cis */
|
||||
'1', /* impact */
|
||||
'1' /* urgency */
|
||||
);
|
||||
}
|
||||
catch(Exception $e)
|
||||
{
|
||||
echo "The ticket could not be created: SOAP Exception = '".$e->getMessage()."'\n";
|
||||
}
|
||||
|
||||
//echo "<pre>\n";
|
||||
//print_r($oRes);
|
||||
//echo "</pre>\n";
|
||||
|
||||
if ($oRes->status)
|
||||
{
|
||||
$sTicketName = $oRes->result[0]->values[1]->value;
|
||||
echo "Created ticket: $sTicketName\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
echo "ERROR: Failed to create the ticket in target iTop ($sItopRoot)\n";
|
||||
foreach ($oRes->errors->messages as $oMessage)
|
||||
{
|
||||
echo $oMessage->text."\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////
|
||||
// Main
|
||||
|
||||
try
|
||||
{
|
||||
utils::UseParamFile();
|
||||
}
|
||||
catch(Exception $e)
|
||||
{
|
||||
echo "Error: ".$e->GetMessage()."\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
$sZipArchiveFile = MakeArchiveFileName();
|
||||
echo date('Y-m-d H:i:s')." - Checking file: $sZipArchiveFile\n";
|
||||
|
||||
if (file_exists($sZipArchiveFile))
|
||||
{
|
||||
if ($aStat = stat($sZipArchiveFile))
|
||||
{
|
||||
$iSize = (int) $aStat['size'];
|
||||
$iMIN = utils::ReadParam('check_size_min', 0);
|
||||
if ($iSize > $iMIN)
|
||||
{
|
||||
echo "Found the archive\n";
|
||||
$sOldArchiveFile = MakeArchiveFileName(time() - 86400); // yesterday's archive
|
||||
if (file_exists($sOldArchiveFile))
|
||||
{
|
||||
if ($aOldStat = stat($sOldArchiveFile))
|
||||
{
|
||||
echo "Comparing its size with older file: $sOldArchiveFile\n";
|
||||
$iOldSize = (int) $aOldStat['size'];
|
||||
$fVariationPercent = 100 * ($iSize - $iOldSize) / $iOldSize;
|
||||
$sVariation = round($fVariationPercent, 2)." percent(s)";
|
||||
|
||||
$iREDUCTIONMAX = utils::ReadParam('check_size_reduction_max');
|
||||
if ($fVariationPercent < -$iREDUCTIONMAX)
|
||||
{
|
||||
RaiseAlarm("Backup file '$sZipArchiveFile' changed by $sVariation, expecting a reduction limited to $iREDUCTIONMAX percents of the original size");
|
||||
}
|
||||
elseif ($fVariationPercent < 0)
|
||||
{
|
||||
echo "Size variation: $sVariation (the maximum allowed reduction is $iREDUCTIONMAX) \n";
|
||||
}
|
||||
else
|
||||
{
|
||||
echo "The archive grew by: $sVariation\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RaiseAlarm("Backup file '$sZipArchiveFile' too small (Found: $iSize, while expecting $iMIN bytes)");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RaiseAlarm("Failed to stat backup file '$sZipArchiveFile'");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RaiseAlarm("Missing backup file '$sZipArchiveFile'");
|
||||
}
|
||||
|
||||
?>
|
||||
129
datamodels/2.x/itop-backup/dbrestore.class.inc.php
Normal file
129
datamodels/2.x/itop-backup/dbrestore.class.inc.php
Normal file
@@ -0,0 +1,129 @@
|
||||
<?php
|
||||
// Copyright (C) 2014 Combodo SARL
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// iTop is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
|
||||
class DBRestore extends DBBackup
|
||||
{
|
||||
protected function LogInfo($sMsg)
|
||||
{
|
||||
//IssueLog::Info('non juste info: '.$sMsg);
|
||||
}
|
||||
protected function LogError($sMsg)
|
||||
{
|
||||
IssueLog::Error($sMsg);
|
||||
}
|
||||
|
||||
protected function LoadDatabase($sDataFile)
|
||||
{
|
||||
$this->LogInfo("Loading data onto $this->sDBHost/$this->sDBName(suffix:'$this->sDBSubName')");
|
||||
|
||||
// Just to check the connection to the DB (more accurate than getting the retcode of mysql)
|
||||
$oMysqli = $this->DBConnect();
|
||||
|
||||
$sHost = self::EscapeShellArg($this->sDBHost);
|
||||
$sUser = self::EscapeShellArg($this->sDBUser);
|
||||
$sPwd = self::EscapeShellArg($this->sDBPwd);
|
||||
$sDBName = self::EscapeShellArg($this->sDBName);
|
||||
if (empty($this->sMySQLBinDir))
|
||||
{
|
||||
$sMySQLExe = 'mysql';
|
||||
}
|
||||
else
|
||||
{
|
||||
$sMySQLExe = '"'.$this->sMySQLBinDir.'/mysql"';
|
||||
}
|
||||
if (is_null($this->iDBPort))
|
||||
{
|
||||
$sPortOption = '';
|
||||
}
|
||||
else
|
||||
{
|
||||
$sPortOption = '--port='.$this->iDBPort.' ';
|
||||
}
|
||||
|
||||
$sDataFileEscaped = self::EscapeShellArg($sDataFile);
|
||||
$sCommand = "$sMySQLExe --default-character-set=utf8 --host=$sHost $sPortOption --user=$sUser --password=$sPwd $sDBName <$sDataFileEscaped 2>&1";
|
||||
$sCommandDisplay = "$sMySQLExe --default-character-set=utf8 --host=$sHost $sPortOption --user=xxxx --password=xxxx $sDBName <$sDataFileEscaped 2>&1";
|
||||
|
||||
// Now run the command for real
|
||||
$this->LogInfo("Executing command: $sCommandDisplay");
|
||||
$aOutput = array();
|
||||
$iRetCode = 0;
|
||||
exec($sCommand, $aOutput, $iRetCode);
|
||||
foreach($aOutput as $sLine)
|
||||
{
|
||||
$this->LogInfo("mysql said: $sLine");
|
||||
}
|
||||
if ($iRetCode != 0)
|
||||
{
|
||||
$this->LogError("Failed to execute: $sCommandDisplay. The command returned:$iRetCode");
|
||||
foreach($aOutput as $sLine)
|
||||
{
|
||||
$this->LogError("mysql said: $sLine");
|
||||
}
|
||||
if (count($aOutput) == 1)
|
||||
{
|
||||
$sMoreInfo = trim($aOutput[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
$sMoreInfo = "Check the log file '".realpath(APPROOT.'/log/error.log')."' for more information.";
|
||||
}
|
||||
throw new BackupException("Failed to execute mysql: ".$sMoreInfo);
|
||||
}
|
||||
}
|
||||
|
||||
public function RestoreFromZip($sZipFile, $sEnvironment = 'production')
|
||||
{
|
||||
$this->LogInfo("Starting restore of ".basename($sZipFile));
|
||||
|
||||
$oZip = new ZipArchive();
|
||||
$res = $oZip->open($sZipFile);
|
||||
|
||||
// Load the database
|
||||
//
|
||||
$sDataDir = tempnam(SetupUtils::GetTmpDir(), 'itop-');
|
||||
unlink($sDataDir); // I need a directory, not a file...
|
||||
SetupUtils::builddir($sDataDir); // Here is the directory
|
||||
$oZip->extractTo($sDataDir, 'itop-dump.sql');
|
||||
$sDataFile = $sDataDir.'/itop-dump.sql';
|
||||
$this->LoadDatabase($sDataFile);
|
||||
unlink($sDataFile);
|
||||
|
||||
// Update the code
|
||||
//
|
||||
$sDeltaFile = APPROOT.'data/'.$sEnvironment.'.delta.xml';
|
||||
if ($oZip->locateName('delta.xml') !== false)
|
||||
{
|
||||
// Extract and rename delta.xml => <env>.delta.xml;
|
||||
file_put_contents($sDeltaFile, $oZip->getFromName('delta.xml'));
|
||||
}
|
||||
else
|
||||
{
|
||||
@unlink($sDeltaFile);
|
||||
}
|
||||
$sConfigFile = APPROOT.'conf/'.$sEnvironment.'/config-itop.php';
|
||||
@chmod($sConfigFile, 0770); // Allow overwriting the file
|
||||
$oZip->extractTo(APPROOT.'conf/'.$sEnvironment, 'config-itop.php');
|
||||
@chmod($sConfigFile, 0444); // Read-only
|
||||
|
||||
$oEnvironment = new RunTimeEnvironment($sEnvironment);
|
||||
$oEnvironment->CompileFrom($sEnvironment);
|
||||
}
|
||||
}
|
||||
|
||||
48
datamodels/2.x/itop-backup/de.dict.itop-backup.php
Normal file
48
datamodels/2.x/itop-backup/de.dict.itop-backup.php
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
/**
|
||||
* Localized data
|
||||
*
|
||||
* @copyright Copyright (C) 2013 Combodo
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
|
||||
* @author Robert Jaehne <robert.jaehne@itomig.de>
|
||||
|
||||
*/
|
||||
|
||||
Dict::Add('DE DE', 'German', 'Deutsch', array(
|
||||
|
||||
'bkp-backup-running' => 'Backup wird durchgeführt. Bitte warten ...',
|
||||
'bkp-restore-running' => 'Wiederherstellung läuft. Bitte warten ...',
|
||||
|
||||
'Menu:BackupStatus' => 'Geplante Backups',
|
||||
'bkp-status-title' => 'Geplante Backups',
|
||||
'bkp-status-checks' => 'Einstellungen und Prüfungen',
|
||||
'bkp-mysqldump-ok' => 'mysqldump ist vorhanden: %1$s',
|
||||
'bkp-mysqldump-notfound' => 'mysqldump wurde nicht gefunden: %1$s - Stellen sie sicher, das er eingespielt und im Pfad verfügbar ist oder editieren sie die Konfigurationsdatei um das MySQL bindir anzupassen.',
|
||||
'bkp-mysqldump-issue' => 'mysqldump konnte nicht eingespielt werden (retcode=%1$d): Stellen sie sicher, das er eingespielt und im Pfad verfügbar ist oder editieren sie die Konfigurationsdatei um das MySQL bindir anzupassen.',
|
||||
'bkp-missing-dir' => 'Zielverzeichniss %1$s nicht gefunden',
|
||||
'bkp-free-disk-space' => '<b>%1$s frei</b> in %2$s',
|
||||
'bkp-dir-not-writeable' => '%1$s ist nicht schreibbar',
|
||||
'bkp-wrong-format-spec' => 'Die verwendete Definition zur Formatierung von Dateinamen ist nicht korrekt (%1$s). Die Standard-Definition %2$s wird verwendet',
|
||||
'bkp-name-sample' => 'Backup-Dateien werden abhängig von Datum, Zeit und Datenbank-Identifier erstellt. Beispiel: %1$s',
|
||||
'bkp-week-days' => 'Backups werden <b>jeden %1$s um %2$s durchgeführt</b>',
|
||||
'bkp-retention' => 'Mindestens <b>%1$d Backups werden im Zielverzeichniss vorgehalten</b>',
|
||||
'bkp-next-to-delete' => 'Wird gelöscht, wenn das nächste Backup angelegt wird (unter Einstellungen "Menge vorhalten")',
|
||||
'bkp-table-file' => 'Datei',
|
||||
'bkp-table-file+' => 'Nur Dateien mit der Endung .zip werden als Backup-Dateien berücksichtigt.',
|
||||
'bkp-table-size' => 'Grösse',
|
||||
'bkp-table-size+' => '',
|
||||
'bkp-table-actions' => 'Aktionen',
|
||||
'bkp-table-actions+' => '',
|
||||
'bkp-status-backups-auto' => 'Geplante Backups',
|
||||
'bkp-status-backups-manual' => 'Manuelle Backups',
|
||||
'bkp-status-backups-none' => 'Kein Backup vorhanden',
|
||||
'bkp-next-backup' => 'Das nächste Backup wird am <b>%1$s</b> (%2$s) um %3$s durchgeführt',
|
||||
'bkp-button-backup-now' => 'Backup läuft!',
|
||||
'bkp-button-restore-now' => 'Wiederherstellen!',
|
||||
'bkp-confirm-backup' => 'Bitte bestätigen sie, dass sie jetzt ein Backup erstellen wollen now.',
|
||||
'bkp-confirm-restore' => 'Bitte bestätigen sie, dass sie mit Backup %1$s eine Wiederherstellung durchführen wollen.',
|
||||
'bkp-wait-backup' => 'Bitte warten, bis das Backup abgeschlossen ist ...',
|
||||
'bkp-wait-restore' => 'Bitte warten, bis die Wiederherstellung abgeschlossen ist ...',
|
||||
'bkp-success-restore' => 'Wiederherstellung erfolgreich.',
|
||||
));
|
||||
46
datamodels/2.x/itop-backup/en.dict.itop-backup.php
Normal file
46
datamodels/2.x/itop-backup/en.dict.itop-backup.php
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
/**
|
||||
* Localized data
|
||||
*
|
||||
* @copyright Copyright (C) 2013 Combodo
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
Dict::Add('EN US', 'English', 'English', array(
|
||||
|
||||
'bkp-backup-running' => 'A backup is running. Please wait...',
|
||||
'bkp-restore-running' => 'A restore is running. Please wait...',
|
||||
|
||||
'Menu:BackupStatus' => 'Scheduled Backups',
|
||||
'bkp-status-title' => 'Scheduled Backups',
|
||||
'bkp-status-checks' => 'Settings and checks',
|
||||
'bkp-mysqldump-ok' => 'mysqldump is present: %1$s',
|
||||
'bkp-mysqldump-notfound' => 'mysqldump could not be found: %1$s - Please make sure it is installed and in the path, or edit the configuration file to tune mysql_bindir.',
|
||||
'bkp-mysqldump-issue' => 'mysqldump could not be executed (retcode=%1$d): Please make sure it is installed and in the path, or edit the configuration file to tune mysql_bindir',
|
||||
'bkp-missing-dir' => 'The target directory %1$s count not be found',
|
||||
'bkp-free-disk-space' => '<b>%1$s free</b> in %2$s',
|
||||
'bkp-dir-not-writeable' => '%1$s is not writeable',
|
||||
'bkp-wrong-format-spec' => 'The current specification to format the file names is wrong (%1$s). A default specification will apply: %2$s',
|
||||
'bkp-name-sample' => 'Backup files are named depending on DB identifiers, date and time. Example: %1$s',
|
||||
'bkp-week-days' => 'Backups will occur <b>every %1$s at %2$s</b>',
|
||||
'bkp-retention' => 'At most <b>%1$d backup files will be kept</b> in the target directory.',
|
||||
'bkp-next-to-delete' => 'Will be deleted when the next backup occurs (see the setting "retention_count")',
|
||||
'bkp-table-file' => 'File',
|
||||
'bkp-table-file+' => 'Only files having the extension .zip are considered as being backup files',
|
||||
'bkp-table-size' => 'Size',
|
||||
'bkp-table-size+' => '',
|
||||
'bkp-table-actions' => 'Actions',
|
||||
'bkp-table-actions+' => '',
|
||||
'bkp-status-backups-auto' => 'Scheduled backups',
|
||||
'bkp-status-backups-manual' => 'Manual backups',
|
||||
'bkp-status-backups-none' => 'No backup yet',
|
||||
'bkp-next-backup' => 'The next backup will occur on <b>%1$s</b> (%2$s) at %3$s',
|
||||
'bkp-button-backup-now' => 'Backup now!',
|
||||
'bkp-button-restore-now' => 'Restore!',
|
||||
'bkp-confirm-backup' => 'Please confirm that you do request the backup to occur right now.',
|
||||
'bkp-confirm-restore' => 'Please confirm that you do want to restore the backup %1$s.',
|
||||
'bkp-wait-backup' => 'Please wait for the backup to complete...',
|
||||
'bkp-wait-restore' => 'Please wait for the restore to complete...',
|
||||
'bkp-success-restore' => 'Restore successfully completed.',
|
||||
));
|
||||
?>
|
||||
46
datamodels/2.x/itop-backup/fr.dict.itop-backup.php
Normal file
46
datamodels/2.x/itop-backup/fr.dict.itop-backup.php
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
/**
|
||||
* Localized data
|
||||
*
|
||||
* @copyright Copyright (C) 2013 Combodo
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
Dict::Add('FR FR', 'French', 'Français', array(
|
||||
|
||||
'bkp-backup-running' => 'Une sauvegarde est en cours. Veuillez patienter...',
|
||||
'bkp-restore-running' => 'Une restauration des données est en cours. Veuillez patienter...',
|
||||
|
||||
'Menu:BackupStatus' => 'Sauvegarde automatique',
|
||||
'bkp-status-title' => 'Sauvegarde automatique',
|
||||
'bkp-status-checks' => 'Réglages et vérifications',
|
||||
'bkp-mysqldump-ok' => 'mysqldump est installé: %1$s',
|
||||
'bkp-mysqldump-notfound' => 'mysqldump n\'a pas été trouvé: %1$s - Veuillez vous assurer que les outils mysql sont installés et qu\'ils sont accessibles en ligne de commande, ou bien éditez le fichier de configuration pour en donner le chemin via mysql_bindir.',
|
||||
'bkp-mysqldump-issue' => 'mysqldump n\'a pas pu être exécuté (code de retour: %1$d). Veuillez vérifier que les outils mysql sont installés et qu\'ils sont accessibles en ligne de commande, ou bien éditez le fichier de configuration pour en donner le chemin via mysql_bindir.',
|
||||
'bkp-missing-dir' => 'Le répertoire cible \'%1$s\' n\'existe pas ou ne peut pas être lu.',
|
||||
'bkp-free-disk-space' => 'Vous disposez de <b>%1$s d\'espace disque</b> sur %2$s',
|
||||
'bkp-dir-not-writeable' => 'Le répertoire cible \'%1$s\' n\'est pas accessible en écriture.',
|
||||
'bkp-wrong-format-spec' => 'La spécification de format pour le nom des sauvegarde est incorrecte (%1$s). La spécification par défaut sera appliquée: %2$s',
|
||||
'bkp-name-sample' => 'Les fichiers de sauvegardes seront nommés en fonction de la base, la date et l\'heure. Par exemple: %1$s',
|
||||
'bkp-week-days' => 'Les sauvegardes seront effectuées <b>tous les %1$s à %2$s</b>',
|
||||
'bkp-retention' => 'Au plus <b>%1$d fichiers de sauvegardes seront conservés</b> dans le répertoire cible.',
|
||||
'bkp-next-to-delete' => 'Sera effacé lors de la prochaine sauvegarde (Cf. réglage "retention_count")',
|
||||
'bkp-table-file' => 'Fichier',
|
||||
'bkp-table-file+' => 'Seuls les fichiers ayant l\'extension .zip sont considérés comme étant des fichiers de sauvegarde',
|
||||
'bkp-table-size' => 'Taille',
|
||||
'bkp-table-size+' => '',
|
||||
'bkp-table-actions' => 'Actions',
|
||||
'bkp-table-actions+' => '',
|
||||
'bkp-status-backups-auto' => 'Sauvegardes automatiques',
|
||||
'bkp-status-backups-manual' => 'Sauvegardes manuelles',
|
||||
'bkp-status-backups-none' => 'Aucune sauvegarde n\'a été faite jusqu\' à présent.',
|
||||
'bkp-next-backup' => 'La prochaine sauvegarde aura lieu <b>%1$s</b> (%2$s) à %3$s',
|
||||
'bkp-button-backup-now' => 'Sauvegarder maintenant !',
|
||||
'bkp-button-restore-now' => 'Restaurer !',
|
||||
'bkp-confirm-backup' => 'Veuillez confirmer que vous souhaiter effectuer une sauvegarde maintenant.',
|
||||
'bkp-confirm-restore' => 'Veuillez confirmer que vous souhaiter effectuer la restauration de \'%1$s\' maintenant.',
|
||||
'bkp-wait-backup' => 'Sauvegarde en cours...',
|
||||
'bkp-wait-restore' => 'Restauration des données en cours...',
|
||||
'bkp-success-restore' => 'Restauration des données terminée.',
|
||||
));
|
||||
?>
|
||||
302
datamodels/2.x/itop-backup/main.itop-backup.php
Normal file
302
datamodels/2.x/itop-backup/main.itop-backup.php
Normal file
@@ -0,0 +1,302 @@
|
||||
<?php
|
||||
// Copyright (C) 2014 Combodo SARL
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; version 3 of the License.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
|
||||
require_once(APPROOT.'setup/setuputils.class.inc.php');
|
||||
require_once(APPROOT.'setup/backup.class.inc.php');
|
||||
require_once(APPROOT.'core/mutex.class.inc.php');
|
||||
|
||||
|
||||
define('BACKUP_DEFAULT_FORMAT', '__DB__-%Y-%m-%d_%H_%M');
|
||||
|
||||
class BackupHandler extends ModuleHandlerAPI
|
||||
{
|
||||
public static function OnMetaModelStarted()
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
$oBackupMutex = new iTopMutex('backup.'.utils::GetCurrentEnvironment());
|
||||
if ($oBackupMutex->TryLock())
|
||||
{
|
||||
$oBackupMutex->Unlock();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not needed: the DB dump is done in a single transaction
|
||||
//MetaModel::GetConfig()->Set('access_mode', ACCESS_READONLY, 'itop-backup');
|
||||
//MetaModel::GetConfig()->Set('access_message', ' - '.dict::S('bkp-backup-running'), 'itop-backup');
|
||||
}
|
||||
|
||||
$oRestoreMutex = new iTopMutex('restore.'.utils::GetCurrentEnvironment());
|
||||
if ($oRestoreMutex->TryLock())
|
||||
{
|
||||
$oRestoreMutex->Unlock();
|
||||
}
|
||||
else
|
||||
{
|
||||
MetaModel::GetConfig()->Set('access_mode', ACCESS_READONLY, 'itop-backup');
|
||||
MetaModel::GetConfig()->Set('access_message', ' - '.dict::S('bkp-restore-running'), 'itop-backup');
|
||||
}
|
||||
}
|
||||
catch(Exception $e)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class DBBackupScheduled extends DBBackup
|
||||
{
|
||||
protected function LogInfo($sMsg)
|
||||
{
|
||||
static $bDebug = null;
|
||||
if ($bDebug == null)
|
||||
{
|
||||
$bDebug = MetaModel::GetConfig()->GetModuleSetting('itop-backup', 'debug', false);
|
||||
}
|
||||
|
||||
if ($bDebug)
|
||||
{
|
||||
echo $sMsg."\n";
|
||||
}
|
||||
}
|
||||
|
||||
protected function LogError($sMsg)
|
||||
{
|
||||
static $bDebug = null;
|
||||
if ($bDebug == null)
|
||||
{
|
||||
$bDebug = MetaModel::GetConfig()->GetModuleSetting('itop-backup', 'debug', false);
|
||||
}
|
||||
|
||||
IssueLog::Error($sMsg);
|
||||
if ($bDebug)
|
||||
{
|
||||
echo 'Error: '.$sMsg."\n";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* List and order by date the backups in the given directory
|
||||
* Note: the algorithm is currently based on the file modification date... because there is no "creation date" in general
|
||||
*/
|
||||
public function ListFiles($sBackupDir)
|
||||
{
|
||||
$aFiles = array();
|
||||
$aTimes = array();
|
||||
foreach(glob($sBackupDir.'*.zip') as $sFilePath)
|
||||
{
|
||||
$aFiles[] = $sFilePath;
|
||||
$aTimes[] = filemtime($sFilePath); // unix time
|
||||
}
|
||||
array_multisort($aTimes, $aFiles);
|
||||
|
||||
return $aFiles;
|
||||
}
|
||||
}
|
||||
|
||||
class BackupExec implements iScheduledProcess
|
||||
{
|
||||
protected $sBackupDir;
|
||||
protected $iRetentionCount;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param sBackupDir string Target directory, defaults to APPROOT/data/backups/auto
|
||||
* @param iRetentionCount int Rotation (default to the value given in the configuration file 'retentation_count') set to 0 to disable this feature
|
||||
*/
|
||||
public function __construct($sBackupDir = null, $iRetentionCount = null)
|
||||
{
|
||||
if (is_null($sBackupDir))
|
||||
{
|
||||
$this->sBackupDir = APPROOT.'data/backups/auto/';
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->sBackupDir = $sBackupDir;
|
||||
}
|
||||
if (is_null($iRetentionCount))
|
||||
{
|
||||
$this->iRetentionCount = MetaModel::GetConfig()->GetModuleSetting('itop-backup', 'retention_count', 5);
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->iRetentionCount = $iRetentionCount;
|
||||
}
|
||||
}
|
||||
|
||||
public function Process($iUnixTimeLimit)
|
||||
{
|
||||
$oMutex = new iTopMutex('backup.'.utils::GetCurrentEnvironment());
|
||||
$oMutex->Lock();
|
||||
|
||||
try
|
||||
{
|
||||
// Make sure the target directory exists
|
||||
SetupUtils::builddir($this->sBackupDir);
|
||||
|
||||
$oBackup = new DBBackupScheduled();
|
||||
|
||||
// Eliminate files exceeding the retention setting
|
||||
//
|
||||
if ($this->iRetentionCount > 0)
|
||||
{
|
||||
$aFiles = $oBackup->ListFiles($this->sBackupDir);
|
||||
while (count($aFiles) >= $this->iRetentionCount)
|
||||
{
|
||||
$sFileToDelete = array_shift($aFiles);
|
||||
unlink($sFileToDelete);
|
||||
if (file_exists($sFileToDelete))
|
||||
{
|
||||
// Ok, do not loop indefinitely on this
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Do execute the backup
|
||||
//
|
||||
$oBackup->SetMySQLBinDir(MetaModel::GetConfig()->GetModuleSetting('itop-backup', 'mysql_bindir', ''));
|
||||
|
||||
$sBackupFile = MetaModel::GetConfig()->GetModuleSetting('itop-backup', 'file_name_format', '__DB__-%Y-%m-%d_%H_%M');
|
||||
$sName = $oBackup->MakeName($sBackupFile);
|
||||
if ($sName == '')
|
||||
{
|
||||
$sName = $oBackup->MakeName(BACKUP_DEFAULT_FORMAT);
|
||||
}
|
||||
$sZipFile = $this->sBackupDir.$sName.'.zip';
|
||||
$sSourceConfigFile = APPCONF.utils::GetCurrentEnvironment().'/'.ITOP_CONFIG_FILE;
|
||||
$oBackup->CreateZip($sZipFile, $sSourceConfigFile);
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
$oMutex->Unlock();
|
||||
throw $e;
|
||||
}
|
||||
$oMutex->Unlock();
|
||||
return "Created the backup: $sZipFile";
|
||||
}
|
||||
|
||||
/*
|
||||
Interpret current setting for the week days
|
||||
@returns array of int (monday = 1)
|
||||
*/
|
||||
public function InterpretWeekDays()
|
||||
{
|
||||
static $aWEEKDAYTON = array('monday' => 1, 'tuesday' => 2, 'wednesday' => 3, 'thursday' => 4, 'friday' => 5, 'saturday' => 6, 'sunday' => 7);
|
||||
$aDays = array();
|
||||
$sWeekDays = MetaModel::GetConfig()->GetModuleSetting('itop-backup', 'week_days', 'monday, tuesday, wednesday, thursday, friday');
|
||||
if ($sWeekDays != '')
|
||||
{
|
||||
$aWeekDaysRaw = explode(',', $sWeekDays);
|
||||
foreach ($aWeekDaysRaw as $sWeekDay)
|
||||
{
|
||||
$sWeekDay = strtolower(trim($sWeekDay));
|
||||
if (array_key_exists($sWeekDay, $aWEEKDAYTON))
|
||||
{
|
||||
$aDays[] = $aWEEKDAYTON[$sWeekDay];
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("'itop-backup: wrong format for setting 'week_days' (found '$sWeekDay')");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (count($aDays) == 0)
|
||||
{
|
||||
throw new Exception("'itop-backup: missing setting 'week_days'");
|
||||
}
|
||||
$aDays = array_unique($aDays);
|
||||
sort($aDays);
|
||||
return $aDays;
|
||||
}
|
||||
|
||||
/*
|
||||
Gives the exact time at which the process must be run next time
|
||||
@returns DateTime
|
||||
*/
|
||||
public function GetNextOccurrence()
|
||||
{
|
||||
$bEnabled = MetaModel::GetConfig()->GetModuleSetting('itop-backup', 'enabled', true);
|
||||
if (!$bEnabled)
|
||||
{
|
||||
$oRet = new DateTime('3000-01-01');
|
||||
}
|
||||
else
|
||||
{
|
||||
// 1st - Interpret the list of days as ordered numbers (monday = 1)
|
||||
//
|
||||
$aDays = $this->InterpretWeekDays();
|
||||
|
||||
// 2nd - Find the next active week day
|
||||
//
|
||||
$sBackupTime = MetaModel::GetConfig()->GetModuleSetting('itop-backup', 'time', '23:30');
|
||||
if (!preg_match('/[0-2][0-9]:[0-5][0-9]/', $sBackupTime))
|
||||
{
|
||||
throw new Exception("'itop-backup: wrong format for setting 'time' (found '$sBackupTime')");
|
||||
}
|
||||
$oNow = new DateTime();
|
||||
$iNextPos = false;
|
||||
for ($iDay = $oNow->format('N') ; $iDay <= 7 ; $iDay++)
|
||||
{
|
||||
$iNextPos = array_search($iDay, $aDays);
|
||||
if ($iNextPos !== false)
|
||||
{
|
||||
if (($iDay > $oNow->format('N')) || ($oNow->format('H:i') < $sBackupTime))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3rd - Compute the result
|
||||
//
|
||||
if ($iNextPos === false)
|
||||
{
|
||||
// Jump to the first day within the next week
|
||||
$iFirstDayOfWeek = $aDays[0];
|
||||
$iDayMove = $oNow->format('N') - $iFirstDayOfWeek;
|
||||
$oRet = clone $oNow;
|
||||
$oRet->modify('-'.$iDayMove.' days');
|
||||
$oRet->modify('+1 weeks');
|
||||
}
|
||||
else
|
||||
{
|
||||
$iNextDayOfWeek = $aDays[$iNextPos];
|
||||
$iMove = $iNextDayOfWeek - $oNow->format('N');
|
||||
$oRet = clone $oNow;
|
||||
$oRet->modify('+'.$iMove.' days');
|
||||
}
|
||||
list($sHours, $sMinutes) = explode(':', $sBackupTime);
|
||||
$oRet->setTime((int)$sHours, (int) $sMinutes);
|
||||
}
|
||||
return $oRet;
|
||||
}
|
||||
}
|
||||
|
||||
class ItopBackup extends ModuleHandlerAPI
|
||||
{
|
||||
public static function OnMenuCreation()
|
||||
{
|
||||
if (UserRights::IsAdministrator())
|
||||
{
|
||||
$oAdminMenu = new MenuGroup('AdminTools', 80 /* fRank */);
|
||||
new WebPageMenuNode('BackupStatus', utils::GetAbsoluteUrlModulePage('itop-backup', 'status.php'), $oAdminMenu->GetIndex(), 15 /* fRank */);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
60
datamodels/2.x/itop-backup/module.itop-backup.php
Normal file
60
datamodels/2.x/itop-backup/module.itop-backup.php
Normal file
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-backup/2.1.1',
|
||||
array(
|
||||
// Identification
|
||||
//
|
||||
'label' => 'Backup utilities',
|
||||
'category' => 'Application management',
|
||||
|
||||
// Setup
|
||||
//
|
||||
'dependencies' => array(
|
||||
),
|
||||
'mandatory' => true,
|
||||
'visible' => false,
|
||||
|
||||
// Components
|
||||
//
|
||||
'datamodel' => array(
|
||||
'main.itop-backup.php',
|
||||
//'model.itop-backup.php',
|
||||
),
|
||||
'webservice' => array(
|
||||
//'webservices.itop-backup.php',
|
||||
),
|
||||
'dictionary' => array(
|
||||
'en.dict.itop-backup.php',
|
||||
'fr.dict.itop-backup.php',
|
||||
//'de.dict.itop-backup.php',
|
||||
),
|
||||
'data.struct' => array(
|
||||
//'data.struct.itop-backup.xml',
|
||||
),
|
||||
'data.sample' => array(
|
||||
//'data.sample.itop-backup.xml',
|
||||
),
|
||||
|
||||
// Documentation
|
||||
//
|
||||
'doc.manual_setup' => '',
|
||||
'doc.more_information' => '',
|
||||
|
||||
// Default settings
|
||||
//
|
||||
'settings' => array(
|
||||
'mysql_bindir' => '',
|
||||
'week_days' => 'monday, tuesday, wednesday, thursday, friday',
|
||||
'time' => '23:30',
|
||||
//'file_name_format' => '__DB__-%Y-%m-%d_%H_%M',
|
||||
'retention_count' => 5,
|
||||
'enabled' => true,
|
||||
'debug' => false
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
?>
|
||||
410
datamodels/2.x/itop-backup/status.php
Normal file
410
datamodels/2.x/itop-backup/status.php
Normal file
@@ -0,0 +1,410 @@
|
||||
<?php
|
||||
// Copyright (C) 2014 Combodo SARL
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// iTop is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
|
||||
/**
|
||||
* Monitor the backup
|
||||
*
|
||||
* @copyright Copyright (C) 2013 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
if (!defined('__DIR__')) define('__DIR__', dirname(__FILE__));
|
||||
require_once(__DIR__.'/../../approot.inc.php');
|
||||
require_once(APPROOT.'application/application.inc.php');
|
||||
require_once(APPROOT.'application/itopwebpage.class.inc.php');
|
||||
|
||||
require_once(APPROOT.'application/startup.inc.php');
|
||||
|
||||
require_once(APPROOT.'application/loginwebpage.class.inc.php');
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// Main program
|
||||
//
|
||||
LoginWebPage::DoLogin(true); // Check user rights and prompt if needed (must be admin)
|
||||
|
||||
//$sOperation = utils::ReadParam('operation', 'menu');
|
||||
//$oAppContext = new ApplicationContext();
|
||||
|
||||
$oP = new iTopWebPage(Dict::S('bkp-status-title'));
|
||||
$oP->set_base(utils::GetAbsoluteUrlAppRoot().'pages/');
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
$oP->add("<h1>".Dict::S('bkp-status-title')."</h1>");
|
||||
|
||||
if (MetaModel::GetConfig()->Get('demo_mode'))
|
||||
{
|
||||
$oP->add("<div class=\"header_message message_info\">iTop is in <b>demonstration mode</b>: the feature is disabled.</div>");
|
||||
}
|
||||
|
||||
$sImgOk = '<img src="../images/validation_ok.png"> ';
|
||||
$sImgError = '<img src="../images/validation_error.png"> ';
|
||||
|
||||
$oP->add("<fieldset>");
|
||||
$oP->add("<legend>".Dict::S('bkp-status-checks')."</legend>");
|
||||
|
||||
// Availability of mysqldump
|
||||
//
|
||||
$sMySQLBinDir = MetaModel::GetConfig()->GetModuleSetting('itop-backup', 'mysql_bindir', '');
|
||||
$sMySQLBinDir = utils::ReadParam('mysql_bindir', $sMySQLBinDir, true);
|
||||
if (empty($sMySQLBinDir))
|
||||
{
|
||||
$sMySQLDump = 'mysqldump';
|
||||
}
|
||||
else
|
||||
{
|
||||
//echo 'Info - Found mysql_bindir: '.$sMySQLBinDir;
|
||||
$sMySQLDump = '"'.$sMySQLBinDir.'/mysqldump"';
|
||||
}
|
||||
$sCommand = "$sMySQLDump -V 2>&1";
|
||||
|
||||
$aOutput = array();
|
||||
$iRetCode = 0;
|
||||
exec($sCommand, $aOutput, $iRetCode);
|
||||
if ($iRetCode == 0)
|
||||
{
|
||||
$sMySqlDump = $sImgOk.Dict::Format("bkp-mysqldump-ok", $aOutput[0]);
|
||||
}
|
||||
elseif ($iRetCode == 1)
|
||||
{
|
||||
$sMySqlDump = $sImgError.Dict::Format("bkp-mysqldump-notfound", implode(' ', $aOutput));
|
||||
}
|
||||
else
|
||||
{
|
||||
$sMySqlDump = $sImgError.Dict::Format("bkp-mysqldump-issue", $iRetCode);
|
||||
}
|
||||
foreach($aOutput as $sLine)
|
||||
{
|
||||
//echo 'Info - mysqldump -V said: '.$sLine;
|
||||
}
|
||||
$oP->p($sMySqlDump);
|
||||
|
||||
// Destination directory
|
||||
//
|
||||
// Make sure the target directory exists and is writeable
|
||||
$sBackupDir = APPROOT.'data/backups/';
|
||||
SetupUtils::builddir($sBackupDir);
|
||||
if (!is_dir($sBackupDir))
|
||||
{
|
||||
$oP->p($sImgError.Dict::Format('bkp-missing-dir', $sBackupDir));
|
||||
}
|
||||
else
|
||||
{
|
||||
$oP->p(Dict::Format('bkp-free-disk-space', SetupUtils::HumanReadableSize(SetupUtils::CheckDiskSpace($sBackupDir)), $sBackupDir));
|
||||
if (!is_writable($sBackupDir))
|
||||
{
|
||||
$oP->p($sImgError.Dict::Format('bkp-dir-not-writeable', $sBackupDir));
|
||||
}
|
||||
}
|
||||
$sBackupDirAuto = $sBackupDir.'auto/';
|
||||
SetupUtils::builddir($sBackupDirAuto);
|
||||
$sBackupDirManual = $sBackupDir.'manual/';
|
||||
SetupUtils::builddir($sBackupDirManual);
|
||||
|
||||
// Wrong format
|
||||
//
|
||||
$sBackupFile = MetaModel::GetConfig()->GetModuleSetting('itop-backup', 'file_name_format', BACKUP_DEFAULT_FORMAT);
|
||||
$oBackup = new DBBackupScheduled();
|
||||
$sZipName = $oBackup->MakeName($sBackupFile);
|
||||
if ($sZipName == '')
|
||||
{
|
||||
$oP->p($sImgError.Dict::Format('bkp-wrong-format-spec', $sBackupFile, BACKUP_DEFAULT_FORMAT));
|
||||
}
|
||||
else
|
||||
{
|
||||
$oP->p(Dict::Format('bkp-name-sample', $sZipName));
|
||||
}
|
||||
|
||||
// Week Days
|
||||
//
|
||||
$aWeekDayToString = array(
|
||||
1 => Dict::S('DayOfWeek-Monday'),
|
||||
2 => Dict::S('DayOfWeek-Tuesday'),
|
||||
3 => Dict::S('DayOfWeek-Wednesday'),
|
||||
4 => Dict::S('DayOfWeek-Thursday'),
|
||||
5 => Dict::S('DayOfWeek-Friday'),
|
||||
6 => Dict::S('DayOfWeek-Saturday'),
|
||||
7 => Dict::S('DayOfWeek-Sunday')
|
||||
);
|
||||
$aDayLabels = array();
|
||||
$oBackupExec = new BackupExec();
|
||||
foreach ($oBackupExec->InterpretWeekDays() as $iDay)
|
||||
{
|
||||
$aDayLabels[] = $aWeekDayToString[$iDay];
|
||||
}
|
||||
$sDays = implode(', ', $aDayLabels);
|
||||
$sBackupTime = MetaModel::GetConfig()->GetModuleSetting('itop-backup', 'time', '23:30');
|
||||
$oP->p(Dict::Format('bkp-week-days', $sDays, $sBackupTime));
|
||||
|
||||
$iRetention = MetaModel::GetConfig()->GetModuleSetting('itop-backup', 'retention_count', 5);
|
||||
$oP->p(Dict::Format('bkp-retention', $iRetention));
|
||||
|
||||
$oP->add("</fieldset>");
|
||||
|
||||
// List of backups
|
||||
//
|
||||
$aFiles = $oBackup->ListFiles($sBackupDirAuto);
|
||||
$aFilesToDelete = array();
|
||||
while (count($aFiles) > $iRetention - 1)
|
||||
{
|
||||
$aFilesToDelete[] = array_shift($aFiles);
|
||||
}
|
||||
|
||||
$oRestoreMutex = new iTopMutex('restore.'.utils::GetCurrentEnvironment());
|
||||
if ($oRestoreMutex->TryLock())
|
||||
{
|
||||
$oRestoreMutex->Unlock();
|
||||
$sDisableRestore = '';
|
||||
}
|
||||
else
|
||||
{
|
||||
$sDisableRestore = 'disabled="disabled"';
|
||||
}
|
||||
|
||||
// 1st table: list the backups made in the background
|
||||
//
|
||||
$aDetails = array();
|
||||
foreach ($oBackup->ListFiles($sBackupDirAuto) as $sBackupFile)
|
||||
{
|
||||
$sFileName = basename($sBackupFile);
|
||||
$sFilePath = 'auto/'.$sFileName;
|
||||
if (MetaModel::GetConfig()->Get('demo_mode'))
|
||||
{
|
||||
$sName = $sFileName;
|
||||
}
|
||||
else
|
||||
{
|
||||
$sAjax = utils::GetAbsoluteUrlModulePage('itop-backup', 'ajax.backup.php', array('operation' => 'download', 'file' => $sFilePath));
|
||||
$sName = "<a href=\"$sAjax\">".$sFileName.'</a>';
|
||||
}
|
||||
$sSize = SetupUtils::HumanReadableSize(filesize($sBackupFile));
|
||||
$sConfirmRestore = addslashes(Dict::Format('bkp-confirm-restore', $sFileName));
|
||||
$sFileEscaped = addslashes($sFilePath);
|
||||
$sRestoreBtn = '<button class="restore" onclick="LaunchRestoreNow(\''.$sFileEscaped.'\', \''.$sConfirmRestore.'\');" '.$sDisableRestore.'>'.Dict::S('bkp-button-restore-now').'</button>';
|
||||
if (in_array($sBackupFile, $aFilesToDelete))
|
||||
{
|
||||
$aDetails[] = array('file' => $sName.' <span class="next_to_delete" title="'.Dict::S('bkp-next-to-delete').'">*</span>', 'size' => $sSize, 'actions' => $sRestoreBtn);
|
||||
}
|
||||
else
|
||||
{
|
||||
$aDetails[] = array('file' => $sName, 'size' => $sSize, 'actions' => $sRestoreBtn);
|
||||
}
|
||||
}
|
||||
$aConfig = array(
|
||||
'file' => array('label' => Dict::S('bkp-table-file'), 'description' => Dict::S('bkp-table-file+')),
|
||||
'size' => array('label' => Dict::S('bkp-table-size'), 'description' => Dict::S('bkp-table-size+')),
|
||||
'actions' => array('label' => Dict::S('bkp-table-actions'), 'description' => Dict::S('bkp-table-actions+')),
|
||||
);
|
||||
$oP->add("<fieldset>");
|
||||
$oP->add("<legend>".Dict::S('bkp-status-backups-auto')."</legend>");
|
||||
if (count($aDetails) > 0)
|
||||
{
|
||||
$oP->add('<div style="max-height:400px; overflow: auto;">');
|
||||
$oP->table($aConfig, array_reverse($aDetails));
|
||||
$oP->add('</div>');
|
||||
}
|
||||
else
|
||||
{
|
||||
$oP->p(Dict::S('bkp-status-backups-none'));
|
||||
}
|
||||
$oP->add("</fieldset>");
|
||||
|
||||
// 2nd table: list the backups made manually
|
||||
//
|
||||
$aDetails = array();
|
||||
foreach ($oBackup->ListFiles($sBackupDirManual) as $sBackupFile)
|
||||
{
|
||||
$sFileName = basename($sBackupFile);
|
||||
$sFilePath = 'manual/'.$sFileName;
|
||||
if (MetaModel::GetConfig()->Get('demo_mode'))
|
||||
{
|
||||
$sName = $sFileName;
|
||||
}
|
||||
else
|
||||
{
|
||||
$sAjax = utils::GetAbsoluteUrlModulePage('itop-backup', 'ajax.backup.php', array('operation' => 'download', 'file' => $sFilePath));
|
||||
$sName = "<a href=\"$sAjax\">".$sFileName.'</a>';
|
||||
}
|
||||
$sSize = SetupUtils::HumanReadableSize(filesize($sBackupFile));
|
||||
$sConfirmRestore = addslashes(Dict::Format('bkp-confirm-restore', $sFileName));
|
||||
$sFileEscaped = addslashes($sFilePath);
|
||||
$sRestoreBtn = '<button class="restore" onclick="LaunchRestoreNow(\''.$sFileEscaped.'\', \''.$sConfirmRestore.'\');" '.$sDisableRestore.'>'.Dict::S('bkp-button-restore-now').'</button>';
|
||||
$aDetails[] = array('file' => $sName, 'size' => $sSize, 'actions' => $sRestoreBtn);
|
||||
}
|
||||
$aConfig = array(
|
||||
'file' => array('label' => Dict::S('bkp-table-file'), 'description' => Dict::S('bkp-table-file+')),
|
||||
'size' => array('label' => Dict::S('bkp-table-size'), 'description' => Dict::S('bkp-table-size+')),
|
||||
'actions' => array('label' => Dict::S('bkp-table-actions'), 'description' => Dict::S('bkp-table-actions+')),
|
||||
);
|
||||
$oP->add("<fieldset>");
|
||||
$oP->add("<legend>".Dict::S('bkp-status-backups-manual')."</legend>");
|
||||
if (count($aDetails) > 0)
|
||||
{
|
||||
$oP->add('<div style="max-height:400px; overflow: auto;">');
|
||||
$oP->table($aConfig, array_reverse($aDetails));
|
||||
$oP->add('</div>');
|
||||
}
|
||||
else
|
||||
{
|
||||
$oP->p(Dict::S('bkp-status-backups-none'));
|
||||
}
|
||||
$oP->add("</fieldset>");
|
||||
|
||||
// Ongoing operation ?
|
||||
//
|
||||
$oBackupMutex = new iTopMutex('backup.'.utils::GetCurrentEnvironment());
|
||||
if ($oBackupMutex->TryLock())
|
||||
{
|
||||
$oBackupMutex->Unlock();
|
||||
}
|
||||
else
|
||||
{
|
||||
$oP->p(Dict::S('bkp-backup-running'));
|
||||
}
|
||||
$oRestoreMutex = new iTopMutex('restore.'.utils::GetCurrentEnvironment());
|
||||
if ($oRestoreMutex->TryLock())
|
||||
{
|
||||
$oRestoreMutex->Unlock();
|
||||
}
|
||||
else
|
||||
{
|
||||
$oP->p(Dict::S('bkp-restore-running'));
|
||||
}
|
||||
|
||||
// Do backup now
|
||||
//
|
||||
$oBackupExec = new BackupExec();
|
||||
$oNext = $oBackupExec->GetNextOccurrence();
|
||||
$oP->p(Dict::Format('bkp-next-backup', $aWeekDayToString[$oNext->Format('N')], $oNext->Format('Y-m-d'), $oNext->Format('H:i')));
|
||||
$oP->p('<button onclick="LaunchBackupNow();">'.Dict::S('bkp-button-backup-now').'</button>');
|
||||
$oP->add('<div id="backup_success" class="header_message message_ok" style="display: none;"></div>');
|
||||
$oP->add('<div id="backup_errors" class="header_message message_error" style="display: none;"></div>');
|
||||
$oP->add('<input type="hidden" name="restore_token" id="restore_token"/>');
|
||||
|
||||
$sConfirmBackup = addslashes(Dict::S('bkp-confirm-backup'));
|
||||
$sPleaseWaitBackup = addslashes(Dict::S('bkp-wait-backup'));
|
||||
$sPleaseWaitRestore = addslashes(Dict::S('bkp-wait-restore'));
|
||||
$sRestoreDone = addslashes(Dict::S('bkp-success-restore'));
|
||||
|
||||
$sMySQLBinDir = addslashes(MetaModel::GetConfig()->GetModuleSetting('itop-backup', 'mysql_bindir', ''));
|
||||
$sDBHost = addslashes(MetaModel::GetConfig()->GetDBHost());
|
||||
$sDBUser = addslashes(MetaModel::GetConfig()->GetDBUser());
|
||||
$sDBPwd = addslashes(MetaModel::GetConfig()->GetDBPwd());
|
||||
$sDBName = addslashes(MetaModel::GetConfig()->GetDBName());
|
||||
$sDBSubName = addslashes(MetaModel::GetConfig()->GetDBSubName());
|
||||
|
||||
$sEnvironment = addslashes(utils::GetCurrentEnvironment());
|
||||
|
||||
$oP->add_script(
|
||||
<<<EOF
|
||||
function LaunchBackupNow()
|
||||
{
|
||||
$('#backup_success').hide();
|
||||
$('#backup_errors').hide();
|
||||
|
||||
if (confirm('$sConfirmBackup'))
|
||||
{
|
||||
$.blockUI({ message: '<h1><img src="../images/indicator.gif" /> $sPleaseWaitBackup</h1>' });
|
||||
|
||||
var oParams = {};
|
||||
oParams.operation = 'backup';
|
||||
$.post(GetAbsoluteUrlModulePage('itop-backup', 'ajax.backup.php'), oParams, function(data){
|
||||
if (data.search(/error|exceptio|notice|warning/i) != -1)
|
||||
{
|
||||
$('#backup_errors').html(data);
|
||||
$('#backup_errors').show();
|
||||
}
|
||||
else
|
||||
{
|
||||
window.location.reload();
|
||||
}
|
||||
$.unblockUI();
|
||||
});
|
||||
}
|
||||
}
|
||||
function LaunchRestoreNow(sBackupFile, sConfirmationMessage)
|
||||
{
|
||||
if (confirm(sConfirmationMessage))
|
||||
{
|
||||
$.blockUI({ message: '<h1><img src="../images/indicator.gif" /> $sPleaseWaitRestore</h1>' });
|
||||
|
||||
$('#backup_success').hide();
|
||||
$('#backup_errors').hide();
|
||||
|
||||
var oParams = {};
|
||||
oParams.operation = 'restore_get_token';
|
||||
oParams.file = sBackupFile;
|
||||
$.post(GetAbsoluteUrlModulePage('itop-backup', 'ajax.backup.php'), oParams, function(data){
|
||||
|
||||
// Get the value of restore_token
|
||||
$('#backup_errors').append(data);
|
||||
|
||||
var oParams = {};
|
||||
oParams.operation = 'restore_exec';
|
||||
oParams.token = $("#restore_token").val();
|
||||
oParams.mysql_bindir = '$sMySQLBinDir';
|
||||
oParams.db_host = '$sDBHost';
|
||||
oParams.db_user = '$sDBUser';
|
||||
oParams.db_pwd = '$sDBPwd';
|
||||
oParams.db_name = '$sDBName';
|
||||
oParams.db_subname = '$sDBSubName';
|
||||
oParams.environment = '$sEnvironment';
|
||||
if (oParams.token.length > 0)
|
||||
{
|
||||
$.post(GetAbsoluteUrlModulePage('itop-backup', 'ajax.backup.php'), oParams, function(data){
|
||||
if (data.search(/error|exceptio|notice|warning/i) != -1)
|
||||
{
|
||||
$('#backup_success').hide();
|
||||
$('#backup_errors').html(data);
|
||||
$('#backup_errors').show();
|
||||
}
|
||||
else
|
||||
{
|
||||
$('#backup_errors').hide();
|
||||
$('#backup_success').html('$sRestoreDone');
|
||||
$('#backup_success').show();
|
||||
}
|
||||
$.unblockUI();
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
$('button.restore').attr('disabled', 'disabled');
|
||||
$.unblockUI();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
EOF
|
||||
);
|
||||
|
||||
if (MetaModel::GetConfig()->Get('demo_mode'))
|
||||
{
|
||||
$oP->add_ready_script("$('button').attr('disabled', 'disabled').attr('title', 'Disabled in demonstration mode')");
|
||||
}
|
||||
}
|
||||
catch(Exception $e)
|
||||
{
|
||||
$oP->p('<b>'.$e->getMessage().'</b>');
|
||||
}
|
||||
|
||||
$oP->output();
|
||||
?>
|
||||
@@ -1,9 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0">
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.1">
|
||||
<classes>
|
||||
<class id="lnkVirtualDeviceToVolume" _delta="define">
|
||||
<parent>cmdbAbstractObject</parent>
|
||||
<properties>
|
||||
<is_link>1</is_link>
|
||||
<category>bizmodel,configmgmt</category>
|
||||
<abstract>false</abstract>
|
||||
<key_type>autoincrement</key_type>
|
||||
@@ -91,4 +92,4 @@
|
||||
</presentation>
|
||||
</class>
|
||||
</classes>
|
||||
</itop_design>
|
||||
</itop_design>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-bridge-virtualization-storage/2.0.0',
|
||||
'itop-bridge-virtualization-storage/2.1.0',
|
||||
array(
|
||||
// Identification
|
||||
//
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -3,7 +3,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-change-mgmt-itil/2.0.0',
|
||||
'itop-change-mgmt-itil/2.1.0',
|
||||
array(
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0">
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.1">
|
||||
<classes>
|
||||
<class id="Change" _delta="define">
|
||||
<parent>Ticket</parent>
|
||||
@@ -38,12 +38,12 @@
|
||||
<fields>
|
||||
<field id="status" xsi:type="AttributeEnum">
|
||||
<values>
|
||||
<value>new</value>
|
||||
<value>assigned</value>
|
||||
<value>planned</value>
|
||||
<value>approved</value>
|
||||
<value>closed</value>
|
||||
<value>rejected</value>
|
||||
<value id="new">new</value>
|
||||
<value id="assigned">assigned</value>
|
||||
<value id="planned">planned</value>
|
||||
<value id="approved">approved</value>
|
||||
<value id="closed">closed</value>
|
||||
<value id="rejected">rejected</value>
|
||||
</values>
|
||||
<sql>status</sql>
|
||||
<default_value>new</default_value>
|
||||
@@ -51,12 +51,12 @@
|
||||
</field>
|
||||
<field id="category" xsi:type="AttributeEnum">
|
||||
<values>
|
||||
<value>hardware</value>
|
||||
<value>software</value>
|
||||
<value>system</value>
|
||||
<value>network</value>
|
||||
<value>application</value>
|
||||
<value>other</value>
|
||||
<value id="hardware">hardware</value>
|
||||
<value id="software">software</value>
|
||||
<value id="system">system</value>
|
||||
<value id="network">network</value>
|
||||
<value id="application">application</value>
|
||||
<value id="other">other</value>
|
||||
</values>
|
||||
<sql>category</sql>
|
||||
<default_value>hardware</default_value>
|
||||
@@ -107,8 +107,8 @@
|
||||
</field>
|
||||
<field id="outage" xsi:type="AttributeEnum">
|
||||
<values>
|
||||
<value>yes</value>
|
||||
<value>no</value>
|
||||
<value id="yes">yes</value>
|
||||
<value id="no">no</value>
|
||||
</values>
|
||||
<sql>outage</sql>
|
||||
<default_value>no</default_value>
|
||||
@@ -145,6 +145,23 @@
|
||||
</field>
|
||||
</fields>
|
||||
<lifecycle>
|
||||
<highlight_scale>
|
||||
<item id="approved">
|
||||
<rank>1</rank>
|
||||
<color>HIGHLIGHT_CLASS_NONE</color>
|
||||
<icon>images/change-approved.png</icon>
|
||||
</item>
|
||||
<item id="rejected">
|
||||
<rank>2</rank>
|
||||
<color>HIGHLIGHT_CLASS_NONE</color>
|
||||
<icon>images/change-rejected.png</icon>
|
||||
</item>
|
||||
<item id="closed">
|
||||
<rank>3</rank>
|
||||
<color>HIGHLIGHT_CLASS_NONE</color>
|
||||
<icon>images/change-closed.png</icon>
|
||||
</item>
|
||||
</highlight_scale>
|
||||
<attribute>status</attribute>
|
||||
<stimuli>
|
||||
<stimulus id="ev_assign" xsi:type="StimulusUserAction"/>
|
||||
@@ -201,21 +218,15 @@
|
||||
</attribute>
|
||||
</flags>
|
||||
<transitions>
|
||||
<transition>
|
||||
<stimulus>ev_assign</stimulus>
|
||||
<transition id="ev_assign">
|
||||
<target>assigned</target>
|
||||
<actions/>
|
||||
</transition>
|
||||
</transitions>
|
||||
</state>
|
||||
<state id="assigned">
|
||||
<inherit_flags_from>new</inherit_flags_from>
|
||||
<flags>
|
||||
<attribute id="ref">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="org_id">
|
||||
<mandatory/>
|
||||
</attribute>
|
||||
<attribute id="team_id">
|
||||
<mandatory/>
|
||||
<must_prompt/>
|
||||
@@ -224,57 +235,22 @@
|
||||
<mandatory/>
|
||||
<must_prompt/>
|
||||
</attribute>
|
||||
<attribute id="title">
|
||||
<mandatory/>
|
||||
</attribute>
|
||||
<attribute id="description">
|
||||
<mandatory/>
|
||||
</attribute>
|
||||
<attribute id="last_update">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="close_date">
|
||||
<hidden/>
|
||||
</attribute>
|
||||
<attribute id="reject_reason">
|
||||
<hidden/>
|
||||
</attribute>
|
||||
<attribute id="changemanager_id">
|
||||
<mandatory/>
|
||||
<must_prompt/>
|
||||
</attribute>
|
||||
<attribute id="creation_date">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="approval_date">
|
||||
<hidden/>
|
||||
</attribute>
|
||||
<attribute id="outage">
|
||||
<hidden/>
|
||||
</attribute>
|
||||
<attribute id="caller_id"/>
|
||||
</flags>
|
||||
<transitions>
|
||||
<transition>
|
||||
<stimulus>ev_plan</stimulus>
|
||||
<transition id="ev_plan">
|
||||
<target>planned</target>
|
||||
<actions/>
|
||||
</transition>
|
||||
</transitions>
|
||||
</state>
|
||||
<state id="planned">
|
||||
<inherit_flags_from>assigned</inherit_flags_from>
|
||||
<flags>
|
||||
<attribute id="ref">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="org_id">
|
||||
<mandatory/>
|
||||
</attribute>
|
||||
<attribute id="title">
|
||||
<mandatory/>
|
||||
</attribute>
|
||||
<attribute id="description">
|
||||
<mandatory/>
|
||||
</attribute>
|
||||
<attribute id="start_date">
|
||||
<mandatory/>
|
||||
<must_prompt/>
|
||||
@@ -283,21 +259,6 @@
|
||||
<mandatory/>
|
||||
<must_prompt/>
|
||||
</attribute>
|
||||
<attribute id="last_update">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="close_date">
|
||||
<hidden/>
|
||||
</attribute>
|
||||
<attribute id="reject_reason">
|
||||
<hidden/>
|
||||
</attribute>
|
||||
<attribute id="creation_date">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="approval_date">
|
||||
<hidden/>
|
||||
</attribute>
|
||||
<attribute id="fallback_plan">
|
||||
<mandatory/>
|
||||
<must_prompt/>
|
||||
@@ -305,28 +266,17 @@
|
||||
<attribute id="caller_id">
|
||||
<mandatory/>
|
||||
</attribute>
|
||||
<attribute id="team_id">
|
||||
<mandatory/>
|
||||
</attribute>
|
||||
<attribute id="agent_id">
|
||||
<mandatory/>
|
||||
</attribute>
|
||||
<attribute id="changemanager_id">
|
||||
<mandatory/>
|
||||
</attribute>
|
||||
<attribute id="outage">
|
||||
<mandatory/>
|
||||
<must_prompt/>
|
||||
</attribute>
|
||||
</flags>
|
||||
<transitions>
|
||||
<transition>
|
||||
<stimulus>ev_reject</stimulus>
|
||||
<transition id="ev_reject">
|
||||
<target>rejected</target>
|
||||
<actions/>
|
||||
</transition>
|
||||
<transition>
|
||||
<stimulus>ev_approve</stimulus>
|
||||
<transition id="ev_approve">
|
||||
<target>approved</target>
|
||||
<actions>
|
||||
<action>
|
||||
@@ -340,8 +290,31 @@
|
||||
</transitions>
|
||||
</state>
|
||||
<state id="rejected">
|
||||
<highlight>
|
||||
<code>rejected</code>
|
||||
</highlight>
|
||||
<inherit_flags_from>assigned</inherit_flags_from>
|
||||
<flags>
|
||||
<attribute id="ref">
|
||||
<attribute id="start_date">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="end_date">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="private_log">
|
||||
<read_only/>
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="caller_id">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="fallback_plan">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="category">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="parent_id">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="org_id">
|
||||
@@ -353,34 +326,13 @@
|
||||
<attribute id="description">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="last_update">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="close_date">
|
||||
<hidden/>
|
||||
</attribute>
|
||||
<attribute id="start_date">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="end_date">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="private_log">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="reject_reason">
|
||||
<mandatory/>
|
||||
<must_prompt/>
|
||||
</attribute>
|
||||
<attribute id="creation_date">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="approval_date">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="caller_id">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="team_id">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
@@ -390,35 +342,26 @@
|
||||
<attribute id="changemanager_id">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="private_log">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="fallback_plan">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="category">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="parent_id">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="outage">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
</flags>
|
||||
<transitions>
|
||||
<transition>
|
||||
<stimulus>ev_reopen</stimulus>
|
||||
<transition id="ev_reopen">
|
||||
<target>assigned</target>
|
||||
<actions/>
|
||||
</transition>
|
||||
</transitions>
|
||||
</state>
|
||||
<state id="approved">
|
||||
<highlight>
|
||||
<code>approved</code>
|
||||
</highlight>
|
||||
<inherit_flags_from>planned</inherit_flags_from>
|
||||
<flags>
|
||||
<attribute id="ref">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="private_log"/>
|
||||
<attribute id="category"/>
|
||||
<attribute id="parent_id"/>
|
||||
<attribute id="org_id">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
@@ -428,21 +371,12 @@
|
||||
<attribute id="description">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="last_update">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="close_date">
|
||||
<hidden/>
|
||||
</attribute>
|
||||
<attribute id="start_date">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="end_date">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="private_log">
|
||||
<normal/>
|
||||
</attribute>
|
||||
<attribute id="reject_reason">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
@@ -464,22 +398,13 @@
|
||||
<attribute id="changemanager_id">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="fallback_plan">
|
||||
<normal/>
|
||||
</attribute>
|
||||
<attribute id="category">
|
||||
<normal/>
|
||||
</attribute>
|
||||
<attribute id="parent_id">
|
||||
<normal/>
|
||||
</attribute>
|
||||
<attribute id="fallback_plan"/>
|
||||
<attribute id="outage">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
</flags>
|
||||
<transitions>
|
||||
<transition>
|
||||
<stimulus>ev_finish</stimulus>
|
||||
<transition id="ev_finish">
|
||||
<target>closed</target>
|
||||
<actions>
|
||||
<action>
|
||||
@@ -490,52 +415,17 @@
|
||||
</transitions>
|
||||
</state>
|
||||
<state id="closed">
|
||||
<highlight>
|
||||
<code>closed</code>
|
||||
</highlight>
|
||||
<inherit_flags_from>approved</inherit_flags_from>
|
||||
<flags>
|
||||
<attribute id="ref">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="org_id">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="title">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="description">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="last_update">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="close_date">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="start_date">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="end_date">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="reject_reason">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="creation_date">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="approval_date">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="caller_id">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="team_id">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="agent_id">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="changemanager_id">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="private_log">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
@@ -548,9 +438,6 @@
|
||||
<attribute id="parent_id">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="outage">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
</flags>
|
||||
<transitions/>
|
||||
</state>
|
||||
@@ -633,63 +520,6 @@
|
||||
$this->Set('last_update', time());
|
||||
}]]></code>
|
||||
</method>
|
||||
<method id="GetIcon">
|
||||
<comment>/**
|
||||
* Get the icon representing this object
|
||||
* @param boolean $bImgTag If true the result is a full IMG tag (or an emtpy string if no icon is defined)
|
||||
* @return string Either the full IMG tag ($bImgTag == true) or just the path to the icon file
|
||||
*/</comment>
|
||||
<static>false</static>
|
||||
<access>public</access>
|
||||
<type>Overload-DBObject</type>
|
||||
<code><![CDATA[ public function GetIcon($bImgTag = true)
|
||||
{
|
||||
$sStatus = $this->Get('status');
|
||||
switch($this->GetState())
|
||||
{
|
||||
case 'approved':
|
||||
case 'implemented':
|
||||
case 'monitored':
|
||||
$sIcon = self::MakeIconFromName('change-approved.png');
|
||||
break;
|
||||
|
||||
case 'rejected':
|
||||
case 'notapproved':
|
||||
$sIcon = self::MakeIconFromName('change-rejected.png');
|
||||
break;
|
||||
|
||||
case 'closed':
|
||||
$sIcon = self::MakeIconFromName('change-closed.png');
|
||||
break;
|
||||
|
||||
default:
|
||||
$sIcon = MetaModel::GetClassIcon(get_class($this), $bImgTag);
|
||||
}
|
||||
return $sIcon;
|
||||
}]]></code>
|
||||
</method>
|
||||
<method id="MakeIconFromName">
|
||||
<static>true</static>
|
||||
<access>protected</access>
|
||||
<type>Overload-DBObject</type>
|
||||
<code><![CDATA[ protected static function MakeIconFromName($sIconName, $bImgTag = true)
|
||||
{
|
||||
$sIcon = '';
|
||||
if ($sIconName != '')
|
||||
{
|
||||
$sPath = '../env-'.utils::GetCurrentEnvironment().'/itop-change-mgmt/images/'.$sIconName;
|
||||
if ($bImgTag)
|
||||
{
|
||||
$sIcon = "<img src=\"$sPath\" style=\"vertical-align:middle;\"/>";
|
||||
}
|
||||
else
|
||||
{
|
||||
$sIcon = $sPath;
|
||||
}
|
||||
}
|
||||
return $sIcon;
|
||||
}]]></code>
|
||||
</method>
|
||||
</methods>
|
||||
<presentation>
|
||||
<details>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-change-mgmt/2.0.0',
|
||||
'itop-change-mgmt/2.1.0',
|
||||
array(
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0">
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.1">
|
||||
<classes>
|
||||
<class id="Organization" _delta="define">
|
||||
<parent>cmdbAbstractObject</parent>
|
||||
@@ -44,8 +44,8 @@
|
||||
</field>
|
||||
<field id="status" xsi:type="AttributeEnum">
|
||||
<values>
|
||||
<value>active</value>
|
||||
<value>inactive</value>
|
||||
<value id="active">active</value>
|
||||
<value id="inactive">inactive</value>
|
||||
</values>
|
||||
<sql>status</sql>
|
||||
<default_value>active</default_value>
|
||||
@@ -144,8 +144,8 @@
|
||||
</field>
|
||||
<field id="status" xsi:type="AttributeEnum">
|
||||
<values>
|
||||
<value>active</value>
|
||||
<value>inactive</value>
|
||||
<value id="active">active</value>
|
||||
<value id="inactive">inactive</value>
|
||||
</values>
|
||||
<sql>status</sql>
|
||||
<default_value>active</default_value>
|
||||
@@ -307,8 +307,8 @@
|
||||
</field>
|
||||
<field id="status" xsi:type="AttributeEnum">
|
||||
<values>
|
||||
<value>active</value>
|
||||
<value>inactive</value>
|
||||
<value id="active">active</value>
|
||||
<value id="inactive">inactive</value>
|
||||
</values>
|
||||
<sql>status</sql>
|
||||
<default_value>active</default_value>
|
||||
@@ -337,8 +337,8 @@
|
||||
</field>
|
||||
<field id="notify" xsi:type="AttributeEnum">
|
||||
<values>
|
||||
<value>yes</value>
|
||||
<value>no</value>
|
||||
<value id="yes">yes</value>
|
||||
<value id="no">no</value>
|
||||
</values>
|
||||
<sql>notify</sql>
|
||||
<default_value>yes</default_value>
|
||||
@@ -486,7 +486,7 @@
|
||||
<target_class>Location</target_class>
|
||||
<is_null_allowed>true</is_null_allowed>
|
||||
<on_target_delete>DEL_MANUAL</on_target_delete>
|
||||
<allow_target_creation>false</allow_target_creation>
|
||||
<allow_target_creation>false</allow_target_creation>
|
||||
</field>
|
||||
<field id="location_name" xsi:type="AttributeExternalField">
|
||||
<extkey_attcode>location_id</extkey_attcode>
|
||||
@@ -835,9 +835,9 @@
|
||||
</field>
|
||||
<field id="status" xsi:type="AttributeEnum">
|
||||
<values>
|
||||
<value>draft</value>
|
||||
<value>published</value>
|
||||
<value>obsolete</value>
|
||||
<value id="draft">draft</value>
|
||||
<value id="published">published</value>
|
||||
<value id="obsolete">obsolete</value>
|
||||
</values>
|
||||
<sql>status</sql>
|
||||
<default_value/>
|
||||
@@ -972,7 +972,7 @@
|
||||
<static>false</static>
|
||||
<access>public</access>
|
||||
<type>Overload-cmdbAbstractObject</type>
|
||||
<comment><![CDATA[/**
|
||||
<comment><![CDATA[/**
|
||||
* Overload the display of the properties to add a tab (the first one)
|
||||
* with the preview of the document
|
||||
*/
|
||||
@@ -1320,9 +1320,9 @@
|
||||
</field>
|
||||
<field id="business_criticity" xsi:type="AttributeEnum">
|
||||
<values>
|
||||
<value>high</value>
|
||||
<value>medium</value>
|
||||
<value>low</value>
|
||||
<value id="high">high</value>
|
||||
<value id="medium">medium</value>
|
||||
<value id="low">low</value>
|
||||
</values>
|
||||
<sql>business_criticity</sql>
|
||||
<default_value>low</default_value>
|
||||
@@ -1526,7 +1526,7 @@
|
||||
<target_class>Location</target_class>
|
||||
<is_null_allowed>true</is_null_allowed>
|
||||
<on_target_delete>DEL_MANUAL</on_target_delete>
|
||||
<allow_target_creation>false</allow_target_creation>
|
||||
<allow_target_creation>false</allow_target_creation>
|
||||
</field>
|
||||
<field id="location_name" xsi:type="AttributeExternalField">
|
||||
<extkey_attcode>location_id</extkey_attcode>
|
||||
@@ -1534,10 +1534,10 @@
|
||||
</field>
|
||||
<field id="status" xsi:type="AttributeEnum">
|
||||
<values>
|
||||
<value>production</value>
|
||||
<value>implementation</value>
|
||||
<value>stock</value>
|
||||
<value>obsolete</value>
|
||||
<value id="production">production</value>
|
||||
<value id="implementation">implementation</value>
|
||||
<value id="stock">stock</value>
|
||||
<value id="obsolete">obsolete</value>
|
||||
</values>
|
||||
<sql>status</sql>
|
||||
<default_value>production</default_value>
|
||||
@@ -1708,8 +1708,6 @@
|
||||
</list>
|
||||
</presentation>
|
||||
</class>
|
||||
|
||||
|
||||
<class id="ConnectableCI" _delta="define">
|
||||
<parent>PhysicalDevice</parent>
|
||||
<properties>
|
||||
@@ -1940,7 +1938,7 @@
|
||||
<target_class>Rack</target_class>
|
||||
<is_null_allowed>true</is_null_allowed>
|
||||
<on_target_delete>DEL_MANUAL</on_target_delete>
|
||||
<allow_target_creation>false</allow_target_creation>
|
||||
<allow_target_creation>false</allow_target_creation>
|
||||
</field>
|
||||
<field id="rack_name" xsi:type="AttributeExternalField">
|
||||
<extkey_attcode>rack_id</extkey_attcode>
|
||||
@@ -1955,7 +1953,7 @@
|
||||
<target_class>Enclosure</target_class>
|
||||
<is_null_allowed>true</is_null_allowed>
|
||||
<on_target_delete>DEL_MANUAL</on_target_delete>
|
||||
<allow_target_creation>false</allow_target_creation>
|
||||
<allow_target_creation>false</allow_target_creation>
|
||||
</field>
|
||||
<field id="enclosure_name" xsi:type="AttributeExternalField">
|
||||
<extkey_attcode>enclosure_id</extkey_attcode>
|
||||
@@ -1980,7 +1978,7 @@
|
||||
<target_class>PowerConnection</target_class>
|
||||
<is_null_allowed>true</is_null_allowed>
|
||||
<on_target_delete>DEL_MANUAL</on_target_delete>
|
||||
<allow_target_creation>false</allow_target_creation>
|
||||
<allow_target_creation>false</allow_target_creation>
|
||||
</field>
|
||||
<field id="powerA_name" xsi:type="AttributeExternalField">
|
||||
<extkey_attcode>powerA_id</extkey_attcode>
|
||||
@@ -1995,7 +1993,7 @@
|
||||
<target_class>PowerConnection</target_class>
|
||||
<is_null_allowed>true</is_null_allowed>
|
||||
<on_target_delete>DEL_MANUAL</on_target_delete>
|
||||
<allow_target_creation>false</allow_target_creation>
|
||||
<allow_target_creation>false</allow_target_creation>
|
||||
</field>
|
||||
<field id="powerB_name" xsi:type="AttributeExternalField">
|
||||
<extkey_attcode>powerB_id</extkey_attcode>
|
||||
@@ -2835,8 +2833,6 @@
|
||||
</list>
|
||||
</presentation>
|
||||
</class>
|
||||
|
||||
|
||||
<class id="ApplicationSolution" _delta="define">
|
||||
<parent>FunctionalCI</parent>
|
||||
<properties>
|
||||
@@ -2881,8 +2877,8 @@
|
||||
</field>
|
||||
<field id="status" xsi:type="AttributeEnum">
|
||||
<values>
|
||||
<value>active</value>
|
||||
<value>inactive</value>
|
||||
<value id="active">active</value>
|
||||
<value id="inactive">inactive</value>
|
||||
</values>
|
||||
<sql>status</sql>
|
||||
<default_value>active</default_value>
|
||||
@@ -3030,8 +3026,8 @@
|
||||
</field>
|
||||
<field id="status" xsi:type="AttributeEnum">
|
||||
<values>
|
||||
<value>active</value>
|
||||
<value>inactive</value>
|
||||
<value id="active">active</value>
|
||||
<value id="inactive">inactive</value>
|
||||
</values>
|
||||
<sql>status</sql>
|
||||
<default_value>active</default_value>
|
||||
@@ -3163,7 +3159,7 @@
|
||||
<target_class>FunctionalCI</target_class>
|
||||
<is_null_allowed>false</is_null_allowed>
|
||||
<on_target_delete>DEL_AUTO</on_target_delete>
|
||||
<allow_target_creation>false</allow_target_creation>
|
||||
<allow_target_creation>false</allow_target_creation>
|
||||
</field>
|
||||
<field id="system_name" xsi:type="AttributeExternalField">
|
||||
<extkey_attcode>system_id</extkey_attcode>
|
||||
@@ -3189,7 +3185,7 @@
|
||||
<target_class>SoftwareLicence</target_class>
|
||||
<is_null_allowed>true</is_null_allowed>
|
||||
<on_target_delete>DEL_MANUAL</on_target_delete>
|
||||
<allow_target_creation>false</allow_target_creation>
|
||||
<allow_target_creation>false</allow_target_creation>
|
||||
</field>
|
||||
<field id="softwarelicence_name" xsi:type="AttributeExternalField">
|
||||
<extkey_attcode>softwarelicence_id</extkey_attcode>
|
||||
@@ -3202,8 +3198,8 @@
|
||||
</field>
|
||||
<field id="status" xsi:type="AttributeEnum">
|
||||
<values>
|
||||
<value>active</value>
|
||||
<value>inactive</value>
|
||||
<value id="active">active</value>
|
||||
<value id="inactive">inactive</value>
|
||||
</values>
|
||||
<sql>status</sql>
|
||||
<default_value/>
|
||||
@@ -4501,11 +4497,11 @@
|
||||
</field>
|
||||
<field id="type" xsi:type="AttributeEnum">
|
||||
<values>
|
||||
<value>Middleware</value>
|
||||
<value>DBServer</value>
|
||||
<value>PCSoftware</value>
|
||||
<value>OtherSoftware</value>
|
||||
<value>WebServer</value>
|
||||
<value id="Middleware">Middleware</value>
|
||||
<value id="DBServer">DBServer</value>
|
||||
<value id="PCSoftware">PCSoftware</value>
|
||||
<value id="OtherSoftware">OtherSoftware</value>
|
||||
<value id="WebServer">WebServer</value>
|
||||
</values>
|
||||
<sql>type</sql>
|
||||
<default_value/>
|
||||
@@ -4926,8 +4922,8 @@
|
||||
</field>
|
||||
<field id="perpetual" xsi:type="AttributeEnum">
|
||||
<values>
|
||||
<value>yes</value>
|
||||
<value>no</value>
|
||||
<value id="yes">yes</value>
|
||||
<value id="no">no</value>
|
||||
</values>
|
||||
<sql>perpetual</sql>
|
||||
<default_value>no</default_value>
|
||||
@@ -5736,24 +5732,24 @@
|
||||
</field>
|
||||
<field id="type" xsi:type="AttributeEnum">
|
||||
<values>
|
||||
<value>NetworkDevice</value>
|
||||
<value>Server</value>
|
||||
<value>SANSwitch</value>
|
||||
<value>StorageSystem</value>
|
||||
<value>Rack</value>
|
||||
<value>Enclosure</value>
|
||||
<value>PC</value>
|
||||
<value>Tablet</value>
|
||||
<value>Telephone</value>
|
||||
<value>MobilePhone</value>
|
||||
<value>Printer</value>
|
||||
<value>DiskArray</value>
|
||||
<value>NAS</value>
|
||||
<value>TapeLibrary</value>
|
||||
<value>IPPhone</value>
|
||||
<value>Peripheral</value>
|
||||
<value>PowerSource</value>
|
||||
<value>PDU</value>
|
||||
<value id="NetworkDevice">NetworkDevice</value>
|
||||
<value id="Server">Server</value>
|
||||
<value id="SANSwitch">SANSwitch</value>
|
||||
<value id="StorageSystem">StorageSystem</value>
|
||||
<value id="Rack">Rack</value>
|
||||
<value id="Enclosure">Enclosure</value>
|
||||
<value id="PC">PC</value>
|
||||
<value id="Tablet">Tablet</value>
|
||||
<value id="Telephone">Telephone</value>
|
||||
<value id="MobilePhone">MobilePhone</value>
|
||||
<value id="Printer">Printer</value>
|
||||
<value id="DiskArray">DiskArray</value>
|
||||
<value id="NAS">NAS</value>
|
||||
<value id="TapeLibrary">TapeLibrary</value>
|
||||
<value id="IPPhone">IPPhone</value>
|
||||
<value id="Peripheral">Peripheral</value>
|
||||
<value id="PowerSource">PowerSource</value>
|
||||
<value id="PDU">PDU</value>
|
||||
</values>
|
||||
<sql>type</sql>
|
||||
<default_value/>
|
||||
@@ -6817,8 +6813,6 @@
|
||||
</list>
|
||||
</presentation>
|
||||
</class>
|
||||
|
||||
|
||||
<class id="NetworkInterface" _delta="define">
|
||||
<parent>cmdbAbstractObject</parent>
|
||||
<properties>
|
||||
@@ -6874,7 +6868,6 @@
|
||||
</list>
|
||||
</presentation>
|
||||
</class>
|
||||
|
||||
<class id="IPInterface" _delta="define">
|
||||
<parent>NetworkInterface</parent>
|
||||
<properties>
|
||||
@@ -7214,7 +7207,6 @@
|
||||
</list>
|
||||
</presentation>
|
||||
</class>
|
||||
|
||||
<class id="lnkConnectableCIToNetworkDevice" _delta="define">
|
||||
<parent>cmdbAbstractObject</parent>
|
||||
<properties>
|
||||
@@ -7274,8 +7266,8 @@
|
||||
</field>
|
||||
<field id="connection_type" xsi:type="AttributeEnum">
|
||||
<values>
|
||||
<value>uplink</value>
|
||||
<value>downlink</value>
|
||||
<value id="uplink">uplink</value>
|
||||
<value id="downlink">downlink</value>
|
||||
</values>
|
||||
<sql>type</sql>
|
||||
<default_value>downlink</default_value>
|
||||
@@ -7290,13 +7282,11 @@
|
||||
<type>Overload-cmdbAbstractObject</type>
|
||||
<code><![CDATA[ protected function AddConnectedNetworkDevice()
|
||||
{
|
||||
$iNetworkDeviceID = $this->Get('networkdevice_id');
|
||||
$iDeviceID = $this->Get('connectableci_id');
|
||||
$oDevice = MetaModel::GetObject('ConnectableCI', $this->Get('connectableci_id'));
|
||||
|
||||
$sOQL = "SELECT lnkConnectableCIToNetworkDevice WHERE connectableci_id = :device AND networkdevice_id = :network AND network_port = :nwport AND device_port = :devport";
|
||||
|
||||
$oConnectionSet = new DBObjectSet(DBObjectSearch::FromOQL($sOQL),
|
||||
if (is_object($oDevice) && (get_class($oDevice) == 'NetworkDevice'))
|
||||
{
|
||||
$sOQL = "SELECT lnkConnectableCIToNetworkDevice WHERE connectableci_id = :device AND networkdevice_id = :network AND network_port = :nwport AND device_port = :devport";
|
||||
$oConnectionSet = new DBObjectSet(DBObjectSearch::FromOQL($sOQL),
|
||||
array(),
|
||||
array(
|
||||
'network' => $this->Get('connectableci_id'),
|
||||
@@ -7304,36 +7294,21 @@
|
||||
'devport' => $this->Get('network_port'),
|
||||
'nwport' => $this->Get('device_port'),
|
||||
)
|
||||
);
|
||||
$iAlreadyExist = $oConnectionSet->count();
|
||||
if ((get_class($oDevice) == 'NetworkDevice') && ($iAlreadyExist == 0))
|
||||
{
|
||||
$sLink = $this->Get('connection_type');
|
||||
$sConnLink = ($sLink == 'uplink') ? 'downlink' : 'uplink';
|
||||
|
||||
$oNewLink = new lnkConnectableCIToNetworkDevice();
|
||||
$oNewLink->Set('networkdevice_id', $this->Get('connectableci_id'));
|
||||
$oNewLink->Set('connectableci_id', $this->Get('networkdevice_id'));
|
||||
$oNewLink->Set('network_port', $this->Get('device_port'));
|
||||
$oNewLink->Set('device_port', $this->Get('network_port'));
|
||||
$oNewLink->Set('connection_type', $sConnLink);
|
||||
|
||||
$oMyChange = MetaModel::NewObject("CMDBChange");
|
||||
$oMyChange->Set("date", time());
|
||||
if (UserRights::IsImpersonated())
|
||||
);
|
||||
if ($oConnectionSet->Count() == 0)
|
||||
{
|
||||
$sUserString = Dict::Format('UI:Archive_User_OnBehalfOf_User', UserRights::GetRealUser(), UserRights::GetUser());
|
||||
}
|
||||
else
|
||||
{
|
||||
$sUserString = UserRights::GetUser();
|
||||
}
|
||||
$oMyChange->Set("userinfo", $sUserString);
|
||||
$iChangeId = $oMyChange->DBInsert();
|
||||
$oNewLink->DBInsertTracked($oMyChange);
|
||||
$sLink = $this->Get('connection_type');
|
||||
$sConnLink = ($sLink == 'uplink') ? 'downlink' : 'uplink';
|
||||
|
||||
$oNewLink = new lnkConnectableCIToNetworkDevice();
|
||||
$oNewLink->Set('networkdevice_id', $this->Get('connectableci_id'));
|
||||
$oNewLink->Set('connectableci_id', $this->Get('networkdevice_id'));
|
||||
$oNewLink->Set('network_port', $this->Get('device_port'));
|
||||
$oNewLink->Set('device_port', $this->Get('network_port'));
|
||||
$oNewLink->Set('connection_type', $sConnLink);
|
||||
$oNewLink->DBInsert();
|
||||
}
|
||||
}
|
||||
|
||||
}]]></code>
|
||||
</method>
|
||||
<method id="UpdateConnectedNetworkDevice">
|
||||
@@ -7342,45 +7317,32 @@
|
||||
<type>Overload-cmdbAbstractObject</type>
|
||||
<code><![CDATA[ protected function UpdateConnectedNetworkDevice()
|
||||
{
|
||||
$iNetworkDeviceID = $this->Get('networkdevice_id');
|
||||
$iDeviceID = $this->Get('connectableci_id');
|
||||
$oDevice = MetaModel::GetObject('ConnectableCI', $this->Get('connectableci_id'));
|
||||
|
||||
$sOQL = "SELECT lnkConnectableCIToNetworkDevice WHERE connectableci_id = :device AND networkdevice_id = :network AND network_port = :nwport AND device_port = :devport";
|
||||
$oConnectionSet = new DBObjectSet(DBObjectSearch::FromOQL($sOQL),
|
||||
if (is_object($oDevice) && (get_class($oDevice) == 'NetworkDevice'))
|
||||
{
|
||||
// Note: in case a port has been changed, search with the original values
|
||||
$sOQL = "SELECT lnkConnectableCIToNetworkDevice WHERE connectableci_id = :device AND networkdevice_id = :network AND network_port = :nwport AND device_port = :devport";
|
||||
$oConnectionSet = new DBObjectSet(DBObjectSearch::FromOQL($sOQL),
|
||||
array(),
|
||||
array(
|
||||
'network' => $this->Get('connectableci_id'),
|
||||
'device' => $this->Get('networkdevice_id'),
|
||||
'devport' => $this->Get('network_port'),
|
||||
'nwport' => $this->Get('device_port'),
|
||||
'devport' => $this->GetOriginal('network_port'),
|
||||
'nwport' => $this->GetOriginal('device_port'),
|
||||
)
|
||||
);
|
||||
$iAlreadyExist = $oConnectionSet->count();
|
||||
if ((get_class($oDevice) == 'NetworkDevice') && ($iAlreadyExist != 0))
|
||||
{
|
||||
|
||||
);
|
||||
$sLink = $this->Get('connection_type');
|
||||
$sConnLink = ($sLink == 'uplink') ? 'downlink' : 'uplink';
|
||||
|
||||
$oMyChange = MetaModel::NewObject("CMDBChange");
|
||||
$oMyChange->Set("date", time());
|
||||
if (UserRights::IsImpersonated())
|
||||
// There should be one link - do it in a safe manner anyway
|
||||
while ($oConnection = $oConnectionSet->Fetch())
|
||||
{
|
||||
$sUserString = Dict::Format('UI:Archive_User_OnBehalfOf_User', UserRights::GetRealUser(), UserRights::GetUser());
|
||||
$oConnection->Set('connection_type', $sConnLink);
|
||||
$oConnection->Set('network_port', $this->Get('device_port'));
|
||||
$oConnection->Set('device_port', $this->Get('network_port'));
|
||||
$oConnection->DBUpdate();
|
||||
}
|
||||
else
|
||||
{
|
||||
$sUserString = UserRights::GetUser();
|
||||
}
|
||||
$oMyChange->Set("userinfo", $sUserString);
|
||||
$iChangeId = $oMyChange->DBInsert();
|
||||
$oConnection = $oConnectionSet->Fetch();
|
||||
$oConnection->Set('connection_type', $sConnLink);
|
||||
$oConnection->DBUpdateTracked($oMyChange);
|
||||
|
||||
}
|
||||
|
||||
}]]></code>
|
||||
</method>
|
||||
<method id="DeleteConnectedNetworkDevice">
|
||||
@@ -7389,13 +7351,13 @@
|
||||
<type>Overload-cmdbAbstractObject</type>
|
||||
<code><![CDATA[ protected function DeleteConnectedNetworkDevice()
|
||||
{
|
||||
$iNetworkDeviceID = $this->Get('networkdevice_id');
|
||||
$iDeviceID = $this->Get('connectableci_id');
|
||||
|
||||
$oDevice = MetaModel::GetObject('ConnectableCI', $this->Get('connectableci_id'));
|
||||
|
||||
$sOQL = "SELECT lnkConnectableCIToNetworkDevice WHERE connectableci_id = :device AND networkdevice_id = :network AND network_port = :nwport AND device_port = :devport";
|
||||
$oConnectionSet = new DBObjectSet(DBObjectSearch::FromOQL($sOQL),
|
||||
// The device might be already deleted (reentrance in the current procedure when both device are NETWORK devices!)
|
||||
$oDevice = MetaModel::GetObject('ConnectableCI', $this->Get('connectableci_id'), false);
|
||||
if (is_object($oDevice) && (get_class($oDevice) == 'NetworkDevice'))
|
||||
{
|
||||
// Track and delete the counterpart link
|
||||
$sOQL = "SELECT lnkConnectableCIToNetworkDevice WHERE connectableci_id = :device AND networkdevice_id = :network AND network_port = :nwport AND device_port = :devport";
|
||||
$oConnectionSet = new DBObjectSet(DBObjectSearch::FromOQL($sOQL),
|
||||
array(),
|
||||
array(
|
||||
'network' => $this->Get('connectableci_id'),
|
||||
@@ -7403,27 +7365,13 @@
|
||||
'devport' => $this->Get('network_port'),
|
||||
'nwport' => $this->Get('device_port'),
|
||||
)
|
||||
);
|
||||
$iAlreadyExist = $oConnectionSet->count();
|
||||
if ((get_class($oDevice) == 'NetworkDevice') && ($iAlreadyExist != 0))
|
||||
{
|
||||
$oMyChange = MetaModel::NewObject("CMDBChange");
|
||||
$oMyChange->Set("date", time());
|
||||
if (UserRights::IsImpersonated())
|
||||
);
|
||||
// There should be one link - do it in a safe manner anyway
|
||||
while ($oConnection = $oConnectionSet->Fetch())
|
||||
{
|
||||
$sUserString = Dict::Format('UI:Archive_User_OnBehalfOf_User', UserRights::GetRealUser(), UserRights::GetUser());
|
||||
$oConnection->DBDelete();
|
||||
}
|
||||
else
|
||||
{
|
||||
$sUserString = UserRights::GetUser();
|
||||
}
|
||||
$oMyChange->Set("userinfo", $sUserString);
|
||||
$iChangeId = $oMyChange->DBInsert();
|
||||
$oConnection = $oConnectionSet->Fetch();
|
||||
$oConnection->DBDeleteTracked($oMyChange);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}]]></code>
|
||||
</method>
|
||||
<method id="AfterInsert">
|
||||
@@ -7815,9 +7763,9 @@
|
||||
</field>
|
||||
<field id="status" xsi:type="AttributeEnum">
|
||||
<values>
|
||||
<value>production</value>
|
||||
<value>implementation</value>
|
||||
<value>obsolete</value>
|
||||
<value id="production">production</value>
|
||||
<value id="implementation">implementation</value>
|
||||
<value id="obsolete">obsolete</value>
|
||||
</values>
|
||||
<sql>status</sql>
|
||||
<default_value>implementation</default_value>
|
||||
@@ -8053,146 +8001,146 @@
|
||||
<rank>1</rank>
|
||||
<parent>ConfigManagement</parent>
|
||||
<definition>
|
||||
<layout>DashboardLayoutOneCol</layout>
|
||||
<title></title>
|
||||
<cells>
|
||||
<cell id="0">
|
||||
<rank>0</rank>
|
||||
<dashlets>
|
||||
<dashlet id="1" xsi:type="DashletHeaderStatic">
|
||||
<rank>0</rank>
|
||||
<title>Menu:ConfigManagement:AllDevices</title>
|
||||
<icon>itop-config-mgmt/images/server.png</icon>
|
||||
<subtitle>Menu_ConfigManagement_AllDevices</subtitle>
|
||||
</dashlet>
|
||||
<dashlet id="2" xsi:type="DashletBadge">
|
||||
<rank>3</rank>
|
||||
<class>Server</class>
|
||||
</dashlet>
|
||||
<dashlet id="3" xsi:type="DashletBadge">
|
||||
<rank>4</rank>
|
||||
<class>NetworkDevice</class>
|
||||
</dashlet>
|
||||
</dashlets>
|
||||
</cell>
|
||||
<cell id="3">
|
||||
<rank>3</rank>
|
||||
<dashlets>
|
||||
<dashlet id="4" xsi:type="DashletHeaderStatic">
|
||||
<rank>0</rank>
|
||||
<title>Menu:ConfigManagement:SWAndApps</title>
|
||||
<icon>itop-config-mgmt/images/application.png</icon>
|
||||
</dashlet>
|
||||
<dashlet id="5" xsi:type="DashletBadge">
|
||||
<rank>1</rank>
|
||||
<class>Middleware</class>
|
||||
</dashlet>
|
||||
<dashlet id="6" xsi:type="DashletBadge">
|
||||
<rank>2</rank>
|
||||
<class>DBServer</class>
|
||||
</dashlet>
|
||||
<dashlet id="7" xsi:type="DashletBadge">
|
||||
<rank>3</rank>
|
||||
<class>WebServer</class>
|
||||
</dashlet>
|
||||
<dashlet id="8" xsi:type="DashletBadge">
|
||||
<rank>4</rank>
|
||||
<class>PCSoftware</class>
|
||||
</dashlet>
|
||||
<dashlet id="9" xsi:type="DashletBadge">
|
||||
<rank>5</rank>
|
||||
<class>OtherSoftware</class>
|
||||
</dashlet>
|
||||
<dashlet id="10" xsi:type="DashletBadge">
|
||||
<rank>6</rank>
|
||||
<class>MiddlewareInstance</class>
|
||||
</dashlet>
|
||||
<dashlet id="11" xsi:type="DashletBadge">
|
||||
<rank>7</rank>
|
||||
<class>DatabaseSchema</class>
|
||||
</dashlet>
|
||||
<dashlet id="12" xsi:type="DashletBadge">
|
||||
<rank>8</rank>
|
||||
<class>WebApplication</class>
|
||||
</dashlet>
|
||||
<dashlet id="13" xsi:type="DashletBadge">
|
||||
<rank>9</rank>
|
||||
<class>Patch</class>
|
||||
</dashlet>
|
||||
<dashlet id="14" xsi:type="DashletBadge">
|
||||
<rank>10</rank>
|
||||
<class>Licence</class>
|
||||
</dashlet>
|
||||
</dashlets>
|
||||
</cell>
|
||||
<cell id="4">
|
||||
<rank>4</rank>
|
||||
<dashlets>
|
||||
<dashlet id="15" xsi:type="DashletHeaderStatic">
|
||||
<rank>0</rank>
|
||||
<title>Menu:ConfigManagement:Misc</title>
|
||||
<icon>itop-config-mgmt/images/subnet.png</icon>
|
||||
</dashlet>
|
||||
<dashlet id="16" xsi:type="DashletBadge">
|
||||
<rank>1</rank>
|
||||
<class>NetworkInterface</class>
|
||||
</dashlet>
|
||||
<dashlet id="17" xsi:type="DashletBadge">
|
||||
<rank>2</rank>
|
||||
<class>Subnet</class>
|
||||
</dashlet>
|
||||
<dashlet id="vlan" xsi:type="DashletBadge">
|
||||
<rank>2.1</rank>
|
||||
<class>VLAN</class>
|
||||
</dashlet>
|
||||
<dashlet id="18" xsi:type="DashletBadge">
|
||||
<rank>4</rank>
|
||||
<class>BusinessProcess</class>
|
||||
</dashlet>
|
||||
<dashlet id="19" xsi:type="DashletBadge">
|
||||
<rank>5</rank>
|
||||
<class>ApplicationSolution</class>
|
||||
</dashlet>
|
||||
<dashlet id="20" xsi:type="DashletBadge">
|
||||
<rank>6</rank>
|
||||
<class>Group</class>
|
||||
</dashlet>
|
||||
</dashlets>
|
||||
</cell>
|
||||
</cells>
|
||||
<layout>DashboardLayoutOneCol</layout>
|
||||
<title/>
|
||||
<cells>
|
||||
<cell id="0">
|
||||
<rank>0</rank>
|
||||
<dashlets>
|
||||
<dashlet id="1" xsi:type="DashletHeaderStatic">
|
||||
<rank>0</rank>
|
||||
<title>Menu:ConfigManagement:AllDevices</title>
|
||||
<icon>itop-config-mgmt/images/server.png</icon>
|
||||
<subtitle>Menu_ConfigManagement_AllDevices</subtitle>
|
||||
</dashlet>
|
||||
<dashlet id="2" xsi:type="DashletBadge">
|
||||
<rank>3</rank>
|
||||
<class>Server</class>
|
||||
</dashlet>
|
||||
<dashlet id="3" xsi:type="DashletBadge">
|
||||
<rank>4</rank>
|
||||
<class>NetworkDevice</class>
|
||||
</dashlet>
|
||||
</dashlets>
|
||||
</cell>
|
||||
<cell id="3">
|
||||
<rank>3</rank>
|
||||
<dashlets>
|
||||
<dashlet id="4" xsi:type="DashletHeaderStatic">
|
||||
<rank>0</rank>
|
||||
<title>Menu:ConfigManagement:SWAndApps</title>
|
||||
<icon>itop-config-mgmt/images/application.png</icon>
|
||||
</dashlet>
|
||||
<dashlet id="5" xsi:type="DashletBadge">
|
||||
<rank>1</rank>
|
||||
<class>Middleware</class>
|
||||
</dashlet>
|
||||
<dashlet id="6" xsi:type="DashletBadge">
|
||||
<rank>2</rank>
|
||||
<class>DBServer</class>
|
||||
</dashlet>
|
||||
<dashlet id="7" xsi:type="DashletBadge">
|
||||
<rank>3</rank>
|
||||
<class>WebServer</class>
|
||||
</dashlet>
|
||||
<dashlet id="8" xsi:type="DashletBadge">
|
||||
<rank>4</rank>
|
||||
<class>PCSoftware</class>
|
||||
</dashlet>
|
||||
<dashlet id="9" xsi:type="DashletBadge">
|
||||
<rank>5</rank>
|
||||
<class>OtherSoftware</class>
|
||||
</dashlet>
|
||||
<dashlet id="10" xsi:type="DashletBadge">
|
||||
<rank>6</rank>
|
||||
<class>MiddlewareInstance</class>
|
||||
</dashlet>
|
||||
<dashlet id="11" xsi:type="DashletBadge">
|
||||
<rank>7</rank>
|
||||
<class>DatabaseSchema</class>
|
||||
</dashlet>
|
||||
<dashlet id="12" xsi:type="DashletBadge">
|
||||
<rank>8</rank>
|
||||
<class>WebApplication</class>
|
||||
</dashlet>
|
||||
<dashlet id="13" xsi:type="DashletBadge">
|
||||
<rank>9</rank>
|
||||
<class>Patch</class>
|
||||
</dashlet>
|
||||
<dashlet id="14" xsi:type="DashletBadge">
|
||||
<rank>10</rank>
|
||||
<class>Licence</class>
|
||||
</dashlet>
|
||||
</dashlets>
|
||||
</cell>
|
||||
<cell id="4">
|
||||
<rank>4</rank>
|
||||
<dashlets>
|
||||
<dashlet id="15" xsi:type="DashletHeaderStatic">
|
||||
<rank>0</rank>
|
||||
<title>Menu:ConfigManagement:Misc</title>
|
||||
<icon>itop-config-mgmt/images/subnet.png</icon>
|
||||
</dashlet>
|
||||
<dashlet id="16" xsi:type="DashletBadge">
|
||||
<rank>1</rank>
|
||||
<class>NetworkInterface</class>
|
||||
</dashlet>
|
||||
<dashlet id="17" xsi:type="DashletBadge">
|
||||
<rank>2</rank>
|
||||
<class>Subnet</class>
|
||||
</dashlet>
|
||||
<dashlet id="vlan" xsi:type="DashletBadge">
|
||||
<rank>2.1</rank>
|
||||
<class>VLAN</class>
|
||||
</dashlet>
|
||||
<dashlet id="18" xsi:type="DashletBadge">
|
||||
<rank>4</rank>
|
||||
<class>BusinessProcess</class>
|
||||
</dashlet>
|
||||
<dashlet id="19" xsi:type="DashletBadge">
|
||||
<rank>5</rank>
|
||||
<class>ApplicationSolution</class>
|
||||
</dashlet>
|
||||
<dashlet id="20" xsi:type="DashletBadge">
|
||||
<rank>6</rank>
|
||||
<class>Group</class>
|
||||
</dashlet>
|
||||
</dashlets>
|
||||
</cell>
|
||||
</cells>
|
||||
</definition>
|
||||
</menu>
|
||||
<menu id="Contact" xsi:type="DashboardMenuNode" _delta="define">
|
||||
<rank>2</rank>
|
||||
<parent>ConfigManagement</parent>
|
||||
<definition>
|
||||
<layout>DashboardLayoutOneCol</layout>
|
||||
<title></title>
|
||||
<cells>
|
||||
<cell id="0">
|
||||
<rank>0</rank>
|
||||
<dashlets>
|
||||
<dashlet id="1" xsi:type="DashletHeaderDynamic">
|
||||
<rank>1</rank>
|
||||
<title>Menu:Contact</title>
|
||||
<icon>itop-config-mgmt/images/team.png</icon>
|
||||
<subtitle>Menu:Contact:Count</subtitle>
|
||||
<query>SELECT Contact</query>
|
||||
<group_by>status</group_by>
|
||||
<values>active,inactive</values>
|
||||
</dashlet>
|
||||
<dashlet id="2" xsi:type="DashletBadge">
|
||||
<rank>2</rank>
|
||||
<class>Team</class>
|
||||
</dashlet>
|
||||
<dashlet id="3" xsi:type="DashletBadge">
|
||||
<rank>3</rank>
|
||||
<class>Person</class>
|
||||
</dashlet>
|
||||
</dashlets>
|
||||
</cell>
|
||||
</cells>
|
||||
</definition>
|
||||
<layout>DashboardLayoutOneCol</layout>
|
||||
<title/>
|
||||
<cells>
|
||||
<cell id="0">
|
||||
<rank>0</rank>
|
||||
<dashlets>
|
||||
<dashlet id="1" xsi:type="DashletHeaderDynamic">
|
||||
<rank>1</rank>
|
||||
<title>Menu:Contact</title>
|
||||
<icon>itop-config-mgmt/images/team.png</icon>
|
||||
<subtitle>Menu:Contact:Count</subtitle>
|
||||
<query>SELECT Contact</query>
|
||||
<group_by>status</group_by>
|
||||
<values>active,inactive</values>
|
||||
</dashlet>
|
||||
<dashlet id="2" xsi:type="DashletBadge">
|
||||
<rank>2</rank>
|
||||
<class>Team</class>
|
||||
</dashlet>
|
||||
<dashlet id="3" xsi:type="DashletBadge">
|
||||
<rank>3</rank>
|
||||
<class>Person</class>
|
||||
</dashlet>
|
||||
</dashlets>
|
||||
</cell>
|
||||
</cells>
|
||||
</definition>
|
||||
</menu>
|
||||
<menu id="NewContact" xsi:type="NewObjectMenuNode" _delta="define">
|
||||
<rank>3</rank>
|
||||
@@ -8238,57 +8186,57 @@
|
||||
<oql>SELECT Group</oql>
|
||||
<do_search>1</do_search>
|
||||
</menu>
|
||||
<menu id="Typology" xsi:type="DashboardMenuNode" _delta="define">
|
||||
<rank>80</rank>
|
||||
<parent>Catalogs</parent>
|
||||
<definition>
|
||||
<layout>DashboardLayoutOneCol</layout>
|
||||
<title>Menu:ConfigManagement:Typology</title>
|
||||
<cells>
|
||||
<cell id="0">
|
||||
<rank>0</rank>
|
||||
<dashlets>
|
||||
<dashlet id="1" xsi:type="DashletHeaderStatic">
|
||||
<rank>0</rank>
|
||||
<title>Menu:ConfigManagement:Typology</title>
|
||||
<icon>itop-config-mgmt/images/typology.png</icon>
|
||||
</dashlet>
|
||||
<dashlet id="2" xsi:type="DashletBadge">
|
||||
<rank>1</rank>
|
||||
<class>Brand</class>
|
||||
</dashlet>
|
||||
<dashlet id="3" xsi:type="DashletBadge">
|
||||
<rank>2</rank>
|
||||
<class>Model</class>
|
||||
</dashlet>
|
||||
<dashlet id="4" xsi:type="DashletBadge">
|
||||
<rank>3</rank>
|
||||
<class>OSFamily</class>
|
||||
</dashlet>
|
||||
<dashlet id="5" xsi:type="DashletBadge">
|
||||
<rank>4</rank>
|
||||
<class>OSVersion</class>
|
||||
</dashlet>
|
||||
<dashlet id="6" xsi:type="DashletBadge">
|
||||
<rank>5</rank>
|
||||
<class>IOSVersion</class>
|
||||
</dashlet>
|
||||
<dashlet id="7" xsi:type="DashletBadge">
|
||||
<rank>6</rank>
|
||||
<class>NetworkDeviceType</class>
|
||||
</dashlet>
|
||||
<dashlet id="9" xsi:type="DashletBadge">
|
||||
<rank>8</rank>
|
||||
<class>ContactType</class>
|
||||
</dashlet>
|
||||
<dashlet id="10" xsi:type="DashletBadge">
|
||||
<rank>9</rank>
|
||||
<class>DocumentType</class>
|
||||
</dashlet>
|
||||
</dashlets>
|
||||
</cell>
|
||||
</cells>
|
||||
</definition>
|
||||
</menu>
|
||||
<menu id="Typology" xsi:type="DashboardMenuNode" _delta="define">
|
||||
<rank>80</rank>
|
||||
<parent>Catalogs</parent>
|
||||
<definition>
|
||||
<layout>DashboardLayoutOneCol</layout>
|
||||
<title>Menu:ConfigManagement:Typology</title>
|
||||
<cells>
|
||||
<cell id="0">
|
||||
<rank>0</rank>
|
||||
<dashlets>
|
||||
<dashlet id="1" xsi:type="DashletHeaderStatic">
|
||||
<rank>0</rank>
|
||||
<title>Menu:ConfigManagement:Typology</title>
|
||||
<icon>itop-config-mgmt/images/typology.png</icon>
|
||||
</dashlet>
|
||||
<dashlet id="2" xsi:type="DashletBadge">
|
||||
<rank>1</rank>
|
||||
<class>Brand</class>
|
||||
</dashlet>
|
||||
<dashlet id="3" xsi:type="DashletBadge">
|
||||
<rank>2</rank>
|
||||
<class>Model</class>
|
||||
</dashlet>
|
||||
<dashlet id="4" xsi:type="DashletBadge">
|
||||
<rank>3</rank>
|
||||
<class>OSFamily</class>
|
||||
</dashlet>
|
||||
<dashlet id="5" xsi:type="DashletBadge">
|
||||
<rank>4</rank>
|
||||
<class>OSVersion</class>
|
||||
</dashlet>
|
||||
<dashlet id="6" xsi:type="DashletBadge">
|
||||
<rank>5</rank>
|
||||
<class>IOSVersion</class>
|
||||
</dashlet>
|
||||
<dashlet id="7" xsi:type="DashletBadge">
|
||||
<rank>6</rank>
|
||||
<class>NetworkDeviceType</class>
|
||||
</dashlet>
|
||||
<dashlet id="9" xsi:type="DashletBadge">
|
||||
<rank>8</rank>
|
||||
<class>ContactType</class>
|
||||
</dashlet>
|
||||
<dashlet id="10" xsi:type="DashletBadge">
|
||||
<rank>9</rank>
|
||||
<class>DocumentType</class>
|
||||
</dashlet>
|
||||
</dashlets>
|
||||
</cell>
|
||||
</cells>
|
||||
</definition>
|
||||
</menu>
|
||||
</menus>
|
||||
</itop_design>
|
||||
|
||||
@@ -33,7 +33,7 @@ Dict::Add('EN US', 'English', 'English', array(
|
||||
'Relation:impacts/Description' => 'Elements impacted by',
|
||||
'Relation:impacts/VerbUp' => 'Impact...',
|
||||
'Relation:impacts/VerbDown' => 'Elements impacted by...',
|
||||
'Relation:depends on/Description' => 'Elements this element depends on',
|
||||
'Relation:depends on/Description' => 'Elements impacting',
|
||||
'Relation:depends on/VerbUp' => 'Depends on...',
|
||||
'Relation:depends on/VerbDown' => 'Impacts...',
|
||||
));
|
||||
|
||||
@@ -1817,7 +1817,7 @@ Dict::Add('FR FR', 'French', 'Français', array(
|
||||
'Relation:impacts/Description' => 'Eléments impactés par',
|
||||
'Relation:impacts/VerbUp' => 'Impacte...',
|
||||
'Relation:impacts/VerbDown' => 'Dépend de...',
|
||||
'Relation:depends on/Description' => 'Eléments dont dépend cet élément',
|
||||
'Relation:depends on/Description' => 'Eléments dont dépend',
|
||||
'Relation:depends on/VerbUp' => 'Dépend de...',
|
||||
'Relation:depends on/VerbDown' => 'Impacte...',
|
||||
'Menu:ConfigManagement:Typology' => 'Configuration des typologies',
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-config-mgmt/2.0.0',
|
||||
'itop-config-mgmt/2.1.0',
|
||||
array(
|
||||
// Identification
|
||||
//
|
||||
|
||||
223
datamodels/2.x/itop-config/config.php
Normal file
223
datamodels/2.x/itop-config/config.php
Normal file
@@ -0,0 +1,223 @@
|
||||
<?php
|
||||
// Copyright (C) 2014 Combodo SARL
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// iTop is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
|
||||
/**
|
||||
* Monitor the backup
|
||||
*
|
||||
* @copyright Copyright (C) 2013 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
require_once('../../approot.inc.php');
|
||||
require_once(APPROOT.'application/application.inc.php');
|
||||
require_once(APPROOT.'application/itopwebpage.class.inc.php');
|
||||
|
||||
require_once(APPROOT.'application/startup.inc.php');
|
||||
|
||||
require_once(APPROOT.'application/loginwebpage.class.inc.php');
|
||||
|
||||
|
||||
function TestConfig($sContents, $oP)
|
||||
{
|
||||
try
|
||||
{
|
||||
ini_set('display_errors', 1);
|
||||
ob_start();
|
||||
eval('?'.'>'.trim($sContents));
|
||||
$sNoise = trim(ob_get_contents());
|
||||
ob_end_clean();
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
// well, never reach in case of parsing error :-(
|
||||
throw new Exception('Error in configuration: '.$e->getMessage());
|
||||
}
|
||||
if (strlen($sNoise) > 0)
|
||||
{
|
||||
if (preg_match("/(Error|Parse error|Notice|Warning): (.+) in \S+ : eval\(\)'d code on line (\d+)/i", strip_tags($sNoise), $aMatches))
|
||||
{
|
||||
$sMessage = $aMatches[2];
|
||||
$sLine = $aMatches[3];
|
||||
$iLine = (int) $sLine;
|
||||
|
||||
// Highlight the line
|
||||
$aLines = explode("\n", $sContents);
|
||||
$iStart = 0;
|
||||
for ($i = 0 ; $i < $iLine - 1; $i++) $iStart += strlen($aLines[$i]);
|
||||
$iEnd = $iStart + strlen($aLines[$iLine - 1]);
|
||||
$iTotalLines = count($aLines);
|
||||
$oP->add_ready_script(
|
||||
<<<EOF
|
||||
setCursorPos($('#new_config')[0], $iStart, $iEnd);
|
||||
$('#new_config')[0].focus();
|
||||
var iScroll = Math.floor($('#new_config')[0].scrollHeight * ($iLine - 20) / $iTotalLines);
|
||||
$('#new_config').scrollTop(iScroll);
|
||||
EOF
|
||||
);
|
||||
|
||||
$sMessage = Dict::Format('config-parse-error', $sMessage, $sLine);
|
||||
throw new Exception($sMessage);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Note: sNoise is an html output, but so far it was ok for me (e.g. showing the entire call stack)
|
||||
throw new Exception('Syntax error in configuration file: <tt>'.$sNoise.'</tt>');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// Main program
|
||||
//
|
||||
LoginWebPage::DoLogin(true); // Check user rights and prompt if needed (must be admin)
|
||||
|
||||
//$sOperation = utils::ReadParam('operation', 'menu');
|
||||
//$oAppContext = new ApplicationContext();
|
||||
|
||||
$oP = new iTopWebPage(Dict::S('config-edit-title'));
|
||||
$oP->set_base(utils::GetAbsoluteUrlAppRoot().'pages/');
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
$sOperation = utils::ReadParam('operation', '');
|
||||
|
||||
$oP->add("<h1>".Dict::S('config-edit-title')."</h1>");
|
||||
|
||||
if (MetaModel::GetConfig()->Get('demo_mode'))
|
||||
{
|
||||
$oP->add("<div class=\"header_message message_info\">Sorry, iTop is in <b>demonstration mode</b>: the configuration file cannot be edited.</div>");
|
||||
}
|
||||
else
|
||||
{
|
||||
$oP->add_style(
|
||||
<<<EOF
|
||||
textarea {
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
|
||||
width: 100%;
|
||||
height: 550px;
|
||||
}
|
||||
.current_line {
|
||||
display: none;
|
||||
margin-left: 20px;
|
||||
}
|
||||
EOF
|
||||
);
|
||||
|
||||
$sConfigFile = APPROOT.'conf/'.utils::GetCurrentEnvironment().'/config-itop.php';
|
||||
|
||||
if ($sOperation == 'save')
|
||||
{
|
||||
$sConfig = utils::ReadParam('new_config', '', false, 'raw_data');
|
||||
$sOrginalConfig = utils::ReadParam('prev_config', '', false, 'raw_data');
|
||||
if ($sConfig == $sOrginalConfig)
|
||||
{
|
||||
$oP->add('<div id="save_result" class="header_message">'.Dict::S('config-no-change').'</div>');
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
TestConfig($sConfig, $oP); // throws exceptions
|
||||
|
||||
@chmod($sConfigFile, 0770); // Allow overwriting the file
|
||||
file_put_contents($sConfigFile, $sConfig);
|
||||
@chmod($sConfigFile, 0444); // Read-only
|
||||
|
||||
$oP->p('<div id="save_result" class="header_message message_ok">'.Dict::S('Successfully recorded.').'</div>');
|
||||
$sOrginalConfig = str_replace("\r\n", "\n", file_get_contents($sConfigFile));
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
$oP->p('<div id="save_result" class="header_message message_error">'.$e->getMessage().'</div>');
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$sConfig = str_replace("\r\n", "\n", file_get_contents($sConfigFile));
|
||||
$sOrginalConfig = $sConfig;
|
||||
}
|
||||
|
||||
$sConfigEscaped = htmlentities($sConfig, ENT_QUOTES, 'UTF-8');
|
||||
$sOriginalConfigEscaped = htmlentities($sOrginalConfig, ENT_QUOTES, 'UTF-8');
|
||||
$oP->p(Dict::S('config-edit-intro'));
|
||||
$oP->add("<form method=\"POST\">");
|
||||
$oP->add("<input type=\"hidden\" name=\"operation\" value=\"save\">");
|
||||
$oP->add("<input type=\"submit\" value=\"".Dict::S('config-apply')."\"><button onclick=\"ResetConfig(); return false;\">".Dict::S('config-cancel')."</button>");
|
||||
$oP->add("<span class=\"current_line\">".Dict::Format('config-current-line', "<span class=\"line_number\"></span>")."</span>");
|
||||
$oP->add("<input type=\"hidden\" id=\"prev_config\" name=\"prev_config\" value=\"$sOriginalConfigEscaped\">");
|
||||
$oP->add("<textarea id =\"new_config\" name=\"new_config\" onkeyup=\"UpdateLineNumber();\" onmouseup=\"UpdateLineNumber();\">$sConfigEscaped</textarea>");
|
||||
$oP->add("<input type=\"submit\" value=\"".Dict::S('config-apply')."\"><button onclick=\"ResetConfig(); return false;\">".Dict::S('config-cancel')."</button>");
|
||||
$oP->add("<span class=\"current_line\">".Dict::Format('config-current-line', "<span class=\"line_number\"></span>")."</span>");
|
||||
$oP->add("</form>");
|
||||
|
||||
$sConfirmCancel = addslashes(Dict::S('config-confirm-cancel'));
|
||||
$oP->add_script(
|
||||
<<<EOF
|
||||
function UpdateLineNumber()
|
||||
{
|
||||
var oTextArea = $('#new_config')[0];
|
||||
$('.line_number').html(oTextArea.value.substr(0, oTextArea.selectionStart).split("\\n").length);
|
||||
$('.current_line').show();
|
||||
}
|
||||
function ResetConfig()
|
||||
{
|
||||
if ($('#new_config').val() != $('#prev_config').val())
|
||||
{
|
||||
if (confirm('$sConfirmCancel'))
|
||||
{
|
||||
$('#new_config').val($('#prev_config').val());
|
||||
}
|
||||
}
|
||||
$('.current_line').hide();
|
||||
$('#save_result').hide();
|
||||
return false;
|
||||
}
|
||||
|
||||
function setCursorPos(input, start, end) {
|
||||
if (arguments.length < 3) end = start;
|
||||
if ("selectionStart" in input) {
|
||||
setTimeout(function() {
|
||||
input.selectionStart = start;
|
||||
input.selectionEnd = end;
|
||||
}, 1);
|
||||
}
|
||||
else if (input.createTextRange) {
|
||||
var rng = input.createTextRange();
|
||||
rng.moveStart("character", start);
|
||||
rng.collapse();
|
||||
rng.moveEnd("character", end - start);
|
||||
rng.select();
|
||||
}
|
||||
}
|
||||
EOF
|
||||
);
|
||||
}
|
||||
}
|
||||
catch(Exception $e)
|
||||
{
|
||||
$oP->p('<b>'.$e->getMessage().'</b>');
|
||||
}
|
||||
|
||||
$oP->output();
|
||||
20
datamodels/2.x/itop-config/de.dict.itop-config.php
Normal file
20
datamodels/2.x/itop-config/de.dict.itop-config.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
/**
|
||||
* Localized data
|
||||
*
|
||||
* @copyright Copyright (C) 2013 Combodo
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
Dict::Add('DE DE', 'German', 'Deutsch', array(
|
||||
|
||||
'Menu:ConfigEditor' => 'Konfiguration',
|
||||
'config-edit-title' => 'Konfigurations-Editor',
|
||||
'config-edit-intro' => 'Seien sie bei der Bearbeitung der Konfigurationsdatei sehr vorsichtig. Normalerweise sollten es aureichen die Einträge im oberen Teil der Konfiguration zu bearbeiten (Bsp.: die globalen Konfigurations- und Moduleinstellungen).',
|
||||
'config-apply' => 'Anwenden',
|
||||
'config-cancel' => 'Zurücksetzen',
|
||||
'config-confirm-cancel' => 'Ihre Änderungen werden nicht gespeichert.',
|
||||
'config-no-change' => 'Keine Änderungen: Die Datei wurde nicht verändert.',
|
||||
'config-parse-error' => 'Zeile %2$d: %1$s.<br/>Die Datei wurde nicht aktualisiert.',
|
||||
'config-current-line' => 'Editiere Zeile: %1$s',
|
||||
));
|
||||
21
datamodels/2.x/itop-config/en.dict.itop-config.php
Normal file
21
datamodels/2.x/itop-config/en.dict.itop-config.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
/**
|
||||
* Localized data
|
||||
*
|
||||
* @copyright Copyright (C) 2013 Combodo
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
Dict::Add('EN US', 'English', 'English', array(
|
||||
|
||||
'Menu:ConfigEditor' => 'Configuration',
|
||||
'config-edit-title' => 'Configuration File Editor',
|
||||
'config-edit-intro' => 'Be very cautious when editing the configuration file. In particular, only the upper items (i.e. the global configuration and modules settings) should be edited.',
|
||||
'config-apply' => 'Apply',
|
||||
'config-cancel' => 'Reset',
|
||||
'config-confirm-cancel' => 'Your changes will be lost.',
|
||||
'config-no-change' => 'No change: the file has been left unchanged.',
|
||||
'config-parse-error' => 'Line %2$d: %1$s.<br/>The file has NOT been updated.',
|
||||
'config-current-line' => 'Editing line: %1$s',
|
||||
));
|
||||
?>
|
||||
21
datamodels/2.x/itop-config/fr.dict.itop-config.php
Normal file
21
datamodels/2.x/itop-config/fr.dict.itop-config.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
/**
|
||||
* Localized data
|
||||
*
|
||||
* @copyright Copyright (C) 2013 Combodo
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
Dict::Add('FR FR', 'French', 'Français', array(
|
||||
|
||||
'Menu:ConfigEditor' => 'Configuration',
|
||||
'config-edit-title' => 'Editeur du Fichier de Configuration',
|
||||
'config-edit-intro' => 'Attention: une configuration incorrecte peut rendre iTop indisponible. En particulier, vous ne devriez éditer QUE les deux premiers éléments, à savoir la configuration globale et la configuration des modules.',
|
||||
'config-save' => 'Appliquer',
|
||||
'config-restore' => 'Réinitialiser',
|
||||
'config-confirm-cancel' => 'Vos modifications seront perdues.',
|
||||
'config-no-change' => 'Aucun changement : le fichier n\'a pas été altéré.',
|
||||
'config-parse-error' => 'Ligne %2$d: %1$s.<br/>Le fichier n\'a PAS été modifié.',
|
||||
'config-current-line' => 'Ligne en édition : %1$s',
|
||||
));
|
||||
?>
|
||||
30
datamodels/2.x/itop-config/main.itop-config.php
Normal file
30
datamodels/2.x/itop-config/main.itop-config.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
// Copyright (C) 2013 Combodo SARL
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; version 3 of the License.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
|
||||
//require_once(APPROOT.'setup/setuputils.class.inc.php');
|
||||
|
||||
class ItopConfigEditor extends ModuleHandlerAPI
|
||||
{
|
||||
public static function OnMenuCreation()
|
||||
{
|
||||
if (UserRights::IsAdministrator())
|
||||
{
|
||||
$oAdminMenu = new MenuGroup('AdminTools', 80 /* fRank */);
|
||||
new WebPageMenuNode('ConfigEditor', utils::GetAbsoluteUrlModulesRoot().'itop-config/config.php', $oAdminMenu->GetIndex(), 18 /* fRank */);
|
||||
}
|
||||
}
|
||||
}
|
||||
53
datamodels/2.x/itop-config/module.itop-config.php
Normal file
53
datamodels/2.x/itop-config/module.itop-config.php
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-config/1.0.2',
|
||||
array(
|
||||
// Identification
|
||||
//
|
||||
'label' => 'Configuration editor',
|
||||
'category' => 'Application management',
|
||||
|
||||
// Setup
|
||||
//
|
||||
'dependencies' => array(
|
||||
),
|
||||
'mandatory' => true,
|
||||
'visible' => false,
|
||||
|
||||
// Components
|
||||
//
|
||||
'datamodel' => array(
|
||||
'main.itop-config.php',
|
||||
//'model.itop-config.php',
|
||||
),
|
||||
'webservice' => array(
|
||||
//'webservices.itop-config.php',
|
||||
),
|
||||
'dictionary' => array(
|
||||
'en.dict.itop-config.php',
|
||||
'fr.dict.itop-config.php',
|
||||
//'de.dict.itop-config.php',
|
||||
),
|
||||
'data.struct' => array(
|
||||
//'data.struct.itop-config.xml',
|
||||
),
|
||||
'data.sample' => array(
|
||||
//'data.sample.itop-config.xml',
|
||||
),
|
||||
|
||||
// Documentation
|
||||
//
|
||||
'doc.manual_setup' => '',
|
||||
'doc.more_information' => '',
|
||||
|
||||
// Default settings
|
||||
//
|
||||
'settings' => array(
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
?>
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0">
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.1">
|
||||
<classes>
|
||||
<class id="Rack" _delta="define">
|
||||
<parent>PhysicalDevice</parent>
|
||||
@@ -769,7 +769,7 @@
|
||||
<target_class>Rack</target_class>
|
||||
<is_null_allowed>false</is_null_allowed>
|
||||
<on_target_delete>DEL_MANUAL</on_target_delete>
|
||||
<allow_target_creation>false</allow_target_creation>
|
||||
<allow_target_creation>false</allow_target_creation>
|
||||
</field>
|
||||
<field id="rack_name" xsi:type="AttributeExternalField">
|
||||
<extkey_attcode>rack_id</extkey_attcode>
|
||||
@@ -784,8 +784,8 @@
|
||||
<target_class>PowerConnection</target_class>
|
||||
<is_null_allowed>true</is_null_allowed>
|
||||
<on_target_delete>DEL_MANUAL</on_target_delete>
|
||||
<allow_target_creation>false</allow_target_creation>
|
||||
<allow_target_creation>false</allow_target_creation>
|
||||
<allow_target_creation>false</allow_target_creation>
|
||||
<allow_target_creation>false</allow_target_creation>
|
||||
</field>
|
||||
<field id="powerstart_name" xsi:type="AttributeExternalField">
|
||||
<extkey_attcode>powerstart_id</extkey_attcode>
|
||||
@@ -958,25 +958,25 @@
|
||||
</classes>
|
||||
<menus>
|
||||
<menu id="ConfigManagementOverview" xsi:type="DashboardMenuNode" _delta="must_exist">
|
||||
<definition>
|
||||
<cells>
|
||||
<cell id="0" _delta="must_exist">
|
||||
<dashlets>
|
||||
<dashlet id="21" xsi:type="DashletBadge" _delta="define">
|
||||
<rank>1</rank>
|
||||
<class>Rack</class>
|
||||
</dashlet>
|
||||
<dashlet id="22" xsi:type="DashletBadge" _delta="define">
|
||||
<rank>2</rank>
|
||||
<class>Enclosure</class>
|
||||
</dashlet>
|
||||
<dashlet id="23" xsi:type="DashletBadge" _delta="define">
|
||||
<rank>9</rank>
|
||||
<class>PowerConnection</class>
|
||||
</dashlet>
|
||||
</dashlets>
|
||||
</cell>
|
||||
</cells>
|
||||
<definition>
|
||||
<cells>
|
||||
<cell id="0" _delta="must_exist">
|
||||
<dashlets>
|
||||
<dashlet id="21" xsi:type="DashletBadge" _delta="define">
|
||||
<rank>1</rank>
|
||||
<class>Rack</class>
|
||||
</dashlet>
|
||||
<dashlet id="22" xsi:type="DashletBadge" _delta="define">
|
||||
<rank>2</rank>
|
||||
<class>Enclosure</class>
|
||||
</dashlet>
|
||||
<dashlet id="23" xsi:type="DashletBadge" _delta="define">
|
||||
<rank>9</rank>
|
||||
<class>PowerConnection</class>
|
||||
</dashlet>
|
||||
</dashlets>
|
||||
</cell>
|
||||
</cells>
|
||||
</definition>
|
||||
</menu>
|
||||
</menus>
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-datacenter-mgmt/2.0.0',
|
||||
'itop-datacenter-mgmt/2.1.0',
|
||||
array(
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0">
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.1">
|
||||
<classes>
|
||||
<class id="TelephonyCI" _delta="define">
|
||||
<class id="TelephonyCI" _delta="define">
|
||||
<parent>PhysicalDevice</parent>
|
||||
<properties>
|
||||
<category>bizmodel,searchable</category>
|
||||
@@ -860,8 +860,8 @@
|
||||
</field>
|
||||
<field id="type" xsi:type="AttributeEnum">
|
||||
<values>
|
||||
<value>laptop</value>
|
||||
<value>desktop</value>
|
||||
<value id="laptop">laptop</value>
|
||||
<value id="desktop">desktop</value>
|
||||
</values>
|
||||
<sql>type</sql>
|
||||
<default_value/>
|
||||
@@ -1242,7 +1242,6 @@
|
||||
</list>
|
||||
</presentation>
|
||||
</class>
|
||||
|
||||
<class id="Peripheral" _delta="define">
|
||||
<parent>PhysicalDevice</parent>
|
||||
<properties>
|
||||
@@ -1396,51 +1395,51 @@
|
||||
</list>
|
||||
</presentation>
|
||||
</class>
|
||||
</classes>
|
||||
<menus>
|
||||
<menu id="ConfigManagementOverview" xsi:type="DashboardMenuNode" _delta="must_exist">
|
||||
<definition>
|
||||
<cells>
|
||||
<cell id="2" _delta="define">
|
||||
<rank>2</rank>
|
||||
<dashlets>
|
||||
<dashlet id="25" xsi:type="DashletHeaderStatic">
|
||||
<rank>0</rank>
|
||||
<title>Menu:ConfigManagement:EndUsers</title>
|
||||
<icon>itop-config-mgmt/images/team.png</icon>
|
||||
</dashlet>
|
||||
<dashlet id="26" xsi:type="DashletBadge">
|
||||
<rank>1</rank>
|
||||
<class>PC</class>
|
||||
</dashlet>
|
||||
<dashlet id="27" xsi:type="DashletBadge">
|
||||
<rank>2</rank>
|
||||
<class>Phone</class>
|
||||
</dashlet>
|
||||
<dashlet id="28" xsi:type="DashletBadge">
|
||||
<rank>3</rank>
|
||||
<class>IPPhone</class>
|
||||
</dashlet>
|
||||
<dashlet id="29" xsi:type="DashletBadge">
|
||||
<rank>4</rank>
|
||||
<class>MobilePhone</class>
|
||||
</dashlet>
|
||||
<dashlet id="30" xsi:type="DashletBadge">
|
||||
<rank>5</rank>
|
||||
<class>Tablet</class>
|
||||
</dashlet>
|
||||
<dashlet id="31" xsi:type="DashletBadge">
|
||||
<rank>6</rank>
|
||||
<class>Printer</class>
|
||||
</dashlet>
|
||||
<dashlet id="32" xsi:type="DashletBadge">
|
||||
<rank>7</rank>
|
||||
<class>Peripheral</class>
|
||||
</dashlet>
|
||||
</dashlets>
|
||||
</cell>
|
||||
</cells>
|
||||
</definition>
|
||||
</menu>
|
||||
</menus>
|
||||
</classes>
|
||||
<menus>
|
||||
<menu id="ConfigManagementOverview" xsi:type="DashboardMenuNode" _delta="must_exist">
|
||||
<definition>
|
||||
<cells>
|
||||
<cell id="2" _delta="define">
|
||||
<rank>2</rank>
|
||||
<dashlets>
|
||||
<dashlet id="25" xsi:type="DashletHeaderStatic">
|
||||
<rank>0</rank>
|
||||
<title>Menu:ConfigManagement:EndUsers</title>
|
||||
<icon>itop-config-mgmt/images/team.png</icon>
|
||||
</dashlet>
|
||||
<dashlet id="26" xsi:type="DashletBadge">
|
||||
<rank>1</rank>
|
||||
<class>PC</class>
|
||||
</dashlet>
|
||||
<dashlet id="27" xsi:type="DashletBadge">
|
||||
<rank>2</rank>
|
||||
<class>Phone</class>
|
||||
</dashlet>
|
||||
<dashlet id="28" xsi:type="DashletBadge">
|
||||
<rank>3</rank>
|
||||
<class>IPPhone</class>
|
||||
</dashlet>
|
||||
<dashlet id="29" xsi:type="DashletBadge">
|
||||
<rank>4</rank>
|
||||
<class>MobilePhone</class>
|
||||
</dashlet>
|
||||
<dashlet id="30" xsi:type="DashletBadge">
|
||||
<rank>5</rank>
|
||||
<class>Tablet</class>
|
||||
</dashlet>
|
||||
<dashlet id="31" xsi:type="DashletBadge">
|
||||
<rank>6</rank>
|
||||
<class>Printer</class>
|
||||
</dashlet>
|
||||
<dashlet id="32" xsi:type="DashletBadge">
|
||||
<rank>7</rank>
|
||||
<class>Peripheral</class>
|
||||
</dashlet>
|
||||
</dashlets>
|
||||
</cell>
|
||||
</cells>
|
||||
</definition>
|
||||
</menu>
|
||||
</menus>
|
||||
</itop_design>
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-endusers-devices/2.0.0',
|
||||
'itop-endusers-devices/2.1.0',
|
||||
array(
|
||||
// Identification
|
||||
//
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -3,7 +3,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-incident-mgmt-itil/2.0.0',
|
||||
'itop-incident-mgmt-itil/2.1.0',
|
||||
array(
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0">
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.1">
|
||||
<classes>
|
||||
<class id="KnownError" _delta="define">
|
||||
<parent>cmdbAbstractObject</parent>
|
||||
@@ -81,10 +81,10 @@
|
||||
</field>
|
||||
<field id="domain" xsi:type="AttributeEnum">
|
||||
<values>
|
||||
<value>Network</value>
|
||||
<value>Server</value>
|
||||
<value>Application</value>
|
||||
<value>Desktop</value>
|
||||
<value id="Network">Network</value>
|
||||
<value id="Server">Server</value>
|
||||
<value id="Application">Application</value>
|
||||
<value id="Desktop">Desktop</value>
|
||||
</values>
|
||||
<sql>domain</sql>
|
||||
<default_value>Application</default_value>
|
||||
@@ -573,7 +573,7 @@
|
||||
<menu id="Problem:Shortcuts" xsi:type="TemplateMenuNode" _delta="define_if_not_exists">
|
||||
<rank>5</rank>
|
||||
<parent>ProblemManagement</parent>
|
||||
<template_file />
|
||||
<template_file/>
|
||||
</menu>
|
||||
<menu id="NewError" xsi:type="NewObjectMenuNode" _delta="define">
|
||||
<rank>3</rank>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-knownerror-mgmt/2.0.0',
|
||||
'itop-knownerror-mgmt/2.1.0',
|
||||
array(
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0">
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.1">
|
||||
<classes>
|
||||
<class id="Problem" _delta="define">
|
||||
<parent>Ticket</parent>
|
||||
@@ -38,10 +38,10 @@
|
||||
<fields>
|
||||
<field id="status" xsi:type="AttributeEnum">
|
||||
<values>
|
||||
<value>new</value>
|
||||
<value>assigned</value>
|
||||
<value>resolved</value>
|
||||
<value>closed</value>
|
||||
<value id="new">new</value>
|
||||
<value id="assigned">assigned</value>
|
||||
<value id="resolved">resolved</value>
|
||||
<value id="closed">closed</value>
|
||||
</values>
|
||||
<sql>status</sql>
|
||||
<default_value>new</default_value>
|
||||
@@ -57,7 +57,7 @@
|
||||
<target_class>Service</target_class>
|
||||
<is_null_allowed>true</is_null_allowed>
|
||||
<on_target_delete>DEL_MANUAL</on_target_delete>
|
||||
<allow_target_creation>false</allow_target_creation>
|
||||
<allow_target_creation>false</allow_target_creation>
|
||||
</field>
|
||||
<field id="service_name" xsi:type="AttributeExternalField">
|
||||
<extkey_attcode>service_id</extkey_attcode>
|
||||
@@ -72,7 +72,7 @@
|
||||
<target_class>ServiceSubcategory</target_class>
|
||||
<is_null_allowed>true</is_null_allowed>
|
||||
<on_target_delete>DEL_MANUAL</on_target_delete>
|
||||
<allow_target_creation>false</allow_target_creation>
|
||||
<allow_target_creation>false</allow_target_creation>
|
||||
</field>
|
||||
<field id="servicesubcategory_name" xsi:type="AttributeExternalField">
|
||||
<extkey_attcode>servicesubcategory_id</extkey_attcode>
|
||||
@@ -85,9 +85,9 @@
|
||||
</field>
|
||||
<field id="impact" xsi:type="AttributeEnum">
|
||||
<values>
|
||||
<value>1</value>
|
||||
<value>2</value>
|
||||
<value>3</value>
|
||||
<value id="1">1</value>
|
||||
<value id="2">2</value>
|
||||
<value id="3">3</value>
|
||||
</values>
|
||||
<sql>impact</sql>
|
||||
<default_value>1</default_value>
|
||||
@@ -96,10 +96,10 @@
|
||||
</field>
|
||||
<field id="urgency" xsi:type="AttributeEnum">
|
||||
<values>
|
||||
<value>1</value>
|
||||
<value>2</value>
|
||||
<value>3</value>
|
||||
<value>4</value>
|
||||
<value id="1">1</value>
|
||||
<value id="2">2</value>
|
||||
<value id="3">3</value>
|
||||
<value id="4">4</value>
|
||||
</values>
|
||||
<sql>urgency</sql>
|
||||
<default_value>1</default_value>
|
||||
@@ -108,10 +108,10 @@
|
||||
</field>
|
||||
<field id="priority" xsi:type="AttributeEnum">
|
||||
<values>
|
||||
<value>1</value>
|
||||
<value>2</value>
|
||||
<value>3</value>
|
||||
<value>4</value>
|
||||
<value id="1">1</value>
|
||||
<value id="2">2</value>
|
||||
<value id="3">3</value>
|
||||
<value id="4">4</value>
|
||||
</values>
|
||||
<sql>priority</sql>
|
||||
<default_value>1</default_value>
|
||||
@@ -169,7 +169,7 @@
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="org_id">
|
||||
<must_change/>
|
||||
<must_prompt/>
|
||||
</attribute>
|
||||
<attribute id="team_id">
|
||||
<hidden/>
|
||||
@@ -178,7 +178,7 @@
|
||||
<hidden/>
|
||||
</attribute>
|
||||
<attribute id="description">
|
||||
<must_change/>
|
||||
<must_prompt/>
|
||||
</attribute>
|
||||
<attribute id="start_date">
|
||||
<read_only/>
|
||||
@@ -199,10 +199,10 @@
|
||||
<normal/>
|
||||
</attribute>
|
||||
<attribute id="impact">
|
||||
<must_change/>
|
||||
<must_prompt/>
|
||||
</attribute>
|
||||
<attribute id="urgency">
|
||||
<must_change/>
|
||||
<must_prompt/>
|
||||
</attribute>
|
||||
<attribute id="priority">
|
||||
<read_only/>
|
||||
@@ -218,8 +218,7 @@
|
||||
</attribute>
|
||||
</flags>
|
||||
<transitions>
|
||||
<transition>
|
||||
<stimulus>ev_assign</stimulus>
|
||||
<transition id="ev_assign">
|
||||
<target>assigned</target>
|
||||
<actions>
|
||||
<action>
|
||||
@@ -230,13 +229,9 @@
|
||||
</transitions>
|
||||
</state>
|
||||
<state id="assigned">
|
||||
<inherit_flags_from>new</inherit_flags_from>
|
||||
<flags>
|
||||
<attribute id="ref">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="org_id">
|
||||
<normal/>
|
||||
</attribute>
|
||||
<attribute id="title"/>
|
||||
<attribute id="team_id">
|
||||
<mandatory/>
|
||||
<must_prompt/>
|
||||
@@ -245,39 +240,22 @@
|
||||
<mandatory/>
|
||||
<must_prompt/>
|
||||
</attribute>
|
||||
<attribute id="title">
|
||||
<normal/>
|
||||
</attribute>
|
||||
<attribute id="description">
|
||||
<normal/>
|
||||
</attribute>
|
||||
<attribute id="start_date">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="last_update">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="close_date">
|
||||
<hidden/>
|
||||
</attribute>
|
||||
<attribute id="priority">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="assignment_date">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="resolution_date">
|
||||
<hidden/>
|
||||
</attribute>
|
||||
<attribute id="service_id"/>
|
||||
<attribute id="servicesubcategory_id"/>
|
||||
<attribute id="product"/>
|
||||
<attribute id="impact"/>
|
||||
<attribute id="urgency"/>
|
||||
<attribute id="related_change_id"/>
|
||||
</flags>
|
||||
<transitions>
|
||||
<transition>
|
||||
<stimulus>ev_reassign</stimulus>
|
||||
<transition id="ev_reassign">
|
||||
<target>assigned</target>
|
||||
<actions/>
|
||||
</transition>
|
||||
<transition>
|
||||
<stimulus>ev_resolve</stimulus>
|
||||
<transition id="ev_resolve">
|
||||
<target>resolved</target>
|
||||
<actions>
|
||||
<action>
|
||||
@@ -288,37 +266,11 @@
|
||||
</transitions>
|
||||
</state>
|
||||
<state id="resolved">
|
||||
<inherit_flags_from>assigned</inherit_flags_from>
|
||||
<flags>
|
||||
<attribute id="ref">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="org_id">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="team_id">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="agent_id">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="caller_id">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="title">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="description">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="start_date">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="last_update">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="close_date">
|
||||
<hidden/>
|
||||
</attribute>
|
||||
<attribute id="service_id">
|
||||
<mandatory/>
|
||||
</attribute>
|
||||
@@ -334,24 +286,28 @@
|
||||
<attribute id="urgency">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="priority">
|
||||
<attribute id="org_id">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="assignment_date">
|
||||
<attribute id="team_id">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="resolution_date">
|
||||
<hidden/>
|
||||
<attribute id="agent_id">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="title">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="description">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
</flags>
|
||||
<transitions>
|
||||
<transition>
|
||||
<stimulus>ev_reassign</stimulus>
|
||||
<transition id="ev_reassign">
|
||||
<target>assigned</target>
|
||||
<actions/>
|
||||
</transition>
|
||||
<transition>
|
||||
<stimulus>ev_close</stimulus>
|
||||
<transition id="ev_close">
|
||||
<target>closed</target>
|
||||
<actions>
|
||||
<action>
|
||||
@@ -362,40 +318,17 @@
|
||||
</transitions>
|
||||
</state>
|
||||
<state id="closed">
|
||||
<inherit_flags_from>resolved</inherit_flags_from>
|
||||
<flags>
|
||||
<attribute id="ref">
|
||||
<attribute id="private_log">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="org_id">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="team_id">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="agent_id">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="caller_id">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="title">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="description">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="start_date">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="last_update">
|
||||
<attribute id="related_change_id">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="close_date">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="private_log">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="service_id">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
@@ -405,24 +338,6 @@
|
||||
<attribute id="product">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="impact">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="urgency">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="priority">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="assignment_date">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
<attribute id="resolution_date">
|
||||
<hidden/>
|
||||
</attribute>
|
||||
<attribute id="related_change_id">
|
||||
<read_only/>
|
||||
</attribute>
|
||||
</flags>
|
||||
<transitions/>
|
||||
</state>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-problem-mgmt/2.0.0',
|
||||
'itop-problem-mgmt/2.1.0',
|
||||
array(
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0">
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.1">
|
||||
<classes/>
|
||||
<user_rights>
|
||||
<groups>
|
||||
@@ -8,17 +8,11 @@
|
||||
<class id="Organization"/>
|
||||
<class id="Location"/>
|
||||
<class id="Contact"/>
|
||||
<class id="Person"/>
|
||||
<class id="Team"/>
|
||||
<class id="lnkPersonToTeam"/>
|
||||
</classes>
|
||||
</group>
|
||||
<group id="Documentation" _delta="define">
|
||||
<classes>
|
||||
<class id="Document"/>
|
||||
<class id="WebDoc"/>
|
||||
<class id="Note"/>
|
||||
<class id="FileDoc"/>
|
||||
</classes>
|
||||
</group>
|
||||
<group id="Configuration" _delta="define">
|
||||
@@ -27,76 +21,30 @@
|
||||
<class id="Subnet"/>
|
||||
<class id="Patch"/>
|
||||
<class id="Software"/>
|
||||
<class id="Application"/>
|
||||
<class id="DBServer"/>
|
||||
<class id="lnkPatchToCI"/>
|
||||
<class id="FunctionalCI"/>
|
||||
<class id="SoftwareInstance"/>
|
||||
<class id="DBServerInstance"/>
|
||||
<class id="ApplicationInstance"/>
|
||||
<class id="DatabaseInstance"/>
|
||||
<class id="ApplicationSolution"/>
|
||||
<class id="BusinessProcess"/>
|
||||
<class id="ConnectableCI"/>
|
||||
<class id="NetworkInterface"/>
|
||||
<class id="Device"/>
|
||||
<class id="PC"/>
|
||||
<class id="MobileCI"/>
|
||||
<class id="MobilePhone"/>
|
||||
<class id="InfrastructureCI"/>
|
||||
<class id="NetworkDevice"/>
|
||||
<class id="Server"/>
|
||||
<class id="Printer"/>
|
||||
<class id="Group"/>
|
||||
<class id="lnkDocumentToLicence"/>
|
||||
<class id="Typology"/>
|
||||
<class id="NASFileSystem"/>
|
||||
<class id="LogicalVolume"/>
|
||||
<class id="Tape"/>
|
||||
<class id="VLAN"/>
|
||||
<class id="lnkPhysicalInterfaceToVLAN"/>
|
||||
<class id="lnkSubnetToVLAN"/>
|
||||
<class id="lnkApplicationSolutionToBusinessProcess"/>
|
||||
<class id="lnkApplicationSolutionToFunctionalCI"/>
|
||||
<class id="lnkConnectableCIToNetworkDevice"/>
|
||||
<class id="lnkContactToFunctionalCI"/>
|
||||
<class id="lnkDocumentToFunctionalCI"/>
|
||||
<class id="lnkDocumentToLicence"/>
|
||||
<class id="lnkDocumentToPatch"/>
|
||||
<class id="lnkDocumentToSoftware"/>
|
||||
<class id="lnkFunctionalCIToOSPatch"/>
|
||||
<class id="lnkGroupToCI"/>
|
||||
<class id="lnkSanToDatacenterDevice"/>
|
||||
<class id="lnkServerToVolume"/>
|
||||
<class id="lnkVirtualDeviceToVolume"/>
|
||||
<class id="lnkSoftwareInstanceToSoftwarePatch"/>
|
||||
</classes>
|
||||
</group>
|
||||
<group id="Incident" _delta="define">
|
||||
<classes>
|
||||
<class id="lnkTicketToDoc"/>
|
||||
<class id="lnkTicketToContact"/>
|
||||
<class id="lnkTicketToCI"/>
|
||||
<class id="Incident"/>
|
||||
<class id="lnkTicketToIncident"/>
|
||||
</classes>
|
||||
</group>
|
||||
<group id="Problem" _delta="define">
|
||||
<classes>
|
||||
<class id="lnkTicketToDoc"/>
|
||||
<class id="lnkTicketToContact"/>
|
||||
<class id="lnkTicketToCI"/>
|
||||
<class id="Problem"/>
|
||||
</classes>
|
||||
</group>
|
||||
<group id="Change" _delta="define">
|
||||
<classes>
|
||||
<class id="lnkTicketToDoc"/>
|
||||
<class id="lnkTicketToContact"/>
|
||||
<class id="lnkTicketToCI"/>
|
||||
<class id="Change"/>
|
||||
<class id="RoutineChange"/>
|
||||
<class id="ApprovedChange"/>
|
||||
<class id="NormalChange"/>
|
||||
<class id="EmergencyChange"/>
|
||||
</classes>
|
||||
@@ -106,107 +54,44 @@
|
||||
<class id="Contract"/>
|
||||
<class id="ProviderContract"/>
|
||||
<class id="CustomerContract"/>
|
||||
<class id="lnkCustomerContractToProviderContract"/>
|
||||
<class id="lnkCustomerContractToFunctionalCI"/>
|
||||
<class id="ServiceFamily"/>
|
||||
<class id="Service"/>
|
||||
<class id="ServiceSubcategory"/>
|
||||
<class id="SLA"/>
|
||||
<class id="SLT"/>
|
||||
<class id="DeliveryModel"/>
|
||||
<class id="lnkContactToContract"/>
|
||||
<class id="lnkContactToService"/>
|
||||
<class id="lnkContractToDocument"/>
|
||||
<class id="lnkCustomerContractToService"/>
|
||||
<class id="lnkDeliveryModelToContact"/>
|
||||
<class id="lnkDocumentToService"/>
|
||||
<class id="lnkFunctionalCIToProviderContract"/>
|
||||
<class id="lnkFunctionalCIToService"/>
|
||||
<class id="lnkProviderContractToService"/>
|
||||
<class id="lnkSLAToSLT"/>
|
||||
</classes>
|
||||
</group>
|
||||
<group id="Call" _delta="define">
|
||||
<group id="UserRequest" _delta="define">
|
||||
<classes>
|
||||
<class id="UserRequest"/>
|
||||
<class id="lnkFunctionalCIToTicket"/>
|
||||
<class id="lnkContactToTicket"/>
|
||||
</classes>
|
||||
</group>
|
||||
<group id="KnownError" _delta="define">
|
||||
<classes>
|
||||
<class id="KnownError"/>
|
||||
<class id="lnkErrorToFunctionalCI"/>
|
||||
<class id="lnkDocumentToError"/>
|
||||
<class id="FAQ"/>
|
||||
<class id="FAQCategory"/>
|
||||
<class id="FAQCategory"/>
|
||||
</classes>
|
||||
</group>
|
||||
<group id="LnkTickets" _delta="define">
|
||||
<group id="Ticketing" _delta="define">
|
||||
<classes>
|
||||
<class id="lnkFunctionalCIToTicket"/>
|
||||
<class id="lnkContactToTicket"/>
|
||||
<class id="WorkOrder"/>
|
||||
</classes>
|
||||
</group>
|
||||
<group id="LnkServices" _delta="define">
|
||||
<classes>
|
||||
<class id="lnkContactToContract"/>
|
||||
<class id="lnkContactToService"/>
|
||||
<class id="lnkContractToDocument"/>
|
||||
<class id="lnkCustomerContractToService"/>
|
||||
<class id="lnkDeliveryModelToContact"/>
|
||||
<class id="lnkDocumentToService"/>
|
||||
<class id="lnkFunctionalCIToProviderContract"/>
|
||||
<class id="lnkFunctionalCIToService"/>
|
||||
<class id="lnkProviderContractToService"/>
|
||||
<class id="lnkSLAToSLT"/>
|
||||
</classes>
|
||||
</group>
|
||||
<group id="LnkKnownErrors" _delta="define">
|
||||
<classes>
|
||||
<class id="lnkErrorToFunctionalCI"/>
|
||||
<class id="lnkDocumentToError"/>
|
||||
</classes>
|
||||
</group>
|
||||
<group id="Portal user - write" _delta="define">
|
||||
<classes>
|
||||
<class id="FileDoc"/>
|
||||
<class id="lnkTicketToDoc"/>
|
||||
<class id="UserRequest"/>
|
||||
</classes>
|
||||
</group>
|
||||
<group id="Portal user - delete" _delta="define">
|
||||
<classes>
|
||||
<class id="lnkTicketToDoc"/>
|
||||
</classes>
|
||||
</group>
|
||||
<group id="class:UserRequest" _delta="define">
|
||||
<classes>
|
||||
<class id="UserRequest"/>
|
||||
</classes>
|
||||
</group>
|
||||
<group id="class:Incident" _delta="define">
|
||||
<classes>
|
||||
<class id="Incident"/>
|
||||
</classes>
|
||||
</group>
|
||||
<group id="class:Problem" _delta="define">
|
||||
<classes>
|
||||
<class id="Problem"/>
|
||||
</classes>
|
||||
</group>
|
||||
<group id="class:NormalChange" _delta="define">
|
||||
<group id="NormalChange" _delta="define">
|
||||
<classes>
|
||||
<class id="NormalChange"/>
|
||||
</classes>
|
||||
</group>
|
||||
<group id="class:EmergencyChange" _delta="define">
|
||||
<group id="EmergencyChange" _delta="define">
|
||||
<classes>
|
||||
<class id="EmergencyChange"/>
|
||||
</classes>
|
||||
</group>
|
||||
<group id="class:RoutineChange" _delta="define">
|
||||
<group id="RoutineChange" _delta="define">
|
||||
<classes>
|
||||
<class id="RoutineChange"/>
|
||||
</classes>
|
||||
@@ -219,29 +104,29 @@
|
||||
<groups>
|
||||
<group id="General">
|
||||
<actions>
|
||||
<action xsi:type="write">allow</action>
|
||||
<action xsi:type="bulk write">allow</action>
|
||||
<action xsi:type="delete">allow</action>
|
||||
<action id="action:write">allow</action>
|
||||
<action id="action:bulk write">allow</action>
|
||||
<action id="action:delete">allow</action>
|
||||
</actions>
|
||||
</group>
|
||||
<group id="Documentation">
|
||||
<actions>
|
||||
<action xsi:type="write">allow</action>
|
||||
<action xsi:type="bulk write">allow</action>
|
||||
<action xsi:type="delete">allow</action>
|
||||
<action id="action:write">allow</action>
|
||||
<action id="action:bulk write">allow</action>
|
||||
<action id="action:delete">allow</action>
|
||||
</actions>
|
||||
</group>
|
||||
<group id="Configuration">
|
||||
<actions>
|
||||
<action xsi:type="write">allow</action>
|
||||
<action xsi:type="bulk write">allow</action>
|
||||
<action xsi:type="delete">allow</action>
|
||||
<action id="action:write">allow</action>
|
||||
<action id="action:bulk write">allow</action>
|
||||
<action id="action:delete">allow</action>
|
||||
</actions>
|
||||
</group>
|
||||
<group id="*">
|
||||
<actions>
|
||||
<action xsi:type="read">allow</action>
|
||||
<action xsi:type="bulk read">allow</action>
|
||||
<action id="action:read">allow</action>
|
||||
<action id="action:bulk read">allow</action>
|
||||
</actions>
|
||||
</group>
|
||||
</groups>
|
||||
@@ -250,40 +135,32 @@
|
||||
<name>Service Desk Agent</name>
|
||||
<description>Person in charge of creating incident reports</description>
|
||||
<groups>
|
||||
<group id="Ticketing">
|
||||
<actions>
|
||||
<action id="action:delete">allow</action>
|
||||
<action id="action:write">allow</action>
|
||||
<action id="action:bulk write">allow</action>
|
||||
<action id="stimulus:ev_close">allow</action>
|
||||
</actions>
|
||||
</group>
|
||||
<group id="Incident">
|
||||
<actions>
|
||||
<action xsi:type="write">allow</action>
|
||||
<action xsi:type="bulk write">allow</action>
|
||||
<action id="action:write">allow</action>
|
||||
<action id="action:bulk write">allow</action>
|
||||
<action id="stimulus:ev_assign">allow</action>
|
||||
</actions>
|
||||
</group>
|
||||
<group id="Call">
|
||||
<group id="UserRequest">
|
||||
<actions>
|
||||
<action xsi:type="write">allow</action>
|
||||
<action xsi:type="bulk write">allow</action>
|
||||
</actions>
|
||||
</group>
|
||||
<group id="LnkTickets">
|
||||
<actions>
|
||||
<action xsi:type="delete">allow</action>
|
||||
<action xsi:type="write">allow</action>
|
||||
<action xsi:type="bulk write">allow</action>
|
||||
<action id="ev_close" xsi:type="stimulus">allow</action>
|
||||
</actions>
|
||||
</group>
|
||||
<group id="class:Incident">
|
||||
<actions>
|
||||
<action id="ev_assign" xsi:type="stimulus">allow</action>
|
||||
</actions>
|
||||
</group>
|
||||
<group id="class:UserRequest">
|
||||
<actions>
|
||||
<action id="ev_assign" xsi:type="stimulus">allow</action>
|
||||
<action id="action:write">allow</action>
|
||||
<action id="action:bulk write">allow</action>
|
||||
<action id="stimulus:ev_assign">allow</action>
|
||||
</actions>
|
||||
</group>
|
||||
<group id="*">
|
||||
<actions>
|
||||
<action xsi:type="read">allow</action>
|
||||
<action xsi:type="bulk read">allow</action>
|
||||
<action id="action:read">allow</action>
|
||||
<action id="action:bulk read">allow</action>
|
||||
</actions>
|
||||
</group>
|
||||
</groups>
|
||||
@@ -292,49 +169,41 @@
|
||||
<name>Support Agent</name>
|
||||
<description>Person analyzing and solving the current incidents</description>
|
||||
<groups>
|
||||
<group id="Ticketing">
|
||||
<actions>
|
||||
<action id="action:delete">allow</action>
|
||||
<action id="action:write">allow</action>
|
||||
<action id="action:bulk write">allow</action>
|
||||
<action id="stimulus:ev_close">allow</action>
|
||||
</actions>
|
||||
</group>
|
||||
<group id="Incident">
|
||||
<actions>
|
||||
<action xsi:type="write">allow</action>
|
||||
<action xsi:type="bulk write">allow</action>
|
||||
<action id="action:write">allow</action>
|
||||
<action id="action:bulk write">allow</action>
|
||||
<action id="stimulus:ev_assign">allow</action>
|
||||
<action id="stimulus:ev_reassign">allow</action>
|
||||
<action id="stimulus:ev_resolve">allow</action>
|
||||
<action id="stimulus:ev_close">allow</action>
|
||||
<action id="stimulus:ev_pending">allow</action>
|
||||
</actions>
|
||||
</group>
|
||||
<group id="Call">
|
||||
<group id="UserRequest">
|
||||
<actions>
|
||||
<action xsi:type="write">allow</action>
|
||||
<action xsi:type="bulk write">allow</action>
|
||||
</actions>
|
||||
</group>
|
||||
<group id="LnkTickets">
|
||||
<actions>
|
||||
<action xsi:type="delete">allow</action>
|
||||
<action xsi:type="write">allow</action>
|
||||
<action xsi:type="bulk write">allow</action>
|
||||
<action id="ev_close" xsi:type="stimulus">allow</action>
|
||||
</actions>
|
||||
</group>
|
||||
<group id="class:Incident">
|
||||
<actions>
|
||||
<action id="ev_assign" xsi:type="stimulus">allow</action>
|
||||
<action id="ev_reassign" xsi:type="stimulus">allow</action>
|
||||
<action id="ev_resolve" xsi:type="stimulus">allow</action>
|
||||
<action id="ev_close" xsi:type="stimulus">allow</action>
|
||||
<action id="ev_pending" xsi:type="stimulus">allow</action>
|
||||
</actions>
|
||||
</group>
|
||||
<group id="class:UserRequest">
|
||||
<actions>
|
||||
<action id="ev_assign" xsi:type="stimulus">allow</action>
|
||||
<action id="ev_reassign" xsi:type="stimulus">allow</action>
|
||||
<action id="ev_resolve" xsi:type="stimulus">allow</action>
|
||||
<action id="ev_close" xsi:type="stimulus">allow</action>
|
||||
<action id="ev_pending" xsi:type="stimulus">allow</action>
|
||||
<action id="ev_wait_for_approval" xsi:type="stimulus">allow</action>
|
||||
<action id="action:write">allow</action>
|
||||
<action id="action:bulk write">allow</action>
|
||||
<action id="stimulus:ev_assign">allow</action>
|
||||
<action id="stimulus:ev_reassign">allow</action>
|
||||
<action id="stimulus:ev_resolve">allow</action>
|
||||
<action id="stimulus:ev_close">allow</action>
|
||||
<action id="stimulus:ev_pending">allow</action>
|
||||
<action id="stimulus:ev_wait_for_approval">allow</action>
|
||||
</actions>
|
||||
</group>
|
||||
<group id="*">
|
||||
<actions>
|
||||
<action xsi:type="read">allow</action>
|
||||
<action xsi:type="bulk read">allow</action>
|
||||
<action id="action:read">allow</action>
|
||||
<action id="action:bulk read">allow</action>
|
||||
</actions>
|
||||
</group>
|
||||
</groups>
|
||||
@@ -343,44 +212,35 @@
|
||||
<name>Problem Manager</name>
|
||||
<description>Person analyzing and solving the current problems</description>
|
||||
<groups>
|
||||
<group id="Problem">
|
||||
<actions>
|
||||
<action xsi:type="write">allow</action>
|
||||
<action xsi:type="bulk write">allow</action>
|
||||
</actions>
|
||||
</group>
|
||||
<group id="KnownError">
|
||||
<actions>
|
||||
<action xsi:type="write">allow</action>
|
||||
<action xsi:type="bulk write">allow</action>
|
||||
<action xsi:type="delete">allow</action>
|
||||
<action id="action:write">allow</action>
|
||||
<action id="action:bulk write">allow</action>
|
||||
<action id="action:delete">allow</action>
|
||||
</actions>
|
||||
</group>
|
||||
<group id="LnkTickets">
|
||||
<group id="Ticketing">
|
||||
<actions>
|
||||
<action xsi:type="delete">allow</action>
|
||||
<action xsi:type="write">allow</action>
|
||||
<action xsi:type="bulk write">allow</action>
|
||||
<action id="ev_close" xsi:type="stimulus">allow</action>
|
||||
<action id="action:delete">allow</action>
|
||||
<action id="action:write">allow</action>
|
||||
<action id="action:bulk write">allow</action>
|
||||
<action id="stimulus:ev_close">allow</action>
|
||||
</actions>
|
||||
</group>
|
||||
<group id="LnkKnownErrors">
|
||||
<group id="Problem">
|
||||
<actions>
|
||||
<action xsi:type="delete">allow</action>
|
||||
</actions>
|
||||
</group>
|
||||
<group id="class:Problem">
|
||||
<actions>
|
||||
<action id="ev_assign" xsi:type="stimulus">allow</action>
|
||||
<action id="ev_reassign" xsi:type="stimulus">allow</action>
|
||||
<action id="ev_resolve" xsi:type="stimulus">allow</action>
|
||||
<action id="ev_close" xsi:type="stimulus">allow</action>
|
||||
<action id="action:write">allow</action>
|
||||
<action id="action:bulk write">allow</action>
|
||||
<action id="stimulus:ev_assign">allow</action>
|
||||
<action id="stimulus:ev_reassign">allow</action>
|
||||
<action id="stimulus:ev_resolve">allow</action>
|
||||
<action id="stimulus:ev_close">allow</action>
|
||||
</actions>
|
||||
</group>
|
||||
<group id="*">
|
||||
<actions>
|
||||
<action xsi:type="read">allow</action>
|
||||
<action xsi:type="bulk read">allow</action>
|
||||
<action id="action:read">allow</action>
|
||||
<action id="action:bulk read">allow</action>
|
||||
</actions>
|
||||
</group>
|
||||
</groups>
|
||||
@@ -391,50 +251,50 @@
|
||||
<groups>
|
||||
<group id="Change">
|
||||
<actions>
|
||||
<action xsi:type="write">allow</action>
|
||||
<action xsi:type="bulk write">allow</action>
|
||||
<action id="ev_assign" xsi:type="stimulus">allow</action>
|
||||
<action id="ev_plan" xsi:type="stimulus">allow</action>
|
||||
<action id="ev_reopen" xsi:type="stimulus">allow</action>
|
||||
<action id="ev_finish" xsi:type="stimulus">allow</action>
|
||||
<action id="action:write">allow</action>
|
||||
<action id="action:bulk write">allow</action>
|
||||
<action id="stimulus:ev_assign">allow</action>
|
||||
<action id="stimulus:ev_plan">allow</action>
|
||||
<action id="stimulus:ev_reopen">allow</action>
|
||||
<action id="stimulus:ev_finish">allow</action>
|
||||
</actions>
|
||||
</group>
|
||||
<group id="LnkTickets">
|
||||
<group id="Ticketing">
|
||||
<actions>
|
||||
<action xsi:type="delete">allow</action>
|
||||
<action xsi:type="write">allow</action>
|
||||
<action xsi:type="bulk write">allow</action>
|
||||
<action id="ev_close" xsi:type="stimulus">allow</action>
|
||||
<action id="action:delete">allow</action>
|
||||
<action id="action:write">allow</action>
|
||||
<action id="action:bulk write">allow</action>
|
||||
<action id="stimulus:ev_close">allow</action>
|
||||
</actions>
|
||||
</group>
|
||||
<group id="class:NormalChange">
|
||||
<group id="NormalChange">
|
||||
<actions>
|
||||
<action id="ev_plan" xsi:type="stimulus">allow</action>
|
||||
<action id="ev_replan" xsi:type="stimulus">allow</action>
|
||||
<action id="ev_implement" xsi:type="stimulus">allow</action>
|
||||
<action id="ev_monitor" xsi:type="stimulus">allow</action>
|
||||
<action id="stimulus:ev_plan">allow</action>
|
||||
<action id="stimulus:ev_replan">allow</action>
|
||||
<action id="stimulus:ev_implement">allow</action>
|
||||
<action id="stimulus:ev_monitor">allow</action>
|
||||
</actions>
|
||||
</group>
|
||||
<group id="class:EmergencyChange">
|
||||
<group id="EmergencyChange">
|
||||
<actions>
|
||||
<action id="ev_plan" xsi:type="stimulus">allow</action>
|
||||
<action id="ev_replan" xsi:type="stimulus">allow</action>
|
||||
<action id="ev_implement" xsi:type="stimulus">allow</action>
|
||||
<action id="ev_monitor" xsi:type="stimulus">allow</action>
|
||||
<action id="stimulus:ev_plan">allow</action>
|
||||
<action id="stimulus:ev_replan">allow</action>
|
||||
<action id="stimulus:ev_implement">allow</action>
|
||||
<action id="stimulus:ev_monitor">allow</action>
|
||||
</actions>
|
||||
</group>
|
||||
<group id="class:RoutineChange">
|
||||
<group id="RoutineChange">
|
||||
<actions>
|
||||
<action id="ev_plan" xsi:type="stimulus">allow</action>
|
||||
<action id="ev_replan" xsi:type="stimulus">allow</action>
|
||||
<action id="ev_implement" xsi:type="stimulus">allow</action>
|
||||
<action id="ev_monitor" xsi:type="stimulus">allow</action>
|
||||
<action id="stimulus:ev_plan">allow</action>
|
||||
<action id="stimulus:ev_replan">allow</action>
|
||||
<action id="stimulus:ev_implement">allow</action>
|
||||
<action id="stimulus:ev_monitor">allow</action>
|
||||
</actions>
|
||||
</group>
|
||||
<group id="*">
|
||||
<actions>
|
||||
<action xsi:type="read">allow</action>
|
||||
<action xsi:type="bulk read">allow</action>
|
||||
<action id="action:read">allow</action>
|
||||
<action id="action:bulk read">allow</action>
|
||||
</actions>
|
||||
</group>
|
||||
</groups>
|
||||
@@ -445,48 +305,48 @@
|
||||
<groups>
|
||||
<group id="Change">
|
||||
<actions>
|
||||
<action xsi:type="write">allow</action>
|
||||
<action xsi:type="bulk write">allow</action>
|
||||
<action id="ev_assign" xsi:type="stimulus">allow</action>
|
||||
<action id="ev_reopen" xsi:type="stimulus">allow</action>
|
||||
<action id="ev_finish" xsi:type="stimulus">allow</action>
|
||||
<action id="action:write">allow</action>
|
||||
<action id="action:bulk write">allow</action>
|
||||
<action id="stimulus:ev_assign">allow</action>
|
||||
<action id="stimulus:ev_reopen">allow</action>
|
||||
<action id="stimulus:ev_finish">allow</action>
|
||||
</actions>
|
||||
</group>
|
||||
<group id="LnkTickets">
|
||||
<group id="Ticketing">
|
||||
<actions>
|
||||
<action xsi:type="delete">allow</action>
|
||||
<action xsi:type="write">allow</action>
|
||||
<action xsi:type="bulk write">allow</action>
|
||||
<action id="ev_close" xsi:type="stimulus">allow</action>
|
||||
<action id="action:delete">allow</action>
|
||||
<action id="action:write">allow</action>
|
||||
<action id="action:bulk write">allow</action>
|
||||
<action id="stimulus:ev_close">allow</action>
|
||||
</actions>
|
||||
</group>
|
||||
<group id="class:NormalChange">
|
||||
<group id="NormalChange">
|
||||
<actions>
|
||||
<action id="ev_validate" xsi:type="stimulus">allow</action>
|
||||
<action id="ev_reject" xsi:type="stimulus">allow</action>
|
||||
<action id="ev_assign" xsi:type="stimulus">allow</action>
|
||||
<action id="ev_reopen" xsi:type="stimulus">allow</action>
|
||||
<action id="ev_finish" xsi:type="stimulus">allow</action>
|
||||
<action id="stimulus:ev_validate">allow</action>
|
||||
<action id="stimulus:ev_reject">allow</action>
|
||||
<action id="stimulus:ev_assign">allow</action>
|
||||
<action id="stimulus:ev_reopen">allow</action>
|
||||
<action id="stimulus:ev_finish">allow</action>
|
||||
</actions>
|
||||
</group>
|
||||
<group id="class:EmergencyChange">
|
||||
<group id="EmergencyChange">
|
||||
<actions>
|
||||
<action id="ev_assign" xsi:type="stimulus">allow</action>
|
||||
<action id="ev_reopen" xsi:type="stimulus">allow</action>
|
||||
<action id="ev_finish" xsi:type="stimulus">allow</action>
|
||||
<action id="stimulus:ev_assign">allow</action>
|
||||
<action id="stimulus:ev_reopen">allow</action>
|
||||
<action id="stimulus:ev_finish">allow</action>
|
||||
</actions>
|
||||
</group>
|
||||
<group id="class:RoutineChange">
|
||||
<group id="RoutineChange">
|
||||
<actions>
|
||||
<action id="ev_assign" xsi:type="stimulus">allow</action>
|
||||
<action id="ev_reopen" xsi:type="stimulus">allow</action>
|
||||
<action id="ev_finish" xsi:type="stimulus">allow</action>
|
||||
<action id="stimulus:ev_assign">allow</action>
|
||||
<action id="stimulus:ev_reopen">allow</action>
|
||||
<action id="stimulus:ev_finish">allow</action>
|
||||
</actions>
|
||||
</group>
|
||||
<group id="*">
|
||||
<actions>
|
||||
<action xsi:type="read">allow</action>
|
||||
<action xsi:type="bulk read">allow</action>
|
||||
<action id="action:read">allow</action>
|
||||
<action id="action:bulk read">allow</action>
|
||||
</actions>
|
||||
</group>
|
||||
</groups>
|
||||
@@ -497,39 +357,39 @@
|
||||
<groups>
|
||||
<group id="Change">
|
||||
<actions>
|
||||
<action xsi:type="write">allow</action>
|
||||
<action xsi:type="bulk write">allow</action>
|
||||
<action id="ev_approve" xsi:type="stimulus">allow</action>
|
||||
<action id="ev_reject" xsi:type="stimulus">allow</action>
|
||||
<action id="action:write">allow</action>
|
||||
<action id="action:bulk write">allow</action>
|
||||
<action id="stimulus:ev_approve">allow</action>
|
||||
<action id="stimulus:ev_reject">allow</action>
|
||||
</actions>
|
||||
</group>
|
||||
<group id="LnkTickets">
|
||||
<group id="Ticketing">
|
||||
<actions>
|
||||
<action xsi:type="delete">allow</action>
|
||||
<action xsi:type="write">allow</action>
|
||||
<action xsi:type="bulk write">allow</action>
|
||||
<action id="ev_close" xsi:type="stimulus">allow</action>
|
||||
<action id="action:delete">allow</action>
|
||||
<action id="action:write">allow</action>
|
||||
<action id="action:bulk write">allow</action>
|
||||
<action id="stimulus:ev_close">allow</action>
|
||||
</actions>
|
||||
</group>
|
||||
<group id="class:NormalChange">
|
||||
<group id="NormalChange">
|
||||
<actions>
|
||||
<action id="ev_approve" xsi:type="stimulus">allow</action>
|
||||
<action id="ev_notapprove" xsi:type="stimulus">allow</action>
|
||||
<action id="stimulus:ev_approve">allow</action>
|
||||
<action id="stimulus:ev_notapprove">allow</action>
|
||||
</actions>
|
||||
</group>
|
||||
<group id="class:EmergencyChange">
|
||||
<group id="EmergencyChange">
|
||||
<actions>
|
||||
<action id="ev_approve" xsi:type="stimulus">allow</action>
|
||||
<action id="ev_notapprove" xsi:type="stimulus">allow</action>
|
||||
<action id="stimulus:ev_approve">allow</action>
|
||||
<action id="stimulus:ev_notapprove">allow</action>
|
||||
</actions>
|
||||
</group>
|
||||
<group id="class:RoutineChange">
|
||||
<group id="RoutineChange">
|
||||
<actions/>
|
||||
</group>
|
||||
<group id="*">
|
||||
<actions>
|
||||
<action xsi:type="read">allow</action>
|
||||
<action xsi:type="bulk read">allow</action>
|
||||
<action id="action:read">allow</action>
|
||||
<action id="action:bulk read">allow</action>
|
||||
</actions>
|
||||
</group>
|
||||
</groups>
|
||||
@@ -540,20 +400,15 @@
|
||||
<groups>
|
||||
<group id="Service">
|
||||
<actions>
|
||||
<action xsi:type="write">allow</action>
|
||||
<action xsi:type="bulk write">allow</action>
|
||||
<action xsi:type="delete">allow</action>
|
||||
</actions>
|
||||
</group>
|
||||
<group id="LnkServices">
|
||||
<actions>
|
||||
<action xsi:type="delete">allow</action>
|
||||
<action id="action:write">allow</action>
|
||||
<action id="action:bulk write">allow</action>
|
||||
<action id="action:delete">allow</action>
|
||||
</actions>
|
||||
</group>
|
||||
<group id="*">
|
||||
<actions>
|
||||
<action xsi:type="read">allow</action>
|
||||
<action xsi:type="bulk read">allow</action>
|
||||
<action id="action:read">allow</action>
|
||||
<action id="action:bulk read">allow</action>
|
||||
</actions>
|
||||
</group>
|
||||
</groups>
|
||||
@@ -564,15 +419,15 @@
|
||||
<groups>
|
||||
<group id="Documentation">
|
||||
<actions>
|
||||
<action xsi:type="write">allow</action>
|
||||
<action xsi:type="bulk write">allow</action>
|
||||
<action xsi:type="delete">allow</action>
|
||||
<action id="action:write">allow</action>
|
||||
<action id="action:bulk write">allow</action>
|
||||
<action id="action:delete">allow</action>
|
||||
</actions>
|
||||
</group>
|
||||
<group id="*">
|
||||
<actions>
|
||||
<action xsi:type="read">allow</action>
|
||||
<action xsi:type="bulk read">allow</action>
|
||||
<action id="action:read">allow</action>
|
||||
<action id="action:bulk read">allow</action>
|
||||
</actions>
|
||||
</group>
|
||||
</groups>
|
||||
@@ -581,26 +436,17 @@
|
||||
<name>Portal user</name>
|
||||
<description>Has the rights to access to the user portal. People having this profile will not be allowed to access the standard application, they will be automatically redirected to the user portal.</description>
|
||||
<groups>
|
||||
<group id="Portal user - write">
|
||||
<group id="UserRequest">
|
||||
<actions>
|
||||
<action xsi:type="write">allow</action>
|
||||
</actions>
|
||||
</group>
|
||||
<group id="Portal user - delete">
|
||||
<actions>
|
||||
<action xsi:type="delete">allow</action>
|
||||
</actions>
|
||||
</group>
|
||||
<group id="class:UserRequest">
|
||||
<actions>
|
||||
<action id="ev_close" xsi:type="stimulus">allow</action>
|
||||
<action id="ev_reopen" xsi:type="stimulus">allow</action>
|
||||
<action id="action:write">allow</action>
|
||||
<action id="stimulus:ev_close">allow</action>
|
||||
<action id="stimulus:ev_reopen">allow</action>
|
||||
</actions>
|
||||
</group>
|
||||
<group id="*">
|
||||
<actions>
|
||||
<action xsi:type="read">allow</action>
|
||||
<action xsi:type="bulk read">allow</action>
|
||||
<action id="action:read">allow</action>
|
||||
<action id="action:bulk read">allow</action>
|
||||
</actions>
|
||||
</group>
|
||||
</groups>
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-profiles-itil/1.0.0',
|
||||
'itop-profiles-itil/2.1.0',
|
||||
array(
|
||||
// Identification
|
||||
//
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -3,7 +3,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-request-mgmt-itil/2.0.0',
|
||||
'itop-request-mgmt-itil/2.1.0',
|
||||
array(
|
||||
// Identification
|
||||
//
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -3,7 +3,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-request-mgmt/2.0.0',
|
||||
'itop-request-mgmt/2.1.0',
|
||||
array(
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0">
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.1">
|
||||
<classes>
|
||||
<class id="Organization">
|
||||
<fields>
|
||||
@@ -18,7 +18,7 @@
|
||||
<presentation>
|
||||
<details>
|
||||
<items>
|
||||
<item id="deliverymodel_id" _delta="define">
|
||||
<item id="deliverymodel_id" _delta="define">
|
||||
<rank>50</rank>
|
||||
</item>
|
||||
</items>
|
||||
@@ -26,7 +26,7 @@
|
||||
</presentation>
|
||||
</class>
|
||||
<class id="Ticket">
|
||||
<fields>
|
||||
<fields>
|
||||
<field id="team_id" xsi:type="AttributeExternalKey" _delta="redefine">
|
||||
<filter><![CDATA[SELECT Team AS t JOIN lnkDeliveryModelToContact AS l1 ON l1.contact_id=t.id JOIN DeliveryModel AS dm ON l1.deliverymodel_id=dm.id JOIN Organization AS o ON o.deliverymodel_id=dm.id WHERE o.id = :this->org_id]]></filter>
|
||||
<dependencies>
|
||||
@@ -36,7 +36,7 @@
|
||||
<target_class>Team</target_class>
|
||||
<is_null_allowed>true</is_null_allowed>
|
||||
<on_target_delete>DEL_AUTO</on_target_delete>
|
||||
<allow_target_creation>false</allow_target_creation>
|
||||
<allow_target_creation>false</allow_target_creation>
|
||||
</field>
|
||||
</fields>
|
||||
</class>
|
||||
@@ -123,8 +123,8 @@
|
||||
</field>
|
||||
<field id="cost_currency" xsi:type="AttributeEnum">
|
||||
<values>
|
||||
<value>dollars</value>
|
||||
<value>euros</value>
|
||||
<value id="dollars">dollars</value>
|
||||
<value id="euros">euros</value>
|
||||
</values>
|
||||
<sql>cost_currency</sql>
|
||||
<default_value/>
|
||||
@@ -163,9 +163,9 @@
|
||||
</field>
|
||||
<field id="status" xsi:type="AttributeEnum">
|
||||
<values>
|
||||
<value>production</value>
|
||||
<value>implementation</value>
|
||||
<value>obsolete</value>
|
||||
<value id="production">production</value>
|
||||
<value id="implementation">implementation</value>
|
||||
<value id="obsolete">obsolete</value>
|
||||
</values>
|
||||
<sql>status</sql>
|
||||
<default_value/>
|
||||
@@ -1069,9 +1069,9 @@
|
||||
</field>
|
||||
<field id="status" xsi:type="AttributeEnum">
|
||||
<values>
|
||||
<value>production</value>
|
||||
<value>implementation</value>
|
||||
<value>obsolete</value>
|
||||
<value id="production">production</value>
|
||||
<value id="implementation">implementation</value>
|
||||
<value id="obsolete">obsolete</value>
|
||||
</values>
|
||||
<sql>status</sql>
|
||||
<default_value/>
|
||||
@@ -1383,8 +1383,8 @@
|
||||
</field>
|
||||
<field id="request_type" xsi:type="AttributeEnum">
|
||||
<values>
|
||||
<value>incident</value>
|
||||
<value>service_request</value>
|
||||
<value id="incident">incident</value>
|
||||
<value id="service_request">service_request</value>
|
||||
</values>
|
||||
<sql>request_type</sql>
|
||||
<default_value>incident</default_value>
|
||||
@@ -1393,9 +1393,9 @@
|
||||
</field>
|
||||
<field id="status" xsi:type="AttributeEnum">
|
||||
<values>
|
||||
<value>production</value>
|
||||
<value>implementation</value>
|
||||
<value>obsolete</value>
|
||||
<value id="production">production</value>
|
||||
<value id="implementation">implementation</value>
|
||||
<value id="obsolete">obsolete</value>
|
||||
</values>
|
||||
<sql>status</sql>
|
||||
<default_value/>
|
||||
@@ -1610,10 +1610,10 @@
|
||||
</field>
|
||||
<field id="priority" xsi:type="AttributeEnum">
|
||||
<values>
|
||||
<value>1</value>
|
||||
<value>2</value>
|
||||
<value>3</value>
|
||||
<value>4</value>
|
||||
<value id="1">1</value>
|
||||
<value id="2">2</value>
|
||||
<value id="3">3</value>
|
||||
<value id="4">4</value>
|
||||
</values>
|
||||
<sql>priority</sql>
|
||||
<default_value/>
|
||||
@@ -1622,8 +1622,8 @@
|
||||
</field>
|
||||
<field id="request_type" xsi:type="AttributeEnum">
|
||||
<values>
|
||||
<value>service_request</value>
|
||||
<value>incident</value>
|
||||
<value id="service_request">service_request</value>
|
||||
<value id="incident">incident</value>
|
||||
</values>
|
||||
<sql>request_type</sql>
|
||||
<default_value/>
|
||||
@@ -1632,8 +1632,8 @@
|
||||
</field>
|
||||
<field id="metric" xsi:type="AttributeEnum">
|
||||
<values>
|
||||
<value>tto</value>
|
||||
<value>ttr</value>
|
||||
<value id="tto">tto</value>
|
||||
<value id="ttr">ttr</value>
|
||||
</values>
|
||||
<sql>metric</sql>
|
||||
<default_value/>
|
||||
@@ -1647,8 +1647,8 @@
|
||||
</field>
|
||||
<field id="unit" xsi:type="AttributeEnum">
|
||||
<values>
|
||||
<value>hours</value>
|
||||
<value>minutes</value>
|
||||
<value id="hours">hours</value>
|
||||
<value id="minutes">minutes</value>
|
||||
</values>
|
||||
<sql>unit</sql>
|
||||
<default_value/>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-service-mgmt-provider/2.0.0',
|
||||
'itop-service-mgmt-provider/2.1.0',
|
||||
array(
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0">
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.1">
|
||||
<classes>
|
||||
<class id="Organization">
|
||||
<fields>
|
||||
@@ -18,7 +18,7 @@
|
||||
<presentation>
|
||||
<details>
|
||||
<items>
|
||||
<item id="deliverymodel_id" _delta="define">
|
||||
<item id="deliverymodel_id" _delta="define">
|
||||
<rank>50</rank>
|
||||
</item>
|
||||
</items>
|
||||
@@ -26,7 +26,7 @@
|
||||
</presentation>
|
||||
</class>
|
||||
<class id="Ticket">
|
||||
<fields>
|
||||
<fields>
|
||||
<field id="team_id" xsi:type="AttributeExternalKey" _delta="redefine">
|
||||
<filter><![CDATA[SELECT Team AS t JOIN lnkDeliveryModelToContact AS l1 ON l1.contact_id=t.id JOIN DeliveryModel AS dm ON l1.deliverymodel_id=dm.id JOIN Organization AS o ON o.deliverymodel_id=dm.id WHERE o.id = :this->org_id]]></filter>
|
||||
<dependencies>
|
||||
@@ -36,7 +36,7 @@
|
||||
<target_class>Team</target_class>
|
||||
<is_null_allowed>true</is_null_allowed>
|
||||
<on_target_delete>DEL_AUTO</on_target_delete>
|
||||
<allow_target_creation>false</allow_target_creation>
|
||||
<allow_target_creation>false</allow_target_creation>
|
||||
</field>
|
||||
</fields>
|
||||
</class>
|
||||
@@ -123,8 +123,8 @@
|
||||
</field>
|
||||
<field id="cost_currency" xsi:type="AttributeEnum">
|
||||
<values>
|
||||
<value>dollars</value>
|
||||
<value>euros</value>
|
||||
<value id="dollars">dollars</value>
|
||||
<value id="euros">euros</value>
|
||||
</values>
|
||||
<sql>cost_currency</sql>
|
||||
<default_value/>
|
||||
@@ -163,9 +163,9 @@
|
||||
</field>
|
||||
<field id="status" xsi:type="AttributeEnum">
|
||||
<values>
|
||||
<value>production</value>
|
||||
<value>implementation</value>
|
||||
<value>obsolete</value>
|
||||
<value id="production">production</value>
|
||||
<value id="implementation">implementation</value>
|
||||
<value id="obsolete">obsolete</value>
|
||||
</values>
|
||||
<sql>status</sql>
|
||||
<default_value/>
|
||||
@@ -1042,9 +1042,9 @@
|
||||
</field>
|
||||
<field id="status" xsi:type="AttributeEnum">
|
||||
<values>
|
||||
<value>production</value>
|
||||
<value>implementation</value>
|
||||
<value>obsolete</value>
|
||||
<value id="production">production</value>
|
||||
<value id="implementation">implementation</value>
|
||||
<value id="obsolete">obsolete</value>
|
||||
</values>
|
||||
<sql>status</sql>
|
||||
<default_value/>
|
||||
@@ -1378,8 +1378,8 @@
|
||||
</field>
|
||||
<field id="request_type" xsi:type="AttributeEnum">
|
||||
<values>
|
||||
<value>incident</value>
|
||||
<value>service_request</value>
|
||||
<value id="incident">incident</value>
|
||||
<value id="service_request">service_request</value>
|
||||
</values>
|
||||
<sql>request_type</sql>
|
||||
<default_value>incident</default_value>
|
||||
@@ -1388,9 +1388,9 @@
|
||||
</field>
|
||||
<field id="status" xsi:type="AttributeEnum">
|
||||
<values>
|
||||
<value>production</value>
|
||||
<value>implementation</value>
|
||||
<value>obsolete</value>
|
||||
<value id="production">production</value>
|
||||
<value id="implementation">implementation</value>
|
||||
<value id="obsolete">obsolete</value>
|
||||
</values>
|
||||
<sql>status</sql>
|
||||
<default_value/>
|
||||
@@ -1605,10 +1605,10 @@
|
||||
</field>
|
||||
<field id="priority" xsi:type="AttributeEnum">
|
||||
<values>
|
||||
<value>1</value>
|
||||
<value>2</value>
|
||||
<value>3</value>
|
||||
<value>4</value>
|
||||
<value id="1">1</value>
|
||||
<value id="2">2</value>
|
||||
<value id="3">3</value>
|
||||
<value id="4">4</value>
|
||||
</values>
|
||||
<sql>priority</sql>
|
||||
<default_value/>
|
||||
@@ -1617,8 +1617,8 @@
|
||||
</field>
|
||||
<field id="request_type" xsi:type="AttributeEnum">
|
||||
<values>
|
||||
<value>service_request</value>
|
||||
<value>incident</value>
|
||||
<value id="service_request">service_request</value>
|
||||
<value id="incident">incident</value>
|
||||
</values>
|
||||
<sql>request_type</sql>
|
||||
<default_value/>
|
||||
@@ -1627,8 +1627,8 @@
|
||||
</field>
|
||||
<field id="metric" xsi:type="AttributeEnum">
|
||||
<values>
|
||||
<value>tto</value>
|
||||
<value>ttr</value>
|
||||
<value id="tto">tto</value>
|
||||
<value id="ttr">ttr</value>
|
||||
</values>
|
||||
<sql>metric</sql>
|
||||
<default_value/>
|
||||
@@ -1642,8 +1642,8 @@
|
||||
</field>
|
||||
<field id="unit" xsi:type="AttributeEnum">
|
||||
<values>
|
||||
<value>hours</value>
|
||||
<value>minutes</value>
|
||||
<value id="hours">hours</value>
|
||||
<value id="minutes">minutes</value>
|
||||
</values>
|
||||
<sql>unit</sql>
|
||||
<default_value/>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-service-mgmt/2.0.0',
|
||||
'itop-service-mgmt/2.1.0',
|
||||
array(
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0">
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.1">
|
||||
<classes>
|
||||
<class id="StorageSystem" _delta="define">
|
||||
<parent>DatacenterDevice</parent>
|
||||
@@ -1757,48 +1757,47 @@
|
||||
</list>
|
||||
</presentation>
|
||||
</class>
|
||||
</classes>
|
||||
<menus>
|
||||
</classes>
|
||||
<menus>
|
||||
<menu id="ConfigManagementOverview" xsi:type="DashboardMenuNode" _delta="must_exist">
|
||||
<rank>1</rank>
|
||||
<parent>ConfigManagement</parent>
|
||||
<definition>
|
||||
<layout>DashboardLayoutOneCol</layout>
|
||||
<title></title>
|
||||
<cells>
|
||||
<cell id="0" _delta="must_exist">
|
||||
<rank>0</rank>
|
||||
<dashlets>
|
||||
<dashlet id="33" xsi:type="DashletBadge" _delta="define">
|
||||
<rank>5</rank>
|
||||
<class>StorageSystem</class>
|
||||
</dashlet>
|
||||
<dashlet id="34" xsi:type="DashletBadge" _delta="define">
|
||||
<rank>6</rank>
|
||||
<class>SANSwitch</class>
|
||||
</dashlet>
|
||||
<dashlet id="35" xsi:type="DashletBadge" _delta="define">
|
||||
<rank>7</rank>
|
||||
<class>NAS</class>
|
||||
</dashlet>
|
||||
<dashlet id="36" xsi:type="DashletBadge" _delta="define">
|
||||
<rank>8</rank>
|
||||
<class>TapeLibrary</class>
|
||||
</dashlet>
|
||||
</dashlets>
|
||||
</cell>
|
||||
<cell id="4" _delta="must_exist">
|
||||
<rank>4</rank>
|
||||
<dashlets>
|
||||
<dashlet id="37" xsi:type="DashletBadge" _delta="define">
|
||||
<rank>3</rank>
|
||||
<class>LogicalVolume</class>
|
||||
</dashlet>
|
||||
</dashlets>
|
||||
</cell>
|
||||
|
||||
</cells>
|
||||
</definition>
|
||||
<layout>DashboardLayoutOneCol</layout>
|
||||
<title/>
|
||||
<cells>
|
||||
<cell id="0" _delta="must_exist">
|
||||
<rank>0</rank>
|
||||
<dashlets>
|
||||
<dashlet id="33" xsi:type="DashletBadge" _delta="define">
|
||||
<rank>5</rank>
|
||||
<class>StorageSystem</class>
|
||||
</dashlet>
|
||||
<dashlet id="34" xsi:type="DashletBadge" _delta="define">
|
||||
<rank>6</rank>
|
||||
<class>SANSwitch</class>
|
||||
</dashlet>
|
||||
<dashlet id="35" xsi:type="DashletBadge" _delta="define">
|
||||
<rank>7</rank>
|
||||
<class>NAS</class>
|
||||
</dashlet>
|
||||
<dashlet id="36" xsi:type="DashletBadge" _delta="define">
|
||||
<rank>8</rank>
|
||||
<class>TapeLibrary</class>
|
||||
</dashlet>
|
||||
</dashlets>
|
||||
</cell>
|
||||
<cell id="4" _delta="must_exist">
|
||||
<rank>4</rank>
|
||||
<dashlets>
|
||||
<dashlet id="37" xsi:type="DashletBadge" _delta="define">
|
||||
<rank>3</rank>
|
||||
<class>LogicalVolume</class>
|
||||
</dashlet>
|
||||
</dashlets>
|
||||
</cell>
|
||||
</cells>
|
||||
</definition>
|
||||
</menu>
|
||||
</menus>
|
||||
</menus>
|
||||
</itop_design>
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-storage-mgmt/2.0.0',
|
||||
'itop-storage-mgmt/2.1.0',
|
||||
array(
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0">
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.1">
|
||||
<constants>
|
||||
<constant id="RESPONSE_TICKET_SLT_QUERY" xsi:type="string" _delta="define"><![CDATA[SELECT SLT AS slt JOIN lnkSLAToSLT AS l1 ON l1.slt_id=slt.id JOIN SLA AS sla ON l1.sla_id=sla.id JOIN lnkCustomerContractToService AS l2 ON l2.sla_id=sla.id JOIN CustomerContract AS sc ON l2.customercontract_id=sc.id WHERE slt.metric = :metric AND l2.service_id = :this->service_id AND sc.org_id = :this->org_id AND slt.request_type = :request_type AND slt.priority = :this->priority]]></constant>
|
||||
<constant id="PORTAL_POWER_USER_PROFILE" xsi:type="string" _delta="define"><![CDATA[Portal power user]]></constant>
|
||||
@@ -93,7 +93,7 @@
|
||||
<target_class>Person</target_class>
|
||||
<is_null_allowed>true</is_null_allowed>
|
||||
<on_target_delete>DEL_AUTO</on_target_delete>
|
||||
<allow_target_creation>false</allow_target_creation>
|
||||
<allow_target_creation>false</allow_target_creation>
|
||||
</field>
|
||||
<field id="agent_name" xsi:type="AttributeExternalField">
|
||||
<extkey_attcode>agent_id</extkey_attcode>
|
||||
@@ -213,7 +213,7 @@
|
||||
}
|
||||
]]></code>
|
||||
</method>
|
||||
</methods>
|
||||
</methods>
|
||||
<presentation>
|
||||
<details>
|
||||
<items>
|
||||
@@ -529,7 +529,6 @@
|
||||
</naming>
|
||||
<display_template/>
|
||||
<icon>images/workorder.png</icon>
|
||||
<icon/>
|
||||
<reconciliation>
|
||||
<attributes>
|
||||
<attribute id="name"/>
|
||||
@@ -545,8 +544,8 @@
|
||||
</field>
|
||||
<field id="status" xsi:type="AttributeEnum">
|
||||
<values>
|
||||
<value>open</value>
|
||||
<value>closed</value>
|
||||
<value id="open">open</value>
|
||||
<value id="closed">closed</value>
|
||||
</values>
|
||||
<sql>status</sql>
|
||||
<default_value>open</default_value>
|
||||
@@ -588,7 +587,7 @@
|
||||
<target_class>Person</target_class>
|
||||
<is_null_allowed>true</is_null_allowed>
|
||||
<on_target_delete>DEL_MANUAL</on_target_delete>
|
||||
<allow_target_creation>false</allow_target_creation>
|
||||
<allow_target_creation>false</allow_target_creation>
|
||||
</field>
|
||||
<field id="agent_email" xsi:type="AttributeExternalField">
|
||||
<extkey_attcode>agent_id</extkey_attcode>
|
||||
@@ -619,8 +618,7 @@
|
||||
<state id="open">
|
||||
<flags/>
|
||||
<transitions>
|
||||
<transition>
|
||||
<stimulus>ev_close</stimulus>
|
||||
<transition id="ev_close">
|
||||
<target>closed</target>
|
||||
<actions/>
|
||||
</transition>
|
||||
@@ -637,6 +635,8 @@
|
||||
<static>false</static>
|
||||
<access>public</access>
|
||||
<type>StimulusUserAction</type>
|
||||
<arguments>
|
||||
</arguments>
|
||||
<code><![CDATA[ public function UpdateParentTicketLog()
|
||||
{
|
||||
$oLog = $this->Get('log');
|
||||
@@ -741,4 +741,67 @@
|
||||
</presentation>
|
||||
</class>
|
||||
</classes>
|
||||
<meta>
|
||||
<classes>
|
||||
<class id="cmdbAbstractObject" _delta="define">
|
||||
<methods>
|
||||
<method id="Set">
|
||||
<arguments>
|
||||
<argument>
|
||||
<label>Field Code</label>
|
||||
<type>attcode</type>
|
||||
<mandatory>true</mandatory>
|
||||
<description>The field to set, in the current object</description>
|
||||
</argument>
|
||||
<argument>
|
||||
<label>Value</label>
|
||||
<type>string</type>
|
||||
<mandatory>true</mandatory>
|
||||
<description>The value to set</description>
|
||||
</argument>
|
||||
</arguments>
|
||||
</method>
|
||||
<method id="SetCurrentDate">
|
||||
<arguments>
|
||||
<argument>
|
||||
<label>Field Code</label>
|
||||
<type>attcode</type>
|
||||
<mandatory>true</mandatory>
|
||||
<description>The field, in the current object, to set to
|
||||
the current date</description>
|
||||
</argument>
|
||||
</arguments>
|
||||
</method>
|
||||
<method id="Reset">
|
||||
<arguments>
|
||||
<argument>
|
||||
<label>Field Code</label>
|
||||
<type>attcode</type>
|
||||
<mandatory>true</mandatory>
|
||||
<description>The field, in the current object, to reset
|
||||
to its default value</description>
|
||||
</argument>
|
||||
</arguments>
|
||||
</method>
|
||||
<method id="Copy">
|
||||
<arguments>
|
||||
<argument>
|
||||
<label>Destination</label>
|
||||
<type>attcode</type>
|
||||
<mandatory>true</mandatory>
|
||||
<description>The field, in the current object, to set</description>
|
||||
</argument>
|
||||
<argument>
|
||||
<label>Source</label>
|
||||
<type>attcode</type>
|
||||
<mandatory>true</mandatory>
|
||||
<description>The field, in the current object, to get
|
||||
the value from</description>
|
||||
</argument>
|
||||
</arguments>
|
||||
</method>
|
||||
</methods>
|
||||
</class>
|
||||
</classes>
|
||||
</meta>
|
||||
</itop_design>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__,
|
||||
'itop-tickets/2.0.0',
|
||||
'itop-tickets/2.1.0',
|
||||
array(
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0">
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.1">
|
||||
<classes>
|
||||
<class id="VirtualDevice" _delta="define">
|
||||
<parent>FunctionalCI</parent>
|
||||
@@ -30,10 +30,10 @@
|
||||
<fields>
|
||||
<field id="status" xsi:type="AttributeEnum">
|
||||
<values>
|
||||
<value>production</value>
|
||||
<value>implementation</value>
|
||||
<value>stock</value>
|
||||
<value>obsolete</value>
|
||||
<value id="production">production</value>
|
||||
<value id="implementation">implementation</value>
|
||||
<value id="stock">stock</value>
|
||||
<value id="obsolete">obsolete</value>
|
||||
</values>
|
||||
<sql>status</sql>
|
||||
<default_value>production</default_value>
|
||||
@@ -967,35 +967,35 @@
|
||||
</list>
|
||||
</presentation>
|
||||
</class>
|
||||
</classes>
|
||||
<menus>
|
||||
<menu id="ConfigManagementOverview" xsi:type="DashboardMenuNode" _delta="must_exist">
|
||||
<definition>
|
||||
<cells>
|
||||
<cell id="1" _delta="define">
|
||||
<rank>1</rank>
|
||||
<dashlets>
|
||||
<dashlet id="38" xsi:type="DashletHeaderStatic">
|
||||
<rank>0</rank>
|
||||
<title>Menu:ConfigManagement:virtualization</title>
|
||||
<icon>itop-virtualization-mgmt/images/hypervisor-sw.png</icon>
|
||||
</dashlet>
|
||||
<dashlet id="39" xsi:type="DashletBadge">
|
||||
<rank>1</rank>
|
||||
<class>Farm</class>
|
||||
</dashlet>
|
||||
<dashlet id="40" xsi:type="DashletBadge">
|
||||
<rank>2</rank>
|
||||
<class>Hypervisor</class>
|
||||
</dashlet>
|
||||
<dashlet id="41" xsi:type="DashletBadge">
|
||||
<rank>3</rank>
|
||||
<class>VirtualMachine</class>
|
||||
</dashlet>
|
||||
</dashlets>
|
||||
</cell>
|
||||
</cells>
|
||||
</definition>
|
||||
</menu>
|
||||
</menus>
|
||||
</classes>
|
||||
<menus>
|
||||
<menu id="ConfigManagementOverview" xsi:type="DashboardMenuNode" _delta="must_exist">
|
||||
<definition>
|
||||
<cells>
|
||||
<cell id="1" _delta="define">
|
||||
<rank>1</rank>
|
||||
<dashlets>
|
||||
<dashlet id="38" xsi:type="DashletHeaderStatic">
|
||||
<rank>0</rank>
|
||||
<title>Menu:ConfigManagement:virtualization</title>
|
||||
<icon>itop-virtualization-mgmt/images/hypervisor-sw.png</icon>
|
||||
</dashlet>
|
||||
<dashlet id="39" xsi:type="DashletBadge">
|
||||
<rank>1</rank>
|
||||
<class>Farm</class>
|
||||
</dashlet>
|
||||
<dashlet id="40" xsi:type="DashletBadge">
|
||||
<rank>2</rank>
|
||||
<class>Hypervisor</class>
|
||||
</dashlet>
|
||||
<dashlet id="41" xsi:type="DashletBadge">
|
||||
<rank>3</rank>
|
||||
<class>VirtualMachine</class>
|
||||
</dashlet>
|
||||
</dashlets>
|
||||
</cell>
|
||||
</cells>
|
||||
</definition>
|
||||
</menu>
|
||||
</menus>
|
||||
</itop_design>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-virtualization-mgmt/2.0.0',
|
||||
'itop-virtualization-mgmt/2.1.0',
|
||||
array(
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0">
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.1">
|
||||
<menus>
|
||||
<menu id="WelcomeMenu" xsi:type="MenuGroup" _delta="define">
|
||||
<rank>10</rank>
|
||||
@@ -9,7 +9,7 @@
|
||||
<parent>WelcomeMenu</parent>
|
||||
<definition>
|
||||
<layout>DashboardLayoutOneCol</layout>
|
||||
<title></title>
|
||||
<title/>
|
||||
<cells>
|
||||
<cell id="0">
|
||||
<rank>0</rank>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-welcome-itil/2.0.0',
|
||||
'itop-welcome-itil/2.1.0',
|
||||
array(
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -1196,7 +1196,10 @@ When associated with a trigger, each action is given an "order" number, specifyi
|
||||
'Class:ShortcutOQL/Attribute:auto_reload_sec+' => 'The minimum allowed is 5 seconds',
|
||||
|
||||
'UI:FillAllMandatoryFields' => 'Please fill all mandatory fields.',
|
||||
|
||||
'UI:ValueMustBeSet' => 'Please specify a value',
|
||||
'UI:ValueMustBeChanged' => 'Please change the value',
|
||||
'UI:ValueInvalidFormat' => 'Invalid format',
|
||||
|
||||
'UI:CSVImportConfirmTitle' => 'Please confirm the operation',
|
||||
'UI:CSVImportConfirmMessage' => 'Are you sure you want to do this?',
|
||||
'UI:CSVImportError_items' => 'Errors: %1$d',
|
||||
@@ -1214,5 +1217,16 @@ When associated with a trigger, each action is given an "order" number, specifyi
|
||||
'UI:About:Support' => 'Support information',
|
||||
'UI:About:Licenses' => 'Licenses',
|
||||
'UI:About:Modules' => 'Installed modules',
|
||||
|
||||
'ExcelExporter:ExportMenu' => 'Excel Export...',
|
||||
'ExcelExporter:ExportDialogTitle' => 'Excel Export',
|
||||
'ExcelExporter:ExportButton' => 'Export',
|
||||
'ExcelExporter:DownloadButton' => 'Download %1$s',
|
||||
'ExcelExporter:RetrievingData' => 'Retrieving data...',
|
||||
'ExcelExporter:BuildingExcelFile' => 'Building the Excel file...',
|
||||
'ExcelExporter:Done' => 'Done.',
|
||||
'ExcelExport:AutoDownload' => 'Start the download automatically when the export is ready',
|
||||
'ExcelExport:PreparingExport' => 'Preparing the export...',
|
||||
'ExcelExport:Statistics' => 'Statistics',
|
||||
));
|
||||
?>
|
||||
|
||||
@@ -1036,6 +1036,9 @@ Lors de l\'association à un déclencheur, on attribue à chaque action un numé
|
||||
'Class:ShortcutOQL/Attribute:auto_reload_sec+' => 'Le minimum permis est de 5 secondes',
|
||||
|
||||
'UI:FillAllMandatoryFields' => 'Veuillez remplir tous les champs obligatoires.',
|
||||
'UI:ValueMustBeSet' => 'Veuillez spécifier une valeur pour ce champ',
|
||||
'UI:ValueMustBeChanged' => 'Veuillez modifier la valeur de ce champ',
|
||||
'UI:ValueInvalidFormat' => 'Format invalide',
|
||||
|
||||
'UI:CSVImportConfirmTitle' => 'Veuillez confirmer cette opération',
|
||||
'UI:CSVImportConfirmMessage' => 'Etes-vous sûr(e) de vouloir faire cela ?',
|
||||
@@ -1054,5 +1057,16 @@ Lors de l\'association à un déclencheur, on attribue à chaque action un numé
|
||||
'UI:About:Support' => 'Informations pour le support',
|
||||
'UI:About:Licenses' => 'Licences',
|
||||
'UI:About:Modules' => 'Modules installés',
|
||||
|
||||
'ExcelExporter:ExportMenu' => 'Exporter pour Excel...',
|
||||
'ExcelExporter:ExportDialogTitle' => 'Export au format Excel',
|
||||
'ExcelExporter:ExportButton' => 'Exporter',
|
||||
'ExcelExporter:DownloadButton' => 'Télécharger %1$s',
|
||||
'ExcelExporter:RetrievingData' => 'Récupération des données...',
|
||||
'ExcelExporter:BuildingExcelFile' => 'Construction du fichier Excel...',
|
||||
'ExcelExporter:Done' => 'Terminé.',
|
||||
'ExcelExport:AutoDownload' => 'Téléchargement automatique dès que le fichier est prêt',
|
||||
'ExcelExport:PreparingExport' => 'Préparation de l\'export...',
|
||||
'ExcelExport:Statistics' => 'Statistiques',
|
||||
));
|
||||
?>
|
||||
|
||||
BIN
images/xlsx.png
Normal file
BIN
images/xlsx.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
@@ -146,7 +146,7 @@ function CheckFields(sFormId, bDisplayAlert)
|
||||
return (oFormErrors['err_'+sFormId] == 0); // If no error, submit the form
|
||||
}
|
||||
|
||||
function ReportFieldValidationStatus(sFieldId, sFormId, bValid)
|
||||
function ReportFieldValidationStatus(sFieldId, sFormId, bValid, sExplain)
|
||||
{
|
||||
if (bValid)
|
||||
{
|
||||
@@ -163,13 +163,21 @@ function ReportFieldValidationStatus(sFieldId, sFormId, bValid)
|
||||
oFormErrors['input_'+sFormId] = sFieldId;
|
||||
}
|
||||
// Visual feedback
|
||||
$('#v_'+sFieldId).html('<img src="../images/validation_error.png" style="vertical-align:middle"/>');
|
||||
$('#v_'+sFieldId).html('<img src="../images/validation_error.png" style="vertical-align:middle" data-tooltip="'+sExplain+'"/>');
|
||||
$('#v_'+sFieldId).tooltip({
|
||||
items: 'span',
|
||||
tooltipClass: 'form_field_error',
|
||||
content: function() {
|
||||
return $(this).find('img').attr('data-tooltip'); // As opposed to the default 'content' handler, do not escape the contents of 'title'
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function ValidateField(sFieldId, sPattern, bMandatory, sFormId, nullValue)
|
||||
function ValidateField(sFieldId, sPattern, bMandatory, sFormId, nullValue, originalValue)
|
||||
{
|
||||
var bValid = true;
|
||||
var sExplain = '';
|
||||
if ($('#'+sFieldId).attr('disabled'))
|
||||
{
|
||||
bValid = true; // disabled fields are not checked
|
||||
@@ -185,6 +193,19 @@ function ValidateField(sFieldId, sPattern, bMandatory, sFormId, nullValue)
|
||||
else if (bMandatory && (currentVal == nullValue))
|
||||
{
|
||||
bValid = false;
|
||||
sExplain = Dict.S('UI:ValueMustBeSet');
|
||||
}
|
||||
else if ((originalValue != undefined) && (currentVal == originalValue))
|
||||
{
|
||||
bValid = false;
|
||||
if (originalValue == nullValue)
|
||||
{
|
||||
sExplain = Dict.S('UI:ValueMustBeSet');
|
||||
}
|
||||
else
|
||||
{
|
||||
sExplain = Dict.S('UI:ValueMustBeChanged');
|
||||
}
|
||||
}
|
||||
else if (currentVal == nullValue)
|
||||
{
|
||||
@@ -196,9 +217,10 @@ function ValidateField(sFieldId, sPattern, bMandatory, sFormId, nullValue)
|
||||
re = new RegExp(sPattern);
|
||||
//console.log('Validating field: '+sFieldId + ' current value: '+currentVal + ' pattern: '+sPattern );
|
||||
bValid = re.test(currentVal);
|
||||
sExplain = Dict.S('UI:ValueInvalidFormat');
|
||||
}
|
||||
}
|
||||
ReportFieldValidationStatus(sFieldId, sFormId, bValid);
|
||||
ReportFieldValidationStatus(sFieldId, sFormId, bValid, sExplain);
|
||||
//console.log('Form: '+sFormId+' Validating field: '+sFieldId + ' current value: '+currentVal+' pattern: '+sPattern+' result: '+bValid );
|
||||
return true; // Do not stop propagation ??
|
||||
}
|
||||
@@ -229,7 +251,7 @@ function ValidateCKEditField(sFieldId, sPattern, bMandatory, sFormId, nullValue)
|
||||
bValid = true;
|
||||
}
|
||||
|
||||
ReportFieldValidationStatus(sFieldId, sFormId, bValid);
|
||||
ReportFieldValidationStatus(sFieldId, sFormId, bValid, '');
|
||||
|
||||
setTimeout(function(){ValidateCKEditField(sFieldId, sPattern, bMandatory, sFormId, nullValue);}, 500);
|
||||
}
|
||||
@@ -321,7 +343,7 @@ function ValidateCaseLogField(sFieldId, bMandatory, sFormId)
|
||||
}
|
||||
}
|
||||
}
|
||||
ReportFieldValidationStatus(sFieldId, sFormId, bValid);
|
||||
ReportFieldValidationStatus(sFieldId, sFormId, bValid, '');
|
||||
return bValid;
|
||||
}
|
||||
// Manage a 'duration' field
|
||||
|
||||
@@ -139,7 +139,7 @@ $(function()
|
||||
this.datatable.tableHover();
|
||||
this.datatable.find('.selectList'+this.id).bind('change', function() { me._updateButtons(); });
|
||||
},
|
||||
_updateDlgSize: function()
|
||||
_updateDlgPosition: function()
|
||||
{
|
||||
this.oDlg.dialog('option', { position: { my: "center", at: "center", of: window }});
|
||||
},
|
||||
@@ -171,7 +171,7 @@ $(function()
|
||||
});
|
||||
me.indicator.html('');
|
||||
me.oButtons['create'].removeAttr('disabled');
|
||||
me._updateDlgSize();
|
||||
me._updateDlgPosition();
|
||||
});
|
||||
},
|
||||
_selectToAdd: function()
|
||||
@@ -197,20 +197,23 @@ $(function()
|
||||
me.oDlg.find('form').removeAttr('onsubmit').bind('submit', function() { me._onSearchToAdd(); return false; } );
|
||||
me.oDlg.find('button.cancel').unbind('click').click( function() { me.oDlg.dialog('close'); } );
|
||||
me.oDlg.find('button.ok').unbind('click').click( function() { me._onDoAdd(); } );
|
||||
$('#SearchFormToAdd_'+me.id).resize(function() { me._onSearchDlgUpdateSize(); });
|
||||
|
||||
me.oDlg.dialog({
|
||||
title: me.options.labels['selection_title'],
|
||||
modal: true,
|
||||
width: 'auto',
|
||||
height: 'auto',
|
||||
width: $(window).width()*0.8,
|
||||
height: $(window).height()*0.8,
|
||||
maxHeight: $(window).height() - 50,
|
||||
position: { my: "center", at: "center", of: window },
|
||||
close: function() { me._onDlgClose(); }
|
||||
close: function() { me._onDlgClose(); },
|
||||
resizeStop: function() { me._onSearchDlgUpdateSize(); }
|
||||
});
|
||||
me.indicator.html('');
|
||||
me.oButtons['add'].removeAttr('disabled');
|
||||
me._onSearchToAdd();
|
||||
me._updateDlgSize();
|
||||
me._updateDlgPosition();
|
||||
me._onSearchDlgUpdateSize();
|
||||
});
|
||||
},
|
||||
_onSearchToAdd: function()
|
||||
@@ -255,8 +258,8 @@ $(function()
|
||||
me._onUpdateDlgButtons(c);
|
||||
});
|
||||
$('#SearchResultsToAdd_'+me.id).unblock();
|
||||
me._onSearchDlgUpdateSize();
|
||||
});
|
||||
//alert("C'est parti mon kiki !");
|
||||
return false; // Stay on the page, no submit
|
||||
},
|
||||
_getSelection: function(sName)
|
||||
@@ -373,7 +376,7 @@ $(function()
|
||||
me.oDlg.html(data);
|
||||
me.oDlg.find('form').removeAttr('onsubmit').bind('submit', function() { me._onCreateRow(); return false; } );
|
||||
me.oDlg.find('button.cancel').unbind('click').click( function() { me.oDlg.dialog('close'); } );
|
||||
me._updateDlgSize();
|
||||
me._updateDlgPosition();
|
||||
});
|
||||
},
|
||||
_onCreateRow: function()
|
||||
@@ -426,6 +429,13 @@ $(function()
|
||||
this.oDlg.remove();
|
||||
this.oDlg = null;
|
||||
},
|
||||
_onSearchDlgUpdateSize: function()
|
||||
{
|
||||
var searchHeight = $('#SearchFormToAdd_'+this.id).outerHeight();
|
||||
var dlgHeight = this.oDlg.height();
|
||||
$('.wizContainer', this.oDlg).height(dlgHeight - 20);
|
||||
$('#SearchResultsToAdd_'+this.id).height(dlgHeight - 50 - searchHeight);
|
||||
},
|
||||
_deleteRow: function(oCheckbox)
|
||||
{
|
||||
var iObjKey = parseInt(oCheckbox.val(), 10); // Number in base 10
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user