diff --git a/application/cmdbabstract.class.inc.php b/application/cmdbabstract.class.inc.php index 66ae5b847..9065e5a9e 100644 --- a/application/cmdbabstract.class.inc.php +++ b/application/cmdbabstract.class.inc.php @@ -2121,6 +2121,138 @@ EOF } return $oObj->DisplayModifyForm( $oPage, $aExtraParams); } + + public function DisplayStimulusForm(WebPage $oPage, $sStimulus) + { + $sClass = get_class($this); + $aTransitions = $this->EnumTransitions(); + $aStimuli = MetaModel::EnumStimuli($sClass); + if (!isset($aTransitions[$sStimulus])) + { + // Invalid stimulus + throw new ApplicationException(Dict::Format('UI:Error:Invalid_Stimulus_On_Object_In_State', $sStimulus, $this->GetName(), $this->GetStateLabel())); + } + $sActionLabel = $aStimuli[$sStimulus]->GetLabel(); + $sActionDetails = $aStimuli[$sStimulus]->GetDescription(); + $aTransition = $aTransitions[$sStimulus]; + $sTargetState = $aTransition['target_state']; + $aTargetStates = MetaModel::EnumStates($sClass); + $oPage->add("
\n"); + $oPage->add("

$sActionLabel - {$this->GetName()}

\n"); + $oPage->set_title($sActionLabel); + $oPage->add("
\n"); + $aTargetState = $aTargetStates[$sTargetState]; + $aExpectedAttributes = $aTargetState['attribute_list']; + $oPage->add("

$sActionDetails

\n"); + $sButtonsPosition = MetaModel::GetConfig()->Get('buttons_position'); + if ($sButtonsPosition == 'bottom') + { + // bottom: Displays the ticket details BEFORE the actions + $oPage->add('
'); + $this->DisplayBareProperties($oPage); + $oPage->add('
'); + } + $oPage->add("
\n"); + $oPage->add("
\n"); + $aDetails = array(); + $iFieldIndex = 0; + $aFieldsMap = array(); + + $aDetailsList =$this->FlattenZList(MetaModel::GetZListItems($sClass, 'details')); + // Order the fields based on their dependencies, set the fields for which there is only one possible value + // and perform this in the order of dependencies to avoid dead-ends + $aDeps = array(); + foreach($aDetailsList as $sAttCode) + { + $aDeps[$sAttCode] = MetaModel::GetPrequisiteAttributes($sClass, $sAttCode); + } + $aList =$this->OrderDependentFields($aDeps); + + foreach($aList as $sAttCode) + { + // Consider only the "expected" fields for the target state + if (array_key_exists($sAttCode, $aExpectedAttributes)) + { + $iExpectCode = $aExpectedAttributes[$sAttCode]; + // Prompt for an attribute if + // - the attribute must be changed or must be displayed to the user for confirmation + // - or the field is mandatory and currently empty + if ( ($iExpectCode & (OPT_ATT_MUSTCHANGE | OPT_ATT_MUSTPROMPT)) || + (($iExpectCode & OPT_ATT_MANDATORY) && ($this->Get($sAttCode) == '')) ) + { + $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode); + $aArgs = array('this' => $this); + // If the field is mandatory, set it to the only possible value + if ((!$oAttDef->IsNullAllowed()) || ($iExpectCode & OPT_ATT_MANDATORY)) + { + if ($oAttDef->IsExternalKey()) + { + $oAllowedValues = MetaModel::GetAllowedValuesAsObjectSet($sClass, $sAttCode, $aArgs); + if ($oAllowedValues->Count() == 1) + { + $oRemoteObj = $oAllowedValues->Fetch(); + $this->Set($sAttCode, $oRemoteObj->GetKey()); + } + } + else + { + $aAllowedValues = MetaModel::GetAllowedValues_att($sClass, $sAttCode, $aArgs); + if (count($aAllowedValues) == 1) + { + $aValues = array_keys($aAllowedValues); + $this->Set($sAttCode, $aValues[0]); + } + } + } + $sHTMLValue = cmdbAbstractObject::GetFormElementForField($oPage, $sClass, $sAttCode, $oAttDef,$this->Get($sAttCode),$this->GetEditValue($sAttCode), 'att_'.$iFieldIndex, '', $iExpectCode, $aArgs); + $aDetails[] = array('label' => ''.$oAttDef->GetLabel().'', 'value' => "$sHTMLValue"); + $aFieldsMap[$sAttCode] = 'att_'.$iFieldIndex; + $iFieldIndex++; + } + } + } + + $oPage->add('
'); + $oPage->details($aDetails); + $oPage->add('
'); + $oPage->add("GetKey()."\" id=\"id\">\n"); + $aFieldsMap['id'] = 'id'; + $oPage->add("\n"); + $oPage->add("\n"); + $oPage->add("\n"); + $oPage->add("\n"); + $oAppContext = new ApplicationContext(); + $oPage->add($oAppContext->GetForForm()); + $oPage->add("    \n"); + $oPage->add("\n"); + $oPage->add("
\n"); + $oPage->add("
\n"); + if ($sButtonsPosition != 'top') + { + // bottom or both: Displays the ticket details AFTER the actions + $oPage->add('
'); + $this->DisplayBareProperties($oPage); + $oPage->add('
'); + } + + $iFieldsCount = count($aFieldsMap); + $sJsonFieldsMap = json_encode($aFieldsMap); + + $oPage->add_script( +<<add_ready_script( +<<GetName(), $oObj->GetStateLabel())); + throw new ApplicationException(Dict::Format('UI:Error:Invalid_Stimulus_On_Object_In_State', $sStimulus,$this->GetName(),$this->GetStateLabel())); } $aTransition = $aTransitions[$sStimulus]; $sTargetState = $aTransition['target_state']; diff --git a/pages/UI.php b/pages/UI.php index 84e7889ca..f63670b48 100644 --- a/pages/UI.php +++ b/pages/UI.php @@ -398,6 +398,7 @@ try case 'form_for_modify_all': // Form to modify multiple objects (bulk modify) case 'bulk_stimulus': // For to apply a stimulus to multiple objects case 'stimulus': // Form displayed when applying a stimulus (state change) + case 'apply_stimulus': // Form displayed when applying a stimulus (state change) $oP->add_linked_script("../js/json.js"); $oP->add_linked_script("../js/forms-json-utils.js"); $oP->add_linked_script("../js/wizardhelper.js"); @@ -1381,132 +1382,7 @@ EOF $oObj = MetaModel::GetObject($sClass, $id, false); if ($oObj != null) { - $aTransitions = $oObj->EnumTransitions(); - $aStimuli = MetaModel::EnumStimuli($sClass); - if (!isset($aTransitions[$sStimulus])) - { - // Invalid stimulus - throw new ApplicationException(Dict::Format('UI:Error:Invalid_Stimulus_On_Object_In_State', $sStimulus, $oObj->GetName(), $oObj->GetStateLabel())); - } - $sActionLabel = $aStimuli[$sStimulus]->GetLabel(); - $sActionDetails = $aStimuli[$sStimulus]->GetDescription(); - $aTransition = $aTransitions[$sStimulus]; - $sTargetState = $aTransition['target_state']; - $aTargetStates = MetaModel::EnumStates($sClass); - $oP->add("
\n"); - $oP->add("

$sActionLabel - {$oObj->GetName()}

\n"); - $oP->set_title($sActionLabel); - $oP->add("
\n"); - $aTargetState = $aTargetStates[$sTargetState]; - $aExpectedAttributes = $aTargetState['attribute_list']; - $oP->add("

$sActionDetails

\n"); - $sButtonsPosition = MetaModel::GetConfig()->Get('buttons_position'); - if ($sButtonsPosition == 'bottom') - { - // bottom: Displays the ticket details BEFORE the actions - $oP->add('
'); - $oObj->DisplayBareProperties($oP); - $oP->add('
'); - } - $oP->add("
\n"); - $oP->add("
\n"); - $aDetails = array(); - $iFieldIndex = 0; - $aFieldsMap = array(); - - $aDetailsList = $oObj->FlattenZList(MetaModel::GetZListItems($sClass, 'details')); - // Order the fields based on their dependencies, set the fields for which there is only one possible value - // and perform this in the order of dependencies to avoid dead-ends - $aDeps = array(); - foreach($aDetailsList as $sAttCode) - { - $aDeps[$sAttCode] = MetaModel::GetPrequisiteAttributes($sClass, $sAttCode); - } - $aList = $oObj->OrderDependentFields($aDeps); - - foreach($aList as $sAttCode) - { - // Consider only the "expected" fields for the target state - if (array_key_exists($sAttCode, $aExpectedAttributes)) - { - $iExpectCode = $aExpectedAttributes[$sAttCode]; - // Prompt for an attribute if - // - the attribute must be changed or must be displayed to the user for confirmation - // - or the field is mandatory and currently empty - if ( ($iExpectCode & (OPT_ATT_MUSTCHANGE | OPT_ATT_MUSTPROMPT)) || - (($iExpectCode & OPT_ATT_MANDATORY) && ($oObj->Get($sAttCode) == '')) ) - { - $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode); - $aArgs = array('this' => $oObj); - // If the field is mandatory, set it to the only possible value - if ((!$oAttDef->IsNullAllowed()) || ($iExpectCode & OPT_ATT_MANDATORY)) - { - if ($oAttDef->IsExternalKey()) - { - $oAllowedValues = MetaModel::GetAllowedValuesAsObjectSet($sClass, $sAttCode, $aArgs); - if ($oAllowedValues->Count() == 1) - { - $oRemoteObj = $oAllowedValues->Fetch(); - $oObj->Set($sAttCode, $oRemoteObj->GetKey()); - } - } - else - { - $aAllowedValues = MetaModel::GetAllowedValues_att($sClass, $sAttCode, $aArgs); - if (count($aAllowedValues) == 1) - { - $aValues = array_keys($aAllowedValues); - $oObj->Set($sAttCode, $aValues[0]); - } - } - } - $sHTMLValue = cmdbAbstractObject::GetFormElementForField($oP, $sClass, $sAttCode, $oAttDef, $oObj->Get($sAttCode), $oObj->GetEditValue($sAttCode), 'att_'.$iFieldIndex, '', $iExpectCode, $aArgs); - $aDetails[] = array('label' => ''.$oAttDef->GetLabel().'', 'value' => "$sHTMLValue"); - $aFieldsMap[$sAttCode] = 'att_'.$iFieldIndex; - $iFieldIndex++; - } - } - } - - $oP->add('
'); - $oP->details($aDetails); - $oP->add('
'); - $oP->add("\n"); - $aFieldsMap['id'] = 'id'; - $oP->add("\n"); - $oP->add("\n"); - $oP->add("\n"); - $oP->add("\n"); - $oP->add($oAppContext->GetForForm()); - $oP->add("    \n"); - $oP->add("\n"); - $oP->add("
\n"); - $oP->add("
\n"); - if ($sButtonsPosition != 'top') - { - // bottom or both: Displays the ticket details AFTER the actions - $oP->add('
'); - $oObj->DisplayBareProperties($oP); - $oP->add('
'); - } - - $iFieldsCount = count($aFieldsMap); - $sJsonFieldsMap = json_encode($aFieldsMap); - - $oP->add_script( -<<add_ready_script( -<<DisplayStimulusForm($oP, $sStimulus); } else { @@ -1533,6 +1409,7 @@ EOF $aStimuli = MetaModel::EnumStimuli($sClass); $sMessage = ''; $sSeverity = 'ok'; + $bDisplayDetails = true; if (!isset($aTransitions[$sStimulus])) { throw new ApplicationException(Dict::Format('UI:Error:Invalid_Stimulus_On_Object_In_State', $sStimulus, $oObj->GetName(), $oObj->GetStateLabel())); @@ -1568,20 +1445,52 @@ EOF } } - $oObj->UpdateObjectFromPostedForm('', array_keys($aExpectedAttributes), $sTargetState); + $oObj->UpdateObjectFromPostedForm('', array_keys($aExpectedAttributes), $sTargetState); if (count($aErrors) == 0) { - if ($oObj->ApplyStimulus($sStimulus)) + $sIssues = ''; + $bApplyStimulus = true; + list($bRes, $aIssues) = $oObj->CheckToWrite(); // Check before trying to write the object + if ($bRes) { - $oObj->DBUpdate(); - $sMessage = Dict::Format('UI:Class_Object_Updated', MetaModel::GetName(get_class($oObj)), $oObj->GetName()); - $sSeverity = 'ok'; + try + { + $bApplyStimulus = $oObj->ApplyStimulus($sStimulus); // will write the object in the DB + } + catch(CoreException $e) + { + // Rollback to the previous state... by reloading the object from the database and applying the modifications again + $oObj = MetaModel::GetObject(get_class($oObj), $oObj->GetKey()); + $oObj->UpdateObjectFromPostedForm('', array_keys($aExpectedAttributes), $sTargetState); + $aData = $e->getContextData(); + $sIssues = (array_key_exists('issues', $aData)) ? $aData['issues'] : 'Unknown error...'; + } } else + { + $sIssues = implode(' ', $aIssues); + } + + if (!$bApplyStimulus) { $sMessage = Dict::S('UI:FailedToApplyStimuli'); - $sSeverity = 'error'; + $sSeverity = 'error'; + } + else if ($sIssues != '') + { + $bDisplayDetails = false; + // Found issues, explain and give the user a second chance + // + $oObj->DisplayStimulusForm($oP, $sStimulus); + $sIssueDesc = Dict::Format('UI:ObjectCouldNotBeWritten',$sIssues); + $oP->add_ready_script("alert('".addslashes($sIssueDesc)."');"); + } + else + { + $sMessage = Dict::Format('UI:Class_Object_Updated', MetaModel::GetName(get_class($oObj)), $oObj->GetName()); + $sSeverity = 'ok'; + utils::RemoveTransaction($sTransactionId); } } else @@ -1590,7 +1499,10 @@ EOF $sSeverity = 'error'; } } - ReloadAndDisplay($oP, $oObj, 'apply_stimulus', $sMessage, $sSeverity); + if ($bDisplayDetails) + { + ReloadAndDisplay($oP, $oObj, 'apply_stimulus', $sMessage, $sSeverity); + } } else {