mirror of
https://github.com/Combodo/iTop.git
synced 2026-04-21 09:38:48 +02:00
N°5909 - Fix iApplicationExtension not called when attachment is added
This commit is contained in:
@@ -523,7 +523,6 @@ abstract class CMDBObject extends DBObject
|
||||
public function DBUpdate()
|
||||
{
|
||||
if (count($this->ListChanges()) === 0) {
|
||||
$this->InitPreviousValuesForUpdatedAttributes();
|
||||
return $this->GetKey();
|
||||
}
|
||||
return parent::DBUpdate(); // TODO: Change the autogenerated stub
|
||||
|
||||
@@ -2927,52 +2927,7 @@ abstract class MetaModel
|
||||
}
|
||||
|
||||
self::$m_sTablePrefix = $sTablePrefix;
|
||||
|
||||
// Build the list of available extensions
|
||||
//
|
||||
$aInterfaces = [
|
||||
'iApplicationUIExtension',
|
||||
'iPreferencesExtension',
|
||||
'iApplicationObjectExtension',
|
||||
'iLoginFSMExtension',
|
||||
'iLoginUIExtension',
|
||||
'iLogoutExtension',
|
||||
'iQueryModifier',
|
||||
'iOnClassInitialization',
|
||||
'iPopupMenuExtension',
|
||||
'iPageUIExtension',
|
||||
'iPageUIBlockExtension',
|
||||
'iBackofficeLinkedScriptsExtension',
|
||||
'iBackofficeEarlyScriptExtension',
|
||||
'iBackofficeScriptExtension',
|
||||
'iBackofficeInitScriptExtension',
|
||||
'iBackofficeReadyScriptExtension',
|
||||
'iBackofficeLinkedStylesheetsExtension',
|
||||
'iBackofficeStyleExtension',
|
||||
'iBackofficeDictEntriesExtension',
|
||||
'iBackofficeDictEntriesPrefixesExtension',
|
||||
'iPortalUIExtension',
|
||||
'ModuleHandlerApiInterface',
|
||||
'iNewsroomProvider',
|
||||
'iModuleExtension',
|
||||
];
|
||||
foreach($aInterfaces as $sInterface)
|
||||
{
|
||||
self::$m_aExtensionClassNames[$sInterface] = array();
|
||||
}
|
||||
|
||||
foreach(get_declared_classes() as $sPHPClass)
|
||||
{
|
||||
$oRefClass = new ReflectionClass($sPHPClass);
|
||||
$oExtensionInstance = null;
|
||||
foreach($aInterfaces as $sInterface)
|
||||
{
|
||||
if ($oRefClass->implementsInterface($sInterface) && $oRefClass->isInstantiable())
|
||||
{
|
||||
self::$m_aExtensionClassNames[$sInterface][$sPHPClass] = $sPHPClass;
|
||||
}
|
||||
}
|
||||
}
|
||||
self::InitExtensions();
|
||||
|
||||
// Initialize the classes (declared attributes, etc.)
|
||||
//
|
||||
@@ -7642,6 +7597,56 @@ abstract class MetaModel
|
||||
unset(self::$m_aReentranceProtection[get_class($oObject)][$oObject->GetKey()]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* For test purpose
|
||||
* @throws \ReflectionException
|
||||
* @since 3.1.0
|
||||
*/
|
||||
public static function InitExtensions()
|
||||
{
|
||||
// Build the list of available extensions
|
||||
//
|
||||
$aInterfaces = [
|
||||
'iApplicationUIExtension',
|
||||
'iPreferencesExtension',
|
||||
'iApplicationObjectExtension',
|
||||
'iLoginFSMExtension',
|
||||
'iLoginUIExtension',
|
||||
'iLogoutExtension',
|
||||
'iQueryModifier',
|
||||
'iOnClassInitialization',
|
||||
'iPopupMenuExtension',
|
||||
'iPageUIExtension',
|
||||
'iPageUIBlockExtension',
|
||||
'iBackofficeLinkedScriptsExtension',
|
||||
'iBackofficeEarlyScriptExtension',
|
||||
'iBackofficeScriptExtension',
|
||||
'iBackofficeInitScriptExtension',
|
||||
'iBackofficeReadyScriptExtension',
|
||||
'iBackofficeLinkedStylesheetsExtension',
|
||||
'iBackofficeStyleExtension',
|
||||
'iBackofficeDictEntriesExtension',
|
||||
'iBackofficeDictEntriesPrefixesExtension',
|
||||
'iPortalUIExtension',
|
||||
'ModuleHandlerApiInterface',
|
||||
'iNewsroomProvider',
|
||||
'iModuleExtension',
|
||||
];
|
||||
foreach ($aInterfaces as $sInterface) {
|
||||
self::$m_aExtensionClassNames[$sInterface] = array();
|
||||
}
|
||||
|
||||
foreach (get_declared_classes() as $sPHPClass) {
|
||||
$oRefClass = new ReflectionClass($sPHPClass);
|
||||
$oExtensionInstance = null;
|
||||
foreach ($aInterfaces as $sInterface) {
|
||||
if ($oRefClass->implementsInterface($sInterface) && $oRefClass->isInstantiable()) {
|
||||
self::$m_aExtensionClassNames[$sInterface][$sPHPClass] = $sPHPClass;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -98,4 +98,14 @@ class PluginManager
|
||||
|
||||
return $oInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* For test purpose
|
||||
* @return void
|
||||
* @since 3.1.0
|
||||
*/
|
||||
protected static function ResetPlugins()
|
||||
{
|
||||
self::$m_aExtensionClasses = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2023 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @runTestsInSeparateProcesses
|
||||
* @preserveGlobalState disabled
|
||||
* @backupGlobals disabled
|
||||
*/
|
||||
class ApplicationObjectExtensionTest extends \Combodo\iTop\Test\UnitTest\ItopDataTestCase
|
||||
{
|
||||
const CREATE_TEST_ORG = true;
|
||||
|
||||
// Count the calls by name
|
||||
private static array $aCalls = [];
|
||||
private static int $iCalls = 0;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
require_once 'iApplicationObjectExtension/ObjectModifyExtension.php';
|
||||
|
||||
// Add ObjectModifyExtension to the plugin list
|
||||
$this->InvokeNonPublicStaticMethod(MetaModel::class, 'InitExtensions', []);
|
||||
// Instantiate the new object
|
||||
$this->InvokeNonPublicStaticMethod(PluginManager::class, 'ResetPlugins', []);
|
||||
ObjectModifyExtension::SetCallBack([ApplicationObjectExtensionTest::class, 'IncrementCallCount']);
|
||||
}
|
||||
|
||||
public function tearDown(): void
|
||||
{
|
||||
ObjectModifyExtension::SetModifications('Person', 'name', 0);
|
||||
ObjectModifyExtension::SetAlwaysChanged(false);
|
||||
ObjectModifyExtension::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 testUpdateReentranceProtection()
|
||||
{
|
||||
// Check that extension is called
|
||||
$oPerson = $this->CreatePerson(1);
|
||||
$oPerson->Set('first_name', 'testUpdateReentranceProtection');
|
||||
ObjectModifyExtension::SetModifications('Person', 'name', 1);
|
||||
self::ResetCallCount();
|
||||
$oPerson->DBUpdate();
|
||||
$this->assertEquals(1, self::$iCalls);
|
||||
|
||||
// Check that loop limit is 10
|
||||
$i = 15;
|
||||
self::ResetCallCount();
|
||||
ObjectModifyExtension::SetModifications('Person', 'name', $i);
|
||||
$oPerson->Set('first_name', 'testUpdateReentranceProtection');
|
||||
$oPerson->DBUpdate();
|
||||
$this->assertEquals(10, self::$iCalls);
|
||||
}
|
||||
|
||||
public function testModificationsLost()
|
||||
{
|
||||
self::ResetCallCount();
|
||||
$oPerson = $this->CreatePerson(1);
|
||||
$oPerson->Set('first_name', 'testUpdateReentranceProtection');
|
||||
|
||||
ObjectModifyExtension::SetModifications('Person', 'name', 1);
|
||||
ObjectModifyExtension::SetAlwaysChanged(true);
|
||||
$oPerson->DBUpdate();
|
||||
$this->assertEquals(1, self::$iCalls);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2023 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* Test object for AbstractApplicationObjectExtension API
|
||||
*/
|
||||
class ObjectModifyExtension extends AbstractApplicationObjectExtension
|
||||
{
|
||||
private static $iCountModify;
|
||||
private static $bAlwaysChanged;
|
||||
private static $sClass;
|
||||
private static $sAttCodeToModify;
|
||||
private static $callBack;
|
||||
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
public static function SetCallBack($callBack)
|
||||
{
|
||||
self::$callBack = $callBack;
|
||||
}
|
||||
|
||||
public static function SetModifications($sClass, $sAttCodeToModify, $iCountModify)
|
||||
{
|
||||
self::$sClass = $sClass;
|
||||
self::$sAttCodeToModify = $sAttCodeToModify;
|
||||
if (!MetaModel::IsValidClass($sClass) || !MetaModel::IsValidAttCode($sClass, $sAttCodeToModify)) {
|
||||
throw new Exception("Invalid class $sClass or attcode $sAttCodeToModify");
|
||||
}
|
||||
self::$iCountModify = $iCountModify;
|
||||
}
|
||||
|
||||
public static function SetAlwaysChanged($bAlwaysChanged)
|
||||
{
|
||||
self::$bAlwaysChanged = $bAlwaysChanged;
|
||||
}
|
||||
|
||||
public function OnDBUpdate($oObject, $oChange = null)
|
||||
{
|
||||
if (get_class($oObject) !== self::$sClass) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (self::$iCountModify > 0) {
|
||||
if (!empty($oObject->ListPreviousValuesForUpdatedAttributes())) {
|
||||
if (!is_null(self::$callBack)) {
|
||||
call_user_func(self::$callBack, 'OnDBUpdate');
|
||||
}
|
||||
self::$iCountModify--;
|
||||
$oObject->Set(self::$sAttCodeToModify, 'Value_'.rand());
|
||||
$oObject->DBUpdate();
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function OnIsModified($oObject)
|
||||
{
|
||||
return self::$bAlwaysChanged;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user