Exemplo n.º 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();
    }
}
Exemplo n.º 2
0
 function DisplayBareProperties(WebPage $oPage, $bEditMode = false, $sPrefix = '', $aExtraParams = array())
 {
     $aFieldsMap = parent::DisplayBareProperties($oPage, $bEditMode, $sPrefix, $aExtraParams);
     if (!$bEditMode) {
         $sUrl = utils::GetAbsoluteUrlAppRoot() . 'webservices/export-v2.php?format=spreadsheet&login_mode=basic&query=' . $this->GetKey();
         $sOql = $this->Get('oql');
         $sMessage = null;
         try {
             $oSearch = DBObjectSearch::FromOQL($sOql);
             $aParameters = $oSearch->GetQueryParams();
             foreach ($aParameters as $sParam => $val) {
                 $sUrl .= '&arg_' . $sParam . '=["' . $sParam . '"]';
             }
             $oPage->p(Dict::S('UI:Query:UrlForExcel') . ':<br/><textarea cols="80" rows="3" READONLY>' . $sUrl . '</textarea>');
             if (count($aParameters) == 0) {
                 $oBlock = new DisplayBlock($oSearch, 'list');
                 $aExtraParams = array('table_id' => 'query_preview_' . $this->getKey());
                 $sBlockId = 'block_query_preview_' . $this->GetKey();
                 // make a unique id (edition occuring in the same DOM)
                 $oBlock->Display($oPage, $sBlockId, $aExtraParams);
             }
         } catch (OQLException $e) {
             $sMessage = '<div class="message message_error" style="padding-left: 30px;"><div style="padding: 10px;">' . Dict::Format('UI:RunQuery:Error', $e->getHtmlDesc()) . '</div></div>';
             $oPage->p($sMessage);
         }
     }
     return $aFieldsMap;
 }
Exemplo n.º 3
0
 function DisplayDetails(WebPage $oPage, $bEditMode = false)
 {
     // Object's details
     //$this->DisplayBareHeader($oPage, $bEditMode);
     $oPage->AddTabContainer(OBJECT_PROPERTIES_TAB);
     $oPage->SetCurrentTabContainer(OBJECT_PROPERTIES_TAB);
     $oPage->SetCurrentTab(Dict::S('UI:PropertiesTab'));
     $this->DisplayBareProperties($oPage, $bEditMode);
 }
Exemplo n.º 4
0
function MakeDictEntry($sKey, $sValueFromOldSystem, $sDefaultValue, &$bNotInDico)
{
    $sValue = Dict::S($sKey, 'x-no-nothing');
    if ($sValue == 'x-no-nothing') {
        $bNotInDico = true;
        $sValue = $sValueFromOldSystem;
        if (strlen($sValue) == 0) {
            $sValue = $sDefaultValue;
        }
    }
    return "\t'{$sKey}' => '" . str_replace("'", "\\'", $sValue) . "',\n";
}
 public function ComputeResults()
 {
     $this->m_iToDelete = 0;
     $this->m_iToUpdate = 0;
     foreach ($this->m_aToDelete as $sClass => $aToDelete) {
         foreach ($aToDelete as $iId => $aData) {
             $this->m_iToDelete++;
             if (isset($aData['issue'])) {
                 $this->m_bFoundStopper = true;
                 $this->m_bFoundManualOperation = true;
                 if (isset($aData['issue_security'])) {
                     $this->m_bFoundSecurityIssue = true;
                 }
             }
             if ($aData['mode'] == DEL_MANUAL) {
                 $this->m_aToDelete[$sClass][$iId]['issue'] = $sClass . '::' . $iId . ' ' . Dict::S('UI:Delete:MustBeDeletedManually');
                 $this->m_bFoundStopper = true;
                 $this->m_bFoundManualDelete = true;
             }
         }
     }
     // Getting and setting time limit are not symetric:
     // www.php.net/manual/fr/function.set-time-limit.php#72305
     $iPreviousTimeLimit = ini_get('max_execution_time');
     $iLoopTimeLimit = MetaModel::GetConfig()->Get('max_execution_time_per_loop');
     foreach ($this->m_aToUpdate as $sClass => $aToUpdate) {
         foreach ($aToUpdate as $iId => $aData) {
             set_time_limit($iLoopTimeLimit);
             $this->m_iToUpdate++;
             $oObject = $aData['to_reset'];
             $aExtKeyLabels = array();
             foreach ($aData['attributes'] as $sRemoteExtKey => $aRemoteAttDef) {
                 $oObject->Set($sRemoteExtKey, $aData['values'][$sRemoteExtKey]);
                 $aExtKeyLabels[] = $aRemoteAttDef->GetLabel();
             }
             $this->m_aToUpdate[$sClass][$iId]['attributes_list'] = implode(', ', $aExtKeyLabels);
             list($bRes, $aIssues, $bSecurityIssues) = $oObject->CheckToWrite();
             if (!$bRes) {
                 $this->m_aToUpdate[$sClass][$iId]['issue'] = implode(', ', $aIssues);
                 $this->m_bFoundStopper = true;
                 if ($bSecurityIssues) {
                     $this->m_aToUpdate[$sClass][$iId]['issue_security'] = true;
                     $this->m_bFoundSecurityIssue = true;
                 }
             }
         }
     }
     set_time_limit($iPreviousTimeLimit);
 }
 /**
  * Get the HTML fragment corresponding to the linkset editing widget
  * @param WebPage $oP The web page used for all the output
  * @param Hash $aArgs Extra context arguments
  * @return string The HTML fragment to be inserted into the page
  */
 public function Display(WebPage $oPage, $aArgs = array())
 {
     $sCode = $this->sAttCode . $this->sNameSuffix;
     $iWidgetIndex = self::$iWidgetIndex;
     $aPasswordValues = utils::ReadPostedParam("attr_{$sCode}", null, 'raw_data');
     $sPasswordValue = $aPasswordValues ? $aPasswordValues['value'] : '*****';
     $sConfirmPasswordValue = $aPasswordValues ? $aPasswordValues['confirm'] : '*****';
     $sChangedValue = $sPasswordValue != '*****' || $sConfirmPasswordValue != '*****' ? 1 : 0;
     $sHtmlValue = '';
     $sHtmlValue = '<input type="password" maxlength="255" name="attr_' . $sCode . '[value]" id="' . $this->iId . '" value="' . htmlentities($sPasswordValue, ENT_QUOTES, 'UTF-8') . '"/>&nbsp;<span class="form_validation" id="v_' . $this->iId . '"></span><br/>';
     $sHtmlValue .= '<input type="password" maxlength="255" id="' . $this->iId . '_confirm" value="' . htmlentities($sConfirmPasswordValue, ENT_QUOTES, 'UTF-8') . '" name="attr_' . $sCode . '[confirm]"/> ' . Dict::S('UI:PasswordConfirm') . ' <input id="' . $this->iId . '_reset" type="button" value="' . Dict::S('UI:Button:ResetPassword') . '" onClick="ResetPwd(\'' . $this->iId . '\');">';
     $sHtmlValue .= '<input type="hidden" id="' . $this->iId . '_changed" name="attr_' . $sCode . '[changed]" value="' . $sChangedValue . '"/>';
     $oPage->add_ready_script("\$('#{$this->iId}').bind('keyup change', function(evt) { return PasswordFieldChanged('{$this->iId}') } );");
     // Bind to a custom event: validate
     $oPage->add_ready_script("\$('#{$this->iId}').bind('keyup change validate', function(evt, sFormId) { return ValidatePasswordField('{$this->iId}', sFormId) } );");
     // Bind to a custom event: validate
     $oPage->add_ready_script("\$('#{$this->iId}_confirm').bind('keyup change', function(evt, sFormId) { return ValidatePasswordField('{$this->iId}', sFormId) } );");
     // Bind to a custom event: validate
     $oPage->add_ready_script("\$('#{$this->iId}').bind('update', function(evt, sFormId)\n\t\t\t{\n\t\t\t\tif (\$(this).attr('disabled'))\n\t\t\t\t{\n\t\t\t\t\t\$('#{$this->iId}_confirm').attr('disabled', 'disabled');\n\t\t\t\t\t\$('#{$this->iId}_changed').attr('disabled', 'disabled');\n\t\t\t\t\t\$('#{$this->iId}_reset').attr('disabled', 'disabled');\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t\$('#{$this->iId}_confirm').removeAttr('disabled');\n\t\t\t\t\t\$('#{$this->iId}_changed').removeAttr('disabled');\n\t\t\t\t\t\$('#{$this->iId}_reset').removeAttr('disabled');\n\t\t\t\t}\n\t\t\t}\n\t\t);");
     // Bind to a custom event: update to handle enabling/disabling
     return $sHtmlValue;
 }
