From 80a8b63498877e0dba276a7d50c631d0f9009d2f Mon Sep 17 00:00:00 2001
From: Romain Quetiez
Date: Fri, 8 Mar 2013 13:36:31 +0000
Subject: [PATCH] Modified the mechanism to display object dedicated messages
(allows the plugin to add their message or replace standard ones) Factorized
the code to bulk update / bulk delete objects in an interactive way.
SVN:trunk[2610]
---
application/cmdbabstract.class.inc.php | 624 +++++++++++++++++++++++-
pages/UI.php | 628 ++-----------------------
2 files changed, 666 insertions(+), 586 deletions(-)
diff --git a/application/cmdbabstract.class.inc.php b/application/cmdbabstract.class.inc.php
index a981075b7..d6e522352 100644
--- a/application/cmdbabstract.class.inc.php
+++ b/application/cmdbabstract.class.inc.php
@@ -92,7 +92,38 @@ abstract class cmdbAbstractObject extends CMDBObject implements iDisplay
{
return 'UI.php';
}
-
+
+ /**
+ * Set a message diplayed to the end-user next time this object will be displayed
+ * Messages are uniquely identified so that plugins can override standard messages (the final work is given to the last plugin to set the message for a given message id)
+ * In practice, standard messages are recorded at the end but they will not overwrite existing messages
+ *
+ * @param string $sClass The class of the object (must be the final class)
+ * @param int $iKey The identifier of the object
+ * @param string $sMessageId Your id or one of the well-known ids: 'create', 'update' and 'apply_stimulus'
+ * @param string $sMessage The HTML message (must be correctly escaped)
+ * @param string $sSeverity Any of the following: ok, info, error.
+ * @param float $fRank Ordering of the message: smallest displayed first (can be negative)
+ * @param bool $bMustNotExist Do not alter any existing message (considering the id)
+ *
+ */
+ public static function SetSessionMessage($sClass, $iKey, $sMessageId, $sMessage, $sSeverity, $fRank, $bMustNotExist = false)
+ {
+ $sMessageKey = $sClass.'::'.$iKey;
+ if (!isset($_SESSION['obj_messages'][$sMessageKey]))
+ {
+ $_SESSION['obj_messages'][$sMessageKey] = array();
+ }
+ if (!$bMustNotExist || !array_key_exists($sMessageId, $_SESSION['obj_messages'][$sMessageKey]))
+ {
+ $_SESSION['obj_messages'][$sMessageKey][$sMessageId] = array(
+ 'rank' => $fRank,
+ 'severity' => $sSeverity,
+ 'message' => $sMessage
+ );
+ }
+ }
+
function DisplayBareHeader(WebPage $oPage, $bEditMode = false)
{
// Standard Header with name, actions menu and history block
@@ -102,8 +133,19 @@ abstract class cmdbAbstractObject extends CMDBObject implements iDisplay
$sMessageKey = get_class($this).'::'.$this->GetKey();
if (array_key_exists('obj_messages', $_SESSION) && array_key_exists($sMessageKey, $_SESSION['obj_messages']))
{
- $sMsgClass = 'message_'.$_SESSION['obj_messages'][$sMessageKey]['severity'];
- $oPage->add("");
+ $aMessages = array();
+ $aRanks = array();
+ foreach ($_SESSION['obj_messages'][$sMessageKey] as $sMessageId => $aMessageData)
+ {
+ $sMsgClass = 'message_'.$aMessageData['severity'];
+ $aMessages[] = "";
+ $aRanks[] = $aMessageData['rank'];
+ }
+ array_multisort($aRanks, $aMessages);
+ foreach ($aMessages as $sMessage)
+ {
+ $oPage->add($sMessage);
+ }
unset($_SESSION['obj_messages'][$sMessageKey]);
}
@@ -1754,7 +1796,7 @@ abstract class cmdbAbstractObject extends CMDBObject implements iDisplay
}
return "{$sHTMLValue}
";
}
-
+
public function DisplayModifyForm(WebPage $oPage, $aExtraParams = array())
{
self::$iGlobalFormId++;
@@ -2868,5 +2910,579 @@ EOF
}
return $aComputedAttributes;
}
+
+ /**
+ * Display a form for modifying several objects at once
+ * The form will be submitted to the current page, with the specified additional values
+ */
+ public static function DisplayBulkModifyForm($oP, $sClass, $aSelectedObj, $sCustomOperation, $sCancelUrl, $aExcludeAttributes = array(), $aContextData = array())
+ {
+ if (count($aSelectedObj) > 0)
+ {
+ $iAllowedCount = count($aSelectedObj);
+ $sSelectedObj = implode(',', $aSelectedObj);
+
+ $sOQL = "SELECT $sClass WHERE id IN (".$sSelectedObj.")";
+ $oSet = new CMDBObjectSet(DBObjectSearch::FromOQL($sOQL));
+
+ // Compute the distribution of the values for each field to determine which of the "scalar" fields are homogenous
+ $aList = MetaModel::ListAttributeDefs($sClass);
+ $aValues = array();
+ foreach($aList as $sAttCode => $oAttDef)
+ {
+ if ($oAttDef->IsScalar())
+ {
+ $aValues[$sAttCode] = array();
+ }
+ }
+ while($oObj = $oSet->Fetch())
+ {
+ foreach($aList as $sAttCode => $oAttDef)
+ {
+ if ($oAttDef->IsScalar() && $oAttDef->IsWritable())
+ {
+ $currValue = $oObj->Get($sAttCode);
+ if ($oAttDef instanceof AttributeCaseLog)
+ {
+ $currValue = ' '; // Don't put an empty string, in case the field would be considered as mandatory...
+ }
+ if (is_object($currValue)) continue; // Skip non scalar values...
+ if(!array_key_exists($currValue, $aValues[$sAttCode]))
+ {
+ $aValues[$sAttCode][$currValue] = array('count' => 1, 'display' => $oObj->GetAsHTML($sAttCode));
+ }
+ else
+ {
+ $aValues[$sAttCode][$currValue]['count']++;
+ }
+ }
+ }
+ }
+ // Now create an object that has values for the homogenous values only
+ $oDummyObj = new $sClass(); // @@ What if the class is abstract ?
+ $aComments = array();
+ function MyComparison($a, $b) // Sort descending
+ {
+ if ($a['count'] == $b['count'])
+ {
+ return 0;
+ }
+ return ($a['count'] > $b['count']) ? -1 : 1;
+ }
+
+ $iFormId = cmdbAbstractObject::GetNextFormId(); // Identifier that prefixes all the form fields
+ $sReadyScript = '';
+ $aDependsOn = array();
+ $sFormPrefix = '2_';
+ foreach($aList as $sAttCode => $oAttDef)
+ {
+ $aPrerequisites = MetaModel::GetPrequisiteAttributes($sClass, $sAttCode); // List of attributes that are needed for the current one
+ if (count($aPrerequisites) > 0)
+ {
+ // When 'enabling' a field, all its prerequisites must be enabled too
+ $sFieldList = "['{$sFormPrefix}".implode("','{$sFormPrefix}", $aPrerequisites)."']";
+ $oP->add_ready_script("$('#enable_{$sFormPrefix}{$sAttCode}').bind('change', function(evt, sFormId) { return PropagateCheckBox( this.checked, $sFieldList, true); } );\n");
+ }
+ $aDependents = MetaModel::GetDependentAttributes($sClass, $sAttCode); // List of attributes that are needed for the current one
+ if (count($aDependents) > 0)
+ {
+ // When 'disabling' a field, all its dependent fields must be disabled too
+ $sFieldList = "['{$sFormPrefix}".implode("','{$sFormPrefix}", $aDependents)."']";
+ $oP->add_ready_script("$('#enable_{$sFormPrefix}{$sAttCode}').bind('change', function(evt, sFormId) { return PropagateCheckBox( this.checked, $sFieldList, false); } );\n");
+ }
+ if ($oAttDef->IsScalar() && $oAttDef->IsWritable())
+ {
+ if ($oAttDef->GetEditClass() == 'One Way Password')
+ {
+
+ $sTip = "Unknown values";
+ $sReadyScript .= "$('#multi_values_$sAttCode').qtip( { content: '$sTip', show: 'mouseover', hide: 'mouseout', style: { name: 'dark', tip: 'leftTop' }, position: { corner: { target: 'rightMiddle', tooltip: 'leftTop' }} } );";
+
+ $oDummyObj->Set($sAttCode, null);
+ $aComments[$sAttCode] = ' ';
+ $aComments[$sAttCode] .= ' ?
';
+ $sReadyScript .= 'ToogleField(false, \''.$iFormId.'_'.$sAttCode.'\');'."\n";
+ }
+ else
+ {
+ $iCount = count($aValues[$sAttCode]);
+ if ($iCount == 1)
+ {
+ // Homogenous value
+ reset($aValues[$sAttCode]);
+ $aKeys = array_keys($aValues[$sAttCode]);
+ $currValue = $aKeys[0]; // The only value is the first key
+ //echo "current value for $sAttCode : $currValue
";
+ $oDummyObj->Set($sAttCode, $currValue);
+ $aComments[$sAttCode] = ' ';
+ $aComments[$sAttCode] .= '1
';
+ }
+ else
+ {
+ // Non-homogenous value
+ $aMultiValues = $aValues[$sAttCode];
+ uasort($aMultiValues, 'MyComparison');
+ $iMaxCount = 5;
+ $sTip = "".Dict::Format('UI:BulkModify_Count_DistinctValues', $iCount)."
";
+ $index = 0;
+ foreach($aMultiValues as $sCurrValue => $aVal)
+ {
+ $sDisplayValue = empty($aVal['display']) ? ''.Dict::S('Enum:Undefined').' ' : str_replace(array("\n", "\r"), " ", $aVal['display']);
+ $sTip .= "".Dict::Format('UI:BulkModify:Value_Exists_N_Times', $sDisplayValue, $aVal['count'])." ";
+ $index++;
+ if ($iMaxCount == $index)
+ {
+ $sTip .= "".Dict::Format('UI:BulkModify:N_MoreValues', count($aMultiValues) - $iMaxCount)." ";
+ break;
+ }
+ }
+ $sTip .= "
";
+ $sTip = addslashes($sTip);
+ $sReadyScript .= "$('#multi_values_$sAttCode').qtip( { content: '$sTip', show: 'mouseover', hide: 'mouseout', style: { name: 'dark', tip: 'leftTop' }, position: { corner: { target: 'rightMiddle', tooltip: 'leftTop' }} } );";
+
+ $oDummyObj->Set($sAttCode, null);
+ $aComments[$sAttCode] = ' ';
+ $aComments[$sAttCode] .= ''.$iCount.'
';
+ }
+ $sReadyScript .= 'ToogleField('.(($iCount == 1) ? 'true': 'false').', \''.$iFormId.'_'.$sAttCode.'\');'."\n";
+ }
+ }
+ }
+
+ $sStateAttCode = MetaModel::GetStateAttributeCode($sClass);
+ if (($sStateAttCode != '') && ($oDummyObj->GetState() == ''))
+ {
+ // Hmmm, it's not gonna work like this ! Set a default value for the "state"
+ // Maybe we should use the "state" that is the most common among the objects...
+ $aMultiValues = $aValues[$sStateAttCode];
+ uasort($aMultiValues, 'MyComparison');
+ foreach($aMultiValues as $sCurrValue => $aVal)
+ {
+ $oDummyObj->Set($sStateAttCode, $sCurrValue);
+ break;
+ }
+ //$oStateAtt = MetaModel::GetAttributeDef($sClass, $sStateAttCode);
+ //$oDummyObj->Set($sStateAttCode, $oStateAtt->GetDefaultValue());
+ }
+ $oP->add("\n");
+
+ $oP->add("\n");
+ $sDisableFields = json_encode($aExcludeAttributes);
+
+ $aParams = array
+ (
+ 'fieldsComments' => $aComments,
+ 'noRelations' => true,
+ 'custom_operation' => $sCustomOperation,
+ 'custom_button' => Dict::S('UI:Button:PreviewModifications'),
+ 'selectObj' => $sSelectedObj,
+ 'preview_mode' => true,
+ 'disabled_fields' => $sDisableFields,
+ 'disable_plugins' => true
+ );
+ $aParams = $aParams + $aContextData; // merge keeping associations
+
+ $oDummyObj->DisplayModifyForm($oP, $aParams);
+ $oP->add("
\n");
+ $oP->add_ready_script($sReadyScript);
+ $oP->add_ready_script(
+<<p("No object selected !, nothing to do");
+ }
+ }
+
+ /**
+ * 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' => " ", '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("\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);
+ }
+ foreach($aSelectedObj as $iId)
+ {
+ $oObj = MetaModel::GetObject($sClass, $iId);
+ $aErrors = $oObj->UpdateObjectFromPostedForm('');
+ $bResult = (count($aErrors) == 0);
+ if ($bResult)
+ {
+ list($bResult, $aErrors) = $oObj->CheckToWrite(true /* Enforce Read-only fields */);
+ }
+ 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' => " ",
+ 'object' => $oObj->GetHyperlink(),
+ 'status' => $sStatus,
+ 'errors' => ''.($bResult ? '': implode('
', $aErrors)).'
',
+ '@class' => $sCSSClass,
+ );
+ if ($bResult && (!$bPreview))
+ {
+ $oObj->DBUpdate();
+ }
+ }
+ $oP->Table($aHeaders, $aRows);
+ if ($bPreview)
+ {
+ $sFormAction = $_SERVER['SCRIPT_NAME']; // No parameter in the URL, the only parameter will be the ones passed through the form
+ // Form to submit:
+ $oP->add("\n");
+ }
+ else
+ {
+ $oP->add("".Dict::S('UI:Button:Done')." \n");
+ }
+ }
+
+ /**
+ * 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("".Dict::Format('UI:Delete:ConfirmDeletionOf_Name', $oObj->GetName())." \n");
+ }
+ else
+ {
+ $oP->add("".Dict::Format('UI:Delete:ConfirmDeletionOf_Count_ObjectsOf_Class', count($aObjects), MetaModel::GetName($sClass))." \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 // $bFoundManualOp
+ {
+ $oP->p(Dict::S('UI:Delete:PleaseDoTheManualOperations'));
+ }
+ $oAppContext = new ApplicationContext();
+ $oP->add("\n");
+ }
+ else
+ {
+ if (count($aObjects) == 1)
+ {
+ $oObj = $aObjects[0];
+ $id = $oObj->GetKey();
+ $oP->p(''.Dict::Format('UI:Delect:Confirm_Object', $oObj->GetHyperLink()).' ');
+ }
+ else
+ {
+ $oP->p(''.Dict::Format('UI:Delect:Confirm_Count_ObjectsOf_Class', count($aObjects), MetaModel::GetName($sClass)).' ');
+ }
+ foreach($aObjects as $oObj)
+ {
+ $aKeys[] = $oObj->GetKey();
+ }
+ $oFilter = new DBObjectSearch($sClass);
+ $oFilter->AddCondition('id', $aKeys, 'IN');
+ $oSet = new CMDBobjectSet($oFilter);
+ $oP->add('');
+ CMDBAbstractObject::DisplaySet($oP, $oSet, array('display_limit' => false, 'menu' => false));
+ $oP->add("
\n");
+ $oP->add("\n");
+ }
+ }
+ else // if ($bPreview)...
+ {
+ // Execute the deletion
+ //
+ if (count($aObjects) == 1)
+ {
+ $oObj = $aObjects[0];
+ $oP->add("".Dict::Format('UI:Title:DeletionOf_Object', $oObj->GetName())." \n");
+ }
+ else
+ {
+ $oP->add("".Dict::Format('UI:Title:BulkDeletionOf_Count_ObjectsOf_Class', count($aObjects), MetaModel::GetName($sClass))." \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);
+ }
+ }
+ }
}
?>
diff --git a/pages/UI.php b/pages/UI.php
index 8083960ec..d43710aeb 100644
--- a/pages/UI.php
+++ b/pages/UI.php
@@ -24,288 +24,6 @@
* @license http://opensource.org/licenses/AGPL-3.0
*/
-/**
- * Perform all the needed checks to delete one (or more) objects
- */
-function DeleteObjects(WebPage $oP, $sClass, $aObjects, $bDeleteConfirmed, $oFilter = null)
-{
- $oDeletionPlan = new DeletionPlan();
-
- foreach($aObjects as $oObj)
- {
- if ($bDeleteConfirmed)
- {
- $oObj->DBDeleteTracked(CMDBObject::GetCurrentChange(), null, $oDeletionPlan);
- }
- else
- {
- $oObj->CheckToDelete($oDeletionPlan);
- }
- }
-
- if ($bDeleteConfirmed)
- {
- if (count($aObjects) == 1)
- {
- $oObj = $aObjects[0];
- $oP->add("".Dict::Format('UI:Title:DeletionOf_Object', $oObj->GetName())." \n");
- }
- else
- {
- $oP->add("".Dict::Format('UI:Title:BulkDeletionOf_Count_ObjectsOf_Class', count($aObjects), MetaModel::GetName($sClass))." \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);
- }
- }
- else
- {
- if (count($aObjects) == 1)
- {
- $oObj = $aObjects[0];
- $oP->add("".Dict::Format('UI:Delete:ConfirmDeletionOf_Name', $oObj->GetName())." \n");
- }
- else
- {
- $oP->add("".Dict::Format('UI:Delete:ConfirmDeletionOf_Count_ObjectsOf_Class', count($aObjects), MetaModel::GetName($sClass))." \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 // $bFoundManualOp
- {
- $oP->p(Dict::S('UI:Delete:PleaseDoTheManualOperations'));
- }
- $oAppContext = new ApplicationContext();
- $oP->add("\n");
- }
- else
- {
- $oAppContext = new ApplicationContext();
- if (count($aObjects) == 1)
- {
- $oObj = $aObjects[0];
- $id = $oObj->GetKey();
- $oP->p(''.Dict::Format('UI:Delect:Confirm_Object', $oObj->GetHyperLink()).' ');
- $oP->add("\n");
- }
- else
- {
- $oP->p(''.Dict::Format('UI:Delect:Confirm_Count_ObjectsOf_Class', count($aObjects), MetaModel::GetName($sClass)).' ');
- foreach($aObjects as $oObj)
- {
- $aKeys[] = $oObj->GetKey();
- }
- $oFilter = new DBObjectSearch($sClass);
- $oFilter->AddCondition('id', $aKeys, 'IN');
- $oSet = new CMDBobjectSet($oFilter);
- $oP->add('');
- CMDBAbstractObject::DisplaySet($oP, $oSet, array('display_limit' => false, 'menu' => false));
- $oP->add("
\n");
- $oP->add("\n");
- }
- }
- }
-}
/**
* Displays a popup welcome message, once per session at maximum
@@ -390,13 +108,12 @@ function ApplyNextAction(Webpage $oP, CMDBObject $oObj, $sNextAction)
}
}
-function ReloadAndDisplay($oPage, $oObj, $sMessage = '', $sSeverity)
+function ReloadAndDisplay($oPage, $oObj, $sMessageId = '', $sMessage = '', $sSeverity = null)
{
$oAppContext = new ApplicationContext();
- $sMessageKey = get_class($oObj).'::'.$oObj->GetKey();
- if ($sMessage != '')
+ if ($sMessageId != '')
{
- $_SESSION['obj_messages'][$sMessageKey] = array('severity' => $sSeverity, 'message' => $sMessage);
+ cmdbAbstractObject::SetSessionMessage(get_class($oObj), $oObj->GetKey(), $sMessageId, $sMessage, $sSeverity, 0, true /* must not exist */);
}
$oPage->add_header('Location: '.utils::GetAbsoluteUrlAppRoot().'pages/UI.php?operation=details&class='.get_class($oObj).'&id='.$oObj->getKey().'&'.$oAppContext->GetForLink());
}
@@ -959,174 +676,9 @@ try
$sClass = utils::ReadParam('class', '', false, 'class');
$oFullSetFilter = DBObjectSearch::unserialize($sFilter);
$aSelectedObj = utils::ReadMultipleSelection($oFullSetFilter);
- if (count($aSelectedObj) > 0)
- {
- $iAllowedCount = count($aSelectedObj);
- $sSelectedObj = implode(',', $aSelectedObj);
-
- $sOQL = "SELECT $sClass WHERE id IN (".$sSelectedObj.")";
- $oSet = new CMDBObjectSet(DBObjectSearch::FromOQL($sOQL));
-
- // Compute the distribution of the values for each field to determine which of the "scalar" fields are homogenous
- $aList = MetaModel::ListAttributeDefs($sClass);
- $aValues = array();
- foreach($aList as $sAttCode => $oAttDef)
- {
- if ($oAttDef->IsScalar())
- {
- $aValues[$sAttCode] = array();
- }
- }
- while($oObj = $oSet->Fetch())
- {
- foreach($aList as $sAttCode => $oAttDef)
- {
- if ($oAttDef->IsScalar() && $oAttDef->IsWritable())
- {
- $currValue = $oObj->Get($sAttCode);
- if ($oAttDef instanceof AttributeCaseLog)
- {
- $currValue = ' '; // Don't put an empty string, in case the field would be considered as mandatory...
- }
- if (is_object($currValue)) continue; // Skip non scalar values...
- if(!array_key_exists($currValue, $aValues[$sAttCode]))
- {
- $aValues[$sAttCode][$currValue] = array('count' => 1, 'display' => $oObj->GetAsHTML($sAttCode));
- }
- else
- {
- $aValues[$sAttCode][$currValue]['count']++;
- }
- }
- }
- }
- // Now create an object that has values for the homogenous values only
- $oDummyObj = new $sClass(); // @@ What if the class is abstract ?
- $aComments = array();
- function MyComparison($a, $b) // Sort descending
- {
- if ($a['count'] == $b['count'])
- {
- return 0;
- }
- return ($a['count'] > $b['count']) ? -1 : 1;
- }
-
- $iFormId = cmdbAbstractObject::GetNextFormId(); // Identifier that prefixes all the form fields
- $sReadyScript = '';
- $aDependsOn = array();
- $sFormPrefix = '2_';
- foreach($aList as $sAttCode => $oAttDef)
- {
- $aPrerequisites = MetaModel::GetPrequisiteAttributes($sClass, $sAttCode); // List of attributes that are needed for the current one
- if (count($aPrerequisites) > 0)
- {
- // When 'enabling' a field, all its prerequisites must be enabled too
- $sFieldList = "['{$sFormPrefix}".implode("','{$sFormPrefix}", $aPrerequisites)."']";
- $oP->add_ready_script("$('#enable_{$sFormPrefix}{$sAttCode}').bind('change', function(evt, sFormId) { return PropagateCheckBox( this.checked, $sFieldList, true); } );\n");
- }
- $aDependents = MetaModel::GetDependentAttributes($sClass, $sAttCode); // List of attributes that are needed for the current one
- if (count($aDependents) > 0)
- {
- // When 'disabling' a field, all its dependent fields must be disabled too
- $sFieldList = "['{$sFormPrefix}".implode("','{$sFormPrefix}", $aDependents)."']";
- $oP->add_ready_script("$('#enable_{$sFormPrefix}{$sAttCode}').bind('change', function(evt, sFormId) { return PropagateCheckBox( this.checked, $sFieldList, false); } );\n");
- }
- if ($oAttDef->IsScalar() && $oAttDef->IsWritable())
- {
- if ($oAttDef->GetEditClass() == 'One Way Password')
- {
-
- $sTip = "Unknown values";
- $sReadyScript .= "$('#multi_values_$sAttCode').qtip( { content: '$sTip', show: 'mouseover', hide: 'mouseout', style: { name: 'dark', tip: 'leftTop' }, position: { corner: { target: 'rightMiddle', tooltip: 'leftTop' }} } );";
-
- $oDummyObj->Set($sAttCode, null);
- $aComments[$sAttCode] = ' ';
- $aComments[$sAttCode] .= ' ?
';
- $sReadyScript .= 'ToogleField(false, \''.$iFormId.'_'.$sAttCode.'\');'."\n";
- }
- else
- {
- $iCount = count($aValues[$sAttCode]);
- if ($iCount == 1)
- {
- // Homogenous value
- reset($aValues[$sAttCode]);
- $aKeys = array_keys($aValues[$sAttCode]);
- $currValue = $aKeys[0]; // The only value is the first key
- //echo "current value for $sAttCode : $currValue
";
- $oDummyObj->Set($sAttCode, $currValue);
- $aComments[$sAttCode] = ' ';
- $aComments[$sAttCode] .= '1
';
- }
- else
- {
- // Non-homogenous value
- $aMultiValues = $aValues[$sAttCode];
- uasort($aMultiValues, 'MyComparison');
- $iMaxCount = 5;
- $sTip = "".Dict::Format('UI:BulkModify_Count_DistinctValues', $iCount)."
";
- $index = 0;
- foreach($aMultiValues as $sCurrValue => $aVal)
- {
- $sDisplayValue = empty($aVal['display']) ? ''.Dict::S('Enum:Undefined').' ' : str_replace(array("\n", "\r"), " ", $aVal['display']);
- $sTip .= "".Dict::Format('UI:BulkModify:Value_Exists_N_Times', $sDisplayValue, $aVal['count'])." ";
- $index++;
- if ($iMaxCount == $index)
- {
- $sTip .= "".Dict::Format('UI:BulkModify:N_MoreValues', count($aMultiValues) - $iMaxCount)." ";
- break;
- }
- }
- $sTip .= " ";
- $sTip = addslashes($sTip);
- $sReadyScript .= "$('#multi_values_$sAttCode').qtip( { content: '$sTip', show: 'mouseover', hide: 'mouseout', style: { name: 'dark', tip: 'leftTop' }, position: { corner: { target: 'rightMiddle', tooltip: 'leftTop' }} } );";
-
- $oDummyObj->Set($sAttCode, null);
- $aComments[$sAttCode] = ' ';
- $aComments[$sAttCode] .= ''.$iCount.'
';
- }
- $sReadyScript .= 'ToogleField('.(($iCount == 1) ? 'true': 'false').', \''.$iFormId.'_'.$sAttCode.'\');'."\n";
- }
- }
- }
-
- $sStateAttCode = MetaModel::GetStateAttributeCode($sClass);
- if (($sStateAttCode != '') && ($oDummyObj->GetState() == ''))
- {
- // Hmmm, it's not gonna work like this ! Set a default value for the "state"
- // Maybe we should use the "state" that is the most common among the objects...
- $aMultiValues = $aValues[$sStateAttCode];
- uasort($aMultiValues, 'MyComparison');
- foreach($aMultiValues as $sCurrValue => $aVal)
- {
- $oDummyObj->Set($sStateAttCode, $sCurrValue);
- break;
- }
- //$oStateAtt = MetaModel::GetAttributeDef($sClass, $sStateAttCode);
- //$oDummyObj->Set($sStateAttCode, $oStateAtt->GetDefaultValue());
- }
- $oP->add("\n");
-
- $oP->add("\n");
- $oDummyObj->DisplayModifyForm($oP, array('fieldsComments' => $aComments, 'noRelations' => true, 'custom_operation' => 'preview_or_modify_all', 'custom_button' => Dict::S('UI:Button:PreviewModifications'), 'selectObj' => $sSelectedObj, 'filter' => $sFilter, 'preview_mode' => true, 'disabled_fields' => '{}', 'disable_plugins' => true));
- $oP->add("
\n");
- $oP->add_ready_script($sReadyScript);
- $sURL = "./UI.php?operation=search&filter=".urlencode($sFilter)."&".$oAppContext->GetForLink();
- $oP->add_ready_script(
-<<p("No object selected !, nothing to do");
- }
+ $sCancelUrl = "./UI.php?operation=search&filter=".urlencode($sFilter)."&".$oAppContext->GetForLink();
+ $aContext = array('filter' => $sFilter);
+ cmdbAbstractObject::DisplayBulkModifyForm($oP, $sClass, $aSelectedObj, 'preview_or_modify_all', $sCancelUrl, array(), $aContext);
break;
///////////////////////////////////////////////////////////////////////////////////////////
@@ -1145,101 +697,12 @@ EOF
throw new ApplicationException(Dict::Format('UI:Error:2ParametersMissing', 'class', 'selectObj'));
}
$aSelectedObj = explode(',', $sSelectedObj);
- $aHeaders = array(
- 'form::select' => array('label' => " ", '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+')),
+ $sCancelUrl = "./UI.php?operation=search&filter=".urlencode($sFilter)."&".$oAppContext->GetForLink();
+ $aContext = array(
+ 'filter' => $sFilter,
+ 'selectObj' => $sSelectedObj,
);
- $aRows = array();
-
- $oP->add("\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);
- }
- foreach($aSelectedObj as $iId)
- {
- $oObj = MetaModel::GetObject($sClass, $iId);
- $aErrors = $oObj->UpdateObjectFromPostedForm('');
- $bResult = (count($aErrors) == 0);
- if ($bResult)
- {
- list($bResult, $aErrors) = $oObj->CheckToWrite(true /* Enforce Read-only fields */);
- }
- 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' => " ",
- 'object' => $oObj->GetHyperlink(),
- 'status' => $sStatus,
- 'errors' => ''.($bResult ? '': implode('
', $aErrors)).'
',
- '@class' => $sCSSClass,
- );
- if ($bResult && (!$bPreview))
- {
- $oObj->DBUpdate();
- }
- }
- $oP->Table($aHeaders, $aRows);
- $sURL = "./UI.php?operation=search&filter=".urlencode($sFilter)."&".$oAppContext->GetForLink();
- if ($bPreview)
- {
- // Form to submit:
- $oP->add("\n");
- }
- else
- {
- $sURL = "./UI.php?operation=search&filter=".urlencode($sFilter)."&".$oAppContext->GetForLink();
- $oP->add("".Dict::S('UI:Button:Done')." \n");
- }
+ cmdbAbstractObject::DoBulkModify($oP, $sClass, $aSelectedObj, 'preview_or_modify_all', $bPreview, $sCancelUrl, $aContext);
break;
///////////////////////////////////////////////////////////////////////////////////////////
@@ -1431,7 +894,7 @@ EOF
else
{
// Nothing more to do
- ReloadAndDisplay($oP, $oObj, $sMessage, $sSeverity);
+ ReloadAndDisplay($oP, $oObj, 'update', $sMessage, $sSeverity);
}
}
break;
@@ -1464,47 +927,48 @@ EOF
///////////////////////////////////////////////////////////////////////////////////////////
+ case 'delete':
case 'bulk_delete': // Actual bulk deletion (if confirmed)
- $sClass = utils::ReadPostedParam('class', '');
+ $sClass = utils::ReadParam('class', '', false, 'class');
$sClassLabel = MetaModel::GetName($sClass);
- $sFilter = utils::ReadPostedParam('filter', '');
- $oFullSetFilter = DBObjectSearch::unserialize($sFilter);
- $aSelectObject = utils::ReadMultipleSelection($oFullSetFilter);
$aObjects = array();
- if ( empty($sClass) || empty($aSelectObject)) // TO DO: check that the class name is valid !
+ if ($operation == 'delete')
{
- throw new ApplicationException(Dict::Format('UI:Error:2ParametersMissing', 'class', 'selectObject[]'));
+ // Single object
+ $id = utils::ReadParam('id', '');
+ $oObj = MetaModel::GetObject($sClass, $id);
+ $aObjects[] = $oObj;
+ if (!UserRights::IsActionAllowed($sClass, UR_ACTION_MODIFY, DBObjectSet::FromObject($oObj)))
+ {
+ throw new SecurityException(Dict::Format('UI:Error:DeleteNotAllowedOn_Class', $sClass));
+ }
}
- foreach($aSelectObject as $iId)
+ else
{
- $aObjects[] = MetaModel::GetObject($sClass, $iId);
+ // Several objects
+ $sFilter = utils::ReadPostedParam('filter', '');
+ $oFullSetFilter = DBObjectSearch::unserialize($sFilter);
+ $aSelectObject = utils::ReadMultipleSelection($oFullSetFilter);
+ if ( empty($sClass) || empty($aSelectObject)) // TO DO: check that the class name is valid !
+ {
+ throw new ApplicationException(Dict::Format('UI:Error:2ParametersMissing', 'class', 'selectObject[]'));
+ }
+ foreach($aSelectObject as $iId)
+ {
+ $aObjects[] = MetaModel::GetObject($sClass, $iId);
+ }
+ if (!UserRights::IsActionAllowed($sClass, UR_ACTION_BULK_DELETE, DBObjectSet::FromArray($sClass, $aObjects)))
+ {
+ throw new SecurityException(Dict::Format('UI:Error:BulkDeleteNotAllowedOn_Class', $sClass));
+ }
+ $oP->set_title(Dict::S('UI:BulkDeletePageTitle'));
}
- if (!UserRights::IsActionAllowed($sClass, UR_ACTION_BULK_DELETE, DBObjectSet::FromArray($sClass, $aObjects)))
- {
- throw new SecurityException(Dict::Format('UI:Error:BulkDeleteNotAllowedOn_Class', $sClass));
- }
- $oP->set_title(Dict::S('UI:BulkDeletePageTitle'));
- DeleteObjects($oP, $sClass, $aObjects, ($operation == 'bulk_delete_confirmed'), $oFullSetFilter);
- break;
+ // Go for the common part... (delete single, delete bulk, delete confirmed)
+ cmdbAbstractObject::DeleteObjects($oP, $sClass, $aObjects, ($operation != 'bulk_delete_confirmed'), 'bulk_delete_confirmed');
+ break;
///////////////////////////////////////////////////////////////////////////////////////////
- case 'delete': // Deletion (preview)
- case 'delete_confirmed': // Deletion (confirmed)
- $sClass = utils::ReadParam('class', '', false, 'class');
- $sClassLabel = MetaModel::GetName($sClass);
- $id = utils::ReadParam('id', '');
- $oObj = MetaModel::GetObject($sClass, $id);
-
- if (!UserRights::IsActionAllowed($sClass, UR_ACTION_MODIFY, DBObjectSet::FromObject($oObj)))
- {
- throw new SecurityException(Dict::Format('UI:Error:DeleteNotAllowedOn_Class', $sClass));
- }
- DeleteObjects($oP, $sClass, array($oObj), ($operation == 'delete_confirmed'));
- break;
-
- ///////////////////////////////////////////////////////////////////////////////////////////
-
case 'apply_new': // Creation of a new object
$sClass = utils::ReadPostedParam('class', '', 'class');
$sClassLabel = MetaModel::GetName($sClass);
@@ -1555,7 +1019,7 @@ EOF
else
{
// Nothing more to do
- ReloadAndDisplay($oP, $oObj, $sMessage, 'ok');
+ ReloadAndDisplay($oP, $oObj, 'create', $sMessage, 'ok');
}
}
else
@@ -2116,7 +1580,7 @@ EOF
$sSeverity = 'error';
}
}
- ReloadAndDisplay($oP, $oObj, $sMessage, $sSeverity);
+ ReloadAndDisplay($oP, $oObj, 'apply_stimulus', $sMessage, $sSeverity);
}
else
{