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; }
public function DoActivate($aContextArgs) { // Find the related actions $oLinkedActions = $this->Get('action_list'); while ($oLink = $oLinkedActions->Fetch()) { $iActionId = $oLink->Get('action_id'); $oAction = MetaModel::GetObject('Action', $iActionId); if ($oAction->IsActive()) { $oAction->DoExecute($this, $aContextArgs); } } }
/** * 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; }
/** * 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"); }
/** * Make the most relevant label, given the value of the expression * * @param DBSearch oFilter The context in which this expression has been used * @param string sValue The value returned by the query, for this expression * @param string sDefault The default value if no relevant label could be computed * @return The label */ public function MakeValueLabel($oFilter, $sValue, $sDefault) { $sAttCode = $this->GetName(); $sParentAlias = $this->GetParent(); $aSelectedClasses = $oFilter->GetSelectedClasses(); $sClass = $aSelectedClasses[$sParentAlias]; $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode); // Set a default value for the general case $sRes = $oAttDef->GetAsHtml($sValue); // Exceptions... if ($oAttDef->IsExternalKey()) { $sObjClass = $oAttDef->GetTargetClass(); $iObjKey = (int) $sValue; if ($iObjKey > 0) { $oObject = MetaModel::GetObject($sObjClass, $iObjKey); $sRes = $oObject->GetHyperlink(); } else { // Undefined $sRes = DBObject::MakeHyperLink($sObjClass, 0); } } elseif ($oAttDef->IsExternalField()) { if (is_null($sValue)) { $sRes = Dict::S('UI:UndefinedObject'); } } return $sRes; }
/** * Get The organization of the current user (i.e. the organization of its contact) * @param WebPage $oP The current page, for errors output * @return Organization The user's org or null in case of problem... */ function GetUserOrg() { $oOrg = null; $iContactId = UserRights::GetContactId(); $oContact = MetaModel::GetObject('Contact', $iContactId, false); // false => Can fail if (is_object($oContact)) { $oOrg = MetaModel::GetObject('Organization', $oContact->Get('org_id'), false); // false => can fail } else { throw new Exception(Dict::S('Portal:ErrorNoContactForThisUser')); } return $oOrg; }
public function DoAddObjects(WebPage $oP, $oFullSetFilter, $oCurrentObj) { $aLinkedObjectIds = utils::ReadMultipleSelection($oFullSetFilter); foreach ($aLinkedObjectIds as $iObjectId) { $oLinkedObj = MetaModel::GetObject($this->m_sRemoteClass, $iObjectId); if (is_object($oLinkedObj)) { $aRow = $this->GetFormRow($oP, $oLinkedObj, -$iObjectId, array(), $oCurrentObj); // Not yet created link get negative Ids $oP->add($this->DisplayFormRow($oP, $this->m_aTableConfig, $aRow, -$iObjectId)); } else { $oP->p(Dict::Format('UI:Error:Object_Class_Id_NotFound', $this->m_sLinkedClass, $iObjectId)); } } }
/** * Find the object of the specified Class/ID. * @param WebPage $oP The current page * @return DBObject The found object, or throws an exception in case of failure */ public function FindObjectFromArgs($aAllowedClasses = null) { $sClass = utils::ReadParam('class', '', true, 'class'); $iId = utils::ReadParam('id', 0, true, 'integer'); if (empty($sClass)) { throw new Exception("Missing argument 'class'"); } if (!MetaModel::IsValidClass($sClass)) { throw new Exception("Wrong value for argument 'class': {$sClass}"); } if ($iId == 0) { throw new Exception("Missing argument 'id'"); } if (!is_null($aAllowedClasses)) { $bAllowed = false; foreach ($aAllowedClasses as $sParentClass) { if (MetaModel::IsParentClass($sParentClass, $sClass)) { $bAllowed = true; } } if (!$bAllowed) { throw new Exception("Class '{$sClass} not allowed in this implementation'"); } } $oObj = MetaModel::GetObject($sClass, $iId, false); if (!is_object($oObj)) { throw new Exception("Could not find the object {$sClass}/{$iId}"); } return $oObj; }
protected function DBCloneTracked_Internal($newKey = null) { $newKey = parent::DBClone($newKey); $oClone = MetaModel::GetObject(get_class($this), $newKey); return $newKey; }
public function GetRenderContent(WebPage $oPage, $aExtraParams = array(), $sId) { $sHtml = ''; $bTruncated = false; $oSet = new CMDBObjectSet($this->m_oFilter, array('date' => false)); if ($this->iLimitStart > 0 || $this->iLimitCount > 0) { $oSet->SetLimit($this->iLimitCount, $this->iLimitStart); if ($this->iLimitCount - $this->iLimitStart < $oSet->Count()) { $bTruncated = true; } } $sHtml .= "<!-- filter: " . $this->m_oFilter->ToOQL() . "-->\n"; switch ($this->m_sStyle) { case 'toggle': // First the latest change that the user is allowed to see do { $oLatestChangeOp = $oSet->Fetch(); } while (is_object($oLatestChangeOp) && $oLatestChangeOp->GetDescription() == ''); if (is_object($oLatestChangeOp)) { // There is one change in the list... only when the object has been created ! $sDate = $oLatestChangeOp->GetAsHTML('date'); $oChange = MetaModel::GetObject('CMDBChange', $oLatestChangeOp->Get('change')); $sUserInfo = $oChange->GetAsHTML('userinfo'); $sHtml .= $oPage->GetStartCollapsibleSection(Dict::Format('UI:History:LastModified_On_By', $sDate, $sUserInfo)); $sHtml .= $this->GetHistoryTable($oPage, $oSet); $sHtml .= $oPage->GetEndCollapsibleSection(); } break; case 'table': default: if ($bTruncated) { $sFilter = $this->m_oFilter->serialize(); $sHtml .= '<div id="history_container"><p>'; $sHtml .= Dict::Format('UI:TruncatedResults', $this->iLimitCount, $oSet->Count()); $sHtml .= ' '; $sHtml .= '<a href="#" onclick="DisplayHistory(\'#history_container\', \'' . $sFilter . '\', 0, 0); return false;">' . Dict::S('UI:DisplayAll') . '</a>'; $sHtml .= $this->GetHistoryTable($oPage, $oSet); $sHtml .= '</p></div>'; $oPage->add_ready_script("\$('#{$sId} table.listResults tr:last td').addClass('truncated');"); } else { $sHtml .= $this->GetHistoryTable($oPage, $oSet); } } return $sHtml; }
/** * Get the display name of the selected object, to fill back the autocomplete */ public function GetObjectName($iObjId) { $aModifierProps = array(); $aModifierProps['UserRightsGetSelectFilter']['bSearchMode'] = $this->bSearchMode; $oObj = MetaModel::GetObject($this->sTargetClass, $iObjId, false, false, $aModifierProps); if ($oObj) { return $oObj->GetName(); } else { return ''; } }
/** * Give a default value for item_org_id (if relevant...) * @return void */ public function SetDefaultOrgId() { // First check that the organization CAN be fetched from the target class // $sClass = $this->Get('item_class'); $aCallSpec = array($sClass, 'MapContextParam'); if (is_callable($aCallSpec)) { $sAttCode = call_user_func($aCallSpec, 'org_id'); // Returns null when there is no mapping for this parameter if (MetaModel::IsValidAttCode($sClass, $sAttCode)) { // Second: check that the organization CAN be fetched from the current user // if (MetaModel::IsValidClass('Person')) { $aCallSpec = array($sClass, 'MapContextParam'); if (is_callable($aCallSpec)) { $sAttCode = call_user_func($aCallSpec, 'org_id'); // Returns null when there is no mapping for this parameter if (MetaModel::IsValidAttCode($sClass, $sAttCode)) { // OK - try it // $oCurrentPerson = MetaModel::GetObject('Person', UserRights::GetContactId(), false); if ($oCurrentPerson) { $this->Set('item_org_id', $oCurrentPerson->Get($sAttCode)); } } } } } } }
/** * Display the graph inside the given page, with the "filter" drawer above it * @param WebPage $oP * @param hash $aResults * @param string $sRelation * @param ApplicationContext $oAppContext * @param array $aExcludedObjects */ function Display(WebPage $oP, $aResults, $sRelation, ApplicationContext $oAppContext, $aExcludedObjects = array(), $sObjClass = null, $iObjKey = null, $sContextKey, $aContextParams = array()) { $aContextDefs = static::GetContextDefinitions($sContextKey, true, $aContextParams); $aExcludedByClass = array(); foreach ($aExcludedObjects as $oObj) { if (!array_key_exists(get_class($oObj), $aExcludedByClass)) { $aExcludedByClass[get_class($oObj)] = array(); } $aExcludedByClass[get_class($oObj)][] = $oObj->GetKey(); } $oP->add("<div class=\"not-printable\">\n"); $oP->add("<div id=\"ds_flash\" class=\"SearchDrawer\" style=\"display:none;\">\n"); if (!$oP->IsPrintableVersion()) { $oP->add_ready_script(<<<EOF \t\$( "#tabbedContent_0" ).tabs({ heightStyle: "fill" }); EOF ); } $oP->add_ready_script(<<<EOF \t\$("#dh_flash").click( function() { \t\t\$("#ds_flash").slideToggle('normal', function() { \$("#ds_flash").parent().resize(); \$("#dh_flash").trigger('toggle_complete'); } ); \t\t\$("#dh_flash").toggleClass('open'); \t}); \$('#ReloadMovieBtn').button().button('disable'); EOF ); $aSortedElements = array(); foreach ($aResults as $sClassIdx => $aObjects) { foreach ($aObjects as $oCurrObj) { $sSubClass = get_class($oCurrObj); $aSortedElements[$sSubClass] = MetaModel::GetName($sSubClass); } } asort($aSortedElements); $idx = 0; foreach ($aSortedElements as $sSubClass => $sClassName) { $oP->add("<span style=\"padding-right:2em; white-space:nowrap;\"><input type=\"checkbox\" id=\"exclude_{$idx}\" name=\"excluded[]\" value=\"{$sSubClass}\" checked onChange=\"\$('#ReloadMovieBtn').button('enable')\"><label for=\"exclude_{$idx}\"> " . MetaModel::GetClassIcon($sSubClass) . " {$sClassName}</label></span> "); $idx++; } $oP->add("<p style=\"text-align:right\"><button type=\"button\" id=\"ReloadMovieBtn\" onClick=\"DoReload()\">" . Dict::S('UI:Button:Refresh') . "</button></p>"); $oP->add("</div>\n"); $oP->add("<div class=\"HRDrawer\"></div>\n"); $oP->add("<div id=\"dh_flash\" class=\"DrawerHandle\">" . Dict::S('UI:ElementsDisplayed') . "</div>\n"); $oP->add("</div>\n"); // class="not-printable" $aAdditionalContexts = array(); foreach ($aContextDefs as $sKey => $aDefinition) { $aAdditionalContexts[] = array('key' => $sKey, 'label' => Dict::S($aDefinition['dict']), 'oql' => $aDefinition['oql'], 'default' => array_key_exists('default', $aDefinition) && $aDefinition['default'] == 'yes'); } $sDirection = utils::ReadParam('d', 'horizontal'); $iGroupingThreshold = utils::ReadParam('g', 5); $oP->add_linked_script(utils::GetAbsoluteUrlAppRoot() . 'js/fraphael.js'); $oP->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot() . 'css/jquery.contextMenu.css'); $oP->add_linked_script(utils::GetAbsoluteUrlAppRoot() . 'js/jquery.contextMenu.js'); $oP->add_linked_script(utils::GetAbsoluteUrlAppRoot() . 'js/simple_graph.js'); try { $this->InitFromGraphviz(); $sExportAsPdfURL = ''; $sExportAsPdfURL = utils::GetAbsoluteUrlAppRoot() . 'pages/ajax.render.php?operation=relation_pdf&relation=' . $sRelation . '&direction=' . ($this->bDirectionDown ? 'down' : 'up'); $oAppcontext = new ApplicationContext(); $sContext = $oAppContext->GetForLink(); $sDrillDownURL = utils::GetAbsoluteUrlAppRoot() . 'pages/UI.php?operation=details&class=%1$s&id=%2$s&' . $sContext; $sExportAsDocumentURL = utils::GetAbsoluteUrlAppRoot() . 'pages/ajax.render.php?operation=relation_attachment&relation=' . $sRelation . '&direction=' . ($this->bDirectionDown ? 'down' : 'up'); $sLoadFromURL = utils::GetAbsoluteUrlAppRoot() . 'pages/ajax.render.php?operation=relation_json&relation=' . $sRelation . '&direction=' . ($this->bDirectionDown ? 'down' : 'up'); $sAttachmentExportTitle = ''; if ($sObjClass != null && $iObjKey != null) { $oTargetObj = MetaModel::GetObject($sObjClass, $iObjKey, false); if ($oTargetObj) { $sAttachmentExportTitle = Dict::Format('UI:Relation:AttachmentExportOptions_Name', $oTargetObj->GetName()); } } $sId = 'graph'; $sStyle = ''; if ($oP->IsPrintableVersion()) { // Optimize for printing on A4/Letter vertically $sStyle = 'margin-left:auto; margin-right:auto;'; $oP->add_ready_script("\$('.simple-graph').width(18/2.54*96).resizable({ stop: function() { \$(window).trigger('resized'); }});"); // Default width about 18 cm, since most browsers assume 96 dpi } $oP->add('<div id="' . $sId . '" class="simple-graph" style="' . $sStyle . '"></div>'); $aParams = array('source_url' => $sLoadFromURL, 'sources' => $this->bDirectionDown ? $this->aSourceObjects : $this->aSinkObjects, 'excluded' => $aExcludedByClass, 'grouping_threshold' => $iGroupingThreshold, 'export_as_pdf' => array('url' => $sExportAsPdfURL, 'label' => Dict::S('UI:Relation:ExportAsPDF')), 'export_as_attachment' => array('url' => $sExportAsDocumentURL, 'label' => Dict::S('UI:Relation:ExportAsAttachment'), 'obj_class' => $sObjClass, 'obj_key' => $iObjKey), 'drill_down' => array('url' => $sDrillDownURL, 'label' => Dict::S('UI:Relation:DrillDown')), 'labels' => array('export_pdf_title' => Dict::S('UI:Relation:PDFExportOptions'), 'export_as_attachment_title' => $sAttachmentExportTitle, 'export' => Dict::S('UI:Button:Export'), 'cancel' => Dict::S('UI:Button:Cancel'), 'title' => Dict::S('UI:RelationOption:Title'), 'untitled' => Dict::S('UI:RelationOption:Untitled'), 'include_list' => Dict::S('UI:RelationOption:IncludeList'), 'comments' => Dict::S('UI:RelationOption:Comments'), 'grouping_threshold' => Dict::S('UI:RelationOption:GroupingThreshold'), 'refresh' => Dict::S('UI:Button:Refresh'), 'check_all' => Dict::S('UI:SearchValue:CheckAll'), 'uncheck_all' => Dict::S('UI:SearchValue:UncheckAll'), 'none_selected' => Dict::S('UI:Relation:NoneSelected'), 'nb_selected' => Dict::S('UI:SearchValue:NbSelected'), 'additional_context_info' => Dict::S('UI:Relation:AdditionalContextInfo'), 'zoom' => Dict::S('UI:Relation:Zoom'), 'loading' => Dict::S('UI:Loading')), 'page_format' => array('label' => Dict::S('UI:Relation:PDFExportPageFormat'), 'values' => array('A3' => Dict::S('UI:PageFormat_A3'), 'A4' => Dict::S('UI:PageFormat_A4'), 'Letter' => Dict::S('UI:PageFormat_Letter'))), 'page_orientation' => array('label' => Dict::S('UI:Relation:PDFExportPageOrientation'), 'values' => array('P' => Dict::S('UI:PageOrientation_Portrait'), 'L' => Dict::S('UI:PageOrientation_Landscape'))), 'additional_contexts' => $aAdditionalContexts, 'context_key' => $sContextKey); if (!extension_loaded('gd')) { // PDF export requires GD unset($aParams['export_as_pdf']); } if (!extension_loaded('gd') || is_null($sObjClass) || is_null($iObjKey)) { // Export as Attachment requires GD (for building the PDF) AND a valid objclass/objkey couple unset($aParams['export_as_attachment']); } $oP->add_ready_script("\$('#{$sId}').simple_graph(" . json_encode($aParams) . ");"); } catch (Exception $e) { $oP->add('<div>' . $e->getMessage() . '</div>'); } $oP->add_script(<<<EOF \t\t \tfunction DoReload() \t{ \t\t\$('#ReloadMovieBtn').button('disable'); \t\ttry \t\t{ \t\t\tvar aExcluded = []; \t\t\t\$('input[name^=excluded]').each( function() { \t\t\t\tif (!\$(this).prop('checked')) \t\t\t\t{ \t\t\t\t\taExcluded.push(\$(this).val()); \t\t\t\t} \t\t\t} ); \t\t\t\$('#graph').simple_graph('option', {excluded_classes: aExcluded}); \t\t\t\$('#graph').simple_graph('reload'); \t\t} \t\tcatch(err) \t\t{ \t\t\talert(err); \t\t} \t} EOF ); }
/** * Process the CSV data, for real or as a simulation * @param WebPage $oPage The page used to display the wizard * @param bool $bSimulate Whether or not to simulate the data load * @return array The CSV lines in error that were rejected from the load (with the header line - if any) or null */ function ProcessCSVData(WebPage $oPage, $bSimulate = true) { $aResult = array(); $sCSVData = utils::ReadParam('csvdata', '', false, 'raw_data'); $sCSVDataTruncated = utils::ReadParam('csvdata_truncated', '', false, 'raw_data'); $sSeparator = utils::ReadParam('separator', ',', false, 'raw_data'); $sTextQualifier = utils::ReadParam('text_qualifier', '"', false, 'raw_data'); $bHeaderLine = utils::ReadParam('header_line', '0') == 1; $iSkippedLines = 0; if (utils::ReadParam('box_skiplines', '0') == 1) { $iSkippedLines = utils::ReadParam('nb_skipped_lines', '0'); } $sClassName = utils::ReadParam('class_name', '', false, 'class'); $aFieldsMapping = utils::ReadParam('field', array(), false, 'raw_data'); $aSearchFields = utils::ReadParam('search_field', array(), false, 'field_name'); $iCurrentStep = $bSimulate ? 4 : 5; $bAdvanced = utils::ReadParam('advanced', 0); $sEncoding = utils::ReadParam('encoding', 'UTF-8'); $sSynchroScope = utils::ReadParam('synchro_scope', '', false, 'raw_data'); if (!empty($sSynchroScope)) { $oSearch = DBObjectSearch::FromOQL($sSynchroScope); $sClassName = $oSearch->GetClass(); // If a synchronization scope is set, then the class is fixed ! $oSet = new DBObjectSet($oSearch); $iCount = $oSet->Count(); DisplaySynchroBanner($oPage, $sClassName, $iCount); $sClassesSelect = "<select id=\"select_class_name\" name=\"class_name\"><option value=\"{$sClassName}\" selected>" . MetaModel::GetName($sClassName) . "</option>"; $aSynchroUpdate = utils::ReadParam('synchro_update', array()); } else { $sSynchroScope = ''; $aSynchroUpdate = null; } // Parse the data set $oCSVParser = new CSVParser($sCSVData, $sSeparator, $sTextQualifier); $aData = $oCSVParser->ToArray($iSkippedLines); $iRealSkippedLines = $iSkippedLines; if ($bHeaderLine) { $aResult[] = $sTextQualifier . implode($sTextQualifier . $sSeparator . $sTextQualifier, array_shift($aData)) . $sTextQualifier; // Remove the first line and store it in case of error $iRealSkippedLines++; } // Format for the line numbers $sMaxLen = strlen('' . count($aData)) < 3 ? 3 : strlen('' . count($aData)); // Pad line numbers to the appropriate number of chars, but at least 3 // Compute the list of search/reconciliation criteria $aSearchKeys = array(); foreach ($aSearchFields as $index => $sDummy) { $sSearchField = $aFieldsMapping[$index]; $aMatches = array(); if (preg_match('/(.+)->(.+)/', $sSearchField, $aMatches) > 0) { $sSearchField = $aMatches[1]; $aSearchKeys[$aMatches[1]] = ''; } else { $aSearchKeys[$sSearchField] = ''; } if (!MetaModel::IsValidFilterCode($sClassName, $sSearchField)) { // Remove invalid or unmapped search fields $aSearchFields[$index] = null; unset($aSearchKeys[$sSearchField]); } } // Compute the list of fields and external keys to process $aExtKeys = array(); $aAttributes = array(); $aExternalKeysByColumn = array(); foreach ($aFieldsMapping as $iNumber => $sAttCode) { $iIndex = $iNumber - 1; if (!empty($sAttCode) && $sAttCode != ':none:' && $sAttCode != 'finalclass') { if (preg_match('/(.+)->(.+)/', $sAttCode, $aMatches) > 0) { $sAttribute = $aMatches[1]; $sField = $aMatches[2]; $aExtKeys[$sAttribute][$sField] = $iIndex; $aExternalKeysByColumn[$iIndex] = $sAttribute; } else { if ($sAttCode == 'id') { $aAttributes['id'] = $iIndex; } else { $oAttDef = MetaModel::GetAttributeDef($sClassName, $sAttCode); if ($oAttDef->IsExternalKey()) { $aExtKeys[$sAttCode]['id'] = $iIndex; $aExternalKeysByColumn[$iIndex] = $sAttCode; } else { $aAttributes[$sAttCode] = $iIndex; } } } } } $oMyChange = null; if (!$bSimulate) { // We're doing it for real, let's create a change $sUserString = CMDBChange::GetCurrentUserName() . ' (CSV)'; CMDBObject::SetTrackInfo($sUserString); CMDBObject::SetTrackOrigin('csv-interactive'); $oMyChange = CMDBObject::GetCurrentChange(); } $oBulk = new BulkChange($sClassName, $aData, $aAttributes, $aExtKeys, array_keys($aSearchKeys), empty($sSynchroScope) ? null : $sSynchroScope, $aSynchroUpdate, null, true); $oBulk->SetReportHtml(); $oPage->add('<input type="hidden" name="csvdata_truncated" id="csvdata_truncated" value="' . htmlentities($sCSVDataTruncated, ENT_QUOTES, 'UTF-8') . '"/>'); $aRes = $oBulk->Process($oMyChange); $sHtml = '<table id="bulk_preview" style="border-collapse: collapse;">'; $sHtml .= '<tr><th style="padding:2px;border-right: 2px #fff solid;">Line</th>'; $sHtml .= '<th style="padding:2px;border-right: 2px #fff solid;">Status</th>'; $sHtml .= '<th style="padding:2px;border-right: 2px #fff solid;">Object</th>'; foreach ($aFieldsMapping as $iNumber => $sAttCode) { if (!empty($sAttCode) && $sAttCode != ':none:' && $sAttCode != 'finalclass') { $sHtml .= "<th style=\"padding:2px;border-right: 2px #fff solid;\">" . MetaModel::GetLabel($sClassName, $sAttCode) . "</th>"; } } $sHtml .= '<th>Message</th>'; $sHtml .= '</tr>'; $iErrors = 0; $iCreated = 0; $iModified = 0; $iUnchanged = 0; foreach ($aRes as $iLine => $aResRow) { $oStatus = $aResRow['__STATUS__']; $sUrl = ''; $sMessage = ''; $sCSSRowClass = ''; $sCSSMessageClass = 'cell_ok'; switch (get_class($oStatus)) { case 'RowStatus_NoChange': $iUnchanged++; $sFinalClass = $aResRow['finalclass']; $oObj = MetaModel::GetObject($sFinalClass, $aResRow['id']->GetPureValue()); $sUrl = $oObj->GetHyperlink(); $sStatus = '<img src="../images/unchanged.png" title="' . Dict::S('UI:CSVReport-Icon-Unchanged') . '">'; $sCSSRowClass = 'row_unchanged'; break; case 'RowStatus_Modify': $iModified++; $sFinalClass = $aResRow['finalclass']; $oObj = MetaModel::GetObject($sFinalClass, $aResRow['id']->GetPureValue()); $sUrl = $oObj->GetHyperlink(); $sStatus = '<img src="../images/modified.png" title="' . Dict::S('UI:CSVReport-Icon-Modified') . '">'; $sCSSRowClass = 'row_modified'; break; case 'RowStatus_Disappeared': $iModified++; $sFinalClass = $aResRow['finalclass']; $oObj = MetaModel::GetObject($sFinalClass, $aResRow['id']->GetPureValue()); $sUrl = $oObj->GetHyperlink(); $sStatus = '<img src="../images/delete.png" title="' . Dict::S('UI:CSVReport-Icon-Missing') . '">'; $sCSSRowClass = 'row_modified'; if ($bSimulate) { $sMessage = Dict::S('UI:CSVReport-Object-MissingToUpdate'); } else { $sMessage = Dict::S('UI:CSVReport-Object-MissingUpdated'); } break; case 'RowStatus_NewObj': $iCreated++; $sFinalClass = $aResRow['finalclass']; $sStatus = '<img src="../images/added.png" title="' . Dict::S('UI:CSVReport-Icon-Created') . '">'; $sCSSRowClass = 'row_added'; if ($bSimulate) { $sMessage = Dict::S('UI:CSVReport-Object-ToCreate'); } else { $sFinalClass = $aResRow['finalclass']; $oObj = MetaModel::GetObject($sFinalClass, $aResRow['id']->GetPureValue()); $sUrl = $oObj->GetHyperlink(); $sMessage = Dict::S('UI:CSVReport-Object-Created'); } break; case 'RowStatus_Issue': $iErrors++; $sMessage .= $oPage->GetP($oStatus->GetDescription()); $sStatus = '<img src="../images/error.png" title="' . Dict::S('UI:CSVReport-Icon-Error') . '">'; //translate $sCSSMessageClass = 'cell_error'; $sCSSRowClass = 'row_error'; if (array_key_exists($iLine, $aData)) { $aRow = $aData[$iLine]; $aResult[] = $sTextQualifier . implode($sTextQualifier . $sSeparator . $sTextQualifier, $aRow) . $sTextQualifier; // Remove the first line and store it in case of error } break; } $sHtml .= '<tr class="' . $sCSSRowClass . '">'; $sHtml .= "<td style=\"background-color:#f1f1f1;border-right:2px #fff solid;\">" . sprintf("%0{$sMaxLen}d", 1 + $iLine + $iRealSkippedLines) . "</td>"; $sHtml .= "<td style=\"text-align:center;background-color:#f1f1f1;border-right:2px #fff solid;\">{$sStatus}</td>"; $sHtml .= "<td style=\"text-align:center;background-color:#f1f1f1;\">{$sUrl}</td>"; foreach ($aFieldsMapping as $iNumber => $sAttCode) { if (!empty($sAttCode) && $sAttCode != ':none:' && $sAttCode != 'finalclass') { $oCellStatus = $aResRow[$iNumber - 1]; $sCellMessage = ''; if (isset($aExternalKeysByColumn[$iNumber - 1])) { $sExtKeyName = $aExternalKeysByColumn[$iNumber - 1]; $oExtKeyCellStatus = $aResRow[$sExtKeyName]; switch (get_class($oExtKeyCellStatus)) { case 'CellStatus_Issue': case 'CellStatus_SearchIssue': case 'CellStatus_NullIssue': $sCellMessage .= $oPage->GetP($oExtKeyCellStatus->GetDescription()); break; case 'CellStatus_Ambiguous': $sCellMessage .= $oPage->GetP($oExtKeyCellStatus->GetDescription()); break; default: // Do nothing } } $sHtmlValue = $oCellStatus->GetDisplayableValue(); switch (get_class($oCellStatus)) { case 'CellStatus_Issue': $sCellMessage .= $oPage->GetP($oCellStatus->GetDescription()); $sHtml .= '<td class="cell_error" style="border-right:1px #eee solid;">' . Dict::Format('UI:CSVReport-Object-Error', $sHtmlValue) . $sCellMessage . '</td>'; break; case 'CellStatus_SearchIssue': $sCellMessage .= $oPage->GetP($oCellStatus->GetDescription()); $sHtml .= '<td class="cell_error">ERROR: ' . $sHtmlValue . $sCellMessage . '</td>'; break; case 'CellStatus_Ambiguous': $sCellMessage .= $oPage->GetP($oCellStatus->GetDescription()); $sHtml .= '<td class="cell_error" style="border-right:1px #eee solid;">' . Dict::Format('UI:CSVReport-Object-Ambiguous', $sHtmlValue) . $sCellMessage . '</td>'; break; case 'CellStatus_Modify': $sHtml .= '<td class="cell_modified" style="border-right:1px #eee solid;"><b>' . $sHtmlValue . '</b></td>'; break; default: $sHtml .= '<td class="cell_ok" style="border-right:1px #eee solid;">' . $sHtmlValue . $sCellMessage . '</td>'; } } } $sHtml .= "<td class=\"{$sCSSMessageClass}\" style=\"background-color:#f1f1f1;\">{$sMessage}</td>"; $sHtml .= '</tr>'; } $iUnchanged = count($aRes) - $iErrors - $iModified - $iCreated; $sHtml .= '</table>'; $oPage->add('<div class="wizContainer" style="width:auto;display:inline-block;">'); $oPage->add('<form enctype="multipart/form-data" id="wizForm" method="post">'); $oPage->add('<input type="hidden" name="step" value="' . ($iCurrentStep + 1) . '"/>'); $oPage->add('<input type="hidden" name="separator" value="' . htmlentities($sSeparator, ENT_QUOTES, 'UTF-8') . '"/>'); $oPage->add('<input type="hidden" name="text_qualifier" value="' . htmlentities($sTextQualifier, ENT_QUOTES, 'UTF-8') . '"/>'); $oPage->add('<input type="hidden" name="header_line" value="' . $bHeaderLine . '"/>'); $oPage->add('<input type="hidden" name="nb_skipped_lines" value="' . utils::ReadParam('nb_skipped_lines', '0') . '"/>'); $oPage->add('<input type="hidden" name="box_skiplines" value="' . utils::ReadParam('box_skiplines', '0') . '"/>'); $oPage->add('<input type="hidden" name="csvdata" value="' . htmlentities($sCSVData, ENT_QUOTES, 'UTF-8') . '"/>'); $oPage->add('<input type="hidden" name="csvdata_truncated" value="' . htmlentities($sCSVDataTruncated, ENT_QUOTES, 'UTF-8') . '"/>'); $oPage->add('<input type="hidden" name="class_name" value="' . $sClassName . '"/>'); $oPage->add('<input type="hidden" name="advanced" value="' . $bAdvanced . '"/>'); $oPage->add('<input type="hidden" name="encoding" value="' . $sEncoding . '"/>'); $oPage->add('<input type="hidden" name="synchro_scope" value="' . $sSynchroScope . '"/>'); if (!empty($sSynchroScope)) { foreach ($aSynchroUpdate as $sKey => $value) { $oPage->add('<input type="hidden" name="synchro_update[' . $sKey . ']" value="' . $value . '"/>'); } } foreach ($aFieldsMapping as $iNumber => $sAttCode) { $oPage->add('<input type="hidden" name="field[' . $iNumber . ']" value="' . $sAttCode . '"/>'); } foreach ($aSearchFields as $index => $sDummy) { $oPage->add('<input type="hidden" name="search_field[' . $index . ']" value="1"/>'); } $aDisplayFilters = array(); if ($bSimulate) { $aDisplayFilters['unchanged'] = Dict::S('UI:CSVImport:ObjectsWillStayUnchanged'); $aDisplayFilters['modified'] = Dict::S('UI:CSVImport:ObjectsWillBeModified'); $aDisplayFilters['added'] = Dict::S('UI:CSVImport:ObjectsWillBeAdded'); $aDisplayFilters['errors'] = Dict::S('UI:CSVImport:ObjectsWillHaveErrors'); } else { $aDisplayFilters['unchanged'] = Dict::S('UI:CSVImport:ObjectsRemainedUnchanged'); $aDisplayFilters['modified'] = Dict::S('UI:CSVImport:ObjectsWereModified'); $aDisplayFilters['added'] = Dict::S('UI:CSVImport:ObjectsWereAdded'); $aDisplayFilters['errors'] = Dict::S('UI:CSVImport:ObjectsHadErrors'); } $oPage->add('<p><input type="checkbox" checked id="show_unchanged" onClick="ToggleRows(\'row_unchanged\')"/> <img src="../images/unchanged.png"> ' . sprintf($aDisplayFilters['unchanged'], $iUnchanged) . '  '); $oPage->add('<input type="checkbox" checked id="show_modified" onClick="ToggleRows(\'row_modified\')"/> <img src="../images/modified.png"> ' . sprintf($aDisplayFilters['modified'], $iModified) . '  '); $oPage->add('<input type="checkbox" checked id="show_created" onClick="ToggleRows(\'row_added\')"/> <img src="../images/added.png"> ' . sprintf($aDisplayFilters['added'], $iCreated) . '  '); $oPage->add('<input type="checkbox" checked id="show_errors" onClick="ToggleRows(\'row_error\')"/> <img src="../images/error.png"> ' . sprintf($aDisplayFilters['errors'], $iErrors) . '</p>'); $oPage->add('<div class="white" style="display:inline-block">'); $oPage->add($sHtml); $oPage->add('</div> <!-- end of preview -->'); $oPage->add('<p>'); if ($bSimulate) { $oPage->add('<input type="button" value="' . Dict::S('UI:Button:Restart') . '" onClick="CSVRestart()"/> '); } $oPage->add('<input type="button" value="' . Dict::S('UI:Button:Back') . '" onClick="CSVGoBack()"/> '); $bShouldConfirm = false; if ($bSimulate) { // if there are *too many* changes, we should ask the user for a confirmation if (count($aRes) >= MetaModel::GetConfig()->Get('csv_import_min_object_confirmation')) { $fErrorsPercentage = 100.0 * $iErrors / count($aRes); if ($fErrorsPercentage >= MetaModel::GetConfig()->Get('csv_import_errors_percentage')) { $sMessage = Dict::Format('UI:CSVReport-Stats-Errors', $fErrorsPercentage); $bShouldConfirm = true; } $fCreatedPercentage = 100.0 * $iCreated / count($aRes); if ($fCreatedPercentage >= MetaModel::GetConfig()->Get('csv_import_creations_percentage')) { $sMessage = Dict::Format('UI:CSVReport-Stats-Created', $fCreatedPercentage); $bShouldConfirm = true; } $fModifiedPercentage = 100.0 * $iModified / count($aRes); if ($fModifiedPercentage >= MetaModel::GetConfig()->Get('csv_import_modifications_percentage')) { $sMessage = Dict::Format('UI:CSVReport-Stats-Modified', $fModifiedPercentage); $bShouldConfirm = true; } } $iCount = count($aRes); //$oPage->add('<input type="submit" value="'.Dict::S('UI:Button:DoImport').'" onClick="$(\'#wizForm\').block();"/></p>'); $sConfirm = $bShouldConfirm ? 'true' : 'false'; $oPage->add('<input type="button" value="' . Dict::S('UI:Button:DoImport') . "\" onClick=\"return DoSubmit({$sConfirm});\"/></p>"); } else { $oPage->add('<input type="submit" value="' . Dict::S('UI:Button:Done') . '"/></p>'); } $oPage->add('</form>'); $oPage->add('</div> <!-- end of wizForm -->'); if ($bShouldConfirm) { $sYesButton = Dict::S('UI:Button:Ok'); $sNoButton = Dict::S('UI:Button:Cancel'); $oPage->add('<div id="dlg_confirmation" title="' . htmlentities(Dict::S('UI:CSVImportConfirmTitle'), ENT_QUOTES, 'UTF-8') . '">'); $oPage->add('<p style="text-align:center"><b>' . $sMessage . '</b></p>'); $oPage->add('<p style="text-align:center">' . htmlentities(Dict::S('UI:CSVImportConfirmMessage'), ENT_QUOTES, 'UTF-8') . '</p>'); $oPage->add('<div id="confirmation_chart"></div>'); $oPage->add('</div> <!-- end of dlg_confirmation -->'); $oPage->add_ready_script(<<<EOF \t\$('#dlg_confirmation').dialog( \t\t{ \t\t\theight: 'auto', \t\t\twidth: 500, \t\t\tmodal:true, \t\t\tautoOpen: false, \t\t\tbuttons: \t\t\t{ \t\t\t\t'{$sYesButton}': RunImport, \t\t\t\t'{$sNoButton}': CancelImport \t\t\t} \t\t}); \t\tswfobject.embedSWF(\t"../images/open-flash-chart.swf", \t\t\t\t\t\t\t"confirmation_chart", \t\t\t\t\t\t\t"100%", "300","9.0.0", \t\t\t\t\t\t\t"expressInstall.swf", \t\t\t\t\t\t\t{}, \t\t\t\t\t\t\t{'wmode': 'transparent'} \t\t\t\t\t\t); EOF ); } $sErrors = addslashes(Dict::Format('UI:CSVImportError_items', $iErrors)); $sCreated = addslashes(Dict::Format('UI:CSVImportCreated_items', $iCreated)); $sModified = addslashes(Dict::Format('UI:CSVImportModified_items', $iModified)); $sUnchanged = addslashes(Dict::Format('UI:CSVImportUnchanged_items', $iUnchanged)); $oPage->add_script(<<<EOF function CSVGoBack() { \t\$('input[name=step]').val({$iCurrentStep}-1); \t\$('#wizForm').submit(); \t } function CSVRestart() { \t\$('input[name=step]').val(1); \t\$('#wizForm').submit(); \t } function ToggleRows(sCSSClass) { \t\$('.'+sCSSClass).toggle(); } function DoSubmit(bConfirm) { \tif (bConfirm) //Ask for a confirmation \t{ \t\t\$('#dlg_confirmation').dialog('open'); \t} \telse \t{ \t\t// Submit the form \t\t\$('#wizForm').block(); \t\t\$('#wizForm').submit(); \t} \treturn false; } function CancelImport() { \t\$('#dlg_confirmation').dialog('close'); } function RunImport() { \t\$('#dlg_confirmation').dialog('close'); \t// Submit the form \t\$('#wizForm').block(); \t\$('#wizForm').submit(); } function open_flash_chart_data() { \tvar iErrors = {$iErrors}; \tvar iModified = {$iModified}; \tvar iCreated = {$iCreated}; \tvar iUnchanged = {$iUnchanged}; \tvar fAlpha = 0.9; \t \tvar oResult = { \t\t"elements": [ \t\t\t{ \t\t\t\t"type": "pie", \t\t\t\t"tip": "#label# (#percent#)", \t\t\t\t"gradient-fill": true, \t\t\t\t"font-size": 14, \t\t\t\t"colours":[], \t\t\t\t"values": [], \t\t\t\t"animate":[ \t\t\t { \t\t\t "type": "fade" \t\t\t } \t\t ] \t\t\t} \t\t], \t\t"x_axis": null, \t\t"font-size": 14, \t\t"bg_colour": "#EEEEEE" \t}; \tif (iErrors > 0) \t{ \t\tvar oErrors = \t\t{ \t\t\t"value": iErrors, \t\t\t"label": "{$sErrors}", \t\t\t"alpha": fAlpha, \t\t\t"label-colour": "#CC3333", \t\t}; \t\toResult.elements[0].values.push(oErrors); \t\toResult.elements[0].colours.push('#FF6666'); \t} \tif (iModified > 0) \t{ \t\tvar oModified = \t\t{ \t\t\t"value": iModified, \t\t\t"label": "{$sModified}", \t\t\t"alpha": fAlpha, \t\t\t"label-colour": "#3333CC", \t\t}; \t\toResult.elements[0].values.push(oModified); \t\toResult.elements[0].colours.push('#6666FF'); \t} \tif (iCreated > 0) \t{ \t\tvar oCreated = \t\t{ \t\t\t"value": iCreated, \t\t\t"label": "{$sCreated}", \t\t\t"alpha": fAlpha, \t\t\t"label-colour": "#33CC33", \t\t\t \t\t}; \t\toResult.elements[0].values.push(oCreated); \t\toResult.elements[0].colours.push('#66FF66'); \t} \tif (iUnchanged > 0) \t{ \t\tvar oUnchanged = \t\t{ \t\t\t"value": iUnchanged, \t\t\t"label": "{$sUnchanged}", \t\t\t"alpha": fAlpha, \t\t\t"label-colour": "#333333", \t\t\t \t\t}; \t\toResult.elements[0].values.push(oUnchanged); \t\toResult.elements[0].colours.push('#666666'); \t} \treturn JSON.stringify(oResult); } EOF ); if ($iErrors > 0) { return $aResult; } else { return null; } }
/** * Check the user's password against the LDAP server * Algorithm: * 1) Connect to the LDAP server, using a predefined account (or anonymously) * 2) Search for the specified user, based on a specific search query/pattern * 3) If exactly one user is found, continue, otherwise return false (wrong user or wrong query configured) * 3) Bind again to LDAP using the DN of the found user and the password * 4) If the bind is successful return true, otherwise return false (wrong password) * @param string $sPassword The user's password to validate against the LDAP server * @return boolean True if the password is Ok, false otherwise */ public function CheckCredentials($sPassword) { $sLDAPHost = MetaModel::GetModuleSetting('authent-ldap', 'host', 'localhost'); $iLDAPPort = MetaModel::GetModuleSetting('authent-ldap', 'port', 389); $sDefaultLDAPUser = MetaModel::GetModuleSetting('authent-ldap', 'default_user', ''); $sDefaultLDAPPwd = MetaModel::GetModuleSetting('authent-ldap', 'default_pwd', ''); $hDS = @ldap_connect($sLDAPHost, $iLDAPPort); if ($hDS === false) { $this->LogMessage("ldap_authentication: can not connect to the LDAP server '{$sLDAPHost}' (port: {$iLDAPPort}). Check the configuration file config-itop.php."); return false; } $aOptions = MetaModel::GetModuleSetting('authent-ldap', 'options', array()); foreach ($aOptions as $name => $value) { ldap_set_option($hDS, $name, $value); } if ($bind = @ldap_bind($hDS, $sDefaultLDAPUser, $sDefaultLDAPPwd)) { // Search for the person, using the specified query expression $sLDAPUserQuery = MetaModel::GetModuleSetting('authent-ldap', 'user_query', ''); $sBaseDN = MetaModel::GetModuleSetting('authent-ldap', 'base_dn', ''); $sLogin = $this->Get('login'); $iContactId = $this->Get('contactid'); $sFirstName = ''; $sLastName = ''; $sEMail = ''; if ($iContactId > 0) { $oPerson = MetaModel::GetObject('Person', $iContactId); if (is_object($oPerson)) { $sFirstName = $oPerson->Get('first_name'); $sLastName = $oPerson->Get('name'); $sEMail = $oPerson->Get('email'); } } // %1$s => login // %2$s => first name // %3$s => last name // %4$s => email $sQuery = sprintf($sLDAPUserQuery, $sLogin, $sFirstName, $sLastName, $sEMail); $hSearchResult = @ldap_search($hDS, $sBaseDN, $sQuery); $iCountEntries = $hSearchResult !== false ? @ldap_count_entries($hDS, $hSearchResult) : 0; switch ($iCountEntries) { case 1: // Exactly one entry found, let's check the password by trying to bind with this user $aEntry = ldap_get_entries($hDS, $hSearchResult); $sUserDN = $aEntry[0]['dn']; $bUserBind = @ldap_bind($hDS, $sUserDN, $sPassword); if ($bUserBind !== false && !empty($sPassword)) { ldap_unbind($hDS); return true; // Password Ok } $this->LogMessage("ldap_authentication: wrong password for user: '******'."); return false; // Wrong password break; case 0: // User not found... $this->LogMessage("ldap_authentication: no entry found with the query '{$sQuery}', base_dn = '{$sBaseDN}'. User not found in LDAP."); break; default: // More than one entry... maybe the query is not specific enough... $this->LogMessage("ldap_authentication: several (" . ldap_count_entries($hDS, $hSearchResult) . ") entries match the query '{$sQuery}', base_dn = '{$sBaseDN}', check that the query defined in config-itop.php is specific enough."); } return false; } else { // Trace: invalid default user for LDAP initial binding $this->LogMessage("ldap_authentication: can not bind to the LDAP server '{$sLDAPHost}' (port: {$iLDAPPort}), user='******', pwd='{$sDefaultLDAPPwd}'. Error: '" . ldap_error($hDS) . "'. Check the configuration file config-itop.php."); return false; } }
ReloadAndDisplay($oP, $oObj, 'apply_stimulus', $sMessage, $sSeverity); } } else { $oP->set_title(Dict::S('UI:ErrorPageTitle')); $oP->P(Dict::S('UI:ObjectDoesNotExist')); } break; /////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////// case 'swf_navigator': // Graphical display of the relations "impact" / "depends on" $sClass = utils::ReadParam('class', '', false, 'class'); $id = utils::ReadParam('id', 0); $sRelation = utils::ReadParam('relation', 'impact'); $aResults = array(); $oObj = MetaModel::GetObject($sClass, $id); $oObj->GetRelatedObjects($sRelation, 20, $aResults); $oP->AddTabContainer('Navigator'); $oP->SetCurrentTabContainer('Navigator'); $sFirstTab = MetaModel::GetConfig()->Get('impact_analysis_first_tab'); if ($sFirstTab == 'list') { DisplayNavigatorListTab($oP, $aResults, $sRelation, $oObj); DisplayNavigatorGraphicsTab($oP, $aResults, $sClass, $id, $sRelation, $oAppContext); } else { DisplayNavigatorGraphicsTab($oP, $aResults, $sClass, $id, $sRelation, $oAppContext); DisplayNavigatorListTab($oP, $aResults, $sRelation, $oObj); } $oP->SetCurrentTab(''); break; /////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
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(); } } }
/** * Common to the recording of link set changes (add/remove/modify) */ private function PrepareChangeOpLinkSet($iLinkSetOwnerId, $oLinkSet, $sChangeOpClass, $aOriginalValues = null) { if ($iLinkSetOwnerId <= 0) { return null; } if (!is_subclass_of($oLinkSet->GetHostClass(), 'CMDBObject')) { // The link set owner class does not keep track of its history return null; } // Determine the linked item class and id // if ($oLinkSet->IsIndirect()) { // The "item" is on the other end (N-N links) $sExtKeyToRemote = $oLinkSet->GetExtKeyToRemote(); $oExtKeyToRemote = MetaModel::GetAttributeDef(get_class($this), $sExtKeyToRemote); $sItemClass = $oExtKeyToRemote->GetTargetClass(); if ($aOriginalValues) { // Get the value from the original values $iItemId = $aOriginalValues[$sExtKeyToRemote]; } else { $iItemId = $this->Get($sExtKeyToRemote); } } else { // I am the "item" (1-N links) $sItemClass = get_class($this); $iItemId = $this->GetKey(); } // Get the remote object, to determine its exact class // Possible optimization: implement a tool in MetaModel, to get the final class of an object (not always querying + query reduced to a select on the root table! $oOwner = MetaModel::GetObject($oLinkSet->GetHostClass(), $iLinkSetOwnerId, false); if ($oOwner) { $sLinkSetOwnerClass = get_class($oOwner); $oMyChangeOp = MetaModel::NewObject($sChangeOpClass); $oMyChangeOp->Set("objclass", $sLinkSetOwnerClass); $oMyChangeOp->Set("objkey", $iLinkSetOwnerId); $oMyChangeOp->Set("attcode", $oLinkSet->GetCode()); $oMyChangeOp->Set("item_class", $sItemClass); $oMyChangeOp->Set("item_id", $iItemId); return $oMyChangeOp; } else { // Depending on the deletion order, it may happen that the id is already invalid... ignore return null; } }
function DisplayBareProperties(WebPage $oPage, $bEditMode = false, $sPrefix = '', $aExtraParams = array()) { if ($bEditMode) { return; } // Not editable $oPage->add('<table style="vertical-align:top"><tr style="vertical-align:top"><td>'); $aDetails = array(); $sClass = get_class($this); $oPage->add('<fieldset>'); $oPage->add('<legend>' . Dict::S('Core:SynchroReplica:PrivateDetails') . '</legend>'); $aZList = MetaModel::FlattenZlist(MetaModel::GetZListItems($sClass, 'details')); foreach ($aZList as $sAttCode) { $sDisplayValue = $this->GetAsHTML($sAttCode); $aDetails[] = array('label' => '<span title="' . MetaModel::GetDescription($sClass, $sAttCode) . '">' . MetaModel::GetLabel($sClass, $sAttCode) . '</span>', 'value' => $sDisplayValue); } $oPage->Details($aDetails); $oPage->add('</fieldset>'); if (strlen($this->Get('dest_class')) > 0) { $oDestObj = MetaModel::GetObject($this->Get('dest_class'), $this->Get('dest_id'), false); if (is_object($oDestObj)) { $oPage->add('<fieldset>'); $oPage->add('<legend>' . Dict::Format('Core:SynchroReplica:TargetObject', $oDestObj->GetHyperlink()) . '</legend>'); $oDestObj->DisplayBareProperties($oPage, false, $sPrefix, $aExtraParams); $oPage->add('<fieldset>'); } } $oPage->add('</td><td>'); $oPage->add('<fieldset>'); $oPage->add('<legend>' . Dict::S('Core:SynchroReplica:PublicData') . '</legend>'); $oSource = MetaModel::GetObject('SynchroDataSource', $this->Get('sync_source_id')); $sSQLTable = $oSource->GetDataTable(); $aData = $this->LoadExtendedDataFromTable($sSQLTable); $aHeaders = array('attcode' => array('label' => 'Attribute Code', 'description' => ''), 'data' => array('label' => 'Value', 'description' => '')); $aRows = array(); foreach ($aData as $sKey => $value) { $aRows[] = array('attcode' => $sKey, 'data' => $value); } $oPage->Table($aHeaders, $aRows); $oPage->add('</fieldset>'); $oPage->add('</td></tr></table>'); }
/** * Downloads a document to the browser, either as 'inline' or 'attachment' * * @param WebPage $oPage The web page for the output * @param string $sClass Class name of the object * @param mixed $id Identifier of the object * @param string $sAttCode Name of the attribute containing the document to download * @param string $sContentDisposition Either 'inline' or 'attachment' * @return none */ function DownloadDocument(WebPage $oPage, $sClass, $id, $sAttCode, $sContentDisposition = 'attachment') { try { $oObj = MetaModel::GetObject($sClass, $id, false, false); if (!is_object($oObj)) { throw new Exception("Invalid id ({$id}) for class '{$sClass}' - the object does not exist or you are not allowed to view it"); } $oDocument = $oObj->Get($sAttCode); if (is_object($oDocument)) { $oPage->TrashUnexpectedOutput(); $oPage->SetContentType($oDocument->GetMimeType()); $oPage->SetContentDisposition($sContentDisposition, $oDocument->GetFileName()); $oPage->add($oDocument->GetData()); } } catch (Exception $e) { $oPage->p($e->getMessage()); } }
foreach ($aResults as $sClass => $aObjects) { $oSet = CMDBObjectSet::FromArray($sClass, $aObjects); $oPage->add("<h1>" . MetaModel::GetRelationDescription($sRelation) . ' ' . $oObj->GetName() . "</h1>\n"); $oPage->add("<div class=\"page_header\">\n"); $oPage->add("<h2>" . MetaModel::GetClassIcon($sClass) . " <span class=\"hilite\">" . Dict::Format('UI:Search:Count_ObjectsOf_Class_Found', count($aObjects), Metamodel::GetName($sClass)) . "</h2>\n"); $oPage->add("</div>\n"); $oBlock = DisplayBlock::FromObjectSet($oSet, 'list'); $oBlock->Display($oPage, $iBlock++); $oPage->P(' '); // Some space ? } break; case 'xml': default: $oPage->SetContentType('text/xml'); $oObj = MetaModel::GetObject($sClass, $id, true); // Build the root XML part $oXmlDoc = new DOMDocument('1.0', 'UTF-8'); $oXmlRoot = $oXmlDoc->CreateElement('root'); $oXmlNode = $oXmlDoc->CreateElement('node'); $oXmlNode->SetAttribute('id', $oObj->GetKey()); $oXmlNode->SetAttribute('obj_class', get_class($oObj)); $oXmlNode->SetAttribute('obj_class_name', htmlspecialchars(MetaModel::GetName(get_class($oObj)))); $oXmlNode->SetAttribute('name', htmlspecialchars($oObj->GetRawName())); $oXmlNode->SetAttribute('icon', BuildIconPath($oObj->GetIcon(false))); // Hard coded for the moment AddNodeDetails($oXmlNode, $oObj); $oLinks = $oXmlDoc->CreateElement("links"); $oXmlRoot->SetAttribute('position', 'left'); $oXmlRoot->SetAttribute('title', MetaModel::GetRelationDescription($sRelation) . ' ' . htmlspecialchars($oObj->GetRawName())); IssueLog::Info(__FUNCTION__ . " Rel: {$sRelation}");
/** * Process the reply made from a form built with DisplayBulkModifyForm */ public static function DoBulkModify($oP, $sClass, $aSelectedObj, $sCustomOperation, $bPreview, $sCancelUrl, $aContextData = array()) { $aHeaders = array('form::select' => array('label' => "<input type=\"checkbox\" onClick=\"CheckAll('.selectList:not(:disabled)', this.checked);\"></input>", 'description' => Dict::S('UI:SelectAllToggle+')), 'object' => array('label' => MetaModel::GetName($sClass), 'description' => Dict::S('UI:ModifiedObject')), 'status' => array('label' => Dict::S('UI:BulkModifyStatus'), 'description' => Dict::S('UI:BulkModifyStatus+')), 'errors' => array('label' => Dict::S('UI:BulkModifyErrors'), 'description' => Dict::S('UI:BulkModifyErrors+'))); $aRows = array(); $oP->add("<div class=\"page_header\">\n"); $oP->add("<h1>" . MetaModel::GetClassIcon($sClass) . " " . Dict::Format('UI:Modify_N_ObjectsOf_Class', count($aSelectedObj), MetaModel::GetName($sClass)) . "</h1>\n"); $oP->add("</div>\n"); $oP->set_title(Dict::Format('UI:Modify_N_ObjectsOf_Class', count($aSelectedObj), $sClass)); if (!$bPreview) { // Not in preview mode, do the update for real $sTransactionId = utils::ReadPostedParam('transaction_id', ''); if (!utils::IsTransactionValid($sTransactionId, false)) { throw new Exception(Dict::S('UI:Error:ObjectAlreadyUpdated')); } utils::RemoveTransaction($sTransactionId); } $iPreviousTimeLimit = ini_get('max_execution_time'); $iLoopTimeLimit = MetaModel::GetConfig()->Get('max_execution_time_per_loop'); foreach ($aSelectedObj as $iId) { set_time_limit($iLoopTimeLimit); $oObj = MetaModel::GetObject($sClass, $iId); $aErrors = $oObj->UpdateObjectFromPostedForm(''); $bResult = count($aErrors) == 0; if ($bResult) { list($bResult, $aErrors) = $oObj->CheckToWrite(true); } if ($bPreview) { $sStatus = $bResult ? Dict::S('UI:BulkModifyStatusOk') : Dict::S('UI:BulkModifyStatusError'); } else { $sStatus = $bResult ? Dict::S('UI:BulkModifyStatusModified') : Dict::S('UI:BulkModifyStatusSkipped'); } $sCSSClass = $bResult ? HILIGHT_CLASS_NONE : HILIGHT_CLASS_CRITICAL; $sChecked = $bResult ? 'checked' : ''; $sDisabled = $bResult ? '' : 'disabled'; $aRows[] = array('form::select' => "<input type=\"checkbox\" class=\"selectList\" {$sChecked} {$sDisabled}\"></input>", 'object' => $oObj->GetHyperlink(), 'status' => $sStatus, 'errors' => '<p>' . ($bResult ? '' : implode('</p><p>', $aErrors)) . '</p>', '@class' => $sCSSClass); if ($bResult && !$bPreview) { $oObj->DBUpdate(); } } set_time_limit($iPreviousTimeLimit); $oP->Table($aHeaders, $aRows); if ($bPreview) { $sFormAction = utils::GetAbsoluteUrlAppRoot() . 'pages/UI.php'; // No parameter in the URL, the only parameter will be the ones passed through the form // Form to submit: $oP->add("<form method=\"post\" action=\"{$sFormAction}\" enctype=\"multipart/form-data\">\n"); $aDefaults = utils::ReadParam('default', array()); $oAppContext = new ApplicationContext(); $oP->add($oAppContext->GetForForm()); foreach ($aContextData as $sKey => $value) { $oP->add("<input type=\"hidden\" name=\"{$sKey}\" value=\"{$value}\">\n"); } $oP->add("<input type=\"hidden\" name=\"operation\" value=\"{$sCustomOperation}\">\n"); $oP->add("<input type=\"hidden\" name=\"class\" value=\"{$sClass}\">\n"); $oP->add("<input type=\"hidden\" name=\"preview_mode\" value=\"0\">\n"); $oP->add("<input type=\"hidden\" name=\"transaction_id\" value=\"" . utils::GetNewTransactionId() . "\">\n"); $oP->add("<button type=\"button\" class=\"action cancel\" onClick=\"window.location.href='{$sCancelUrl}'\">" . Dict::S('UI:Button:Cancel') . "</button> \n"); $oP->add("<button type=\"submit\" class=\"action\"><span>" . Dict::S('UI:Button:ModifyAll') . "</span></button>\n"); foreach ($_POST as $sKey => $value) { if (preg_match('/attr_(.+)/', $sKey, $aMatches)) { // Beware: some values (like durations) are passed as arrays if (is_array($value)) { foreach ($value as $vKey => $vValue) { $oP->add("<input type=\"hidden\" name=\"{$sKey}[{$vKey}]\" value=\"" . htmlentities($vValue, ENT_QUOTES, 'UTF-8') . "\">\n"); } } else { $oP->add("<input type=\"hidden\" name=\"{$sKey}\" value=\"" . htmlentities($value, ENT_QUOTES, 'UTF-8') . "\">\n"); } } } $oP->add("</form>\n"); } else { $oP->add("<button type=\"button\" onClick=\"window.location.href='{$sCancelUrl}'\" class=\"action\"><span>" . Dict::S('UI:Button:Done') . "</span></button>\n"); } }
/** * @return boolean True if the task record can be deleted */ public function Process() { // By default: consider that the task is not completed $bRet = false; // Attempt to take the ownership $iStatus = $this->MarkAsRunning(); if ($iStatus == self::OK) { try { $sStatus = $this->DoProcess(); if ($this->Get('event_id') != 0) { $oEventLog = MetaModel::GetObject('Event', $this->Get('event_id')); $oEventLog->Set('message', $sStatus); $oEventLog->DBUpdate(); } $bRet = true; } catch (Exception $e) { $iRemaining = $this->Get('remaining_retries'); if ($iRemaining > 0) { $iRetryDelay = $this->GetRetryDelay(); IssueLog::Info('Failed to process async task #' . $this->GetKey() . ' - reason: ' . $e->getMessage() . ' - remaining retries: ' . $iRemaining . ' - next retry in ' . $iRetryDelay . 's'); $this->Set('remaining_retries', $iRemaining - 1); $this->Set('status', 'planned'); $this->Set('started', null); $this->Set('planned', time() + $iRetryDelay); $this->DBUpdate(); } else { IssueLog::Error('Failed to process async task #' . $this->GetKey() . ' - reason: ' . $e->getMessage()); } } } else { // Already done or being handled by another process... skip... $bRet = false; } return $bRet; }
/** * Helper function to load the objects from a standard XML file into the database * @param $sFilePath string The full path to the XML file to load * @param $bUpdateKeyCacheOnly bool Set to true to *just* update the keys cache but not reload the objects */ function LoadFile($sFilePath, $bUpdateKeyCacheOnly = false) { global $aKeys; $oXml = simplexml_load_file($sFilePath); $aReplicas = array(); foreach ($oXml as $sClass => $oXmlObj) { if (!MetaModel::IsValidClass($sClass)) { SetupPage::log_error("Unknown class - {$sClass}"); throw new Exception("Unknown class - {$sClass}"); } $iSrcId = (int) $oXmlObj['id']; // Mandatory to cast // Import algorithm // Here enumerate all the attributes of the object // for all attribute that is neither an external field // not an external key, assign it // Store all external keys for further reference // Create the object an store the correspondance between its newly created Id // and its original Id // Once all the objects have been created re-assign all the external keys to // their actual Ids $iExistingId = $this->GetObjectKey($sClass, $iSrcId); if ($iExistingId != 0) { $oTargetObj = MetaModel::GetObject($sClass, $iExistingId); } else { $oTargetObj = MetaModel::NewObject($sClass); } foreach ($oXmlObj as $sAttCode => $oSubNode) { if (!MetaModel::IsValidAttCode($sClass, $sAttCode)) { $sMsg = "Unknown attribute code - {$sClass}/{$sAttCode}"; continue; // ignore silently... //SetupPage::log_error($sMsg); //throw(new Exception($sMsg)); } $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode); if ($oAttDef->IsWritable() && $oAttDef->IsScalar()) { if ($oAttDef->IsExternalKey()) { if (substr(trim($oSubNode), 0, 6) == 'SELECT') { $sQuery = trim($oSubNode); $oSet = new DBObjectSet(DBObjectSearch::FromOQL($sQuery)); $iMatches = $oSet->Count(); if ($iMatches == 1) { $oFoundObject = $oSet->Fetch(); $iExtKey = $oFoundObject->GetKey(); } else { $sMsg = "Ext key not reconcilied - {$sClass}/{$iSrcId} - {$sAttCode}: '" . $sQuery . "' - found {$iMatches} matche(s)"; SetupPage::log_error($sMsg); $this->m_aErrors[] = $sMsg; $iExtKey = 0; } } else { $iDstObj = (int) $oSubNode; // Attempt to find the object in the list of loaded objects $iExtKey = $this->GetObjectKey($oAttDef->GetTargetClass(), $iDstObj); if ($iExtKey == 0) { $iExtKey = -$iDstObj; // Convention: Unresolved keys are stored as negative ! $oTargetObj->RegisterAsDirty(); } // here we allow external keys to be invalid because we will resolve them later on... } //$oTargetObj->CheckValue($sAttCode, $iExtKey); $oTargetObj->Set($sAttCode, $iExtKey); } elseif ($oAttDef instanceof AttributeBlob) { $sMimeType = (string) $oSubNode->mimetype; $sFileName = (string) $oSubNode->filename; $data = base64_decode((string) $oSubNode->data); $oDoc = new ormDocument($data, $sMimeType, $sFileName); $oTargetObj->Set($sAttCode, $oDoc); } else { $value = (string) $oSubNode; if ($value == '') { $value = $oAttDef->GetNullValue(); } $res = $oTargetObj->CheckValue($sAttCode, $value); if ($res !== true) { // $res contains the error description $sMsg = "Value not allowed - {$sClass}/{$iSrcId} - {$sAttCode}: '" . $oSubNode . "' ; {$res}"; SetupPage::log_error($sMsg); $this->m_aErrors[] = $sMsg; } $oTargetObj->Set($sAttCode, $value); } } } $this->StoreObject($sClass, $oTargetObj, $iSrcId, $bUpdateKeyCacheOnly, $bUpdateKeyCacheOnly); } return true; }
function DisplayForm(WebPage $oP, $sAction = '', $sExpression = '', $sQueryId = '', $sFormat = null) { $oExportSearch = null; $oP->add_linked_script(utils::GetAbsoluteUrlAppRoot() . 'js/tabularfieldsselector.js'); $oP->add_linked_script(utils::GetAbsoluteUrlAppRoot() . 'js/jquery.dragtable.js'); $oP->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot() . 'css/dragtable.css'); $oP->add('<form id="export-form" action="' . $sAction . '" method="post" data-state="not-yet-started">'); $bExpressionIsValid = true; $sExpressionError = ''; if ($sExpression === null && $sQueryId === null) { $bExpressionIsValid = false; } else { if ($sExpression !== '') { try { $oExportSearch = DBObjectSearch::FromOQL($sExpression); } catch (OQLException $e) { $bExpressionIsValid = false; $sExpressionError = $e->getMessage(); } } } if (!$bExpressionIsValid) { DisplayExpressionForm($oP, $sAction, $sExpression, $sExpressionError); return; } if ($sExpression !== '') { $oP->add('<input type="hidden" name="expression" value="' . htmlentities($sExpression, ENT_QUOTES, 'UTF-8') . '">'); $oExportSearch = DBObjectSearch::FromOQL($sExpression); } else { $oQuery = MetaModel::GetObject('QueryOQL', $sQueryId); $oExportSearch = DBObjectSearch::FromOQL($oQuery->Get('oql')); $oP->add('<input type="hidden" name="query" value="' . htmlentities($sQueryId, ENT_QUOTES, 'UTF-8') . '">'); } $aFormPartsByFormat = array(); $aAllFormParts = array(); if ($sFormat == null) { // No specific format chosen $sDefaultFormat = utils::ReadParam('format', 'xlsx'); $oP->add('<p>' . Dict::S('Core:BulkExport:ExportFormatPrompt') . ' <select name="format" id="format_selector">'); $aSupportedFormats = BulkExport::FindSupportedFormats(); asort($aSupportedFormats); foreach ($aSupportedFormats as $sFormatCode => $sLabel) { $sSelected = $sFormatCode == $sDefaultFormat ? 'selected' : ''; $oP->add('<option value="' . $sFormatCode . '" ' . $sSelected . '>' . htmlentities($sLabel, ENT_QUOTES, 'UTF-8') . '</option>'); $oExporter = BulkExport::FindExporter($sFormatCode); $oExporter->SetObjectList($oExportSearch); $aParts = $oExporter->EnumFormParts(); foreach ($aParts as $sPartId => $void) { $aAllFormParts[$sPartId] = $oExporter; } $aFormPartsByFormat[$sFormatCode] = array_keys($aParts); } $oP->add('</select></p>'); } else { // One specific format was chosen $oP->add('<input type="hidden" name="format" value="' . htmlentities($sFormat, ENT_QUOTES, 'UTF-8') . '">'); $oExporter = BulkExport::FindExporter($sFormat, $oExportSearch); $aParts = $oExporter->EnumFormParts(); foreach ($aParts as $sPartId => $void) { $aAllFormParts[$sPartId] = $oExporter; } $aFormPartsByFormat[$sFormat] = array_keys($aAllFormParts); } foreach ($aAllFormParts as $sPartId => $oExport) { $oP->add('<div class="form_part" id="form_part_' . $sPartId . '">'); $oExport->DisplayFormPart($oP, $sPartId); $oP->add('</div>'); } $oP->add('</form>'); $oP->add('<div id="export-feedback" style="display:none;"><p class="export-message" style="text-align:center;">' . Dict::S('ExcelExport:PreparingExport') . '</p><div class="export-progress-bar" style="max-width:30em; margin-left:auto;margin-right:auto;"><div class="export-progress-message" style="text-align:center;"></div></div></div>'); $oP->add('<button type="button" id="export-btn">' . Dict::S('UI:Button:Export') . '</button>'); $oP->add('<div id="export_text_result" style="display:none;">'); $oP->add('<div>' . Dict::S('Core:BulkExport:ExportResult') . '</div>'); $oP->add('<textarea id="export_content" style="width:100%;min-height:15em;"></textarea>'); $oP->add('</div>'); $sJSParts = json_encode($aFormPartsByFormat); $sJSCancel = json_encode(Dict::S('UI:Button:Cancel')); $sJSClose = json_encode(Dict::S('UI:Button:Done')); $oP->add_ready_script(<<<EOF window.aFormParts = {$sJSParts}; \$('#format_selector').on('change init', function() { \tExportToggleFormat(\$(this).val()); }).trigger('init'); \t\t \$('.export-progress-bar').progressbar({ \t value: 0, \t change: function() { \t\t\$('.export-progress-message').text( \$(this).progressbar( "value" ) + "%" ); \t }, \t complete: function() { \t\t \$('.export-progress-message').text( '100 %' ); \t } }); ExportInitButton('#export-btn'); EOF ); }
// Therefore, we have to allow users to transform the format according to a given specification: date_format ////////////////////////////////////////////////// // // Statistics // $iCountErrors = 0; $iCountCreations = 0; $iCountUpdates = 0; ////////////////////////////////////////////////// // // Check parameters format/consistency // if (strlen($sCSVData) == 0) { throw new ExchangeException("Missing data - at least one line is expected"); } $oDataSource = MetaModel::GetObject('SynchroDataSource', $iDataSourceId, false); if (is_null($oDataSource)) { throw new ExchangeException("Unknown data source id: '{$iDataSourceId}'"); } $sClass = $oDataSource->GetTargetClass(); if (strlen($sSep) > 1) { throw new ExchangeException("Separator is limited to one character, found '{$sSep}'"); } if (strlen($sQualifier) > 1) { throw new ExchangeException("Text qualifier is limited to one character, found '{$sQualifier}'"); } if (!in_array($sOutput, array('retcode', 'summary', 'details'))) { throw new ExchangeException("Unknown output format: '{$sOutput}'"); } /* $aReportLevels = explode('|', $sReportLevel);
exit - 1; } $iStepCount = ReadMandatoryParam($oP, 'step_count'); $oP->p('Executing a partial synchro - step ' . $iStepCount); $iSource = ReadMandatoryParam($oP, 'source'); $iStatLog = ReadMandatoryParam($oP, 'log'); $iChange = ReadMandatoryParam($oP, 'change'); $sLastFullLoad = ReadMandatoryParam($oP, 'last_full_load', 'raw_data'); $iChunkSize = ReadMandatoryParam($oP, 'chunk'); $oP->p('Last full load: ' . $sLastFullLoad); $oP->p('Chunk size: ' . $iChunkSize); $oP->p('Source: ' . $iSource); try { $oSynchroDataSource = MetaModel::GetObject('SynchroDataSource', $iSource); $oLog = MetaModel::GetObject('SynchroLog', $iStatLog); $oChange = MetaModel::GetObject('CMDBChange', $iChange); if (strlen($sLastFullLoad) > 0) { $oLastFullLoad = new DateTime($sLastFullLoad); $oSynchroExec = new SynchroExecution($oSynchroDataSource, $oLastFullLoad); } else { $oSynchroExec = new SynchroExecution($oSynchroDataSource); } if ($oSynchroExec->DoSynchronizeChunk($oLog, $oChange, $iChunkSize)) { // The last line MUST follow this convention $oP->p("continue"); } else { // The last line MUST follow this convention $oP->p("finished"); } $oP->output(); } catch (Exception $e) {
/** * Helpr to clone (in memory) an object and to apply to it the values taken from a second object * @param DBObject $oObjToClone * @param DBObject $oObjWithValues * @return DBObject The modified clone */ protected function CopyFrom($oObjToClone, $oObjWithValues) { $oObj = MetaModel::GetObject(get_class($oObjToClone), $oObjToClone->GetKey()); foreach (MetaModel::ListAttributeDefs(get_class($oObj)) as $sAttCode => $oAttDef) { if (!in_array($sAttCode, $this->aExcludedColumns) && $oAttDef->IsWritable()) { $oObj->Set($sAttCode, $oObjWithValues->Get($sAttCode)); } } return $oObj; }
static function ParseJsonSet($oMe, $sLinkClass, $sExtKeyToMe, $sJsonSet) { $aSet = json_decode($sJsonSet, true); // true means hash array instead of object $oSet = CMDBObjectSet::FromScratch($sLinkClass); foreach ($aSet as $aLinkObj) { $oLink = MetaModel::NewObject($sLinkClass); foreach ($aLinkObj as $sAttCode => $value) { $oAttDef = MetaModel::GetAttributeDef($sLinkClass, $sAttCode); if ($oAttDef->IsExternalKey() && $value != '' && $value > 0) { // For external keys: load the target object so that external fields // get filled too $oTargetObj = MetaModel::GetObject($oAttDef->GetTargetClass(), $value); $oLink->Set($sAttCode, $oTargetObj); } $oLink->Set($sAttCode, $value); } $oLink->Set($sExtKeyToMe, $oMe->GetKey()); $oSet->AddObject($oLink); } return $oSet; }
/** * Find an object from a polymorph search specification (Rest/Json) * * @param string $sClass Name of the class * @param mixed $key Either search criteria (substructure), or an object or an OQL string. * @param bool $bAllowNullValue Allow the cases such as key = 0 or key = {null} and return null then * @return DBObject The object found * @throws Exception If the input structure is not valid or it could not find exactly one object * @api */ public static function FindObjectFromKey($sClass, $key, $bAllowNullValue = false) { if (is_object($key)) { $res = static::FindObjectFromCriteria($sClass, $key); } elseif (is_numeric($key)) { if ($bAllowNullValue && $key == 0) { $res = null; } else { $res = MetaModel::GetObject($sClass, $key, false); if (is_null($res)) { throw new Exception("Invalid object {$sClass}::{$key}"); } } } elseif (is_string($key)) { // OQL $oSearch = DBObjectSearch::FromOQL($key); $oSet = new DBObjectSet($oSearch); $iCount = $oSet->Count(); if ($iCount == 0) { throw new Exception("No item found for query: {$key}"); } elseif ($iCount > 1) { throw new Exception("Several items found ({$iCount}) for query: {$key}"); } $res = $oSet->Fetch(); } else { throw new Exception("Wrong format for key"); } return $res; }