Exemplo n.º 7
0
            $sConfig = str_replace("\r\n", "\n", file_get_contents($sConfigFile));
            $sOrginalConfig = $sConfig;
        }
        $sConfigEscaped = htmlentities($sConfig, ENT_QUOTES, 'UTF-8');
        $sOriginalConfigEscaped = htmlentities($sOrginalConfig, ENT_QUOTES, 'UTF-8');
        $oP->p(Dict::S('config-edit-intro'));
        $oP->add("<form method=\"POST\">");
        $oP->add("<input type=\"hidden\" name=\"operation\" value=\"save\">");
        $oP->add("<input type=\"submit\" value=\"" . Dict::S('config-apply') . "\"><button onclick=\"ResetConfig(); return false;\">" . Dict::S('config-cancel') . "</button>");
        $oP->add("<span class=\"current_line\">" . Dict::Format('config-current-line', "<span class=\"line_number\"></span>") . "</span>");
        $oP->add("<input type=\"hidden\" id=\"prev_config\" name=\"prev_config\" value=\"{$sOriginalConfigEscaped}\">");
        $oP->add("<textarea id =\"new_config\" name=\"new_config\" onkeyup=\"UpdateLineNumber();\" onmouseup=\"UpdateLineNumber();\">{$sConfigEscaped}</textarea>");
        $oP->add("<input type=\"submit\" value=\"" . Dict::S('config-apply') . "\"><button onclick=\"ResetConfig(); return false;\">" . Dict::S('config-cancel') . "</button>");
        $oP->add("<span class=\"current_line\">" . Dict::Format('config-current-line', "<span class=\"line_number\"></span>") . "</span>");
        $oP->add("</form>");
        $sConfirmCancel = addslashes(Dict::S('config-confirm-cancel'));
        $oP->add_script(<<<EOF
function UpdateLineNumber()
{
\tvar oTextArea = \$('#new_config')[0];
\t\$('.line_number').html(oTextArea.value.substr(0, oTextArea.selectionStart).split("\\n").length);
\t\$('.current_line').show();
}
function ResetConfig()
{
\tif (\$('#new_config').val() != \$('#prev_config').val())
\t{
\t\tif (confirm('{$sConfirmCancel}'))
\t\t{
\t\t\t\$('#new_config').val(\$('#prev_config').val());
\t\t}
 public function WizardFormButtons($iButtonFlags)
 {
     $aButtons = array();
     if ($iButtonFlags & BUTTON_CANCEL) {
         $aButtons[] = "<input id=\"btn_cancel\" type=\"button\" value=\"" . Dict::S('UI:Button:Cancel') . "\" onClick=\"GoHome();\">";
     }
     if ($iButtonFlags & BUTTON_BACK) {
         if (utils::ReadParam('step_back', 1) != 1) {
             $aButtons[] = "<input id=\"btn_back\" type=\"submit\" value=\"" . Dict::S('UI:Button:Back') . "\"  onClick=\"GoBack('{$this->m_sWizardId}');\">";
         }
     }
     if ($iButtonFlags & BUTTON_NEXT) {
         $aButtons[] = "<input id=\"btn_next\" type=\"submit\" value=\"" . Dict::S('UI:Button:Next') . "\">";
     }
     if ($iButtonFlags & BUTTON_FINISH) {
         $aButtons[] = "<input id=\"btn_finish\" type=\"submit\" value=\"" . Dict::S('UI:Button:Finish') . "\">";
     }
     $this->add('<div id="buttons">');
     $this->add(implode('', $aButtons));
     $this->add('</div>');
 }
    /**
     * Generates the javascript code handle the "watchdog" associated with the concurrent access locking mechanism
     * @param Webpage $oPage
     * @param string $sOwnershipToken
     */
    protected function GetOwnershipJSHandler($oPage, $sOwnershipToken)
    {
        $iInterval = max(MIN_WATCHDOG_INTERVAL, MetaModel::GetConfig()->Get('concurrent_lock_expiration_delay')) * 1000 / 2;
        // Minimum interval for the watchdog is MIN_WATCHDOG_INTERVAL
        $sJSClass = json_encode(get_class($this));
        $iKey = (int) $this->GetKey();
        $sJSToken = json_encode($sOwnershipToken);
        $sJSTitle = json_encode(Dict::S('UI:DisconnectedDlgTitle'));
        $sJSOk = json_encode(Dict::S('UI:Button:Ok'));
        $oPage->add_ready_script(<<<EOF
\t\twindow.setInterval(function() {
\t\t\tif (window.bInSubmit || window.bInCancel) return;
\t\t\t
\t\t\t\$.post(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php', {operation: 'extend_lock', obj_class: {$sJSClass}, obj_key: {$iKey}, token: {$sJSToken} }, function(data) {
\t\t\t\tif (!data.status)
\t\t\t\t{
\t\t\t\t\tif (\$('.lock_owned').length == 0)
\t\t\t\t\t{
\t\t\t\t\t\t\$('.ui-layout-content').prepend('<div class="header_message message_error lock_owned">'+data.message+'</div>');
\t\t\t\t\t\t\$('<div>'+data.popup_message+'</div>').dialog({title: {$sJSTitle}, modal: true, autoOpen: true, buttons:[ {text: {$sJSOk}, click: function() { \$(this).dialog('close'); } }], close: function() { \$(this).remove(); }});
\t\t\t\t\t}
\t\t\t\t\t\$('.wizContainer form button.action:not(.cancel)').attr('disabled', 'disabled');
\t\t\t\t}
\t\t\t\telse if ((data.operation == 'lost') || (data.operation == 'expired'))
\t\t\t\t{
\t\t\t\t\tif (\$('.lock_owned').length == 0)
\t\t\t\t\t{
\t\t\t\t\t\t\$('.ui-layout-content').prepend('<div class="header_message message_error lock_owned">'+data.message+'</div>');
\t\t\t\t\t\t\$('<div>'+data.popup_message+'</div>').dialog({title: {$sJSTitle}, modal: true, autoOpen: true, buttons:[ {text: {$sJSOk}, click: function() { \$(this).dialog('close'); } }], close: function() { \$(this).remove(); }});
\t\t\t\t\t}
\t\t\t\t\t\$('.wizContainer form button.action:not(.cancel)').attr('disabled', 'disabled');
\t\t\t\t}
\t\t\t}, 'json');
\t\t}, {$iInterval});
EOF
);
    }
 protected static function HandleOperations($operation)
 {
     $sMessage = '';
     // most of the operations never return, but some can return a message to be displayed
     if ($operation == 'logoff') {
         if (isset($_SESSION['login_mode'])) {
             $sLoginMode = $_SESSION['login_mode'];
         } else {
             $aAllowedLoginTypes = MetaModel::GetConfig()->GetAllowedLoginTypes();
             if (count($aAllowedLoginTypes) > 0) {
                 $sLoginMode = $aAllowedLoginTypes[0];
             } else {
                 $sLoginMode = 'form';
             }
         }
         self::ResetSession();
         $oPage = self::NewLoginWebPage();
         $oPage->DisplayLoginForm($sLoginMode, false);
         $oPage->output();
         exit;
     } else {
         if ($operation == 'forgot_pwd') {
             $oPage = self::NewLoginWebPage();
             $oPage->DisplayForgotPwdForm();
             $oPage->output();
             exit;
         } else {
             if ($operation == 'forgot_pwd_go') {
                 $oPage = self::NewLoginWebPage();
                 $oPage->ForgotPwdGo();
                 $oPage->output();
                 exit;
             } else {
                 if ($operation == 'reset_pwd') {
                     $oPage = self::NewLoginWebPage();
                     $oPage->DisplayResetPwdForm();
                     $oPage->output();
                     exit;
                 } else {
                     if ($operation == 'do_reset_pwd') {
                         $oPage = self::NewLoginWebPage();
                         $oPage->DoResetPassword();
                         $oPage->output();
                         exit;
                     } else {
                         if ($operation == 'change_pwd') {
                             $sAuthUser = $_SESSION['auth_user'];
                             UserRights::Login($sAuthUser);
                             // Set the user's language
                             $oPage = self::NewLoginWebPage();
                             $oPage->DisplayChangePwdForm();
                             $oPage->output();
                             exit;
                         }
                     }
                 }
             }
         }
     }
     if ($operation == 'do_change_pwd') {
         $sAuthUser = $_SESSION['auth_user'];
         UserRights::Login($sAuthUser);
         // Set the user's language
         $sOldPwd = utils::ReadPostedParam('old_pwd', '', false, 'raw_data');
         $sNewPwd = utils::ReadPostedParam('new_pwd', '', false, 'raw_data');
         if (UserRights::CanChangePassword() && (!UserRights::CheckCredentials($sAuthUser, $sOldPwd) || !UserRights::ChangePassword($sOldPwd, $sNewPwd))) {
             $oPage = self::NewLoginWebPage();
             $oPage->DisplayChangePwdForm(true);
             // old pwd was wrong
             $oPage->output();
             exit;
         }
         $sMessage = Dict::S('UI:Login:PasswordChanged');
     }
     return $sMessage;
 }
Exemplo n.º 11
0
function InteractiveShell($sExpression, $sQueryId, $sFormat, $sFileName, $sMode)
{
    if ($sMode == 'dialog') {
        $oP = new ajax_page('');
        $oP->add('<div id="interactive_export_dlg">');
        $sExportBtnLabel = json_encode(Dict::S('UI:Button:Export'));
        $sJSTitle = json_encode(htmlentities(utils::ReadParam('dialog_title', '', false, 'raw_data'), ENT_QUOTES, 'UTF-8'));
        $oP->add_ready_script(<<<EOF
\t\t\$('#interactive_export_dlg').dialog({
\t\t\tautoOpen: true,
\t\t\tmodal: true,
\t\t\twidth: '80%',
\t\t\ttitle: {$sJSTitle},
\t\t\tclose: function() { \$('#export-form').attr('data-state', 'cancelled'); \$(this).remove(); },
\t\t\tbuttons: [
\t\t\t\t{text: {$sExportBtnLabel}, id: 'export-dlg-submit', click: function() {} }
\t\t\t]
\t\t});
\t\t\t
\t\tsetTimeout(function() { \$('#interactive_export_dlg').dialog('option', { position: { my: "center", at: "center", of: window }}); \$('#export-btn').hide(); ExportInitButton('#export-dlg-submit'); }, 100);
EOF
);
    } else {
        $oP = new iTopWebPage('iTop Export');
    }
    if ($sExpression === null) {
        // No expression supplied, let's check if phrasebook entry is given
        if ($sQueryId !== null) {
            $oSearch = DBObjectSearch::FromOQL('SELECT QueryOQL WHERE id = :query_id', array('query_id' => $sQueryId));
            $oQueries = new DBObjectSet($oSearch);
            if ($oQueries->Count() > 0) {
                $oQuery = $oQueries->Fetch();
                $sExpression = $oQuery->Get('oql');
                $sFields = trim($oQuery->Get('fields'));
            } else {
                ReportErrorAndExit("Invalid query phrasebook identifier: '{$sQueryId}'");
            }
        } else {
            if (utils::IsModeCLI()) {
                Usage();
                ReportErrorAndExit("No expression or query phrasebook identifier supplied.");
            } else {
                // form to enter an OQL query or pick a query phrasebook identifier
                DisplayForm($oP, utils::GetAbsoluteUrlAppRoot() . 'webservices/export-v2.php', $sExpression, $sQueryId, $sFormat);
                $oP->output();
                exit;
            }
        }
    }
    if ($sFormat !== null) {
        $oExporter = BulkExport::FindExporter($sFormat);
        if ($oExporter === null) {
            $aSupportedFormats = BulkExport::FindSupportedFormats();
            ReportErrorAndExit("Invalid output format: '{$sFormat}'. The supported formats are: " . implode(', ', array_keys($aSupportedFormats)));
        } else {
            DisplayForm($oP, utils::GetAbsoluteUrlAppRoot() . 'webservices/export-v2.php', $sExpression, $sQueryId, $sFormat);
        }
    } else {
        DisplayForm($oP, utils::GetAbsoluteUrlAppRoot() . 'webservices/export-v2.php', $sExpression, $sQueryId, $sFormat);
    }
    if ($sMode == 'dialog') {
        $oP->add('</div>');
    }
    $oP->output();
}
Exemplo n.º 12
0
    public function DisplayAttachments($oObject, WebPage $oPage, $bEditMode = false)
    {
        // Exit here if the class is not allowed
        if (!$this->IsTargetObject($oObject)) {
            return;
        }
        $oSearch = DBObjectSearch::FromOQL("SELECT Attachment WHERE item_class = :class AND item_id = :item_id");
        $oSet = new DBObjectSet($oSearch, array(), array('class' => get_class($oObject), 'item_id' => $oObject->GetKey()));
        if ($this->GetAttachmentsPosition() == 'relations') {
            $sTitle = $oSet->Count() > 0 ? Dict::Format('Attachments:TabTitle_Count', $oSet->Count()) : Dict::S('Attachments:EmptyTabTitle');
            $oPage->SetCurrentTab($sTitle);
        }
        $oPage->add_style(<<<EOF
.attachment {
\tdisplay: inline-block;
\ttext-align:center;
\tfloat:left;
\tpadding:5px;\t
}
.attachment:hover {
\tbackground-color: #e0e0e0;
}
.attachment img {
\tborder: 0;
}
.attachment a {
\ttext-decoration: none;
\tcolor: #1C94C4;
}
.btn_hidden {
\tdisplay: none;
}
.drag_in {
\t-webkit-box-shadow:inset 0 0 10px 2px #1C94C4;
\tbox-shadow:inset 0 0 10px 2px #1C94C4;
}
#history .attachment-history-added {
\tpadding: 0;
\tfloat: none;
}
EOF
);
        $oPage->add('<fieldset>');
        $oPage->add('<legend>' . Dict::S('Attachments:FieldsetTitle') . '</legend>');
        if ($bEditMode) {
            $sIsDeleteEnabled = $this->m_bDeleteEnabled ? 'true' : 'false';
            $iTransactionId = $oPage->GetTransactionId();
            $sClass = get_class($oObject);
            $sTempId = session_id() . '_' . $iTransactionId;
            $sDeleteBtn = Dict::S('Attachments:DeleteBtn');
            $oPage->add_script(<<<EOF
\tfunction RemoveAttachment(att_id)
\t{
\t\t\$('#attachment_'+att_id).attr('name', 'removed_attachments[]');
\t\t\$('#display_attachment_'+att_id).hide();
\t\t\$('#attachment_plugin').trigger('remove_attachment', [att_id]);
\t\treturn false; // Do not submit the form !
\t}
EOF
);
            $oPage->add('<span id="attachments">');
            while ($oAttachment = $oSet->Fetch()) {
                $iAttId = $oAttachment->GetKey();
                $oDoc = $oAttachment->Get('contents');
                $sFileName = $oDoc->GetFileName();
                $sIcon = utils::GetAbsoluteUrlAppRoot() . AttachmentPlugIn::GetFileIcon($sFileName);
                $sPreview = $oDoc->IsPreviewAvailable() ? 'true' : 'false';
                $sDownloadLink = utils::GetAbsoluteUrlAppRoot() . 'pages/ajax.render.php?operation=download_document&class=Attachment&id=' . $iAttId . '&field=contents';
                $oPage->add('<div class="attachment" id="display_attachment_' . $iAttId . '"><a data-preview="' . $sPreview . '" href="' . $sDownloadLink . '"><img src="' . $sIcon . '"><br/>' . $sFileName . '<input id="attachment_' . $iAttId . '" type="hidden" name="attachments[]" value="' . $iAttId . '"/></a><br/>&nbsp;<input id="btn_remove_' . $iAttId . '" type="button" class="btn_hidden" value="Delete" onClick="RemoveAttachment(' . $iAttId . ');"/>&nbsp;</div>');
            }
            // Suggested attachments are listed here but treated as temporary
            $aDefault = utils::ReadParam('default', array(), false, 'raw_data');
            if (array_key_exists('suggested_attachments', $aDefault)) {
                $sSuggestedAttachements = $aDefault['suggested_attachments'];
                if (is_array($sSuggestedAttachements)) {
                    $sSuggestedAttachements = implode(',', $sSuggestedAttachements);
                }
                $oSearch = DBObjectSearch::FromOQL("SELECT Attachment WHERE id IN({$sSuggestedAttachements})");
                $oSet = new DBObjectSet($oSearch, array());
                if ($oSet->Count() > 0) {
                    while ($oAttachment = $oSet->Fetch()) {
                        // Mark the attachments as temporary attachments for the current object/form
                        $oAttachment->Set('temp_id', $sTempId);
                        $oAttachment->DBUpdate();
                        // Display them
                        $iAttId = $oAttachment->GetKey();
                        $oDoc = $oAttachment->Get('contents');
                        $sFileName = $oDoc->GetFileName();
                        $sIcon = utils::GetAbsoluteUrlAppRoot() . AttachmentPlugIn::GetFileIcon($sFileName);
                        $sDownloadLink = utils::GetAbsoluteUrlAppRoot() . 'pages/ajax.render.php?operation=download_document&class=Attachment&id=' . $iAttId . '&field=contents';
                        $sPreview = $oDoc->IsPreviewAvailable() ? 'true' : 'false';
                        $oPage->add('<div class="attachment" id="display_attachment_' . $iAttId . '"><a data-preview="' . $sPreview . '" href="' . $sDownloadLink . '"><img src="' . $sIcon . '"><br/>' . $sFileName . '<input id="attachment_' . $iAttId . '" type="hidden" name="attachments[]" value="' . $iAttId . '"/></a><br/>&nbsp;<input id="btn_remove_' . $iAttId . '" type="button" class="btn_hidden" value="Delete" onClick="RemoveAttachment(' . $iAttId . ');"/>&nbsp;</div>');
                        $oPage->add_ready_script("\$('#attachment_plugin').trigger('add_attachment', [{$iAttId}, '" . addslashes($sFileName) . "']);");
                    }
                }
            }
            $oPage->add('</span>');
            $oPage->add('<div style="clear:both"></div>');
            $sMaxUpload = $this->GetMaxUpload();
            $oPage->p(Dict::S('Attachments:AddAttachment') . '<input type="file" name="file" id="file"><span style="display:none;" id="attachment_loading">&nbsp;<img src="../images/indicator.gif"></span> ' . $sMaxUpload);
            $oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot() . 'js/jquery.iframe-transport.js');
            $oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot() . 'js/jquery.fileupload.js');
            $oPage->add_ready_script(<<<EOF
    \$('#file').fileupload({
\t\turl: GetAbsoluteUrlModulesRoot()+'itop-attachments/ajax.attachment.php',
\t\tformData: { operation: 'add', temp_id: '{$sTempId}', obj_class: '{$sClass}' },
        dataType: 'json',
\t\tpasteZone: null, // Don't accept files via Chrome's copy/paste
        done: function (e, data) {
\t\t\tif(typeof(data.result.error) != 'undefined')
\t\t\t{
\t\t\t\tif(data.result.error != '')
\t\t\t\t{
\t\t\t\t\talert(data.result.error);
\t\t\t\t}
\t\t\t\telse
\t\t\t\t{
\t\t\t\t\tvar sDownloadLink = GetAbsoluteUrlAppRoot()+'pages/ajax.render.php?operation=download_document&class=Attachment&id='+data.result.att_id+'&field=contents';
\t\t\t\t\t\$('#attachments').append('<div class="attachment" id="display_attachment_'+data.result.att_id+'"><a data-preview="'+data.result.preview+'" href="'+sDownloadLink+'"><img src="'+data.result.icon+'"><br/>'+data.result.msg+'<input id="attachment_'+data.result.att_id+'" type="hidden" name="attachments[]" value="'+data.result.att_id+'"/></a><br/><input type="button" class="btn_hidden" value="{$sDeleteBtn}" onClick="RemoveAttachment('+data.result.att_id+');"/></div>');
\t\t\t\t\tif({$sIsDeleteEnabled})
\t\t\t\t\t{
\t\t\t\t\t\t\$('#display_attachment_'+data.result.att_id).hover( function() { \$(this).children(':button').toggleClass('btn_hidden'); } );
\t\t\t\t\t}
\t\t\t\t\t\$('#attachment_plugin').trigger('add_attachment', [data.result.att_id, data.result.msg]);
\t\t\t\t}
\t\t\t}
        },
        start: function() {
        \t\$('#attachment_loading').show();
\t\t},
        stop: function() {
        \t\$('#attachment_loading').hide();
\t\t}
    });

\t\$(document).bind('dragover', function (e) {
\t\tvar bFiles = false;
\t\tif (e.dataTransfer && e.dataTransfer.types)
\t\t{
\t\t\tfor (var i = 0; i < e.dataTransfer.types.length; i++)
\t\t\t{
\t\t\t\tif (e.dataTransfer.types[i] == "application/x-moz-nativeimage")
\t\t\t\t{
\t\t\t\t\tbFiles = false; // mozilla contains "Files" in the types list when dragging images inside the page, but it also contains "application/x-moz-nativeimage" before
\t\t\t\t\tbreak;
\t\t\t\t}
\t\t\t\t
\t\t\t\tif (e.dataTransfer.types[i] == "Files")
\t\t\t\t{
\t\t\t\t\tbFiles = true;
\t\t\t\t\tbreak;
\t\t\t\t}
\t\t\t}
\t\t}
\t
\t\tif (!bFiles) return; // Not dragging files
\t\t
\t\tvar dropZone = \$('#file').closest('fieldset');
\t\tif (!dropZone.is(':visible'))
\t\t{
\t\t\t// Hidden, but inside an inactive tab? Higlight the tab
\t\t\tvar sTabId = dropZone.closest('.ui-tabs-panel').attr('aria-labelledby');
\t\t\tdropZone = \$('#'+sTabId).closest('li');
\t\t}
\t    timeout = window.dropZoneTimeout;
\t    if (!timeout) {
\t        dropZone.addClass('drag_in');
\t    } else {
\t        clearTimeout(timeout);
\t    }
\t    window.dropZoneTimeout = setTimeout(function () {
\t        window.dropZoneTimeout = null;
\t        dropZone.removeClass('drag_in');
\t    }, 300);
\t});   
EOF
);
            $oPage->p('<span style="display:none;" id="attachment_loading">Loading, please wait...</span>');
            $oPage->p('<input type="hidden" id="attachment_plugin" name="attachment_plugin"/>');
            if ($this->m_bDeleteEnabled) {
                $oPage->add_ready_script('$(".attachment").hover( function() {$(this).children(":button").toggleClass("btn_hidden"); } );');
            }
        } else {
            $oPage->add('<span id="attachments">');
            if ($oSet->Count() == 0) {
                $oPage->add(Dict::S('Attachments:NoAttachment'));
            } else {
                while ($oAttachment = $oSet->Fetch()) {
                    $iAttId = $oAttachment->GetKey();
                    $oDoc = $oAttachment->Get('contents');
                    $sFileName = $oDoc->GetFileName();
                    $sIcon = utils::GetAbsoluteUrlAppRoot() . AttachmentPlugIn::GetFileIcon($sFileName);
                    $sPreview = $oDoc->IsPreviewAvailable() ? 'true' : 'false';
                    $sDownloadLink = utils::GetAbsoluteUrlAppRoot() . 'pages/ajax.render.php?operation=download_document&class=Attachment&id=' . $iAttId . '&field=contents';
                    $oPage->add('<div class="attachment" id="attachment_' . $iAttId . '"><a data-preview="' . $sPreview . '" href="' . $sDownloadLink . '"><img src="' . $sIcon . '"><br/>' . $sFileName . '</a><input type="hidden" name="attachments[]" value="' . $iAttId . '"/><br/>&nbsp;&nbsp;</div>');
                }
            }
            $oPage->add('</span>');
        }
        $oPage->add('</fieldset>');
        $sPreviewNotAvailable = addslashes(Dict::S('Attachments:PreviewNotAvailable'));
        $iMaxWidth = MetaModel::GetModuleSetting('itop-attachments', 'preview_max_width', 290);
        $oPage->add_ready_script("\$(document).tooltip({ items: '.attachment a',  position: { my: 'left top', at: 'right top', using: function( position, feedback ) { \$( this ).css( position ); }}, content: function() { if (\$(this).attr('data-preview') == 'true') { return('<img style=\"max-width:{$iMaxWidth}px\" src=\"'+\$(this).attr('href')+'\"></img>');} else { return '{$sPreviewNotAvailable}'; }}});");
    }
 /**
  * Do the synchronization job #1: Obsolete replica "untouched" for some time
  * @param integer $iMaxReplica Limit the number of replicas to process 
  * @param integer $iCurrPos Current position where to resume the processing 
  * @return true if the process must be continued
  */
 protected function DoJob1($iMaxReplica = null, $iCurrPos = -1)
 {
     $sLimitDate = $this->m_oLastFullLoadStartDate->Format('Y-m-d H:i:s');
     // Get all the replicas that were not seen in the last import and mark them as obsolete
     $sDeletePolicy = $this->m_oDataSource->Get('delete_policy');
     if ($sDeletePolicy != 'ignore') {
         $sSelectToObsolete = "SELECT SynchroReplica WHERE id > :curr_pos AND sync_source_id = :source_id AND status IN ('new', 'synchronized', 'modified', 'orphan') AND status_last_seen < :last_import";
         $oSetScope = new DBObjectSet(DBObjectSearch::FromOQL($sSelectToObsolete), array(), array('source_id' => $this->m_oDataSource->GetKey(), 'last_import' => $sLimitDate, 'curr_pos' => $iCurrPos));
         $iCountScope = $oSetScope->Count();
         if ($this->m_iCountAllReplicas > 10 && $this->m_iCountAllReplicas == $iCountScope && MetaModel::GetConfig()->Get('synchro_prevent_delete_all')) {
             throw new SynchroExceptionNotStarted(Dict::S('Core:SyncTooManyMissingReplicas'));
         }
         if ($iMaxReplica) {
             // Consider a given subset, starting from replica iCurrPos, limited to the count of iMaxReplica
             // The replica have to be ordered by id
             $oSetToProcess = new DBObjectSet(DBObjectSearch::FromOQL($sSelectToObsolete), array('id' => true), array('source_id' => $this->m_oDataSource->GetKey(), 'last_import' => $sLimitDate, 'curr_pos' => $iCurrPos));
             $oSetToProcess->SetLimit($iMaxReplica);
         } else {
             $oSetToProcess = $oSetScope;
         }
         $iLastReplicaProcessed = -1;
         while ($oReplica = $oSetToProcess->Fetch()) {
             $iLastReplicaProcessed = $oReplica->GetKey();
             switch ($sDeletePolicy) {
                 case 'update':
                 case 'update_then_delete':
                     $this->m_oStatLog->AddTrace("Destination object to be updated", $oReplica);
                     $aToUpdate = array();
                     $aToUpdateSpec = explode(';', $this->m_oDataSource->Get('delete_policy_update'));
                     //ex: 'status:obsolete;description:stopped',
                     foreach ($aToUpdateSpec as $sUpdateSpec) {
                         $aUpdateSpec = explode(':', $sUpdateSpec);
                         if (count($aUpdateSpec) == 2) {
                             $sAttCode = $aUpdateSpec[0];
                             $sValue = $aUpdateSpec[1];
                             $aToUpdate[$sAttCode] = $sValue;
                         }
                     }
                     $oReplica->Set('status_last_error', '');
                     if ($oReplica->Get('dest_id') == '') {
                         $oReplica->Set('status', 'obsolete');
                         $this->m_oStatLog->Inc('stats_nb_replica_disappeared_no_action');
                     } else {
                         $oReplica->UpdateDestObject($aToUpdate, $this->m_oChange, $this->m_oStatLog);
                         if ($oReplica->Get('status_last_error') == '') {
                             // Change the status of the replica IIF
                             $oReplica->Set('status', 'obsolete');
                         }
                     }
                     $oReplica->DBUpdateTracked($this->m_oChange);
                     break;
                 case 'delete':
                 default:
                     $this->m_oStatLog->AddTrace("Destination object to be DELETED", $oReplica);
                     $oReplica->DeleteDestObject($this->m_oChange, $this->m_oStatLog);
             }
         }
         if ($iMaxReplica) {
             if ($iMaxReplica < $iCountScope) {
                 // Continue with this job!
                 $this->m_oStatLog->Set('status_curr_pos', $iLastReplicaProcessed);
                 return true;
             }
         }
     }
     // if ($sDeletePolicy != 'ignore'
     //Count "seen" objects
     $sSelectSeen = "SELECT SynchroReplica WHERE sync_source_id = :source_id AND status IN ('new', 'synchronized', 'modified', 'orphan') AND status_last_seen >= :last_import";
     $oSetSeen = new DBObjectSet(DBObjectSearch::FromOQL($sSelectSeen), array(), array('source_id' => $this->m_oDataSource->GetKey(), 'last_import' => $sLimitDate));
     $this->m_oStatLog->Set('stats_nb_replica_seen', $oSetSeen->Count());
     // Job complete!
     $this->m_oStatLog->Set('status_curr_job', 2);
     $this->m_oStatLog->Set('status_curr_pos', -1);
     return false;
 }
 function DisplayBareRelations(WebPage $oPage, $bEditMode = false)
 {
     parent::DisplayBareRelations($oPage, $bEditMode);
     if (!$bEditMode) {
         $oPage->SetCurrentTab(Dict::S('Class:Subnet/Tab:IPUsage'));
         $bit_ip = ip2long($this->Get('ip'));
         $bit_mask = ip2long($this->Get('ip_mask'));
         $iIPMin = sprintf('%u', $bit_ip & $bit_mask | 1);
         // exclude the first one: identifies the subnet itself
         $iIPMax = sprintf('%u', ($bit_ip | ~$bit_mask) & 0xfffffffe);
         // exclude the last one : broadcast address
         $sIPMin = long2ip($iIPMin);
         $sIPMax = long2ip($iIPMax);
         $oPage->p(Dict::Format('Class:Subnet/Tab:IPUsage-explain', $sIPMin, $sIPMax));
         $oIfFilter = DBObjectSearch::FromOQL("SELECT IPInterface AS if WHERE INET_ATON(if.ipaddress) >= INET_ATON('{$sIPMin}') AND INET_ATON(if.ipaddress) <= INET_ATON('{$sIPMax}')");
         $oIfSet = new CMDBObjectSet($oIfFilter);
         $oBlock = new DisplayBlock($oIfFilter, 'list', false);
         $oBlock->Display($oPage, 'nwif', array('menu' => false));
         $iCountUsed = $oIfSet->Count();
         $iCountRange = $iIPMax - $iIPMin;
         // On 32-bit systems the substraction will be computed using floats for values greater than PHP_MAX_INT;
         $iFreeCount = $iCountRange - $iCountUsed;
         $oPage->SetCurrentTab(Dict::S('Class:Subnet/Tab:FreeIPs'));
         $oPage->p(Dict::Format('Class:Subnet/Tab:FreeIPs-count', $iFreeCount));
         $oPage->p(Dict::S('Class:Subnet/Tab:FreeIPs-explain'));
         $aUsedIPs = $oIfSet->GetColumnAsArray('ipaddress', false);
         $iAnIP = $iIPMin;
         $iFound = 0;
         while ($iFound < min($iFreeCount, 10) && $iAnIP <= $iIPMax) {
             $sAnIP = long2ip($iAnIP);
             if (!in_array($sAnIP, $aUsedIPs)) {
                 $iFound++;
                 $oPage->p($sAnIP);
             } else {
             }
             $iAnIP++;
         }
     }
 }
 public function GetDescription($sDefault = null)
 {
     $sLabel = parent::GetDescription('');
     if (strlen($sLabel) == 0) {
         $sKeyAttCode = $this->Get("extkey_attcode");
         if ($sKeyAttCode == 'id') {
             return Dict::S('Core:FriendlyName-Description');
         } else {
             $oExtKeyAttDef = MetaModel::GetAttributeDef($this->GetHostClass(), $sKeyAttCode);
             $sLabel = $oExtKeyAttDef->GetDescription('');
         }
     }
     return $sLabel;
 }
