diff --git a/core/action.class.inc.php b/core/action.class.inc.php
index 27947a6987..4054e2107a 100644
--- a/core/action.class.inc.php
+++ b/core/action.class.inc.php
@@ -41,9 +41,10 @@ require_once(APPROOT.'/core/email.class.inc.php');
*/
abstract class Action extends cmdbAbstractObject
{
- /** @var $oCallingTrigger Trigger|null The trigger that called this action {@see DoExecute}
+ /**
+ * @var $oCallingTrigger Trigger|null The trigger that called this action {@see DoExecute}
* @since 3.2.0
- * */
+ */
protected ?Trigger $oCallingTrigger = null;
/**
diff --git a/core/datamodel.core.xml b/core/datamodel.core.xml
index fab9c25725..059a3d6273 100644
--- a/core/datamodel.core.xml
+++ b/core/datamodel.core.xml
@@ -132,7 +132,7 @@
96
256
256
- null
+
priority
@@ -253,7 +253,7 @@
false
public
Get('recipients'));
$oRecipientsSearch->AllowAllData();
@@ -262,15 +262,36 @@
while ($oRecipient = $oRecipientsSet->Fetch()) {
// Skip recipients that have no users
if (get_class($oRecipient) === Person::class && UserRights::GetUserFromPerson($oRecipient) === null) {
- continue;
- }
+ continue;
+ }
if (!\Combodo\iTop\Service\Notification\NotificationsService::GetInstance()->IsSubscribed($oTrigger, $this, $oRecipient)) {
- continue;
- }
+ continue;
+ }
+
+ if (array_key_exists('this->object()', $aContextArgs)) {
+ $iObjectId = $aContextArgs['this->object()']->GetKey();
+ $sObjectClass = get_class($aContextArgs['this->object()']);
+ } else {
+ $iObjectId = 0;
+ $sObjectClass = null;
+ }
+
$oEvent = new EventiTopNotification();
$oEvent->Set('title', MetaModel::ApplyParams($this->Get('title'), $aContextArgs));
$oEvent->Set('message', MetaModel::ApplyParams($this->Get('message'), $aContextArgs));
- $oIcon = !$this->Get('icon')->IsEmpty() ? $this->Get('icon') : MetaModel::GetAttributeDef('EventiTopNotification', 'icon')->MakeRealValue(Combodo\iTop\Application\Branding::GetCompactMainLogoAbsoluteUrl(), $oEvent);
+ // Compute icon
+ // - First check if one is defined on the action
+ if (false === $this->Get('icon')->IsEmpty()) {
+ $oIcon = $this->Get('icon');
+ }
+ // - Then, check if the action is for a DM object and if its class has an icon
+ elseif ($iObjectId > 0 && utils::IsNotNullOrEmptyString(MetaModel::GetClassIcon($sObjectClass, false))) {
+ $oIcon = MetaModel::GetAttributeDef(EventiTopNotification::class, 'icon')->MakeRealValue(MetaModel::GetClassIcon($sObjectClass, false), $oEvent);
+ }
+ // - Otherwise, fallback on the compact logo of the application
+ else {
+ $oIcon = MetaModel::GetAttributeDef(EventiTopNotification::class, 'icon')->MakeRealValue(\Combodo\iTop\Application\Branding::GetCompactMainLogoAbsoluteUrl(), $oEvent);
+ }
$oEvent->Set('icon', $oIcon);
$oEvent->Set('priority', $this->Get('priority'));
$oEvent->Set('contact_id', $oRecipient->GetKey());
@@ -281,7 +302,7 @@
$oEvent->Set('url', MetaModel::ApplyParams($this->Get('url'), $aContextArgs));
$oEvent->DBInsertNoReload();
- \Combodo\iTop\Service\Notification\NotificationsService::GetInstance()->RegisterSubscription($oTrigger, $this, $oRecipient);
+ \Combodo\iTop\Service\Notification\NotificationsService::GetInstance()->RegisterSubscription($oTrigger, $this, $oRecipient);
}
$this->SetNotificationLanguage($sPreviousLanguage, $aPreviousPluginProperties['language_code'] ?? null);
}
@@ -317,7 +338,7 @@
icon
true
- null
+
priority
diff --git a/datamodels/2.x/itop-structure/module.itop-structure.php b/datamodels/2.x/itop-structure/module.itop-structure.php
index e0743c13c9..66e8381f5e 100644
--- a/datamodels/2.x/itop-structure/module.itop-structure.php
+++ b/datamodels/2.x/itop-structure/module.itop-structure.php
@@ -73,7 +73,7 @@ if (!class_exists('StructureInstaller'))
SetupLog::Info("| Migrate ActionEmail language attribute values to its parent.");
$sTableToRead = MetaModel::DBGetTable('ActionEmail');
$sTableToSet = MetaModel::DBGetTable('ActionNotification');
- self::MoveColumnInDB($sTableToRead, 'language', $sTableToSet, 'language');
+ self::MoveColumnInDB($sTableToRead, 'language', $sTableToSet, 'language', true);
SetupLog::Info("| ActionEmail migration done.");
}
// If you want to migrate data from one format to another, do it here
diff --git a/sources/Controller/Newsroom/iTopNewsroomController.php b/sources/Controller/Newsroom/iTopNewsroomController.php
index fac160da6b..b32a85c24d 100644
--- a/sources/Controller/Newsroom/iTopNewsroomController.php
+++ b/sources/Controller/Newsroom/iTopNewsroomController.php
@@ -11,6 +11,7 @@ use Combodo\iTop\Service\Router\Router;
use CoreException;
use DBObjectSearch;
use DBObjectSet;
+use Dict;
use DisplayBlock;
use MetaModel;
use UserRights;
diff --git a/sources/Service/Notification/NotificationsService.php b/sources/Service/Notification/NotificationsService.php
index d0caf209f4..810e27b1ce 100644
--- a/sources/Service/Notification/NotificationsService.php
+++ b/sources/Service/Notification/NotificationsService.php
@@ -105,7 +105,7 @@ class NotificationsService {
// Check if the user is already subscribed to the action notification
$oSubscribedActionsNotificationsSet = NotificationsRepository::GetInstance()->SearchSubscriptionByTriggerContactAndAction($oTrigger->GetKey(), $oRecipient->GetKey(), $oActionNotification->GetKey());
if ($oSubscribedActionsNotificationsSet->Count() === 0) {
- return false;
+ return true;
}
// Return the subscribed status
diff --git a/tests/php-unit-tests/unitary-tests/application/LoginTest.php b/tests/php-unit-tests/unitary-tests/application/LoginTest.php
index 52b4b70c94..583d30d3d5 100644
--- a/tests/php-unit-tests/unitary-tests/application/LoginTest.php
+++ b/tests/php-unit-tests/unitary-tests/application/LoginTest.php
@@ -26,7 +26,7 @@ class LoginTest extends ItopDataTestCase {
@chmod($this->sConfigPath, 0770);
$oConfig->WriteToFile();
- @chmod($this->sConfigPath, 0440);
+ @chmod($this->sConfigPath, 0444);
}
protected function tearDown(): void {
@@ -34,7 +34,7 @@ class LoginTest extends ItopDataTestCase {
//put config back
@chmod($this->sConfigPath, 0770);
file_put_contents($this->sConfigPath, file_get_contents($this->sConfigTmpBackupFile));
- @chmod($this->sConfigPath, 0440);
+ @chmod($this->sConfigPath, 0444);
@unlink($this->sConfigTmpBackupFile);
}
parent::tearDown();
diff --git a/tests/php-unit-tests/unitary-tests/core/AttributeDefinitionTest.php b/tests/php-unit-tests/unitary-tests/core/AttributeDefinitionTest.php
index 122da9cbc4..b3dccfc544 100644
--- a/tests/php-unit-tests/unitary-tests/core/AttributeDefinitionTest.php
+++ b/tests/php-unit-tests/unitary-tests/core/AttributeDefinitionTest.php
@@ -58,7 +58,7 @@ class AttributeDefinitionTest extends ItopDataTestCase {
// Note: This is test is not great as we are datamodel dependent and don't have a class with all the attribute types
return [
'AttributeDateTime' => [
- Change::class,
+ UserRequest::class,
'start_date', // no default value on this field
<<Set('start_date', '2023-09-06 12:26:00');
diff --git a/tests/php-unit-tests/unitary-tests/core/iTopConfigParserTest.php b/tests/php-unit-tests/unitary-tests/core/iTopConfigParserTest.php
index e096c99816..741ae52d61 100644
--- a/tests/php-unit-tests/unitary-tests/core/iTopConfigParserTest.php
+++ b/tests/php-unit-tests/unitary-tests/core/iTopConfigParserTest.php
@@ -47,7 +47,7 @@ class iTopConfigParserTest extends ItopTestCase
@chmod($this->sConfigPath, 0770);
$bRenameResult = rename($this->tmpSavePath, $this->sConfigPath);
echo "Restored config file, result={$bRenameResult}";
- @chmod($this->sConfigPath, 0440);
+ @chmod($this->sConfigPath, 0444);
}
}
diff --git a/tests/php-unit-tests/unitary-tests/setup/DBBackupDataTest.php b/tests/php-unit-tests/unitary-tests/setup/DBBackupDataTest.php
index 129664c749..1952c2c84f 100644
--- a/tests/php-unit-tests/unitary-tests/setup/DBBackupDataTest.php
+++ b/tests/php-unit-tests/unitary-tests/setup/DBBackupDataTest.php
@@ -32,11 +32,14 @@ class DBBackupDataTest extends ItopDataTestCase
if ($bUnsafeFileException) {
$this->expectExceptionMessage("Backup: Aborting, resource '$sExtraFile'. Considered as UNSAFE because not inside the iTop directory.");
}
- $aFiles = $this->InvokeNonPublicMethod('DBBackup', 'PrepareFilesToBackup', $oBackup, [APPROOT . '/conf/production/config-itop.php', $sTmpDir, true]);
+ $aFiles = $this->InvokeNonPublicMethod('DBBackup', 'PrepareFilesToBackup', $oBackup, [APPROOT . '/conf/'.$this->GetTestEnvironment().'/config-itop.php', $sTmpDir, true]);
SetupUtils::rrmdir($sTmpDir);
$aExpectedFiles = [
$sTmpDir . '/config-itop.php',
];
+ if (file_exists(APPROOT.'/data/'.$this->GetTestEnvironment().'.delta.xml')) {
+ $aExpectedFiles[] = $sTmpDir . '/' . 'delta.xml';
+ }
foreach ($aExtraFiles as $sRelFile => $bExists) {
if ($bExists) {
$aExpectedFiles[] = $sTmpDir . '/' . $sRelFile;
@@ -47,13 +50,17 @@ class DBBackupDataTest extends ItopDataTestCase
foreach ($aExtraFiles as $sExtraFile => $bExists) {
if ($bExists) {
unlink(APPROOT . '/' . $sExtraFile);
+ $folderPath = dirname(APPROOT . '/' . $sExtraFile);
+ if (is_dir($folderPath) && count(glob($folderPath . '/*')) === 0) {
+ rmdir($folderPath);
+ }
}
}
}
sort($aFiles);
sort($aExpectedFiles);
- $this->assertEquals($aFiles, $aExpectedFiles);
+ $this->assertEquals($aExpectedFiles, $aFiles);
}
function prepareFilesToBackupProvider()
diff --git a/tests/php-unit-tests/unitary-tests/sources/SessionTracker/SessionHandlerTest.php b/tests/php-unit-tests/unitary-tests/sources/SessionTracker/SessionHandlerTest.php
index ac89a84216..b2ea7864de 100644
--- a/tests/php-unit-tests/unitary-tests/sources/SessionTracker/SessionHandlerTest.php
+++ b/tests/php-unit-tests/unitary-tests/sources/SessionTracker/SessionHandlerTest.php
@@ -161,7 +161,7 @@ class SessionHandlerTest extends ItopDataTestCase
$aJson = json_decode($sFirstContent, true);
$this->assertNotEquals(false, $aJson, 'Should return a valid json string, found: '.$sFirstContent);
$this->assertEquals($sUserId, $aJson['user_id'] ?? '', "Should report the login of the logged in user in [user_id]: $sFirstContent");
- $this->assertEquals(ContextTag::TAG_REST, $aJson['context'] ?? '', "Should report the context tag(s) in [context]: $sFirstContent");
+ $this->assertStringContainsString(ContextTag::TAG_REST, $aJson['context'] ?? '', "Should report the context tag(s) in [context]: $sFirstContent");
$this->assertIsInt($aJson['creation_time'] ?? '', "Should report the session start timestamp in [creation_time]: $sFirstContent");
$this->assertEquals('foo_login_mode', $aJson['login_mode'] ?? '', "Should report the current login mode in [login_mode]: $sFirstContent");
diff --git a/tests/php-unit-tests/unitary-tests/webservices/CliResetSessionTest.php b/tests/php-unit-tests/unitary-tests/webservices/CliResetSessionTest.php
index 612125035a..5e798d3f2d 100644
--- a/tests/php-unit-tests/unitary-tests/webservices/CliResetSessionTest.php
+++ b/tests/php-unit-tests/unitary-tests/webservices/CliResetSessionTest.php
@@ -55,7 +55,7 @@ class CliResetSessionTest extends ItopDataTestCase
@chmod($sConfigPath, 0770);
$oConfig = new Config($this->sConfigTmpBackupFile);
$oConfig->WriteToFile($sConfigPath);
- @chmod($sConfigPath, 0440);
+ @chmod($sConfigPath, 0444);
unlink($this->sConfigTmpBackupFile);
}
@@ -72,14 +72,14 @@ class CliResetSessionTest extends ItopDataTestCase
MetaModel::GetConfig()->SetAllowedLoginTypes($aAllowedLoginTypes);
MetaModel::GetConfig()->WriteToFile();
}
- @chmod(MetaModel::GetConfig()->GetLoadedFile(), 0440);
+ @chmod(MetaModel::GetConfig()->GetLoadedFile(), 0444);
}
protected function SetLoginModes($aAllowedLoginTypes){
@chmod(MetaModel::GetConfig()->GetLoadedFile(), 0770);
MetaModel::GetConfig()->SetAllowedLoginTypes($aAllowedLoginTypes);
MetaModel::GetConfig()->WriteToFile();
- @chmod(MetaModel::GetConfig()->GetLoadedFile(), 0440);
+ @chmod(MetaModel::GetConfig()->GetLoadedFile(), 0444);
}
public function RestProvider(){