From fd9008a163f651e5a2aa099f1b014cb0e30a04f3 Mon Sep 17 00:00:00 2001 From: Denis Flaven Date: Mon, 28 Jul 2014 15:16:16 +0000 Subject: [PATCH] New concept in the XML: HighlightScale to avoid overloading GetIcon and GetHilightClass... SVN:trunk[3291] --- application/cmdbabstract.class.inc.php | 2 +- core/attributedef.class.inc.php | 5 +- core/dbobject.class.php | 141 +++++++++++- core/metamodel.class.php | 113 +++++++++- core/ormstopwatch.class.inc.php | 68 +++++- .../datamodel.itop-change-mgmt-itil.xml | 92 +++----- .../datamodel.itop-change-mgmt.xml | 83 +++---- .../datamodel.itop-incident-mgmt-itil.xml | 187 ++++------------ .../datamodel.itop-request-mgmt-itil.xml | 175 +++------------ .../datamodel.itop-request-mgmt.xml | 209 +++++------------- setup/compiler.class.inc.php | 110 ++++++++- 11 files changed, 604 insertions(+), 581 deletions(-) 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 }