/** * Safety net: in case the change is not given, let's guarantee that it will * be set to the current ongoing change (or create a new one) */ protected function OnInsert() { if ($this->Get('change') <= 0) { $this->Set('change', CMDBObject::GetCurrentChange()); } parent::OnInsert(); }
public function Process($iTimeLimit) { $aList = array(); foreach (MetaModel::GetClasses() as $sClass) { foreach (MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef) { if ($oAttDef instanceof AttributeStopWatch) { foreach ($oAttDef->ListThresholds() as $iThreshold => $aThresholdData) { $iPercent = $aThresholdData['percent']; // could be different than the index ! $sNow = date('Y-m-d H:i:s'); $sExpression = "SELECT {$sClass} WHERE {$sAttCode}_laststart AND {$sAttCode}_{$iThreshold}_triggered = 0 AND {$sAttCode}_{$iThreshold}_deadline < '{$sNow}'"; $oFilter = DBObjectSearch::FromOQL($sExpression); $oSet = new DBObjectSet($oFilter); while (time() < $iTimeLimit && ($oObj = $oSet->Fetch())) { $sClass = get_class($oObj); $aList[] = $sClass . '::' . $oObj->GetKey() . ' ' . $sAttCode . ' ' . $iThreshold; // Execute planned actions // foreach ($aThresholdData['actions'] as $aActionData) { $sVerb = $aActionData['verb']; $aParams = $aActionData['params']; $aValues = array(); foreach ($aParams as $def) { if (is_string($def)) { // Old method (pre-2.1.0) non typed parameters $aValues[] = $def; } else { $sParamType = array_key_exists('type', $def) ? $def['type'] : 'string'; switch ($sParamType) { case 'int': $value = (int) $def['value']; break; case 'float': $value = (double) $def['value']; break; case 'bool': $value = (bool) $def['value']; break; case 'reference': $value = ${$def['value']}; break; case 'string': default: $value = (string) $def['value']; } $aValues[] = $value; } } $aCallSpec = array($oObj, $sVerb); call_user_func_array($aCallSpec, $aValues); } // Mark the threshold as "triggered" // $oSW = $oObj->Get($sAttCode); $oSW->MarkThresholdAsTriggered($iThreshold); $oObj->Set($sAttCode, $oSW); if ($oObj->IsModified()) { CMDBObject::SetTrackInfo("Automatic - threshold triggered"); $oMyChange = CMDBObject::GetCurrentChange(); $oObj->DBUpdateTracked($oMyChange, true); } // Activate any existing trigger // $sClassList = implode("', '", MetaModel::EnumParentClasses($sClass, ENUM_PARENT_CLASSES_ALL)); $oTriggerSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT TriggerOnThresholdReached AS t WHERE t.target_class IN ('{$sClassList}') AND stop_watch_code=:stop_watch_code AND threshold_index = :threshold_index"), array(), array('stop_watch_code' => $sAttCode, 'threshold_index' => $iThreshold)); while ($oTrigger = $oTriggerSet->Fetch()) { $oTrigger->DoActivate($oObj->ToArgs('this')); } } } } } } $iProcessed = count($aList); return "Triggered {$iProcessed} threshold(s):" . implode(", ", $aList); }
/** * Perform all the needed checks to delete one (or more) objects */ public static function DeleteObjects(WebPage $oP, $sClass, $aObjects, $bPreview, $sCustomOperation, $aContextData = array()) { $oDeletionPlan = new DeletionPlan(); foreach ($aObjects as $oObj) { if ($bPreview) { $oObj->CheckToDelete($oDeletionPlan); } else { $oObj->DBDeleteTracked(CMDBObject::GetCurrentChange(), null, $oDeletionPlan); } } if ($bPreview) { if (count($aObjects) == 1) { $oObj = $aObjects[0]; $oP->add("<h1>" . Dict::Format('UI:Delete:ConfirmDeletionOf_Name', $oObj->GetName()) . "</h1>\n"); } else { $oP->add("<h1>" . Dict::Format('UI:Delete:ConfirmDeletionOf_Count_ObjectsOf_Class', count($aObjects), MetaModel::GetName($sClass)) . "</h1>\n"); } // Explain what should be done // $aDisplayData = array(); foreach ($oDeletionPlan->ListDeletes() as $sTargetClass => $aDeletes) { foreach ($aDeletes as $iId => $aData) { $oToDelete = $aData['to_delete']; $bAutoDel = $aData['mode'] == DEL_SILENT || $aData['mode'] == DEL_AUTO; if (array_key_exists('issue', $aData)) { if ($bAutoDel) { if (isset($aData['requested_explicitely'])) { $sConsequence = Dict::Format('UI:Delete:CannotDeleteBecause', $aData['issue']); } else { $sConsequence = Dict::Format('UI:Delete:ShouldBeDeletedAtomaticallyButNotPossible', $aData['issue']); } } else { $sConsequence = Dict::Format('UI:Delete:MustBeDeletedManuallyButNotPossible', $aData['issue']); } } else { if ($bAutoDel) { if (isset($aData['requested_explicitely'])) { $sConsequence = ''; // not applicable } else { $sConsequence = Dict::S('UI:Delete:WillBeDeletedAutomatically'); } } else { $sConsequence = Dict::S('UI:Delete:MustBeDeletedManually'); } } $aDisplayData[] = array('class' => MetaModel::GetName(get_class($oToDelete)), 'object' => $oToDelete->GetHyperLink(), 'consequence' => $sConsequence); } } foreach ($oDeletionPlan->ListUpdates() as $sRemoteClass => $aToUpdate) { foreach ($aToUpdate as $iId => $aData) { $oToUpdate = $aData['to_reset']; if (array_key_exists('issue', $aData)) { $sConsequence = Dict::Format('UI:Delete:CannotUpdateBecause_Issue', $aData['issue']); } else { $sConsequence = Dict::Format('UI:Delete:WillAutomaticallyUpdate_Fields', $aData['attributes_list']); } $aDisplayData[] = array('class' => MetaModel::GetName(get_class($oToUpdate)), 'object' => $oToUpdate->GetHyperLink(), 'consequence' => $sConsequence); } } $iImpactedIndirectly = $oDeletionPlan->GetTargetCount() - count($aObjects); if ($iImpactedIndirectly > 0) { if (count($aObjects) == 1) { $oObj = $aObjects[0]; $oP->p(Dict::Format('UI:Delete:Count_Objects/LinksReferencing_Object', $iImpactedIndirectly, $oObj->GetName())); } else { $oP->p(Dict::Format('UI:Delete:Count_Objects/LinksReferencingTheObjects', $iImpactedIndirectly)); } $oP->p(Dict::S('UI:Delete:ReferencesMustBeDeletedToEnsureIntegrity')); } if ($iImpactedIndirectly > 0 || $oDeletionPlan->FoundStopper()) { $aDisplayConfig = array(); $aDisplayConfig['class'] = array('label' => 'Class', 'description' => ''); $aDisplayConfig['object'] = array('label' => 'Object', 'description' => ''); $aDisplayConfig['consequence'] = array('label' => 'Consequence', 'description' => Dict::S('UI:Delete:Consequence+')); $oP->table($aDisplayConfig, $aDisplayData); } if ($oDeletionPlan->FoundStopper()) { if ($oDeletionPlan->FoundSecurityIssue()) { $oP->p(Dict::S('UI:Delete:SorryDeletionNotAllowed')); } elseif ($oDeletionPlan->FoundManualOperation()) { $oP->p(Dict::S('UI:Delete:PleaseDoTheManualOperations')); } else { $oP->p(Dict::S('UI:Delete:PleaseDoTheManualOperations')); } $oAppContext = new ApplicationContext(); $oP->add("<form method=\"post\">\n"); $oP->add("<input type=\"hidden\" name=\"transaction_id\" value=\"" . utils::ReadParam('transaction_id') . "\">\n"); $oP->add("<input type=\"button\" onclick=\"window.history.back();\" value=\"" . Dict::S('UI:Button:Back') . "\">\n"); $oP->add("<input DISABLED type=\"submit\" name=\"\" value=\"" . Dict::S('UI:Button:Delete') . "\">\n"); $oP->add($oAppContext->GetForForm()); $oP->add("</form>\n"); } else { if (count($aObjects) == 1) { $oObj = $aObjects[0]; $id = $oObj->GetKey(); $oP->p('<h1>' . Dict::Format('UI:Delect:Confirm_Object', $oObj->GetHyperLink()) . '</h1>'); } else { $oP->p('<h1>' . Dict::Format('UI:Delect:Confirm_Count_ObjectsOf_Class', count($aObjects), MetaModel::GetName($sClass)) . '</h1>'); } foreach ($aObjects as $oObj) { $aKeys[] = $oObj->GetKey(); } $oFilter = new DBObjectSearch($sClass); $oFilter->AddCondition('id', $aKeys, 'IN'); $oSet = new CMDBobjectSet($oFilter); $oP->add('<div id="0">'); CMDBAbstractObject::DisplaySet($oP, $oSet, array('display_limit' => false, 'menu' => false)); $oP->add("</div>\n"); $oP->add("<form method=\"post\">\n"); foreach ($aContextData as $sKey => $value) { $oP->add("<input type=\"hidden\" name=\"{$sKey}\" value=\"{$value}\">\n"); } $oP->add("<input type=\"hidden\" name=\"transaction_id\" value=\"" . utils::GetNewTransactionId() . "\">\n"); $oP->add("<input type=\"hidden\" name=\"operation\" value=\"{$sCustomOperation}\">\n"); $oP->add("<input type=\"hidden\" name=\"filter\" value=\"" . $oFilter->Serialize() . "\">\n"); $oP->add("<input type=\"hidden\" name=\"class\" value=\"{$sClass}\">\n"); foreach ($aObjects as $oObj) { $oP->add("<input type=\"hidden\" name=\"selectObject[]\" value=\"" . $oObj->GetKey() . "\">\n"); } $oP->add("<input type=\"button\" onclick=\"window.history.back();\" value=\"" . Dict::S('UI:Button:Back') . "\">\n"); $oP->add("<input type=\"submit\" name=\"\" value=\"" . Dict::S('UI:Button:Delete') . "\">\n"); $oAppContext = new ApplicationContext(); $oP->add($oAppContext->GetForForm()); $oP->add("</form>\n"); } } else { // Execute the deletion // if (count($aObjects) == 1) { $oObj = $aObjects[0]; $oP->add("<h1>" . Dict::Format('UI:Title:DeletionOf_Object', $oObj->GetName()) . "</h1>\n"); } else { $oP->add("<h1>" . Dict::Format('UI:Title:BulkDeletionOf_Count_ObjectsOf_Class', count($aObjects), MetaModel::GetName($sClass)) . "</h1>\n"); } // Security - do not allow the user to force a forbidden delete by the mean of page arguments... if ($oDeletionPlan->FoundSecurityIssue()) { throw new CoreException(Dict::S('UI:Error:NotEnoughRightsToDelete')); } if ($oDeletionPlan->FoundManualOperation()) { throw new CoreException(Dict::S('UI:Error:CannotDeleteBecauseManualOpNeeded')); } if ($oDeletionPlan->FoundManualDelete()) { throw new CoreException(Dict::S('UI:Error:CannotDeleteBecauseOfDepencies')); } // Report deletions // $aDisplayData = array(); foreach ($oDeletionPlan->ListDeletes() as $sTargetClass => $aDeletes) { foreach ($aDeletes as $iId => $aData) { $oToDelete = $aData['to_delete']; if (isset($aData['requested_explicitely'])) { $sMessage = Dict::S('UI:Delete:Deleted'); } else { $sMessage = Dict::S('UI:Delete:AutomaticallyDeleted'); } $aDisplayData[] = array('class' => MetaModel::GetName(get_class($oToDelete)), 'object' => $oToDelete->GetName(), 'consequence' => $sMessage); } } // Report updates // foreach ($oDeletionPlan->ListUpdates() as $sTargetClass => $aToUpdate) { foreach ($aToUpdate as $iId => $aData) { $oToUpdate = $aData['to_reset']; $aDisplayData[] = array('class' => MetaModel::GetName(get_class($oToUpdate)), 'object' => $oToUpdate->GetHyperLink(), 'consequence' => Dict::Format('UI:Delete:AutomaticResetOf_Fields', $aData['attributes_list'])); } } // Report automatic jobs // if ($oDeletionPlan->GetTargetCount() > 0) { if (count($aObjects) == 1) { $oObj = $aObjects[0]; $oP->p(Dict::Format('UI:Delete:CleaningUpRefencesTo_Object', $oObj->GetName())); } else { $oP->p(Dict::Format('UI:Delete:CleaningUpRefencesTo_Several_ObjectsOf_Class', count($aObjects), MetaModel::GetName($sClass))); } $aDisplayConfig = array(); $aDisplayConfig['class'] = array('label' => 'Class', 'description' => ''); $aDisplayConfig['object'] = array('label' => 'Object', 'description' => ''); $aDisplayConfig['consequence'] = array('label' => 'Done', 'description' => Dict::S('UI:Delete:Done+')); $oP->table($aDisplayConfig, $aDisplayData); } } }
public function CreateAdministrator($sAdminUser, $sAdminPwd, $sLanguage = 'EN US') { CMDBObject::SetTrackInfo('Initialization'); $oChange = CMDBObject::GetCurrentChange(); $iContactId = 0; // Support drastic data model changes: no organization class (or not writable)! if (MetaModel::IsValidClass('Organization') && !MetaModel::IsAbstract('Organization')) { $oOrg = new Organization(); $oOrg->Set('name', 'My Company/Department'); $oOrg->Set('code', 'SOMECODE'); $iOrgId = $oOrg->DBInsertTrackedNoReload($oChange, true); // Support drastic data model changes: no Person class (or not writable)! if (MetaModel::IsValidClass('Person') && !MetaModel::IsAbstract('Person')) { $oContact = new Person(); $oContact->Set('name', 'My last name'); $oContact->Set('first_name', 'My first name'); if (MetaModel::IsValidAttCode('Person', 'org_id')) { $oContact->Set('org_id', $iOrgId); } if (MetaModel::IsValidAttCode('Person', 'phone')) { $oContact->Set('phone', '+00 000 000 000'); } $oContact->Set('email', '*****@*****.**'); $iContactId = $oContact->DBInsertTrackedNoReload($oChange, true); } } $oUser = new UserLocal(); $oUser->Set('login', $sAdminUser); $oUser->Set('password', $sAdminPwd); if (MetaModel::IsValidAttCode('UserLocal', 'contactid') && $iContactId != 0) { $oUser->Set('contactid', $iContactId); } $oUser->Set('language', $sLanguage); // Language was chosen during the installation // Add this user to the very specific 'admin' profile $oAdminProfile = MetaModel::GetObjectFromOQL("SELECT URP_Profiles WHERE name = :name", array('name' => ADMIN_PROFILE_NAME), true); if (is_object($oAdminProfile)) { $oUserProfile = new URP_UserProfile(); //$oUserProfile->Set('userid', $iUserId); $oUserProfile->Set('profileid', $oAdminProfile->GetKey()); $oUserProfile->Set('reason', 'By definition, the administrator must have the administrator profile'); //$oUserProfile->DBInsertTrackedNoReload($oChange, true /* skip security */); $oSet = DBObjectSet::FromObject($oUserProfile); $oUser->Set('profile_list', $oSet); } $iUserId = $oUser->DBInsertTrackedNoReload($oChange, true); return true; }
/** * 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; } }
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; foreach ($aRes as $iRow => $aRowData) { $bWritten = false; $oStatus = $aRowData["__STATUS__"]; switch (get_class($oStatus)) {
protected static function DoLoadFiles($aSelectedModules, $sModulesDir, $sDBServer, $sDBUser, $sDBPwd, $sDBName, $sDBPrefix, $sTargetEnvironment = '', $bOldAddon = false, $bSampleData = false) { $aParamValues = array('db_server' => $sDBServer, 'db_user' => $sDBUser, 'db_pwd' => $sDBPwd, 'db_name' => $sDBName, 'new_db_name' => $sDBName, 'db_prefix' => $sDBPrefix); $oConfig = new Config(); $oConfig->UpdateFromParams($aParamValues, $sModulesDir); if ($bOldAddon) { // Old version of the add-on for backward compatibility with pre-2.0 data models $oConfig->SetAddons(array('user rights' => 'addons/userrights/userrightsprofile.db.class.inc.php')); } //Load the MetaModel if needed (asynchronous mode) if (!self::$bMetaModelStarted) { $oProductionEnv = new RunTimeEnvironment($sTargetEnvironment); $oProductionEnv->InitDataModel($oConfig, false); // load data model and connect to the database self::$bMetaModelStarted = true; // No need to reload the final MetaModel in case the installer runs synchronously } $oDataLoader = new XMLDataLoader(); CMDBObject::SetTrackInfo("Initialization"); $oMyChange = CMDBObject::GetCurrentChange(); SetupPage::log_info("starting data load session"); $oDataLoader->StartSession($oMyChange); $aFiles = array(); $aPreviouslyLoadedFiles = array(); $oProductionEnv = new RunTimeEnvironment(); $aAvailableModules = $oProductionEnv->AnalyzeInstallation($oConfig, APPROOT . $sModulesDir); foreach ($aAvailableModules as $sModuleId => $aModule) { if ($sModuleId != ROOT_MODULE) { // Load data only for selected AND newly installed modules if (in_array($sModuleId, $aSelectedModules)) { if ($aModule['version_db'] != '') { // Simulate the load of the previously loaded XML files to get the mapping of the keys if ($bSampleData) { $aPreviouslyLoadedFiles = array_merge($aPreviouslyLoadedFiles, $aAvailableModules[$sModuleId]['data.struct'], $aAvailableModules[$sModuleId]['data.sample']); } else { // Load only structural data $aPreviouslyLoadedFiles = array_merge($aPreviouslyLoadedFiles, $aAvailableModules[$sModuleId]['data.struct']); } } else { if ($bSampleData) { $aFiles = array_merge($aFiles, $aAvailableModules[$sModuleId]['data.struct'], $aAvailableModules[$sModuleId]['data.sample']); } else { // Load only structural data $aFiles = array_merge($aFiles, $aAvailableModules[$sModuleId]['data.struct']); } } } } } // Simulate the load of the previously loaded files, in order to initialize // the mapping between the identifiers in the XML and the actual identifiers // in the current database foreach ($aPreviouslyLoadedFiles as $sFileRelativePath) { $sFileName = APPROOT . $sFileRelativePath; SetupPage::log_info("Loading file: {$sFileName} (just to get the keys mapping)"); if (empty($sFileName) || !file_exists($sFileName)) { throw new Exception("File {$sFileName} does not exist"); } $oDataLoader->LoadFile($sFileName, true); $sResult = sprintf("loading of %s done.", basename($sFileName)); SetupPage::log_info($sResult); } foreach ($aFiles as $sFileRelativePath) { $sFileName = APPROOT . $sFileRelativePath; SetupPage::log_info("Loading file: {$sFileName}"); if (empty($sFileName) || !file_exists($sFileName)) { throw new Exception("File {$sFileName} does not exist"); } $oDataLoader->LoadFile($sFileName); $sResult = sprintf("loading of %s done.", basename($sFileName)); SetupPage::log_info($sResult); } $oDataLoader->EndSession(); SetupPage::log_info("ending data load session"); }