diff --git a/CHANGELOG.md b/CHANGELOG.md
index 08b1293c..6fb84174 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -12,6 +12,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Prevent business rules from triggering twice on tickets
- Fixed routing issue caused by incorrect trailing slash
+### Added
+
+- Add task visibility option (`task_private`)
+
## [2.9.19] - 2026-27-01
### Fixed
diff --git a/hook.php b/hook.php
index a6f4cb33..16ba359b 100644
--- a/hook.php
+++ b/hook.php
@@ -85,12 +85,13 @@ function plugin_escalade_install()
`use_filter_assign_group` INT NOT NULL,
`ticket_last_status` INT NOT NULL,
`remove_requester` INT NOT NULL,
+ `task_private` INT NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET={$default_charset} COLLATE={$default_collation} ROW_FORMAT=DYNAMIC;";
$DB->doQuery($query);
$query = "INSERT INTO glpi_plugin_escalade_configs
- VALUES (NULL, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, '" . Ticket::WAITING . "',0)";
+ VALUES (NULL, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, '" . Ticket::WAITING . "',0, 1)";
$DB->doQuery($query);
}
@@ -390,6 +391,18 @@ function plugin_escalade_install()
$migration->migrationOneTable('glpi_plugin_escalade_users');
}
+ //Update to 2.10.2
+ // add new fields
+ if (!$DB->fieldExists('glpi_plugin_escalade_configs', 'task_private')) {
+ $migration->addField(
+ 'glpi_plugin_escalade_configs',
+ 'task_private',
+ 'integer',
+ ['after' => 'remove_requester'],
+ );
+ $migration->migrationOneTable('glpi_plugin_escalade_configs');
+ }
+
return true;
}
diff --git a/inc/ticket.class.php b/inc/ticket.class.php
index 898271ef..a1223402 100644
--- a/inc/ticket.class.php
+++ b/inc/ticket.class.php
@@ -524,7 +524,7 @@ public static function processAfterAddGroup(Group_Ticket $item)
$task_content = '
' . sprintf(__s('Escalation to the group %s.', 'escalade'), $group->getName()) . '
' . $comment;
PluginEscaladeTaskmanager::setTicketTask([
'tickets_id' => $tickets_id,
- 'is_private' => true,
+ 'is_private' => $_SESSION['glpi_plugins']['escalade']['config']['task_private'],
'state' => Planning::INFO,
'content' => $task_content,
]);
diff --git a/templates/config.html.twig b/templates/config.html.twig
index 715ce3a1..52f8b921 100644
--- a/templates/config.html.twig
+++ b/templates/config.html.twig
@@ -194,6 +194,13 @@
field_options
) }}
+ {{ fields.sliderField(
+ 'task_private',
+ config["task_private"],
+ __("Escalation task is private ?", "escalade"),
+ field_options
+ ) }}
+
{{ fields.dropdownArrayField(
'ticket_last_status',
config["ticket_last_status"],
diff --git a/tests/EscaladeTestCase.php b/tests/EscaladeTestCase.php
index ff6b7950..d831ddac 100644
--- a/tests/EscaladeTestCase.php
+++ b/tests/EscaladeTestCase.php
@@ -113,6 +113,7 @@ public function initConfig(array $conf = [])
'cloneandlink_ticket' => 0,
'close_linkedtickets' => 0,
'reassign_group_from_cat' => 0,
+ 'task_private' => 1,
];
// Update escalade config in database if provided
diff --git a/tests/Units/TaskMessageTest.php b/tests/Units/TaskMessageTest.php
index 65b5f103..6ec75a8e 100644
--- a/tests/Units/TaskMessageTest.php
+++ b/tests/Units/TaskMessageTest.php
@@ -276,4 +276,65 @@ public function testTaskGroupEscalation(array $conf)
}
}
}
+
+ public static function taskPrivateProvider(): iterable
+ {
+ yield [
+ 'task_private' => 0,
+ 'expected_is_private' => 0,
+ ];
+
+ yield [
+ 'task_private' => 1,
+ 'expected_is_private' => 1,
+ ];
+ }
+
+ #[DataProvider('taskPrivateProvider')]
+ public function testTaskPrivateFlagOnEscalationTask(int $task_private, int $expected_is_private): void
+ {
+ $this->initConfig([
+ 'task_history' => 1,
+ 'task_private' => $task_private,
+ ]);
+
+ $ticket = $this->createItem('Ticket', [
+ 'name' => 'Task private escalation test',
+ 'content' => '',
+ 'entities_id' => 0,
+ ]);
+
+ $this->createItem('Group', [
+ 'name' => 'Task private group',
+ 'entities_id' => 0,
+ ]);
+
+ $group2 = $this->createItem('Group', [
+ 'name' => 'Task private group 2',
+ 'entities_id' => 0,
+ ]);
+
+ $this->updateItem(
+ Ticket::class,
+ $ticket->getID(),
+ [
+ '_actors' => [
+ 'assign' => [
+ [
+ 'items_id' => $group2->getID(),
+ 'itemtype' => 'Group',
+ ],
+ ],
+ ],
+ ],
+ );
+
+ $ticket_task = new TicketTask();
+ $ticket_tasks = $ticket_task->find(['tickets_id' => $ticket->getID()]);
+
+ $this->assertCount(1, $ticket_tasks);
+
+ $last_task = end($ticket_tasks);
+ $this->assertSame($expected_is_private, (int) $last_task['is_private']);
+ }
}