Exemplo n.º 16
0
\t\t\t\t{
\t\t\t\t\tfTotal = fTotal + oTimeStatistics[sClass];
\t\t\t\t\tfRounded = Math.round(oTimeStatistics[sClass] * 1000) / 1000;
\t\t\t\t\tsRes += '<tr><td>' + sClass + '</td><td>' + fRounded + '</td></tr>';
\t\t\t\t}
\t\t\t\t
\t\t\t\tfRoundedTotal = Math.round(fTotal * 1000) / 1000;
\t\t\t\tsRes += '<tr><td><b>Total</b></td><td><b>' + fRoundedTotal + '</b></td></tr>';
\t\t\t\tsRes += '</tbody>';
\t\t\t\tsRes += '</table>';
\t\t\t\t\$('#full_text_results').append(sRes);
EOF
);
                }
                if ($iCount == 0) {
                    $sFullTextSummary = addslashes(Dict::S('UI:Search:NoObjectFound'));
                    $oPage->add_ready_script("\$('#full_text_results').append('<div id=\"no_object_found\">{$sFullTextSummary}</div>');");
                }
            }
            break;
        case 'full_text_search_enlarge':
            $sFullText = trim(utils::ReadParam('text', '', false, 'raw_data'));
            $sClass = trim(utils::ReadParam('class', ''));
            $iTune = utils::ReadParam('tune', 0);
            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 <word1> AND <word2> AND <word3>
                $aFullTextNeedles = explode(' ', $sFullText);
            }
