public function DisplayModifyForm(WebPage $oPage, $aExtraParams = array()) { $sOwnershipToken = null; $iKey = $this->GetKey(); $sClass = get_class($this); if ($iKey > 0) { // The concurrent access lock makes sense only for already existing objects $LockEnabled = MetaModel::GetConfig()->Get('concurrent_lock_enabled'); if ($LockEnabled) { $sOwnershipToken = utils::ReadPostedParam('ownership_token', null, false, 'raw_data'); if ($sOwnershipToken !== null) { // We're probably inside something like "apply_modify" where the validation failed and we must prompt the user again to edit the object // let's extend our lock $aLockInfo = iTopOwnershipLock::ExtendLock($sClass, $iKey, $sOwnershipToken); $sOwnershipDate = $aLockInfo['acquired']; } else { $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' => 'modify')); return; } } } } if (isset($aExtraParams['wizard_container']) && $aExtraParams['wizard_container']) { $sClassLabel = MetaModel::GetName($sClass); $oPage->set_title(Dict::Format('UI:ModificationPageTitle_Object_Class', $this->GetRawName(), $sClassLabel)); // Set title will take care of the encoding $oPage->add("<div class=\"page_header\">\n"); $oPage->add("<h1>" . $this->GetIcon() . " " . Dict::Format('UI:ModificationTitle_Class_Object', $sClassLabel, $this->GetName()) . "</h1>\n"); $oPage->add("</div>\n"); $oPage->add("<div class=\"wizContainer\">\n"); } self::$iGlobalFormId++; $this->aFieldsMap = array(); $sPrefix = ''; if (isset($aExtraParams['formPrefix'])) { $sPrefix = $aExtraParams['formPrefix']; } $aFieldsComments = isset($aExtraParams['fieldsComments']) ? $aExtraParams['fieldsComments'] : array(); $this->m_iFormId = $sPrefix . self::$iGlobalFormId; $oAppContext = new ApplicationContext(); $sStateAttCode = MetaModel::GetStateAttributeCode($sClass); $aDetails = array(); $aFieldsMap = array(); if (!isset($aExtraParams['action'])) { $sFormAction = utils::GetAbsoluteUrlAppRoot() . 'pages/' . $this->GetUIPage(); // No parameter in the URL, the only parameter will be the ones passed through the form } else { $sFormAction = $aExtraParams['action']; } // Custom label for the apply button ? if (isset($aExtraParams['custom_button'])) { $sApplyButton = $aExtraParams['custom_button']; } else { if ($iKey > 0) { $sApplyButton = Dict::S('UI:Button:Apply'); } else { $sApplyButton = Dict::S('UI:Button:Create'); } } // Custom operation for the form ? if (isset($aExtraParams['custom_operation'])) { $sOperation = $aExtraParams['custom_operation']; } else { if ($iKey > 0) { $sOperation = 'apply_modify'; } else { $sOperation = 'apply_new'; } } if ($iKey > 0) { // The object already exists in the database, it's a modification $sButtons = "<input id=\"{$sPrefix}_id\" type=\"hidden\" name=\"id\" value=\"{$iKey}\">\n"; $sButtons .= "<input type=\"hidden\" name=\"operation\" value=\"{$sOperation}\">\n"; $sButtons .= "<button type=\"button\" class=\"action cancel\"><span>" . Dict::S('UI:Button:Cancel') . "</span></button> \n"; $sButtons .= "<button type=\"submit\" class=\"action\"><span>{$sApplyButton}</span></button>\n"; } else { // The object does not exist in the database it's a creation $sButtons = "<input type=\"hidden\" name=\"operation\" value=\"{$sOperation}\">\n"; $sButtons .= "<button type=\"button\" class=\"action cancel\">" . Dict::S('UI:Button:Cancel') . "</button> \n"; $sButtons .= "<button type=\"submit\" class=\"action\"><span>{$sApplyButton}</span></button>\n"; } $aTransitions = $this->EnumTransitions(); if (!isset($aExtraParams['custom_operation']) && count($aTransitions)) { // transitions are displayed only for the standard new/modify actions, not for modify_all or any other case... $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 .= "<button type=\"submit\" name=\"next_action\" value=\"{$sStimulusCode}\" class=\"action\"><span>" . $aStimuli[$sStimulusCode]->GetLabel() . "</span></button>\n"; break; default: // Do nothing } } } $sButtonsPosition = MetaModel::GetConfig()->Get('buttons_position'); $iTransactionId = isset($aExtraParams['transaction_id']) ? $aExtraParams['transaction_id'] : utils::GetNewTransactionId(); $oPage->SetTransactionId($iTransactionId); $oPage->add("<form action=\"{$sFormAction}\" id=\"form_{$this->m_iFormId}\" enctype=\"multipart/form-data\" method=\"post\" onSubmit=\"return OnSubmit('form_{$this->m_iFormId}');\">\n"); $sStatesSelection = ''; if (!isset($aExtraParams['custom_operation']) && $this->IsNew()) { $aInitialStates = MetaModel::EnumInitialStates($sClass); //$aInitialStates = array('new' => 'foo', 'closed' => 'bar'); if (count($aInitialStates) > 1) { $sStatesSelection = Dict::Format('UI:Create_Class_InState', MetaModel::GetName($sClass)) . '<select name="obj_state" class="state_select_' . $this->m_iFormId . '">'; foreach ($aInitialStates as $sStateCode => $sStateData) { $sSelected = ''; if ($sStateCode == $this->GetState()) { $sSelected = ' selected'; } $sStatesSelection .= '<option value="' . $sStateCode . '"' . $sSelected . '>' . MetaModel::GetStateLabel($sClass, $sStateCode) . '</option>'; } $sStatesSelection .= '</select>'; $oPage->add_ready_script("\$('.state_select_{$this->m_iFormId}').change( function() { oWizardHelper{$sPrefix}.ReloadObjectCreationForm('form_{$this->m_iFormId}', \$(this).val()); } );"); } } $sConfirmationMessage = addslashes(Dict::S('UI:NavigateAwayConfirmationMessage')); $sJSToken = json_encode($sOwnershipToken); $oPage->add_ready_script(<<<EOF \t\$(window).unload(function() { return OnUnload('{$iTransactionId}', '{$sClass}', {$iKey}, {$sJSToken}) } ); \twindow.onbeforeunload = function() { \t\tif (!window.bInSubmit && !window.bInCancel) \t\t{ \t\t\treturn '{$sConfirmationMessage}';\t \t\t} \t\t// return nothing ! safer for IE \t}; EOF ); if ($sButtonsPosition != 'bottom') { // top or both, display the buttons here $oPage->p($sStatesSelection); $oPage->add($sButtons); } $oPage->AddTabContainer(OBJECT_PROPERTIES_TAB, $sPrefix); $oPage->SetCurrentTabContainer(OBJECT_PROPERTIES_TAB); $oPage->SetCurrentTab(Dict::S('UI:PropertiesTab')); $aFieldsMap = $this->DisplayBareProperties($oPage, true, $sPrefix, $aExtraParams); if ($iKey > 0) { $aFieldsMap['id'] = $sPrefix . '_id'; } // Now display the relations, one tab per relation if (!isset($aExtraParams['noRelations'])) { $this->DisplayBareRelations($oPage, true); // Edit mode, will fill $this->aFieldsMap $aFieldsMap = array_merge($aFieldsMap, $this->aFieldsMap); } $oPage->SetCurrentTab(''); $oPage->add("<input type=\"hidden\" name=\"class\" value=\"{$sClass}\">\n"); $oPage->add("<input type=\"hidden\" name=\"transaction_id\" value=\"{$iTransactionId}\">\n"); foreach ($aExtraParams as $sName => $value) { if (is_scalar($value)) { $oPage->add("<input type=\"hidden\" name=\"{$sName}\" value=\"{$value}\">\n"); } } if ($sOwnershipToken !== null) { $oPage->add("<input type=\"hidden\" name=\"ownership_token\" value=\"" . htmlentities($sOwnershipToken, ENT_QUOTES, 'UTF-8') . "\">\n"); } $oPage->add($oAppContext->GetForForm()); if ($sButtonsPosition != 'top') { // bottom or both: display the buttons here $oPage->p($sStatesSelection); $oPage->add($sButtons); } // Hook the cancel button via jQuery so that it can be unhooked easily as well if needed $sDefaultUrl = utils::GetAbsoluteUrlAppRoot() . 'pages/UI.php?operation=cancel&' . $oAppContext->GetForLink(); $oPage->add_ready_script("\$('#form_{$this->m_iFormId} button.cancel').click( function() { BackToDetails('{$sClass}', {$iKey}, '{$sDefaultUrl}', {$sJSToken})} );"); $oPage->add("</form>\n"); if (isset($aExtraParams['wizard_container']) && $aExtraParams['wizard_container']) { $oPage->add("</div>\n"); } $iFieldsCount = count($aFieldsMap); $sJsonFieldsMap = json_encode($aFieldsMap); $sState = $this->GetState(); $sSessionStorageKey = $sClass . '_' . $iKey; $oPage->add_script(<<<EOF \t\tsessionStorage.removeItem('{$sSessionStorageKey}'); \t\t \t\t// Create the object once at the beginning of the page... \t\tvar oWizardHelper{$sPrefix} = new WizardHelper('{$sClass}', '{$sPrefix}', '{$sState}'); \t\toWizardHelper{$sPrefix}.SetFieldsMap({$sJsonFieldsMap}); \t\toWizardHelper{$sPrefix}.SetFieldsCount({$iFieldsCount}); EOF ); $oPage->add_ready_script(<<<EOF \t\toWizardHelper{$sPrefix}.UpdateWizard(); \t\t// Starts the validation when the page is ready \t\tCheckFields('form_{$this->m_iFormId}', false); EOF ); if ($sOwnershipToken !== null) { $this->GetOwnershipJSHandler($oPage, $sOwnershipToken); } else { // Probably a new object (or no concurrent lock), let's add a watchdog so that the session is kept open while editing $iInterval = MetaModel::GetConfig()->Get('concurrent_lock_expiration_delay') * 1000 / 2; if ($iInterval > 0) { $iInterval = max(MIN_WATCHDOG_INTERVAL * 1000, $iInterval); // Minimum interval for the watchdog is MIN_WATCHDOG_INTERVAL $oPage->add_ready_script(<<<EOF \t\t\t\twindow.setInterval(function() { \t\t\t\t\t\$.post(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php', {operation: 'watchdog'}); \t\t\t\t}, {$iInterval}); EOF ); } } }
case 'export_cancel': $token = utils::ReadParam('token', null); if ($token !== null) { $oExporter = BulkExport::FindExporterFromToken($token); if ($oExporter) { $oExporter->Cleanup(); } } $aResult = array('code' => 'error', 'percentage' => 100, 'message' => Dict::S('Core:BulkExport:ExportCancelledByUser')); $oPage->add(json_encode($aResult)); break; case 'extend_lock': $sObjClass = utils::ReadParam('obj_class', '', false, 'class'); $iObjKey = (int) utils::ReadParam('obj_key', 0, false, 'integer'); $sToken = utils::ReadParam('token', 0, false, 'raw_data'); $aResult = iTopOwnershipLock::ExtendLock($sObjClass, $iObjKey, $sToken); if (!$aResult['status']) { if ($aResult['operation'] == 'lost') { $sName = $aResult['owner']->GetName(); if ($aResult['owner']->Get('contactid') != 0) { $sName .= ' (' . $aResult['owner']->Get('contactid_friendlyname') . ')'; } $aResult['message'] = Dict::Format('UI:CurrentObjectIsLockedBy_User', $sName); $aResult['popup_message'] = Dict::Format('UI:CurrentObjectIsLockedBy_User_Explanation', $sName); } else { if ($aResult['operation'] == 'expired') { $aResult['message'] = Dict::S('UI:CurrentObjectLockExpired'); $aResult['popup_message'] = Dict::S('UI:CurrentObjectLockExpired_Explanation'); } } }