示例#1
0
function ShowExamples($oP, $sExpression)
{
    $bUsingExample = false;
    $aExamples = array('Pedagogic examples' => array("Web applications" => "SELECT WebApplication", "Person having an 'A' in their name" => "SELECT Person AS B WHERE B.name LIKE '%A%'", "Servers having a name like dbserver1.demo.com or dbserver023.foo.fr" => "SELECT Server WHERE name REGEXP '^dbserver[0-9]+\\\\..+\\\\.[a-z]{2,3}\$'", "Changes planned on new year's day" => "SELECT Change AS ch WHERE ch.start_date >= '2009-12-31' AND ch.end_date <= '2010-01-01'", "IPs in a range" => "SELECT DatacenterDevice AS dev WHERE INET_ATON(dev.managementip) > INET_ATON('10.22.32.224') AND INET_ATON(dev.managementip) < INET_ATON('10.22.32.255')", "Persons below a given root organization" => "SELECT Person AS P JOIN Organization AS Node ON P.org_id = Node.id JOIN Organization AS Root ON Node.parent_id BELOW Root.id WHERE Root.id=1"), 'Usefull examples' => array("NW interfaces of equipment in production for customer 'Demo'" => "SELECT PhysicalInterface AS if JOIN DatacenterDevice AS dev ON if.connectableci_id = dev.id WHERE dev.status = 'production' AND dev.organization_name = 'Demo'", "My tickets" => "SELECT Ticket AS t WHERE t.agent_id = :current_contact_id", "People being owner of an active ticket" => "SELECT Person AS p JOIN UserRequest AS u ON u.agent_id = p.id WHERE u.status != 'closed'", "Contracts terminating in the next thirty days" => "SELECT Contract AS c WHERE c.end_date > NOW() AND c.end_date < DATE_ADD(NOW(), INTERVAL 30 DAY)", "Orphan tickets (opened one hour ago, still not assigned)" => "SELECT UserRequest AS u WHERE u.start_date < DATE_SUB(NOW(), INTERVAL 60 MINUTE) AND u.status = 'new'", "Long lasting incidents (duration > 8 hours)" => "SELECT UserRequest AS u WHERE u.close_date > DATE_ADD(u.start_date, INTERVAL 8 HOUR)"));
    $aDisplayData = array();
    $oAppContext = new ApplicationContext();
    $sContext = $oAppContext->GetForForm();
    foreach ($aExamples as $sTopic => $aQueries) {
        foreach ($aQueries as $sDescription => $sOql) {
            $sHighlight = '';
            $sDisable = '';
            if ($sOql == $sExpression) {
                // this one is currently being tested, highlight it
                $sHighlight = "background-color:yellow;";
                $sDisable = 'disabled';
                // and remember we are testing a query of the list
                $bUsingExample = true;
            }
            //$aDisplayData[$sTopic][] = array(
            $aDisplayData[Dict::S('UI:RunQuery:QueryExamples')][] = array('desc' => "<div style=\"{$sHighlight}\">" . htmlentities($sDescription, ENT_QUOTES, 'UTF-8') . "</div>", 'oql' => "<div style=\"{$sHighlight}\">" . htmlentities($sOql, ENT_QUOTES, 'UTF-8') . "</div>", 'go' => "<form method=\"get\"><input type=\"hidden\" name=\"expression\" value=\"{$sOql}\"><input type=\"submit\" value=\"" . Dict::S('UI:Button:Test') . "\" {$sDisable}>{$sContext}</form>\n");
        }
    }
    $aDisplayConfig = array();
    $aDisplayConfig['desc'] = array('label' => Dict::S('UI:RunQuery:HeaderPurpose'), 'description' => Dict::S('UI:RunQuery:HeaderPurpose+'));
    $aDisplayConfig['oql'] = array('label' => Dict::S('UI:RunQuery:HeaderOQLExpression'), 'description' => Dict::S('UI:RunQuery:HeaderOQLExpression+'));
    $aDisplayConfig['go'] = array('label' => '', 'description' => '');
    foreach ($aDisplayData as $sTopic => $aQueriesDisplayData) {
        $bShowOpened = $bUsingExample;
        $oP->StartCollapsibleSection($sTopic, $bShowOpened);
        $oP->table($aDisplayConfig, $aQueriesDisplayData);
        $oP->EndCollapsibleSection();
    }
}
 /**
  * Perform all the needed checks to delete one (or more) objects
  */
 public static function DeleteObjects(WebPage $oP, $sClass, $aObjects, $bPreview, $sCustomOperation, $aContextData = array())
 {
     $oDeletionPlan = new DeletionPlan();
     foreach ($aObjects as $oObj) {
         if ($bPreview) {
             $oObj->CheckToDelete($oDeletionPlan);
         } else {
             $oObj->DBDeleteTracked(CMDBObject::GetCurrentChange(), null, $oDeletionPlan);
         }
     }
     if ($bPreview) {
         if (count($aObjects) == 1) {
             $oObj = $aObjects[0];
             $oP->add("<h1>" . Dict::Format('UI:Delete:ConfirmDeletionOf_Name', $oObj->GetName()) . "</h1>\n");
         } else {
             $oP->add("<h1>" . Dict::Format('UI:Delete:ConfirmDeletionOf_Count_ObjectsOf_Class', count($aObjects), MetaModel::GetName($sClass)) . "</h1>\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 {
                 $oP->p(Dict::S('UI:Delete:PleaseDoTheManualOperations'));
             }
             $oAppContext = new ApplicationContext();
             $oP->add("<form method=\"post\">\n");
             $oP->add("<input type=\"hidden\" name=\"transaction_id\" value=\"" . utils::ReadParam('transaction_id') . "\">\n");
             $oP->add("<input type=\"button\" onclick=\"window.history.back();\" value=\"" . Dict::S('UI:Button:Back') . "\">\n");
             $oP->add("<input DISABLED type=\"submit\" name=\"\" value=\"" . Dict::S('UI:Button:Delete') . "\">\n");
             $oP->add($oAppContext->GetForForm());
             $oP->add("</form>\n");
         } else {
             if (count($aObjects) == 1) {
                 $oObj = $aObjects[0];
                 $id = $oObj->GetKey();
                 $oP->p('<h1>' . Dict::Format('UI:Delect:Confirm_Object', $oObj->GetHyperLink()) . '</h1>');
             } else {
                 $oP->p('<h1>' . Dict::Format('UI:Delect:Confirm_Count_ObjectsOf_Class', count($aObjects), MetaModel::GetName($sClass)) . '</h1>');
             }
             foreach ($aObjects as $oObj) {
                 $aKeys[] = $oObj->GetKey();
             }
             $oFilter = new DBObjectSearch($sClass);
             $oFilter->AddCondition('id', $aKeys, 'IN');
             $oSet = new CMDBobjectSet($oFilter);
             $oP->add('<div id="0">');
             CMDBAbstractObject::DisplaySet($oP, $oSet, array('display_limit' => false, 'menu' => false));
             $oP->add("</div>\n");
             $oP->add("<form method=\"post\">\n");
             foreach ($aContextData as $sKey => $value) {
                 $oP->add("<input type=\"hidden\" name=\"{$sKey}\" value=\"{$value}\">\n");
             }
             $oP->add("<input type=\"hidden\" name=\"transaction_id\" value=\"" . utils::GetNewTransactionId() . "\">\n");
             $oP->add("<input type=\"hidden\" name=\"operation\" value=\"{$sCustomOperation}\">\n");
             $oP->add("<input type=\"hidden\" name=\"filter\" value=\"" . $oFilter->Serialize() . "\">\n");
             $oP->add("<input type=\"hidden\" name=\"class\" value=\"{$sClass}\">\n");
             foreach ($aObjects as $oObj) {
                 $oP->add("<input type=\"hidden\" name=\"selectObject[]\" value=\"" . $oObj->GetKey() . "\">\n");
             }
             $oP->add("<input type=\"button\" onclick=\"window.history.back();\" value=\"" . Dict::S('UI:Button:Back') . "\">\n");
             $oP->add("<input type=\"submit\" name=\"\" value=\"" . Dict::S('UI:Button:Delete') . "\">\n");
             $oAppContext = new ApplicationContext();
             $oP->add($oAppContext->GetForForm());
             $oP->add("</form>\n");
         }
     } else {
         // Execute the deletion
         //
         if (count($aObjects) == 1) {
             $oObj = $aObjects[0];
             $oP->add("<h1>" . Dict::Format('UI:Title:DeletionOf_Object', $oObj->GetName()) . "</h1>\n");
         } else {
             $oP->add("<h1>" . Dict::Format('UI:Title:BulkDeletionOf_Count_ObjectsOf_Class', count($aObjects), MetaModel::GetName($sClass)) . "</h1>\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);
         }
     }
 }
示例#3
0
 public function GetSiloSelectionForm()
 {
     // List of visible Organizations
     $iCount = 0;
     $oSet = null;
     if (MetaModel::IsValidClass('Organization')) {
         // Display the list of *favorite* organizations... but keeping in mind what is the real number of organizations
         $aFavoriteOrgs = appUserPreferences::GetPref('favorite_orgs', null);
         $oSearchFilter = new DBObjectSearch('Organization');
         $oSearchFilter->SetModifierProperty('UserRightsGetSelectFilter', 'bSearchMode', true);
         $oSet = new CMDBObjectSet($oSearchFilter);
         $iCount = $oSet->Count();
         // total number of existing Orgs
         // Now get the list of Orgs to be displayed in the menu
         $oSearchFilter = DBObjectSearch::FromOQL(ApplicationMenu::GetFavoriteSiloQuery());
         $oSearchFilter->SetModifierProperty('UserRightsGetSelectFilter', 'bSearchMode', true);
         if (!empty($aFavoriteOrgs)) {
             $oSearchFilter->AddCondition('id', $aFavoriteOrgs, 'IN');
         }
         $oSet = new CMDBObjectSet($oSearchFilter);
         // List of favorite orgs
     }
     switch ($iCount) {
         case 0:
             // No such dimension/silo => nothing to select
             $sHtml = '<div id="SiloSelection"><!-- nothing to select --></div>';
             break;
         case 1:
             // Only one possible choice... no selection, but display the value
             $oOrg = $oSet->Fetch();
             $sHtml = '<div id="SiloSelection">' . $oOrg->GetName() . '</div>';
             $sHtml .= '';
             break;
         default:
             $sHtml = '';
             $oAppContext = new ApplicationContext();
             $iCurrentOrganization = $oAppContext->GetCurrentValue('org_id');
             $sHtml = '<div id="SiloSelection">';
             $sHtml .= '<form style="display:inline" action="' . utils::GetAbsoluteUrlAppRoot() . 'pages/UI.php">';
             //<select class="org_combo" name="c[org_id]" title="Pick an organization" onChange="this.form.submit();">';
             $sFavoriteOrgs = '';
             $oWidget = new UIExtKeyWidget('Organization', 'org_id', '', true);
             $sHtml .= $oWidget->Display($this, 50, false, '', $oSet, $iCurrentOrganization, 'org_id', false, 'c[org_id]', '', array('iFieldSize' => 20, 'iMinChars' => MetaModel::GetConfig()->Get('min_autocomplete_chars'), 'sDefaultValue' => Dict::S('UI:AllOrganizations')), null, 'select', false);
             $this->add_ready_script('$("#org_id").bind("extkeychange", function() { $("#SiloSelection form").submit(); } )');
             $this->add_ready_script("\$('#label_org_id').click( function() { \$(this).val(''); \$('#org_id').val(''); return true; } );\n");
             // Add other dimensions/context information to this form
             $oAppContext->Reset('org_id');
             // org_id is handled above and we want to be able to change it here !
             $oAppContext->Reset('menu');
             // don't pass the menu, since a menu may expect more parameters
             $sHtml .= $oAppContext->GetForForm();
             // Pass what remains, if anything...
             $sHtml .= '</form>';
             $sHtml .= '</div>';
     }
     return $sHtml;
 }
 /**
  * Display the final step of the wizard: a confirmation screen
  */
 public function DisplayFinalStep($iStepIndex, $aFieldsMap)
 {
     $oAppContext = new ApplicationContext();
     $this->m_oPage->add("<div class=\"wizContainer\" id=\"wizStep{$iStepIndex}\" style=\"display:none;\">\n");
     $this->m_oPage->add("<a name=\"step{$iStepIndex}\" />\n");
     $this->m_oPage->P(Dict::S('UI:Wizard:FinalStepTitle'));
     $this->m_oPage->add("<input type=\"hidden\" name=\"operation\" value=\"wizard_apply_new\" />\n");
     $this->m_oPage->add("<input type=\"hidden\" name=\"transaction_id\" value=\"" . utils::GetNewTransactionId() . "\" />\n");
     $this->m_oPage->add("<input type=\"hidden\" id=\"wizard_json_obj\" name=\"json_obj\" value=\"\" />\n");
     $sScript = "function OnEnterStep{$iStepIndex}() {\n";
     foreach ($aFieldsMap as $iInputId => $sAttCode) {
         $sScript .= "\toWizardHelper.UpdateCurrentValue('{$sAttCode}');\n";
     }
     $sScript .= "\toWizardHelper.Preview('object_preview');\n";
     $sScript .= "\t\$('#wizard_json_obj').val(oWizardHelper.ToJSON());\n";
     $sScript .= "}\n";
     $this->m_oPage->add_script($sScript);
     $this->m_oPage->add("<div id=\"object_preview\">\n");
     $this->m_oPage->add("</div>\n");
     $this->m_oPage->add($oAppContext->GetForForm());
     $this->m_oPage->add("<input type=\"button\" value=\"" . Dict::S('UI:Button:Back') . "\" onClick=\"GoToStep({$iStepIndex}, {$iStepIndex} - 1)\" />");
     $this->m_oPage->add("<input type=\"submit\" value=\"Create " . MetaModel::GetName($this->m_sClass) . "\" />\n");
     $this->m_oPage->add("</div>\n");
     $this->m_oPage->add("</form>\n");
 }
示例#5
0
/**
 * 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("<form method=\"post\" action=\"./UI.php\">\n");
    $oP->add("<input type=\"hidden\" name=\"operation\" value=\"{$sNextOperation}\">\n");
    $oP->add("<input type=\"hidden\" name=\"class\" value=\"" . $oFilter->GetClass() . "\">\n");
    $oP->add("<input type=\"hidden\" name=\"filter\" value=\"" . $oFilter->Serialize() . "\">\n");
    $oP->add("<input type=\"hidden\" name=\"transaction_id\" value=\"" . utils::GetNewTransactionId() . "\">\n");
    foreach ($aExtraFormParams as $sName => $sValue) {
        $oP->add("<input type=\"hidden\" name=\"{$sName}\" value=\"{$sValue}\">\n");
    }
    $oP->add($oAppContext->GetForForm());
    $oBlock->Display($oP, 1, $aExtraParams);
    $oP->add("<input type=\"button\" value=\"" . Dict::S('UI:Button:Cancel') . "\" onClick=\"window.history.back()\">&nbsp;&nbsp;<input type=\"submit\" value=\"" . Dict::S('UI:Button:Next') . "\">\n");
    $oP->add("</form>\n");
    $oP->add_ready_script("\$('#1 table.listResults').trigger('check_all');");
}
示例#6
0
$sOperation = utils::ReadParam('operation', '');
// First part: select the class to search for
$oP->add("<form>");
$oP->add(Dict::S('UI:UniversalSearch:LabelSelectTheClass') . "<select style=\"width: 150px;\" id=\"select_class\" name=\"baseClass\" onChange=\"this.form.submit();\">");
$aClassLabels = array();
foreach (MetaModel::GetClasses('bizmodel') as $sCurrentClass) {
    $aClassLabels[$sCurrentClass] = MetaModel::GetName($sCurrentClass);
}
asort($aClassLabels);
foreach ($aClassLabels as $sCurrentClass => $sLabel) {
    $sDescription = MetaModel::GetClassDescription($sCurrentClass);
    $sSelected = $sCurrentClass == $sBaseClass ? " SELECTED" : "";
    $oP->add("<option value=\"{$sCurrentClass}\" title=\"{$sDescription}\"{$sSelected}>{$sLabel}</option>");
}
$oP->add("</select>\n");
$oP->add($oAppContext->GetForForm());
$oP->add("</form>\n");
try {
    if ($sOperation == 'search_form') {
        $sOQL = "SELECT {$sClass} {$sOQLClause}";
        $oFilter = DBObjectSearch::FromOQL($sOQL);
    } else {
        // Second part: advanced search form:
        if (!empty($sFilter)) {
            $oFilter = CMDBSearchFilter::unserialize($sFilter);
        } else {
            if (!empty($sClass)) {
                $oFilter = new CMDBSearchFilter($sClass);
            }
        }
    }
示例#7
0
/**
 * Displays the user's changeable preferences
 * @param $oP WebPage The web page used for the output
 */
function DisplayPreferences($oP)
{
    $oAppContext = new ApplicationContext();
    $sURL = utils::GetAbsoluteUrlAppRoot() . 'pages/UI.php?' . $oAppContext->GetForLink();
    $oP->add('<div class="page_header"><h1><img style="vertical-align:middle" src="../images/preferences.png"/>&nbsp;' . Dict::S('UI:Preferences') . "</h1></div>\n");
    $oP->add('<div id="user_prefs" style="max-width:800px; min-width:400px;">');
    //////////////////////////////////////////////////////////////////////////
    //
    // User Language selection
    //
    //////////////////////////////////////////////////////////////////////////
    $oP->add('<fieldset><legend>' . Dict::S('UI:FavoriteLanguage') . '</legend>');
    $oP->add('<form method="post">');
    $aLanguages = Dict::GetLanguages();
    $aSortedlang = array();
    foreach ($aLanguages as $sCode => $aLang) {
        if (MetaModel::GetConfig()->Get('demo_mode')) {
            if ($sCode != Dict::GetUserLanguage()) {
                // Demo mode: only the current user language is listed in the available choices
                continue;
            }
        }
        $aSortedlang[$aLang['description']] = $sCode;
    }
    ksort($aSortedlang);
    $oP->add('<p>' . Dict::S('UI:Favorites:SelectYourLanguage') . ' <select name="language">');
    foreach ($aSortedlang as $sCode) {
        $sSelected = $sCode == Dict::GetUserLanguage() ? 'selected' : '';
        $oP->add('<option value="' . $sCode . '" ' . $sSelected . '/>' . $aLanguages[$sCode]['description'] . ' (' . $aLanguages[$sCode]['localized_description'] . ')</option>');
    }
    $oP->add('</select></p>');
    $oP->add('<input type="hidden" name="operation" value="apply_language"/>');
    $oP->add($oAppContext->GetForForm());
    $oP->add('<p><input type="button" onClick="window.location.href=\'' . $sURL . '\'" value="' . Dict::S('UI:Button:Cancel') . '"/>');
    $oP->add('&nbsp;&nbsp;');
    $oP->add('<input type="submit" value="' . Dict::S('UI:Button:Apply') . '"/></p>');
    $oP->add('</form>');
    $oP->add('</fieldset>');
    //////////////////////////////////////////////////////////////////////////
    //
    // Other (miscellaneous) settings
    //
    //////////////////////////////////////////////////////////////////////////
    $oP->add('<fieldset><legend>' . Dict::S('UI:FavoriteOtherSettings') . '</legend>');
    $oP->add('<form method="post" onsubmit="return ValidateOtherSettings()">');
    $iDefaultPageSize = appUserPreferences::GetPref('default_page_size', MetaModel::GetConfig()->GetMinDisplayLimit());
    $oP->add('<p>' . Dict::Format('UI:Favorites:Default_X_ItemsPerPage', '<input id="default_page_size" name="default_page_size" type="text" size="3" value="' . $iDefaultPageSize . '"/><span id="v_default_page_size"></span>') . '</p>');
    $oP->add('<input type="hidden" name="operation" value="apply_others"/>');
    $oP->add($oAppContext->GetForForm());
    $oP->add('<p><input type="button" onClick="window.location.href=\'' . $sURL . '\'" value="' . Dict::S('UI:Button:Cancel') . '"/>');
    $oP->add('&nbsp;&nbsp;');
    $oP->add('<input id="other_submit" type="submit" value="' . Dict::S('UI:Button:Apply') . '"/></p>');
    $oP->add('</form>');
    $oP->add('</fieldset>');
    $oP->add_script(<<<EOF
function ValidateOtherSettings()
{
\tvar sPageLength = \$('#default_page_size').val();
\tvar iPageLength = parseInt(sPageLength , 10);
\tif (/^[0-9]+\$/.test(sPageLength) && (iPageLength > 0))
\t{
\t\t\$('#v_default_page_size').html('');
\t\t\$('#other_submit').removeAttr('disabled');
\t\treturn true;
\t}
\telse
\t{
\t\t\$('#v_default_page_size').html('<img src="../images/validation_error.png"/>');
\t\t\$('#other_submit').attr('disabled', 'disabled');
\t\treturn false;
\t}
}
EOF
);
    //////////////////////////////////////////////////////////////////////////
    //
    // Favorite Organizations
    //
    //////////////////////////////////////////////////////////////////////////
    $oP->add('<fieldset><legend>' . Dict::S('UI:FavoriteOrganizations') . '</legend>');
    $oP->p(Dict::S('UI:FavoriteOrganizations+'));
    $oP->add('<form method="post">');
    // Favorite organizations: the organizations listed in the drop-down menu
    $sOQL = ApplicationMenu::GetFavoriteSiloQuery();
    $oFilter = DBObjectSearch::FromOQL($sOQL);
    $oBlock = new DisplayBlock($oFilter, 'list', false);
    $oBlock->Display($oP, 1, array('menu' => false, 'selection_mode' => true, 'selection_type' => 'multiple', 'cssCount' => '.selectedCount', 'table_id' => 'user_prefs'));
    $oP->add($oAppContext->GetForForm());
    $oP->add('<input type="hidden" name="operation" value="apply"/>');
    $oP->add('<p><input type="button" onClick="window.location.href=\'' . $sURL . '\'" value="' . Dict::S('UI:Button:Cancel') . '"/>');
    $oP->add('&nbsp;&nbsp;');
    $oP->add('<input type="submit" value="' . Dict::S('UI:Button:Apply') . '"/></p>');
    $oP->add('</form>');
    $oP->add('</fieldset>');
    $aFavoriteOrgs = appUserPreferences::GetPref('favorite_orgs', null);
    if ($aFavoriteOrgs == null) {
        // All checked
        $oP->add_ready_script(<<<EOF
\tif (\$('#user_prefs table.pagination').length > 0)
\t{
\t\t// paginated display, restore the selection
\t\tvar pager = \$('#user_prefs form .pager');
\t\t\$(':input[name=selectionMode]', pager).val('negative');
\t\t\$('#user_prefs table.listResults').trigger('load_selection');
\t}
\telse
\t{
\t\t\$('#user_prefs table.listResults').trigger('check_all');
\t}
EOF
);
    } else {
        $sChecked = implode('","', $aFavoriteOrgs);
        $oP->add_ready_script(<<<EOF
\tvar aChecked = ["{$sChecked}"];
\tif (\$('#user_prefs table.pagination').length > 0)
\t{
\t\t// paginated display, restore the selection
\t\tvar pager = \$('#user_prefs form .pager');
\t\t\$(':input[name=selectionMode]', pager).val('positive');
\t\tfor (i=0; i<aChecked.length; i++)
\t\t{
\t\t\tpager.append('<input type="hidden" name="storedSelection[]" id="'+aChecked[i]+'" value="'+aChecked[i]+'"/>');
\t\t}
\t\t\$('#user_prefs table.listResults').trigger('load_selection');
\t\t
\t}
\telse
\t{
\t\t\$('#user_prefs form :checkbox[name^=selectObject]').each( function()
\t\t\t{
\t\t\t\tif (\$.inArray(\$(this).val(), aChecked) > -1)
\t\t\t\t{
\t\t\t\t\t\$(this).attr('checked', true);
\t\t\t\t\t\$(this).trigger('change');
\t\t\t\t}
\t\t\t});
\t}
EOF
);
    }
    //////////////////////////////////////////////////////////////////////////
    //
    // Shortcuts
    //
    //////////////////////////////////////////////////////////////////////////
    $oP->add('<fieldset><legend>' . Dict::S('Menu:MyShortcuts') . '</legend>');
    //$oP->p(Dict::S('UI:Menu:MyShortcuts+'));
    $oBMSearch = new DBObjectSearch('Shortcut');
    $oBMSearch->AddCondition('user_id', UserRights::GetUserId(), '=');
    //$aExtraParams = array('menu' => false, 'toolkit_menu' => false, 'display_limit' => false, 'localize_values' => $bLocalize, 'zlist' => 'details');
    $aExtraParams = array();
    $oBlock = new DisplayBlock($oBMSearch, 'list', false, $aExtraParams);
    $oBlock->Display($oP, 'shortcut_list', array('view_link' => false, 'menu' => false, 'toolkit_menu' => false, 'selection_mode' => true, 'selection_type' => 'multiple', 'cssCount' => '#shortcut_selection_count', 'table_id' => 'user_prefs_shortcuts'));
    $oP->add('<p>');
    $oSet = new DBObjectSet($oBMSearch);
    if ($oSet->Count() > 0) {
        $sButtons = '<img src="../images/tv-item-last.gif">';
        $sButtons .= '&nbsp;';
        $sButtons .= '<button id="shortcut_btn_rename">' . Dict::S('UI:Button:Rename') . '</button>';
        $sButtons .= '&nbsp;';
        $sButtons .= '<button id="shortcut_btn_delete">' . Dict::S('UI:Button:Delete') . '</button>';
        // Selection count updated by the pager, and used to enable buttons
        $oP->add('<input type="hidden" id="shortcut_selection_count"/>');
        $oP->add('</fieldset>');
        $sConfirmDelete = addslashes(Dict::S('UI:ShortcutDelete:Confirm'));
        $oP->add_ready_script(<<<EOF
function OnShortcutBtnRename()
{
\tvar oParams = \$('#datatable_shortcut_list').datatable('GetMultipleSelectionParams');
\toParams.operation = 'shortcut_rename_dlg';

\t\$.post(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php', oParams, function(data){
\t\t\$('body').append(data);
\t});
\treturn false;
}

function OnShortcutBtnDelete()
{
\tif (confirm('{$sConfirmDelete}'))
\t{
\t\tvar oParams = \$('#datatable_shortcut_list').datatable('GetMultipleSelectionParams');
\t\toParams.operation = 'shortcut_delete_go';

\t\t\$.post(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php', oParams, function(data){
\t\t\t\$('body').append(data);
\t\t});
\t}
\treturn false;
}

function OnSelectionCountChange()
{
\tvar iCountSelected = \$("#shortcut_selection_count").val();
\tif (iCountSelected == 0)
\t{
\t\t\$('#shortcut_btn_rename').attr('disabled', 'disabled');
\t\t\$('#shortcut_btn_delete').attr('disabled', 'disabled');
\t}
\telse if (iCountSelected == 1)
\t{
\t\t\$('#shortcut_btn_rename').removeAttr('disabled');
\t\t\$('#shortcut_btn_delete').removeAttr('disabled');
\t}
\telse
\t{
\t\t\$('#shortcut_btn_rename').attr('disabled', 'disabled');
\t\t\$('#shortcut_btn_delete').removeAttr('disabled');
\t}
}

var oUpperCheckBox = \$('#datatable_shortcut_list .checkAll').first();
oUpperCheckBox.parent().width(oUpperCheckBox.width() + 2);

\$('#datatable_shortcut_list').append('<tr><td colspan="2">&nbsp;&nbsp;&nbsp;{$sButtons}</td></tr>');
\$('#shortcut_selection_count').bind('change', OnSelectionCountChange);
\$('#shortcut_btn_rename').bind('click', OnShortcutBtnRename);
\$('#shortcut_btn_delete').bind('click', OnShortcutBtnDelete);
OnSelectionCountChange();
EOF
);
    }
    // if count > 0
    //////////////////////////////////////////////////////////////////////////
    //
    // Footer
    //
    $oP->add('</div>');
    $oP->add_ready_script("\$('#fav_page_length').bind('keyup change', function(){ ValidateOtherSettings(); })");
}