diff --git a/application/cmdbabstract.class.inc.php b/application/cmdbabstract.class.inc.php
index fbd7e7799..be64e7a48 100644
--- a/application/cmdbabstract.class.inc.php
+++ b/application/cmdbabstract.class.inc.php
@@ -2460,7 +2460,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)
diff --git a/core/attributedef.class.inc.php b/core/attributedef.class.inc.php
index d1f9d96cb..15d0aabfc 100644
--- a/core/attributedef.class.inc.php
+++ b/core/attributedef.class.inc.php
@@ -3717,7 +3717,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 +3725,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
);
}
diff --git a/core/dbobject.class.php b/core/dbobject.class.php
index 50358fb3b..9eee7fb77 100644
--- a/core/dbobject.class.php
+++ b/core/dbobject.class.php
@@ -95,6 +95,7 @@ abstract class DBObject implements iDisplay
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_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 "
";
+ }
+ else
+ {
+ return $sIconUrl;
+ }
+ }
+ }
return MetaModel::GetClassIcon(get_class($this), $bImgTag);
}
@@ -1998,17 +2074,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;
}
@@ -2563,6 +2677,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;
}
diff --git a/core/metamodel.class.php b/core/metamodel.class.php
index 4f078aa4a..0f2151dd8 100644
--- a/core/metamodel.class.php
+++ b/core/metamodel.class.php
@@ -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
@@ -3386,6 +3431,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 +3555,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 +4819,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 +4856,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)');
}
diff --git a/core/ormstopwatch.class.inc.php b/core/ormstopwatch.class.inc.php
index 44d4f4402..e926f6246 100644
--- a/core/ormstopwatch.class.inc.php
+++ b/core/ormstopwatch.class.inc.php
@@ -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)
);
}
@@ -143,6 +144,30 @@ 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 (($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 +449,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"
diff --git a/datamodels/2.x/itop-change-mgmt-itil/datamodel.itop-change-mgmt-itil.xml b/datamodels/2.x/itop-change-mgmt-itil/datamodel.itop-change-mgmt-itil.xml
index c56263613..9ad603e96 100755
--- a/datamodels/2.x/itop-change-mgmt-itil/datamodel.itop-change-mgmt-itil.xml
+++ b/datamodels/2.x/itop-change-mgmt-itil/datamodel.itop-change-mgmt-itil.xml
@@ -201,6 +201,23 @@
status
+
+ -
+ 1
+ HIGHLIGHT_CLASS_NONE
+ images/change-approved.png
+
+ -
+ 2
+ HIGHLIGHT_CLASS_NONE
+ images/change-rejected.png
+
+ -
+ 3
+ HIGHLIGHT_CLASS_NONE
+ images/change-closed.png
+
+
@@ -343,6 +360,9 @@
+
+ rejected
+
@@ -532,6 +552,9 @@
+
+ approved
+
@@ -594,6 +617,9 @@
+
+ rejected
+
@@ -657,6 +683,9 @@
+
+ approved
+
@@ -719,6 +748,9 @@
+
+ approved
+
@@ -790,6 +822,9 @@
+
+ closed
+
@@ -932,63 +967,6 @@
$this->Set('last_update', time());
}]]>
-
- /**
- * 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
- */
- false
- public
- Overload-DBObject
- 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;
- }]]>
-
-
- true
- protected
- Overload-DBObject
- ";
- }
- else
- {
- $sIcon = $sPath;
- }
- }
- return $sIcon;
- }]]>
-
diff --git a/datamodels/2.x/itop-change-mgmt/datamodel.itop-change-mgmt.xml b/datamodels/2.x/itop-change-mgmt/datamodel.itop-change-mgmt.xml
index 6d02d0996..ac78dab66 100755
--- a/datamodels/2.x/itop-change-mgmt/datamodel.itop-change-mgmt.xml
+++ b/datamodels/2.x/itop-change-mgmt/datamodel.itop-change-mgmt.xml
@@ -145,6 +145,23 @@
+
+ -
+ 1
+ HIGHLIGHT_CLASS_NONE
+ images/change-approved.png
+
+ -
+ 2
+ HIGHLIGHT_CLASS_NONE
+ images/change-rejected.png
+
+ -
+ 3
+ HIGHLIGHT_CLASS_NONE
+ images/change-closed.png
+
+
status
@@ -340,6 +357,9 @@
+
+ rejected
+
@@ -415,6 +435,9 @@
+
+ approved
+
@@ -490,6 +513,9 @@
+
+ closed
+
@@ -633,63 +659,6 @@
$this->Set('last_update', time());
}]]>
-
- /**
- * 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
- */
- false
- public
- Overload-DBObject
- 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;
- }]]>
-
-
- true
- protected
- Overload-DBObject
- ";
- }
- else
- {
- $sIcon = $sPath;
- }
- }
- return $sIcon;
- }]]>
-
diff --git a/datamodels/2.x/itop-incident-mgmt-itil/datamodel.itop-incident-mgmt-itil.xml b/datamodels/2.x/itop-incident-mgmt-itil/datamodel.itop-incident-mgmt-itil.xml
index 0d73ed076..ad87f90b2 100755
--- a/datamodels/2.x/itop-incident-mgmt-itil/datamodel.itop-incident-mgmt-itil.xml
+++ b/datamodels/2.x/itop-incident-mgmt-itil/datamodel.itop-incident-mgmt-itil.xml
@@ -188,11 +188,19 @@
75
+
+ warning
+ false
+
100
+
+ critical
+ false
+
ApplyStimulus
@@ -217,11 +225,19 @@
75
+
+ warning
+ false
+
100
+
+ critical
+ false
+
ApplyStimulus
@@ -357,6 +373,23 @@
+
+ -
+ 1
+ HIGHLIGHT_CLASS_WARNING
+ images/incident-deadline.png
+
+ -
+ 2
+ HIGHLIGHT_CLASS_CRITICAL
+ images/incident-escalated.png
+
+ -
+ 3
+ HIGHLIGHT_CLASS_NONE
+ images/incident-closed.png
+
+
status
@@ -481,6 +514,9 @@
+
+ critical
+
@@ -691,6 +727,9 @@
+
+ critical
+
@@ -898,6 +937,9 @@
+
+ closed
+
@@ -1045,6 +1087,9 @@
+
+ closed
+
@@ -1310,148 +1355,6 @@
}
}]]>
-
- /**
- * 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
- */
- false
- public
- Overload-DBObject
- Get('status');
- switch($this->GetState())
- {
-
- case 'escalated_tto':
- case 'escalated_ttr':
- $sIcon = self::MakeIconFromName('incident-escalated.png');
- break;
-
- case 'resolved':
- case 'closed':
- $sIcon = self::MakeIconFromName('incident-closed.png');
- break;
-
- case 'new':
- case 'approved':
- $sIcon = self::MakeIconFromName('incident.png');
- $iEscalationDeadline = $this->Get('tto_escalation_deadline');
- if ($iEscalationDeadline != null)
- {
- // A SLA is running
- $oTTOStopWatch = $this->Get('tto');
- if ($oTTOStopWatch->IsThresholdPassed(100))
- {
- $sIcon = self::MakeIconFromName('incident-escalated.png');
- }
- else if ($oTTOStopWatch->IsThresholdPassed(75))
- {
- $sIcon = self::MakeIconFromName('incident-deadline.png');
- }
- }
- break;
-
- case 'assigned':
- $sIcon = self::MakeIconFromName('incident.png');
- $iEscalationDeadline = $this->Get('ttr_escalation_deadline');
- if ($iEscalationDeadline != null)
- {
- // A SLA is running
- $oTTRStopWatch = $this->Get('ttr');
- if ($oTTRStopWatch->IsThresholdPassed(100))
- {
- $sIcon = self::MakeIconFromName('incident-escalated.png');
- }
- else if ($oTTRStopWatch->IsThresholdPassed(75))
- {
- $sIcon = self::MakeIconFromName('incident-deadline.png');
- }
- }
- break;
-
- default:
- $sIcon = MetaModel::GetClassIcon(get_class($this), $bImgTag);
- }
- return $sIcon;
- }]]>
-
-
- true
- protected
- Overload-DBObject
- ";
- }
- else
- {
- $sIcon = $sPath;
- }
- }
- return $sIcon;
- }]]>
-
-
- false
- public
- Overload-iDisplay
- GetState())
- {
- case 'new':
- case 'approved':
- $iEscalationDeadline = $this->Get('tto_escalation_deadline');
- if ($iEscalationDeadline != null)
- {
- // A SLA is running
- $oTTOStopWatch = $this->Get('tto');
- if ($oTTOStopWatch->IsThresholdPassed(100))
- {
- $sHilightClass = HILIGHT_CLASS_CRITICAL;
- }
- else if ($oTTOStopWatch->IsThresholdPassed(75))
- {
- $sHilightClass = HILIGHT_CLASS_WARNING;
- }
- }
- break;
-
- case 'assigned':
- $iEscalationDeadline = $this->Get('ttr_escalation_deadline');
- if ($iEscalationDeadline != null)
- {
- // A SLA is running
- $oTTRStopWatch = $this->Get('ttr');
- if ($oTTRStopWatch->IsThresholdPassed(100))
- {
- $sHilightClass = HILIGHT_CLASS_CRITICAL;
- }
- else if ($oTTRStopWatch->IsThresholdPassed(75))
- {
- $sHilightClass = HILIGHT_CLASS_WARNING;
- }
- }
- break;
-
- case 'escalated_tto':
- case 'escalated_ttr':
- $sHilightClass = HILIGHT_CLASS_CRITICAL;
- break;
- }
- return $sHilightClass;
- }]]>
-
false
public
diff --git a/datamodels/2.x/itop-request-mgmt-itil/datamodel.itop-request-mgmt-itil.xml b/datamodels/2.x/itop-request-mgmt-itil/datamodel.itop-request-mgmt-itil.xml
index 02e610843..33f6c8e04 100755
--- a/datamodels/2.x/itop-request-mgmt-itil/datamodel.itop-request-mgmt-itil.xml
+++ b/datamodels/2.x/itop-request-mgmt-itil/datamodel.itop-request-mgmt-itil.xml
@@ -388,6 +388,23 @@
+
+ -
+ 1
+ HIGHLIGHT_CLASS_WARNING
+ images/user-request-deadline.png
+
+ -
+ 2
+ HIGHLIGHT_CLASS_CRITICAL
+ images/user-request-escalated.png
+
+ -
+ 3
+ HIGHLIGHT_CLASS_NONE
+ images/user-request-closed.png
+
+
status
@@ -526,6 +543,9 @@
+
+ critical
+
@@ -748,6 +768,9 @@
+
+ critical
+
@@ -1269,6 +1292,9 @@
+
+ closed
+
@@ -1419,6 +1445,9 @@
+
+ closed
+
@@ -1701,152 +1730,6 @@
}
}]]>
-
- /**
- * 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
- */
- false
- public
- Overload-DBObject
- Get('status');
- switch($this->GetState())
- {
-
- case 'escalated_tto':
- case 'escalated_ttr':
- $sIcon = self::MakeIconFromName('user-request-escalated.png');
- break;
-
- case 'resolved':
- case 'closed':
- $sIcon = self::MakeIconFromName('user-request-closed.png');
- break;
-
- case 'new':
- case 'approved':
- $sIcon = self::MakeIconFromName('user-request.png');
- $iEscalationDeadline = $this->Get('tto_escalation_deadline');
- if ($iEscalationDeadline != null)
- {
- // A SLA is running
- $oTTOStopWatch = $this->Get('tto');
- if ($oTTOStopWatch->IsThresholdPassed(100))
- {
- $sIcon = self::MakeIconFromName('user-request-escalated.png');
- }
- else if ($oTTOStopWatch->IsThresholdPassed(75))
- {
- $sIcon = self::MakeIconFromName('user-request-deadline.png');
- }
- }
- break;
-
- case 'assigned':
- $sIcon = self::MakeIconFromName('user-request.png');
- $iEscalationDeadline = $this->Get('ttr_escalation_deadline');
- if ($iEscalationDeadline != null)
- {
- // A SLA is running
- $oTTRStopWatch = $this->Get('ttr');
- if ($oTTRStopWatch->IsThresholdPassed(100))
- {
- $sIcon = self::MakeIconFromName('user-request-escalated.png');
- }
- else if ($oTTRStopWatch->IsThresholdPassed(75))
- {
- $sIcon = self::MakeIconFromName('user-request-deadline.png');
- }
- }
- break;
-
-
-
-
-
-
- default:
- $sIcon = MetaModel::GetClassIcon(get_class($this), $bImgTag);
- }
- return $sIcon;
- }]]>
-
-
- true
- protected
- Overload-DBObject
- ";
- }
- else
- {
- $sIcon = $sPath;
- }
- }
- return $sIcon;
- }]]>
-
-
- false
- public
- Overload-iDisplay
- GetState())
- {
- case 'new':
- case 'approved':
- $iEscalationDeadline = $this->Get('tto_escalation_deadline');
- if ($iEscalationDeadline != null)
- {
- // A SLA is running
- $oTTOStopWatch = $this->Get('tto');
- if ($oTTOStopWatch->IsThresholdPassed(100))
- {
- $sHilightClass = HILIGHT_CLASS_CRITICAL;
- }
- else if ($oTTOStopWatch->IsThresholdPassed(75))
- {
- $sHilightClass = HILIGHT_CLASS_WARNING;
- }
- }
- break;
-
- case 'assigned':
- $iEscalationDeadline = $this->Get('ttr_escalation_deadline');
- if ($iEscalationDeadline != null)
- {
- // A SLA is running
- $oTTRStopWatch = $this->Get('ttr');
- if ($oTTRStopWatch->IsThresholdPassed(100))
- {
- $sHilightClass = HILIGHT_CLASS_CRITICAL;
- }
- else if ($oTTRStopWatch->IsThresholdPassed(75))
- {
- $sHilightClass = HILIGHT_CLASS_WARNING;
- }
- }
- break;
- case 'escalated_tto':
- case 'escalated_ttr':
- $sHilightClass = HILIGHT_CLASS_CRITICAL;
- break;
- }
- return $sHilightClass;
- }]]>
-
false
public
diff --git a/datamodels/2.x/itop-request-mgmt/datamodel.itop-request-mgmt.xml b/datamodels/2.x/itop-request-mgmt/datamodel.itop-request-mgmt.xml
index c5449dd3e..b5fd81480 100755
--- a/datamodels/2.x/itop-request-mgmt/datamodel.itop-request-mgmt.xml
+++ b/datamodels/2.x/itop-request-mgmt/datamodel.itop-request-mgmt.xml
@@ -211,19 +211,27 @@
true
-
-
+
+
-
+
ResponseTicketTTO
75
+
+ warning
+ false
+
-
+
100
+
+ critical
+ false
+
ApplyStimulus
@@ -238,22 +246,30 @@
true
-
-
-
-
-
+
+
+
+
+
-
+
ResponseTicketTTR
75
+
+ critical
+ false
+
-
+
100
+
+ critical
+ false
+
ApplyStimulus
@@ -388,6 +404,23 @@
+
+ -
+ 1
+ HIGHLIGHT_CLASS_WARNING
+ images/user-request-deadline.png
+
+ -
+ 2
+ HIGHLIGHT_CLASS_CRITICAL
+ images/user-request-escalated.png
+
+ -
+ 3
+ HIGHLIGHT_CLASS_NONE
+ images/user-request-closed.png
+
+
status
@@ -523,6 +556,9 @@
+
+ critical
+
@@ -742,6 +778,9 @@
+
+ critical
+
@@ -1254,6 +1293,9 @@
+
+ closed
+
@@ -1404,6 +1446,9 @@
+
+ closed
+
@@ -1686,148 +1731,6 @@
}
}]]>
-
- /**
- * 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
- */
- false
- public
- Overload-DBObject
- Get('status');
- switch($this->GetState())
- {
-
- case 'escalated_tto':
- case 'escalated_ttr':
- $sIcon = self::MakeIconFromName('user-request-escalated.png');
- break;
-
- case 'resolved':
- case 'closed':
- $sIcon = self::MakeIconFromName('user-request-closed.png');
- break;
-
- case 'new':
- case 'approved':
- $sIcon = self::MakeIconFromName('user-request.png');
- $iEscalationDeadline = $this->Get('tto_escalation_deadline');
- if ($iEscalationDeadline != null)
- {
- // A SLA is running
- $oTTOStopWatch = $this->Get('tto');
- if ($oTTOStopWatch->IsThresholdPassed(100))
- {
- $sIcon = self::MakeIconFromName('user-request-escalated.png');
- }
- else if ($oTTOStopWatch->IsThresholdPassed(75))
- {
- $sIcon = self::MakeIconFromName('user-request-deadline.png');
- }
- }
- break;
-
- case 'assigned':
- $sIcon = self::MakeIconFromName('user-request.png');
- $iEscalationDeadline = $this->Get('ttr_escalation_deadline');
- if ($iEscalationDeadline != null)
- {
- // A SLA is running
- $oTTRStopWatch = $this->Get('ttr');
- if ($oTTRStopWatch->IsThresholdPassed(100))
- {
- $sIcon = self::MakeIconFromName('user-request-escalated.png');
- }
- else if ($oTTRStopWatch->IsThresholdPassed(75))
- {
- $sIcon = self::MakeIconFromName('user-request-deadline.png');
- }
- }
- break;
-
- default:
- $sIcon = MetaModel::GetClassIcon(get_class($this), $bImgTag);
- }
- return $sIcon;
- }]]>
-
-
- true
- protected
- Overload-DBObject
- ";
- }
- else
- {
- $sIcon = $sPath;
- }
- }
- return $sIcon;
- }]]>
-
-
- false
- public
- Overload-iDisplay
- GetState())
- {
- case 'new':
- case 'approved':
- $iEscalationDeadline = $this->Get('tto_escalation_deadline');
- if ($iEscalationDeadline != null)
- {
- // A SLA is running
- $oTTOStopWatch = $this->Get('tto');
- if ($oTTOStopWatch->IsThresholdPassed(100))
- {
- $sHilightClass = HILIGHT_CLASS_CRITICAL;
- }
- else if ($oTTOStopWatch->IsThresholdPassed(75))
- {
- $sHilightClass = HILIGHT_CLASS_WARNING;
- }
- }
- break;
-
- case 'assigned':
- $iEscalationDeadline = $this->Get('ttr_escalation_deadline');
- if ($iEscalationDeadline != null)
- {
- // A SLA is running
- $oTTRStopWatch = $this->Get('ttr');
- if ($oTTRStopWatch->IsThresholdPassed(100))
- {
- $sHilightClass = HILIGHT_CLASS_CRITICAL;
- }
- else if ($oTTRStopWatch->IsThresholdPassed(75))
- {
- $sHilightClass = HILIGHT_CLASS_WARNING;
- }
- }
- break;
-
- case 'escalated_tto':
- case 'escalated_ttr':
- $sHilightClass = HILIGHT_CLASS_CRITICAL;
- break;
- }
- return $sHilightClass;
- }]]>
-
false
public
diff --git a/setup/compiler.class.inc.php b/setup/compiler.class.inc.php
index 9172d6f33..fe8efdfb2 100644
--- a/setup/compiler.class.inc.php
+++ b/setup/compiler.class.inc.php
@@ -922,6 +922,15 @@ EOF;
{
$iPercent = $this->GetPropNumber($oThreshold, 'percent');
+ $oHighlight = $oThreshold->GetUniqueElement('highlight', false);
+ $sHighlight = '';
+ if($oHighlight)
+ {
+ $sCode = $oHighlight->GetChildText('code');
+ $bPersistent = $this->GetPropBoolean($oHighlight, 'persistent', false);
+ $sHighlight = "'highlight' => array('code' => '$sCode', 'persistent' => ".($bPersistent ? 'true' : 'false')."), ";
+ }
+
$oActions = $oThreshold->GetUniqueElement('actions');
$oActionNodes = $oActions->getElementsByTagName('action');
$aActions = array();
@@ -934,7 +943,12 @@ EOF;
$oParamNodes = $oParams->getElementsByTagName('param');
foreach($oParamNodes as $oParam)
{
- $aActionParams[] = self::QuoteForPHP($oParam->textContent);
+ $sParamType = $oParam->getAttribute('xsi:type');
+ if ($sParamType == '')
+ {
+ $sParamType = 'string';
+ }
+ $aActionParams[] = "array('type' => '$sParamType', 'value' => '".self::QuoteForPHP($oParam->textContent)."')";
}
}
$sActionParams = 'array('.implode(', ', $aActionParams).')';
@@ -942,7 +956,7 @@ EOF;
$aActions[] = "array('verb' => $sVerb, 'params' => $sActionParams)";
}
$sActions = 'array('.implode(', ', $aActions).')';
- $aThresholds[] = $iPercent." => array('percent' => $iPercent, 'actions' => $sActions)";
+ $aThresholds[] = $iPercent." => array('percent' => $iPercent, $sHighlight 'actions' => $sActions)";
}
$aParameters['thresholds'] = 'array('.implode(', ', $aThresholds).')';
}
@@ -995,6 +1009,7 @@ EOF;
// Lifecycle
//
$sLifecycle = '';
+ $sHighlightScale = '';
if ($oLifecycle)
{
$sLifecycle .= "\t\t// Lifecycle (status attribute: $sStateAttCode)\n";
@@ -1008,7 +1023,57 @@ EOF;
$sLifecycle .= " MetaModel::Init_DefineStimulus(new ".$sStimulusClass."(\"".$sStimulus."\", array()));\n";
}
-
+ $oHighlightScale = $oLifecycle->GetUniqueElement('highlight_scale', false);
+ if ($oHighlightScale)
+ {
+ $sHighlightScale = "\t\t// Higlight Scale\n";
+ $sHighlightScale .= " MetaModel::Init_DefineHighlightScale( array(\n";
+
+ $this->CompileFiles($oHighlightScale, $sTempTargetDir.'/'.$sModuleRelativeDir, $sFinalTargetDir.'/'.$sModuleRelativeDir, '');
+
+ foreach ($oHighlightScale->getElementsByTagName('item') as $oItem)
+ {
+ $sItemCode = $oItem->getAttribute('id');
+ $fRank = (float)$oItem->GetChildText('rank');
+ $sColor = $oItem->GetChildText('color');
+ if (($sIcon = $oItem->GetChildText('icon')) && (strlen($sIcon) > 0))
+ {
+ $sIcon = $sModuleRelativeDir.'/'.$sIcon;
+ $sIcon = "utils::GetAbsoluteUrlModulesRoot().'$sIcon'";
+ }
+ switch($sColor)
+ {
+ // Known PHP constants: keep the literal value as-is
+ case 'HILIGHT_CLASS_CRITICAL':
+ case 'HIGHLIGHT_CLASS_CRITICAL':
+ $sColor = 'HILIGHT_CLASS_CRITICAL';
+ break;
+
+ case 'HILIGHT_CLASS_OK':
+ case 'HIGHLIGHT_CLASS_OK':
+ $sColor = 'HILIGHT_CLASS_OK';
+ break;
+
+ case 'HIGHLIGHT_CLASS_WARNING':
+ case 'HILIGHT_CLASS_WARNING':
+ $sColor = 'HILIGHT_CLASS_WARNING';
+ break;
+
+ case 'HIGHLIGHT_CLASS_NONE':
+ case 'HILIGHT_CLASS_NONE':
+ $sColor = 'HILIGHT_CLASS_NONE';
+ break;
+
+ default:
+ // Future extension, specify your own color??
+ $sColor = "'".addslashes($sColor)."'";
+ }
+ $sHighlightScale .= " '$sItemCode' => array('rank' => $fRank, 'color' => $sColor, 'icon' => $sIcon),\n";
+
+ }
+ $sHighlightScale .= " ));\n";
+ }
+
$oStates = $oLifecycle->GetUniqueElement('states');
foreach ($oStates->getElementsByTagName('state') as $oState)
{
@@ -1028,7 +1093,20 @@ EOF;
$sLifecycle .= " MetaModel::Init_DefineState(\n";
$sLifecycle .= " \"".$sState."\",\n";
$sLifecycle .= " array(\n";
- $sLifecycle .= " \"attribute_inherit\" => '',\n";
+ $sAttributeInherit = '';
+ //$sAttributeInherit = $oState->GetChildText('inherit_flags', ''); // Seems easy but think about the consequences when applying a delta
+ $sLifecycle .= " \"attribute_inherit\" => '$sAttributeInherit',\n";
+ $oHighlight = $oState->GetUniqueElement('highlight', false);
+ if ($oHighlight)
+ {
+ $sCode = $oHighlight->GetChildText('code', '');
+ if ($sCode != '')
+ {
+ $sLifecycle .= " 'highlight' => array('code' => '$sCode'),\n";
+ }
+
+ }
+
$sLifecycle .= " \"attribute_list\" => array(\n";
$oFlags = $oState->GetUniqueElement('flags');
@@ -1061,7 +1139,28 @@ EOF;
foreach ($oActions->getElementsByTagName('action') as $oAction)
{
$sVerb = $oAction->GetChildText('verb');
- $aVerbs[] = "'$sVerb'";
+ $oParams = $oAction->GetOptionalElement('params');
+ $aActionParams = array();
+ if ($oParams)
+ {
+ $oParamNodes = $oParams->getElementsByTagName('param');
+ foreach($oParamNodes as $oParam)
+ {
+ $sParamType = $oParam->getAttribute('xsi:type');
+ if ($sParamType == '')
+ {
+ $sParamType = 'string';
+ }
+ $aActionParams[] = "array('type' => '$sType', 'value' => '".self::QuoteForPHP($oParam->textContent)."')";
+ }
+ }
+ else
+ {
+ // Old (pre 2.0.4) format, when no parameter is specified, assume 1 parameter: reference sStimulusCode
+ $aActionParams[] = "array('type' => 'reference', 'value' => 'sStimulusCode')";
+ }
+ $sActionParams = 'array('.implode(', ', $aActionParams).')';
+ $aVerbs[] = "array('verb' => '$sVerb', 'params' => $sActionParams)";
}
$sActions = implode(', ', $aVerbs);
$sLifecycle .= " MetaModel::Init_DefineTransition(\"$sState\", \"$sStimulus\", array(\"target_state\"=>\"$sTargetState\", \"actions\"=>array($sActions), \"user_restriction\"=>null));\n";
@@ -1158,6 +1257,7 @@ $sClassParams
MetaModel::Init_InheritAttributes();
$sAttributes
$sLifecycle
+$sHighlightScale
$sZlists
}