public function RenderContent(WebPage $oPage, $aExtraParams = array())
 {
     $oPage->set_title($this->Get('name'));
     switch ($this->Get('auto_reload')) {
         case 'custom':
             $iRate = (int) $this->Get('auto_reload_sec');
             if ($iRate > 0) {
                 // Must a string otherwise it can be evaluated to 'true' and defaults to "standard" refresh rate!
                 $aExtraParams['auto_reload'] = (string) $iRate;
             }
             break;
         default:
         case 'none':
     }
     $bSearchPane = true;
     $bSearchOpen = false;
     try {
         OQLMenuNode::RenderOQLSearch($this->Get('oql'), $this->Get('name'), 'shortcut_' . $this->GetKey(), $bSearchPane, $bSearchOpen, $oPage, $aExtraParams);
     } catch (Exception $e) {
         throw new Exception("The OQL shortcut '" . $this->Get('name') . "' (id: " . $this->GetKey() . ") could not be displayed: " . $e->getMessage());
     }
 }
    public function DisplayStimulusForm(WebPage $oPage, $sStimulus)
    {
        $sClass = get_class($this);
        $aTransitions = $this->EnumTransitions();
        $aStimuli = MetaModel::EnumStimuli($sClass);
        if (!isset($aTransitions[$sStimulus])) {
            // Invalid stimulus
            throw new ApplicationException(Dict::Format('UI:Error:Invalid_Stimulus_On_Object_In_State', $sStimulus, $this->GetName(), $this->GetStateLabel()));
        }
        $sActionLabel = $aStimuli[$sStimulus]->GetLabel();
        $sActionDetails = $aStimuli[$sStimulus]->GetDescription();
        $aTransition = $aTransitions[$sStimulus];
        $sTargetState = $aTransition['target_state'];
        $aTargetStates = MetaModel::EnumStates($sClass);
        $oPage->add("<div class=\"page_header\">\n");
        $oPage->add("<h1>{$sActionLabel} - <span class=\"hilite\">{$this->GetName()}</span></h1>\n");
        $oPage->set_title($sActionLabel);
        $oPage->add("</div>\n");
        $aTargetState = $aTargetStates[$sTargetState];
        $aExpectedAttributes = $aTargetState['attribute_list'];
        $oPage->add("<h1>{$sActionDetails}</h1>\n");
        $sButtonsPosition = MetaModel::GetConfig()->Get('buttons_position');
        if ($sButtonsPosition == 'bottom') {
            // bottom: Displays the ticket details BEFORE the actions
            $oPage->add('<div class="ui-widget-content">');
            $this->DisplayBareProperties($oPage);
            $oPage->add('</div>');
        }
        $oPage->add("<div class=\"wizContainer\">\n");
        $oPage->add("<form id=\"apply_stimulus\" method=\"post\" onSubmit=\"return OnSubmit('apply_stimulus');\">\n");
        $aDetails = array();
        $iFieldIndex = 0;
        $aFieldsMap = array();
        $aDetailsList = $this->FlattenZList(MetaModel::GetZListItems($sClass, 'details'));
        // Order the fields based on their dependencies, set the fields for which there is only one possible value
        // and perform this in the order of dependencies to avoid dead-ends
        $aDeps = array();
        foreach ($aDetailsList as $sAttCode) {
            $aDeps[$sAttCode] = MetaModel::GetPrequisiteAttributes($sClass, $sAttCode);
        }
        $aList = $this->OrderDependentFields($aDeps);
        foreach ($aList as $sAttCode) {
            // Consider only the "expected" fields for the target state
            if (array_key_exists($sAttCode, $aExpectedAttributes)) {
                $iExpectCode = $aExpectedAttributes[$sAttCode];
                // Prompt for an attribute if
                // - the attribute must be changed or must be displayed to the user for confirmation
                // - or the field is mandatory and currently empty
                if ($iExpectCode & (OPT_ATT_MUSTCHANGE | OPT_ATT_MUSTPROMPT) || $iExpectCode & OPT_ATT_MANDATORY && $this->Get($sAttCode) == '') {
                    $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
                    $aArgs = array('this' => $this);
                    // If the field is mandatory, set it to the only possible value
                    if (!$oAttDef->IsNullAllowed() || $iExpectCode & OPT_ATT_MANDATORY) {
                        if ($oAttDef->IsExternalKey()) {
                            $oAllowedValues = MetaModel::GetAllowedValuesAsObjectSet($sClass, $sAttCode, $aArgs);
                            if ($oAllowedValues->Count() == 1) {
                                $oRemoteObj = $oAllowedValues->Fetch();
                                $this->Set($sAttCode, $oRemoteObj->GetKey());
                            }
                        } else {
                            $aAllowedValues = MetaModel::GetAllowedValues_att($sClass, $sAttCode, $aArgs);
                            if (count($aAllowedValues) == 1) {
                                $aValues = array_keys($aAllowedValues);
                                $this->Set($sAttCode, $aValues[0]);
                            }
                        }
                    }
                    $sHTMLValue = cmdbAbstractObject::GetFormElementForField($oPage, $sClass, $sAttCode, $oAttDef, $this->Get($sAttCode), $this->GetEditValue($sAttCode), 'att_' . $iFieldIndex, '', $iExpectCode, $aArgs);
                    $aDetails[] = array('label' => '<span>' . $oAttDef->GetLabel() . '</span>', 'value' => "<span id=\"field_att_{$iFieldIndex}\">{$sHTMLValue}</span>");
                    $aFieldsMap[$sAttCode] = 'att_' . $iFieldIndex;
                    $iFieldIndex++;
                }
            }
        }
        $oPage->add('<table><tr><td>');
        $oPage->details($aDetails);
        $oPage->add('</td></tr></table>');
        $oPage->add("<input type=\"hidden\" name=\"id\" value=\"" . $this->GetKey() . "\" id=\"id\">\n");
        $aFieldsMap['id'] = 'id';
        $oPage->add("<input type=\"hidden\" name=\"class\" value=\"{$sClass}\">\n");
        $oPage->add("<input type=\"hidden\" name=\"operation\" value=\"apply_stimulus\">\n");
        $oPage->add("<input type=\"hidden\" name=\"stimulus\" value=\"{$sStimulus}\">\n");
        $oPage->add("<input type=\"hidden\" name=\"transaction_id\" value=\"" . utils::GetNewTransactionId() . "\">\n");
        $oAppContext = new ApplicationContext();
        $oPage->add($oAppContext->GetForForm());
        $oPage->add("<button type=\"button\" class=\"action\" onClick=\"BackToDetails('{$sClass}', " . $this->GetKey() . ")\"><span>" . Dict::S('UI:Button:Cancel') . "</span></button>&nbsp;&nbsp;&nbsp;&nbsp;\n");
        $oPage->add("<button type=\"submit\" class=\"action\"><span>{$sActionLabel}</span></button>\n");
        $oPage->add("</form>\n");
        $oPage->add("</div>\n");
        if ($sButtonsPosition != 'top') {
            // bottom or both: Displays the ticket details AFTER the actions
            $oPage->add('<div class="ui-widget-content">');
            $this->DisplayBareProperties($oPage);
            $oPage->add('</div>');
        }
        $iFieldsCount = count($aFieldsMap);
        $sJsonFieldsMap = json_encode($aFieldsMap);
        $oPage->add_script(<<<EOF
\t\t// Initializes the object once at the beginning of the page...
\t\tvar oWizardHelper = new WizardHelper('{$sClass}', '', '{$sTargetState}');
\t\toWizardHelper.SetFieldsMap({$sJsonFieldsMap});
\t\toWizardHelper.SetFieldsCount({$iFieldsCount});
EOF
);
        $oPage->add_ready_script(<<<EOF
\t\t// Starts the validation when the page is ready
\t\tCheckFields('apply_stimulus', false);
EOF
);
    }
    public function Display(WebPage $oP, $aExtraParams = array())
    {
        $oAttDef = MetaModel::GetAttributeDef($this->m_sClass, $this->m_sLinkageAttr);
        $sTargetClass = $oAttDef->GetTargetClass();
        $oTargetObj = MetaModel::GetObject($sTargetClass, $this->m_iObjectId);
        $oP->set_title("iTop - " . MetaModel::GetName($this->m_sLinkedClass) . " objects linked with " . MetaModel::GetName(get_class($oTargetObj)) . ": " . $oTargetObj->GetRawName());
        $oP->add("<div class=\"wizContainer\">\n");
        $oP->add("<form method=\"post\">\n");
        $oP->add("<div class=\"page_header\">\n");
        $oP->add("<input type=\"hidden\" id=\"linksToRemove\" name=\"linksToRemove\" value=\"\">\n");
        $oP->add("<input type=\"hidden\" name=\"operation\" value=\"do_modify_links\">\n");
        $oP->add("<input type=\"hidden\" name=\"class\" value=\"{$this->m_sClass}\">\n");
        $oP->add("<input type=\"hidden\" name=\"linkage\" value=\"{$this->m_sLinkageAttr}\">\n");
        $oP->add("<input type=\"hidden\" name=\"object_id\" value=\"{$this->m_iObjectId}\">\n");
        $oP->add("<input type=\"hidden\" name=\"linking_attcode\" value=\"{$this->m_sLinkingAttCode}\">\n");
        $oP->add("<h1>" . Dict::Format('UI:ManageObjectsOf_Class_LinkedWith_Class_Instance', MetaModel::GetName($this->m_sLinkedClass), MetaModel::GetName(get_class($oTargetObj)), "<span class=\"hilite\">" . $oTargetObj->GetHyperlink() . "</span>") . "</h1>\n");
        $oP->add("</div>\n");
        $oP->add_script(<<<EOF
\t\tfunction OnSelectChange()
\t\t{
\t\t\tvar nbChecked = \$('.selection:checked').length;
\t\t\tif (nbChecked > 0)
\t\t\t{
\t\t\t\t\$('#btnRemove').removeAttr('disabled');
\t\t\t}
\t\t\telse
\t\t\t{
\t\t\t\t\$('#btnRemove').attr('disabled','disabled');
\t\t\t}
\t\t}
\t\t
\t\tfunction RemoveSelected()
\t\t{
\t\t\t\$('.selection:checked').each(
\t\t\t\tfunction()
\t\t\t\t{
\t\t\t\t\t\$('#linksToRemove').val(\$('#linksToRemove').val() + ' ' + this.value);
\t\t\t\t\t\$('#row_'+this.value).remove();
\t\t\t\t}
\t\t\t);
\t\t\t// Disable the button since all the selected items have been removed
\t\t\t\$('#btnRemove').attr('disabled','disabled');
\t\t\t// Re-run the zebra plugin to properly highlight the remaining lines
\t\t\t\$('.listResults').trigger('update');
\t\t\t
\t\t}
\t\t
\t\tfunction AddObjects()
\t\t{
\t\t\t// TO DO: compute the list of objects already linked with the current Object
\t\t\t\$.post( GetAbsoluteUrlAppRoot()+'pages/ajax.render.php', { 'operation': 'addObjects',
\t\t\t\t\t\t\t\t\t\t'class': '{$this->m_sClass}',
\t\t\t\t\t\t\t\t\t\t'linkageAttr': '{$this->m_sLinkageAttr}',
\t\t\t\t\t\t\t\t\t\t'linkedClass': '{$this->m_sLinkedClass}',
\t\t\t\t\t\t\t\t\t\t'objectId': '{$this->m_iObjectId}'
\t\t\t\t\t\t\t\t\t\t}, 
\t\t\t\tfunction(data)
\t\t\t\t{
\t\t\t\t\t\$('#ModalDlg').html(data);
\t\t\t\t\tdlgWidth = \$(document).width() - 100;
\t\t\t\t\t\$('#ModalDlg').css('width', dlgWidth);
\t\t\t\t\t\$('#ModalDlg').css('left', 50);
\t\t\t\t\t\$('#ModalDlg').css('top', 50);
\t\t\t\t\t\$('#ModalDlg').dialog( 'open' );
\t\t\t\t},
\t\t\t\t'html'
\t\t\t);
\t\t}
\t\t
\t\tfunction SearchObjectsToAdd(currentFormId)
\t\t{
\t\t\tvar theMap = { 'class': '{$this->m_sClass}',
\t\t\t\t\t\t   'linkageAttr': '{$this->m_sLinkageAttr}',
\t\t\t\t\t\t   'linkedClass': '{$this->m_sLinkedClass}',
\t\t\t\t\t\t   'objectId': '{$this->m_iObjectId}'
\t\t\t\t\t\t }
\t\t\tif (\$('#'+currentFormId+' :input[name=class]').val() != undefined)
\t\t\t{
\t\t\t\ttheMap.linkedClass = \$('#'+currentFormId+' :input[name=class]').val();
\t\t\t}
\t\t\t// Gather the parameters from the search form
\t\t\t\$('#'+currentFormId+' :input').each(
\t\t\t\tfunction(i)
\t\t\t\t{
\t\t\t\t\tif (this.name != '')
\t\t\t\t\t{
\t\t\t\t\t\ttheMap[this.name] = this.value;
\t\t\t\t\t}
\t\t\t\t}
\t\t\t);
\t\t\ttheMap['operation'] = 'searchObjectsToAdd';
\t\t\t
\t\t\t// Run the query and display the results
\t\t\t\$.post( GetAbsoluteUrlAppRoot()+'pages/ajax.render.php', theMap, 
\t\t\t\tfunction(data)
\t\t\t\t{
\t\t\t\t\t\$('#SearchResultsToAdd').html(data);
\t\t\t\t\t\$('#SearchResultsToAdd .listResults').tablesorter( { headers: {0: false}}, widgets: ['myZebra', 'truncatedList']} ); // sortable and zebra tables
\t\t\t\t\t
\t\t\t\t},
\t\t\t\t'html'
\t\t\t);

\t\t\treturn false;
\t\t}
\t\t
\t\tfunction DoAddObjects(currentFormId)
\t\t{
\t\t\tvar theMap = { 'class': '{$this->m_sClass}',
\t\t\t\t\t\t   'linkageAttr': '{$this->m_sLinkageAttr}',
\t\t\t\t\t\t   'linkedClass': '{$this->m_sLinkedClass}',
\t\t\t\t\t\t   'objectId': '{$this->m_iObjectId}'
\t\t\t\t\t\t }
\t\t\t
\t\t\t// Gather the parameters from the search form
\t\t\t\$('#'+currentFormId+' :input').each(
\t\t\t\tfunction(i)
\t\t\t\t{
\t\t\t\t\tif ( (this.name != '') && ((this.type != 'checkbox') || (this.checked)) ) 
\t\t\t\t\t{
\t\t\t\t\t\t//console.log(this.type);
\t\t\t\t\t\tarrayExpr = /\\[\\]\$/;
\t\t\t\t\t\tif (arrayExpr.test(this.name))
\t\t\t\t\t\t{
\t\t\t\t\t\t\t// Array
\t\t\t\t\t\t\tif (theMap[this.name] == undefined)
\t\t\t\t\t\t\t{
\t\t\t\t\t\t\t\ttheMap[this.name] = new Array();
\t\t\t\t\t\t\t}
\t\t\t\t\t\t\ttheMap[this.name].push(this.value);
\t\t\t\t\t\t}
\t\t\t\t\t\telse
\t\t\t\t\t\t{
\t\t\t\t\t\t\ttheMap[this.name] = this.value;
\t\t\t\t\t\t}
\t\t\t\t\t}
\t\t\t\t}
\t\t\t);
\t\t\ttheMap['operation'] = 'doAddObjects';
\t\t\t
\t\t\t// Run the query and display the results
\t\t\t\$.post( GetAbsoluteUrlAppRoot()+'pages/ajax.render.php', theMap, 
\t\t\t\tfunction(data)
\t\t\t\t{
\t\t\t\t\t//console.log('Data: ' + data);
\t\t\t\t\tif (data != '')
\t\t\t\t\t{
\t\t\t\t\t\t\$('#empty_row').remove();
\t\t\t\t\t}
\t\t\t\t\t\$('.listResults tbody').append(data);
\t\t\t\t\t\$('.listResults').trigger('update');
\t\t\t\t\t\$('.listResults').tablesorter( { headers: {0: false}}, widgets: ['myZebra', 'truncatedList']} ); // sortable and zebra tables
\t\t\t\t},
\t\t\t\t'html'
\t\t\t);
\t\t\t\$('#ModalDlg').dialog('close');
\t\t\treturn false;
\t\t}
\t\t
\t\tfunction InitForm()
\t\t{
\t\t\t// make sure that the form is clean
\t\t\t\$('.selection').each( function() { this.checked = false; });
\t\t\t\$('#btnRemove').attr('disabled','disabled');
\t\t\t\$('#linksToRemove').val('');
\t\t}
\t\t
\t\tfunction SubmitHook() 
\t\t{
\t\t\tvar the_form = this;
\t\t\tSearchObjectsToAdd(the_form.id);
\t\t\treturn false;
\t\t}
EOF
);
        $oP->add_ready_script("InitForm();");
        $oFilter = new DBObjectSearch($this->m_sClass);
        $oFilter->AddCondition($this->m_sLinkageAttr, $this->m_iObjectId, '=');
        $oSet = new DBObjectSet($oFilter);
        $aForm = array();
        while ($oCurrentLink = $oSet->Fetch()) {
            $aRow = array();
            $key = $oCurrentLink->GetKey();
            $oLinkedObj = MetaModel::GetObject($this->m_sLinkedClass, $oCurrentLink->Get($this->m_sLinkingAttCode));
            $aForm[$key] = $this->GetFormRow($oP, $oLinkedObj, $oCurrentLink);
        }
        //var_dump($aTableLabels);
        //var_dump($aForm);
        $this->DisplayFormTable($oP, $this->m_aTableConfig, $aForm);
        $oP->add("<span style=\"float:left;\">&nbsp;&nbsp;&nbsp;<img src=\"../images/tv-item-last.gif\">&nbsp;&nbsp;<input id=\"btnRemove\" type=\"button\" value=\"" . Dict::S('UI:RemoveLinkedObjectsOf_Class') . "\" onClick=\"RemoveSelected();\" >");
        $oP->add("&nbsp;&nbsp;&nbsp;<input id=\"btnAdd\" type=\"button\" value=\"" . Dict::Format('UI:AddLinkedObjectsOf_Class', MetaModel::GetName($this->m_sLinkedClass)) . "\" onClick=\"AddObjects();\"></span>\n");
        $oP->add("<span style=\"float:right;\"><input id=\"btnCancel\" type=\"button\" value=\"" . Dict::S('UI:Button:Cancel') . "\" onClick=\"BackToDetails('" . $sTargetClass . "', " . $this->m_iObjectId . ");\">");
        $oP->add("&nbsp;&nbsp;&nbsp;<input id=\"btnOk\" type=\"submit\" value=\"" . Dict::S('UI:Button:Ok') . "\"></span>\n");
        $oP->add("<span style=\"clear:both;\"><p>&nbsp;</p></span>\n");
        $oP->add("</div>\n");
        $oP->add("</form>\n");
        if (isset($aExtraParams['StartWithAdd']) && $aExtraParams['StartWithAdd']) {
            $oP->add_ready_script("AddObjects();");
        }
    }