mirror of
https://github.com/Combodo/iTop.git
synced 2026-04-24 11:08:45 +02:00
Deletion of objects:
- automatic delete of mandatory ext keys, and if the option is set in the data model (I've set the "manual" option by default, and the "auto" option for links) - automatic reset of optional ext keys (several keys could be updated on one single object) - takes into account the user rights - security against the use of page arguments when the automatic deletion is not allowed Known limitations: - does not check that resetting an ext key could affect the lifecycle consistency (e.g. delete a workgroup referenced by a ticket) - does not check recursively on the automatic deletion, which should not be a problem given the current data model (TBC) SVN:trunk[181]
This commit is contained in:
@@ -17,6 +17,20 @@ define('EXTKEY_RELATIVE', 1);
|
||||
*/
|
||||
define('EXTKEY_ABSOLUTE', 2);
|
||||
|
||||
/**
|
||||
* Propagation of the deletion through an external key - ask the user to delete the referencing object
|
||||
*
|
||||
* @package iTopORM
|
||||
*/
|
||||
define('DEL_MANUAL', 1);
|
||||
|
||||
/**
|
||||
* Propagation of the deletion through an external key - ask the user to delete the referencing object
|
||||
*
|
||||
* @package iTopORM
|
||||
*/
|
||||
define('DEL_AUTO', 2);
|
||||
|
||||
|
||||
/**
|
||||
* Attribute definition API, implemented in and many flavours (Int, String, Enum, etc.)
|
||||
@@ -805,7 +819,7 @@ class AttributeExternalKey extends AttributeDBFieldVoid
|
||||
{
|
||||
static protected function ListExpectedParams()
|
||||
{
|
||||
return array_merge(parent::ListExpectedParams(), array("targetclass", "is_null_allowed"));
|
||||
return array_merge(parent::ListExpectedParams(), array("targetclass", "is_null_allowed", "on_target_delete"));
|
||||
}
|
||||
|
||||
public function GetType() {return "Extkey";}
|
||||
@@ -862,6 +876,11 @@ class AttributeExternalKey extends AttributeDBFieldVoid
|
||||
return $oValSetDef->GetValues($aArgs, $sBeginsWith);
|
||||
}
|
||||
}
|
||||
|
||||
public function GetDeletionPropagationOption()
|
||||
{
|
||||
return $this->Get("on_target_delete");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -32,7 +32,7 @@ class CMDBChangeOp extends DBObject
|
||||
);
|
||||
MetaModel::Init_Params($aParams);
|
||||
//MetaModel::Init_InheritAttributes();
|
||||
MetaModel::Init_AddAttribute(new AttributeExternalKey("change", array("label"=>"change", "description"=>"change", "allowed_values"=>null, "sql"=>"changeid", "targetclass"=>"CMDBChange", "is_null_allowed"=>false, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeExternalKey("change", array("label"=>"change", "description"=>"change", "allowed_values"=>null, "sql"=>"changeid", "targetclass"=>"CMDBChange", "is_null_allowed"=>false, "on_target_delete"=>DEL_MANUAL, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeExternalField("date", array("label"=>"date", "description"=>"date and time of the change", "allowed_values"=>null, "extkey_attcode"=>"change", "target_attcode"=>"date")));
|
||||
MetaModel::Init_AddAttribute(new AttributeExternalField("userinfo", array("label"=>"user", "description"=>"who made this change", "allowed_values"=>null, "extkey_attcode"=>"change", "target_attcode"=>"userinfo")));
|
||||
MetaModel::Init_AddAttribute(new AttributeString("objclass", array("label"=>"object class", "description"=>"object class", "allowed_values"=>null, "sql"=>"objclass", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
<?php
|
||||
|
||||
|
||||
class SecurityException extends CoreException
|
||||
{
|
||||
}
|
||||
|
||||
class CoreException extends Exception
|
||||
{
|
||||
public function __construct($sIssue, $aContextData = null, $sImpact = '')
|
||||
|
||||
@@ -856,20 +856,79 @@ abstract class DBObject
|
||||
{
|
||||
foreach($aExtKeys as $sExtKeyAttCode => $oExtKeyAttDef)
|
||||
{
|
||||
//$oAttDef = MetaModel::GetAttributeDef($sClass, $sExtKeyAttCode);
|
||||
// skip if this external key is behind an external field
|
||||
if (!$oExtKeyAttDef->IsExternalKey(EXTKEY_ABSOLUTE)) continue;
|
||||
|
||||
$oSearch = new DBObjectSearch($sRemoteClass);
|
||||
$oSearch->AddCondition($sExtKeyAttCode, $this->GetKey());
|
||||
$oSet = new CMDBObjectSet($oSearch);
|
||||
//if ($oSet->Count() > 0)
|
||||
while ($oDependentObj = $oSet->fetch())
|
||||
if ($oSet->Count() > 0)
|
||||
{
|
||||
$aDependentObjects[$sRemoteClass][] = $oDependentObj;
|
||||
$aDependentObjects[$sRemoteClass][$sExtKeyAttCode] = array(
|
||||
'attribute' => $oExtKeyAttDef,
|
||||
'objects' => $oSet,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $aDependentObjects;
|
||||
}
|
||||
|
||||
public function GetDeletionScheme()
|
||||
{
|
||||
$aDependentObjects = $this->GetReferencingObjects();
|
||||
$aDeletedObjs = array(); // [class][key] => structure
|
||||
$aResetedObjs = array(); // [class][key] => object
|
||||
foreach ($aDependentObjects as $sRemoteClass => $aPotentialDeletes)
|
||||
{
|
||||
foreach ($aPotentialDeletes as $sRemoteExtKey => $aData)
|
||||
{
|
||||
$oAttDef = $aData['attribute'];
|
||||
$iDeletePropagationOption = $oAttDef->GetDeletionPropagationOption();
|
||||
$oDepSet = $aData['objects'];
|
||||
$oDepSet->Rewind();
|
||||
while ($oDependentObj = $oDepSet->fetch())
|
||||
{
|
||||
$iId = $oDependentObj->GetKey();
|
||||
if ($oAttDef->IsNullAllowed())
|
||||
{
|
||||
// Optional external key, list to reset
|
||||
if (!array_key_exists($sRemoteClass, $aResetedObjs) || !array_key_exists($iId, $aResetedObjs[$sRemoteClass]))
|
||||
{
|
||||
$aResetedObjs[$sRemoteClass][$iId]['to_reset'] = $oDependentObj;
|
||||
}
|
||||
$aResetedObjs[$sRemoteClass][$iId]['attributes'][$sRemoteExtKey] = $oAttDef;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Mandatory external key, list to delete
|
||||
if (array_key_exists($sRemoteClass, $aDeletedObjs) && array_key_exists($iId, $aDeletedObjs[$sRemoteClass]))
|
||||
{
|
||||
$iCurrentOption = $aDeletedObjs[$sRemoteClass][$iId];
|
||||
if ($iCurrentOption == DEL_AUTO)
|
||||
{
|
||||
// be conservative, take the new option
|
||||
// (DEL_MANUAL has precedence over DEL_AUTO)
|
||||
$aDeletedObjs[$sRemoteClass][$iId]['auto_delete'] = ($iDeletePropagationOption == DEL_AUTO);
|
||||
}
|
||||
else
|
||||
{
|
||||
// DEL_MANUAL... leave it as is, it HAS to be verified anyway
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// First time we find the given object in the list
|
||||
// (and most likely case is that no other occurence will be found)
|
||||
$aDeletedObjs[$sRemoteClass][$iId]['to_delete'] = $oDependentObj;
|
||||
$aDeletedObjs[$sRemoteClass][$iId]['auto_delete'] = ($iDeletePropagationOption == DEL_AUTO);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return array($aDeletedObjs, $aResetedObjs);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -57,6 +57,13 @@ class DBObjectSet
|
||||
return $sRet;
|
||||
}
|
||||
|
||||
static public function FromObject($oObject)
|
||||
{
|
||||
$oRetSet = self::FromScratch(get_class($oObject));
|
||||
$oRetSet->AddObject($oObject);
|
||||
return $oRetSet;
|
||||
}
|
||||
|
||||
static public function FromScratch($sClass)
|
||||
{
|
||||
$oFilter = new CMDBSearchFilter($sClass);
|
||||
|
||||
Reference in New Issue
Block a user