diff --git a/application/cmdbabstract.class.inc.php b/application/cmdbabstract.class.inc.php index 590495ded..a42c0b5a5 100644 --- a/application/cmdbabstract.class.inc.php +++ b/application/cmdbabstract.class.inc.php @@ -4533,8 +4533,6 @@ HTML; } } finally { if (static::IsCrudStackEmpty()) { - // Avoid signaling the current object that links were modified - static::RemoveObjectAwaitingEventDbLinksChanged(get_class($this), $this->GetKey()); static::FireEventDbLinksChangedForAllObjects(); } } @@ -5811,6 +5809,7 @@ JS final protected function FireEventCreateDone(): void { $this->NotifyAttachedObjectsOnLinkClassModification(); + $this->FireEventDbLinksChangedForCurrentObject(); $this->FireEvent(EVENT_DB_CREATE_DONE); } @@ -5829,6 +5828,7 @@ JS final protected function FireEventUpdateDone(array $aChanges): void { $this->NotifyAttachedObjectsOnLinkClassModification(); + $this->FireEventDbLinksChangedForCurrentObject(); $this->FireEvent(EVENT_DB_UPDATE_DONE, ['changes' => $aChanges]); } @@ -5857,6 +5857,7 @@ JS final protected function FireEventDeleteDone(): void { $this->NotifyAttachedObjectsOnLinkClassModification(); + $this->FireEventDbLinksChangedForCurrentObject(); $this->FireEvent(EVENT_DB_DELETE_DONE); } @@ -5955,11 +5956,24 @@ JS return; } - $oObject = MetaModel::GetObject($sClass, $sId); + // First we are disabling firing the event to avoid reentrance + // For example on a Ticket : + // - in the Ticket CRUD stack, DBWriteLinks will generate lnkApplicationSolutionToFunctionalCI instances + // - therefore the $aObjectsAwaitingEventDbLinksChanged attribute will contain our Ticket + // - we have a EVENT_DB_LINKS_CHANGED listener on Ticket that will update impacted items, so it will create new lnkApplicationSolutionToFunctionalCI + // We want to avoid launching the listener twice, first here, and secondly after saving the Ticket in the listener + // By disabling the event to be fired, we can remove the current object from the attribute ! + /** @noinspection PhpRedundantOptionalArgumentInspection */ + $oObject = MetaModel::GetObject($sClass, $sId, true); + self::SetEventDBLinksChangedBlocked(true); + MetaModel::StartReentranceProtection($oObject); $oObject->FireEvent(EVENT_DB_LINKS_CHANGED); - - // The event listeners might have generated new lnk instances pointing to this object, so removing object from stack to avoid reentrance + MetaModel::StopReentranceProtection($oObject); + if ($oObject->IsModified()) { + $oObject->DBUpdate(); + } self::RemoveObjectAwaitingEventDbLinksChanged($sClass, $sId); + cmdbAbstractObject::SetEventDBLinksChangedBlocked(false); } /** diff --git a/datamodels/2.x/itop-change-mgmt-itil/datamodel.itop-change-mgmt-itil.xml b/datamodels/2.x/itop-change-mgmt-itil/datamodel.itop-change-mgmt-itil.xml index 3c1ed44d1..19868bfb5 100755 --- a/datamodels/2.x/itop-change-mgmt-itil/datamodel.itop-change-mgmt-itil.xml +++ b/datamodels/2.x/itop-change-mgmt-itil/datamodel.itop-change-mgmt-itil.xml @@ -1022,8 +1022,7 @@ UpdateImpactedItems(); + parent::OnInsert(); $this->SetIfNull('creation_date', time()); $this->SetIfNull('last_update', time()); }]]> @@ -1036,11 +1035,6 @@ protected function OnUpdate() { parent::OnUpdate(); - $aChanges = $this->ListChanges(); - if (array_key_exists('functionalcis_list', $aChanges)) - { - $this->UpdateImpactedItems(); - } $this->Set('last_update', time()); }]]> diff --git a/datamodels/2.x/itop-change-mgmt/datamodel.itop-change-mgmt.xml b/datamodels/2.x/itop-change-mgmt/datamodel.itop-change-mgmt.xml index 7e810881d..9257d2bc4 100755 --- a/datamodels/2.x/itop-change-mgmt/datamodel.itop-change-mgmt.xml +++ b/datamodels/2.x/itop-change-mgmt/datamodel.itop-change-mgmt.xml @@ -581,8 +581,7 @@ UpdateImpactedItems(); + parent::OnInsert(); $this->SetIfNull('creation_date', time()); $this->SetIfNull('last_update', time()); }]]> @@ -594,12 +593,7 @@ ListChanges(); - if (array_key_exists('functionalcis_list', $aChanges)) - { - $this->UpdateImpactedItems(); - } + parent::OnUpdate(); $this->Set('last_update', time()); }]]> diff --git a/datamodels/2.x/itop-incident-mgmt-itil/datamodel.itop-incident-mgmt-itil.xml b/datamodels/2.x/itop-incident-mgmt-itil/datamodel.itop-incident-mgmt-itil.xml index c436eb272..d7bc535d5 100755 --- a/datamodels/2.x/itop-incident-mgmt-itil/datamodel.itop-incident-mgmt-itil.xml +++ b/datamodels/2.x/itop-incident-mgmt-itil/datamodel.itop-incident-mgmt-itil.xml @@ -1496,12 +1496,7 @@ Overload-DBObject ListChanges(); - if (array_key_exists('functionalcis_list', $aChanges)) - { - $this->UpdateImpactedItems(); - } + parent::OnUpdate(); $this->Set('last_update', time()); $this->UpdateChildRequestLog(); $this->UpdateChildIncidentLog(); diff --git a/datamodels/2.x/itop-request-mgmt-itil/datamodel.itop-request-mgmt-itil.xml b/datamodels/2.x/itop-request-mgmt-itil/datamodel.itop-request-mgmt-itil.xml index b07c6b6ba..0f8eb7fdc 100755 --- a/datamodels/2.x/itop-request-mgmt-itil/datamodel.itop-request-mgmt-itil.xml +++ b/datamodels/2.x/itop-request-mgmt-itil/datamodel.itop-request-mgmt-itil.xml @@ -1567,11 +1567,6 @@ protected function OnUpdate() { parent::OnUpdate(); - $aChanges = $this->ListChanges(); - if (array_key_exists('functionalcis_list', $aChanges)) - { - $this->UpdateImpactedItems(); - } $this->Set('last_update', time()); $this->UpdateChildRequestLog(); }]]> diff --git a/datamodels/2.x/itop-request-mgmt/datamodel.itop-request-mgmt.xml b/datamodels/2.x/itop-request-mgmt/datamodel.itop-request-mgmt.xml index 9531732e7..a3f6c14e0 100755 --- a/datamodels/2.x/itop-request-mgmt/datamodel.itop-request-mgmt.xml +++ b/datamodels/2.x/itop-request-mgmt/datamodel.itop-request-mgmt.xml @@ -1610,12 +1610,7 @@ ListChanges(); - if (array_key_exists('functionalcis_list', $aChanges)) - { - $this->UpdateImpactedItems(); - } + parent::OnUpdate(); $this->Set('last_update', time()); $this->UpdateChildRequestLog(); }]]> diff --git a/datamodels/2.x/itop-tickets/datamodel.itop-tickets.xml b/datamodels/2.x/itop-tickets/datamodel.itop-tickets.xml index d78f9f9db..2c4d3819e 100755 --- a/datamodels/2.x/itop-tickets/datamodel.itop-tickets.xml +++ b/datamodels/2.x/itop-tickets/datamodel.itop-tickets.xml @@ -223,23 +223,11 @@ EVENT_DB_LINKS_CHANGED - UpdateTicketImpactedItems + UpdateImpactedItems 0 - - - false - public - EventListener - UpdateImpactedItems(); - $this->DBUpdate(); -} - ]]> - false public diff --git a/tests/php-unit-tests/unitary-tests/application/cmdbAbstractObjectTest.php b/tests/php-unit-tests/unitary-tests/application/cmdbAbstractObjectTest.php index f2395d9a0..e2d90b7de 100644 --- a/tests/php-unit-tests/unitary-tests/application/cmdbAbstractObjectTest.php +++ b/tests/php-unit-tests/unitary-tests/application/cmdbAbstractObjectTest.php @@ -195,8 +195,8 @@ class cmdbAbstractObjectTest extends ItopDataTestCase { $oTeam->DBInsert(); $this->assertIsObject($oTeam); - // 3 links added to person (the Team side is ignored) - $this->assertEquals(3, self::$aEventCalls[EVENT_DB_LINKS_CHANGED]); + // 3 links added to person + 1 for the Team + $this->assertEquals(4, self::$aEventCalls[EVENT_DB_LINKS_CHANGED]); } /**