protected function DisplayEditInPlace(WebPage $oPage, DBObjectSet $oValue, $aArgs = array(), $sFormPrefix, $oCurrentObj, $aButtons = array('create', 'delete')) { $aAttribs = $this->GetTableConfig(); $oValue->Rewind(); $oPage->add('<table class="listContainer" id="' . $this->sInputid . '"><tr><td>'); $aData = array(); while ($oLinkObj = $oValue->Fetch()) { $aRow = array(); $aRow['form::select'] = '<input type="checkbox" class="selectList' . $this->sInputid . '" value="' . $oLinkObj->GetKey() . '"/>'; foreach ($this->aZlist as $sLinkedAttCode) { $aRow[$sLinkedAttCode] = $oLinkObj->GetAsHTML($sLinkedAttCode); } $aData[] = $aRow; } $oPage->table($aAttribs, $aData); $oPage->add('</td></tr></table>'); //listcontainer $sInputName = $sFormPrefix . 'attr_' . $this->sAttCode; $aLabels = array('delete' => Dict::S('UI:Button:Delete'), 'creation_title' => Dict::Format('UI:CreationTitle_Class', MetaModel::GetName($this->sLinkedClass)), 'create' => Dict::Format('UI:ClickToCreateNew', MetaModel::GetName($this->sLinkedClass)), 'remove' => Dict::S('UI:Button:Remove'), 'add' => Dict::Format('UI:AddAnExisting_Class', MetaModel::GetName($this->sLinkedClass)), 'selection_title' => Dict::Format('UI:SelectionOf_Class', MetaModel::GetName($this->sLinkedClass))); $oContext = new ApplicationContext(); $sSubmitUrl = utils::GetAbsoluteUrlAppRoot() . 'pages/ajax.render.php?' . $oContext->GetForLink(); $sJSONLabels = json_encode($aLabels); $sJSONButtons = json_encode($aButtons); $sWizHelper = 'oWizardHelper' . $sFormPrefix; $oPage->add_ready_script("\$('#{$this->sInputid}').directlinks({class_name: '{$this->sClass}', att_code: '{$this->sAttCode}', input_name:'{$sInputName}', labels: {$sJSONLabels}, submit_to: '{$sSubmitUrl}', buttons: {$sJSONButtons}, oWizardHelper: {$sWizHelper} });"); }
/** * 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); } } }
/** * Display the history of bulk imports */ static function DisplayImportHistory(WebPage $oPage, $bFromAjax = false, $bShowAll = false) { $sAjaxDivId = "CSVImportHistory"; if (!$bFromAjax) { $oPage->add('<div id="' . $sAjaxDivId . '">'); } $oPage->p(Dict::S('UI:History:BulkImports+') . ' <span id="csv_history_reload"></span>'); $oBulkChangeSearch = DBObjectSearch::FromOQL("SELECT CMDBChange WHERE origin IN ('csv-interactive', 'csv-import.php')"); $iQueryLimit = $bShowAll ? 0 : appUserPreferences::GetPref('default_page_size', MetaModel::GetConfig()->GetMinDisplayLimit()); $oBulkChanges = new DBObjectSet($oBulkChangeSearch, array('date' => false), array(), null, $iQueryLimit); $oAppContext = new ApplicationContext(); $bLimitExceeded = false; if ($oBulkChanges->Count() > appUserPreferences::GetPref('default_page_size', MetaModel::GetConfig()->GetMinDisplayLimit())) { $bLimitExceeded = true; if (!$bShowAll) { $iMaxObjects = appUserPreferences::GetPref('default_page_size', MetaModel::GetConfig()->GetMinDisplayLimit()); $oBulkChanges->SetLimit($iMaxObjects); } } $oBulkChanges->Seek(0); $aDetails = array(); while ($oChange = $oBulkChanges->Fetch()) { $sDate = '<a href="csvimport.php?step=10&changeid=' . $oChange->GetKey() . '&' . $oAppContext->GetForLink() . '">' . $oChange->Get('date') . '</a>'; $sUser = $oChange->GetUserName(); if (preg_match('/^(.*)\\(CSV\\)$/i', $oChange->Get('userinfo'), $aMatches)) { $sUser = $aMatches[1]; } else { $sUser = $oChange->Get('userinfo'); } $oOpSearch = DBObjectSearch::FromOQL("SELECT CMDBChangeOpCreate WHERE change = :change_id"); $oOpSet = new DBObjectSet($oOpSearch, array(), array('change_id' => $oChange->GetKey())); $iCreated = $oOpSet->Count(); // Get the class from the first item found (assumption: a CSV load is done for a single class) if ($oCreateOp = $oOpSet->Fetch()) { $sClass = $oCreateOp->Get('objclass'); } $oOpSearch = DBObjectSearch::FromOQL("SELECT CMDBChangeOpSetAttribute WHERE change = :change_id"); $oOpSet = new DBObjectSet($oOpSearch, array(), array('change_id' => $oChange->GetKey())); $aModified = array(); $aAttList = array(); while ($oModified = $oOpSet->Fetch()) { // Get the class (if not done earlier on object creation) $sClass = $oModified->Get('objclass'); $iKey = $oModified->Get('objkey'); $sAttCode = $oModified->Get('attcode'); $aAttList[$sClass][$sAttCode] = true; $aModified["{$sClass}::{$iKey}"] = true; } $iModified = count($aModified); // Assumption: there is only one class of objects being loaded // Then the last class found gives us the class for every object if ($iModified > 0 || $iCreated > 0) { $aDetails[] = array('date' => $sDate, 'user' => $sUser, 'class' => $sClass, 'created' => $iCreated, 'modified' => $iModified); } } $aConfig = array('date' => array('label' => Dict::S('UI:History:Date'), 'description' => Dict::S('UI:History:Date+')), 'user' => array('label' => Dict::S('UI:History:User'), 'description' => Dict::S('UI:History:User+')), 'class' => array('label' => Dict::S('Core:AttributeClass'), 'description' => Dict::S('Core:AttributeClass+')), 'created' => array('label' => Dict::S('UI:History:StatsCreations'), 'description' => Dict::S('UI:History:StatsCreations+')), 'modified' => array('label' => Dict::S('UI:History:StatsModifs'), 'description' => Dict::S('UI:History:StatsModifs+'))); if ($bLimitExceeded) { if ($bShowAll) { // Collapsible list $oPage->add('<p>' . Dict::Format('UI:CountOfResults', $oBulkChanges->Count()) . ' <a class="truncated" onclick="OnTruncatedHistoryToggle(false);">' . Dict::S('UI:CollapseList') . '</a></p>'); } else { // Truncated list $iMinDisplayLimit = appUserPreferences::GetPref('default_page_size', MetaModel::GetConfig()->GetMinDisplayLimit()); $sCollapsedLabel = Dict::Format('UI:TruncatedResults', $iMinDisplayLimit, $oBulkChanges->Count()); $sLinkLabel = Dict::S('UI:DisplayAll'); $oPage->add('<p>' . $sCollapsedLabel . ' <a class="truncated" onclick="OnTruncatedHistoryToggle(true);">' . $sLinkLabel . '</p>'); $oPage->add_ready_script(<<<EOF \t\$('#{$sAjaxDivId} table.listResults').addClass('truncated'); \t\$('#{$sAjaxDivId} table.listResults tr:last td').addClass('truncated'); EOF ); $sAppContext = $oAppContext->GetForLink(); $oPage->add_script(<<<EOF \tfunction OnTruncatedHistoryToggle(bShowAll) \t{ \t\t\$('#csv_history_reload').html('<img src="../images/indicator.gif"/>'); \t\t\$.get(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php?{$sAppContext}', {operation: 'displayCSVHistory', showall: bShowAll}, function(data) \t\t\t{ \t\t\t\t\$('#{$sAjaxDivId}').html(data); \t\t\t\tvar table = \$('#{$sAjaxDivId} .listResults'); \t\t\t\ttable.tableHover(); // hover tables \t\t\t\ttable.tablesorter( { widgets: ['myZebra', 'truncatedList']} ); // sortable and zebra tables \t\t\t} \t\t); \t} EOF ); } } else { // Normal display - full list without any decoration } $oPage->table($aConfig, $aDetails); if (!$bFromAjax) { $oPage->add('</div>'); } }