Exemplo n.º 17
0
 public static function RenderOQLSearch($sOql, $sTitle, $sUsageId, $bSearchPane, $bSearchOpen, WebPage $oPage, $aExtraParams = array())
 {
     $sUsageId = utils::GetSafeId($sUsageId);
     $oSearch = DBObjectSearch::FromOQL($sOql);
     $sIcon = MetaModel::GetClassIcon($oSearch->GetClass());
     if ($bSearchPane) {
         $aParams = array_merge(array('open' => $bSearchOpen, 'table_id' => $sUsageId), $aExtraParams);
         $oBlock = new DisplayBlock($oSearch, 'search', false, $aParams);
         $oBlock->Display($oPage, 0);
     }
     $oPage->add("<p class=\"page-header\">{$sIcon} " . Dict::S($sTitle) . "</p>");
     $aParams = array_merge(array('table_id' => $sUsageId), $aExtraParams);
     $oBlock = new DisplayBlock($oSearch, 'list', false, $aParams);
     $oBlock->Display($oPage, $sUsageId);
 }
Exemplo n.º 18
0
 /**
  * Compute the order of the fields & pages in the wizard
  * @param $oPage iTopWebPage The current page (used to display error messages) 
  * @param $sClass string Name of the class
  * @param $sStateCode string Code of the target state of the object
  * @return hash Two dimensional array: each element represents the list of fields for a given page   
  */
 protected function ComputeWizardStructure()
 {
     $aWizardSteps = array('mandatory' => array(), 'optional' => array());
     $aFieldsDone = array();
     // Store all the fields that are already covered by a previous step of the wizard
     $aStates = MetaModel::EnumStates($this->m_sClass);
     $sStateAttCode = MetaModel::GetStateAttributeCode($this->m_sClass);
     $aMandatoryAttributes = array();
     // Some attributes are always mandatory independently of the state machine (if any)
     foreach (MetaModel::GetAttributesList($this->m_sClass) as $sAttCode) {
         $oAttDef = MetaModel::GetAttributeDef($this->m_sClass, $sAttCode);
         if (!$oAttDef->IsExternalField() && !$oAttDef->IsNullAllowed() && $oAttDef->IsWritable() && $sAttCode != $sStateAttCode) {
             $aMandatoryAttributes[$sAttCode] = OPT_ATT_MANDATORY;
         }
     }
     // Now check the attributes that are mandatory in the specified state
     if (!empty($this->m_sTargetState) && count($aStates[$this->m_sTargetState]['attribute_list']) > 0) {
         // Check all the fields that *must* be included in the wizard for this
         // particular target state
         $aFields = array();
         foreach ($aStates[$this->m_sTargetState]['attribute_list'] as $sAttCode => $iOptions) {
             if (isset($aMandatoryAttributes[$sAttCode]) && $aMandatoryAttributes[$sAttCode] & (OPT_ATT_MANDATORY | OPT_ATT_MUSTCHANGE | OPT_ATT_MUSTPROMPT)) {
                 $aMandatoryAttributes[$sAttCode] |= $iOptions;
             } else {
                 $aMandatoryAttributes[$sAttCode] = $iOptions;
             }
         }
     }
     // Check all the fields that *must* be included in the wizard
     // i.e. all mandatory, must-change or must-prompt fields that are
     // not also read-only or hidden.
     // Some fields may be required (null not allowed) from the database
     // perspective, but hidden or read-only from the user interface perspective
     $aFields = array();
     foreach ($aMandatoryAttributes as $sAttCode => $iOptions) {
         if ($iOptions & (OPT_ATT_MANDATORY | OPT_ATT_MUSTCHANGE | OPT_ATT_MUSTPROMPT) && !($iOptions & (OPT_ATT_READONLY | OPT_ATT_HIDDEN))) {
             $oAttDef = MetaModel::GetAttributeDef($this->m_sClass, $sAttCode);
             $aPrerequisites = $oAttDef->GetPrerequisiteAttributes();
             $aFields[$sAttCode] = array();
             foreach ($aPrerequisites as $sCode) {
                 $aFields[$sAttCode][$sCode] = '';
             }
         }
     }
     // Now use the dependencies between the fields to order them
     // Start from the order of the 'details'
     $aList = MetaModel::FlattenZlist(MetaModel::GetZListItems($this->m_sClass, 'details'));
     $index = 0;
     $aOrder = array();
     foreach ($aFields as $sAttCode => $void) {
         $aOrder[$sAttCode] = 999;
         // At the end of the list...
     }
     foreach ($aList as $sAttCode) {
         if (array_key_exists($sAttCode, $aFields)) {
             $aOrder[$sAttCode] = $index;
         }
         $index++;
     }
     foreach ($aFields as $sAttCode => $aDependencies) {
         // All fields with no remaining dependencies can be entered at this
         // step of the wizard
         if (count($aDependencies) > 0) {
             $iMaxPos = 0;
             // Remove this field from the dependencies of the other fields
             foreach ($aDependencies as $sDependentAttCode => $void) {
                 // position the current field after the ones it depends on
                 $iMaxPos = max($iMaxPos, 1 + $aOrder[$sDependentAttCode]);
             }
         }
     }
     asort($aOrder);
     $aCurrentStep = array();
     foreach ($aOrder as $sAttCode => $rank) {
         $aCurrentStep[] = $sAttCode;
         $aFieldsDone[$sAttCode] = '';
     }
     $aWizardSteps['mandatory'][] = $aCurrentStep;
     // Now computes the steps to fill the optional fields
     $aFields = array();
     // reset
     foreach (MetaModel::ListAttributeDefs($this->m_sClass) as $sAttCode => $oAttDef) {
         $iOptions = isset($aStates[$this->m_sTargetState]['attribute_list'][$sAttCode]) ? $aStates[$this->m_sTargetState]['attribute_list'][$sAttCode] : 0;
         if ($sStateAttCode != $sAttCode && !$oAttDef->IsExternalField() && ($iOptions & (OPT_ATT_HIDDEN | OPT_ATT_READONLY)) == 0 && !isset($aFieldsDone[$sAttCode])) {
             // 'State', external fields, read-only and hidden fields
             // and fields that are already listed in the wizard
             // are removed from the 'optional' part of the wizard
             $oAttDef = MetaModel::GetAttributeDef($this->m_sClass, $sAttCode);
             $aPrerequisites = $oAttDef->GetPrerequisiteAttributes();
             $aFields[$sAttCode] = array();
             foreach ($aPrerequisites as $sCode) {
                 if (!isset($aFieldsDone[$sCode])) {
                     // retain only the dependencies that were not covered
                     // in the 'mandatory' part of the wizard
                     $aFields[$sAttCode][$sCode] = '';
                 }
             }
         }
     }
     // Now use the dependencies between the fields to order them
     while (count($aFields) > 0) {
         $aCurrentStep = array();
         foreach ($aFields as $sAttCode => $aDependencies) {
             // All fields with no remaining dependencies can be entered at this
             // step of the wizard
             if (count($aDependencies) == 0) {
                 $aCurrentStep[] = $sAttCode;
                 $aFieldsDone[$sAttCode] = '';
                 unset($aFields[$sAttCode]);
                 // Remove this field from the dependencies of the other fields
                 foreach ($aFields as $sUpdatedCode => $aDummy) {
                     // remove the dependency
                     unset($aFields[$sUpdatedCode][$sAttCode]);
                 }
             }
         }
         if (count($aCurrentStep) == 0) {
             // This step of the wizard would contain NO field !
             $this->m_oPage->add(Dict::S('UI:Error:WizardCircularReferenceInDependencies'));
             print_r($aFields);
             break;
         }
         $aWizardSteps['optional'][] = $aCurrentStep;
     }
     return $aWizardSteps;
 }
 public function DictString($sStringCode, $sDefault = null, $bUserLanguageOnly = false)
 {
     return Dict::S($sStringCode, $sDefault, $bUserLanguageOnly);
 }
Exemplo n.º 20
0
/**
 * Helper function to build the mapping drop-down list for a field
 * Spec: Possible choices are "writable" fields in this class plus external fields that are listed as reconciliation keys
 *       for any class pointed to by an external key in the current class.
 *       If not in advanced mode, all "id" fields (id and external keys) must be mapped to ":none:" (i.e -- ignore this field --)
 *       External fields that do not correspond to a reconciliation key must be mapped to ":none:"
 *       Otherwise, if a field equals either the 'code' or the 'label' (translated) of a field, then it's mapped automatically
 * @param string $sClassName Name of the class used for the mapping
 * @param string $sFieldName Name of the field, as it comes from the data file (header line)
 * @param integer $iFieldIndex Number of the field in the sequence
 * @param bool $bAdvancedMode Whether or not advanced mode was chosen
 * @param string $sDefaultChoice If set, this will be the item selected by default
 * @return string The HTML code corresponding to the drop-down list for this field
 */
