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(); } }
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; }
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); }
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') . '"/> <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; }
$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; }
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(); }
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/> <input id="btn_remove_' . $iAttId . '" type="button" class="btn_hidden" value="Delete" onClick="RemoveAttachment(' . $iAttId . ');"/> </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/> <input id="btn_remove_' . $iAttId . '" type="button" class="btn_hidden" value="Delete" onClick="RemoveAttachment(' . $iAttId . ');"/> </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"> <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/> </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; }
\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); }
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); }
/** * 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); }
/** * 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; }
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/> <input id="btn_remove_' . $iAttId . '" type="button" class="btn_hidden" value="Delete" onClick="$(\'#attachment_' . $iAttId . '\').remove();"/> </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/> <input id="btn_remove_' . $iAttId . '" type="button" class="btn_hidden" value="Delete" onClick="RemoveNewAttachment(' . $iAttId . ');"/> </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"> <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/> </div>'); } } } }
/** * 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');\"> "); $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"); }
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} -->"); } }
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; }
$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
/** * 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 .= ' <b>' . $sRestrictions . '</b>'; if (strlen($sAdminMessage) > 0) { $sApplicationBanner .= ' <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> <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(); }
public function GetLabel() { return Dict::S('portal:' . $this->sPortalid); }
/** * 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'); }