public function DisplayStimulusForm(WebPage $oPage, $sStimulus) { $sClass = get_class($this); $iKey = $this->GetKey(); $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())); } // Check for concurrent access lock $LockEnabled = MetaModel::GetConfig()->Get('concurrent_lock_enabled'); $sOwnershipToken = null; if ($LockEnabled) { $sOwnershipToken = utils::ReadPostedParam('ownership_token', null, false, 'raw_data'); $aLockInfo = iTopOwnershipLock::AcquireLock($sClass, $iKey); if ($aLockInfo['success']) { $sOwnershipToken = $aLockInfo['token']; $sOwnershipDate = $aLockInfo['acquired']; } else { $oOwner = $aLockInfo['lock']->GetOwner(); // If the object is locked by the current user, it's worth trying again, since // the lock may be released by 'onunload' which is called AFTER loading the current page. //$bTryAgain = $oOwner->GetKey() == UserRights::GetUserId(); self::ReloadAndDisplay($oPage, $this, array('operation' => 'stimulus', 'stimulus' => $sStimulus)); return; } } $sActionLabel = $aStimuli[$sStimulus]->GetLabel(); $sActionDetails = $aStimuli[$sStimulus]->GetDescription(); $aTransition = $aTransitions[$sStimulus]; $sTargetState = $aTransition['target_state']; $aTargetStates = MetaModel::EnumStates($sClass); $oPage->add("<div class=\"page_header\">\n"); $oPage->add("<h1>{$sActionLabel} - <span class=\"hilite\">{$this->GetName()}</span></h1>\n"); $oPage->set_title($sActionLabel); $oPage->add("</div>\n"); $aTargetState = $aTargetStates[$sTargetState]; $aExpectedAttributes = $aTargetState['attribute_list']; $oPage->add("<h1>{$sActionDetails}</h1>\n"); $sButtonsPosition = MetaModel::GetConfig()->Get('buttons_position'); if ($sButtonsPosition == 'bottom') { // bottom: Displays the ticket details BEFORE the actions $oPage->add('<div class="ui-widget-content">'); $this->DisplayBareProperties($oPage); $oPage->add('</div>'); } $oPage->add("<div class=\"wizContainer\">\n"); $oPage->add("<form id=\"apply_stimulus\" method=\"post\" onSubmit=\"return OnSubmit('apply_stimulus');\">\n"); $aDetails = array(); $iFieldIndex = 0; $aFieldsMap = array(); // The list of candidate fields is made of the ordered list of "details" attributes + other attributes $aAttributes = array(); foreach ($this->FlattenZList(MetaModel::GetZListItems($sClass, 'details')) as $sAttCode) { $aAttributes[$sAttCode] = true; } foreach (MetaModel::GetAttributesList($sClass) as $sAttCode) { if (!array_key_exists($sAttCode, $aAttributes)) { $aAttributes[$sAttCode] = true; } } // 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 ($aAttributes as $sAttCode => $trash) { $aDeps[$sAttCode] = MetaModel::GetPrerequisiteAttributes($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' => '<span>' . $oAttDef->GetLabel() . '</span>', 'value' => "<span id=\"field_att_{$iFieldIndex}\">{$sHTMLValue}</span>"); $aFieldsMap[$sAttCode] = 'att_' . $iFieldIndex; $iFieldIndex++; } } } $oPage->add('<table><tr><td>'); $oPage->details($aDetails); $oPage->add('</td></tr></table>'); $oPage->add("<input type=\"hidden\" name=\"id\" value=\"" . $this->GetKey() . "\" id=\"id\">\n"); $aFieldsMap['id'] = 'id'; $oPage->add("<input type=\"hidden\" name=\"class\" value=\"{$sClass}\">\n"); $oPage->add("<input type=\"hidden\" name=\"operation\" value=\"apply_stimulus\">\n"); $oPage->add("<input type=\"hidden\" name=\"stimulus\" value=\"{$sStimulus}\">\n"); $iTransactionId = utils::GetNewTransactionId(); $oPage->add("<input type=\"hidden\" name=\"transaction_id\" value=\"" . $iTransactionId . "\">\n"); if ($sOwnershipToken !== null) { $oPage->add("<input type=\"hidden\" name=\"ownership_token\" value=\"" . htmlentities($sOwnershipToken, ENT_QUOTES, 'UTF-8') . "\">\n"); } $oAppContext = new ApplicationContext(); $oPage->add($oAppContext->GetForForm()); $oPage->add("<button type=\"button\" class=\"action cancel\" onClick=\"BackToDetails('{$sClass}', " . $this->GetKey() . ", '', '{$sOwnershipToken}')\"><span>" . Dict::S('UI:Button:Cancel') . "</span></button> \n"); $oPage->add("<button type=\"submit\" class=\"action\"><span>{$sActionLabel}</span></button>\n"); $oPage->add("</form>\n"); $oPage->add("</div>\n"); if ($sButtonsPosition != 'top') { // bottom or both: Displays the ticket details AFTER the actions $oPage->add('<div class="ui-widget-content">'); $this->DisplayBareProperties($oPage); $oPage->add('</div>'); } $iFieldsCount = count($aFieldsMap); $sJsonFieldsMap = json_encode($aFieldsMap); $oPage->add_script(<<<EOF \t\t// Initializes the object once at the beginning of the page... \t\tvar oWizardHelper = new WizardHelper('{$sClass}', '', '{$sTargetState}'); \t\toWizardHelper.SetFieldsMap({$sJsonFieldsMap}); \t\toWizardHelper.SetFieldsCount({$iFieldsCount}); EOF ); $sJSToken = json_encode($sOwnershipToken); $oPage->add_ready_script(<<<EOF \t\t// Starts the validation when the page is ready \t\tCheckFields('apply_stimulus', false); \t\t\$(window).unload(function() { return OnUnload('{$iTransactionId}', '{$sClass}', {$iKey}, {$sJSToken}) } ); EOF ); if ($sOwnershipToken !== null) { $this->GetOwnershipJSHandler($oPage, $sOwnershipToken); } }