From d74573edb7d6dd05cebc0483489be5b484a73df8 Mon Sep 17 00:00:00 2001 From: Benjamin Dalsass Date: Mon, 18 Aug 2025 10:54:03 +0200 Subject: [PATCH 1/5] =?UTF-8?q?N=C2=B08210=20-=20Remove=20iApplicationObje?= =?UTF-8?q?ctExtension?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- application/applicationextension.inc.php | 167 ------------------ application/cmdbabstract.class.inc.php | 97 +--------- core/metamodel.class.php | 1 - .../main.itop-attachments.php | 48 ++--- lib/composer/autoload_classmap.php | 2 - lib/composer/autoload_static.php | 2 - lib/composer/installed.php | 4 +- .../ApplicationObjectExtensionTest.php | 103 ----------- .../ApplicationExtensionTest.php | 4 - ...plication-extension-usages-in-snippets.xml | 10 -- ...MockApplicationObjectExtensionForTest1.php | 75 -------- ...MockApplicationObjectExtensionForTest2.php | 75 -------- 12 files changed, 18 insertions(+), 570 deletions(-) delete mode 100644 tests/php-unit-tests/unitary-tests/application/ApplicationObjectExtensionTest.php delete mode 100644 tests/php-unit-tests/unitary-tests/application/iApplicationObjectExtension/MockApplicationObjectExtensionForTest1.php delete mode 100644 tests/php-unit-tests/unitary-tests/application/iApplicationObjectExtension/MockApplicationObjectExtensionForTest2.php diff --git a/application/applicationextension.inc.php b/application/applicationextension.inc.php index 022ef6684d..01bb9d1e3e 100644 --- a/application/applicationextension.inc.php +++ b/application/applicationextension.inc.php @@ -553,173 +553,6 @@ public function EnumAllowedActions(DBObjectSet $oSet) } -/** - * Implement this interface to perform specific operations when objects are manipulated - * - * Note that those methods will be called when objects are manipulated, either in a programmatic way - * or through the GUI. - * - * @api - * @deprecated 3.1.0 N°4756 use the new event service instead, see {@see DBObject::FireEvent()} method. More details on each method PHPDoc. - * @package ORMExtensibilityAPI - */ -interface iApplicationObjectExtension -{ - /** - * Invoked to determine whether an object has been modified in memory - * - * The GUI calls this verb to determine the message that will be displayed to the end-user. - * Anyhow, this API can be called in other contexts such as the CSV import tool. - * - * If the extension returns false, then the framework will perform the usual evaluation. - * Otherwise, the answer is definitively "yes, the object has changed". - * - * @api - * @deprecated 3.1.0 N°4756 No alternative available, this API was unstable and is abandoned - * @param \cmdbAbstractObject $oObject The target object - * - * @return boolean True if something has changed for the target object - */ - public function OnIsModified($oObject); - - /** - * Invoked to determine whether an object can be written to the database - * - * The GUI calls this verb and reports any issue. - * Anyhow, this API can be called in other contexts such as the CSV import tool. - * - * @api - * @deprecated 3.1.0 N°4756 Use EVENT_DB_CHECK_TO_WRITE event instead - * @param \cmdbAbstractObject $oObject The target object - * - * @return string[] A list of errors message. An error message is made of one line and it can be displayed to the end-user. - */ - public function OnCheckToWrite($oObject); - - /** - * Invoked to determine wether an object can be deleted from the database - * - * The GUI calls this verb and stops the deletion process if any issue is reported. - * - * Please not that it is not possible to cascade deletion by this mean: only stopper issues can be handled. - * - * @api - * @deprecated 3.1.0 N°4756 Use EVENT_DB_CHECK_TO_DELETE event instead - * @param \cmdbAbstractObject $oObject The target object - * - * @return string[] A list of errors message. An error message is made of one line and it can be displayed to the end-user. - */ - public function OnCheckToDelete($oObject); - - /** - * Invoked when an object is updated into the database. The method is called right after the object has been written to the - * database. - * - * Useful methods you can call on $oObject : - * - * * {@see DBObject::ListPreviousValuesForUpdatedAttributes()} : list of changed attributes and their values before the change - * * {@see DBObject::Get()} : for a given attribute the new value that was persisted - * - * @api - * @deprecated 3.1.0 N°4756 Use EVENT_DB_AFTER_WRITE event instead - * @param \cmdbAbstractObject $oObject The target object - * @param CMDBChange|null $oChange A change context. Since 2.0 it is fine to ignore it, as the framework does maintain this information - * once for all the changes made within the current page - * - * @return void - * - * @since 2.7.0 N°2293 can access object changes by calling {@see DBObject::ListPreviousValuesForUpdatedAttributes()} on $oObject - */ - public function OnDBUpdate($oObject, $oChange = null); - - /** - * Invoked when an object is created into the database - * - * The method is called right after the object has been written to the database. - * - * @api - * @deprecated 3.1.0 N°4756 Use EVENT_DB_AFTER_WRITE event instead - * @param \cmdbAbstractObject $oObject The target object - * @param CMDBChange|null $oChange A change context. Since 2.0 it is fine to ignore it, as the framework does maintain this information - * once for all the changes made within the current page - * - * @return void - */ - public function OnDBInsert($oObject, $oChange = null); - - /** - * Invoked when an object is deleted from the database - * - * The method is called right before the object will be deleted from the database. - * - * @api - * @deprecated 3.1.0 N°4756 Use EVENT_DB_AFTER_DELETE event instead - * @param \cmdbAbstractObject $oObject The target object - * @param CMDBChange|null $oChange A change context. Since 2.0 it is fine to ignore it, as the framework does maintain this information - * once for all the changes made within the current page - * - * @return void - */ - public function OnDBDelete($oObject, $oChange = null); -} - -/** - * Extend this class instead of iApplicationObjectExtension if you don't need to overload all methods - * - * @api - * @deprecated 3.1.0 N°4756 use the new event service instead, see {@see DBObject::FireEvent()} method - * @package ORMExtensibilityAPI - * @since 2.7.0 - */ -abstract class AbstractApplicationObjectExtension implements iApplicationObjectExtension -{ - /** - * @inheritDoc - */ - public function OnIsModified($oObject) - { - return false; - } - - /** - * @inheritDoc - */ - public function OnCheckToWrite($oObject) - { - return array(); - } - - /** - * @inheritDoc - */ - public function OnCheckToDelete($oObject) - { - return array(); - } - - /** - * @inheritDoc - */ - public function OnDBUpdate($oObject, $oChange = null) - { - } - - /** - * @inheritDoc - */ - public function OnDBInsert($oObject, $oChange = null) - { - } - - /** - * @inheritDoc - */ - public function OnDBDelete($oObject, $oChange = null) - { - } - -} - /** * New extension to add menu items in the "popup" menus inside iTop. Provides a greater flexibility than * iApplicationUIExtension::EnumAllowedActions. diff --git a/application/cmdbabstract.class.inc.php b/application/cmdbabstract.class.inc.php index 97de38f255..62eac5b4de 100644 --- a/application/cmdbabstract.class.inc.php +++ b/application/cmdbabstract.class.inc.php @@ -4542,21 +4542,6 @@ public function DBInsertNoReload() return $res; } - protected function PostInsertActions(): void - { - parent::PostInsertActions(); - - // Invoke extensions after insertion (the object must exist, have an id, etc.) - /** @var \iApplicationObjectExtension $oExtensionInstance */ - foreach (MetaModel::EnumPlugins(iApplicationObjectExtension::class) as $oExtensionInstance) { - $sExtensionClass = get_class($oExtensionInstance); - $this->LogCRUDDebug(__METHOD__, "Calling $sExtensionClass::OnDBInsert()"); - $oKPI = new ExecutionKPI(); - $oExtensionInstance->OnDBInsert($this, self::GetCurrentChange()); - $oKPI->ComputeStatsForExtension($oExtensionInstance, 'OnDBInsert'); - } - } - /** * @inheritdoc * Attaches InlineImages to the current object @@ -4589,21 +4574,6 @@ public function DBUpdate() return $res; } - protected function PostUpdateActions(array $aChanges): void - { - parent::PostUpdateActions($aChanges); - - // Invoke extensions after the update (could be before) - /** @var \iApplicationObjectExtension $oExtensionInstance */ - foreach (MetaModel::EnumPlugins(iApplicationObjectExtension::class) as $oExtensionInstance) { - $sExtensionClass = get_class($oExtensionInstance); - $this->LogCRUDDebug(__METHOD__, "Calling $sExtensionClass::OnDBUpdate()"); - $oKPI = new ExecutionKPI(); - $oExtensionInstance->OnDBUpdate($this, self::GetCurrentChange()); - $oKPI->ComputeStatsForExtension($oExtensionInstance, 'OnDBUpdate'); - } - } - /** * @param string $sMessageIdPrefix * @@ -4639,21 +4609,6 @@ public function DBDelete(&$oDeletionPlan = null) return $oDeletionPlan; } - final protected function PreDeleteActions(): void - { - /** @var \iApplicationObjectExtension $oExtensionInstance */ - foreach(MetaModel::EnumPlugins('iApplicationObjectExtension') as $oExtensionInstance) - { - $sExtensionClass = get_class($oExtensionInstance); - $this->LogCRUDDebug(__METHOD__, "Calling $sExtensionClass::OnDBDelete()"); - $oKPI = new ExecutionKPI(); - $oExtensionInstance->OnDBDelete($this, self::GetCurrentChange()); - $oKPI->ComputeStatsForExtension($oExtensionInstance, 'OnDBDelete'); - } - - parent::PreDeleteActions(); - } - final protected function PostDeleteActions(): void { parent::PostDeleteActions(); @@ -4666,24 +4621,6 @@ public function IsModified() return true; } - // Plugins - // - /** @var \iApplicationObjectExtension $oExtensionInstance */ - foreach(MetaModel::EnumPlugins('iApplicationObjectExtension') as $oExtensionInstance) - { - $sExtensionClass = get_class($oExtensionInstance); - $this->LogCRUDDebug(__METHOD__, "Calling $sExtensionClass::OnIsModified()"); - $oKPI = new ExecutionKPI(); - $bIsModified = $oExtensionInstance->OnIsModified($this); - $oKPI->ComputeStatsForExtension($oExtensionInstance, 'OnIsModified'); - if ($bIsModified) { - $this->LogCRUDDebug(__METHOD__, "Calling $sExtensionClass::OnIsModified() -> true"); - return true; - } else { - $this->LogCRUDDebug(__METHOD__, "Calling $sExtensionClass::OnIsModified() -> false"); - } - } - return false; } @@ -4698,7 +4635,7 @@ public function AllowWrite($bAllow = true) } /** - * Whether to bypass the checks of user rights when writing this object, could be used in {@link \iApplicationObjectExtension::OnCheckToWrite()} + * Whether to bypass the checks of user rights when writing this object * * @return bool */ @@ -4727,22 +4664,6 @@ public function DoCheckToWrite() { parent::DoCheckToWrite(); - // Plugins - // - /** @var \iApplicationObjectExtension $oExtensionInstance */ - foreach(MetaModel::EnumPlugins('iApplicationObjectExtension') as $oExtensionInstance) - { - $sExtensionClass = get_class($oExtensionInstance); - $this->LogCRUDDebug(__METHOD__, "Calling $sExtensionClass::OnCheckToWrite()"); - $oKPI = new ExecutionKPI(); - $aNewIssues = $oExtensionInstance->OnCheckToWrite($this); - $oKPI->ComputeStatsForExtension($oExtensionInstance, 'OnCheckToWrite'); - if (is_array($aNewIssues) && (count($aNewIssues) > 0)) // Some extensions return null instead of an empty array - { - $this->m_aCheckIssues = array_merge($this->m_aCheckIssues, $aNewIssues); - } - } - // User rights // if (!$this->bAllowWrite) @@ -4779,22 +4700,6 @@ protected function DoCheckToDelete(&$oDeletionPlan) { parent::DoCheckToDelete($oDeletionPlan); - // Plugins - // - /** @var \iApplicationObjectExtension $oExtensionInstance */ - foreach(MetaModel::EnumPlugins('iApplicationObjectExtension') as $oExtensionInstance) - { - $sExtensionClass = get_class($oExtensionInstance); - $this->LogCRUDDebug(__METHOD__, "Calling $sExtensionClass::OnCheckToDelete()"); - $oKPI = new ExecutionKPI(); - $aNewIssues = $oExtensionInstance->OnCheckToDelete($this); - $oKPI->ComputeStatsForExtension($oExtensionInstance, 'OnCheckToDelete'); - if (is_array($aNewIssues) && count($aNewIssues) > 0) - { - $this->m_aDeleteIssues = array_merge($this->m_aDeleteIssues, $aNewIssues); - } - } - // User rights // if (! $this->bAllowDelete) diff --git a/core/metamodel.class.php b/core/metamodel.class.php index b48835f227..5560b8ea52 100644 --- a/core/metamodel.class.php +++ b/core/metamodel.class.php @@ -7709,7 +7709,6 @@ public static function InitExtensions() 'iLoginUIExtension', 'iPreferencesExtension', 'iApplicationUIExtension', - 'iApplicationObjectExtension', 'iPopupMenuExtension', 'iPageUIBlockExtension', 'iBackofficeLinkedScriptsExtension', diff --git a/datamodels/2.x/itop-attachments/main.itop-attachments.php b/datamodels/2.x/itop-attachments/main.itop-attachments.php index fedbcd941b..3414170e2a 100644 --- a/datamodels/2.x/itop-attachments/main.itop-attachments.php +++ b/datamodels/2.x/itop-attachments/main.itop-attachments.php @@ -5,15 +5,16 @@ */ use Combodo\iTop\Application\WebPage\WebPage; +use Combodo\iTop\Service\Events\EventData; +use Combodo\iTop\Service\Events\EventService; +use Combodo\iTop\Service\Events\iEventServiceSetup; -class AttachmentPlugIn implements iApplicationUIExtension, iApplicationObjectExtension +class AttachmentPlugIn implements iApplicationUIExtension, iEventServiceSetup { const ENUM_GUI_ALL = 'all'; const ENUM_GUI_BACKOFFICE = 'backoffice'; const ENUM_GUI_PORTALS = 'portals'; - protected static $m_bIsModified = false; - public function OnDisplayProperties($oObject, WebPage $oPage, $bEditMode = false) { if ($this->GetAttachmentsPosition() == 'properties') @@ -158,45 +159,27 @@ public function EnumAllowedActions(DBObjectSet $oSet) return array(); } - public function OnIsModified($oObject) - { - return self::$m_bIsModified; - } - - public function OnCheckToWrite($oObject) - { - return array(); - } - - public function OnCheckToDelete($oObject) + public function RegisterEventsAndListeners() : void { - return array(); + EventService::RegisterListener(EVENT_DB_AFTER_WRITE, [$this, 'OnDBAfterWrite']); + EventService::RegisterListener(EVENT_DB_AFTER_DELETE, [$this, 'OnDBAfterDelete']); } - public function OnDBUpdate($oObject, $oChange = null) + public function OnDBAfterWrite(EventData $oEventData) { - if ($this->IsTargetObject($oObject)) - { - // Get all current attachments - $oSearch = DBObjectSearch::FromOQL("SELECT Attachment WHERE item_class = :class AND item_id = :item_id"); - $oSet = new DBObjectSet($oSearch, array(), array('class' => get_class($oObject), 'item_id' => $oObject->GetKey())); - while ($oAttachment = $oSet->Fetch()) - { - $oAttachment->SetItem($oObject, true /*updateonchange*/); - } - } - } + $oObject = $oEventData->Get('object'); + $oChange = $oEventData->Get('changes'); - public function OnDBInsert($oObject, $oChange = null) - { if ($this->IsTargetObject($oObject)) { self::UpdateAttachments($oObject, $oChange); } } - public function OnDBDelete($oObject, $oChange = null) + public function OnDBAfterDelete(EventData $oEventData) { + $oObject = $oEventData->Get('object'); + if ($this->IsTargetObject($oObject)) { $oSearch = DBObjectSearch::FromOQL("SELECT Attachment WHERE item_class = :class AND item_id = :item_id"); @@ -305,8 +288,6 @@ public function DisplayAttachments(DBObject $oObject, WebPage $oPage, $bEditMode */ protected static function UpdateAttachments($oObject, $oChange = null) { - self::$m_bIsModified = false; - if (utils::ReadParam('attachment_plugin', 'not-in-form') == 'not-in-form') { // Workaround to an issue in iTop < 2.0 @@ -365,7 +346,6 @@ protected static function UpdateAttachments($oObject, $oChange = null) { self::RecordHistory($oChange, $oObject, $oChangeOp); } - self::$m_bIsModified = true; } } } @@ -648,6 +628,8 @@ public static function IsReadonlyState(DBObject $oObject, $sState, $sGUI = self: return $bReadonly; } + + } /** diff --git a/lib/composer/autoload_classmap.php b/lib/composer/autoload_classmap.php index eccb877e48..5060546ef3 100644 --- a/lib/composer/autoload_classmap.php +++ b/lib/composer/autoload_classmap.php @@ -6,7 +6,6 @@ $baseDir = dirname($vendorDir); return array( - 'AbstractApplicationObjectExtension' => $baseDir . '/application/applicationextension.inc.php', 'AbstractApplicationUIExtension' => $baseDir . '/application/applicationextension.inc.php', 'AbstractLoginFSMExtension' => $baseDir . '/application/applicationextension.inc.php', 'AbstractPageUIBlockExtension' => $baseDir . '/application/applicationextension.inc.php', @@ -3185,7 +3184,6 @@ 'appUserPreferences' => $baseDir . '/application/user.preferences.class.inc.php', 'cmdbAbstractObject' => $baseDir . '/application/cmdbabstract.class.inc.php', 'cmdbDataGenerator' => $baseDir . '/core/data.generator.class.inc.php', - 'iApplicationObjectExtension' => $baseDir . '/application/applicationextension.inc.php', 'iApplicationUIExtension' => $baseDir . '/application/applicationextension.inc.php', 'iAttributeNoGroupBy' => $baseDir . '/core/attributedef.class.inc.php', 'iBackgroundProcess' => $baseDir . '/core/backgroundprocess.inc.php', diff --git a/lib/composer/autoload_static.php b/lib/composer/autoload_static.php index 2d9aa046ed..6f05aa431f 100644 --- a/lib/composer/autoload_static.php +++ b/lib/composer/autoload_static.php @@ -384,7 +384,6 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f ); public static $classMap = array ( - 'AbstractApplicationObjectExtension' => __DIR__ . '/../..' . '/application/applicationextension.inc.php', 'AbstractApplicationUIExtension' => __DIR__ . '/../..' . '/application/applicationextension.inc.php', 'AbstractLoginFSMExtension' => __DIR__ . '/../..' . '/application/applicationextension.inc.php', 'AbstractPageUIBlockExtension' => __DIR__ . '/../..' . '/application/applicationextension.inc.php', @@ -3563,7 +3562,6 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'appUserPreferences' => __DIR__ . '/../..' . '/application/user.preferences.class.inc.php', 'cmdbAbstractObject' => __DIR__ . '/../..' . '/application/cmdbabstract.class.inc.php', 'cmdbDataGenerator' => __DIR__ . '/../..' . '/core/data.generator.class.inc.php', - 'iApplicationObjectExtension' => __DIR__ . '/../..' . '/application/applicationextension.inc.php', 'iApplicationUIExtension' => __DIR__ . '/../..' . '/application/applicationextension.inc.php', 'iAttributeNoGroupBy' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', 'iBackgroundProcess' => __DIR__ . '/../..' . '/core/backgroundprocess.inc.php', diff --git a/lib/composer/installed.php b/lib/composer/installed.php index 0fa1665fba..3cbeb89498 100644 --- a/lib/composer/installed.php +++ b/lib/composer/installed.php @@ -3,7 +3,7 @@ 'name' => 'combodo/itop', 'pretty_version' => 'dev-develop', 'version' => 'dev-develop', - 'reference' => '5b9e0a1d4f4751778386710eb52a1326d3c29423', + 'reference' => '965c9dba1435ed8605dc3d05f6021e77654137c9', 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), @@ -22,7 +22,7 @@ 'combodo/itop' => array( 'pretty_version' => 'dev-develop', 'version' => 'dev-develop', - 'reference' => '5b9e0a1d4f4751778386710eb52a1326d3c29423', + 'reference' => '965c9dba1435ed8605dc3d05f6021e77654137c9', 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), diff --git a/tests/php-unit-tests/unitary-tests/application/ApplicationObjectExtensionTest.php b/tests/php-unit-tests/unitary-tests/application/ApplicationObjectExtensionTest.php deleted file mode 100644 index 23f952343a..0000000000 --- a/tests/php-unit-tests/unitary-tests/application/ApplicationObjectExtensionTest.php +++ /dev/null @@ -1,103 +0,0 @@ -RequireOnceUnitTestFile('iApplicationObjectExtension/MockApplicationObjectExtensionForTest1.php'); - $this->ResetApplicationObjectExtensions(); - // Count all the calls to this object - MockApplicationObjectExtensionForTest1::SetCallBack([ApplicationObjectExtensionTest::class, 'IncrementCallCount']); - } - - public function tearDown(): void - { - MockApplicationObjectExtensionForTest1::SetModifications('Person', 'name', 0); - MockApplicationObjectExtensionForTest1::SetCallBack(null); - parent::tearDown(); - } - - public static function IncrementCallCount(string $sOrigin) - { - self::$aCalls[$sOrigin] = (self::$aCalls[$sOrigin] ?? 0) + 1; - self::$iCalls++; - } - - public static function ResetCallCount() - { - self::$aCalls = []; - self::$iCalls = 0; - } - - public function testExtensionCalled() - { - // Check that extension is called - $oPerson = $this->CreatePerson(1); - $oPerson->Set('first_name', 'testUpdateReentranceProtection'); - MockApplicationObjectExtensionForTest1::SetModifications('Person', 'name', 1); - self::ResetCallCount(); - $oPerson->DBUpdate(); - // Called twice, the first call will provoke the DBUpdate and call again the object extension - $this->assertEquals(2, self::$iCalls); - } - - public function testUpdateReentranceProtection() - { - $oPerson = $this->CreatePerson(1); - - // Check that loop limit is 10 - $i = 15; - self::ResetCallCount(); - MockApplicationObjectExtensionForTest1::SetModifications('Person', 'name', $i); - $oPerson->Set('first_name', 'testUpdateReentranceProtection'); - $oPerson->DBUpdate(); - $this->assertEquals(10, self::$iCalls); - } - - public function testModificationsOnUpdate() - { - $oPerson = $this->CreatePerson(1); - $oPerson->Set('first_name', 'testUpdateReentranceProtection'); - - self::ResetCallCount(); - MockApplicationObjectExtensionForTest1::SetModifications('Person', 'name', 1); - $oPerson->DBUpdate(); - $this->assertEquals(2, self::$iCalls); - } - - public function testModificationsOnInsert() - { - self::ResetCallCount(); - MockApplicationObjectExtensionForTest1::SetModifications('Person', 'name', 1); - $oPerson = $this->CreatePerson(1); - $this->assertEquals(2, self::$iCalls); - } - - - public function testModificationsOnInsertWith2Extensions() - { - self::ResetCallCount(); - $this->RequireOnceUnitTestFile('iApplicationObjectExtension/MockApplicationObjectExtensionForTest2.php'); - $this->ResetApplicationObjectExtensions(); - // Count all the calls to this object - MockApplicationObjectExtensionForTest2::SetCallBack([ApplicationObjectExtensionTest::class, 'IncrementCallCount']); - - MockApplicationObjectExtensionForTest1::SetModifications('Person', 'name', 2); - MockApplicationObjectExtensionForTest2::SetModifications('Person', 'first_name', 2); - $oPerson = $this->CreatePerson(1); - $this->assertEquals(6, self::$iCalls); - } - -} \ No newline at end of file diff --git a/tests/php-unit-tests/unitary-tests/application/applicationextension/ApplicationExtensionTest.php b/tests/php-unit-tests/unitary-tests/application/applicationextension/ApplicationExtensionTest.php index 50cd21beef..e43244c0db 100644 --- a/tests/php-unit-tests/unitary-tests/application/applicationextension/ApplicationExtensionTest.php +++ b/tests/php-unit-tests/unitary-tests/application/applicationextension/ApplicationExtensionTest.php @@ -78,10 +78,6 @@ public function ExtensionAPIRegisteredAndCalledProvider(): array \iApplicationUIExtension::class, static::ENUM_API_CALL_METHOD_ENUMPLUGINS, ], - \iApplicationObjectExtension::class => [ - \iApplicationObjectExtension::class, - static::ENUM_API_CALL_METHOD_ENUMPLUGINS, - ], \iPopupMenuExtension::class => [ \iPopupMenuExtension::class, static::ENUM_API_CALL_METHOD_ENUMPLUGINS, diff --git a/tests/php-unit-tests/unitary-tests/application/applicationextension/Delta/application-extension-usages-in-snippets.xml b/tests/php-unit-tests/unitary-tests/application/applicationextension/Delta/application-extension-usages-in-snippets.xml index 77d5f10b3b..5997277c5d 100644 --- a/tests/php-unit-tests/unitary-tests/application/applicationextension/Delta/application-extension-usages-in-snippets.xml +++ b/tests/php-unit-tests/unitary-tests/application/applicationextension/Delta/application-extension-usages-in-snippets.xml @@ -66,16 +66,6 @@ class ExampleFor_iPreferencesExtension extends \AbstractPreferencesExtension 0 - - - core - 0 - ListPreviousValuesForUpdatedAttributes(); - $sPreviousValues = print_r($aPreviousValues, true); - - IssueLog::Info(__METHOD__." received previous values:\n$sPreviousValues"); - - if (static::$iCountModify > 0) { - static::$iCountModify--; - $oObject->Set(static::$sAttCodeToModify, 'Value_'.rand()); - $oObject->DBUpdate(); - } - } - - public function OnDBInsert($oObject, $oChange = null) - { - if (get_class($oObject) !== static::$sClass) { - return; - } - - if (!is_null(static::$callBack)) { - call_user_func(static::$callBack, 'OnDBInsert'); - } - - if (static::$iCountModify > 0) { - static::$iCountModify--; - $oObject->Set(static::$sAttCodeToModify, 'Value_'.rand()); - $oObject->DBUpdate(); - } - } -} \ No newline at end of file diff --git a/tests/php-unit-tests/unitary-tests/application/iApplicationObjectExtension/MockApplicationObjectExtensionForTest2.php b/tests/php-unit-tests/unitary-tests/application/iApplicationObjectExtension/MockApplicationObjectExtensionForTest2.php deleted file mode 100644 index 4168c6798d..0000000000 --- a/tests/php-unit-tests/unitary-tests/application/iApplicationObjectExtension/MockApplicationObjectExtensionForTest2.php +++ /dev/null @@ -1,75 +0,0 @@ -ListPreviousValuesForUpdatedAttributes(); - $sPreviousValues = print_r($aPreviousValues, true); - - IssueLog::Info(__METHOD__." received previous values:\n$sPreviousValues"); - - if (static::$iCountModify > 0) { - static::$iCountModify--; - $oObject->Set(static::$sAttCodeToModify, 'Value_'.rand()); - $oObject->DBUpdate(); - } - } - - public function OnDBInsert($oObject, $oChange = null) - { - if (get_class($oObject) !== static::$sClass) { - return; - } - - if (!is_null(static::$callBack)) { - call_user_func(static::$callBack, 'OnDBInsert'); - } - - if (static::$iCountModify > 0) { - static::$iCountModify--; - $oObject->Set(static::$sAttCodeToModify, 'Value_'.rand()); - $oObject->DBUpdate(); - } - } -} \ No newline at end of file From ae9d509d5934c218e2622c183e633f854f7b8c59 Mon Sep 17 00:00:00 2001 From: Benjamin Dalsass Date: Wed, 27 Aug 2025 09:19:00 +0200 Subject: [PATCH 2/5] =?UTF-8?q?N=C2=B08210=20-=20Remove=20iApplicationObje?= =?UTF-8?q?ctExtension=20-=20add=20ability=20to=20mark=20an=20object=20as?= =?UTF-8?q?=20modified?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- application/cmdbabstract.class.inc.php | 24 ++++++++++++++++++- .../main.itop-attachments.php | 2 ++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/application/cmdbabstract.class.inc.php b/application/cmdbabstract.class.inc.php index 62eac5b4de..7ca274bac9 100644 --- a/application/cmdbabstract.class.inc.php +++ b/application/cmdbabstract.class.inc.php @@ -214,6 +214,15 @@ abstract class cmdbAbstractObject extends CMDBObject implements iDisplay */ protected static bool $bBlockEventDBLinksChanged = false; + /** + * If set to true, the object is considered as modified, whatever the actual state is. + * This is used when an object is modified indirectly (eg. through a linked set) + * + * @var bool + * + * @since 3.3.0 N°8210 - Remove iApplicationObjectExtension + */ + private bool $bIsMarkedAsModified = false; /** * Constructor from a row of data (as a hash 'attcode' => value) @@ -4621,7 +4630,20 @@ public function IsModified() return true; } - return false; + return $this->bIsMarkedAsModified; + } + + /** + * Override the default modification state of the object. + * + * The object is considered as modified, whatever the actual state is. + * This is used when an object is modified indirectly (eg. through a linked set) + * + * @return void + */ + public function MarkObjectAsModified(): void + { + $this->bIsMarkedAsModified = true; } /** diff --git a/datamodels/2.x/itop-attachments/main.itop-attachments.php b/datamodels/2.x/itop-attachments/main.itop-attachments.php index 3414170e2a..ef948c6653 100644 --- a/datamodels/2.x/itop-attachments/main.itop-attachments.php +++ b/datamodels/2.x/itop-attachments/main.itop-attachments.php @@ -346,6 +346,8 @@ protected static function UpdateAttachments($oObject, $oChange = null) { self::RecordHistory($oChange, $oObject, $oChangeOp); } + + $oObject->MarkObjectAsModified(); } } } From 22356e11525c30f3985047413db7c3663813b8ce Mon Sep 17 00:00:00 2001 From: Benjamin Dalsass Date: Wed, 3 Sep 2025 15:21:37 +0200 Subject: [PATCH 3/5] Suppress documentation generator from project in favor of the online version --- .../2.x/itop-attachments/main.itop-attachments.php | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/datamodels/2.x/itop-attachments/main.itop-attachments.php b/datamodels/2.x/itop-attachments/main.itop-attachments.php index ef948c6653..3a13e34d4d 100644 --- a/datamodels/2.x/itop-attachments/main.itop-attachments.php +++ b/datamodels/2.x/itop-attachments/main.itop-attachments.php @@ -169,10 +169,22 @@ public function OnDBAfterWrite(EventData $oEventData) { $oObject = $oEventData->Get('object'); $oChange = $oEventData->Get('changes'); + $bIsNew = $oEventData->Get('is_new'); if ($this->IsTargetObject($oObject)) { - self::UpdateAttachments($oObject, $oChange); + if($bIsNew){ + self::UpdateAttachments($oObject, $oChange); + } + else{ + // Get all current attachments + $oSearch = DBObjectSearch::FromOQL("SELECT Attachment WHERE item_class = :class AND item_id = :item_id"); + $oSet = new DBObjectSet($oSearch, array(), array('class' => get_class($oObject), 'item_id' => $oObject->GetKey())); + while ($oAttachment = $oSet->Fetch()) + { + $oAttachment->SetItem($oObject, true /*updateonchange*/); + } + } } } From cdbbd18a4a220da82580b14b0f696c5c2f2e3b85 Mon Sep 17 00:00:00 2001 From: Benjamin Dalsass Date: Wed, 3 Sep 2025 16:03:37 +0200 Subject: [PATCH 4/5] - Add CMDBChange object to event data (cmdb_change) for [EVENT_DB_AFTER_DELETE, EVENT_DB_AFTER_WRITE] - Update attachments changes handling --- application/cmdbabstract.class.inc.php | 4 ++-- .../itop-attachments/main.itop-attachments.php | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/application/cmdbabstract.class.inc.php b/application/cmdbabstract.class.inc.php index 7ca274bac9..7381a045a2 100644 --- a/application/cmdbabstract.class.inc.php +++ b/application/cmdbabstract.class.inc.php @@ -5736,7 +5736,7 @@ final protected function FireEventAfterWrite(array $aChanges, bool $bIsNew, ?str { $this->NotifyAttachedObjectsOnLinkClassModification(); $this->RemoveObjectAwaitingEventDbLinksChanged(get_class($this), $this->GetKey()); - $this->FireEvent(EVENT_DB_AFTER_WRITE, ['is_new' => $bIsNew, 'changes' => $aChanges, 'stimulus_applied' => $sStimulusBeingApplied]); + $this->FireEvent(EVENT_DB_AFTER_WRITE, ['is_new' => $bIsNew, 'changes' => $aChanges, 'stimulus_applied' => $sStimulusBeingApplied, 'cmdb_change' => self::GetCurrentChange()]); } ////////////// @@ -5774,7 +5774,7 @@ final protected function FireEventAboutToDelete(): void final protected function FireEventAfterDelete(): void { $this->NotifyAttachedObjectsOnLinkClassModification(); - $this->FireEvent(EVENT_DB_AFTER_DELETE); + $this->FireEvent(EVENT_DB_AFTER_DELETE, ['cmdb_change' => self::GetCurrentChange()]); } /** diff --git a/datamodels/2.x/itop-attachments/main.itop-attachments.php b/datamodels/2.x/itop-attachments/main.itop-attachments.php index 3a13e34d4d..d7ee5d17d2 100644 --- a/datamodels/2.x/itop-attachments/main.itop-attachments.php +++ b/datamodels/2.x/itop-attachments/main.itop-attachments.php @@ -168,13 +168,13 @@ public function RegisterEventsAndListeners() : void public function OnDBAfterWrite(EventData $oEventData) { $oObject = $oEventData->Get('object'); - $oChange = $oEventData->Get('changes'); + $oCMDBChange = $oEventData->Get('cmdb_change'); $bIsNew = $oEventData->Get('is_new'); if ($this->IsTargetObject($oObject)) { if($bIsNew){ - self::UpdateAttachments($oObject, $oChange); + self::UpdateAttachments($oObject, $oCMDBChange); } else{ // Get all current attachments @@ -286,7 +286,7 @@ public function DisplayAttachments(DBObject $oObject, WebPage $oPage, $bEditMode * @see ObjectFormManager::FinalizeAttachments() for the portal version * * @param $oObject - * @param $oChange + * @param $oCMDBChange * * @return void * @throws \ArchivedObjectException @@ -298,7 +298,7 @@ public function DisplayAttachments(DBObject $oObject, WebPage $oPage, $bEditMode * @throws \MySQLHasGoneAwayException * @throws \OQLException */ - protected static function UpdateAttachments($oObject, $oChange = null) + protected static function UpdateAttachments($oObject, $oCMDBChange = null) { if (utils::ReadParam('attachment_plugin', 'not-in-form') == 'not-in-form') { @@ -356,7 +356,7 @@ protected static function UpdateAttachments($oObject, $oChange = null) { foreach ($aActions as $oChangeOp) { - self::RecordHistory($oChange, $oObject, $oChangeOp); + self::RecordHistory($oCMDBChange, $oObject, $oChangeOp); } $oObject->MarkObjectAsModified(); @@ -550,11 +550,11 @@ public static function GetFileIcon($sFileName) } ///////////////////////////////////////////////////////////////////////// - private static function RecordHistory($oChange, $oTargetObject, $oMyChangeOp) + private static function RecordHistory($oCMDBChange, $oTargetObject, $oMyChangeOp) { - if (!is_null($oChange)) + if (!is_null($oCMDBChange)) { - $oMyChangeOp->Set("change", $oChange->GetKey()); + $oMyChangeOp->Set("change", $oCMDBChange->GetKey()); } $oMyChangeOp->Set("objclass", get_class($oTargetObject)); $oMyChangeOp->Set("objkey", $oTargetObject->GetKey()); From cf3906b47e187f96ee9e7e680f8f094ad327bca5 Mon Sep 17 00:00:00 2001 From: Benjamin Dalsass Date: Fri, 5 Sep 2025 08:40:05 +0200 Subject: [PATCH 5/5] - Remove AbstractApplicationObjectExtension and IApplicationObjectExtension due to split file update --- application/applicationextension.inc.php | 6 - .../AbstractApplicationObjectExtension.php | 58 --------- .../iApplicationObjectExtension.php | 111 ------------------ 3 files changed, 175 deletions(-) delete mode 100644 application/applicationextension/backoffice/AbstractApplicationObjectExtension.php delete mode 100644 application/applicationextension/backoffice/iApplicationObjectExtension.php diff --git a/application/applicationextension.inc.php b/application/applicationextension.inc.php index ea265766e2..76737d8117 100644 --- a/application/applicationextension.inc.php +++ b/application/applicationextension.inc.php @@ -57,12 +57,6 @@ require_once(APPROOT.'application/applicationextension/backoffice/URLButtonItem.php'); require_once(APPROOT.'application/applicationextension/backoffice/URLPopupMenuItem.php'); -//deprecated class and interface -require_once(APPROOT.'application/applicationextension/backoffice/iApplicationObjectExtension.php'); -require_once(APPROOT.'application/applicationextension/backoffice/AbstractApplicationObjectExtension.php'); - - - require_once(APPROOT.'application/applicationextension/iBackupExtraFilesExtension.php'); require_once(APPROOT.'application/applicationextension/iKPILoggerExtension.php'); require_once(APPROOT.'application/applicationextension/iModuleExtension.php'); diff --git a/application/applicationextension/backoffice/AbstractApplicationObjectExtension.php b/application/applicationextension/backoffice/AbstractApplicationObjectExtension.php deleted file mode 100644 index a358a0c322..0000000000 --- a/application/applicationextension/backoffice/AbstractApplicationObjectExtension.php +++ /dev/null @@ -1,58 +0,0 @@ -after the object has been written to the - * database. - * - * Useful methods you can call on $oObject : - * - * * {@see DBObject::ListPreviousValuesForUpdatedAttributes()} : list of changed attributes and their values before the change - * * {@see DBObject::Get()} : for a given attribute the new value that was persisted - * - * @param \cmdbAbstractObject $oObject The target object - * @param CMDBChange|null $oChange A change context. Since 2.0 it is fine to ignore it, as the framework does maintain this information - * once for all the changes made within the current page - * - * @return void - * - * @deprecated 3.1.0 N°4756 Use EVENT_DB_AFTER_WRITE event instead - * @api - * @since 2.7.0 N°2293 can access object changes by calling {@see DBObject::ListPreviousValuesForUpdatedAttributes()} on $oObject - */ - public function OnDBUpdate($oObject, $oChange = null); - - /** - * Invoked when an object is created into the database - * - * The method is called right after the object has been written to the database. - * - * @param \cmdbAbstractObject $oObject The target object - * @param CMDBChange|null $oChange A change context. Since 2.0 it is fine to ignore it, as the framework does maintain this information - * once for all the changes made within the current page - * - * @return void - * @deprecated 3.1.0 N°4756 Use EVENT_DB_AFTER_WRITE event instead - * @api - */ - public function OnDBInsert($oObject, $oChange = null); - - /** - * Invoked when an object is deleted from the database - * - * The method is called right before the object will be deleted from the database. - * - * @param \cmdbAbstractObject $oObject The target object - * @param CMDBChange|null $oChange A change context. Since 2.0 it is fine to ignore it, as the framework does maintain this information - * once for all the changes made within the current page - * - * @return void - * @deprecated 3.1.0 N°4756 Use EVENT_DB_AFTER_DELETE event instead - * @api - */ - public function OnDBDelete($oObject, $oChange = null); -} \ No newline at end of file