diff --git a/application/cmdbabstract.class.inc.php b/application/cmdbabstract.class.inc.php
index d9fcc2361..15404aaab 100644
--- a/application/cmdbabstract.class.inc.php
+++ b/application/cmdbabstract.class.inc.php
@@ -2464,16 +2464,13 @@ EOF
}
$sActionLabel = $aStimuli[$sStimulus]->GetLabel();
$sActionDetails = $aStimuli[$sStimulus]->GetDescription();
- $aTransition = $aTransitions[$sStimulus];
- $sTargetState = $aTransition['target_state'];
- $aTargetStates = MetaModel::EnumStates($sClass);
- $oPage->add("
\n");
- $aTargetState = $aTargetStates[$sTargetState];
- $aExpectedAttributes = $aTargetState['attribute_list'];
- $oPage->add("$sActionDetails
\n");
+ $oPage->add("\n");
+ $oPage->add("$sActionDetails
\n");
+ $sTargetState = $aTransitions[$sStimulus]['target_state'];
+ $aExpectedAttributes = $this->GetTransitionAttributes($sStimulus /*, current state*/);
$sButtonsPosition = MetaModel::GetConfig()->Get('buttons_position');
if ($sButtonsPosition == 'bottom')
{
diff --git a/core/dbobject.class.php b/core/dbobject.class.php
index ab01de12e..c9dc7b6f5 100644
--- a/core/dbobject.class.php
+++ b/core/dbobject.class.php
@@ -1,5 +1,5 @@
Get($sStateAttCode);
+ }
+
+ // Retrieving attribute flags
+ $iAttributeFlags = $this->GetAttributeFlags($sAttCode, $aReasons, $sOriginState);
+
+ // Retrieving transition flags
+ $iTransitionFlags = MetaModel::GetTransitionFlags(get_class($this), $sOriginState, $sStimulus, $sAttCode);
+
+ // Merging transition flags with attribute flags
+ $iFlags = $iTransitionFlags | $iAttributeFlags;
+
+ return $iFlags;
+ }
+
+ /**
+ * Returns an array of attribute codes (with their flags) when $sStimulus is applied on the object in the $sOriginState state.
+ * Note: Attributes (and flags) from the target state and the transition are combined.
+ *
+ * @param $sStimulus string
+ * @param $sOriginState string Default is current state
+ * @return array
+ */
+ public function GetTransitionAttributes($sStimulus, $sOriginState = null)
+ {
+ $sObjClass = get_class($this);
+
+ // Defining current state as origin state if not specified
+ if($sOriginState === null)
+ {
+ $sOriginState = $this->GetState();
+ }
+
+ $aAttributes = MetaModel::GetTransitionAttributes($sObjClass, $sStimulus, $sOriginState);
+
+ return $aAttributes;
+ }
+
/**
* Returns the set of flags (OPT_ATT_HIDDEN, OPT_ATT_READONLY, OPT_ATT_MANDATORY...)
* for the given attribute for the current state of the object considered as an INITIAL state
diff --git a/core/metamodel.class.php b/core/metamodel.class.php
index 34b492975..e21fa7c34 100644
--- a/core/metamodel.class.php
+++ b/core/metamodel.class.php
@@ -1,5 +1,5 @@
$iAttributeFlags)
+ {
+ if(array_key_exists($sAttCode, $aAttributes))
+ {
+ $aAttributes[$sAttCode] = $aAttributes[$sAttCode] | $iAttributeFlags;
+ }
+ else
+ {
+ $aAttributes[$sAttCode] = $iAttributeFlags;
+ }
+ }
+
+ return $aAttributes;
+ }
/**
* Combines the flags from the all states that compose the initial_state_path
diff --git a/pages/UI.php b/pages/UI.php
index cbd8932e7..a2b86841a 100644
--- a/pages/UI.php
+++ b/pages/UI.php
@@ -1120,17 +1120,16 @@ EOF
$sActionLabel = $aStimuli[$sStimulus]->GetLabel();
$sActionDetails = $aStimuli[$sStimulus]->GetDescription();
- $aTransition = $aTransitions[$sStimulus];
- $sTargetState = $aTransition['target_state'];
+ $sTargetState = $aTransitions[$sStimulus]['target_state'];
$aStates = MetaModel::EnumStates($sClass);
$aTargetStateDef = $aStates[$sTargetState];
-
+
$oP->set_title(Dict::Format('UI:StimulusModify_N_ObjectsOf_Class', $sActionLabel, count($aSelectObject), $sClass));
$oP->add('');
- $aExpectedAttributes = $aTargetStateDef['attribute_list'];
+ $aExpectedAttributes = MetaModel::GetTransitionAttributes($sClass, $sStimulus, $sState);
$aDetails = array();
$iFieldIndex = 0;
$aFieldsMap = array();
@@ -1326,16 +1325,13 @@ EOF
{
$sActionLabel = $aStimuli[$sStimulus]->GetLabel();
$sActionDetails = $aStimuli[$sStimulus]->GetDescription();
- $aTransition = $aTransitions[$sStimulus];
- $sTargetState = $aTransition['target_state'];
- $aTargetStates = MetaModel::EnumStates($sClass);
- $aTargetState = $aTargetStates[$sTargetState];
- $aExpectedAttributes = $aTargetState['attribute_list'];
+ $sTargetState = $aTransitions[$sStimulus]['target_state'];
+ $aExpectedAttributes = $oObj->GetTransitionAttributes($sStimulus /* cureent state */);
$aDetails = array();
$aErrors = array();
foreach($aExpectedAttributes as $sAttCode => $iExpectCode)
{
- $iFlags = $oObj->GetAttributeFlags($sAttCode);
+ $iFlags = $oObj->GetTransitionFlags($sAttCode, $sStimulus);
if (($iExpectCode & (OPT_ATT_MUSTCHANGE|OPT_ATT_MUSTPROMPT)) || ($oObj->Get($sAttCode) == '') )
{
$paramValue = utils::ReadPostedParam("attr_$sAttCode", '', 'raw_data');
@@ -1450,16 +1446,13 @@ EOF
{
$sActionLabel = $aStimuli[$sStimulus]->GetLabel();
$sActionDetails = $aStimuli[$sStimulus]->GetDescription();
- $aTransition = $aTransitions[$sStimulus];
- $sTargetState = $aTransition['target_state'];
- $aTargetStates = MetaModel::EnumStates($sClass);
- $aTargetState = $aTargetStates[$sTargetState];
- $aExpectedAttributes = $aTargetState['attribute_list'];
+ $sTargetState = $aTransitions[$sStimulus]['target_state'];
+ $aExpectedAttributes = $oObj->GetTransitionAttributes($sStimulus /*, current state*/);
$aDetails = array();
$aErrors = array();
foreach($aExpectedAttributes as $sAttCode => $iExpectCode)
{
- $iFlags = $oObj->GetAttributeFlags($sAttCode);
+ $iFlags = $oObj->GetTransitionFlags($sAttCode, $sStimulus);
if (($iExpectCode & (OPT_ATT_MUSTCHANGE|OPT_ATT_MUSTPROMPT)) || ($oObj->Get($sAttCode) == '') )
{
$paramValue = utils::ReadPostedParam("attr_$sAttCode", '', 'raw_data');
diff --git a/setup/compiler.class.inc.php b/setup/compiler.class.inc.php
index d353c38a8..7ea224cec 100644
--- a/setup/compiler.class.inc.php
+++ b/setup/compiler.class.inc.php
@@ -1536,7 +1536,29 @@ EOF
$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";
+
+ $sLifecycle .= " MetaModel::Init_DefineTransition(\"$sState\", \"$sStimulus\", array(\n";
+ $sLifecycle .= " \"target_state\"=>\"$sTargetState\",\n";
+ $sLifecycle .= " \"actions\"=>array($sActions),\n";
+ $sLifecycle .= " \"user_restriction\"=>null,\n";
+ $sLifecycle .= " \"attribute_list\"=>array(\n";
+
+ $oFlags = $oTransition->GetOptionalElement('flags');
+ if($oFlags !== null)
+ {
+ foreach ($oFlags->getElementsByTagName('attribute') as $oAttributeNode)
+ {
+ $sFlags = $this->FlagsToPHP($oAttributeNode);
+ if (strlen($sFlags) > 0)
+ {
+ $sAttCode = $oAttributeNode->GetAttribute('id');
+ $sLifecycle .= " '$sAttCode' => $sFlags,\n";
+ }
+ }
+ }
+
+ $sLifecycle .= " )\n";
+ $sLifecycle .= " ));\n";
}
}
}
diff --git a/setup/itopdesignformat.class.inc.php b/setup/itopdesignformat.class.inc.php
index cd5bd2d6c..dc798f44c 100644
--- a/setup/itopdesignformat.class.inc.php
+++ b/setup/itopdesignformat.class.inc.php
@@ -1,5 +1,5 @@
LogWarning('The attribute _delta="force" is not supported, converted to _delta="define" ('.$iCount.' instances processed).');
}
+
+ // Remove attribute flags on transitions
+ //
+ $oNodeList = $oXPath->query("/itop_design/classes//class/lifecycle/states/state/transitions/transition/flags");
+ $this->LogWarning('Before removing flags nodes');
+ foreach ($oNodeList as $oNode)
+ {
+ $this->LogWarning('Attribute flags '.self::GetItopNodePath($oNode).' is irrelevant on transition and must be removed.');
+ $this->DeleteNode($oNode);
+ }
}