function GetRuleResultFilter($iRuleId, $oDefinitionFilter, $oAppContext) { $oRule = MetaModel::GetObject('AuditRule', $iRuleId); $sOql = $oRule->Get('query'); $oRuleFilter = DBObjectSearch::FromOQL($sOql); FilterByContext($oRuleFilter, $oAppContext); // Not needed since this filter is a subset of the definition filter, but may speedup things if ($oRule->Get('valid_flag') == 'false') { // The query returns directly the invalid elements $oFilter = $oRuleFilter->Intersect($oDefinitionFilter); } else { // The query returns only the valid elements, all the others are invalid $aValidRows = $oRuleFilter->ToDataArray(array('id')); $aValidIds = array(); foreach ($aValidRows as $aRow) { $aValidIds[] = $aRow['id']; } $oFilter = $oDefinitionFilter->DeepClone(); if (count($aValidIds) > 0) { $aInDefSet = array(); foreach ($oDefinitionFilter->ToDataArray(array('id')) as $aRow) { $aInDefSet[] = $aRow['id']; } $aInvalids = array_diff($aInDefSet, $aValidIds); if (count($aInvalids) > 0) { $oFilter->AddCondition('id', $aInvalids, 'IN'); } else { $oFilter->AddCondition('id', 0, '='); } } } return $oFilter; }
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; }
/** * Create a User Request ticket from the basic information retrieved from an email * @param string $sSenderEmail eMail address of the sender (From), used to lookup a contact in iTop * @param string $sSubject eMail's subject, will be turned into the title of the ticket * @param string $sBody Body of the email, will be fitted into the ticket's description * @return UserRequest The created ticket, or null if the creation failed for some reason... */ function CreateTicket($sSenderEmail, $sSubject, $sBody) { $oTicket = null; try { $oContactSearch = new DBObjectSearch('Contact'); // Can be either a Person or a Team, but must be a valid Contact $oContactSearch->AddCondition('email', $sSenderEmail, '='); $oSet = new DBObjectSet($oContactSearch); if ($oSet->Count() == 1) { $oContact = $oSet->Fetch(); $oOrganization = MetaModel::GetObject('Organization', $oContact->Get('org_id')); $oTicket = new UserRequest(); $oTicket->Set('title', $sSubject); $oTicket->Set('description', $sBody); $oTicket->Set('org_id', $oOrganization->GetKey()); $oTicket->Set('caller_id', $oContact->GetKey()); $oTicket->Set('impact', DEFAULT_IMPACT); $oTicket->Set('urgency', DEFAULT_URGENCY); $oTicket->Set('product', DEFAULT_PRODUCT); $oTicket->Set('service_id', DEFAULT_SERVICE_ID); // Can be replaced by a search for a valid service for this 'org_id' $oTicket->Set('servicesubcategory_id', DEFAULT_SUBSERVICE_ID); // Same as above... $oTicket->Set('workgroup_id', DEFAULT_WORKGROUP_ID); // Same as above... // Record the change information about the object $oMyChange = MetaModel::NewObject("CMDBChange"); $oMyChange->Set("date", time()); $sUserString = $oContact->GetName() . ', submitted by email'; $oMyChange->Set("userinfo", $sUserString); $iChangeId = $oMyChange->DBInsert(); $oTicket->DBInsertTracked($oMyChange); } else { echo "No contact found in iTop having the email: {$sSenderEmail}, email message ignored.\n"; } } catch (Exception $e) { echo "Error: exception " . $e->getMessage(); $oTicket = null; } return $oTicket; }
/** * Determines the shortest SLT, for this ticket, for the given metric. Returns null is no SLT was found * @param string $sMetric Type of metric 'TTO', 'TTR', etc as defined in the SLT class * @return hash Array with 'SLT' => name of the SLT selected, 'value' => duration in seconds of the SLT metric, null if no SLT applies to this ticket */ protected static function ComputeSLT($oTicket, $sMetric = 'TTO') { $iDeadline = null; if (MetaModel::IsValidClass('SLT')) { $sType = get_class($oTicket); if ($sType == 'Incident') { $sRequestType = 'incident'; } else { $sRequestType = $oTicket->Get('request_type'); } $aArgs = $oTicket->ToArgs(); $aArgs['metric'] = $sMetric; $aArgs['request_type'] = $sRequestType; //echo "<p>Managing:".$sMetric."-".$this->Get('request_type')."-".$this->Get('importance')."</p>\n"; $oSLTSet = new DBObjectSet(DBObjectSearch::FromOQL(RESPONSE_TICKET_SLT_QUERY), array(), $aArgs); $iMinDuration = PHP_INT_MAX; $sSLTName = ''; while ($oSLT = $oSLTSet->Fetch()) { $iDuration = (int) $oSLT->Get('value'); $sUnit = $oSLT->Get('unit'); switch ($sUnit) { case 'days': $iDuration = $iDuration * 24; // 24 hours in 1 days // Fall though // 24 hours in 1 days // Fall though case 'hours': $iDuration = $iDuration * 60; // 60 minutes in 1 hour // Fall though // 60 minutes in 1 hour // Fall though case 'minutes': $iDuration = $iDuration * 60; } if ($iDuration < $iMinDuration) { $iMinDuration = $iDuration; $sSLTName = $oSLT->GetName(); } } if ($iMinDuration == PHP_INT_MAX) { $iDeadline = null; } else { // Store $sSLTName to keep track of which SLT has been used $iDeadline = $iMinDuration; } } return $iDeadline; }
public function Process($iTimeLimit) { $sNow = date('Y-m-d H:i:s'); // Criteria: planned, and expected to occur... ASAP or in the past $sOQL = "SELECT AsyncTask WHERE (status = 'planned') AND (ISNULL(planned) OR (planned < '{$sNow}'))"; $iProcessed = 0; while (time() < $iTimeLimit) { // Next one ? $oSet = new CMDBObjectSet(DBObjectSearch::FromOQL($sOQL), array('created' => true), array(), null, 1); $oTask = $oSet->Fetch(); if (is_null($oTask)) { // Nothing to be done break; } $iProcessed++; if ($oTask->Process()) { $oTask->DBDelete(); } } return "processed {$iProcessed} tasks"; }
public function Process($iTimeLimit) { $oMyChange = new CMDBChange(); $oMyChange->Set("date", time()); $oMyChange->Set("userinfo", "Automatic updates"); $iChangeId = $oMyChange->DBInsertNoReload(); $aReport = array(); $oSet = new DBObjectSet(DBObjectSearch::FromOQL('SELECT ResponseTicket WHERE status = \'new\' AND tto_escalation_deadline <= NOW()')); while (time() < $iTimeLimit && ($oToEscalate = $oSet->Fetch())) { $oToEscalate->ApplyStimulus('ev_timeout'); //$oToEscalate->Set('tto_escalation_deadline', null); $oToEscalate->DBUpdateTracked($oMyChange, true); $aReport['reached TTO ESCALATION deadline'][] = $oToEscalate->Get('ref'); } $oSet = new DBObjectSet(DBObjectSearch::FromOQL('SELECT ResponseTicket WHERE status = \'assigned\' AND ttr_escalation_deadline <= NOW()')); while (time() < $iTimeLimit && ($oToEscalate = $oSet->Fetch())) { $oToEscalate->ApplyStimulus('ev_timeout'); //$oToEscalate->Set('ttr_escalation_deadline', null); $oToEscalate->DBUpdateTracked($oMyChange, true); $aReport['reached TTR ESCALATION deadline'][] = $oToEscalate->Get('ref'); } $oSet = new DBObjectSet(DBObjectSearch::FromOQL('SELECT ResponseTicket WHERE status = \'resolved\' AND closure_deadline <= NOW()')); while (time() < $iTimeLimit && ($oToEscalate = $oSet->Fetch())) { $oToEscalate->ApplyStimulus('ev_close'); //$oToEscalate->Set('closure_deadline', null); $oToEscalate->DBUpdateTracked($oMyChange, true); $aReport['reached closure deadline'][] = $oToEscalate->Get('ref'); } $aStringReport = array(); foreach ($aReport as $sOperation => $aTicketRefs) { if (count($aTicketRefs) > 0) { $aStringReport[] = $sOperation . ': ' . count($aTicketRefs) . ' {' . implode(', ', $aTicketRefs) . '}'; } } if (count($aStringReport) == 0) { return "No ticket to process"; } else { return "Some tickets reached the limit - " . implode('; ', $aStringReport); } }
public function ReloadState() { if ($this->sToken == null) { throw new Exception('ExcelExporter not initialized with a token, cannot reload state'); } if (!file_exists($this->GetStateFile())) { throw new Exception("ExcelExporter: missing status file '" . $this->GetStateFile() . "', cannot reload state."); } $sJson = file_get_contents($this->GetStateFile()); $aState = json_decode($sJson, true); if ($aState === null) { throw new Exception("ExcelExporter:corrupted status file '" . $this->GetStateFile() . "', not a JSON, cannot reload state."); } $this->sState = $aState['state']; $this->aStatistics = $aState['statistics']; $this->oSearch = DBObjectSearch::unserialize($aState['filter']); $this->iPosition = $aState['position']; $this->iChunkSize = $aState['chunk_size']; $this->aObjectsIDs = $aState['object_ids']; $this->sOutputFilePath = $aState['output_file_path']; $this->bAdvancedMode = $aState['advanced_mode']; }
/** * Handler called after the creation/update of the database schema * @param $oConfiguration Config The new configuration of the application * @param $sPreviousVersion string PRevious version number of the module (empty string in case of first install) * @param $sCurrentVersion string Current version number of the module */ public static function AfterDatabaseCreation(Config $oConfiguration, $sPreviousVersion, $sCurrentVersion) { // For each record having item_org_id unset, // get the org_id from the container object // // Prerequisite: change null into 0 (workaround to the fact that we cannot use IS NULL in OQL) SetupPage::log_info("Initializing attachment/item_org_id - null to zero"); $sTableName = MetaModel::DBGetTable('Attachment'); $sRepair = "UPDATE `{$sTableName}` SET `item_org_id` = 0 WHERE `item_org_id` IS NULL"; CMDBSource::Query($sRepair); SetupPage::log_info("Initializing attachment/item_org_id - zero to the container"); $oSearch = DBObjectSearch::FromOQL("SELECT Attachment WHERE item_org_id = 0"); $oSet = new DBObjectSet($oSearch); $iUpdated = 0; while ($oAttachment = $oSet->Fetch()) { $oContainer = MetaModel::GetObject($oAttachment->Get('item_class'), $oAttachment->Get('item_id'), false, true); if ($oContainer) { $oAttachment->SetItem($oContainer, true); $iUpdated++; } } SetupPage::log_info("Initializing attachment/item_org_id - {$iUpdated} records have been adjusted"); }
/** * Checks the parameters and returns the appropriate exporter (if any) * @param string $sExpression The OQL query to export or null * @param string $sQueryId The entry in the query phrasebook if $sExpression is null * @param string $sFormat The code of export format: csv, pdf, html, xlsx * @throws MissingQueryArgument * @return Ambigous <iBulkExport, NULL> */ function CheckParameters($sExpression, $sQueryId, $sFormat) { $oExporter = null; if ($sExpression === null && $sQueryId === null) { ReportErrorAndUsage("Missing parameter. The parameter 'expression' or 'query' must be specified."); } // Either $sExpression or $sQueryId must be specified if ($sExpression === 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 = $oQuery->Get('fields'); if (strlen($sFields) == 0) { $sFields = trim($oQuery->Get('fields')); } } else { ReportErrorAndExit("Invalid query phrasebook identifier: '{$sQueryId}'"); } } if ($sFormat === null) { ReportErrorAndUsage("Missing parameter 'format'."); } // Check if the supplied query is valid (and all the parameters are supplied try { $oSearch = DBObjectSearch::FromOQL($sExpression); $aArgs = array(); foreach ($oSearch->GetQueryParams() as $sParam => $foo) { $value = utils::ReadParam('arg_' . $sParam, null, true, 'raw_data'); if (!is_null($value)) { $aArgs[$sParam] = $value; } else { throw new MissingQueryArgument("Missing parameter '--arg_{$sParam}'"); } } $oSearch->SetInternalParams($aArgs); $sFormat = utils::ReadParam('format', 'html', true, 'raw_data'); $oExporter = BulkExport::FindExporter($sFormat, $oSearch); if ($oExporter == null) { $aSupportedFormats = BulkExport::FindSupportedFormats(); ReportErrorAndExit("Invalid output format: '{$sFormat}'. The supported formats are: " . implode(', ', array_keys($aSupportedFormats))); } } catch (MissingQueryArgument $e) { ReportErrorAndUsage("Invalid OQL query: '{$sExpression}'.\n" . $e->getMessage()); } catch (OQLException $e) { ReportErrorAndExit("Invalid OQL query: '{$sExpression}'.\n" . $e->getMessage()); } catch (Exception $e) { ReportErrorAndExit($e->getMessage()); } $oExporter->SetFormat($sFormat); $oExporter->SetChunkSize(EXPORTER_DEFAULT_CHUNK_SIZE); $oExporter->SetObjectList($oSearch); $oExporter->ReadParameters(); return $oExporter; }
/** * Describe (as a text string) the modifications corresponding to this change */ public function GetDescription() { // Temporary, until we change the options of GetDescription() -needs a more global revision $bIsHtml = true; $sResult = ''; $sTargetObjectClass = 'Attachment'; $iTargetObjectKey = $this->Get('attachment_id'); $sFilename = htmlentities($this->Get('filename'), ENT_QUOTES, 'UTF-8'); $oTargetSearch = new DBObjectSearch($sTargetObjectClass); $oTargetSearch->AddCondition('id', $iTargetObjectKey, '='); $oMonoObjectSet = new DBObjectSet($oTargetSearch); if ($oMonoObjectSet->Count() > 0) { $oAttachment = $oMonoObjectSet->Fetch(); $oDoc = $oAttachment->Get('contents'); $sPreview = $oDoc->IsPreviewAvailable() ? 'data-preview="true"' : ''; $sResult = Dict::Format('Attachments:History_File_Added', '<span class="attachment-history-added attachment"><a ' . $sPreview . ' target="_blank" href="' . $oDoc->GetDownloadURL($sTargetObjectClass, $iTargetObjectKey, 'contents') . '">' . $sFilename . '</a></span>'); } else { $sResult = Dict::Format('Attachments:History_File_Added', '<span class="attachment-history-deleted">' . $sFilename . '</span>'); } return $sResult; }
/** * throws an exception in case of a wrong syntax */ public function __construct($sOQL, ModelReflection $oModelReflection) { $this->oFilter = DBObjectSearch::FromOQL($sOQL); }
$oFilter = new DBObjectSearch($sClass); foreach ($aFullTextNeedles as $sSearchText) { $oFilter->AddCondition_FullText($sSearchText); } $oSet = new DBObjectSet($oFilter); $oPage->add("<div class=\"page_header\">\n"); $oPage->add("<h2>" . MetaModel::GetClassIcon($sClass) . " <span class=\"hilite\">" . Dict::Format('UI:Search:Count_ObjectsOf_Class_Found', $oSet->Count(), Metamodel::GetName($sClass)) . "</h2>\n"); $oPage->add("</div>\n"); if ($oSet->Count() > 0) { $aLeafs = array(); while ($oObj = $oSet->Fetch()) { if (get_class($oObj) == $sClass) { $aLeafs[] = $oObj->GetKey(); } } $oLeafsFilter = new DBObjectSearch($sClass); if (count($aLeafs) > 0) { $oLeafsFilter->AddCondition('id', $aLeafs, 'IN'); $oBlock = new DisplayBlock($oLeafsFilter, 'list', false); $sBlockId = 'global_search_' . $sClass; $oPage->add('<div id="' . $sBlockId . '">'); $oBlock->RenderContent($oPage, array('table_id' => $sBlockId, 'currentId' => $sBlockId)); $oPage->add('</div>'); $oPage->P(' '); // Some space ? // Hide "no object found" $oPage->add_ready_script('$("#no_object_found").hide();'); } } $oPage->add_ready_script(<<<EOF \$('#full_text_indicator').hide();
public function PopulateChildMenus() { // Load user shortcuts in DB // $oBMSearch = new DBObjectSearch('Shortcut'); $oBMSearch->AddCondition('user_id', UserRights::GetUserId(), '='); $oBMSet = new DBObjectSet($oBMSearch, array('friendlyname' => true)); // ascending on friendlyname $fRank = 1; while ($oShortcut = $oBMSet->Fetch()) { $sName = $this->GetMenuId() . '_' . $oShortcut->GetKey(); $oShortcutMenu = new ShortcutMenuNode($sName, $oShortcut, $this->GetIndex(), $fRank++); } // Complete the tree // parent::PopulateChildMenus(); }
public function Process($iTimeLimit) { $aList = array(); foreach (MetaModel::GetClasses() as $sClass) { foreach (MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef) { if ($oAttDef instanceof AttributeStopWatch) { foreach ($oAttDef->ListThresholds() as $iThreshold => $aThresholdData) { $iPercent = $aThresholdData['percent']; // could be different than the index ! $sNow = date('Y-m-d H:i:s'); $sExpression = "SELECT {$sClass} WHERE {$sAttCode}_laststart AND {$sAttCode}_{$iThreshold}_triggered = 0 AND {$sAttCode}_{$iThreshold}_deadline < '{$sNow}'"; $oFilter = DBObjectSearch::FromOQL($sExpression); $oSet = new DBObjectSet($oFilter); while (time() < $iTimeLimit && ($oObj = $oSet->Fetch())) { $sClass = get_class($oObj); $aList[] = $sClass . '::' . $oObj->GetKey() . ' ' . $sAttCode . ' ' . $iThreshold; // Execute planned actions // foreach ($aThresholdData['actions'] as $aActionData) { $sVerb = $aActionData['verb']; $aParams = $aActionData['params']; $aValues = array(); foreach ($aParams as $def) { if (is_string($def)) { // Old method (pre-2.1.0) non typed parameters $aValues[] = $def; } else { $sParamType = array_key_exists('type', $def) ? $def['type'] : 'string'; switch ($sParamType) { case 'int': $value = (int) $def['value']; break; case 'float': $value = (double) $def['value']; break; case 'bool': $value = (bool) $def['value']; break; case 'reference': $value = ${$def['value']}; break; case 'string': default: $value = (string) $def['value']; } $aValues[] = $value; } } $aCallSpec = array($oObj, $sVerb); call_user_func_array($aCallSpec, $aValues); } // Mark the threshold as "triggered" // $oSW = $oObj->Get($sAttCode); $oSW->MarkThresholdAsTriggered($iThreshold); $oObj->Set($sAttCode, $oSW); if ($oObj->IsModified()) { CMDBObject::SetTrackInfo("Automatic - threshold triggered"); $oMyChange = CMDBObject::GetCurrentChange(); $oObj->DBUpdateTracked($oMyChange, true); } // Activate any existing trigger // $sClassList = implode("', '", MetaModel::EnumParentClasses($sClass, ENUM_PARENT_CLASSES_ALL)); $oTriggerSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT TriggerOnThresholdReached AS t WHERE t.target_class IN ('{$sClassList}') AND stop_watch_code=:stop_watch_code AND threshold_index = :threshold_index"), array(), array('stop_watch_code' => $sAttCode, 'threshold_index' => $iThreshold)); while ($oTrigger = $oTriggerSet->Fetch()) { $oTrigger->DoActivate($oObj->ToArgs('this')); } } } } } } $iProcessed = count($aList); return "Triggered {$iProcessed} threshold(s):" . implode(", ", $aList); }
public function GetAllowedValuesAsObjectSet($aArgs = array(), $sContains = '') { $oValSetDef = $this->GetValuesDef(); if (array_key_exists('this', $aArgs)) { // Hierarchical keys have one more constraint: the "parent value" cannot be // "under" themselves $iRootId = $aArgs['this']->GetKey(); if ($iRootId > 0) { $aValuesSetDef = $this->GetValuesDef(); $sClass = $this->m_sTargetClass; $oFilter = DBObjectSearch::FromOQL("SELECT {$sClass} AS node JOIN {$sClass} AS root ON node." . $this->GetCode() . " NOT BELOW root.id WHERE root.id = {$iRootId}"); $oValSetDef->AddCondition($oFilter); } } $oSet = $oValSetDef->ToObjectSet($aArgs, $sContains); return $oSet; }
protected static function UpdateAttachments($oObject, $oChange = null) { self::$m_bIsModified = false; if (utils::ReadParam('attachment_plugin', 'not-in-form') == 'not-in-form') { // Workaround to an issue in iTop < 2.0 // Leave silently if there is no trace of the attachment form return; } $iTransactionId = utils::ReadParam('transaction_id', null); if (!is_null($iTransactionId)) { $aActions = array(); $aAttachmentIds = utils::ReadParam('attachments', array()); // Get all current attachments $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())); while ($oAttachment = $oSet->Fetch()) { // Remove attachments that are no longer attached to the current object if (!in_array($oAttachment->GetKey(), $aAttachmentIds)) { $oAttachment->DBDelete(); $aActions[] = self::GetActionDescription($oAttachment, false); } } // Attach new (temporary) attachements $sTempId = session_id() . '_' . $iTransactionId; // The object is being created from a form, check if there are pending attachments // for this object, but deleting the "new" ones that were already removed from the form $aRemovedAttachmentIds = utils::ReadParam('removed_attachments', array()); $sOQL = 'SELECT Attachment WHERE temp_id = :temp_id'; $oSearch = DBObjectSearch::FromOQL($sOQL); foreach ($aAttachmentIds as $iAttachmentId) { $oSet = new DBObjectSet($oSearch, array(), array('temp_id' => $sTempId)); while ($oAttachment = $oSet->Fetch()) { if (in_array($oAttachment->GetKey(), $aRemovedAttachmentIds)) { $oAttachment->DBDelete(); // temporary attachment removed, don't even mention it in the history } else { $oAttachment->SetItem($oObject); $oAttachment->Set('temp_id', ''); $oAttachment->DBUpdate(); // temporary attachment confirmed, list it in the history $aActions[] = self::GetActionDescription($oAttachment, true); } } } if (count($aActions) > 0) { if ($oChange == null) { // Let's create a change if non is supplied $oChange = MetaModel::NewObject("CMDBChange"); $oChange->Set("date", time()); $sUserString = CMDBChange::GetCurrentUserName(); $oChange->Set("userinfo", $sUserString); $iChangeId = $oChange->DBInsert(); } foreach ($aActions as $sActionDescription) { self::RecordHistory($oChange, $oObject, $sActionDescription); } self::$m_bIsModified = true; } } }
/** * Updates the object form POSTED arguments, and writes it into the DB (applies a stimuli if requested) * @param DBObject $oObj The object to update * $param array $aAttList If set, this will limit the list of updated attributes * @return void */ public function DoUpdateObjectFromPostedForm(DBObject $oObj, $aAttList = null) { $sTransactionId = utils::ReadPostedParam('transaction_id', ''); if (!utils::IsTransactionValid($sTransactionId)) { throw new TransactionException(); } $sClass = get_class($oObj); $sStimulus = trim(utils::ReadPostedParam('apply_stimulus', '')); $sTargetState = ''; if (!empty($sStimulus)) { // Compute the target state $aTransitions = $oObj->EnumTransitions(); if (!isset($aTransitions[$sStimulus])) { throw new ApplicationException(Dict::Format('UI:Error:Invalid_Stimulus_On_Object_In_State', $sStimulus, $oObj->GetName(), $oObj->GetStateLabel())); } $sTargetState = $aTransitions[$sStimulus]['target_state']; } $oObj->UpdateObjectFromPostedForm('', $aAttList, $sTargetState); // Optional: apply a stimulus // if (!empty($sStimulus)) { if (!$oObj->ApplyStimulus($sStimulus)) { throw new Exception("Cannot apply stimulus '{$sStimulus}' to {$oObj->GetName()}"); } } if ($oObj->IsModified()) { // Record the change // $oObj->DBUpdate(); // Trigger ? // $aClasses = MetaModel::EnumParentClasses($sClass, ENUM_PARENT_CLASSES_ALL); $sClassList = implode(", ", CMDBSource::Quote($aClasses)); $oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT TriggerOnPortalUpdate AS t WHERE t.target_class IN ({$sClassList})")); while ($oTrigger = $oSet->Fetch()) { $oTrigger->DoActivate($oObj->ToArgs('this')); } $this->p("<h1>" . Dict::Format('UI:Class_Object_Updated', MetaModel::GetName(get_class($oObj)), $oObj->GetName()) . "</h1>\n"); } $bLockEnabled = MetaModel::GetConfig()->Get('concurrent_lock_enabled'); if ($bLockEnabled) { // Release the concurrent lock, if any $sOwnershipToken = utils::ReadPostedParam('ownership_token', null, false, 'raw_data'); if ($sOwnershipToken !== null) { // We're done, let's release the lock iTopOwnershipLock::ReleaseLock(get_class($oObj), $oObj->GetKey(), $sOwnershipToken); } } }
/** * 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 GetSQLQuery($aOrderBy, $aArgs, $aAttToLoad, $aExtendedDataSpec, $iLimitCount, $iLimitStart, $bGetCount, $aGroupByExpr = null) { // Hide objects that are not visible to the current user // $oSearch = $this; if (!$this->IsAllDataAllowed() && !$this->IsDataFiltered()) { $oVisibleObjects = UserRights::GetSelectFilter($this->GetClass(), $this->GetModifierProperties('UserRightsGetSelectFilter')); if ($oVisibleObjects === false) { // Make sure this is a valid search object, saying NO for all $oVisibleObjects = DBObjectSearch::FromEmptySet($this->GetClass()); } if (is_object($oVisibleObjects)) { $oSearch = $this->Intersect($oVisibleObjects); $oSearch->SetDataFiltered(); } else { // should be true at this point, meaning that no additional filtering // is required } } // Compute query modifiers properties (can be set in the search itself, by the context, etc.) // $aModifierProperties = MetaModel::MakeModifierProperties($oSearch); // Create a unique cache id // if (self::$m_bQueryCacheEnabled || self::$m_bTraceQueries) { // Need to identify the query $sOqlQuery = $oSearch->ToOql(); if (count($aModifierProperties)) { array_multisort($aModifierProperties); $sModifierProperties = json_encode($aModifierProperties); } else { $sModifierProperties = ''; } $sRawId = $sOqlQuery . $sModifierProperties; if (!is_null($aAttToLoad)) { $sRawId .= json_encode($aAttToLoad); } if (!is_null($aGroupByExpr)) { foreach ($aGroupByExpr as $sAlias => $oExpr) { $sRawId .= 'g:' . $sAlias . '!' . $oExpr->Render(); } } $sRawId .= $bGetCount; $sOqlId = md5($sRawId); } else { $sOqlQuery = "SELECTING... " . $oSearch->GetClass(); $sOqlId = "query id ? n/a"; } // Query caching // if (self::$m_bQueryCacheEnabled) { // Warning: using directly the query string as the key to the hash array can FAIL if the string // is long and the differences are only near the end... so it's safer (but not bullet proof?) // to use a hash (like md5) of the string as the key ! // // Example of two queries that were found as similar by the hash array: // SELECT SLT JOIN lnkSLTToSLA AS L1 ON L1.slt_id=SLT.id JOIN SLA ON L1.sla_id = SLA.id JOIN lnkContractToSLA AS L2 ON L2.sla_id = SLA.id JOIN CustomerContract ON L2.contract_id = CustomerContract.id WHERE SLT.ticket_priority = 1 AND SLA.service_id = 3 AND SLT.metric = 'TTO' AND CustomerContract.customer_id = 2 // and // SELECT SLT JOIN lnkSLTToSLA AS L1 ON L1.slt_id=SLT.id JOIN SLA ON L1.sla_id = SLA.id JOIN lnkContractToSLA AS L2 ON L2.sla_id = SLA.id JOIN CustomerContract ON L2.contract_id = CustomerContract.id WHERE SLT.ticket_priority = 1 AND SLA.service_id = 3 AND SLT.metric = 'TTR' AND CustomerContract.customer_id = 2 // the only difference is R instead or O at position 285 (TTR instead of TTO)... // if (array_key_exists($sOqlId, self::$m_aQueryStructCache)) { // hit! $oSQLQuery = unserialize(serialize(self::$m_aQueryStructCache[$sOqlId])); // Note: cloning is not enough because the subtree is made of objects } elseif (self::$m_bUseAPCCache) { // Note: For versions of APC older than 3.0.17, fetch() accepts only one parameter // $sOqlAPCCacheId = 'itop-' . MetaModel::GetEnvironmentId() . '-query-cache-' . $sOqlId; $oKPI = new ExecutionKPI(); $result = apc_fetch($sOqlAPCCacheId); $oKPI->ComputeStats('Query APC (fetch)', $sOqlQuery); if (is_object($result)) { $oSQLQuery = $result; self::$m_aQueryStructCache[$sOqlId] = $oSQLQuery; } } } if (!isset($oSQLQuery)) { $oKPI = new ExecutionKPI(); $oSQLQuery = $oSearch->MakeSQLQuery($aAttToLoad, $bGetCount, $aModifierProperties, $aGroupByExpr); $oSQLQuery->SetSourceOQL($sOqlQuery); $oKPI->ComputeStats('MakeSQLQuery', $sOqlQuery); if (self::$m_bQueryCacheEnabled) { if (self::$m_bUseAPCCache) { $oKPI = new ExecutionKPI(); apc_store($sOqlAPCCacheId, $oSQLQuery, self::$m_iQueryCacheTTL); $oKPI->ComputeStats('Query APC (store)', $sOqlQuery); } self::$m_aQueryStructCache[$sOqlId] = $oSQLQuery->DeepClone(); } } // Join to an additional table, if required... // if ($aExtendedDataSpec != null) { $sTableAlias = '_extended_data_'; $aExtendedFields = array(); foreach ($aExtendedDataSpec['fields'] as $sColumn) { $sColRef = $oSearch->GetClassAlias() . '_extdata_' . $sColumn; $aExtendedFields[$sColRef] = new FieldExpressionResolved($sColumn, $sTableAlias); } $oSQLQueryExt = new SQLObjectQuery($aExtendedDataSpec['table'], $sTableAlias, $aExtendedFields); $oSQLQuery->AddInnerJoin($oSQLQueryExt, 'id', $aExtendedDataSpec['join_key']); } return $oSQLQuery; }
protected function _SearchObjects($sOQL) { $oRes = new WebServiceResult(); try { $oSearch = DBObjectSearch::FromOQL($sOQL); $oSet = new DBObjectSet($oSearch); $aData = $oSet->ToArrayOfValues(); foreach ($aData as $iRow => $aRow) { $oRes->AddResultRow("row_{$iRow}", $aRow); } } catch (CoreException $e) { $oRes->LogError($e->getMessage()); } catch (Exception $e) { $oRes->LogError($e->getMessage()); } $this->LogUsage(__FUNCTION__, $oRes); return $oRes; }
} $sDefaultKeys = '"' . implode('", "', $aDefaultKeys) . '"'; } $oPage->add_ready_script(<<<EOF \t\t\$('select[name^=field]').change( DoCheckMapping ); \t\taDefaultKeys = new Array({$sDefaultKeys}); \t\tDoCheckMapping(); EOF ); } break; case 'get_csv_template': $sClassName = utils::ReadParam('class_name'); $sFormat = utils::ReadParam('format', 'csv'); if (MetaModel::IsValidClass($sClassName)) { $oSearch = new DBObjectSearch($sClassName); $oSearch->AddCondition('id', 0, '='); // Make sure we create an empty set $oSet = new CMDBObjectSet($oSearch); $sResult = cmdbAbstractObject::GetSetAsCSV($oSet, array('showMandatoryFields' => true)); $sClassDisplayName = MetaModel::GetName($sClassName); $sDisposition = utils::ReadParam('disposition', 'inline'); if ($sDisposition == 'attachment') { switch ($sFormat) { case 'xlsx': $oPage = new ajax_page(""); $oPage->SetContentType('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'); $oPage->SetContentDisposition('attachment', $sClassDisplayName . '.xlsx'); require_once APPROOT . '/application/excelexporter.class.inc.php'; $writer = new XLSXWriter(); $writer->setAuthor(UserRights::GetUserFriendlyName());
/** * Determine if there is a redundancy (or use the existing one) and add the corresponding nodes/edges */ protected function ComputeRedundancy($sRelCode, $aQueryInfo, $oFromNode, $oToNode) { $oRedundancyNode = null; $oObject = $oToNode->GetProperty('object'); if ($this->IsRedundancyEnabled($sRelCode, $aQueryInfo, $oToNode)) { $sId = RelationRedundancyNode::MakeId($sRelCode, $aQueryInfo['sNeighbour'], $oToNode->GetProperty('object')); $oRedundancyNode = $this->GetNode($sId); if (is_null($oRedundancyNode)) { // Get the upper neighbours $sQuery = $aQueryInfo['sQueryUp']; try { $oFlt = DBObjectSearch::FromOQL($sQuery); $oObjSet = new DBObjectSet($oFlt, array(), $oObject->ToArgsForQuery()); $iCount = $oObjSet->Count(); } catch (Exception $e) { throw new Exception("Wrong query (upstream) for the relation {$sRelCode}/{$aQueryInfo['sDefinedInClass']}/{$aQueryInfo['sNeighbour']}: " . $e->getMessage()); } $iMinUp = $this->GetRedundancyMinUp($sRelCode, $aQueryInfo, $oToNode, $iCount); $fThreshold = max(0, $iCount - $iMinUp); $oRedundancyNode = new RelationRedundancyNode($this, $sId, $iMinUp, $fThreshold); new RelationEdge($this, $oRedundancyNode, $oToNode); while ($oUpperObj = $oObjSet->Fetch()) { $sObjectRef = RelationObjectNode::MakeId($oUpperObj); $oUpperNode = $this->GetNode($sObjectRef); if (is_null($oUpperNode)) { $oUpperNode = new RelationObjectNode($this, $oUpperObj); } new RelationEdge($this, $oUpperNode, $oRedundancyNode); } } } return $oRedundancyNode; }
/** * Do the synchronization job #3: Delete replica depending on the obsolescence scheme * @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 DoJob3($iMaxReplica = null, $iCurrPos = -1) { $sDeletePolicy = $this->m_oDataSource->Get('delete_policy'); if ($sDeletePolicy != 'update_then_delete') { // Job complete! $this->m_oStatLog->Set('status_curr_job', 0); $this->m_oStatLog->Set('status_curr_pos', -1); return false; } $bFirstPass = $iCurrPos == -1; // Get all the replicas that are to be deleted // $oDeletionDate = $this->m_oLastFullLoadStartDate; $iDeleteRetention = $this->m_oDataSource->Get('delete_policy_retention'); // Duration in seconds if ($iDeleteRetention > 0) { $sInterval = "-{$iDeleteRetention} seconds"; $oDeletionDate->Modify($sInterval); } $sDeletionDate = $oDeletionDate->Format('Y-m-d H:i:s'); if ($bFirstPass) { $this->m_oStatLog->AddTrace("Deletion date: {$sDeletionDate}"); } $sSelectToDelete = "SELECT SynchroReplica WHERE id > :curr_pos AND sync_source_id = :source_id AND status IN ('obsolete') AND status_last_seen < :last_import"; $oSetScope = new DBObjectSet(DBObjectSearch::FromOQL($sSelectToDelete), array(), array('source_id' => $this->m_oDataSource->GetKey(), 'last_import' => $sDeletionDate, 'curr_pos' => $iCurrPos)); $iCountScope = $oSetScope->Count(); 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($sSelectToDelete), array('id' => true), array('source_id' => $this->m_oDataSource->GetKey(), 'last_import' => $sDeletionDate, 'curr_pos' => $iCurrPos)); $oSetToProcess->SetLimit($iMaxReplica); } else { $oSetToProcess = $oSetScope; } $iLastReplicaProcessed = -1; while ($oReplica = $oSetToProcess->Fetch()) { $iLastReplicaProcessed = $oReplica->GetKey(); $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; } } // Job complete! $this->m_oStatLog->Set('status_curr_job', 0); $this->m_oStatLog->Set('status_curr_pos', -1); return false; }
protected function DeleteConnectedNetworkDevice() { // The device might be already deleted (reentrance in the current procedure when both device are NETWORK devices!) $oDevice = MetaModel::GetObject('ConnectableCI', $this->Get('connectableci_id'), false); if (is_object($oDevice) && get_class($oDevice) == 'NetworkDevice') { // Track and delete the counterpart link $sOQL = "SELECT lnkConnectableCIToNetworkDevice WHERE connectableci_id = :device AND networkdevice_id = :network AND network_port = :nwport AND device_port = :devport"; $oConnectionSet = new DBObjectSet(DBObjectSearch::FromOQL($sOQL), array(), array('network' => $this->Get('connectableci_id'), 'device' => $this->Get('networkdevice_id'), 'devport' => $this->Get('network_port'), 'nwport' => $this->Get('device_port'))); // There should be one link - do it in a safe manner anyway while ($oConnection = $oConnectionSet->Fetch()) { $oConnection->DBDelete(); } } }
/** * Perform all the needed checks to delete one (or more) objects */ public static function DeleteObjects(WebPage $oP, $sClass, $aObjects, $bPreview, $sCustomOperation, $aContextData = array()) { $oDeletionPlan = new DeletionPlan(); foreach ($aObjects as $oObj) { if ($bPreview) { $oObj->CheckToDelete($oDeletionPlan); } else { $oObj->DBDeleteTracked(CMDBObject::GetCurrentChange(), null, $oDeletionPlan); } } if ($bPreview) { if (count($aObjects) == 1) { $oObj = $aObjects[0]; $oP->add("<h1>" . Dict::Format('UI:Delete:ConfirmDeletionOf_Name', $oObj->GetName()) . "</h1>\n"); } else { $oP->add("<h1>" . Dict::Format('UI:Delete:ConfirmDeletionOf_Count_ObjectsOf_Class', count($aObjects), MetaModel::GetName($sClass)) . "</h1>\n"); } // Explain what should be done // $aDisplayData = array(); foreach ($oDeletionPlan->ListDeletes() as $sTargetClass => $aDeletes) { foreach ($aDeletes as $iId => $aData) { $oToDelete = $aData['to_delete']; $bAutoDel = $aData['mode'] == DEL_SILENT || $aData['mode'] == DEL_AUTO; if (array_key_exists('issue', $aData)) { if ($bAutoDel) { if (isset($aData['requested_explicitely'])) { $sConsequence = Dict::Format('UI:Delete:CannotDeleteBecause', $aData['issue']); } else { $sConsequence = Dict::Format('UI:Delete:ShouldBeDeletedAtomaticallyButNotPossible', $aData['issue']); } } else { $sConsequence = Dict::Format('UI:Delete:MustBeDeletedManuallyButNotPossible', $aData['issue']); } } else { if ($bAutoDel) { if (isset($aData['requested_explicitely'])) { $sConsequence = ''; // not applicable } else { $sConsequence = Dict::S('UI:Delete:WillBeDeletedAutomatically'); } } else { $sConsequence = Dict::S('UI:Delete:MustBeDeletedManually'); } } $aDisplayData[] = array('class' => MetaModel::GetName(get_class($oToDelete)), 'object' => $oToDelete->GetHyperLink(), 'consequence' => $sConsequence); } } foreach ($oDeletionPlan->ListUpdates() as $sRemoteClass => $aToUpdate) { foreach ($aToUpdate as $iId => $aData) { $oToUpdate = $aData['to_reset']; if (array_key_exists('issue', $aData)) { $sConsequence = Dict::Format('UI:Delete:CannotUpdateBecause_Issue', $aData['issue']); } else { $sConsequence = Dict::Format('UI:Delete:WillAutomaticallyUpdate_Fields', $aData['attributes_list']); } $aDisplayData[] = array('class' => MetaModel::GetName(get_class($oToUpdate)), 'object' => $oToUpdate->GetHyperLink(), 'consequence' => $sConsequence); } } $iImpactedIndirectly = $oDeletionPlan->GetTargetCount() - count($aObjects); if ($iImpactedIndirectly > 0) { if (count($aObjects) == 1) { $oObj = $aObjects[0]; $oP->p(Dict::Format('UI:Delete:Count_Objects/LinksReferencing_Object', $iImpactedIndirectly, $oObj->GetName())); } else { $oP->p(Dict::Format('UI:Delete:Count_Objects/LinksReferencingTheObjects', $iImpactedIndirectly)); } $oP->p(Dict::S('UI:Delete:ReferencesMustBeDeletedToEnsureIntegrity')); } if ($iImpactedIndirectly > 0 || $oDeletionPlan->FoundStopper()) { $aDisplayConfig = array(); $aDisplayConfig['class'] = array('label' => 'Class', 'description' => ''); $aDisplayConfig['object'] = array('label' => 'Object', 'description' => ''); $aDisplayConfig['consequence'] = array('label' => 'Consequence', 'description' => Dict::S('UI:Delete:Consequence+')); $oP->table($aDisplayConfig, $aDisplayData); } if ($oDeletionPlan->FoundStopper()) { if ($oDeletionPlan->FoundSecurityIssue()) { $oP->p(Dict::S('UI:Delete:SorryDeletionNotAllowed')); } elseif ($oDeletionPlan->FoundManualOperation()) { $oP->p(Dict::S('UI:Delete:PleaseDoTheManualOperations')); } else { $oP->p(Dict::S('UI:Delete:PleaseDoTheManualOperations')); } $oAppContext = new ApplicationContext(); $oP->add("<form method=\"post\">\n"); $oP->add("<input type=\"hidden\" name=\"transaction_id\" value=\"" . utils::ReadParam('transaction_id') . "\">\n"); $oP->add("<input type=\"button\" onclick=\"window.history.back();\" value=\"" . Dict::S('UI:Button:Back') . "\">\n"); $oP->add("<input DISABLED type=\"submit\" name=\"\" value=\"" . Dict::S('UI:Button:Delete') . "\">\n"); $oP->add($oAppContext->GetForForm()); $oP->add("</form>\n"); } else { if (count($aObjects) == 1) { $oObj = $aObjects[0]; $id = $oObj->GetKey(); $oP->p('<h1>' . Dict::Format('UI:Delect:Confirm_Object', $oObj->GetHyperLink()) . '</h1>'); } else { $oP->p('<h1>' . Dict::Format('UI:Delect:Confirm_Count_ObjectsOf_Class', count($aObjects), MetaModel::GetName($sClass)) . '</h1>'); } foreach ($aObjects as $oObj) { $aKeys[] = $oObj->GetKey(); } $oFilter = new DBObjectSearch($sClass); $oFilter->AddCondition('id', $aKeys, 'IN'); $oSet = new CMDBobjectSet($oFilter); $oP->add('<div id="0">'); CMDBAbstractObject::DisplaySet($oP, $oSet, array('display_limit' => false, 'menu' => false)); $oP->add("</div>\n"); $oP->add("<form method=\"post\">\n"); foreach ($aContextData as $sKey => $value) { $oP->add("<input type=\"hidden\" name=\"{$sKey}\" value=\"{$value}\">\n"); } $oP->add("<input type=\"hidden\" name=\"transaction_id\" value=\"" . utils::GetNewTransactionId() . "\">\n"); $oP->add("<input type=\"hidden\" name=\"operation\" value=\"{$sCustomOperation}\">\n"); $oP->add("<input type=\"hidden\" name=\"filter\" value=\"" . $oFilter->Serialize() . "\">\n"); $oP->add("<input type=\"hidden\" name=\"class\" value=\"{$sClass}\">\n"); foreach ($aObjects as $oObj) { $oP->add("<input type=\"hidden\" name=\"selectObject[]\" value=\"" . $oObj->GetKey() . "\">\n"); } $oP->add("<input type=\"button\" onclick=\"window.history.back();\" value=\"" . Dict::S('UI:Button:Back') . "\">\n"); $oP->add("<input type=\"submit\" name=\"\" value=\"" . Dict::S('UI:Button:Delete') . "\">\n"); $oAppContext = new ApplicationContext(); $oP->add($oAppContext->GetForForm()); $oP->add("</form>\n"); } } else { // Execute the deletion // if (count($aObjects) == 1) { $oObj = $aObjects[0]; $oP->add("<h1>" . Dict::Format('UI:Title:DeletionOf_Object', $oObj->GetName()) . "</h1>\n"); } else { $oP->add("<h1>" . Dict::Format('UI:Title:BulkDeletionOf_Count_ObjectsOf_Class', count($aObjects), MetaModel::GetName($sClass)) . "</h1>\n"); } // Security - do not allow the user to force a forbidden delete by the mean of page arguments... if ($oDeletionPlan->FoundSecurityIssue()) { throw new CoreException(Dict::S('UI:Error:NotEnoughRightsToDelete')); } if ($oDeletionPlan->FoundManualOperation()) { throw new CoreException(Dict::S('UI:Error:CannotDeleteBecauseManualOpNeeded')); } if ($oDeletionPlan->FoundManualDelete()) { throw new CoreException(Dict::S('UI:Error:CannotDeleteBecauseOfDepencies')); } // Report deletions // $aDisplayData = array(); foreach ($oDeletionPlan->ListDeletes() as $sTargetClass => $aDeletes) { foreach ($aDeletes as $iId => $aData) { $oToDelete = $aData['to_delete']; if (isset($aData['requested_explicitely'])) { $sMessage = Dict::S('UI:Delete:Deleted'); } else { $sMessage = Dict::S('UI:Delete:AutomaticallyDeleted'); } $aDisplayData[] = array('class' => MetaModel::GetName(get_class($oToDelete)), 'object' => $oToDelete->GetName(), 'consequence' => $sMessage); } } // Report updates // foreach ($oDeletionPlan->ListUpdates() as $sTargetClass => $aToUpdate) { foreach ($aToUpdate as $iId => $aData) { $oToUpdate = $aData['to_reset']; $aDisplayData[] = array('class' => MetaModel::GetName(get_class($oToUpdate)), 'object' => $oToUpdate->GetHyperLink(), 'consequence' => Dict::Format('UI:Delete:AutomaticResetOf_Fields', $aData['attributes_list'])); } } // Report automatic jobs // if ($oDeletionPlan->GetTargetCount() > 0) { if (count($aObjects) == 1) { $oObj = $aObjects[0]; $oP->p(Dict::Format('UI:Delete:CleaningUpRefencesTo_Object', $oObj->GetName())); } else { $oP->p(Dict::Format('UI:Delete:CleaningUpRefencesTo_Several_ObjectsOf_Class', count($aObjects), MetaModel::GetName($sClass))); } $aDisplayConfig = array(); $aDisplayConfig['class'] = array('label' => 'Class', 'description' => ''); $aDisplayConfig['object'] = array('label' => 'Object', 'description' => ''); $aDisplayConfig['consequence'] = array('label' => 'Done', 'description' => Dict::S('UI:Delete:Done+')); $oP->table($aDisplayConfig, $aDisplayData); } } }
/** * Add a condition (restriction) to the current DBSearch on which the display block is based * taking into account the hierarchical keys for which the condition is based on the 'below' operator */ protected function AddCondition($sFilterCode, $condition, $sOpCode = null) { // Workaround to an issue revealed whenever a condition on org_id is applied twice (with a hierarchy of organizations) // Moreover, it keeps the query as simple as possible if (isset($this->m_aConditions[$sFilterCode]) && $condition == $this->m_aConditions[$sFilterCode]) { // Skip return; } $this->m_aConditions[$sFilterCode] = $condition; $sClass = $this->m_oFilter->GetClass(); $bConditionAdded = false; // If the condition is an external key with a class having a hierarchy, use a "below" criteria if (MetaModel::IsValidAttCode($sClass, $sFilterCode)) { $oAttDef = MetaModel::GetAttributeDef($sClass, $sFilterCode); if ($oAttDef->IsExternalKey()) { $sHierarchicalKeyCode = MetaModel::IsHierarchicalClass($oAttDef->GetTargetClass()); if ($sHierarchicalKeyCode !== false) { $oFilter = new DBObjectSearch($oAttDef->GetTargetClass()); if ($sOpCode == 'IN' && is_array($condition)) { $oFilter->AddConditionExpression(self::GetConditionIN($oFilter, 'id', $condition)); } else { $oFilter->AddCondition('id', $condition); } $oHKFilter = new DBObjectSearch($oAttDef->GetTargetClass()); $oHKFilter->AddCondition_PointingTo($oFilter, $sHierarchicalKeyCode, TREE_OPERATOR_BELOW); // Use the 'below' operator by default $this->m_oFilter->AddCondition_PointingTo($oHKFilter, $sFilterCode); $bConditionAdded = true; } else { if ($sOpCode == 'IN' && is_array($condition)) { $this->m_oFilter->AddConditionExpression(self::GetConditionIN($this->m_oFilter, $sFilterCode, $condition)); $bConditionAdded = true; } } } else { if ($sOpCode == 'IN' && is_array($condition)) { $this->m_oFilter->AddConditionExpression(self::GetConditionIN($this->m_oFilter, $sFilterCode, $condition)); $bConditionAdded = true; } } } // In all other cases, just add the condition directly if (!$bConditionAdded) { $this->m_oFilter->AddCondition($sFilterCode, $condition); // Use the default 'loose' operator } }
$oAttachment->Set('item_class', $sObjClass); $oAttachment->SetDefaultOrgId(); $oAttachment->Set('contents', $oDoc); $iAttId = $oAttachment->DBInsert(); $aResult['msg'] = $oDoc->GetFileName(); $aResult['icon'] = utils::GetAbsoluteUrlAppRoot() . AttachmentPlugIn::GetFileIcon($oDoc->GetFileName()); $aResult['att_id'] = $iAttId; $aResult['preview'] = $oDoc->IsPreviewAvailable() ? 'true' : 'false'; } catch (FileUploadException $e) { $aResult['error'] = $e->GetMessage(); } } $oPage->add(json_encode($aResult)); break; case 'remove': $iAttachmentId = utils::ReadParam('att_id', ''); $oSearch = DBObjectSearch::FromOQL("SELECT Attachment WHERE id = :id"); $oSet = new DBObjectSet($oSearch, array(), array('id' => $iAttachmentId)); while ($oAttachment = $oSet->Fetch()) { $oAttachment->DBDelete(); } break; default: $oPage->p("Missing argument 'operation'"); } $oPage->output(); } catch (Exception $e) { // note: transform to cope with XSS attacks echo htmlentities($e->GetMessage(), ENT_QUOTES, 'utf-8'); IssueLog::Error($e->getMessage()); }
/** * Describe (as a text string) the modifications corresponding to this change */ public function GetDescription() { $sResult = ''; $oTargetObjectClass = $this->Get('objclass'); $oTargetObjectKey = $this->Get('objkey'); $oTargetSearch = new DBObjectSearch($oTargetObjectClass); $oTargetSearch->AddCondition('id', $oTargetObjectKey, '='); $oMonoObjectSet = new DBObjectSet($oTargetSearch); if (UserRights::IsActionAllowedOnAttribute($this->Get('objclass'), $this->Get('attcode'), UR_ACTION_READ, $oMonoObjectSet) == UR_ALLOWED_YES) { if (!MetaModel::IsValidAttCode($this->Get('objclass'), $this->Get('attcode'))) { return ''; } // Protects against renamed attributes... $oAttDef = MetaModel::GetAttributeDef($this->Get('objclass'), $this->Get('attcode')); $sAttName = $oAttDef->GetLabel(); $sLinkClass = $oAttDef->GetLinkedClass(); $aLinkClasses = MetaModel::EnumChildClasses($sLinkClass, ENUM_CHILD_CLASSES_ALL); // Search for changes on the corresponding link // $oSearch = new DBObjectSearch('CMDBChangeOpSetAttribute'); $oSearch->AddCondition('change', $this->Get('change'), '='); $oSearch->AddCondition('objkey', $this->Get('link_id'), '='); if (count($aLinkClasses) == 1) { // Faster than the whole building of the expression below for just one value ?? $oSearch->AddCondition('objclass', $sLinkClass, '='); } else { $oField = new FieldExpression('objclass', $oSearch->GetClassAlias()); $sListExpr = '(' . implode(', ', CMDBSource::Quote($aLinkClasses)) . ')'; $sOQLCondition = $oField->Render() . " IN {$sListExpr}"; $oNewCondition = Expression::FromOQL($sOQLCondition); $oSearch->AddConditionExpression($oNewCondition); } $oSet = new DBObjectSet($oSearch); $aChanges = array(); while ($oChangeOp = $oSet->Fetch()) { $aChanges[] = $oChangeOp->GetDescription(); } if (count($aChanges) == 0) { return ''; } $sItemDesc = MetaModel::GetHyperLink($this->Get('item_class'), $this->Get('item_id')); $sResult = $sAttName . ' - '; $sResult .= Dict::Format('Change:LinkSet:Modified', $sItemDesc); $sResult .= ' : ' . implode(', ', $aChanges); } return $sResult; }
public function GetSiloSelectionForm() { // List of visible Organizations $iCount = 0; $oSet = null; if (MetaModel::IsValidClass('Organization')) { // Display the list of *favorite* organizations... but keeping in mind what is the real number of organizations $aFavoriteOrgs = appUserPreferences::GetPref('favorite_orgs', null); $oSearchFilter = new DBObjectSearch('Organization'); $oSearchFilter->SetModifierProperty('UserRightsGetSelectFilter', 'bSearchMode', true); $oSet = new CMDBObjectSet($oSearchFilter); $iCount = $oSet->Count(); // total number of existing Orgs // Now get the list of Orgs to be displayed in the menu $oSearchFilter = DBObjectSearch::FromOQL(ApplicationMenu::GetFavoriteSiloQuery()); $oSearchFilter->SetModifierProperty('UserRightsGetSelectFilter', 'bSearchMode', true); if (!empty($aFavoriteOrgs)) { $oSearchFilter->AddCondition('id', $aFavoriteOrgs, 'IN'); } $oSet = new CMDBObjectSet($oSearchFilter); // List of favorite orgs } switch ($iCount) { case 0: // No such dimension/silo => nothing to select $sHtml = '<div id="SiloSelection"><!-- nothing to select --></div>'; break; case 1: // Only one possible choice... no selection, but display the value $oOrg = $oSet->Fetch(); $sHtml = '<div id="SiloSelection">' . $oOrg->GetName() . '</div>'; $sHtml .= ''; break; default: $sHtml = ''; $oAppContext = new ApplicationContext(); $iCurrentOrganization = $oAppContext->GetCurrentValue('org_id'); $sHtml = '<div id="SiloSelection">'; $sHtml .= '<form style="display:inline" action="' . utils::GetAbsoluteUrlAppRoot() . 'pages/UI.php">'; //<select class="org_combo" name="c[org_id]" title="Pick an organization" onChange="this.form.submit();">'; $sFavoriteOrgs = ''; $oWidget = new UIExtKeyWidget('Organization', 'org_id', '', true); $sHtml .= $oWidget->Display($this, 50, false, '', $oSet, $iCurrentOrganization, 'org_id', false, 'c[org_id]', '', array('iFieldSize' => 20, 'iMinChars' => MetaModel::GetConfig()->Get('min_autocomplete_chars'), 'sDefaultValue' => Dict::S('UI:AllOrganizations')), null, 'select', false); $this->add_ready_script('$("#org_id").bind("extkeychange", function() { $("#SiloSelection form").submit(); } )'); $this->add_ready_script("\$('#label_org_id').click( function() { \$(this).val(''); \$('#org_id').val(''); return true; } );\n"); // Add other dimensions/context information to this form $oAppContext->Reset('org_id'); // org_id is handled above and we want to be able to change it here ! $oAppContext->Reset('menu'); // don't pass the menu, since a menu may expect more parameters $sHtml .= $oAppContext->GetForForm(); // Pass what remains, if anything... $sHtml .= '</form>'; $sHtml .= '</div>'; } return $sHtml; }
/** * Make the relevant DBSearch instance (FromOQL) */ public function ToDBSearch($sQuery) { $sClass = $this->GetClass(); $sClassAlias = $this->GetClassAlias(); $oSearch = new DBObjectSearch($sClass, $sClassAlias); $oSearch->InitFromOqlQuery($this, $sQuery); return $oSearch; }