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; } } }
/** * Use with care! */ public function SetPassword($sNewPassword) { $this->Set('password', $sNewPassword); $oChange = MetaModel::NewObject("CMDBChange"); $oChange->Set("date", time()); $sUserString = CMDBChange::GetCurrentUserName(); $oChange->Set("userinfo", $sUserString); $oChange->DBInsert(); $this->DBUpdateTracked($oChange, true); }
/** * Create the persistant information records, for the current synchronization * In fact, those records ARE defining what is the "current" synchronization */ protected function PrepareLogs() { if (!is_null($this->m_oChange)) { return; } // Create a change used for logging all the modifications/creations happening during the synchro $this->m_oChange = MetaModel::NewObject("CMDBChange"); $this->m_oChange->Set("date", time()); $sUserString = CMDBChange::GetCurrentUserName(); $this->m_oChange->Set("userinfo", $sUserString . ' ' . Dict::S('Core:SyncDataExchangeComment')); $this->m_oChange->Set("origin", 'synchro-data-source'); $iChangeId = $this->m_oChange->DBInsert(); // Start logging this execution (stats + protection against reentrance) // $this->m_oStatLog = new SynchroLog(); $this->m_oStatLog->Set('sync_source_id', $this->m_oDataSource->GetKey()); $this->m_oStatLog->Set('start_date', time()); $this->m_oStatLog->Set('status', 'running'); $this->m_oStatLog->Set('stats_nb_replica_seen', 0); $this->m_oStatLog->Set('stats_nb_replica_total', 0); $this->m_oStatLog->Set('stats_nb_obj_deleted', 0); $this->m_oStatLog->Set('stats_nb_obj_deleted_errors', 0); $this->m_oStatLog->Set('stats_nb_obj_obsoleted', 0); $this->m_oStatLog->Set('stats_nb_obj_obsoleted_errors', 0); $this->m_oStatLog->Set('stats_nb_obj_created', 0); $this->m_oStatLog->Set('stats_nb_obj_created_errors', 0); $this->m_oStatLog->Set('stats_nb_obj_created_warnings', 0); $this->m_oStatLog->Set('stats_nb_obj_updated', 0); $this->m_oStatLog->Set('stats_nb_obj_updated_warnings', 0); $this->m_oStatLog->Set('stats_nb_obj_updated_errors', 0); $this->m_oStatLog->Set('stats_nb_obj_unchanged_warnings', 0); // $this->m_oStatLog->Set('stats_nb_replica_reconciled', 0); $this->m_oStatLog->Set('stats_nb_replica_reconciled_errors', 0); $this->m_oStatLog->Set('stats_nb_replica_disappeared_no_action', 0); $this->m_oStatLog->Set('stats_nb_obj_new_updated', 0); $this->m_oStatLog->Set('stats_nb_obj_new_updated_warnings', 0); $this->m_oStatLog->Set('stats_nb_obj_new_unchanged', 0); $this->m_oStatLog->Set('stats_nb_obj_new_unchanged_warnings', 0); $sSelectTotal = "SELECT SynchroReplica WHERE sync_source_id = :source_id"; $oSetTotal = new DBObjectSet(DBObjectSearch::FromOQL($sSelectTotal), array(), array('source_id' => $this->m_oDataSource->GetKey())); $this->m_iCountAllReplicas = $oSetTotal->Count(); $this->m_oStatLog->Set('stats_nb_replica_total', $this->m_iCountAllReplicas); $this->m_oStatLog->DBInsertTracked($this->m_oChange); }
/** * 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; } }
/** * Get the additional information (defaulting to user name) */ protected static function GetTrackInfo() { if (is_null(self::$m_sInfo)) { return CMDBChange::GetCurrentUserName(); } else { return self::$m_sInfo; } }
$aReconciliationReport[] = $sKey; } } $oP->add_comment("Reconciliation Keys: " . implode(', ', $aReconciliationReport)); foreach ($aWarnings as $sWarning) { $oP->add_comment("Warning: " . $sWarning); } } $oBulk = new BulkChange($sClass, $aData, $aAttList, $aExtKeys, $aFinalReconcilKeys, null, null, $sDateFormat, $bLocalize); if ($bSimulate) { $oMyChange = null; } else { if (strlen($sComment) > 0) { $sMoreInfo = CMDBChange::GetCurrentUserName() . ', Web Service (CSV) - ' . $sComment; } else { $sMoreInfo = CMDBChange::GetCurrentUserName() . ', Web Service (CSV)'; } CMDBObject::SetTrackInfo($sMoreInfo); CMDBObject::SetTrackOrigin('csv-import.php'); $oMyChange = CMDBObject::GetCurrentChange(); } $aRes = $oBulk->Process($oMyChange); ////////////////////////////////////////////////// // // Compute statistics // $iCountErrors = 0; $iCountWarnings = 0; $iCountCreations = 0; $iCountUpdates = 0; $iCountUnchanged = 0;
protected function DoExecute() { CMDBSource::Query('START TRANSACTION'); //CMDBSource::Query('ROLLBACK'); automatique ! //////////////////////////////////////////////////////////////////////////////// // Set the stage // $oProvider = new Organization(); $oProvider->Set('name', 'Test-Provider1'); $oProvider->DBInsert(); $iProvider = $oProvider->GetKey(); $oDM1 = new DeliveryModel(); $oDM1->Set('name', 'Test-DM-1'); $oDM1->Set('org_id', $iProvider); $oDM1->DBInsert(); $iDM1 = $oDM1->GetKey(); $oDM2 = new DeliveryModel(); $oDM2->Set('name', 'Test-DM-2'); $oDM2->Set('org_id', $iProvider); $oDM2->DBInsert(); $iDM2 = $oDM2->GetKey(); //////////////////////////////////////////////////////////////////////////////// // Scenarii // $aScenarii = array(array('description' => 'Add the first customer', 'organizations' => array(array('deliverymodel_id' => $iDM1, 'name' => 'Test-Customer-1')), 'expected-res' => array("Test-Customer-1, , active, 0, , {$iDM1}, Test-DM-1, , Test-DM-1"), 'history_added' => 0, 'history_removed' => 0, 'history_modified' => 0), array('description' => 'Remove the customer by loading an empty set', 'organizations' => array(), 'expected-res' => array(), 'history_added' => 0, 'history_removed' => 0, 'history_modified' => 0), array('description' => 'Create two customers at once', 'organizations' => array(array('deliverymodel_id' => $iDM1, 'name' => 'Test-Customer-1'), array('deliverymodel_id' => $iDM1, 'name' => 'Test-Customer-2')), 'expected-res' => array("Test-Customer-1, , active, 0, , {$iDM1}, Test-DM-1, , Test-DM-1", "Test-Customer-2, , active, 0, , {$iDM1}, Test-DM-1, , Test-DM-1"), 'history_added' => 0, 'history_removed' => 0, 'history_modified' => 0), array('description' => 'Move Customer-1 to the second Delivery Model', 'organizations' => array(array('id' => "SELECT Organization WHERE name='Test-Customer-1'", 'deliverymodel_id' => $iDM2, 'name' => 'Test-Customer-1'), array('deliverymodel_id' => $iDM1, 'name' => 'Test-Customer-2')), 'expected-res' => array("Test-Customer-2, , active, 0, , {$iDM1}, Test-DM-1, , Test-DM-1"), 'history_added' => 0, 'history_removed' => 0, 'history_modified' => 0), array('description' => 'Move Customer-1 back to the first Delivery Model and reset Customer-2 (no Delivery Model)', 'organizations' => array(array('id' => "SELECT Organization WHERE name='Test-Customer-1'", 'deliverymodel_id' => $iDM1, 'name' => 'Test-Customer-1'), array('id' => "SELECT Organization WHERE name='Test-Customer-2'", 'deliverymodel_id' => 0, 'name' => 'Test-Customer-2')), 'expected-res' => array("Test-Customer-1, , active, 0, , {$iDM1}, Test-DM-1, , Test-DM-1"), 'history_added' => 0, 'history_removed' => 0, 'history_modified' => 0)); foreach ($aScenarii as $aScenario) { echo "<h4>" . $aScenario['description'] . "</h4>\n"; $oChange = MetaModel::NewObject("CMDBChange"); $oChange->Set("date", time()); $oChange->Set("userinfo", CMDBChange::GetCurrentUserName()); $oChange->Set("origin", 'custom-extension'); $oChange->DBInsert(); CMDBObject::SetCurrentChange($oChange); $iChange = $oChange->GetKey(); // Prepare set $oLinkset = DBObjectSet::FromScratch('Organization'); foreach ($aScenario['organizations'] as $aOrgData) { if (array_key_exists('id', $aOrgData)) { $sOQL = $aOrgData['id']; $oSet = new DBObjectSet(DBObjectSearch::FromOQL($sOQL)); $oOrg = $oSet->Fetch(); if (!is_object($oOrg)) { throw new Exception('Failed to find the Organization: ' . $sOQL); } } else { $oOrg = MetaModel::NewObject('Organization'); } foreach ($aOrgData as $sAttCode => $value) { if ($sAttCode == 'id') { continue; } $oOrg->Set($sAttCode, $value); } $oLinkset->AddObject($oOrg); } // Write $oDM = MetaModel::GetObject('DeliveryModel', $iDM1); $oDM->Set('customers_list', $oLinkset); $oDM->DBWrite(); // Check Results $bFoundIssue = false; $oDM = MetaModel::GetObject('DeliveryModel', $iDM1); $oLinkset = $oDM->Get('customers_list'); $aRes = $this->StandardizedDump($oLinkset, 'zzz'); $sRes = var_export($aRes, true); echo "Found: <pre>" . $sRes . "</pre>\n"; $sExpectedRes = var_export($aScenario['expected-res'], true); if ($sRes != $sExpectedRes) { $bFoundIssue = true; echo "NOT COMPLIANT!!! Expecting: <pre>" . $sExpectedRes . "</pre>\n"; } // Check History $aQueryParams = array('change' => $iChange, 'objclass' => get_class($oDM), 'objkey' => $oDM->GetKey()); $oAdded = new DBObjectSet(DBSearch::FromOQL("SELECT CMDBChangeOpSetAttributeLinksAddRemove WHERE objclass = :objclass AND objkey = :objkey AND change = :change AND type = 'added'"), array(), $aQueryParams); echo "added: " . $oAdded->Count() . "<br/>\n"; if ($aScenario['history_added'] != $oAdded->Count()) { $bFoundIssue = true; echo "NOT COMPLIANT!!! Expecting: " . $aScenario['history_added'] . "<br/>\n"; } $oRemoved = new DBObjectSet(DBSearch::FromOQL("SELECT CMDBChangeOpSetAttributeLinksAddRemove WHERE objclass = :objclass AND objkey = :objkey AND change = :change AND type = 'removed'"), array(), $aQueryParams); echo "removed: " . $oRemoved->Count() . "<br/>\n"; if ($aScenario['history_removed'] != $oRemoved->Count()) { $bFoundIssue = true; echo "NOT COMPLIANT!!! Expecting: " . $aScenario['history_removed'] . "<br/>\n"; } $oModified = new DBObjectSet(DBSearch::FromOQL("SELECT CMDBChangeOpSetAttributeLinksTune WHERE objclass = :objclass AND objkey = :objkey AND change = :change"), array(), $aQueryParams); echo "modified: " . $oModified->Count() . "<br/>\n"; if ($aScenario['history_modified'] != $oModified->Count()) { $bFoundIssue = true; echo "NOT COMPLIANT!!! Expecting: " . $aScenario['history_modified'] . "<br/>\n"; } if ($bFoundIssue) { throw new Exception('Stopping on failed scenario'); } } }
public function resolveChilds($sStimulusCode) { $oMyChange = MetaModel::NewObject("CMDBChange"); $oMyChange->Set("date", time()); $sUserString = CMDBChange::GetCurrentUserName(); $oMyChange->Set("userinfo", $sUserString . "(automatic resolution)"); $iChangeId = $oMyChange->DBInsert(); if (MetaModel::IsValidClass('UserRequest')) { $sOQL = "SELECT UserRequest WHERE parent_request_id=:ticket"; $oChildRequestSet = new DBObjectSet(DBObjectSearch::FromOQL($sOQL), array(), array('ticket' => $this->GetKey())); //automatically resolve child requests while ($oRequest = $oChildRequestSet->Fetch()) { if ($oRequest->Get('status') != 'resolved') { $oRequest->set('servicesubcategory_id', $this->Get('servicesubcategory_id')); $oRequest->set('service_id', $this->Get('service_id')); $oRequest->set('team_id', $this->Get('team_id')); $oRequest->set('agent_id', $this->Get('agent_id')); $oRequest->set('resolution_code', $this->Get('resolution_code')); $oRequest->set('solution', 'Automatically resolved by incident:[[Incident:' . $this->Get('ref') . ']]'); $oRequest->ApplyStimulus('ev_autoresolve'); $oRequest->DBUpdateTracked($oMyChange); } } } //automatically resolve child incidents $sOQL = "SELECT Incident WHERE parent_incident_id=:ticket"; $oChildIncidentSet = new DBObjectSet(DBObjectSearch::FromOQL($sOQL), array(), array('ticket' => $this->GetKey())); while ($oIncident = $oChildIncidentSet->Fetch()) { if ($oIncident->Get('status') != 'resolved') { $oIncident->set('servicesubcategory_id', $this->Get('servicesubcategory_id')); $oIncident->set('service_id', $this->Get('service_id')); $oIncident->set('team_id', $this->Get('team_id')); $oIncident->set('agent_id', $this->Get('agent_id')); $oIncident->set('resolution_code', $this->Get('resolution_code')); $oIncident->set('solution', 'Automatically resolved by incident:[[Incident:' . $this->Get('ref') . ']]'); $oIncident->ApplyStimulus('ev_autoresolve'); $oIncident->DBUpdateTracked($oMyChange); } } return true; }