diff --git a/application/cmdbabstract.class.inc.php b/application/cmdbabstract.class.inc.php index ed829cd0a..9ec6d46fe 100644 --- a/application/cmdbabstract.class.inc.php +++ b/application/cmdbabstract.class.inc.php @@ -1717,7 +1717,26 @@ EOF $sButtons .= "\n"; } - + $aTransitions = $this->EnumTransitions(); + if (count($aTransitions)) + { + $oSetToCheckRights = DBObjectSet::FromObject($this); + $aStimuli = Metamodel::EnumStimuli($sClass); + foreach($aTransitions as $sStimulusCode => $aTransitionDef) + { + $iActionAllowed = (get_class($aStimuli[$sStimulusCode]) == 'StimulusUserAction') ? UserRights::IsStimulusAllowed($sClass, $sStimulusCode, $oSetToCheckRights) : UR_ALLOWED_NO; + switch($iActionAllowed) + { + case UR_ALLOWED_YES: + $sButtons .= "\n"; + break; + + default: + // Do nothing + } + } + } + $bDisplayActionsAtTop = MetaModel::GetConfig()->Get('display_actions_at_top'); $iTransactionId = utils::GetNewTransactionId(); $oPage->SetTransactionId($iTransactionId); @@ -2530,5 +2549,54 @@ EOF $oPage->add(''); } } + + public function GetExpectedAttributes($sCurrentState, $sStimulus, $bOnlyNewOnes) + { + $aTransitions = $this->EnumTransitions(); + $aStimuli = MetaModel::EnumStimuli(get_class($this)); + if (!isset($aTransitions[$sStimulus])) + { + // Invalid stimulus + throw new ApplicationException(Dict::Format('UI:Error:Invalid_Stimulus_On_Object_In_State', $sStimulus, $oObj->GetName(), $oObj->GetStateLabel())); + } + $aTransition = $aTransitions[$sStimulus]; + $sTargetState = $aTransition['target_state']; + $aTargetStates = MetaModel::EnumStates(get_class($this)); + $aTargetState = $aTargetStates[$sTargetState]; + $aCurrentState = $aTargetStates[$this->GetState()]; + $aExpectedAttributes = $aTargetState['attribute_list']; + $aCurrentAttributes = $aCurrentState['attribute_list']; + + $aComputedAttributes = array(); + foreach($aExpectedAttributes as $sAttCode => $iExpectCode) + { + if (!array_key_exists($sAttCode, $aCurrentAttributes)) + { + $aComputedAttributes[$sAttCode] = $iExpectCode; + } + else + { + if ( !($aCurrentAttributes[$sAttCode] & (OPT_ATT_HIDDEN|OPT_ATT_READONLY)) ) + { + $iExpectCode = $iExpectCode & ~(OPT_ATT_MUSTPROMPT|OPT_ATT_MUSTCHANGE); // Already prompted/changed, reset the flags + } + //TODO: better check if the attribute is not *null* + if ( ($iExpectCode & OPT_ATT_MANDATORY) && ($this->Get($sAttCode) != '')) + { + $iExpectCode = $iExpectCode & ~(OPT_ATT_MANDATORY); // If the attribute is present, then no need to request its presence + } + + $aComputedAttributes[$sAttCode] = $iExpectCode; + } + + $aComputedAttributes[$sAttCode] = $aComputedAttributes[$sAttCode] & ~(OPT_ATT_READONLY|OPT_ATT_HIDDEN); // Don't care about this form now + + if ($aComputedAttributes[$sAttCode] == 0) + { + unset($aComputedAttributes[$sAttCode]); + } + } + return $aComputedAttributes; + } } ?> diff --git a/pages/UI.php b/pages/UI.php index 5c459d6c7..61196f934 100644 --- a/pages/UI.php +++ b/pages/UI.php @@ -353,6 +353,52 @@ EOF } } +/** + * Apply the 'next-action' to the given object or redirect to the page that prompts for additional information if needed + * @param $oP WebPage The page for the output + * @param $oObj CMDBObject The object to process + * @param $sNextAction string The code of the stimulus for the 'action' (i.e. Transition) to apply + * @param $oMyChange CMDBChange The change used to log the modifications or null is none is available (a new one will be created) + */ +function ApplyNextAction(Webpage $oP, CMDBObject $oObj, $sNextAction, $oMyChange) +{ + // Here handle the apply stimulus + $aTransitions = $oObj->EnumTransitions(); + $aStimuli = MetaModel::EnumStimuli(get_class($oObj)); + if (!isset($aTransitions[$sNextAction])) + { + // Invalid stimulus + throw new ApplicationException(Dict::Format('UI:Error:Invalid_Stimulus_On_Object_In_State', $sNextAction, $oObj->GetName(), $oObj->GetStateLabel())); + } + // Get the list of missing mandatory fields for the target state, considering only the changes from the previous form (i.e don't prompt twice) + $aExpectedAttributes = $oObj->GetExpectedAttributes($oObj->GetState(), $sNextAction, true /* $bOnlyNewOnes */); + + if (count($aExpectedAttributes) == 0) + { + // If all the mandatory fields are already present, just apply the transition silently... + if ($oObj->ApplyStimulus($sNextAction)) + { + if ($oMyChange == null) + { + $oMyChange = MetaModel::NewObject("CMDBChange"); + $oMyChange->Set("date", time()); + $sUserString = CMDBChange::GetCurrentUserName(); + $oMyChange->Set("userinfo", $sUserString); + $iChangeId = $oMyChange->DBInsert(); + } + $oObj->DBUpdateTracked($oMyChange); + } + $oObj->DisplayDetails($oP); + } + else + { + // redirect to the 'stimulus' action + $oAppContext = new ApplicationContext(); +//echo "
Missing Attributes
".print_r($aExpectedAttributes, true)."\n"; + + $oP->add_header('Location: '.utils::GetAbsoluteUrlAppRoot().'pages/UI.php?operation=stimulus&class='.get_class($oObj).'&stimulus='.$sNextAction.'&id='.$oObj->getKey().'&'.$oAppContext->GetForLink()); + } +} /** * Displays the details of an object * @param $oP WebPage Page for the output @@ -1172,6 +1218,7 @@ EOF } else { + $oMyChange = null; $oObj->UpdateObjectFromPostedForm(); if (!$oObj->IsModified()) @@ -1217,7 +1264,16 @@ EOF if ($bDisplayDetails) { $oObj = MetaModel::GetObject(get_class($oObj), $oObj->GetKey()); //Workaround: reload the object so that the linkedset are displayed properly - $oObj->DisplayDetails($oP); + $sNextAction = utils::ReadPostedParam('next_action', ''); + if (!empty($sNextAction)) + { + ApplyNextAction($oP, $oObj, $sNextAction, $oMyChange); + } + else + { + // Nothing more to do + $oObj->DisplayDetails($oP); + } } break; @@ -1324,7 +1380,18 @@ EOF utils::RemoveTransaction($sTransactionId); $oP->set_title(Dict::S('UI:PageTitle:ObjectCreated')); $oP->add("