function GetMappingForField($sClassName, $sFieldName, $iFieldIndex, $bAdvancedMode, $sDefaultChoice)
{
    $aChoices = array('' => Dict::S('UI:CSVImport:MappingSelectOne'));
    $aChoices[':none:'] = Dict::S('UI:CSVImport:MappingNotApplicable');
    $sFieldCode = '';
    // Code of the attribute, if there is a match
    $aMatches = array();
    if (preg_match('/^(.+)\\*$/', $sFieldName, $aMatches)) {
        // Remove any trailing "star" character.
        // A star character at the end can be used to indicate a mandatory field
        $sFieldName = $aMatches[1];
    } else {
        if (preg_match('/^(.+)\\*->(.+)$/', $sFieldName, $aMatches)) {
            // Remove any trailing "star" character before the arrow (->)
            // A star character at the end can be used to indicate a mandatory field
            $sFieldName = $aMatches[1] . '->' . $aMatches[2];
        }
    }
    if ($sFieldName == 'id') {
        $sFieldCode = 'id';
    }
    if ($bAdvancedMode) {
        $aChoices['id'] = Dict::S('UI:CSVImport:idField');
    }
    foreach (MetaModel::ListAttributeDefs($sClassName) as $sAttCode => $oAttDef) {
        $sStar = '';
        if ($oAttDef->IsExternalKey()) {
            if ($sFieldName == $oAttDef->GetLabel() || $sFieldName == $sAttCode) {
                $sFieldCode = $sAttCode;
            }
            if ($bAdvancedMode) {
                $aChoices[$sAttCode] = $oAttDef->GetLabel();
            }
            $oExtKeyAttDef = MetaModel::GetAttributeDef($sClassName, $oAttDef->GetKeyAttCode());
            if (!$oExtKeyAttDef->IsNullAllowed()) {
                $sStar = '*';
            }
            // Get fields of the external class that are considered as reconciliation keys
            $sTargetClass = $oAttDef->GetTargetClass();
            foreach (MetaModel::ListAttributeDefs($sTargetClass) as $sTargetAttCode => $oTargetAttDef) {
                if (MetaModel::IsReconcKey($sTargetClass, $sTargetAttCode)) {
                    $bExtKey = $oTargetAttDef->IsExternalKey();
                    $sSuffix = '';
                    if ($bExtKey) {
                        $sSuffix = '->id';
                    }
                    if ($bAdvancedMode || !$bExtKey) {
                        // When not in advanced mode do not allow to use reconciliation keys (on external keys) if they are themselves external keys !
                        $aChoices[$sAttCode . '->' . $sTargetAttCode] = MetaModel::GetLabel($sClassName, $sAttCode . '->' . $sTargetAttCode, true);
                        if (strcasecmp($sFieldName, $oAttDef->GetLabel() . '->' . $oTargetAttDef->GetLabel() . $sSuffix) == 0 || strcasecmp($sFieldName, $sAttCode . '->' . $sTargetAttCode . $sSuffix) == 0) {
                            $sFieldCode = $sAttCode . '->' . $sTargetAttCode;
                        }
                    }
                }
            }
        } else {
            if ($oAttDef->IsWritable() && (!$oAttDef->IsLinkset() || $bAdvancedMode && $oAttDef->IsIndirect())) {
                $aChoices[$sAttCode] = MetaModel::GetLabel($sClassName, $sAttCode, true);
                if ($sFieldName == $oAttDef->GetLabel() || $sFieldName == $sAttCode) {
                    $sFieldCode = $sAttCode;
                }
            }
        }
    }
    asort($aChoices);
    $sHtml = "<select id=\"mapping_{$iFieldIndex}\" name=\"field[{$iFieldIndex}]\">\n";
    $bIsIdField = IsIdField($sClassName, $sFieldCode);
    foreach ($aChoices as $sAttCode => $sLabel) {
        $sSelected = '';
        if ($bIsIdField && !$bAdvancedMode) {
            if ($sAttCode == ':none:') {
                $sSelected = ' selected';
            }
        } else {
            if (empty($sFieldCode) && strpos($sFieldName, '->') !== false) {
                if ($sAttCode == ':none:') {
                    $sSelected = ' selected';
                }
            } else {
                if (is_null($sDefaultChoice) && $sFieldCode == $sAttCode) {
                    $sSelected = ' selected';
                } else {
                    if (!is_null($sDefaultChoice) && $sDefaultChoice == $sAttCode) {
                        $sSelected = ' selected';
                    }
                }
            }
        }
        $sHtml .= "<option value=\"{$sAttCode}\"{$sSelected}>{$sLabel}</option>\n";
    }
    $sHtml .= "</select>\n";
    return $sHtml;
}
Exemplo n.º 21
0
    public function DisplayAttachments($oObject, WebPage $oPage, $bEditMode = false)
    {
        // Exit here if the class is not allowed
        if (!$this->IsTargetObject($oObject)) {
            return;
        }
        $oSearch = DBObjectSearch::FromOQL("SELECT Attachment WHERE item_class = :class AND item_id = :item_id");
        $oSet = new DBObjectSet($oSearch, array(), array('class' => get_class($oObject), 'item_id' => $oObject->GetKey()));
        if ($this->GetAttachmentsPosition() == 'relations') {
            $sTitle = $oSet->Count() > 0 ? Dict::Format('Attachments:TabTitle_Count', $oSet->Count()) : Dict::S('Attachments:EmptyTabTitle');
            $oPage->SetCurrentTab($sTitle);
        }
        $oPage->add_style(<<<EOF
.attachment {
\tdisplay: inline-block;
\ttext-align:center;
\tfloat:left;
\tpadding:5px;\t
}
.attachment:hover {
\tbackground-color: #e0e0e0;
}
.attachment img {
\tborder: 0;
}
.attachment a {
\ttext-decoration: none;
\tcolor: #1C94C4;
}
.btn_hidden {
\tdisplay: none;
}
EOF
);
        $oPage->add('<fieldset>');
        $oPage->add('<legend>' . Dict::S('Attachments:FieldsetTitle') . '</legend>');
        if ($bEditMode) {
            $sIsDeleteEnabled = $this->m_bDeleteEnabled ? 'true' : 'false';
            $iTransactionId = $oPage->GetTransactionId();
            $sClass = get_class($oObject);
            $sTempId = session_id() . '_' . $iTransactionId;
            $sDeleteBtn = Dict::S('Attachments:DeleteBtn');
            $oPage->add_script(<<<EOF
\tfunction RemoveNewAttachment(att_id)
\t{
\t\t\$('#attachment_'+att_id).attr('name', 'removed_attachments[]');
\t\t\$('#display_attachment_'+att_id).hide();
\t\t\$('#attachment_plugin').trigger('remove_attachment', [att_id]);
\t\treturn false; // Do not submit the form !
\t}
\tfunction ajaxFileUpload()
\t{
\t\t//starting setting some animation when the ajax starts and completes
\t\t\$("#attachment_loading").ajaxStart(function(){
\t\t\t\$(this).show();
\t\t}).ajaxComplete(function(){
\t\t\t\$(this).hide();
\t\t});
\t\t
\t\t/*
\t\t\tprepareing ajax file upload
\t\t\turl: the url of script file handling the uploaded files
                        fileElementId: the file type of input element id and it will be the index of  \$_FILES Array()
\t\t\tdataType: it support json, xml
\t\t\tsecureuri:use secure protocol
\t\t\tsuccess: call back function when the ajax complete
\t\t\terror: callback function when the ajax failed
\t\t\t
                */
\t\t\$.ajaxFileUpload
\t\t(
\t\t\t{
\t\t\t\turl: GetAbsoluteUrlModulesRoot()+'itop-attachments/ajax.attachment.php?obj_class={$sClass}&temp_id={$sTempId}&operation=add', 
\t\t\t\tsecureuri:false,
\t\t\t\tfileElementId:'file',
\t\t\t\tdataType: 'json',
\t\t\t\tsuccess: function (data, status)
\t\t\t\t{
\t\t\t\t\tif(typeof(data.error) != 'undefined')
\t\t\t\t\t{
\t\t\t\t\t\tif(data.error != '')
\t\t\t\t\t\t{
\t\t\t\t\t\t\talert(data.error);
\t\t\t\t\t\t}
\t\t\t\t\t\telse
\t\t\t\t\t\t{
\t\t\t\t\t\t\tvar sDownloadLink = GetAbsoluteUrlAppRoot()+'pages/ajax.render.php?operation=download_document&class=Attachment&id='+data.att_id+'&field=contents';
\t\t\t\t\t\t\t\$('#attachments').append('<div class="attachment" id="display_attachment_'+data.att_id+'"><a href="'+sDownloadLink+'"><img src="'+data.icon+'"><br/>'+data.msg+'<input id="attachment_'+data.att_id+'" type="hidden" name="attachments[]" value="'+data.att_id+'"/></a><br/><input type="button" class="btn_hidden" value="{$sDeleteBtn}" onClick="RemoveNewAttachment('+data.att_id+');"/></div>');
\t\t\t\t\t\t\tif({$sIsDeleteEnabled})
\t\t\t\t\t\t\t{
\t\t\t\t\t\t\t\t\$('#display_attachment_'+data.att_id).hover( function() { \$(this).children(':button').toggleClass('btn_hidden'); } );
\t\t\t\t\t\t\t}
\t\t\t\t\t\t\t\$('#attachment_plugin').trigger('add_attachment', [data.att_id, data.msg]);
\t\t\t\t\t\t\t
\t\t\t\t\t\t\t//alert(data.msg);
\t\t\t\t\t\t}
\t\t\t\t\t}
\t\t\t\t},
\t\t\t\terror: function (data, status, e)
\t\t\t\t{
\t\t\t\t\talert(e);
\t\t\t\t}
\t\t\t}
\t\t)
\t\t
\t\treturn false;

\t}
EOF
);
            $oPage->add('<span id="attachments">');
            while ($oAttachment = $oSet->Fetch()) {
                $iAttId = $oAttachment->GetKey();
                $oDoc = $oAttachment->Get('contents');
                $sFileName = $oDoc->GetFileName();
                $sIcon = utils::GetAbsoluteUrlAppRoot() . AttachmentPlugIn::GetFileIcon($sFileName);
                $sDownloadLink = utils::GetAbsoluteUrlAppRoot() . 'pages/ajax.render.php?operation=download_document&class=Attachment&id=' . $iAttId . '&field=contents';
                $oPage->add('<div class="attachment" id="attachment_' . $iAttId . '"><a href="' . $sDownloadLink . '"><img src="' . $sIcon . '"><br/>' . $sFileName . '<input type="hidden" name="attachments[]" value="' . $iAttId . '"/></a><br/>&nbsp;<input id="btn_remove_' . $iAttId . '" type="button" class="btn_hidden" value="Delete" onClick="$(\'#attachment_' . $iAttId . '\').remove();"/>&nbsp;</div>');
            }
            // Suggested attachments are listed here but treated as temporary
            $aDefault = utils::ReadParam('default', array(), false, 'raw_data');
            if (array_key_exists('suggested_attachments', $aDefault)) {
                $sSuggestedAttachements = $aDefault['suggested_attachments'];
                if (is_array($sSuggestedAttachements)) {
                    $sSuggestedAttachements = implode(',', $sSuggestedAttachements);
                }
                $oSearch = DBObjectSearch::FromOQL("SELECT Attachment WHERE id IN({$sSuggestedAttachements})");
                $oSet = new DBObjectSet($oSearch, array());
                if ($oSet->Count() > 0) {
                    while ($oAttachment = $oSet->Fetch()) {
                        // Mark the attachments as temporary attachments for the current object/form
                        $oAttachment->Set('temp_id', $sTempId);
                        $oAttachment->DBUpdate();
                        // Display them
                        $iAttId = $oAttachment->GetKey();
                        $oDoc = $oAttachment->Get('contents');
                        $sFileName = $oDoc->GetFileName();
                        $sIcon = utils::GetAbsoluteUrlAppRoot() . AttachmentPlugIn::GetFileIcon($sFileName);
                        $sDownloadLink = utils::GetAbsoluteUrlAppRoot() . 'pages/ajax.render.php?operation=download_document&class=Attachment&id=' . $iAttId . '&field=contents';
                        $oPage->add('<div class="attachment" id="display_attachment_' . $iAttId . '"><a href="' . $sDownloadLink . '"><img src="' . $sIcon . '"><br/>' . $sFileName . '<input type="hidden" name="attachments[]" value="' . $iAttId . '"/></a><br/>&nbsp;<input id="btn_remove_' . $iAttId . '" type="button" class="btn_hidden" value="Delete" onClick="RemoveNewAttachment(' . $iAttId . ');"/>&nbsp;</div>');
                        $oPage->add_ready_script("\$('#attachment_plugin').trigger('add_attachment', [{$iAttId}, '" . addslashes($sFileName) . "']);");
                    }
                }
            }
            $oPage->add('</span>');
            $oPage->add('<div style="clear:both"></div>');
            $sMaxUpload = $this->GetMaxUpload();
            $oPage->p(Dict::S('Attachments:AddAttachment') . '<input type="file" name="file" id="file" onChange="ajaxFileUpload();"><span style="display:none;" id="attachment_loading">&nbsp;<img src="../images/indicator.gif"></span> ' . $sMaxUpload);
            $oPage->p('<span style="display:none;" id="attachment_loading">Loading, please wait...</span>');
            $oPage->p('<input type="hidden" id="attachment_plugin" name="attachment_plugin"/>');
            $oPage->add('</fieldset>');
            if ($this->m_bDeleteEnabled) {
                $oPage->add_ready_script('$(".attachment").hover( function() {$(this).children(":button").toggleClass("btn_hidden"); } );');
            }
        } else {
            $oPage->add('<span id="attachments">');
            if ($oSet->Count() == 0) {
                $oPage->add(Dict::S('Attachments:NoAttachment'));
            } else {
                while ($oAttachment = $oSet->Fetch()) {
                    $iAttId = $oAttachment->GetKey();
                    $oDoc = $oAttachment->Get('contents');
                    $sFileName = $oDoc->GetFileName();
                    $sIcon = utils::GetAbsoluteUrlAppRoot() . AttachmentPlugIn::GetFileIcon($sFileName);
                    $sDownloadLink = utils::GetAbsoluteUrlAppRoot() . 'pages/ajax.render.php?operation=download_document&class=Attachment&id=' . $iAttId . '&field=contents';
                    $oPage->add('<div class="attachment" id="attachment_' . $iAttId . '"><a href="' . $sDownloadLink . '"><img src="' . $sIcon . '"><br/>' . $sFileName . '</a><input type="hidden" name="attachments[]" value="' . $iAttId . '"/><br/>&nbsp;&nbsp;</div>');
                }
            }
        }
    }
Exemplo n.º 22
0
 /**
  * Display the hierarchy of the 'target' class
  */
 public function DisplayHierarchy(WebPage $oPage, $sFilter, $currValue, $oObj)
 {
     $sDialogTitle = addslashes(Dict::Format('UI:HierarchyOf_Class', MetaModel::GetName($this->sTargetClass)));
     $oPage->add('<div id="dlg_tree_' . $this->iId . '"><div class="wizContainer" style="vertical-align:top;"><div style="overflow:auto;background:#fff;margin-bottom:5px;" id="tree_' . $this->iId . '">');
     $oPage->add('<table style="width:100%"><tr><td>');
     if (is_null($sFilter)) {
         throw new Exception('Implementation: null value for allowed values definition');
     }
     try {
         $oFilter = DBObjectSearch::FromOQL($sFilter);
         $oFilter->SetModifierProperty('UserRightsGetSelectFilter', 'bSearchMode', $this->bSearchMode);
         $oSet = new DBObjectSet($oFilter, array(), array('this' => $oObj));
     } catch (MissingQueryArgument $e) {
         // When used in a search form the $this parameter may be missing, in this case return all possible values...
         // TODO check if we can improve this behavior...
         $sOQL = 'SELECT ' . $this->m_sTargetClass;
         $oFilter = DBObjectSearch::FromOQL($sOQL);
         $oFilter->SetModifierProperty('UserRightsGetSelectFilter', 'bSearchMode', $this->bSearchMode);
         $oSet = new DBObjectSet($oFilter);
     }
     $sHKAttCode = MetaModel::IsHierarchicalClass($this->sTargetClass);
     $this->DumpTree($oPage, $oSet, $sHKAttCode, $currValue);
     $oPage->add('</td></tr></table>');
     $oPage->add('</div>');
     $oPage->add("<input type=\"button\" id=\"btn_cancel_{$this->iId}\" value=\"" . Dict::S('UI:Button:Cancel') . "\" onClick=\"\$('#dlg_tree_{$this->iId}').dialog('close');\">&nbsp;&nbsp;");
     $oPage->add("<input type=\"button\" id=\"btn_ok_{$this->iId}\" value=\"" . Dict::S('UI:Button:Ok') . "\"  onClick=\"oACWidget_{$this->iId}.DoHKOk();\">");
     $oPage->add('</div></div>');
     $oPage->add_ready_script("\$('#tree_{$this->iId} ul').treeview();\n");
     $oPage->add_ready_script("\$('#dlg_tree_{$this->iId}').dialog({ width: 'auto', height: 'auto', autoOpen: true, modal: true, title: '{$sDialogTitle}', resizeStop: oACWidget_{$this->iId}.OnHKResize, close: oACWidget_{$this->iId}.OnHKClose });\n");
 }
