mirror of
https://github.com/Combodo/iTop.git
synced 2026-02-13 07:24:13 +01:00
Protection against reentrance for DBUpdate
This commit is contained in:
@@ -4488,7 +4488,7 @@ HTML;
|
||||
|
||||
// Protection against reentrance (e.g. cascading the update of ticket logs)
|
||||
// Note: This is based on the fix made on r 3190 in DBObject::DBUpdate()
|
||||
if (!MetaModel::StartReentranceProtection($this)) {
|
||||
if (!MetaModel::StartReentranceProtection(Metamodel::REENTRANCE_TYPE_UPDATE, $this)) {
|
||||
$sClass = get_class($this);
|
||||
$sKey = $this->GetKey();
|
||||
IssueLog::Debug("CRUD: DBUpdate $sClass::$sKey Rejected (reentrance)", LogChannels::DM_CRUD);
|
||||
@@ -4507,7 +4507,7 @@ HTML;
|
||||
}
|
||||
finally
|
||||
{
|
||||
MetaModel::StopReentranceProtection($this);
|
||||
MetaModel::StopReentranceProtection(Metamodel::REENTRANCE_TYPE_UPDATE, $this);
|
||||
}
|
||||
|
||||
if ($this->IsModified()) {
|
||||
|
||||
@@ -3063,7 +3063,7 @@ abstract class DBObject implements iDisplay
|
||||
}
|
||||
|
||||
// Prevent DBUpdate at this point (reentrance protection)
|
||||
MetaModel::StartReentranceProtection($this);
|
||||
MetaModel::StartReentranceProtection(Metamodel::REENTRANCE_TYPE_UPDATE, $this);
|
||||
|
||||
$this->AfterInsert();
|
||||
|
||||
@@ -3086,7 +3086,7 @@ abstract class DBObject implements iDisplay
|
||||
// - TriggerOnObjectMention
|
||||
$this->ActivateOnMentionTriggers(true);
|
||||
|
||||
MetaModel::StopReentranceProtection($this);
|
||||
MetaModel::StopReentranceProtection(Metamodel::REENTRANCE_TYPE_UPDATE, $this);
|
||||
|
||||
if ($this->IsModified()) {
|
||||
$this->DBUpdate();
|
||||
@@ -3157,7 +3157,7 @@ abstract class DBObject implements iDisplay
|
||||
// Protect against reentrance (e.g. cascading the update of ticket logs)
|
||||
$sClass = get_class($this);
|
||||
$sKey = $this->GetKey();
|
||||
if (!MetaModel::StartReentranceProtection($this)) {
|
||||
if (!MetaModel::StartReentranceProtection(Metamodel::REENTRANCE_TYPE_UPDATE, $this)) {
|
||||
|
||||
IssueLog::Debug("CRUD: DBUpdate $sClass::$sKey Rejected (reentrance)", LogChannels::DM_CRUD);
|
||||
|
||||
@@ -3195,7 +3195,7 @@ abstract class DBObject implements iDisplay
|
||||
if (count($aChanges) == 0)
|
||||
{
|
||||
// Attempting to update an unchanged object
|
||||
MetaModel::StopReentranceProtection($this);
|
||||
MetaModel::StopReentranceProtection(Metamodel::REENTRANCE_TYPE_UPDATE, $this);
|
||||
IssueLog::Debug("CRUD: DBUpdate $sClass::$sKey Aborted (no change)", LogChannels::DM_CRUD);
|
||||
|
||||
return $this->m_iKey;
|
||||
@@ -3411,7 +3411,7 @@ abstract class DBObject implements iDisplay
|
||||
}
|
||||
finally
|
||||
{
|
||||
MetaModel::StopReentranceProtection($this);
|
||||
MetaModel::StopReentranceProtection(Metamodel::REENTRANCE_TYPE_UPDATE, $this);
|
||||
}
|
||||
|
||||
if ($this->IsModified()) {
|
||||
|
||||
@@ -128,7 +128,9 @@ abstract class MetaModel
|
||||
/** @var string */
|
||||
protected static $m_sEnvironment = 'production';
|
||||
|
||||
protected static $m_aReentryProtection = [];
|
||||
public const REENTRANCE_TYPE_UPDATE = 'update';
|
||||
|
||||
protected static $m_aReentranceProtection = [];
|
||||
|
||||
/**
|
||||
* MetaModel constructor.
|
||||
@@ -6800,6 +6802,19 @@ abstract class MetaModel
|
||||
}
|
||||
$sClass = $aRow[$sClassAlias."finalclass"];
|
||||
}
|
||||
|
||||
// if an object is already being updated, then this method will return this object instead of recreating a new one.
|
||||
// At this point the method DBUpdate of a new object with the same class and id won't do anything due to reentrance protection,
|
||||
// so to ensure that the potential modifications are correctly saved, the object currently being updated is returned.
|
||||
// DBUpdate() method then will take care that all the modifications will be saved.
|
||||
if (array_key_exists($sClassAlias.'id', $aRow)) {
|
||||
$iKey = $aRow[$sClassAlias."id"];
|
||||
$oObject = self::GetReentranceObject(Metamodel::REENTRANCE_TYPE_UPDATE, $sClass, $iKey);
|
||||
if ($oObject !== false) {
|
||||
return $oObject;
|
||||
}
|
||||
}
|
||||
|
||||
return new $sClass($aRow, $sClassAlias, $aAttToLoad, $aExtendedDataSpec);
|
||||
}
|
||||
|
||||
@@ -6825,11 +6840,6 @@ abstract class MetaModel
|
||||
*/
|
||||
public static function GetObject($sClass, $iKey, $bMustBeFound = true, $bAllowAllData = false, $aModifierProperties = null)
|
||||
{
|
||||
$oObject = self::GetReentryObject($sClass, $iKey);
|
||||
if ($oObject !== false) {
|
||||
return $oObject;
|
||||
}
|
||||
|
||||
$oObject = self::GetObjectWithArchive($sClass, $iKey, $bMustBeFound, $bAllowAllData, $aModifierProperties);
|
||||
|
||||
if (empty($oObject))
|
||||
@@ -7567,32 +7577,33 @@ abstract class MetaModel
|
||||
return $oAttDef->GetStyle($sValue);
|
||||
}
|
||||
|
||||
protected static function GetReentryObject($sClass, $sKey)
|
||||
protected static function GetReentranceObject($sType, $sClass, $sKey)
|
||||
{
|
||||
if (isset(self::$m_aReentryProtection[$sClass][$sKey])) {
|
||||
return self::$m_aReentryProtection[$sClass][$sKey];
|
||||
if (isset(self::$m_aReentranceProtection[$sType][$sClass][$sKey])) {
|
||||
return self::$m_aReentranceProtection[$sType][$sClass][$sKey];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $sType
|
||||
* @param \DBObject $oObject
|
||||
*
|
||||
* @return bool true if reentry possible
|
||||
*/
|
||||
public static function StartReentranceProtection(DBObject $oObject)
|
||||
public static function StartReentranceProtection($sType, DBObject $oObject)
|
||||
{
|
||||
if (isset(self::$m_aReentryProtection[get_class($oObject)][$oObject->GetKey()])) {
|
||||
if (isset(self::$m_aReentranceProtection[$sType][get_class($oObject)][$oObject->GetKey()])) {
|
||||
return false;
|
||||
}
|
||||
self::$m_aReentryProtection[get_class($oObject)][$oObject->GetKey()] = $oObject;
|
||||
self::$m_aReentranceProtection[$sType][get_class($oObject)][$oObject->GetKey()] = $oObject;
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function StopReentranceProtection(DBObject $oObject)
|
||||
public static function StopReentranceProtection($sType, DBObject $oObject)
|
||||
{
|
||||
if (isset(self::$m_aReentryProtection[get_class($oObject)][$oObject->GetKey()])) {
|
||||
unset(self::$m_aReentryProtection[get_class($oObject)][$oObject->GetKey()]);
|
||||
if (isset(self::$m_aReentranceProtection[$sType][get_class($oObject)][$oObject->GetKey()])) {
|
||||
unset(self::$m_aReentranceProtection[$sType][get_class($oObject)][$oObject->GetKey()]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,7 +151,7 @@ class DBObjectTest extends ItopDataTestCase
|
||||
$oNewPerson = MetaModel::GetObject('Person', $oPerson->GetKey());
|
||||
$this->assertNotEquals($oPerson->GetObjectUniqId(), $oNewPerson->GetObjectUniqId());
|
||||
|
||||
MetaModel::StartReentranceProtection($oPerson);
|
||||
MetaModel::StartReentranceProtection(Metamodel::REENTRANCE_TYPE_UPDATE, $oPerson);
|
||||
|
||||
$oPerson->Set('email', 'test1@combodo.com');
|
||||
$oPerson->DBUpdate();
|
||||
@@ -161,7 +161,7 @@ class DBObjectTest extends ItopDataTestCase
|
||||
$oNewPerson = MetaModel::GetObject('Person', $oPerson->GetKey());
|
||||
$this->assertEquals($oPerson->GetObjectUniqId(), $oNewPerson->GetObjectUniqId());
|
||||
|
||||
MetaModel::StopReentranceProtection($oPerson);
|
||||
MetaModel::StopReentranceProtection(Metamodel::REENTRANCE_TYPE_UPDATE, $oPerson);
|
||||
}
|
||||
|
||||
public function testObjectIsReadOnly()
|
||||
|
||||
Reference in New Issue
Block a user