* @author Romain Quetiez * @author Denis Flaven * @license http://www.opensource.org/licenses/gpl-3.0.html LGPL */ /** * Perform all the needed checks to delete one (or more) objects */ function DeleteObjects(WebPage $oP, $sClass, $aObjects, $bDeleteConfirmed) { $oDeletionPlan = new DeletionPlan(); foreach($aObjects as $oObj) { if ($bDeleteConfirmed) { // Prepare the change reporting // $oMyChange = MetaModel::NewObject("CMDBChange"); $oMyChange->Set("date", time()); $sUserString = CMDBChange::GetCurrentUserName(); $oMyChange->Set("userinfo", $sUserString); $oMyChange->DBInsert(); $oObj->DBDeleteTracked($oMyChange, null, $oDeletionPlan); } else { $oObj->CheckToDelete($oDeletionPlan); } } if ($bDeleteConfirmed) { if (count($aObjects) == 1) { $oObj = $aObjects[0]; $oP->add("

".Dict::Format('UI:Title:DeletionOf_Object', $oObj->GetName())."

\n"); } else { $oP->add("

".Dict::Format('UI:Title:BulkDeletionOf_Count_ObjectsOf_Class', count($aObjects), MetaModel::GetName($sClass))."

\n"); } // Security - do not allow the user to force a forbidden delete by the mean of page arguments... if ($oDeletionPlan->FoundSecurityIssue()) { throw new CoreException(Dict::S('UI:Error:NotEnoughRightsToDelete')); } if ($oDeletionPlan->FoundManualOperation()) { throw new CoreException(Dict::S('UI:Error:CannotDeleteBecauseManualOpNeeded')); } if ($oDeletionPlan->FoundManualDelete()) { throw new CoreException(Dict::S('UI:Error:CannotDeleteBecauseOfDepencies')); } // Report deletions // $aDisplayData = array(); foreach ($oDeletionPlan->ListDeletes() as $sTargetClass => $aDeletes) { foreach ($aDeletes as $iId => $aData) { $oToDelete = $aData['to_delete']; if (isset($aData['requested_explicitely'])) { $sMessage = Dict::S('UI:Delete:Deleted'); } else { $sMessage = Dict::S('UI:Delete:AutomaticallyDeleted'); } $aDisplayData[] = array( 'class' => MetaModel::GetName(get_class($oToDelete)), 'object' => $oToDelete->GetName(), 'consequence' => $sMessage, ); } } // Report updates // foreach ($oDeletionPlan->ListUpdates() as $sTargetClass => $aToUpdate) { foreach ($aToUpdate as $iId => $aData) { $oToUpdate = $aData['to_reset']; $aDisplayData[] = array( 'class' => MetaModel::GetName(get_class($oToUpdate)), 'object' => $oToUpdate->GetHyperLink(), 'consequence' => Dict::Format('UI:Delete:AutomaticResetOf_Fields', $aData['attributes_list']), ); } } // Report automatic jobs // if ($oDeletionPlan->GetTargetCount() > 0) { if (count($aObjects) == 1) { $oObj = $aObjects[0]; $oP->p(Dict::Format('UI:Delete:CleaningUpRefencesTo_Object', $oObj->GetName())); } else { $oP->p(Dict::Format('UI:Delete:CleaningUpRefencesTo_Several_ObjectsOf_Class', count($aObjects), MetaModel::GetName($sClass))); } $aDisplayConfig = array(); $aDisplayConfig['class'] = array('label' => 'Class', 'description' => ''); $aDisplayConfig['object'] = array('label' => 'Object', 'description' => ''); $aDisplayConfig['consequence'] = array('label' => 'Done', 'description' => Dict::S('UI:Delete:Done+')); $oP->table($aDisplayConfig, $aDisplayData); } } else { if (count($aObjects) == 1) { $oObj = $aObjects[0]; $oP->add("

".Dict::Format('UI:Delete:ConfirmDeletionOf_Name', $oObj->GetName())."

\n"); } else { $oP->add("

".Dict::Format('UI:Delete:ConfirmDeletionOf_Count_ObjectsOf_Class', count($aObjects), MetaModel::GetName($sClass))."

\n"); } // Explain what should be done // $aDisplayData = array(); foreach ($oDeletionPlan->ListDeletes() as $sTargetClass => $aDeletes) { foreach ($aDeletes as $iId => $aData) { $oToDelete = $aData['to_delete']; $bAutoDel = (($aData['mode'] == DEL_SILENT) || ($aData['mode'] == DEL_AUTO)); if (array_key_exists('issue', $aData)) { if ($bAutoDel) { if (isset($aData['requested_explicitely'])) { $sConsequence = Dict::Format('UI:Delete:CannotDeleteBecause', $aData['issue']); } else { $sConsequence = Dict::Format('UI:Delete:ShouldBeDeletedAtomaticallyButNotPossible', $aData['issue']); } } else { $sConsequence = Dict::Format('UI:Delete:MustBeDeletedManuallyButNotPossible', $aData['issue']); } } else { if ($bAutoDel) { if (isset($aData['requested_explicitely'])) { $sConsequence = ''; // not applicable } else { $sConsequence = Dict::S('UI:Delete:WillBeDeletedAutomatically'); } } else { $sConsequence = Dict::S('UI:Delete:MustBeDeletedManually'); } } $aDisplayData[] = array( 'class' => MetaModel::GetName(get_class($oToDelete)), 'object' => $oToDelete->GetHyperLink(), 'consequence' => $sConsequence, ); } } foreach ($oDeletionPlan->ListUpdates() as $sRemoteClass => $aToUpdate) { foreach ($aToUpdate as $iId => $aData) { $oToUpdate = $aData['to_reset']; if (array_key_exists('issue', $aData)) { $sConsequence = Dict::Format('UI:Delete:CannotUpdateBecause_Issue', $aData['issue']); } else { $sConsequence = Dict::Format('UI:Delete:WillAutomaticallyUpdate_Fields', $aData['attributes_list']); } $aDisplayData[] = array( 'class' => MetaModel::GetName(get_class($oToUpdate)), 'object' => $oToUpdate->GetHyperLink(), 'consequence' => $sConsequence, ); } } $iImpactedIndirectly = $oDeletionPlan->GetTargetCount() - count($aObjects); if ($iImpactedIndirectly > 0) { if (count($aObjects) == 1) { $oObj = $aObjects[0]; $oP->p(Dict::Format('UI:Delete:Count_Objects/LinksReferencing_Object', $iImpactedIndirectly, $oObj->GetName())); } else { $oP->p(Dict::Format('UI:Delete:Count_Objects/LinksReferencingTheObjects', $iImpactedIndirectly)); } $oP->p(Dict::S('UI:Delete:ReferencesMustBeDeletedToEnsureIntegrity')); } if (($iImpactedIndirectly > 0) || $oDeletionPlan->FoundStopper()) { $aDisplayConfig = array(); $aDisplayConfig['class'] = array('label' => 'Class', 'description' => ''); $aDisplayConfig['object'] = array('label' => 'Object', 'description' => ''); $aDisplayConfig['consequence'] = array('label' => 'Consequence', 'description' => Dict::S('UI:Delete:Consequence+')); $oP->table($aDisplayConfig, $aDisplayData); } if ($oDeletionPlan->FoundStopper()) { if ($oDeletionPlan->FoundSecurityIssue()) { $oP->p(Dict::S('UI:Delete:SorryDeletionNotAllowed')); } elseif ($oDeletionPlan->FoundManualOperation()) { $oP->p(Dict::S('UI:Delete:PleaseDoTheManualOperations')); } else // $bFoundManualOp { $oP->p(Dict::S('UI:Delete:PleaseDoTheManualOperations')); } $oAppContext = new ApplicationContext(); $oP->add("
\n"); $oP->add("\n"); $oP->add("\n"); $oP->add("\n"); $oP->add($oAppContext->GetForForm()); $oP->add("
\n"); } else { $oAppContext = new ApplicationContext(); if (count($aObjects) == 1) { $oObj = $aObjects[0]; $id = $oObj->GetKey(); $oP->p('

'.Dict::Format('UI:Delect:Confirm_Object', $oObj->GetHyperLink()).'

'); $oP->add("
\n"); $oP->add("\n"); $oP->add("\n"); $oP->add("\n"); $oP->add("\n"); $oP->add("\n"); $oP->add("\n"); $oP->add($oAppContext->GetForForm()); $oP->add("
\n"); } else { $oP->p('

'.Dict::Format('UI:Delect:Confirm_Count_ObjectsOf_Class', count($aObjects), MetaModel::GetName($sClass)).'