Exemplo n.º 23
0
 protected function RenderTag($oPage, $sTag, $aAttributes, $sContent)
 {
     static $iTabContainerCount = 0;
     switch ($sTag) {
         case 'itoptabs':
             $oPage->AddTabContainer('Tabs_' . $iTabContainerCount);
             $oPage->SetCurrentTabContainer('Tabs_' . $iTabContainerCount);
             $iTabContainerCount++;
             //$oPage->p('Content:<pre>'.htmlentities($sContent, ENT_QUOTES, 'UTF-8').'</pre>');
             $oTemplate = new DisplayTemplate($sContent);
             $oTemplate->Render($oPage, array());
             // no params to apply, they have already been applied
             $oPage->SetCurrentTabContainer('');
             break;
         case 'itopcheck':
             $sClassName = $aAttributes['class'];
             if (MetaModel::IsValidClass($sClassName) && UserRights::IsActionAllowed($sClassName, UR_ACTION_READ)) {
                 $oTemplate = new DisplayTemplate($sContent);
                 $oTemplate->Render($oPage, array());
                 // no params to apply, they have already been applied
             } else {
                 // Leave a trace for those who'd like to understand why nothing is displayed
                 $oPage->add("<!-- class {$sClassName} does not exist, skipping some part of the template -->\n");
             }
             break;
         case 'itoptab':
             $oPage->SetCurrentTab(Dict::S(str_replace('_', ' ', $aAttributes['name'])));
             $oTemplate = new DisplayTemplate($sContent);
             $oTemplate->Render($oPage, array());
             // no params to apply, they have already been applied
             //$oPage->p('iTop Tab Content:<pre>'.htmlentities($sContent, ENT_QUOTES, 'UTF-8').'</pre>');
             $oPage->SetCurrentTab('');
             break;
         case 'itoptoggle':
             $sName = isset($aAttributes['name']) ? $aAttributes['name'] : 'Tagada';
             $bOpen = isset($aAttributes['open']) ? $aAttributes['open'] : true;
             $oPage->StartCollapsibleSection(Dict::S($sName), $bOpen);
             $oTemplate = new DisplayTemplate($sContent);
             $oTemplate->Render($oPage, array());
             // no params to apply, they have already been applied
             //$oPage->p('iTop Tab Content:<pre>'.htmlentities($sContent, ENT_QUOTES, 'UTF-8').'</pre>');
             $oPage->EndCollapsibleSection();
             break;
         case 'itopstring':
             $oPage->add(Dict::S($sContent));
             break;
         case 'sqlblock':
             $oBlock = SqlBlock::FromTemplate($sContent);
             $oBlock->RenderContent($oPage);
             break;
         case 'itopblock':
             // No longer used, handled by DisplayBlock::FromTemplate see above
             $oPage->add("<!-- Application Error: should be handled by DisplayBlock::FromTemplate -->");
             break;
         default:
             // Unknown tag, just ignore it or now -- output an HTML comment
             $oPage->add("<!-- unsupported tag: {$sTag} -->");
     }
 }
Exemplo n.º 24
0
 protected function GetHTMLTableConfig($aColumns, $sSelectMode, $bViewLink)
 {
     $aAttribs = array();
     if ($sSelectMode == 'multiple') {
         $aAttribs['form::select'] = array('label' => "<input type=\"checkbox\" onClick=\"CheckAll('.selectList{$this->iListId}:not(:disabled)', this.checked);\" class=\"checkAll\"></input>", 'description' => Dict::S('UI:SelectAllToggle+'));
     } else {
         if ($sSelectMode == 'single') {
             $aAttribs['form::select'] = array('label' => "", 'description' => '');
         }
     }
     foreach ($this->aClassAliases as $sAlias => $sClassName) {
         foreach ($aColumns[$sAlias] as $sAttCode => $aData) {
             if ($aData['checked']) {
                 if ($sAttCode == '_key_') {
                     $aAttribs['key_' . $sAlias] = array('label' => MetaModel::GetName($sClassName), 'description' => '');
                 } else {
                     $oAttDef = MetaModel::GetAttributeDef($sClassName, $sAttCode);
                     $aAttribs[$sAttCode . '_' . $sAlias] = array('label' => MetaModel::GetLabel($sClassName, $sAttCode), 'description' => $oAttDef->GetOrderByHint());
                 }
             }
         }
     }
     return $aAttribs;
 }
