From 8fb0f3b31bdeb0bab8c50ecf402c7390d1bcd973 Mon Sep 17 00:00:00 2001 From: tremo Date: Mon, 8 Jun 2026 13:21:38 +0200 Subject: [PATCH 1/6] fix(alert): force closed alerts display after alert update --- .phpunit.result.cache | 1 + composer.json | 3 +- inc/alert.class.php | 33 ++-- phpunit.xml | 11 ++ tests/bootstrap.php | 44 ++++++ tests/units/PluginNewsAlertTest.php | 225 ++++++++++++++++++++++++++++ 6 files changed, 297 insertions(+), 20 deletions(-) create mode 100644 .phpunit.result.cache create mode 100644 phpunit.xml create mode 100644 tests/bootstrap.php create mode 100644 tests/units/PluginNewsAlertTest.php diff --git a/.phpunit.result.cache b/.phpunit.result.cache new file mode 100644 index 0000000..30c38a8 --- /dev/null +++ b/.phpunit.result.cache @@ -0,0 +1 @@ +{"version":2,"defects":{"GlpiPlugin\\News\\Tests\\Units\\PluginNewsAlertTest::testPostUpdateItemResetsHiddenAlerts":7,"GlpiPlugin\\News\\Tests\\Units\\PluginNewsAlertTest::testPostUpdateItemDoesNotAffectOtherAlerts":7},"times":{"GlpiPlugin\\News\\Tests\\Units\\PluginNewsAlertTest::testPostUpdateItemResetsHiddenAlerts":0.666,"GlpiPlugin\\News\\Tests\\Units\\PluginNewsAlertTest::testPostUpdateItemDoesNotAffectOtherAlerts":0.277}} \ No newline at end of file diff --git a/composer.json b/composer.json index 8338bce..945d30f 100644 --- a/composer.json +++ b/composer.json @@ -14,7 +14,8 @@ }, "autoload-dev": { "psr-4": { - "Glpi\\Tools\\": "../../tools/src/" + "Glpi\\Tools\\": "../../tools/src/", + "GlpiPlugin\\News\\Tests\\": "tests/" } } } diff --git a/inc/alert.class.php b/inc/alert.class.php index a965f63..e9e5188 100644 --- a/inc/alert.class.php +++ b/inc/alert.class.php @@ -227,28 +227,23 @@ public function rawSearchOptions() public function post_updateItem($history = true) { - // if close is not allowed update all user alerts to force display - if ( - isset($this->input['is_close_allowed']) - && !$this->input['is_close_allowed'] - ) { - $alert_user = new PluginNewsAlert_User(); - //get all Alert_User for this alert where state is hidden - $all_alert = $alert_user->find( + // force display of alerts after update regardless of their closable state + $alert_user = new PluginNewsAlert_User(); + //get all Alert_User for this alert where state is hidden + $all_alert = $alert_user->find( + [ + 'plugin_news_alerts_id' => $this->getID(), + 'state' => PluginNewsAlert_User::HIDDEN, + ], + ); + foreach ($all_alert as $alert) { + //update state to force display + $alert_user->update( [ - 'plugin_news_alerts_id' => $this->getID(), - 'state' => PluginNewsAlert_User::HIDDEN, + 'id' => $alert['id'], + 'state' => PluginNewsAlert_User::VISIBLE, ], ); - foreach ($all_alert as $alert) { - //update state to force display - $alert_user->update( - [ - 'id' => $alert['id'], - 'state' => PluginNewsAlert_User::VISIBLE, - ], - ); - } } } diff --git a/phpunit.xml b/phpunit.xml new file mode 100644 index 0000000..cd6c7b3 --- /dev/null +++ b/phpunit.xml @@ -0,0 +1,11 @@ + + + + tests + + + diff --git a/tests/bootstrap.php b/tests/bootstrap.php new file mode 100644 index 0000000..aed262b --- /dev/null +++ b/tests/bootstrap.php @@ -0,0 +1,44 @@ +. + * ------------------------------------------------------------------------- + * @copyright Copyright (C) 2015-2023 by News plugin team. + * @license GPLv2 https://www.gnu.org/licenses/gpl-2.0.html + * @link https://github.com/pluginsGLPI/news + * ------------------------------------------------------------------------- + */ + +require __DIR__ . '/../../../tests/bootstrap.php'; +require dirname(__DIR__) . '/vendor/autoload.php'; + +$plugin = new Plugin(); +$plugin->checkPluginState('news'); +$plugin->getFromDBbyDir('news'); + +if (!$plugin->isInstalled('news')) { + $plugin->install($plugin->getID()); +} + +if (!$plugin->isActivated('news')) { + $plugin->activate($plugin->getID()); +} diff --git a/tests/units/PluginNewsAlertTest.php b/tests/units/PluginNewsAlertTest.php new file mode 100644 index 0000000..9dee10f --- /dev/null +++ b/tests/units/PluginNewsAlertTest.php @@ -0,0 +1,225 @@ +. + * ------------------------------------------------------------------------- + * @copyright Copyright (C) 2015-2023 by News plugin team. + * @license GPLv2 https://www.gnu.org/licenses/gpl-2.0.html + * @link https://github.com/pluginsGLPI/news + * ------------------------------------------------------------------------- + */ + +namespace GlpiPlugin\News\Tests\Units; + +use Glpi\Tests\DbTestCase; +use PluginNewsAlert; +use PluginNewsAlert_User; +use User; + +class PluginNewsAlertTest extends DbTestCase +{ + private function getAlertUserState(int $au_id): int + { + $alert_user = new PluginNewsAlert_User(); + $this->assertTrue($alert_user->getFromDB($au_id)); + return (int) $alert_user->fields['state']; + } + + public function testPostUpdateItemResetsHiddenAlerts(): void + { + $this->login('glpi'); + + $alert = $this->createItem( + PluginNewsAlert::class, + [ + 'name' => 'closable Alert', + 'message' => 'This is a closable alert', + 'type' => 1, + 'is_displayed_onlogin' => 1, + 'is_displayed_oncentral' => 1, + 'is_displayed_onservicecatalog' => 1, + 'display_dates' => 1, + 'background_color' => 'white', + 'emphasis_color' => 'dark', + 'size' => 'medium', + 'icon' => 'settings', + 'is_displayed_onhelpdesk' => 1, + 'is_active' => 1, + 'entities_id' => 0, + 'is_close_allowed' => 1, + ], + ); + $this->assertEquals(PluginNewsAlert::class, get_class($alert)); + $alert_id = $alert->getID(); + + $user_1 = $this->createItem( + User::class, + [ + 'name' => 'user 1', + 'password' => 'test', + 'password2' => 'test', + ], + ['password', 'password2'], + ); + + $user_2 = $this->createItem( + User::class, + [ + 'name' => 'user 2', + 'password' => 'test', + 'password2' => 'test', + ], + ['password', 'password2'], + ); + + $this->assertEquals(User::class, get_class($user_1)); + $this->assertEquals(User::class, get_class($user_2)); + + $user_1_id = $user_1->getID(); + $user_2_id = $user_2->getID(); + + $alert_user_1 = $this->createItem(PluginNewsAlert_User::class, [ + 'plugin_news_alerts_id' => $alert_id, + 'users_id' => $user_1_id, + 'state' => PluginNewsAlert_User::HIDDEN, + ]); + + $alert_user_2 = $this->createItem(PluginNewsAlert_User::class, [ + 'plugin_news_alerts_id' => $alert_id, + 'users_id' => $user_2_id, + 'state' => PluginNewsAlert_User::HIDDEN, + ]); + + $this->assertEquals(PluginNewsAlert_User::class, get_class($alert_user_1)); + $this->assertEquals(PluginNewsAlert_User::class, get_class($alert_user_2)); + + $alert_user_1_id = $alert_user_1->getID(); + $alert_user_2_id = $alert_user_2->getID(); + + $result = $alert->update(['id' => $alert_id, 'name' => 'Alert with hidden users (updated)']); + $this->assertTrue($result); + + //assert that both users are now in VISIBLE state + $this->assertSame(PluginNewsAlert_User::VISIBLE, $this->getAlertUserState($alert_user_1_id)); + $this->assertSame(PluginNewsAlert_User::VISIBLE, $this->getAlertUserState($alert_user_2_id)); + + //re-hide users alerts + $alert_user = new PluginNewsAlert_User(); + $this->assertTrue($alert_user->update(['id' => $alert_user_1_id, 'state' => PluginNewsAlert_User::HIDDEN])); + $this->assertTrue($alert_user->update(['id' => $alert_user_2_id, 'state' => PluginNewsAlert_User::HIDDEN])); + + //update the alert with is_close_allowed = 0 + $result = $alert->update(['id' => $alert_id, 'is_close_allowed' => 0]); + $this->assertTrue($result); + + //assert that alerts are visible again + $this->assertSame(PluginNewsAlert_User::VISIBLE, $this->getAlertUserState($alert_user_1_id)); + $this->assertSame(PluginNewsAlert_User::VISIBLE, $this->getAlertUserState($alert_user_2_id)); + } + + public function testPostUpdateItemDoesNotAffectOtherAlerts(): void + { + $this->login('glpi'); + + $alert_1 = $this->createItem( + PluginNewsAlert::class, + [ + 'name' => 'alert 1', + 'message' => 'This is a closable alert', + 'type' => 1, + 'is_displayed_onlogin' => 1, + 'is_displayed_oncentral' => 1, + 'is_displayed_onservicecatalog' => 1, + 'display_dates' => 1, + 'background_color' => 'white', + 'emphasis_color' => 'dark', + 'size' => 'medium', + 'icon' => 'settings', + 'is_displayed_onhelpdesk' => 1, + 'is_active' => 1, + 'entities_id' => 0, + 'is_close_allowed' => 1, + ], + ); + $this->assertEquals(PluginNewsAlert::class, get_class($alert_1)); + $alert_1_id = $alert_1->getID(); + + $alert_2 = $this->createItem( + PluginNewsAlert::class, + [ + 'name' => 'alert 2', + 'message' => 'This is a closable alert', + 'type' => 1, + 'is_displayed_onlogin' => 1, + 'is_displayed_oncentral' => 1, + 'is_displayed_onservicecatalog' => 1, + 'display_dates' => 1, + 'background_color' => 'white', + 'emphasis_color' => 'dark', + 'size' => 'medium', + 'icon' => 'settings', + 'is_displayed_onhelpdesk' => 1, + 'is_active' => 1, + 'entities_id' => 0, + 'is_close_allowed' => 1, + ], + ); + $this->assertEquals(PluginNewsAlert::class, get_class($alert_1)); + $alert_2_id = $alert_2->getID(); + + $user_1 = $this->createItem( + User::class, + [ + 'name' => 'user 1', + 'password' => 'test', + 'password2' => 'test', + ], + ['password', 'password2'], + ); + $this->assertEquals(User::class, get_class($user_1)); + $user_1_id = $user_1->getID(); + + $alert_user_1 = $this->createItem(PluginNewsAlert_User::class, [ + 'plugin_news_alerts_id' => $alert_1_id, + 'users_id' => $user_1_id, + 'state' => PluginNewsAlert_User::HIDDEN, + ]); + + $alert_user_2 = $this->createItem(PluginNewsAlert_User::class, [ + 'plugin_news_alerts_id' => $alert_2_id, + 'users_id' => $user_1_id, + 'state' => PluginNewsAlert_User::HIDDEN, + ]); + + $this->assertEquals(PluginNewsAlert_User::class, get_class($alert_user_1)); + $this->assertEquals(PluginNewsAlert_User::class, get_class($alert_user_2)); + + $alert_user_1_id = $alert_user_1->getID(); + $alert_user_2_id = $alert_user_2->getID(); + + $alert = new PluginNewsAlert(); + $alert->update(['id' => $alert_1_id, 'name' => 'Alert 1 (updated)']); + + $this->assertSame(PluginNewsAlert_User::VISIBLE, $this->getAlertUserState($alert_user_1_id)); + $this->assertSame(PluginNewsAlert_User::HIDDEN, $this->getAlertUserState($alert_user_2_id)); + } +} From 7179d6e38186173467487bb9d7157c4f90b4500b Mon Sep 17 00:00:00 2001 From: tremo Date: Mon, 8 Jun 2026 13:24:06 +0200 Subject: [PATCH 2/6] changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e72bab..2d05158 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +### Fixed + +- Force closed alerts display after alert update. + ## [1.14.0] - 2026-04-30 ### Added From 4fb49b3cbfb573e9b703da6ff1d8d01480be7381 Mon Sep 17 00:00:00 2001 From: tremo Date: Mon, 8 Jun 2026 13:25:55 +0200 Subject: [PATCH 3/6] remove cache file --- .phpunit.result.cache | 1 - 1 file changed, 1 deletion(-) delete mode 100644 .phpunit.result.cache diff --git a/.phpunit.result.cache b/.phpunit.result.cache deleted file mode 100644 index 30c38a8..0000000 --- a/.phpunit.result.cache +++ /dev/null @@ -1 +0,0 @@ -{"version":2,"defects":{"GlpiPlugin\\News\\Tests\\Units\\PluginNewsAlertTest::testPostUpdateItemResetsHiddenAlerts":7,"GlpiPlugin\\News\\Tests\\Units\\PluginNewsAlertTest::testPostUpdateItemDoesNotAffectOtherAlerts":7},"times":{"GlpiPlugin\\News\\Tests\\Units\\PluginNewsAlertTest::testPostUpdateItemResetsHiddenAlerts":0.666,"GlpiPlugin\\News\\Tests\\Units\\PluginNewsAlertTest::testPostUpdateItemDoesNotAffectOtherAlerts":0.277}} \ No newline at end of file From ee8abb60b24bef307f17b81b07e9f3f1dcd61877 Mon Sep 17 00:00:00 2001 From: tremo Date: Mon, 8 Jun 2026 16:17:19 +0200 Subject: [PATCH 4/6] fix unit tests --- tests/units/PluginNewsAlertTest.php | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/tests/units/PluginNewsAlertTest.php b/tests/units/PluginNewsAlertTest.php index 9dee10f..d738d11 100644 --- a/tests/units/PluginNewsAlertTest.php +++ b/tests/units/PluginNewsAlertTest.php @@ -115,21 +115,18 @@ public function testPostUpdateItemResetsHiddenAlerts(): void $alert_user_1_id = $alert_user_1->getID(); $alert_user_2_id = $alert_user_2->getID(); - $result = $alert->update(['id' => $alert_id, 'name' => 'Alert with hidden users (updated)']); - $this->assertTrue($result); + $this->updateItem(PluginNewsAlert::class, $alert_id, ['name' => 'Alert with hidden users (updated)']); //assert that both users are now in VISIBLE state $this->assertSame(PluginNewsAlert_User::VISIBLE, $this->getAlertUserState($alert_user_1_id)); $this->assertSame(PluginNewsAlert_User::VISIBLE, $this->getAlertUserState($alert_user_2_id)); //re-hide users alerts - $alert_user = new PluginNewsAlert_User(); - $this->assertTrue($alert_user->update(['id' => $alert_user_1_id, 'state' => PluginNewsAlert_User::HIDDEN])); - $this->assertTrue($alert_user->update(['id' => $alert_user_2_id, 'state' => PluginNewsAlert_User::HIDDEN])); + $this->updateItem(PluginNewsAlert_User::class, $alert_user_1_id, ['state' => PluginNewsAlert_User::HIDDEN]); + $this->updateItem(PluginNewsAlert_User::class, $alert_user_2_id, ['state' => PluginNewsAlert_User::HIDDEN]); //update the alert with is_close_allowed = 0 - $result = $alert->update(['id' => $alert_id, 'is_close_allowed' => 0]); - $this->assertTrue($result); + $this->updateItem(PluginNewsAlert::class, $alert_id, ['is_close_allowed' => 0]); //assert that alerts are visible again $this->assertSame(PluginNewsAlert_User::VISIBLE, $this->getAlertUserState($alert_user_1_id)); From 8a3b81df945c8a2fccbab848e71f01b385e9d301 Mon Sep 17 00:00:00 2001 From: tremo Date: Tue, 9 Jun 2026 08:57:44 +0200 Subject: [PATCH 5/6] changes --- tests/units/PluginNewsAlertTest.php | 34 +++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/tests/units/PluginNewsAlertTest.php b/tests/units/PluginNewsAlertTest.php index d738d11..61a48a0 100644 --- a/tests/units/PluginNewsAlertTest.php +++ b/tests/units/PluginNewsAlertTest.php @@ -91,11 +91,23 @@ public function testPostUpdateItemResetsHiddenAlerts(): void ['password', 'password2'], ); + $user_3 = $this->createItem( + User::class, + [ + 'name' => 'user 3', + 'password' => 'test', + 'password2' => 'test', + ], + ['password', 'password2'], + ); + $this->assertEquals(User::class, get_class($user_1)); $this->assertEquals(User::class, get_class($user_2)); + $this->assertEquals(User::class, get_class($user_3)); $user_1_id = $user_1->getID(); $user_2_id = $user_2->getID(); + $user_3_id = $user_3->getID(); $alert_user_1 = $this->createItem(PluginNewsAlert_User::class, [ 'plugin_news_alerts_id' => $alert_id, @@ -109,11 +121,20 @@ public function testPostUpdateItemResetsHiddenAlerts(): void 'state' => PluginNewsAlert_User::HIDDEN, ]); + //user 3 has not hidden the alert + $alert_user_3 = $this->createItem(PluginNewsAlert_User::class, [ + 'plugin_news_alerts_id' => $alert_id, + 'users_id' => $user_3_id, + 'state' => PluginNewsAlert_User::VISIBLE, + ]); + $this->assertEquals(PluginNewsAlert_User::class, get_class($alert_user_1)); $this->assertEquals(PluginNewsAlert_User::class, get_class($alert_user_2)); + $this->assertEquals(PluginNewsAlert_User::class, get_class($alert_user_3)); $alert_user_1_id = $alert_user_1->getID(); $alert_user_2_id = $alert_user_2->getID(); + $alert_user_3_id = $alert_user_3->getID(); $this->updateItem(PluginNewsAlert::class, $alert_id, ['name' => 'Alert with hidden users (updated)']); @@ -121,7 +142,10 @@ public function testPostUpdateItemResetsHiddenAlerts(): void $this->assertSame(PluginNewsAlert_User::VISIBLE, $this->getAlertUserState($alert_user_1_id)); $this->assertSame(PluginNewsAlert_User::VISIBLE, $this->getAlertUserState($alert_user_2_id)); - //re-hide users alerts + //assert that user 3 is still in VISIBLE state + $this->assertSame(PluginNewsAlert_User::VISIBLE, $this->getAlertUserState($alert_user_3_id)); + + //re-hide users 1 and 2 alerts $this->updateItem(PluginNewsAlert_User::class, $alert_user_1_id, ['state' => PluginNewsAlert_User::HIDDEN]); $this->updateItem(PluginNewsAlert_User::class, $alert_user_2_id, ['state' => PluginNewsAlert_User::HIDDEN]); @@ -131,6 +155,9 @@ public function testPostUpdateItemResetsHiddenAlerts(): void //assert that alerts are visible again $this->assertSame(PluginNewsAlert_User::VISIBLE, $this->getAlertUserState($alert_user_1_id)); $this->assertSame(PluginNewsAlert_User::VISIBLE, $this->getAlertUserState($alert_user_2_id)); + + //assert that user 3 is still in VISIBLE state + $this->assertSame(PluginNewsAlert_User::VISIBLE, $this->getAlertUserState($alert_user_3_id)); } public function testPostUpdateItemDoesNotAffectOtherAlerts(): void @@ -180,7 +207,7 @@ public function testPostUpdateItemDoesNotAffectOtherAlerts(): void 'is_close_allowed' => 1, ], ); - $this->assertEquals(PluginNewsAlert::class, get_class($alert_1)); + $this->assertEquals(PluginNewsAlert::class, get_class($alert_2)); $alert_2_id = $alert_2->getID(); $user_1 = $this->createItem( @@ -213,8 +240,7 @@ public function testPostUpdateItemDoesNotAffectOtherAlerts(): void $alert_user_1_id = $alert_user_1->getID(); $alert_user_2_id = $alert_user_2->getID(); - $alert = new PluginNewsAlert(); - $alert->update(['id' => $alert_1_id, 'name' => 'Alert 1 (updated)']); + $this->updateItem(PluginNewsAlert::class, $alert_1_id, ['name' => 'Alert 1 (updated)']); $this->assertSame(PluginNewsAlert_User::VISIBLE, $this->getAlertUserState($alert_user_1_id)); $this->assertSame(PluginNewsAlert_User::HIDDEN, $this->getAlertUserState($alert_user_2_id)); From 973d68a54aaf7f21ed6ae0cf49d4da6f705bdaa8 Mon Sep 17 00:00:00 2001 From: tremo Date: Tue, 9 Jun 2026 14:03:45 +0200 Subject: [PATCH 6/6] changes --- tests/units/PluginNewsAlertTest.php | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/tests/units/PluginNewsAlertTest.php b/tests/units/PluginNewsAlertTest.php index 61a48a0..0ef3929 100644 --- a/tests/units/PluginNewsAlertTest.php +++ b/tests/units/PluginNewsAlertTest.php @@ -68,7 +68,6 @@ public function testPostUpdateItemResetsHiddenAlerts(): void 'is_close_allowed' => 1, ], ); - $this->assertEquals(PluginNewsAlert::class, get_class($alert)); $alert_id = $alert->getID(); $user_1 = $this->createItem( @@ -101,10 +100,6 @@ public function testPostUpdateItemResetsHiddenAlerts(): void ['password', 'password2'], ); - $this->assertEquals(User::class, get_class($user_1)); - $this->assertEquals(User::class, get_class($user_2)); - $this->assertEquals(User::class, get_class($user_3)); - $user_1_id = $user_1->getID(); $user_2_id = $user_2->getID(); $user_3_id = $user_3->getID(); @@ -128,10 +123,6 @@ public function testPostUpdateItemResetsHiddenAlerts(): void 'state' => PluginNewsAlert_User::VISIBLE, ]); - $this->assertEquals(PluginNewsAlert_User::class, get_class($alert_user_1)); - $this->assertEquals(PluginNewsAlert_User::class, get_class($alert_user_2)); - $this->assertEquals(PluginNewsAlert_User::class, get_class($alert_user_3)); - $alert_user_1_id = $alert_user_1->getID(); $alert_user_2_id = $alert_user_2->getID(); $alert_user_3_id = $alert_user_3->getID(); @@ -184,7 +175,6 @@ public function testPostUpdateItemDoesNotAffectOtherAlerts(): void 'is_close_allowed' => 1, ], ); - $this->assertEquals(PluginNewsAlert::class, get_class($alert_1)); $alert_1_id = $alert_1->getID(); $alert_2 = $this->createItem( @@ -207,7 +197,6 @@ public function testPostUpdateItemDoesNotAffectOtherAlerts(): void 'is_close_allowed' => 1, ], ); - $this->assertEquals(PluginNewsAlert::class, get_class($alert_2)); $alert_2_id = $alert_2->getID(); $user_1 = $this->createItem( @@ -219,7 +208,6 @@ public function testPostUpdateItemDoesNotAffectOtherAlerts(): void ], ['password', 'password2'], ); - $this->assertEquals(User::class, get_class($user_1)); $user_1_id = $user_1->getID(); $alert_user_1 = $this->createItem(PluginNewsAlert_User::class, [ @@ -234,9 +222,6 @@ public function testPostUpdateItemDoesNotAffectOtherAlerts(): void 'state' => PluginNewsAlert_User::HIDDEN, ]); - $this->assertEquals(PluginNewsAlert_User::class, get_class($alert_user_1)); - $this->assertEquals(PluginNewsAlert_User::class, get_class($alert_user_2)); - $alert_user_1_id = $alert_user_1->getID(); $alert_user_2_id = $alert_user_2->getID();