'); foreach($aObjects as $oObj) { $aKeys[] = $oObj->GetKey(); } $oFilter = new DBObjectSearch($sClass); $oFilter->AddCondition('id', $aKeys, 'IN'); $oSet = new CMDBobjectSet($oFilter); $oP->add('
'); CMDBAbstractObject::DisplaySet($oP, $oSet, array('display_limit' => false, 'menu' => false)); $oP->add("
\n"); $oP->add("
\n"); $oP->add("\n"); $oP->add("\n"); $oP->add("\n"); foreach($aObjects as $oObj) { $oP->add("GetKey()."\">\n"); } $oP->add("\n"); $oP->add("\n"); $oP->add($oAppContext->GetForForm()); $oP->add("
\n"); } } } } /** * Displays a popup welcome message, once per session at maximum * until the user unchecks the "Display welcome at startup" * @param WebPage $oP The current web page for the display * @return void */ function DisplayWelcomePopup(WebPage $oP) { if (!isset($_SESSION['welcome'])) { // Check, only once per session, if the popup should be displayed... // If the user did not already ask for hiding it forever $bPopup = appUserPreferences::GetPref('welcome_popup', true); if ($bPopup) { $sTemplate = @file_get_contents('../application/templates/welcome_popup.html'); if ($sTemplate !== false) { $oTemplate = new DisplayTemplate($sTemplate); $oP->add("
"); $oTemplate->Render($oP, array()); $oP->add("

\n"); $oP->add("

\n"); $oP->add("

\n"); $sTitle = addslashes(Dict::S('UI:WelcomeMenu:Title')); $oP->add_ready_script( << ($(window).height()-70)) { $('#welcome_popup').height($(window).height()-70); } EOF ); $_SESSION['welcome'] = 'ok'; } } } } /** * 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->Reload(); $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 * @param $sClass string The name of the class of the object * @param $oObj DBObject The object to display * @param $id mixed Identifier of the object (name or ID) */ function DisplayDetails($oP, $sClass, $oObj, $id) { $sClassLabel = MetaModel::GetName($sClass); $oSearch = new DBObjectSearch($sClass); $oBlock = new DisplayBlock($oSearch, 'search', false); $oBlock->Display($oP, 0); // The object could be listed, check if it is actually allowed to view it $oSet = CMDBObjectSet::FromObject($oObj); if (UserRights::IsActionAllowed($sClass, UR_ACTION_READ, $oSet) == UR_ALLOWED_NO) { throw new SecurityException('User not allowed to view this object', array('class' => $sClass, 'id' => $id)); } $oP->set_title(Dict::Format('UI:DetailsPageTitle', $oObj->GetRawName(), $sClassLabel)); // Set title will take care of the encoding $oObj->DisplayDetails($oP); } /** * Displays the result of a search request * @param $oP WebPage Web page for the output * @param $oFilter DBObjectSearch The search of objects to display * @param $bSearchForm boolean Whether or not to display the search form at the top the page * @param $sBaseClass string The base class for the search (can be different from the actual class of the results) * @param $sFormat string The format to use for the output: csv or html */ function DisplaySearchSet($oP, $oFilter, $bSearchForm = true, $sBaseClass = '', $sFormat = '') { if ($bSearchForm) { $aParams = array('open' => true); if (!empty($sBaseClass)) { $aParams['baseClass'] = $sBaseClass; } $oBlock = new DisplayBlock($oFilter, 'search', false /* Asynchronous */, $aParams); $oBlock->Display($oP, 0); } if (strtolower($sFormat) == 'csv') { $oBlock = new DisplayBlock($oFilter, 'csv', false); $oBlock->Display($oP, 1); // Adjust the size of the Textarea containing the CSV to fit almost all the remaining space $oP->add_ready_script(" $('#1>textarea').height($('#1').parent().height() - $('#0').outerHeight() - 30).width( $('#1').parent().width() - 20);"); // adjust the size of the block } else { $oBlock = new DisplayBlock($oFilter, 'list', false); $oBlock->Display($oP, 1); } } /** * Displays a form (checkboxes) to select the objects for which to apply a given action * Only the objects for which the action is valid can be checked. By default all valid objects are checked * @param $oP WebPage The page for output * @param $oFilter DBObjectSearch The filter that defines the list of objects * @param $sNextOperation string The next operation (code) to be executed when the form is submitted * @param $oChecker ActionChecker The helper class/instance used to check for which object the action is valid * @return none */ function DisplayMultipleSelectionForm($oP, $oFilter, $sNextOperation, $oChecker, $aExtraFormParams = array()) { $oAppContext = new ApplicationContext(); $iBulkActionAllowed = $oChecker->IsAllowed(); $sClass = $oFilter->GetClass(); $aExtraParams = array('selection_type' => 'multiple', 'selection_mode' => true, 'display_limit' => false, 'menu' => false); if ($iBulkActionAllowed == UR_ALLOWED_DEPENDS) { $aAllowed = array(); $aExtraParams['selection_enabled'] = $oChecker->GetAllowedIDs(); } else if(UR_ALLOWED_NO) { throw new ApplicationException(Dict::Format('UI:ActionNotAllowed')); } $oBlock = new DisplayBlock($oFilter, 'list', false); $oP->add("
\n"); $oP->add("\n"); $oP->add("GetClass()."\">\n"); $oP->add("Serialize()."\">\n"); $oP->add("\n"); foreach($aExtraFormParams as $sName => $sValue) { $oP->add("\n"); } $oP->add($oAppContext->GetForForm()); $oBlock->Display($oP, 1, $aExtraParams); $oP->add("  \n"); $oP->add("
\n"); $oP->add_ready_script("$('#1 table.listResults').trigger('check_all');"); } /*********************************************************************************** * * Main user interface page, starts here * * ***********************************************************************************/ try { require_once('../approot.inc.php'); require_once(APPROOT.'/application/application.inc.php'); require_once(APPROOT.'/application/itopwebpage.class.inc.php'); require_once(APPROOT.'/application/wizardhelper.class.inc.php'); require_once(APPROOT.'/application/startup.inc.php'); $operation = utils::ReadParam('operation', ''); $oKPI = new ApplicationStartupKPI(); $oKPI->ComputeAndReport('Load of data model and all includes'); $oKPI = new ExecutionKPI(); require_once(APPROOT.'/application/loginwebpage.class.inc.php'); $sLoginMessage = LoginWebPage::DoLogin(); // Check user rights and prompt if needed $oAppContext = new ApplicationContext(); $oKPI->ComputeAndReport('User login'); $oP = new iTopWebPage(Dict::S('UI:WelcomeToITop')); $oP->SetMessage($sLoginMessage); // All the following actions use advanced forms that require more javascript to be loaded switch($operation) { case 'new': // Form to create a new object case 'modify': // Form to modify an object case 'apply_new': // Creation of a new object case 'apply_modify': // Applying the modifications to an existing object 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) $oP->add_linked_script("../js/json.js"); $oP->add_linked_script("../js/forms-json-utils.js"); $oP->add_linked_script("../js/wizardhelper.js"); $oP->add_linked_script("../js/wizard.utils.js"); $oP->add_linked_script("../js/linkswidget.js"); $oP->add_linked_script("../js/extkeywidget.js"); $oP->add_linked_script("../js/jquery.blockUI.js"); break; } switch($operation) { /////////////////////////////////////////////////////////////////////////////////////////// case 'details': // Details of an object $sClass = utils::ReadParam('class', ''); $id = utils::ReadParam('id', ''); if ( empty($sClass) || empty($id)) { throw new ApplicationException(Dict::Format('UI:Error:2ParametersMissing', 'class', 'id')); } if (is_numeric($id)) { $oObj = MetaModel::GetObject($sClass, $id, false /* MustBeFound */); } else { $oObj = MetaModel::GetObjectByName($sClass, $id, false /* MustBeFound */); } if (is_null($oObj)) { $oP->set_title(Dict::S('UI:ErrorPageTitle')); $oP->P(Dict::S('UI:ObjectDoesNotExist')); } else { DisplayDetails($oP, $sClass, $oObj, $id); } break; /////////////////////////////////////////////////////////////////////////////////////////// case 'search_oql': // OQL query $sOQLClass = utils::ReadParam('oql_class', '', false, 'class'); $sBaseClass = utils::ReadParam('base_class', $sOQLClass, false, 'class'); $sOQLClause = utils::ReadParam('oql_clause', '', false, 'raw_data'); $sFormat = utils::ReadParam('format', ''); $bSearchForm = utils::ReadParam('search_form', true); $sTitle = utils::ReadParam('title', 'UI:SearchResultsPageTitle'); if (empty($sOQLClass)) { throw new ApplicationException(Dict::Format('UI:Error:1ParametersMissing', 'oql_class')); } $oP->set_title(Dict::S($sTitle)); $oP->add('

'.Dict::S($sTitle).'

'); $sOQL = "SELECT $sOQLClass $sOQLClause"; try { $oFilter = DBObjectSearch::FromOQL($sOQL); DisplaySearchSet($oP, $oFilter, $bSearchForm, $sBaseClass, $sFormat); } catch(CoreException $e) { $oFilter = new DBObjectSearch($sOQLClass); $oSet = new DBObjectSet($oFilter); if ($bSearchForm) { $oBlock = new DisplayBlock($oFilter, 'search', false); $oBlock->Display($oP, 0); } $oP->P(''.Dict::Format('UI:Error:IncorrectOQLQuery_Message', $e->getHtmlDesc()).''); } catch(Exception $e) { $oP->P(''.Dict::Format('UI:Error:AnErrorOccuredWhileRunningTheQuery_Message', $e->getMessage()).''); } break; /////////////////////////////////////////////////////////////////////////////////////////// case 'search_form': // Search form $sClass = utils::ReadParam('class', '', false, 'class'); $sFormat = utils::ReadParam('format', 'html'); $bSearchForm = utils::ReadParam('search_form', true); if (empty($sClass)) { throw new ApplicationException(Dict::Format('UI:Error:1ParametersMissing', 'class')); } $oP->set_title(Dict::S('UI:SearchResultsPageTitle')); $oFilter = new DBObjectSearch($sClass); DisplaySearchSet($oP, $oFilter, $bSearchForm, '' /* sBaseClass */, $sFormat); break; /////////////////////////////////////////////////////////////////////////////////////////// case 'search': // Serialized CMDBSearchFilter $sFilter = utils::ReadParam('filter', '', false, 'raw_data'); $sFormat = utils::ReadParam('format', ''); $bSearchForm = utils::ReadParam('search_form', true); if (empty($sFilter)) { throw new ApplicationException(Dict::Format('UI:Error:1ParametersMissing', 'filter')); } $oP->set_title(Dict::S('UI:SearchResultsPageTitle')); // TO DO: limit the search filter by the user context $oFilter = CMDBSearchFilter::unserialize($sFilter); // TO DO : check that the filter is valid DisplaySearchSet($oP, $oFilter, $bSearchForm, '' /* sBaseClass */, $sFormat); break; /////////////////////////////////////////////////////////////////////////////////////////// case 'full_text': // Global "google-like" search $sFullText = trim(utils::ReadParam('text', '', false, 'raw_data')); if (empty($sFullText)) { $oP->p(Dict::S('UI:Search:NoSearch')); } else { $oP->set_title(Dict::S('UI:SearchResultsPageTitle')); $oP->p("

".Dict::Format('UI:FullTextSearchTitle_Text', $sFullText)."

"); $iCount = 0; $iBlock = 0; // Search in full text mode in all the classes $aMatches = array(); $sClassName = ''; // Check if a class name/label is supplied to limit the search if (preg_match('/^(.+):(.+)$/', $sFullText, $aMatches)) { $sClassName = $aMatches[1]; if (MetaModel::IsValidClass($sClassName)) { $sFullText = $aMatches[2]; } elseif ($sClassName = MetaModel::GetClassFromLabel($sClassName, false /* => not case sensitive */)) { $sFullText = $aMatches[2]; } } if (preg_match('/^"(.*)"$/', $sFullText, $aMatches)) { // The text is surrounded by double-quotes, remove the quotes and treat it as one single expression $aFullTextNeedles = array($aMatches[1]); } else { // Split the text on the blanks and treat this as a search for AND AND $aFullTextNeedles = explode(' ', $sFullText); } // Search is limited ot a given class, or not... if (empty($sClassName)) { $aSearchClasses = MetaModel::GetClasses('searchable'); } else { $aSearchClasses = MetaModel::EnumChildClasses($sClassName, ENUM_CHILD_CLASSES_ALL); } foreach($aSearchClasses as $sClassName) { $oFilter = new DBObjectSearch($sClassName); foreach($aFullTextNeedles as $sSearchText) { $oFilter->AddCondition_FullText($sSearchText); } $oSet = new DBObjectSet($oFilter); if ($oSet->Count() > 0) { $aLeafs = array(); while($oObj = $oSet->Fetch()) { if (get_class($oObj) == $sClassName) { $aLeafs[] = $oObj->GetKey(); } } $oLeafsFilter = new DBObjectSearch($sClassName); if (count($aLeafs) > 0) { $iCount += count($aLeafs); $oP->add("
\n"); $oP->add("

".MetaModel::GetClassIcon($sClassName)." ".Dict::Format('UI:Search:Count_ObjectsOf_Class_Found', count($aLeafs), Metamodel::GetName($sClassName))."

\n"); $oP->add("
\n"); $oLeafsFilter->AddCondition('id', $aLeafs, 'IN'); $oBlock = new DisplayBlock($oLeafsFilter, 'list', false); $oBlock->Display($oP, $iBlock++, array('table_id' => 'global_search')); $oP->P(' '); // Some space ? } } } if ($iCount == 0) { $oP->p(Dict::S('UI:Search:NoObjectFound')); } } break; /////////////////////////////////////////////////////////////////////////////////////////// case 'modify': // Form to modify an object $sClass = utils::ReadParam('class', '', false, 'class'); $sClassLabel = MetaModel::GetName($sClass); $id = utils::ReadParam('id', ''); if ( empty($sClass) || empty($id)) // TO DO: check that the class name is valid ! { throw new ApplicationException(Dict::Format('UI:Error:2ParametersMissing', 'class', 'id')); } // Check if the user can modify this object $oObj = MetaModel::GetObject($sClass, $id, false /* MustBeFound */); if (is_null($oObj)) { $oP->set_title(Dict::S('UI:ErrorPageTitle')); $oP->P(Dict::S('UI:ObjectDoesNotExist')); } else { // The object could be read - check if it is allowed to modify it $oSet = CMDBObjectSet::FromObject($oObj); if (UserRights::IsActionAllowed($sClass, UR_ACTION_MODIFY, $oSet) == UR_ALLOWED_NO) { throw new SecurityException('User not allowed to modify this object', array('class' => $sClass, 'id' => $id)); } // Note: code duplicated to the case 'apply_modify' when a data integrity issue has been found $oP->set_title(Dict::Format('UI:ModificationPageTitle_Object_Class', $oObj->GetRawName(), $sClassLabel)); // Set title will take care of the encoding $oP->add("
\n"); $oP->add("

".$oObj->GetIcon()." ".Dict::Format('UI:ModificationTitle_Class_Object', $sClassLabel, $oObj->GetName())."

\n"); $oP->add("
\n"); $oP->add("
\n"); $oObj->DisplayModifyForm($oP); $oP->add("
\n"); } break; /////////////////////////////////////////////////////////////////////////////////////////// case 'select_for_modify_all': // Select the list of objects to be modified (bulk modify) $oP->set_title(Dict::S('UI:ModifyAllPageTitle')); $sFilter = utils::ReadParam('filter', '', false, 'raw_data'); if (empty($sFilter)) { throw new ApplicationException(Dict::Format('UI:Error:1ParametersMissing', 'filter')); } // TO DO: limit the search filter by the user context $oFilter = DBObjectSearch::unserialize($sFilter); // TO DO : check that the filter is valid $sClass = $oFilter->GetClass(); $oChecker = new ActionChecker($oFilter, UR_ACTION_BULK_MODIFY); $oP->add("

Modify All...

\n"); DisplayMultipleSelectionForm($oP, $oFilter, 'form_for_modify_all', $oChecker); break; /////////////////////////////////////////////////////////////////////////////////////////// case 'form_for_modify_all': // Form to modify multiple objects (bulk modify) $sFilter = utils::ReadParam('filter', '', false, 'raw_data'); $sClass = utils::ReadParam('class', '', false, 'class'); $oFullSetFilter = DBObjectSearch::unserialize($sFilter); $aSelectedObj = utils::ReadMultipleSelection($oFullSetFilter); if (count($aSelectedObj) > 0) { $iAllowedCount = count($aSelectedObj); $sSelectedObj = implode(',', $aSelectedObj); $sOQL = "SELECT $sClass WHERE id IN (".$sSelectedObj.")"; $oSet = new CMDBObjectSet(DBObjectSearch::FromOQL($sOQL)); // Compute the distribution of the values for each field to determine which of the "scalar" fields are homogenous $aList = MetaModel::ListAttributeDefs($sClass); $aValues = array(); foreach($aList as $sAttCode => $oAttDef) { if ($oAttDef->IsScalar()) { $aValues[$sAttCode] = array(); } } while($oObj = $oSet->Fetch()) { foreach($aList as $sAttCode => $oAttDef) { if ($oAttDef->IsScalar() && $oAttDef->IsWritable()) { $currValue = $oObj->Get($sAttCode); if ($oAttDef instanceof AttributeCaseLog) { $currValue = ' '; // Don't put an empty string, in case the field would be considered as mandatory... } if (is_object($currValue)) continue; // Skip non scalar values... if(!array_key_exists($currValue, $aValues[$sAttCode])) { $aValues[$sAttCode][$currValue] = array('count' => 1, 'display' => $oObj->GetAsHTML($sAttCode)); } else { $aValues[$sAttCode][$currValue]['count']++; } } } } // Now create an object that has values for the homogenous values only $oDummyObj = new $sClass(); // @@ What if the class is abstract ? $aComments = array(); function MyComparison($a, $b) // Sort descending { if ($a['count'] == $b['count']) { return 0; } return ($a['count'] > $b['count']) ? -1 : 1; } $iFormId = cmdbAbstractObject::GetNextFormId(); // Identifier that prefixes all the form fields $sReadyScript = ''; $aDependsOn = array(); $sFormPrefix = '2_'; foreach($aList as $sAttCode => $oAttDef) { $aPrerequisites = MetaModel::GetPrequisiteAttributes($sClass, $sAttCode); // List of attributes that are needed for the current one if (count($aPrerequisites) > 0) { // When 'enabling' a field, all its prerequisites must be enabled too $sFieldList = "['{$sFormPrefix}".implode("','{$sFormPrefix}", $aPrerequisites)."']"; $oP->add_ready_script("$('#enable_{$sFormPrefix}{$sAttCode}').bind('change', function(evt, sFormId) { return PropagateCheckBox( this.checked, $sFieldList, true); } );\n"); } $aDependents = MetaModel::GetDependentAttributes($sClass, $sAttCode); // List of attributes that are needed for the current one if (count($aDependents) > 0) { // When 'disabling' a field, all its dependent fields must be disabled too $sFieldList = "['{$sFormPrefix}".implode("','{$sFormPrefix}", $aDependents)."']"; $oP->add_ready_script("$('#enable_{$sFormPrefix}{$sAttCode}').bind('change', function(evt, sFormId) { return PropagateCheckBox( this.checked, $sFieldList, false); } );\n"); } if ($oAttDef->IsScalar() && $oAttDef->IsWritable()) { if ($oAttDef->GetEditClass() == 'One Way Password') { $sTip = "Unknown values"; $sReadyScript .= "$('#multi_values_$sAttCode').qtip( { content: '$sTip', show: 'mouseover', hide: 'mouseout', style: { name: 'dark', tip: 'leftTop' }, position: { corner: { target: 'rightMiddle', tooltip: 'leftTop' }} } );"; $oDummyObj->Set($sAttCode, null); $aComments[$sAttCode] = ''; $aComments[$sAttCode] .= '
?
'; $sReadyScript .= 'ToogleField(false, \''.$iFormId.'_'.$sAttCode.'\');'."\n"; } else { $iCount = count($aValues[$sAttCode]); if ($iCount == 1) { // Homogenous value reset($aValues[$sAttCode]); $aKeys = array_keys($aValues[$sAttCode]); $currValue = $aKeys[0]; // The only value is the first key //echo "

current value for $sAttCode : $currValue

"; $oDummyObj->Set($sAttCode, $currValue); $aComments[$sAttCode] = ''; $aComments[$sAttCode] .= '
1
'; } else { // Non-homogenous value $aMultiValues = $aValues[$sAttCode]; uasort($aMultiValues, 'MyComparison'); $iMaxCount = 5; $sTip = "

".Dict::Format('UI:BulkModify_Count_DistinctValues', $iCount)."

    "; $index = 0; foreach($aMultiValues as $sCurrValue => $aVal) { $sDisplayValue = empty($aVal['display']) ? ''.Dict::S('Enum:Undefined').'' : str_replace(array("\n", "\r"), " ", $aVal['display']); $sTip .= "
  • ".Dict::Format('UI:BulkModify:Value_Exists_N_Times', $sDisplayValue, $aVal['count'])."
  • "; $index++; if ($iMaxCount == $index) { $sTip .= "
  • ".Dict::Format('UI:BulkModify:N_MoreValues', count($aMultiValues) - $iMaxCount)."
  • "; break; } } $sTip .= "

"; $sTip = addslashes($sTip); $sReadyScript .= "$('#multi_values_$sAttCode').qtip( { content: '$sTip', show: 'mouseover', hide: 'mouseout', style: { name: 'dark', tip: 'leftTop' }, position: { corner: { target: 'rightMiddle', tooltip: 'leftTop' }} } );"; $oDummyObj->Set($sAttCode, null); $aComments[$sAttCode] = ''; $aComments[$sAttCode] .= '
'.$iCount.'
'; } $sReadyScript .= 'ToogleField('.(($iCount == 1) ? 'true': 'false').', \''.$iFormId.'_'.$sAttCode.'\');'."\n"; } } } $sStateAttCode = MetaModel::GetStateAttributeCode($sClass); if (($sStateAttCode != '') && ($oDummyObj->GetState() == '')) { // Hmmm, it's not gonna work like this ! Set a default value for the "state" // Maybe we should use the "state" that is the most common among the objects... $aMultiValues = $aValues[$sStateAttCode]; uasort($aMultiValues, 'MyComparison'); foreach($aMultiValues as $sCurrValue => $aVal) { $oDummyObj->Set($sStateAttCode, $sCurrValue); break; } //$oStateAtt = MetaModel::GetAttributeDef($sClass, $sStateAttCode); //$oDummyObj->Set($sStateAttCode, $oStateAtt->GetDefaultValue()); } $oP->add("
\n"); $oP->add("

".$oDummyObj->GetIcon()." ".Dict::Format('UI:Modify_M_ObjectsOf_Class_OutOf_N', $iAllowedCount, $sClass, $iAllowedCount)."

\n"); $oP->add("
\n"); $oP->add("
\n"); $oDummyObj->DisplayModifyForm($oP, array('fieldsComments' => $aComments, 'noRelations' => true, 'custom_operation' => 'preview_or_modify_all', 'custom_button' => Dict::S('UI:Button:PreviewModifications'), 'selectObj' => $sSelectedObj, 'filter' => $sFilter, 'preview_mode' => true, 'disabled_fields' => '{}')); $oP->add("
\n"); $oP->add_ready_script($sReadyScript); $sURL = "./UI.php?operation=search&filter=".urlencode($sFilter)."&".$oAppContext->GetForLink(); $oP->add_ready_script( <<p("No object selected !, nothing to do"); } break; /////////////////////////////////////////////////////////////////////////////////////////// case 'preview_or_modify_all': // Preview or apply bulk modify $sFilter = utils::ReadParam('filter', '', false, 'raw_data'); // TO DO: limit the search filter by the user context $oFilter = DBObjectSearch::unserialize($sFilter); // TO DO : check that the filter is valid $oChecker = new ActionChecker($oFilter, UR_ACTION_BULK_MODIFY); $sClass = utils::ReadParam('class', '', false, 'class'); $bPreview = utils::ReadParam('preview_mode', ''); $sSelectedObj = utils::ReadParam('selectObj', '', false, 'raw_data'); if ( empty($sClass) || empty($sSelectedObj)) // TO DO: check that the class name is valid ! { throw new ApplicationException(Dict::Format('UI:Error:2ParametersMissing', 'class', 'selectObj')); } $aSelectedObj = explode(',', $sSelectedObj); $aHeaders = array( 'form::select' => array('label' => "", 'description' => Dict::S('UI:SelectAllToggle+')), 'object' => array('label' => MetaModel::GetName($sClass), 'description' => Dict::S('UI:ModifiedObject')), 'status' => array('label' => Dict::S('UI:BulkModifyStatus'), 'description' => Dict::S('UI:BulkModifyStatus+')), 'errors' => array('label' => Dict::S('UI:BulkModifyErrors'), 'description' => Dict::S('UI:BulkModifyErrors+')), ); $aRows = array(); $oP->add("
\n"); $oP->add("

".MetaModel::GetClassIcon($sClass)." ".Dict::Format('UI:Modify_N_ObjectsOf_Class', count($aSelectedObj), $sClass)."

\n"); $oP->add("
\n"); $oP->set_title(Dict::Format('UI:Modify_N_ObjectsOf_Class', count($aSelectedObj), $sClass)); if (!$bPreview) { // Not in preview mode, do the update for real $sTransactionId = utils::ReadPostedParam('transaction_id', ''); if (!utils::IsTransactionValid($sTransactionId, false)) { throw new Exception(Dict::S('UI:Error:ObjectAlreadyUpdated')); } $oMyChange = MetaModel::NewObject("CMDBChange"); $oMyChange->Set("date", time()); $sUserString = CMDBChange::GetCurrentUserName(); $oMyChange->Set("userinfo", $sUserString); $iChangeId = $oMyChange->DBInsert(); utils::RemoveTransaction($sTransactionId); } foreach($aSelectedObj as $iId) { $oObj = MetaModel::GetObject($sClass, $iId); $aErrors = $oObj->UpdateObjectFromPostedForm(''); $bResult = (count($aErrors) == 0); if ($bResult) { list($bResult, $aErrors) = $oObj->CheckToWrite(true /* Enforce Read-only fields */); } if ($bPreview) { $sStatus = $bResult ? Dict::S('UI:BulkModifyStatusOk') : Dict::S('UI:BulkModifyStatusError'); } else { $sStatus = $bResult ? Dict::S('UI:BulkModifyStatusModified') : Dict::S('UI:BulkModifyStatusSkipped'); } $sCSSClass = $bResult ? HILIGHT_CLASS_NONE : HILIGHT_CLASS_CRITICAL; $sChecked = $bResult ? 'checked' : ''; $sDisabled = $bResult ? '' : 'disabled'; $aRows[] = array( 'form::select' => "", 'object' => $oObj->GetHyperlink(), 'status' => $sStatus, 'errors' => '

'.($bResult ? '': implode('

', $aErrors)).'

', '@class' => $sCSSClass, ); if ($bResult && (!$bPreview)) { $oObj->DBUpdateTracked($oMyChange); } } $oP->Table($aHeaders, $aRows); $sURL = "./UI.php?operation=search&filter=".urlencode($sFilter)."&".$oAppContext->GetForLink(); if ($bPreview) { // Form to submit: $oP->add("
\n"); $aDefaults = utils::ReadParam('default', array()); $oP->add($oAppContext->GetForForm()); $oP->add("\n"); $oP->add("\n"); $oP->add("\n"); $oP->add("\n"); $oP->add("\n"); $oP->add("\n"); $oP->add("    \n"); $oP->add("\n"); foreach($_POST as $sKey => $value) { if (preg_match('/attr_(.+)/', $sKey, $aMatches)) { $oP->add("\n"); } } $oP->add("
\n"); } else { $sURL = "./UI.php?operation=search&filter=".urlencode($sFilter)."&".$oAppContext->GetForLink(); $oP->add("\n"); } break; /////////////////////////////////////////////////////////////////////////////////////////// case 'new': // Form to create a new object $sClass = utils::ReadParam('class', '', false, 'class'); $sStateCode = utils::ReadParam('state', ''); $bCheckSubClass = utils::ReadParam('checkSubclass', true); if ( empty($sClass) ) { throw new ApplicationException(Dict::Format('UI:Error:1ParametersMissing', 'class')); } $aArgs = utils::ReadParam('default', array(), false, 'raw_data'); $aContext = $oAppContext->GetAsHash(); foreach( $oAppContext->GetNames() as $key) { $aArgs[$key] = $oAppContext->GetCurrentValue($key); } // If the specified class has subclasses, ask the user an instance of which class to create $aSubClasses = MetaModel::EnumChildClasses($sClass, ENUM_CHILD_CLASSES_ALL); // Including the specified class itself $aPossibleClasses = array(); $sRealClass = ''; if ($bCheckSubClass) { foreach($aSubClasses as $sCandidateClass) { if (!MetaModel::IsAbstract($sCandidateClass) && (UserRights::IsActionAllowed($sCandidateClass, UR_ACTION_MODIFY) == UR_ALLOWED_YES)) { $aPossibleClasses[$sCandidateClass] = MetaModel::GetName($sCandidateClass); } } // Only one of the subclasses can be instantiated... if (count($aPossibleClasses) == 1) { $aKeys = array_keys($aPossibleClasses); $sRealClass = $aKeys[0]; } } else { $sRealClass = $sClass; } if (!empty($sRealClass)) { // Display the creation form $sClassLabel = MetaModel::GetName($sRealClass); // Note: some code has been duplicated to the case 'apply_new' when a data integrity issue has been found $oP->set_title(Dict::Format('UI:CreationPageTitle_Class', $sClassLabel)); $oP->add("

".MetaModel::GetClassIcon($sRealClass)." ".Dict::Format('UI:CreationTitle_Class', $sClassLabel)."

\n"); $oP->add("
\n"); // Set all the default values in an object and clone this "default" object $oObjToClone = MetaModel::NewObject($sRealClass); // 1st - set context values $oAppContext->InitObjectFromContext($oObjToClone); // 2nd - set values from the page argument 'default' $oObjToClone->UpdateObjectFromArg('default'); cmdbAbstractObject::DisplayCreationForm($oP, $sRealClass, $oObjToClone, array()); $oP->add("
\n"); } else { // Select the derived class to create $sClassLabel = MetaModel::GetName($sClass); $oP->add("

".MetaModel::GetClassIcon($sClass)." ".Dict::Format('UI:CreationTitle_Class', $sClassLabel)."

\n"); $oP->add("
\n"); $oP->add('
'); $oP->add('

'.Dict::Format('UI:SelectTheTypeOf_Class_ToCreate', $sClassLabel)); $aDefaults = utils::ReadParam('default', array(), false, 'raw_data'); $oP->add($oAppContext->GetForForm()); $oP->add("\n"); $oP->add("\n"); $oP->add("\n"); foreach($aDefaults as $key => $value) { if (is_array($value)) { foreach($value as $key2 => $value2) { if (is_array($value2)) { foreach($value2 as $key3 => $value3) { $oP->add("\n"); } } else { $oP->add("\n"); } } } else { $oP->add("\n"); } } $oP->add(''); $oP->add(" 

"); $oP->add('
'); $oP->add("
\n"); } break; /////////////////////////////////////////////////////////////////////////////////////////// case 'apply_modify': // Applying the modifications to an existing object $sClass = utils::ReadPostedParam('class', ''); $sClassLabel = MetaModel::GetName($sClass); $id = utils::ReadPostedParam('id', ''); $sTransactionId = utils::ReadPostedParam('transaction_id', ''); if ( empty($sClass) || empty($id)) // TO DO: check that the class name is valid ! { throw new ApplicationException(Dict::Format('UI:Error:2ParametersMissing', 'class', 'id')); } $bDisplayDetails = true; $oObj = MetaModel::GetObject($sClass, $id, false); if ($oObj == null) { $bDisplayDetails = false; $oP->set_title(Dict::S('UI:ErrorPageTitle')); $oP->P(Dict::S('UI:ObjectDoesNotExist')); } elseif (!utils::IsTransactionValid($sTransactionId, false)) { $oP->set_title(Dict::Format('UI:ModificationPageTitle_Object_Class', $oObj->GetRawName(), $sClassLabel)); // Set title will take care of the encoding $oP->p("".Dict::S('UI:Error:ObjectAlreadyUpdated')."\n"); } else { $oMyChange = null; $oObj->UpdateObjectFromPostedForm(); if (!$oObj->IsModified()) { $oP->set_title(Dict::Format('UI:ModificationPageTitle_Object_Class', $oObj->GetRawName(), $sClassLabel)); // Set title will take care of the encoding $oP->p(Dict::Format('UI:Class_Object_NotUpdated', MetaModel::GetName(get_class($oObj)), $oObj->GetName())); } else { list($bRes, $aIssues) = $oObj->CheckToWrite(); if ($bRes) { $oP->set_title(Dict::Format('UI:ModificationPageTitle_Object_Class', $oObj->GetRawName(), $sClassLabel)); // Set title will take care of the encoding $oP->add("

".Dict::Format('UI:ModificationTitle_Class_Object', $sClassLabel, $oObj->GetName())."

\n"); $oMyChange = MetaModel::NewObject("CMDBChange"); $oMyChange->Set("date", time()); $sUserString = CMDBChange::GetCurrentUserName(); $oMyChange->Set("userinfo", $sUserString); $iChangeId = $oMyChange->DBInsert(); $oObj->DBUpdateTracked($oMyChange); utils::RemoveTransaction($sTransactionId); $oP->p(Dict::Format('UI:Class_Object_Updated', MetaModel::GetName(get_class($oObj)), $oObj->GetName())); } else { $bDisplayDetails = false; // Found issues, explain and give the user a second chance // $oP->set_title(Dict::Format('UI:ModificationPageTitle_Object_Class', $oObj->GetRawName(), $sClassLabel)); // Set title will take care of the encoding $oP->add("
\n"); $oP->add("

".$oObj->GetIcon()." ".Dict::Format('UI:ModificationTitle_Class_Object', $sClassLabel, $oObj->GetName())."

\n"); $oP->add("
\n"); $oP->add("
\n"); $oObj->DisplayModifyForm($oP); $oP->add("
\n"); $sIssueDesc = Dict::Format('UI:ObjectCouldNotBeWritten', implode(', ', $aIssues)); $oP->add_ready_script("alert('".addslashes($sIssueDesc)."');"); } } } if ($bDisplayDetails) { $oObj = MetaModel::GetObject(get_class($oObj), $oObj->GetKey()); //Workaround: reload the object so that the linkedset are displayed properly $sNextAction = utils::ReadPostedParam('next_action', ''); if (!empty($sNextAction)) { ApplyNextAction($oP, $oObj, $sNextAction, $oMyChange); } else { // Nothing more to do $oObj->DisplayDetails($oP); } } break; /////////////////////////////////////////////////////////////////////////////////////////// case 'select_for_deletion': // Select multiple objects for deletion $sFilter = utils::ReadParam('filter', '', false, 'raw_data'); if (empty($sFilter)) { throw new ApplicationException(Dict::Format('UI:Error:1ParametersMissing', 'filter')); } $oP->set_title(Dict::S('UI:BulkDeletePageTitle')); $oP->add("

".Dict::S('UI:BulkDeleteTitle')."

\n"); // TO DO: limit the search filter by the user context $oFilter = CMDBSearchFilter::unserialize($sFilter); // TO DO : check that the filter is valid $oChecker = new ActionChecker($oFilter, UR_ACTION_BULK_DELETE); DisplayMultipleSelectionForm($oP, $oFilter, 'bulk_delete', $oChecker); break; /////////////////////////////////////////////////////////////////////////////////////////// case 'bulk_delete_confirmed': // Confirm bulk deletion of objects $sTransactionId = utils::ReadPostedParam('transaction_id', ''); if (!utils::IsTransactionValid($sTransactionId)) { throw new ApplicationException(Dict::S('UI:Error:ObjectsAlreadyDeleted')); } // Fall through /////////////////////////////////////////////////////////////////////////////////////////// case 'bulk_delete': // Actual bulk deletion (if confirmed) $sClass = utils::ReadPostedParam('class', ''); $sClassLabel = MetaModel::GetName($sClass); $sFilter = utils::ReadPostedParam('filter', ''); $oFullSetFilter = DBObjectSearch::unserialize($sFilter); $aSelectObject = utils::ReadMultipleSelection($oFullSetFilter); $aObjects = array(); if ( empty($sClass) || empty($aSelectObject)) // TO DO: check that the class name is valid ! { throw new ApplicationException(Dict::Format('UI:Error:2ParametersMissing', 'class', 'selectObject[]')); } foreach($aSelectObject as $iId) { $aObjects[] = MetaModel::GetObject($sClass, $iId); } if (!UserRights::IsActionAllowed($sClass, UR_ACTION_BULK_DELETE, DBObjectSet::FromArray($sClass, $aObjects))) { throw new SecurityException(Dict::Format('UI:Error:BulkDeleteNotAllowedOn_Class', $sClass)); } $oP->set_title(Dict::S('UI:BulkDeletePageTitle')); DeleteObjects($oP, $sClass, $aObjects, ($operation == 'bulk_delete_confirmed')); break; /////////////////////////////////////////////////////////////////////////////////////////// case 'delete': // Deletion (preview) case 'delete_confirmed': // Deletion (confirmed) $sClass = utils::ReadParam('class', '', false, 'class'); $sClassLabel = MetaModel::GetName($sClass); $id = utils::ReadParam('id', ''); $oObj = MetaModel::GetObject($sClass, $id); if (!UserRights::IsActionAllowed($sClass, UR_ACTION_MODIFY, DBObjectSet::FromObject($oObj))) { throw new SecurityException(Dict::Format('UI:Error:DeleteNotAllowedOn_Class', $sClass)); } DeleteObjects($oP, $sClass, array($oObj), ($operation == 'delete_confirmed')); break; /////////////////////////////////////////////////////////////////////////////////////////// case 'apply_new': // Creation of a new object $sClass = utils::ReadPostedParam('class', '', 'class'); $sClassLabel = MetaModel::GetName($sClass); $sTransactionId = utils::ReadPostedParam('transaction_id', ''); if ( empty($sClass) ) // TO DO: check that the class name is valid ! { throw new ApplicationException(Dict::Format('UI:Error:1ParametersMissing', 'class')); } if (!utils::IsTransactionValid($sTransactionId, false)) { $oP->p("".Dict::S('UI:Error:ObjectAlreadyCreated')."\n"); } else { $oObj = MetaModel::NewObject($sClass); $sStateAttCode = MetaModel::GetStateAttributeCode($sClass); if (!empty($sStateAttCode)) { $sTargetState = utils::ReadPostedParam('obj_state', ''); if ($sTargetState != '') { $oObj->Set($sStateAttCode, $sTargetState); } } $oObj->UpdateObjectFromPostedForm(); } if (isset($oObj) && is_object($oObj)) { $sClass = get_class($oObj); $sClassLabel = MetaModel::GetName($sClass); list($bRes, $aIssues) = $oObj->CheckToWrite(); if ($bRes) { $oMyChange = MetaModel::NewObject("CMDBChange"); $oMyChange->Set("date", time()); $sUserString = CMDBChange::GetCurrentUserName(); $oMyChange->Set("userinfo", $sUserString); $iChangeId = $oMyChange->DBInsert(); $oObj->DBInsertTracked($oMyChange); utils::RemoveTransaction($sTransactionId); $oP->set_title(Dict::S('UI:PageTitle:ObjectCreated')); $oP->add("

".Dict::Format('UI:Title:Object_Of_Class_Created', $oObj->GetName(), $sClassLabel)."

\n"); $oObj = MetaModel::GetObject(get_class($oObj), $oObj->GetKey()); //Workaround: reload the object so that the linkedset are displayed properly $sNextAction = utils::ReadPostedParam('next_action', ''); if (!empty($sNextAction)) { ApplyNextAction($oP, $oObj, $sNextAction, $oMyChange); } else { // Nothing more to do $oObj->DisplayDetails($oP); } } else { // Found issues, explain and give the user a second chance // $oP->set_title(Dict::Format('UI:CreationPageTitle_Class', $sClassLabel)); $oP->add("

".MetaModel::GetClassIcon($sClass)." ".Dict::Format('UI:CreationTitle_Class', $sClassLabel)."

\n"); $oP->add("
\n"); cmdbAbstractObject::DisplayCreationForm($oP, $sClass, $oObj); $oP->add("
\n"); $sIssueDesc = Dict::Format('UI:ObjectCouldNotBeWritten', implode(', ', $aIssues)); $oP->add_ready_script("alert('".addslashes($sIssueDesc)."');"); } } break; /////////////////////////////////////////////////////////////////////////////////////////// case 'wizard_apply_new': // no more used ??? $sJson = utils::ReadPostedParam('json_obj', '', 'raw_data'); $oWizardHelper = WizardHelper::FromJSON($sJson); $sTransactionId = utils::ReadPostedParam('transaction_id', ''); if (!utils::IsTransactionValid($sTransactionId)) { $oP->p(Dict::S('UI:Error:ObjectAlreadyCreated')); } else { $oObj = $oWizardHelper->GetTargetObject(true /* read uploaded files */); if (is_object($oObj)) { $sClass = get_class($oObj); $sClassLabel = MetaModel::GetName($sClass); $oMyChange = MetaModel::NewObject("CMDBChange"); $oMyChange->Set("date", time()); $sUserString = CMDBChange::GetCurrentUserName(); $oMyChange->Set("userinfo", $sUserString); $iChangeId = $oMyChange->DBInsert(); $oObj->DBInsertTracked($oMyChange); $oP->set_title(Dict::S('UI:PageTitle:ObjectCreated')); $oP->add("

".Dict::Format('UI:Title:Object_Of_Class_Created', $oObj->GetName(), $sClassLabel)."

\n"); $oObj->DisplayDetails($oP); } } break; /////////////////////////////////////////////////////////////////////////////////////////// case 'select_bulk_stimulus': // Form displayed when applying a stimulus to many objects $sFilter = utils::ReadParam('filter', '', false, 'raw_data'); $sStimulus = utils::ReadParam('stimulus', ''); $sState = utils::ReadParam('state', ''); if (empty($sFilter) || empty($sStimulus) || empty($sState)) { throw new ApplicationException(Dict::Format('UI:Error:3ParametersMissing', 'filter', 'stimulus', 'state')); } $oFilter = DBObjectSearch::unserialize($sFilter); $sClass = $oFilter->GetClass(); $aStimuli = MetaModel::EnumStimuli($sClass); $sActionLabel = $aStimuli[$sStimulus]->GetLabel(); $sActionDetails = $aStimuli[$sStimulus]->GetDescription(); $oP->set_title($sActionLabel); $oP->add(''); $oChecker = new StimulusChecker($oFilter, $sState, $sStimulus); $aExtraFormParams = array('stimulus' => $sStimulus, 'state' => $sState); DisplayMultipleSelectionForm($oP, $oFilter, 'bulk_stimulus', $oChecker, $aExtraFormParams); break; case 'bulk_stimulus': $sFilter = utils::ReadParam('filter', '', false, 'raw_data'); $sStimulus = utils::ReadParam('stimulus', ''); $sState = utils::ReadParam('state', ''); if (empty($sFilter) || empty($sStimulus) || empty($sState)) { throw new ApplicationException(Dict::Format('UI:Error:3ParametersMissing', 'filter', 'stimulus', 'state')); } $oFilter = DBObjectSearch::unserialize($sFilter); $sClass = $oFilter->GetClass(); $aSelectObject = utils::ReadMultipleSelection($oFilter); if (count($aSelectObject) == 0) { // Nothing to do, no object was selected ! throw new ApplicationException(Dict::S('UI:BulkAction:NoObjectSelected')); } else { $aTransitions = MetaModel::EnumTransitions($sClass, $sState); $aStimuli = MetaModel::EnumStimuli($sClass); $sActionLabel = $aStimuli[$sStimulus]->GetLabel(); $sActionDetails = $aStimuli[$sStimulus]->GetDescription(); $aTransition = $aTransitions[$sStimulus]; $sTargetState = $aTransition['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']; $aDetails = array(); $iFieldIndex = 0; $aFieldsMap = array(); $aValues = array(); $aObjects = array(); foreach($aSelectObject as $iId) { $aObjects[] = MetaModel::GetObject($sClass, $iId); } $oSet = DBObjectSet::FromArray($sClass, $aObjects); $oObj = $oSet->ComputeCommonObject($aValues); $sStateAttCode = MetaModel::GetStateAttributeCode($sClass); $oObj->Set($sStateAttCode,$sTargetState); $sReadyScript = ''; foreach($aExpectedAttributes as $sAttCode => $iExpectCode) { // 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) == '')) ) { $aAttributesDef = MetaModel::ListAttributeDefs($sClass); $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode); $aPrerequisites = MetaModel::GetPrequisiteAttributes($sClass, $sAttCode); // List of attributes that are needed for the current one if (count($aPrerequisites) > 0) { // When 'enabling' a field, all its prerequisites must be enabled too $sFieldList = "['".implode("','", $aPrerequisites)."']"; $oP->add_ready_script("$('#enable_{$sAttCode}').bind('change', function(evt, sFormId) { return PropagateCheckBox( this.checked, $sFieldList, true); } );\n"); } $aDependents = MetaModel::GetDependentAttributes($sClass, $sAttCode); // List of attributes that are needed for the current one if (count($aDependents) > 0) { // When 'disabling' a field, all its dependent fields must be disabled too $sFieldList = "['".implode("','", $aDependents)."']"; $oP->add_ready_script("$('#enable_{$sAttCode}').bind('change', function(evt, sFormId) { return PropagateCheckBox( this.checked, $sFieldList, false); } );\n"); } $aArgs = array('this' => $oObj); $sHTMLValue = cmdbAbstractObject::GetFormElementForField($oP, $sClass, $sAttCode, $oAttDef, $oObj->Get($sAttCode), $oObj->GetEditValue($sAttCode), $sAttCode, '', $iExpectCode, $aArgs); $sComments = ''; if (!isset($aValues[$sAttCode])) { $aValues[$sAttCode] = array(); } if (count($aValues[$sAttCode]) == 1) { $sComments .= '
1
'; } else { // Non-homogenous value $iMaxCount = 5; $sTip = "

".Dict::Format('UI:BulkModify_Count_DistinctValues', count($aValues[$sAttCode]))."

    "; $index = 0; foreach($aValues[$sAttCode] as $sCurrValue => $aVal) { $sDisplayValue = empty($aVal['display']) ? ''.Dict::S('Enum:Undefined').'' : str_replace(array("\n", "\r"), " ", $aVal['display']); $sTip .= "
  • ".Dict::Format('UI:BulkModify:Value_Exists_N_Times', $sDisplayValue, $aVal['count'])."
  • "; $index++; if ($iMaxCount == $index) { $sTip .= "
  • ".Dict::Format('UI:BulkModify:N_MoreValues', count($aValues[$sAttCode]) - $iMaxCount)."
  • "; break; } } $sTip .= "

"; $sTip = addslashes($sTip); $sReadyScript .= "$('#multi_values_$sAttCode').qtip( { content: '$sTip', show: 'mouseover', hide: 'mouseout', style: { name: 'dark', tip: 'leftTop' }, position: { corner: { target: 'rightMiddle', tooltip: 'leftTop' }} } );\n"; $sComments .= '
'.count($aValues[$sAttCode]).'
'; } $aDetails[] = array('label' => ''.$oAttDef->GetLabel().'', 'value' => "$sHTMLValue", 'comments' => $sComments); $aFieldsMap[$sAttCode] = $sAttCode; $iFieldIndex++; } } $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"); $oP->add("
\n"); $oP->details($aDetails); $oP->add("
\n"); $oP->add("\n"); $oP->add("\n"); $oP->add("\n"); $oP->add("\n"); $oP->add("\n"); $oP->add("\n"); $oP->add("\n"); $oP->add($oAppContext->GetForForm()); $oP->add("\n"); $sURL = "./UI.php?operation=search&filter=".urlencode($sFilter)."&".$oAppContext->GetForLink(); $oP->add("    \n"); $oP->add("\n"); $oP->add("
\n"); $oP->add("
\n"); if ($sButtonsPosition != 'bottom') { // top 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( <<p(Dict::S('UI:Error:ObjectAlreadyUpdated')); } else { // For archiving the modification $oFilter = DBObjectSearch::unserialize($sFilter); $sClass = $oFilter->GetClass(); $aObjects = array(); foreach($aSelectObject as $iId) { $aObjects[] = MetaModel::GetObject($sClass, $iId); } $aTransitions = MetaModel::EnumTransitions($sClass, $sState); $aStimuli = MetaModel::EnumStimuli($sClass); $sActionLabel = $aStimuli[$sStimulus]->GetLabel(); $sActionDetails = $aStimuli[$sStimulus]->GetDescription(); $oP->set_title(Dict::Format('UI:StimulusModify_N_ObjectsOf_Class', $sActionLabel, count($aObjects), $sClass)); $oP->add(''); $oSet = DBObjectSet::FromArray($sClass, $aObjects); $oMyChange = MetaModel::NewObject("CMDBChange"); $oMyChange->Set("date", time()); $sUserString = CMDBChange::GetCurrentUserName(); $oMyChange->Set("userinfo", $sUserString); $iChangeId = $oMyChange->DBInsert(); // For reporting $aHeaders = array( 'object' => array('label' => MetaModel::GetName($sClass), 'description' => Dict::S('UI:ModifiedObject')), 'status' => array('label' => Dict::S('UI:BulkModifyStatus'), 'description' => Dict::S('UI:BulkModifyStatus+')), 'errors' => array('label' => Dict::S('UI:BulkModifyErrors'), 'description' => Dict::S('UI:BulkModifyErrors+')), ); $aRows = array(); while ($oObj = $oSet->Fetch()) { $sError = Dict::S('UI:BulkModifyStatusOk'); try { $aTransitions = $oObj->EnumTransitions(); $aStimuli = MetaModel::EnumStimuli($sClass); if (!isset($aTransitions[$sStimulus])) { throw new ApplicationException(Dict::Format('UI:Error:Invalid_Stimulus_On_Object_In_State', $sStimulus, $oObj->GetName(), $oObj->GetStateLabel())); } else { $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']; $aDetails = array(); $aErrors = array(); foreach($aExpectedAttributes as $sAttCode => $iExpectCode) { $iFlags = $oObj->GetAttributeFlags($sAttCode); if (($iExpectCode & (OPT_ATT_MUSTCHANGE|OPT_ATT_MUSTPROMPT)) || ($oObj->Get($sAttCode) == '') ) { $paramValue = utils::ReadPostedParam("attr_$sAttCode", '', 'raw_data'); if ( ($iFlags & OPT_ATT_SLAVE) && ($paramValue != $oObj->Get($sAttCode)) ) { $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode); $aErrors[] = Dict::Format('UI:AttemptingToSetASlaveAttribute_Name', $oAttDef->GetLabel()); } else { $oObj->Set($sAttCode, $paramValue); } } } if (count($aErrors) == 0) { if ($oObj->ApplyStimulus($sStimulus)) { list($bResult, $aErrors) = $oObj->CheckToWrite(); $sStatus = $bResult ? Dict::S('UI:BulkModifyStatusModified') : Dict::S('UI:BulkModifyStatusSkipped'); if ($bResult) { $oObj->DBUpdateTracked($oMyChange); } else { $sError = '

'.implode('

',$aErrors)."

\n"; } } else { $sStatus = Dict::S('UI:BulkModifyStatusSkipped'); $sError = '

'.Dict::S('UI:FailedToApplyStimuli')."

\n"; } } else { $sStatus = Dict::S('UI:BulkModifyStatusSkipped'); $sError = '

'.implode('

',$aErrors)."

\n"; } } } catch(Exception $e) { $sError = $e->getMessage(); $sStatus = Dict::S('UI:BulkModifyStatusSkipped'); } $aRows[] = array( 'object' => $oObj->GetHyperlink(), 'status' => $sStatus, 'errors' => $sError, ); } $oP->Table($aHeaders, $aRows); // Back to the list $sURL = "./UI.php?operation=search&filter=".urlencode($sFilter)."&".$oAppContext->GetForLink(); $oP->add(''); } break; case 'stimulus': // Form displayed when applying a stimulus (state change) $sClass = utils::ReadParam('class', '', false, 'class'); $id = utils::ReadParam('id', ''); $sStimulus = utils::ReadParam('stimulus', ''); if ( empty($sClass) || empty($id) || empty($sStimulus) ) // TO DO: check that the class name is valid ! { throw new ApplicationException(Dict::Format('UI:Error:3ParametersMissing', 'class', 'id', 'stimulus')); } $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( <<set_title(Dict::S('UI:ErrorPageTitle')); $oP->P(Dict::S('UI:ObjectDoesNotExist')); } break; /////////////////////////////////////////////////////////////////////////////////////////// case 'apply_stimulus': // Actual state change $sClass = utils::ReadPostedParam('class', ''); $id = utils::ReadPostedParam('id', ''); $sTransactionId = utils::ReadPostedParam('transaction_id', ''); $sStimulus = utils::ReadPostedParam('stimulus', ''); if ( empty($sClass) || empty($id) || empty($sStimulus) ) // TO DO: check that the class name is valid ! { throw new ApplicationException(Dict::Format('UI:Error:3ParametersMissing', 'class', 'id', 'stimulus')); } $oObj = MetaModel::GetObject($sClass, $id, false); if ($oObj != null) { $aTransitions = $oObj->EnumTransitions(); $aStimuli = MetaModel::EnumStimuli($sClass); if (!isset($aTransitions[$sStimulus])) { throw new ApplicationException(Dict::Format('UI:Error:Invalid_Stimulus_On_Object_In_State', $sStimulus, $oObj->GetName(), $oObj->GetStateLabel())); } if (!utils::IsTransactionValid($sTransactionId)) { $oP->p(Dict::S('UI:Error:ObjectAlreadyUpdated')); } else { $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']; $aDetails = array(); $aErrors = array(); foreach($aExpectedAttributes as $sAttCode => $iExpectCode) { $iFlags = $oObj->GetAttributeFlags($sAttCode); if (($iExpectCode & (OPT_ATT_MUSTCHANGE|OPT_ATT_MUSTPROMPT)) || ($oObj->Get($sAttCode) == '') ) { $paramValue = utils::ReadPostedParam("attr_$sAttCode", '', 'raw_data'); if ( ($iFlags & OPT_ATT_SLAVE) && ($paramValue != $oObj->Get($sAttCode))) { $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode); $aErrors[] = Dict::Format('UI:AttemptingToChangeASlaveAttribute_Name', $oAttDef->GetLabel()); } else { $oObj->Set($sAttCode, $paramValue); } } } if (count($aErrors) == 0) { if ($oObj->ApplyStimulus($sStimulus)) { $oMyChange = MetaModel::NewObject("CMDBChange"); $oMyChange->Set("date", time()); $sUserString = CMDBChange::GetCurrentUserName(); $oMyChange->Set("userinfo", $sUserString); $iChangeId = $oMyChange->DBInsert(); $oObj->DBUpdateTracked($oMyChange); $oP->p(Dict::Format('UI:Class_Object_Updated', MetaModel::GetName(get_class($oObj)), $oObj->GetName())); } else { $oP->p(Dict::S('UI:FailedToApplyStimuli')); } } else { $oP->p(implode('

', $aErrors)); } } $oObj->Reload(); $oObj->DisplayDetails($oP); } else { $oP->set_title(Dict::S('UI:ErrorPageTitle')); $oP->P(Dict::S('UI:ObjectDoesNotExist')); } break; /////////////////////////////////////////////////////////////////////////////////////////// case 'swf_navigator': // Graphical display of the relations "impact" / "depends on" $sClass = utils::ReadParam('class', '', false, 'class'); $id = utils::ReadParam('id', 0); $sRelation = utils::ReadParam('relation', 'impact'); $oP->AddTabContainer('Navigator'); $oP->SetCurrentTabContainer('Navigator'); $oP->SetCurrentTab(Dict::S('UI:RelationshipGraph')); $oP->add("

\n"); $oP->add_ready_script( <<GetRelatedObjects($sRelation, 20 /* iMaxDepth */, $aResults); foreach($aResults as $sClassIdx => $aObjects) { foreach($aObjects as $oCurrObj) { $sSubClass = get_class($oCurrObj); $aSortedElements[$sSubClass] = MetaModel::GetName($sSubClass); } } asort($aSortedElements); $idx = 0; foreach($aSortedElements as $sSubClass => $sClassName) { $oP->add(" "); $idx++; } $oP->add("

"); $oP->add("
\n"); $oP->add("
\n"); $oP->add("
".Dict::S('UI:ElementsDisplayed')."
\n"); $width = 1000; $height = 700; $sDrillUrl = utils::GetAbsoluteUrlAppRoot().'pages/UI.php?operation=details&'.$oAppContext->GetForLink(); $sParams = "pWidth=$width&pHeight=$height&drillUrl=".urlencode($sDrillUrl)."&displayController=false&xmlUrl=".urlencode("./xml.navigator.php")."&obj_class=$sClass&obj_id=$id&relation=$sRelation"; $oP->add("
\n"); $oP->SetCurrentTab(Dict::S('UI:RelationshipList')); $oP->add("

 

"); $oP->add_script( <<add_ready_script( <<SetCurrentTab(''); break; /////////////////////////////////////////////////////////////////////////////////////////// case 'cancel': // An action was cancelled $oP->set_title(Dict::S('UI:OperationCancelled')); $oP->add('

'.Dict::S('UI:OperationCancelled').'

'); break; /////////////////////////////////////////////////////////////////////////////////////////// default: // Menu node rendering (templates) $oMenuNode = ApplicationMenu::GetMenuNode(ApplicationMenu::GetMenuIndexById(ApplicationMenu::GetActiveNodeId())); if (is_object($oMenuNode)) { $oMenuNode->RenderContent($oP, $oAppContext->GetAsHash()); $oP->set_title($oMenuNode->GetLabel()); } /////////////////////////////////////////////////////////////////////////////////////////// } $oKPI->ComputeAndReport('GUI creation before output'); ExecutionKPI::ReportStats(); MetaModel::ShowQueryTrace(); DisplayWelcomePopup($oP); $oP->output(); } catch(CoreException $e) { require_once(APPROOT.'/setup/setuppage.class.inc.php'); $oP = new SetupPage(Dict::S('UI:PageTitle:FatalError')); if ($e instanceof SecurityException) { $oP->add("

".Dict::S('UI:SystemIntrusion')."

\n"); } else { $oP->add("

".Dict::S('UI:FatalErrorMessage')."

\n"); } $oP->error(Dict::Format('UI:Error_Details', $e->getHtmlDesc())); $oP->output(); if (MetaModel::IsLogEnabledIssue()) { if (MetaModel::IsValidClass('EventIssue')) { try { $oLog = new EventIssue(); $oLog->Set('message', $e->getMessage()); $oLog->Set('userinfo', ''); $oLog->Set('issue', $e->GetIssue()); $oLog->Set('impact', 'Page could not be displayed'); $oLog->Set('callstack', $e->getTrace()); $oLog->Set('data', $e->getContextData()); $oLog->DBInsertNoReload(); } catch(Exception $e) { IssueLog::Error("Failed to log issue into the DB"); } } IssueLog::Error($e->getMessage()); } // For debugging only //throw $e; } catch(Exception $e) { require_once(APPROOT.'/setup/setuppage.class.inc.php'); $oP = new SetupPage(Dict::S('UI:PageTitle:FatalError')); $oP->add("

".Dict::S('UI:FatalErrorMessage')."

\n"); $oP->error(Dict::Format('UI:Error_Details', $e->getMessage())); $oP->output(); if (MetaModel::IsLogEnabledIssue()) { if (MetaModel::IsValidClass('EventIssue')) { try { $oLog = new EventIssue(); $oLog->Set('message', $e->getMessage()); $oLog->Set('userinfo', ''); $oLog->Set('issue', 'PHP Exception'); $oLog->Set('impact', 'Page could not be displayed'); $oLog->Set('callstack', $e->getTrace()); $oLog->Set('data', array()); $oLog->DBInsertNoReload(); } catch(Exception $e) { IssueLog::Error("Failed to log issue into the DB"); } } IssueLog::Error($e->getMessage()); } } ?>