Exemplo n.º 25
0
    $sValue = utils::ReadParam($sParam, null, true, $sSanitizationFilter);
    if (is_null($sValue)) {
        $oP->p("ERROR: Missing argument '{$sParam}'\n");
        exit(29);
    }
    return trim($sValue);
}
/////////////////////////////////
// Main program
if (!utils::IsModeCLI()) {
    $oP = new WebPage(Dict::S("TitleSynchroExecution"));
    $oP->p("This page is used internally by iTop");
    $oP->output();
    exit - 2;
}
$oP = new CLIPage(Dict::S("TitleSynchroExecution"));
try {
    utils::UseParamFile();
} catch (Exception $e) {
    $oP->p("Error: " . $e->GetMessage());
    $oP->output();
    exit - 2;
}
// Next steps:
//   specific arguments: 'csvfile'
//
$sAuthUser = ReadMandatoryParam($oP, 'auth_user', 'raw_data');
$sAuthPwd = ReadMandatoryParam($oP, 'auth_pwd', 'raw_data');
if (UserRights::CheckCredentials($sAuthUser, $sAuthPwd)) {
    UserRights::Login($sAuthUser);
    // Login & set the user's language
Exemplo n.º 26
0
    /**
     * Outputs (via some echo) the complete HTML page by assembling all its elements
     */
    public function output()
    {
        $sAbsURLAppRoot = addslashes($this->m_sRootUrl);
        //$this->set_base($this->m_sRootUrl.'pages/');
        $sForm = $this->GetSiloSelectionForm();
        $this->DisplayMenu();
        // Compute the menu
        // Call the extensions to add content to the page, so that they can also add styles or scripts
        $sBannerExtraHtml = '';
        foreach (MetaModel::EnumPlugins('iPageUIExtension') as $oExtensionInstance) {
            $sBannerExtraHtml .= $oExtensionInstance->GetBannerHtml($this);
        }
        $sNorthPane = '';
        foreach (MetaModel::EnumPlugins('iPageUIExtension') as $oExtensionInstance) {
            $sNorthPane .= $oExtensionInstance->GetNorthPaneHtml($this);
        }
        if (UserRights::IsAdministrator() && ExecutionKPI::IsEnabled()) {
            $sNorthPane .= '<div id="admin-banner"><span style="padding:5px;">' . ExecutionKPI::GetDescription() . '<span></div>';
        }
        //$sSouthPane = '<p>Peak memory Usage: '.sprintf('%.3f MB', memory_get_peak_usage(true) / (1024*1024)).'</p>';
        $sSouthPane = '';
        foreach (MetaModel::EnumPlugins('iPageUIExtension') as $oExtensionInstance) {
            $sSouthPane .= $oExtensionInstance->GetSouthPaneHtml($this);
        }
        // Put here the 'ready scripts' that must be executed after all others
        $aMultiselectOptions = array('header' => true, 'checkAllText' => Dict::S('UI:SearchValue:CheckAll'), 'uncheckAllText' => Dict::S('UI:SearchValue:UncheckAll'), 'noneSelectedText' => Dict::S('UI:SearchValue:Any'), 'selectedText' => Dict::S('UI:SearchValue:NbSelected'), 'selectedList' => 1);
        $sJSMultiselectOptions = json_encode($aMultiselectOptions);
        $this->add_ready_script(<<<EOF
\t\t// Since the event is only triggered when the hash changes, we need to trigger
\t\t// the event now, to handle the hash the page may have loaded with.
\t\t\$(window).trigger( 'hashchange' );
\t\t
\t\t// Some table are sort-able, some are not, let's fix this
\t\t\$('table.listResults').each( function() { FixTableSorter(\$(this)); } );
\t\t
\t\t\$('.multiselect').multiselect({$sJSMultiselectOptions});

\t\tFixSearchFormsDisposition();

EOF
);
        if ($this->GetOutputFormat() == 'html') {
            foreach ($this->a_headers as $s_header) {
                header($s_header);
            }
        }
        $s_captured_output = $this->ob_get_clean_safe();
        $sHtml = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n";
        $sHtml .= "<html>\n";
        $sHtml .= "<head>\n";
        // Make sure that Internet Explorer renders the page using its latest/highest/greatest standards !
        $sHtml .= "<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />\n";
        $sHtml .= "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n";
        $sHtml .= "<title>" . htmlentities($this->s_title, ENT_QUOTES, 'UTF-8') . "</title>\n";
        $sHtml .= $this->get_base_tag();
        // Stylesheets MUST be loaded before any scripts otherwise
        // jQuery scripts may face some spurious problems (like failing on a 'reload')
        foreach ($this->a_linked_stylesheets as $a_stylesheet) {
            if ($a_stylesheet['condition'] != "") {
                $sHtml .= "<!--[if {$a_stylesheet['condition']}]>\n";
            }
            $sHtml .= "<link rel=\"stylesheet\" type=\"text/css\" href=\"{$a_stylesheet['link']}\" />\n";
            if ($a_stylesheet['condition'] != "") {
                $sHtml .= "<![endif]-->\n";
            }
        }
        // special stylesheet for printing, hides the navigation gadgets
        $sHtml .= "<link rel=\"stylesheet\" media=\"print\" type=\"text/css\" href=\"../css/print.css\" />\n";
        if ($this->GetOutputFormat() == 'html') {
            $sHtml .= $this->output_dict_entries(true);
            // before any script so that they can benefit from the translations
            foreach ($this->a_linked_scripts as $s_script) {
                // Make sure that the URL to the script contains the application's version number
                // so that the new script do NOT get reloaded from the cache when the application is upgraded
                if (strpos($s_script, '?') === false) {
                    $s_script .= "?itopversion=" . ITOP_VERSION;
                } else {
                    $s_script .= "&itopversion=" . ITOP_VERSION;
                }
                $sHtml .= "<script type=\"text/javascript\" src=\"{$s_script}\"></script>\n";
            }
            $this->add_script("var iPaneVisWatchDog  = window.setTimeout('FixPaneVis()',5000);\n\$(document).ready(function() {\n{$this->m_sInitScript};\nwindow.setTimeout('onDelayedReady()',10)\n});");
            if (count($this->m_aReadyScripts) > 0) {
                $this->add_script("\nonDelayedReady = function() {\n" . implode("\n", $this->m_aReadyScripts) . "\n}\n");
            }
            if (count($this->a_scripts) > 0) {
                $sHtml .= "<script type=\"text/javascript\">\n";
                foreach ($this->a_scripts as $s_script) {
                    $sHtml .= "{$s_script}\n";
                }
                $sHtml .= "</script>\n";
            }
        }
        if (count($this->a_styles) > 0) {
            $sHtml .= "<style>\n";
            foreach ($this->a_styles as $s_style) {
                $sHtml .= "{$s_style}\n";
            }
            $sHtml .= "</style>\n";
        }
        $sHtml .= "<link rel=\"search\" type=\"application/opensearchdescription+xml\" title=\"iTop\" href=\"" . utils::GetAbsoluteUrlAppRoot() . "pages/opensearch.xml.php\" />\n";
        $sHtml .= "<link rel=\"shortcut icon\" href=\"" . utils::GetAbsoluteUrlAppRoot() . "images/favicon.ico\" />\n";
        $sHtml .= "</head>\n";
        $sHtml .= "<body>\n";
        // Render the revision number
        if (ITOP_REVISION == '$WCREV$') {
            // This is NOT a version built using the buil system, just display the main version
            $sVersionString = Dict::Format('UI:iTopVersion:Short', ITOP_VERSION);
        } else {
            // This is a build made from SVN, let display the full information
            $sVersionString = Dict::Format('UI:iTopVersion:Long', ITOP_VERSION, ITOP_REVISION, ITOP_BUILD_DATE);
        }
        // Render the text of the global search form
        $sText = htmlentities(utils::ReadParam('text', '', false, 'raw_data'), ENT_QUOTES, 'UTF-8');
        $sOnClick = "";
        if (empty($sText)) {
            // if no search text is supplied then
            // 1) the search text is filled with "your search"
            // 2) clicking on it will erase it
            $sText = Dict::S("UI:YourSearch");
            $sOnClick = " onclick=\"this.value='';this.onclick=null;\"";
        }
        // Render the tabs in the page (if any)
        $this->s_content = $this->m_oTabs->RenderIntoContent($this->s_content);
        if ($this->GetOutputFormat() == 'html') {
            $oAppContext = new ApplicationContext();
            $sUserName = UserRights::GetUser();
            $sIsAdmin = UserRights::IsAdministrator() ? '(Administrator)' : '';
            if (UserRights::IsAdministrator()) {
                $sLogonMessage = Dict::Format('UI:LoggedAsMessage+Admin', $sUserName);
            } else {
                $sLogonMessage = Dict::Format('UI:LoggedAsMessage', $sUserName);
            }
            $sLogOffMenu = "<span id=\"logOffBtn\"><ul><li><img src=\"../images/onOffBtn.png\"><ul>";
            $sLogOffMenu .= "<li><span>{$sLogonMessage}</span></li>\n";
            $aActions = array();
            $oPrefs = new URLPopupMenuItem('UI:Preferences', Dict::S('UI:Preferences'), utils::GetAbsoluteUrlAppRoot() . "pages/preferences.php?" . $oAppContext->GetForLink());
            $aActions[$oPrefs->GetUID()] = $oPrefs->GetMenuItem();
            if (utils::CanLogOff()) {
                $oLogOff = new URLPopupMenuItem('UI:LogOffMenu', Dict::S('UI:LogOffMenu'), utils::GetAbsoluteUrlAppRoot() . 'pages/logoff.php?operation=do_logoff');
                $aActions[$oLogOff->GetUID()] = $oLogOff->GetMenuItem();
            }
            if (UserRights::CanChangePassword()) {
                $oChangePwd = new URLPopupMenuItem('UI:ChangePwdMenu', Dict::S('UI:ChangePwdMenu'), utils::GetAbsoluteUrlAppRoot() . 'pages/UI.php?loginop=change_pwd');
                $aActions[$oChangePwd->GetUID()] = $oChangePwd->GetMenuItem();
            }
            utils::GetPopupMenuItems($this, iPopupMenuExtension::MENU_USER_ACTIONS, null, $aActions);
            $oAbout = new JSPopupMenuItem('UI:AboutBox', Dict::S('UI:AboutBox'), 'return ShowAboutBox();');
            $aActions[$oAbout->GetUID()] = $oAbout->GetMenuItem();
            $sLogOffMenu .= $this->RenderPopupMenuItems($aActions);
            $sRestrictions = '';
            if (!MetaModel::DBHasAccess(ACCESS_ADMIN_WRITE)) {
                if (!MetaModel::DBHasAccess(ACCESS_ADMIN_WRITE)) {
                    $sRestrictions = Dict::S('UI:AccessRO-All');
                }
            } elseif (!MetaModel::DBHasAccess(ACCESS_USER_WRITE)) {
                $sRestrictions = Dict::S('UI:AccessRO-Users');
            }
            $sApplicationBanner = '';
            if (strlen($sRestrictions) > 0) {
                $sAdminMessage = trim(MetaModel::GetConfig()->Get('access_message'));
                $sApplicationBanner .= '<div id="admin-banner">';
                $sApplicationBanner .= '<img src="../images/locked.png" style="vertical-align:middle;">';
                $sApplicationBanner .= '&nbsp;<b>' . $sRestrictions . '</b>';
                if (strlen($sAdminMessage) > 0) {
                    $sApplicationBanner .= '&nbsp;<b>' . $sAdminMessage . '</b>';
                }
                $sApplicationBanner .= '</div>';
            }
            if (strlen($this->m_sMessage)) {
                $sApplicationBanner .= '<div id="admin-banner"><span style="padding:5px;">' . $this->m_sMessage . '<span></div>';
            }
            $sApplicationBanner .= $sBannerExtraHtml;
            if (!empty($sNorthPane)) {
                $sNorthPane = '<div id="bottom-pane" class="ui-layout-north">' . $sNorthPane . '</div>';
            }
            if (!empty($sSouthPane)) {
                $sSouthPane = '<div id="bottom-pane" class="ui-layout-south">' . $sSouthPane . '</div>';
            }
            $sIconUrl = Utils::GetConfig()->Get('app_icon_url');
            $sOnlineHelpUrl = MetaModel::GetConfig()->Get('online_help');
            //$sLogOffMenu = "<span id=\"logOffBtn\" style=\"height:55px;padding:0;margin:0;\"><img src=\"../images/onOffBtn.png\"></span>";
            $sDisplayIcon = utils::GetAbsoluteUrlAppRoot() . 'images/itop-logo.png';
            if (file_exists(MODULESROOT . 'branding/main-logo.png')) {
                $sDisplayIcon = utils::GetAbsoluteUrlModulesRoot() . 'branding/main-logo.png';
            }
            $sHtml .= $sNorthPane;
            $sHtml .= '<div id="left-pane" class="ui-layout-west">';
            $sHtml .= '<!-- Beginning of the left pane -->';
            $sHtml .= ' <div class="ui-layout-north">';
            $sHtml .= ' <div id="header-logo">';
            $sHtml .= ' <div id="top-left"></div><div id="logo"><a href="' . htmlentities($sIconUrl, ENT_QUOTES, 'UTF-8') . '"><img src="' . $sDisplayIcon . '" title="' . htmlentities($sVersionString, ENT_QUOTES, 'UTF-8') . '" style="border:0; margin-top:16px; margin-right:40px;"/></a></div>';
            $sHtml .= ' </div>';
            $sHtml .= ' <div class="header-menu">';
            if (!MetaModel::GetConfig()->Get('demo_mode')) {
                $sHtml .= '		<div class="icon ui-state-default ui-corner-all"><span id="tPinMenu" class="ui-icon ui-icon-pin-w">pin</span></div>';
            }
            $sHtml .= '		<div style="text-align:center;">' . self::FilterXSS($sForm) . '</div>';
            $sHtml .= ' </div>';
            $sHtml .= ' </div>';
            $sHtml .= ' <div id="menu" class="ui-layout-center">';
            $sHtml .= '		<div id="inner_menu">';
            $sHtml .= '			<div id="accordion">';
            $sHtml .= self::FilterXSS($this->m_sMenu);
            $sHtml .= '			<!-- Beginning of the accordion menu -->';
            $sHtml .= '			<!-- End of the accordion menu-->';
            $sHtml .= '			</div>';
            $sHtml .= '		</div> <!-- /inner menu -->';
            $sHtml .= ' </div> <!-- /menu -->';
            $sHtml .= ' <div class="footer ui-layout-south"><div id="combodo_logo"><a href="http://www.combodo.com" title="www.combodo.com" target="_blank"><img src="../images/logo-combodo.png"/></a></div></div>';
            $sHtml .= '<!-- End of the left pane -->';
            $sHtml .= '</div>';
            $sHtml .= '<div class="ui-layout-center">';
            $sHtml .= ' <div id="top-bar" style="width:100%">';
            $sHtml .= self::FilterXSS($sApplicationBanner);
            $sHtml .= '		<div id="global-search"><form action="' . utils::GetAbsoluteUrlAppRoot() . 'pages/UI.php"><table><tr><td></td><td id="g-search-input"><input type="text" name="text" value="' . $sText . '"' . $sOnClick . '/></td>';
            $sHtml .= '<td><input type="image" src="../images/searchBtn.png"/></a></td>';
            $sHtml .= '<td><a style="background:transparent;" href="' . $sOnlineHelpUrl . '" target="_blank"><img style="border:0;padding-left:20px;padding-right:10px;" title="' . Dict::S('UI:Help') . '" src="../images/help.png"/></td>';
            $sHtml .= '<td style="padding-right:20px;padding-left:10px;">' . self::FilterXSS($sLogOffMenu) . '</td><td><input type="hidden" name="operation" value="full_text"/></td></tr></table></form></div>';
            //echo '<td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<input type="hidden" name="operation" value="full_text"/></td></tr></table></form></div>';
            $sHtml .= ' </div>';
            $sHtml .= ' <div class="ui-layout-content" style="overflow:auto;">';
            $sHtml .= ' <!-- Beginning of page content -->';
            $sHtml .= self::FilterXSS($this->s_content);
            $sHtml .= ' <!-- End of page content -->';
            $sHtml .= ' </div>';
            $sHtml .= '</div>';
            $sHtml .= $sSouthPane;
            // Add the captured output
            if (trim($s_captured_output) != "") {
                $sHtml .= "<div id=\"rawOutput\" title=\"Debug Output\"><div style=\"height:500px; overflow-y:auto;\">" . self::FilterXSS($s_captured_output) . "</div></div>\n";
            }
            $sHtml .= "<div id=\"at_the_end\">" . self::FilterXSS($this->s_deferred_content) . "</div>";
            $sHtml .= "<div style=\"display:none\" title=\"ex2\" id=\"ex2\">Please wait...</div>\n";
            // jqModal Window
            $sHtml .= "<div style=\"display:none\" title=\"dialog\" id=\"ModalDlg\"></div>";
            $sHtml .= "<div style=\"display:none\" id=\"ajax_content\"></div>";
        } else {
            $sHtml .= self::FilterXSS($this->s_content);
        }
        $sHtml .= "</body>\n";
        $sHtml .= "</html>\n";
        if ($this->GetOutputFormat() == 'html') {
            $oKPI = new ExecutionKPI();
            echo $sHtml;
            $oKPI->ComputeAndReport('Echoing (' . round(strlen($sHtml) / 1024) . ' Kb)');
        } else {
            if ($this->GetOutputFormat() == 'pdf' && $this->IsOutputFormatAvailable('pdf')) {
                if (@is_readable(APPROOT . 'lib/MPDF/mpdf.php')) {
                    require_once APPROOT . 'lib/MPDF/mpdf.php';
                    $oMPDF = new mPDF('c');
                    $oMPDF->mirroMargins = false;
                    if ($this->a_base['href'] != '') {
                        $oMPDF->setBasePath($this->a_base['href']);
                        // Seems that the <BASE> tag is not recognized by mPDF...
                    }
                    $oMPDF->showWatermarkText = true;
                    if ($this->GetOutputOption('pdf', 'template_path')) {
                        $oMPDF->setImportUse();
                        // Allow templates
                        $oMPDF->SetDocTemplate($this->GetOutputOption('pdf', 'template_path'), 1);
                    }
                    $oMPDF->WriteHTML($sHtml);
                    $sOutputName = $this->s_title . '.pdf';
                    if ($this->GetOutputOption('pdf', 'output_name')) {
                        $sOutputName = $this->GetOutputOption('pdf', 'output_name');
                    }
                    $oMPDF->Output($sOutputName, 'I');
                }
            }
        }
        DBSearch::RecordQueryTrace();
        ExecutionKPI::ReportStats();
    }
Exemplo n.º 27
0
 public function GetLabel()
 {
     return Dict::S('portal:' . $this->sPortalid);
 }
Exemplo n.º 28
0
 /**
  * Renders the "Actions" popup menu for the given set of objects
  * 
  * Note that the menu links containing (or ending) with a hash (#) will have their fragment
  * part (whatever is after the hash) dynamically replaced (by javascript) when the menu is
  * displayed, to correspond to the current hash/fragment in the page. This allows modifying
  * an object in with the same tab active by default as the tab that was active when selecting
  * the "Modify..." action.
  */
 public function GetRenderContent(WebPage $oPage, $aExtraParams = array(), $sId)
 {
     if ($this->m_sStyle == 'popup') {
         $this->m_sStyle = 'list';
     }
     $sHtml = '';
     $oAppContext = new ApplicationContext();
     $sContext = $oAppContext->GetForLink();
     if (!empty($sContext)) {
         $sContext = '&' . $sContext;
     }
     $sClass = $this->m_oFilter->GetClass();
     $oReflectionClass = new ReflectionClass($sClass);
     $oSet = new CMDBObjectSet($this->m_oFilter);
     $sFilter = $this->m_oFilter->serialize();
     $sFilterDesc = $this->m_oFilter->ToOql(true);
     $aActions = array();
     $sUIPage = cmdbAbstractObject::ComputeStandardUIPage($sClass);
     $sRootUrl = utils::GetAbsoluteUrlAppRoot();
     // 1:n links, populate the target object as a default value when creating a new linked object
     if (isset($aExtraParams['target_attr'])) {
         $aExtraParams['default'][$aExtraParams['target_attr']] = $aExtraParams['object_id'];
     }
     $sDefault = '';
     if (!empty($aExtraParams['default'])) {
         foreach ($aExtraParams['default'] as $sKey => $sValue) {
             $sDefault .= "&default[{$sKey}]={$sValue}";
         }
     }
     $bIsCreationAllowed = UserRights::IsActionAllowed($sClass, UR_ACTION_CREATE) == UR_ALLOWED_YES && $oReflectionClass->IsSubclassOf('cmdbAbstractObject');
     switch ($oSet->Count()) {
         case 0:
             // No object in the set, the only possible action is "new"
             if ($bIsCreationAllowed) {
                 $aActions['UI:Menu:New'] = array('label' => Dict::S('UI:Menu:New'), 'url' => "{$sRootUrl}pages/{$sUIPage}?operation=new&class={$sClass}{$sContext}{$sDefault}");
             }
             break;
         case 1:
             $oObj = $oSet->Fetch();
             $id = $oObj->GetKey();
             $bLocked = false;
             if (MetaModel::GetConfig()->Get('concurrent_lock_enabled')) {
                 $aLockInfo = iTopOwnershipLock::IsLocked(get_class($oObj), $id);
                 if ($aLockInfo['locked']) {
                     $bLocked = true;
                     //$this->AddMenuSeparator($aActions);
                     //$aActions['concurrent_lock_unlock'] = array ('label' => Dict::S('UI:Menu:ReleaseConcurrentLock'), 'url' => "{$sRootUrl}pages/$sUIPage?operation=kill_lock&class=$sClass&id=$id{$sContext}");
                 }
             }
             $bRawModifiedAllowed = UserRights::IsActionAllowed($sClass, UR_ACTION_MODIFY, $oSet) == UR_ALLOWED_YES && $oReflectionClass->IsSubclassOf('cmdbAbstractObject');
             $bIsModifyAllowed = !$bLocked && $bRawModifiedAllowed;
             $bIsDeleteAllowed = !$bLocked && UserRights::IsActionAllowed($sClass, UR_ACTION_DELETE, $oSet);
             // Just one object in the set, possible actions are "new / clone / modify and delete"
             if (!isset($aExtraParams['link_attr'])) {
                 if ($bIsModifyAllowed) {
                     $aActions['UI:Menu:Modify'] = array('label' => Dict::S('UI:Menu:Modify'), 'url' => "{$sRootUrl}pages/{$sUIPage}?operation=modify&class={$sClass}&id={$id}{$sContext}#");
                 }
                 if ($bIsCreationAllowed) {
                     $aActions['UI:Menu:New'] = array('label' => Dict::S('UI:Menu:New'), 'url' => "{$sRootUrl}pages/{$sUIPage}?operation=new&class={$sClass}{$sContext}{$sDefault}");
                 }
                 if ($bIsDeleteAllowed) {
                     $aActions['UI:Menu:Delete'] = array('label' => Dict::S('UI:Menu:Delete'), 'url' => "{$sRootUrl}pages/{$sUIPage}?operation=delete&class={$sClass}&id={$id}{$sContext}");
                 }
                 // Transitions / Stimuli
                 if (!$bLocked) {
                     $aTransitions = $oObj->EnumTransitions();
                     if (count($aTransitions)) {
                         $this->AddMenuSeparator($aActions);
                         $aStimuli = Metamodel::EnumStimuli(get_class($oObj));
                         foreach ($aTransitions as $sStimulusCode => $aTransitionDef) {
                             $iActionAllowed = get_class($aStimuli[$sStimulusCode]) == 'StimulusUserAction' ? UserRights::IsStimulusAllowed($sClass, $sStimulusCode, $oSet) : UR_ALLOWED_NO;
                             switch ($iActionAllowed) {
                                 case UR_ALLOWED_YES:
                                     $aActions[$sStimulusCode] = array('label' => $aStimuli[$sStimulusCode]->GetLabel(), 'url' => "{$sRootUrl}pages/UI.php?operation=stimulus&stimulus={$sStimulusCode}&class={$sClass}&id={$id}{$sContext}");
                                     break;
                                 default:
                                     // Do nothing
                             }
                         }
                     }
                 }
                 // Relations...
                 $aRelations = MetaModel::EnumRelationsEx($sClass);
                 if (count($aRelations)) {
                     $this->AddMenuSeparator($aActions);
                     foreach ($aRelations as $sRelationCode => $aRelationInfo) {
                         if (array_key_exists('down', $aRelationInfo)) {
                             $aActions[$sRelationCode . '_down'] = array('label' => $aRelationInfo['down'], 'url' => "{$sRootUrl}pages/{$sUIPage}?operation=swf_navigator&relation={$sRelationCode}&direction=down&class={$sClass}&id={$id}{$sContext}");
                         }
                         if (array_key_exists('up', $aRelationInfo)) {
                             $aActions[$sRelationCode . '_up'] = array('label' => $aRelationInfo['up'], 'url' => "{$sRootUrl}pages/{$sUIPage}?operation=swf_navigator&relation={$sRelationCode}&direction=up&class={$sClass}&id={$id}{$sContext}");
                         }
                     }
                 }
                 if ($bLocked && $bRawModifiedAllowed) {
                     // Add a special menu to kill the lock, but only to allowed users who can also modify this object
                     $aAllowedProfiles = MetaModel::GetConfig()->Get('concurrent_lock_override_profiles');
                     $bCanKill = false;
                     $oUser = UserRights::GetUserObject();
                     $aUserProfiles = array();
                     if (!is_null($oUser)) {
                         $oProfileSet = $oUser->Get('profile_list');
                         while ($oProfile = $oProfileSet->Fetch()) {
                             $aUserProfiles[$oProfile->Get('profile')] = true;
                         }
                     }
                     foreach ($aAllowedProfiles as $sProfile) {
                         if (array_key_exists($sProfile, $aUserProfiles)) {
                             $bCanKill = true;
                             break;
                         }
                     }
                     if ($bCanKill) {
                         $this->AddMenuSeparator($aActions);
                         $aActions['concurrent_lock_unlock'] = array('label' => Dict::S('UI:Menu:KillConcurrentLock'), 'url' => "{$sRootUrl}pages/{$sUIPage}?operation=kill_lock&class={$sClass}&id={$id}{$sContext}");
                     }
                 }
                 /*
                 $this->AddMenuSeparator($aActions);
                 // Static menus: Email this page & CSV Export
                 $sUrl = ApplicationContext::MakeObjectUrl($sClass, $id);
                 $aActions['UI:Menu:EMail'] = array ('label' => Dict::S('UI:Menu:EMail'), 'url' => "mailto:?subject=".urlencode($oObj->GetRawName())."&body=".urlencode($sUrl));
                 $aActions['UI:Menu:CSVExport'] = array ('label' => Dict::S('UI:Menu:CSVExport'), 'url' => "{$sRootUrl}pages/$sUIPage?operation=search&filter=".urlencode($sFilter)."&format=csv{$sContext}");
                 // The style tells us whether the menu is displayed on a list of one object, or on the details of the given object 
                 if ($this->m_sStyle == 'list')
                 {
                 	// Actions specific to the list
                 	$sOQL = addslashes($sFilterDesc);
                 	$aActions['UI:Menu:AddToDashboard'] = array ('label' => Dict::S('UI:Menu:AddToDashboard'), 'url' => "#", 'onclick' => "return DashletCreationDlg('$sOQL')");
                 }
                 */
             }
             $this->AddMenuSeparator($aActions);
             foreach (MetaModel::EnumPlugins('iApplicationUIExtension') as $oExtensionInstance) {
                 $oSet->Rewind();
                 foreach ($oExtensionInstance->EnumAllowedActions($oSet) as $sLabel => $sUrl) {
                     $aActions[$sLabel] = array('label' => $sLabel, 'url' => $sUrl);
                 }
             }
             break;
         default:
             // Check rights
             // New / Modify
             $bIsModifyAllowed = UserRights::IsActionAllowed($sClass, UR_ACTION_MODIFY, $oSet) && $oReflectionClass->IsSubclassOf('cmdbAbstractObject');
             $bIsBulkModifyAllowed = !MetaModel::IsAbstract($sClass) && UserRights::IsActionAllowed($sClass, UR_ACTION_BULK_MODIFY, $oSet) && $oReflectionClass->IsSubclassOf('cmdbAbstractObject');
             $bIsBulkDeleteAllowed = UserRights::IsActionAllowed($sClass, UR_ACTION_BULK_DELETE, $oSet);
             if (isset($aExtraParams['link_attr'])) {
                 $id = $aExtraParams['object_id'];
                 $sTargetAttr = $aExtraParams['target_attr'];
                 $oAttDef = MetaModel::GetAttributeDef($sClass, $sTargetAttr);
                 $sTargetClass = $oAttDef->GetTargetClass();
                 $bIsDeleteAllowed = UserRights::IsActionAllowed($sClass, UR_ACTION_DELETE, $oSet);
                 if ($bIsModifyAllowed) {
                     $aActions['UI:Menu:Add'] = array('label' => Dict::S('UI:Menu:Add'), 'url' => "{$sRootUrl}pages/{$sUIPage}?operation=modify_links&class={$sClass}&link_attr=" . $aExtraParams['link_attr'] . "&target_class={$sTargetClass}&id={$id}&addObjects=true{$sContext}");
                 }
                 if ($bIsBulkModifyAllowed) {
                     $aActions['UI:Menu:Manage'] = array('label' => Dict::S('UI:Menu:Manage'), 'url' => "{$sRootUrl}pages/{$sUIPage}?operation=modify_links&class={$sClass}&link_attr=" . $aExtraParams['link_attr'] . "&target_class={$sTargetClass}&id={$id}{$sContext}");
                 }
                 //if ($bIsBulkDeleteAllowed) { $aActions[] = array ('label' => 'Remove All...', 'url' => "#"); }
             } else {
                 // many objects in the set, possible actions are: new / modify all / delete all
                 if ($bIsCreationAllowed) {
                     $aActions['UI:Menu:New'] = array('label' => Dict::S('UI:Menu:New'), 'url' => "{$sRootUrl}pages/{$sUIPage}?operation=new&class={$sClass}{$sContext}{$sDefault}");
                 }
                 if ($bIsBulkModifyAllowed) {
                     $aActions['UI:Menu:ModifyAll'] = array('label' => Dict::S('UI:Menu:ModifyAll'), 'url' => "{$sRootUrl}pages/{$sUIPage}?operation=select_for_modify_all&class={$sClass}&filter=" . urlencode($sFilter) . "{$sContext}");
                 }
                 if ($bIsBulkDeleteAllowed) {
                     $aActions['UI:Menu:BulkDelete'] = array('label' => Dict::S('UI:Menu:BulkDelete'), 'url' => "{$sRootUrl}pages/{$sUIPage}?operation=select_for_deletion&filter=" . urlencode($sFilter) . "{$sContext}");
                 }
                 // Stimuli
                 $aStates = MetaModel::EnumStates($sClass);
                 // Do not perform time consuming computations if there are too may objects in the list
                 $iLimit = MetaModel::GetConfig()->Get('complex_actions_limit');
                 if (count($aStates) > 0 && ($iLimit == 0 || $oSet->Count() < $iLimit)) {
                     // Life cycle actions may be available... if all objects are in the same state
                     //
                     // Group by <state>
                     $oGroupByExp = new FieldExpression(MetaModel::GetStateAttributeCode($sClass), $this->m_oFilter->GetClassAlias());
                     $aGroupBy = array('__state__' => $oGroupByExp);
                     $aQueryParams = array();
                     if (isset($aExtraParams['query_params'])) {
                         $aQueryParams = $aExtraParams['query_params'];
                     }
                     $sSql = $this->m_oFilter->MakeGroupByQuery($aQueryParams, $aGroupBy);
                     $aRes = CMDBSource::QueryToArray($sSql);
                     if (count($aRes) == 1) {
                         // All objects are in the same state...
                         $sState = $aRes[0]['__state__'];
                         $aTransitions = Metamodel::EnumTransitions($sClass, $sState);
                         if (count($aTransitions)) {
                             $this->AddMenuSeparator($aActions);
                             $aStimuli = Metamodel::EnumStimuli($sClass);
                             foreach ($aTransitions as $sStimulusCode => $aTransitionDef) {
                                 $oSet->Rewind();
                                 // As soon as the user rights implementation will browse the object set,
                                 // then we might consider using OptimizeColumnLoad() here
                                 $iActionAllowed = UserRights::IsStimulusAllowed($sClass, $sStimulusCode, $oSet);
                                 $iActionAllowed = get_class($aStimuli[$sStimulusCode]) == 'StimulusUserAction' ? $iActionAllowed : UR_ALLOWED_NO;
                                 switch ($iActionAllowed) {
                                     case UR_ALLOWED_YES:
                                     case UR_ALLOWED_DEPENDS:
                                         $aActions[$sStimulusCode] = array('label' => $aStimuli[$sStimulusCode]->GetLabel(), 'url' => "{$sRootUrl}pages/UI.php?operation=select_bulk_stimulus&stimulus={$sStimulusCode}&state={$sState}&class={$sClass}&filter=" . urlencode($sFilter) . "{$sContext}");
                                         break;
                                     default:
                                         // Do nothing
                                 }
                             }
                         }
                     }
                 }
                 /*
                 $this->AddMenuSeparator($aActions);
                 $sUrl = utils::GetAbsoluteUrlAppRoot();
                 $aActions['UI:Menu:EMail'] = array ('label' => Dict::S('UI:Menu:EMail'), 'url' => "mailto:?subject=$sFilterDesc&body=".urlencode("{$sUrl}pages/$sUIPage?operation=search&filter=".urlencode($sFilter)."{$sContext}"));
                 $aActions['UI:Menu:CSVExport'] = array ('label' => Dict::S('UI:Menu:CSVExport'), 'url' => "{$sRootUrl}pages/$sUIPage?operation=search&filter=".urlencode($sFilter)."&format=csv{$sContext}");
                 $sOQL = addslashes($sFilterDesc);
                 $aActions['UI:Menu:AddToDashboard'] = array ('label' => Dict::S('UI:Menu:AddToDashboard'), 'url' => "#", 'onclick' => "return DashletCreationDlg('$sOQL')");
                 */
             }
     }
     $this->AddMenuSeparator($aActions);
     foreach (MetaModel::EnumPlugins('iApplicationUIExtension') as $oExtensionInstance) {
         $oSet->Rewind();
         foreach ($oExtensionInstance->EnumAllowedActions($oSet) as $sLabel => $data) {
             if (is_array($data)) {
                 // New plugins can provide javascript handlers via the 'onclick' property
                 //TODO: enable extension of different menus by checking the 'target' property ??
                 $aActions[$sLabel] = array('label' => $sLabel, 'url' => isset($data['url']) ? $data['url'] : '#', 'onclick' => isset($data['onclick']) ? $data['onclick'] : '');
             } else {
                 // Backward compatibility with old plugins
                 $aActions[$sLabel] = array('label' => $sLabel, 'url' => $data);
             }
         }
     }
     // New extensions based on iPopupMenuItem interface
     switch ($this->m_sStyle) {
         case 'list':
             $oSet->Rewind();
             $param = $oSet;
             $iMenuId = iPopupMenuExtension::MENU_OBJLIST_ACTIONS;
             break;
         case 'details':
             $oSet->Rewind();
             $param = $oSet->Fetch();
             $iMenuId = iPopupMenuExtension::MENU_OBJDETAILS_ACTIONS;
             break;
     }
     utils::GetPopupMenuItems($oPage, $iMenuId, $param, $aActions);
     $aFavoriteActions = array();
     $aCallSpec = array($sClass, 'GetShortcutActions');
     if (is_callable($aCallSpec)) {
         $aShortcutActions = call_user_func($aCallSpec, $sClass);
         foreach ($aActions as $key => $aAction) {
             if (in_array($key, $aShortcutActions)) {
                 $aFavoriteActions[] = $aAction;
                 unset($aActions[$key]);
             }
         }
     } else {
         $aShortcutActions = array();
     }
     if (count($aFavoriteActions) > 0) {
         $sHtml .= "<div class=\"itop_popup actions_menu\"><ul>\n<li>" . Dict::S('UI:Menu:OtherActions') . "\n<ul>\n";
     } else {
         $sHtml .= "<div class=\"itop_popup actions_menu\"><ul>\n<li>" . Dict::S('UI:Menu:Actions') . "\n<ul>\n";
     }
     $sHtml .= $oPage->RenderPopupMenuItems($aActions, $aFavoriteActions);
     static $bPopupScript = false;
     if (!$bPopupScript) {
         // Output this once per page...
         $oPage->add_ready_script("\$(\"div.itop_popup>ul\").popupmenu();\n");
         $bPopupScript = true;
     }
     return $sHtml;
 }
 public function GetSupportedFormats()
 {
     return array('csv' => Dict::S('Core:BulkExport:CSVFormat'));
 }
 /**
  * Describe (as a text string) the modifications corresponding to this change
  */
 public function GetDescription()
 {
     return Dict::S('Change:ObjectDeleted');
 }