Pārlūkot izejas kodu

#886 Delete change history so that if an ID is reused the history starts from scratch (and cleanup most of the data as soon as the object is deleted)

git-svn-id: http://svn.code.sf.net/p/itop/code/trunk@3177 a333f486-631f-4898-b8df-5754b55c2be0
romainq 11 gadi atpakaļ
vecāks
revīzija
a76dbb3a95
2 mainītis faili ar 58 papildinājumiem un 0 dzēšanām
  1. 23 0
      core/cmdbobject.class.inc.php
  2. 35 0
      core/metamodel.class.php

+ 23 - 0
core/cmdbobject.class.inc.php

@@ -162,6 +162,21 @@ abstract class CMDBObject extends DBObject
 
 	protected function RecordObjCreation()
 	{
+		// Delete any existing change tracking about the current object (IDs can be reused due to InnoDb bug; see TRAC #886)
+		//
+		// 1 - remove the deletion record(s)
+		// Note that objclass contain the ROOT class
+		$oFilter = new DBObjectSearch('CMDBChangeOpDelete');
+		$oFilter->AddCondition('objclass', MetaModel::GetRootClass(get_class($this)), '=');
+		$oFilter->AddCondition('objkey', $this->GetKey(), '=');
+		MetaModel::PurgeData($oFilter);
+		// 2 - any other change tracking information left prior to 2.0.3 (when the purge of the history has been implemented in RecordObjDeletion
+		// In that case, objclass is the final class of the object
+		$oFilter = new DBObjectSearch('CMDBChangeOp');
+		$oFilter->AddCondition('objclass', get_class($this), '=');
+		$oFilter->AddCondition('objkey', $this->GetKey(), '=');
+		MetaModel::PurgeData($oFilter);
+
 		parent::RecordObjCreation();
 		$oMyChangeOp = MetaModel::NewObject("CMDBChangeOpCreate");
 		$oMyChangeOp->Set("objclass", get_class($this));
@@ -171,6 +186,14 @@ abstract class CMDBObject extends DBObject
 
 	protected function RecordObjDeletion($objkey)
 	{
+		$sRootClass = MetaModel::GetRootClass(get_class($this));
+
+		// Delete any existing change tracking about the current object
+		$oFilter = new DBObjectSearch('CMDBChangeOp');
+		$oFilter->AddCondition('objclass', get_class($this), '=');
+		$oFilter->AddCondition('objkey', $objkey, '=');
+		MetaModel::PurgeData($oFilter);
+
 		parent::RecordObjDeletion($objkey);
 		$oMyChangeOp = MetaModel::NewObject("CMDBChangeOpDelete");
 		$oMyChangeOp->Set("objclass", MetaModel::GetRootClass(get_class($this)));

+ 35 - 0
core/metamodel.class.php

@@ -5087,6 +5087,41 @@ abstract class MetaModel
 		}
 	}
 
+	/**
+	 * Helper to remove selected objects without calling any handler
+	 * Surpasses BulkDelete as it can handle abstract classes, but has the other limitation as it bypasses standard objects handlers 
+	 * 	 
+	 * @param string $oFilter Scope of objects to wipe out
+	 * @return The count of deleted objects
+	 */	 	
+	public static function PurgeData($oFilter)
+	{
+		$sTargetClass = $oFilter->GetClass();
+		$oSet = new DBObjectSet($oFilter);
+		$oSet->OptimizeColumnLoad(array($sTargetClass => array('finalclass')));
+		$aIdToClass = $oSet->GetColumnAsArray('finalclass', true);
+
+		$aIds = array_keys($aIdToClass);
+		if (count($aIds) > 0)
+		{
+			$aQuotedIds = CMDBSource::Quote($aIds);
+			$sIdList = implode(',', $aQuotedIds);
+			$aTargetClasses = array_merge(
+				self::EnumChildClasses($sTargetClass, ENUM_CHILD_CLASSES_ALL),
+				self::EnumParentClasses($sTargetClass, ENUM_PARENT_CLASSES_EXCLUDELEAF)
+			);
+			foreach ($aTargetClasses as $sSomeClass)
+			{
+				$sTable = MetaModel::DBGetTable($sSomeClass);
+				$sPKField = MetaModel::DBGetKey($sSomeClass);
+		
+				$sDeleteSQL = "DELETE FROM `$sTable` WHERE `$sPKField` IN ($sIdList)";
+				CMDBSource::DeleteFrom($sDeleteSQL);
+			}
+		}
+		return count($aIds);
+	}
+
 	// Links
 	//
 	//