Correction du fichier hook.php pour le plugin SOC

This commit is contained in:
tips-of-mine
2025-05-31 14:43:12 +02:00
committed by GitHub
parent 5b30a110ac
commit 4622a1a2cd
6 changed files with 554 additions and 24 deletions

9
SOC-Case-Management.xml Normal file
View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<root>
<versions>
<version>
<num>1.0.0</num>
<compatibility>~10.0.0</compatibility>
</version>
</versions>
</root>

326
hook.php
View File

@ -4,49 +4,156 @@
*/
/**
* Hook called after a new item has been added
* Item display hook - adds tabs to items
*
* @param CommonDBTM $item
* @return void
* @param CommonGLPI $item Object on which to add the tab
* @param integer $withtemplate
* @return array|string
*/
function plugin_soc_item_add(CommonDBTM $item) {
// Add actions when a new item is created
function plugin_soc_getTabNameForItem(CommonGLPI $item, $withtemplate = 0) {
if ($withtemplate) {
return '';
}
switch ($item->getType()) {
case 'Ticket':
if (Session::haveRight('plugin_soc_case', READ)) {
return PluginSocCase::getTypeName(Session::getPluralNumber());
}
break;
case 'Change':
if (Session::haveRight('plugin_soc_case', READ)) {
return PluginSocCase::getTypeName(Session::getPluralNumber());
}
break;
}
return '';
}
/**
* Hook called after an item has been updated
* Item update hook
*
* @param CommonDBTM $item
* @param CommonDBTM $item Item being updated
* @return void
*/
function plugin_soc_item_update(CommonDBTM $item) {
// Add actions when an item is updated
// Handle item updates
switch ($item->getType()) {
case 'Ticket':
case 'Change':
// Custom update logic if needed
break;
}
}
/**
* Hook called after an item has been deleted
* Item add hook
*
* @param CommonDBTM $item
* @param CommonDBTM $item Item being added
* @return void
*/
function plugin_soc_item_add(CommonDBTM $item) {
// Handle item additions
switch ($item->getType()) {
case 'Ticket':
case 'Change':
// Custom add logic if needed
break;
}
}
/**
* Item delete hook
*
* @param CommonDBTM $item Item being deleted
* @return void
*/
function plugin_soc_item_delete(CommonDBTM $item) {
// Add actions when an item is deleted
// Handle item deletions
switch ($item->getType()) {
case 'Ticket':
case 'Change':
// Custom delete logic if needed
break;
}
}
/**
* Hook called after an item has been purged
* Item purge hook
*
* @param CommonDBTM $item
* @param CommonDBTM $item Item being purged
* @return void
*/
function plugin_soc_item_purge(CommonDBTM $item) {
// Add actions when an item is purged
// Handle item purges
global $DB;
switch ($item->getType()) {
case 'Ticket':
// Delete case-ticket relations
$DB->delete(
'glpi_plugin_soc_case_tickets',
['tickets_id' => $item->getID()]
);
break;
case 'Change':
// Delete case-change relations
$DB->delete(
'glpi_plugin_soc_case_changes',
['changes_id' => $item->getID()]
);
break;
case 'PluginSocCase':
// Delete related items
$DB->delete(
'glpi_plugin_soc_case_tickets',
['plugin_soc_cases_id' => $item->getID()]
);
$DB->delete(
'glpi_plugin_soc_case_changes',
['plugin_soc_cases_id' => $item->getID()]
);
break;
}
}
/**
* Hook called when displaying the tabs for an item
* Display tab content for item
*
* @param array $params
* @param CommonGLPI $item Object on which to display the tab
* @param integer $tabnum Tab number
* @param integer $withtemplate
* @return boolean
*/
function plugin_soc_displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) {
if ($withtemplate) {
return false;
}
switch ($item->getType()) {
case 'Ticket':
$case_ticket = new PluginSocCaseTicket();
$case_ticket->showForTicket($item);
return true;
case 'Change':
$case_change = new PluginSocCaseChange();
$case_change->showForChange($item);
return true;
}
return false;
}
/**
* Hook to define additional search options for types
*
* @param string $itemtype Item type
* @return array
*/
function plugin_soc_getAddSearchOptions($itemtype) {
@ -58,6 +165,27 @@ function plugin_soc_getAddSearchOptions($itemtype) {
'table' => 'glpi_plugin_soc_cases',
'field' => 'name',
'name' => __('SOC Case', 'soc'),
'datatype' => 'itemlink',
'itemlink_type' => 'PluginSocCase',
'massiveaction' => false,
'joinparams' => [
'beforejoin' => [
'table' => $itemtype == 'Ticket' ? 'glpi_plugin_soc_case_tickets' : 'glpi_plugin_soc_case_changes',
'joinparams' => [
'jointype' => 'itemtype_item',
'specific_itemtype' => $itemtype
]
]
]
];
$options[9001] = [
'table' => 'glpi_plugin_soc_cases',
'field' => 'severity',
'name' => __('SOC Case Severity', 'soc'),
'datatype' => 'specific',
'searchtype' => ['equals', 'notequals'],
'massiveaction' => false,
'joinparams' => [
'beforejoin' => [
'table' => $itemtype == 'Ticket' ? 'glpi_plugin_soc_case_tickets' : 'glpi_plugin_soc_case_changes',
@ -72,3 +200,169 @@ function plugin_soc_getAddSearchOptions($itemtype) {
return $options;
}
/**
* Hook to add cron tasks
*
* @return array
*/
function plugin_soc_cron_info() {
return [
'soc' => [
'description' => __('Auto-close SOC cases', 'soc'),
'parameter' => __('Delay in days', 'soc'),
'state' => CronTask::STATE_WAITING,
'mode' => CronTask::MODE_EXTERNAL,
'frequency' => DAY_TIMESTAMP,
]
];
}
/**
* Execute cron task
*
* @param CronTask $task CronTask object
* @return integer
*/
function plugin_soc_cronSoc(CronTask $task) {
global $DB;
// Get autoclose delay from config
$config = PluginSocConfig::getConfig();
$delay = $config['autoclose_delay'];
if ($delay <= 0) {
// Auto-closing is disabled
$task->log(__('Auto-closing SOC cases is disabled in plugin configuration.', 'soc'));
return 0;
}
$time_limit = date('Y-m-d H:i:s', strtotime("-$delay days"));
// Find resolved cases older than the delay
$cases = $DB->request([
'FROM' => 'glpi_plugin_soc_cases',
'WHERE' => [
'status' => PluginSocCase::STATUS_RESOLVED,
'date_mod' => ['<', $time_limit],
'is_deleted' => 0
]
]);
$count = 0;
foreach ($cases as $case_data) {
$case = new PluginSocCase();
$case->getFromDB($case_data['id']);
// Update status to closed
$case->update([
'id' => $case_data['id'],
'status' => PluginSocCase::STATUS_CLOSED
]);
$task->addVolume(1);
$count++;
}
$task->log(sprintf(__('Closed %d SOC cases.', 'soc'), $count));
return ($count > 0) ? 1 : 0;
}
/**
* Hook for database relations
*
* @return array
*/
function plugin_soc_getDatabaseRelations() {
return [
'glpi_entities' => [
'glpi_plugin_soc_cases' => 'entities_id'
],
'glpi_users' => [
'glpi_plugin_soc_cases' => 'users_id_tech'
],
'glpi_groups' => [
'glpi_plugin_soc_cases' => 'groups_id_tech'
],
'glpi_tickets' => [
'glpi_plugin_soc_case_tickets' => 'tickets_id'
],
'glpi_changes' => [
'glpi_plugin_soc_case_changes' => 'changes_id'
],
'glpi_plugin_soc_cases' => [
'glpi_plugin_soc_case_tickets' => 'plugin_soc_cases_id',
'glpi_plugin_soc_case_changes' => 'plugin_soc_cases_id'
]
];
}
/**
* Hook for headings (used in massive actions)
*
* @param string $type Item type
* @return array
*/
function plugin_soc_getHaveItemtype($type) {
switch ($type) {
case 'PluginSocCase':
return ['Ticket' => PluginSocCase::getTypeName(Session::getPluralNumber()),
'Change' => PluginSocCase::getTypeName(Session::getPluralNumber())];
}
return [];
}
/**
* Hook for massive actions
*
* @param string $type Item type
* @return array
*/
function plugin_soc_getMassiveActions($type) {
switch ($type) {
case 'Ticket':
return [
'PluginSocCase:add_to_case' => __('Add to SOC case', 'soc'),
'PluginSocCase:create_from_ticket' => __('Create SOC case from ticket', 'soc')
];
case 'Change':
return [
'PluginSocCase:add_to_case' => __('Add to SOC case', 'soc'),
'PluginSocCase:create_from_change' => __('Create SOC case from change', 'soc')
];
}
return [];
}
/**
* Define dropdown tables
*
* @return array
*/
function plugin_soc_getDropdowns() {
return [
PluginSocCase::getTypeName(Session::getPluralNumber()) => [
'table' => 'glpi_plugin_soc_cases',
'title' => PluginSocCase::getTypeName(Session::getPluralNumber()),
'field' => 'name',
'linkfield' => '',
],
];
}
/**
* Add event to notifications
*
* @return array
*/
function plugin_soc_getEvents() {
return [
'new_soc_case' => __('New SOC case', 'soc'),
'update_soc_case' => __('SOC case updated', 'soc'),
'close_soc_case' => __('SOC case closed', 'soc'),
];
}

View File

@ -77,4 +77,101 @@ class PluginSocCaseChange extends CommonDBRelation {
return $iterator;
}
/**
* Show cases for a change
*
* @param Change $change
* @return void
*/
function showForChange(Change $change) {
global $DB;
$change_id = $change->getID();
if (!$change->can($change_id, READ)) {
return false;
}
$cases = self::getCasesForChange($change_id);
$nb = count($cases);
echo "<div class='spaced'>";
if ($nb > 0) {
echo "<table class='tab_cadre_fixehov'>";
$header = "<tr>";
$header .= "<th>" . __('Name') . "</th>";
$header .= "<th>" . __('Status') . "</th>";
$header .= "<th>" . __('Severity', 'soc') . "</th>";
$header .= "<th>" . __('Creation date') . "</th>";
$header .= "</tr>";
echo $header;
foreach ($cases as $data) {
$case = new PluginSocCase();
$case->getFromDB($data['id']);
echo "<tr class='tab_bg_1'>";
echo "<td><a href='".Plugin::getWebDir('soc')."/front/case.form.php?id=".$data['id']."'>".$data['name']."</a></td>";
echo "<td><span class='soc-status soc-status-".$data['status']."'>".$case->getStatusOptions()[$data['status']]."</span></td>";
echo "<td><span class='soc-severity soc-severity-".$data['severity']."'>".$case->getSeverityOptions()[$data['severity']]."</span></td>";
echo "<td>".Html::convDateTime($data['date_creation'])."</td>";
echo "</tr>";
}
echo "</table>";
} else {
echo "<p class='center'>".__('No SOC case associated with this change', 'soc')."</p>";
}
// If user has rights to create cases
if (Session::haveRight('plugin_soc_case', CREATE)) {
echo "<div class='center'>";
echo "<a href='".Plugin::getWebDir('soc')."/front/case.form.php?changes_id=".$change_id."' class='submit'>";
echo __('Create SOC case from this change', 'soc');
echo "</a>";
echo "</div>";
}
echo "</div>";
}
/**
* Show form for linking a change to a case
*
* @param integer $cases_id
* @param array $options
* @return void
*/
function showFormForCase($cases_id, $options = []) {
global $CFG_GLPI;
$case = new PluginSocCase();
$case->getFromDB($cases_id);
echo "<form method='post' action='".Plugin::getWebDir('soc')."/front/case.form.php'>";
echo "<div class='spaced'>";
echo "<table class='tab_cadre_fixe'>";
echo "<tr class='tab_bg_2'><th colspan='2'>".__('Link a change to this case', 'soc')."</th></tr>";
echo "<tr class='tab_bg_1'><td class='right'>".__('Change')."</td>";
echo "<td class='left'>";
Change::dropdown(['name' => 'changes_id', 'entity' => $case->fields['entities_id']]);
echo "</td></tr>";
echo "<tr class='tab_bg_1'>";
echo "<td class='center' colspan='2'>";
echo "<input type='hidden' name='plugin_soc_cases_id' value='$cases_id'>";
echo "<input type='submit' name='add_change' value=\""._sx('button', 'Add')."\" class='submit'>";
echo "</td></tr>";
echo "</table>";
echo "</div>";
Html::closeForm();
}
}

View File

@ -77,4 +77,101 @@ class PluginSocCaseTicket extends CommonDBRelation {
return $iterator;
}
/**
* Show cases for a ticket
*
* @param Ticket $ticket
* @return void
*/
function showForTicket(Ticket $ticket) {
global $DB;
$ticket_id = $ticket->getID();
if (!$ticket->can($ticket_id, READ)) {
return false;
}
$cases = self::getCasesForTicket($ticket_id);
$nb = count($cases);
echo "<div class='spaced'>";
if ($nb > 0) {
echo "<table class='tab_cadre_fixehov'>";
$header = "<tr>";
$header .= "<th>" . __('Name') . "</th>";
$header .= "<th>" . __('Status') . "</th>";
$header .= "<th>" . __('Severity', 'soc') . "</th>";
$header .= "<th>" . __('Creation date') . "</th>";
$header .= "</tr>";
echo $header;
foreach ($cases as $data) {
$case = new PluginSocCase();
$case->getFromDB($data['id']);
echo "<tr class='tab_bg_1'>";
echo "<td><a href='".Plugin::getWebDir('soc')."/front/case.form.php?id=".$data['id']."'>".$data['name']."</a></td>";
echo "<td><span class='soc-status soc-status-".$data['status']."'>".$case->getStatusOptions()[$data['status']]."</span></td>";
echo "<td><span class='soc-severity soc-severity-".$data['severity']."'>".$case->getSeverityOptions()[$data['severity']]."</span></td>";
echo "<td>".Html::convDateTime($data['date_creation'])."</td>";
echo "</tr>";
}
echo "</table>";
} else {
echo "<p class='center'>".__('No SOC case associated with this ticket', 'soc')."</p>";
}
// If user has rights to create cases
if (Session::haveRight('plugin_soc_case', CREATE)) {
echo "<div class='center'>";
echo "<a href='".Plugin::getWebDir('soc')."/front/case.form.php?tickets_id=".$ticket_id."' class='submit'>";
echo __('Create SOC case from this ticket', 'soc');
echo "</a>";
echo "</div>";
}
echo "</div>";
}
/**
* Show form for linking a ticket to a case
*
* @param integer $cases_id
* @param array $options
* @return void
*/
function showFormForCase($cases_id, $options = []) {
global $CFG_GLPI;
$case = new PluginSocCase();
$case->getFromDB($cases_id);
echo "<form method='post' action='".Plugin::getWebDir('soc')."/front/case.form.php'>";
echo "<div class='spaced'>";
echo "<table class='tab_cadre_fixe'>";
echo "<tr class='tab_bg_2'><th colspan='2'>".__('Link a ticket to this case', 'soc')."</th></tr>";
echo "<tr class='tab_bg_1'><td class='right'>".__('Ticket')."</td>";
echo "<td class='left'>";
Ticket::dropdown(['name' => 'tickets_id', 'entity' => $case->fields['entities_id']]);
echo "</td></tr>";
echo "<tr class='tab_bg_1'>";
echo "<td class='center' colspan='2'>";
echo "<input type='hidden' name='plugin_soc_cases_id' value='$cases_id'>";
echo "<input type='submit' name='add_ticket' value=\""._sx('button', 'Add')."\" class='submit'>";
echo "</td></tr>";
echo "</table>";
echo "</div>";
Html::closeForm();
}
}

View File

@ -0,0 +1,17 @@
<?php
/**
* Initialize plugin translations
*
* @return void
*/
function plugin_init_soc_translations() {
global $CFG_GLPI;
$domain = 'soc';
$locale_dir = GLPI_ROOT . '/plugins/soc/locales/';
if (file_exists($locale_dir)) {
// Load plugin translations
$GLOBALS['LANG']->addTranslationFile('gettext', $locale_dir, $domain, $_SESSION['glpilanguage']);
}
}

View File

@ -65,35 +65,51 @@ function plugin_init_soc() {
global $PLUGIN_HOOKS;
$PLUGIN_HOOKS['csrf_compliant']['soc'] = true;
$PLUGIN_HOOKS['menu_toadd']['soc'] = ['management' => 'PluginSocCase'];
// Add JavaScript and CSS
$PLUGIN_HOOKS['javascript']['soc'] = ['plugins/soc/js/soc.js'];
$PLUGIN_HOOKS['add_css']['soc'] = ['plugins/soc/css/soc.css'];
// Initialize translations
Plugin::registerClass('PluginSocCase');
include_once(GLPI_ROOT . '/plugins/soc/inc/plugin_init_translations.php');
$PLUGIN_HOOKS['init_translations']['soc'] = 'plugin_init_soc_translations';
// Register plugin classes
Plugin::registerClass('PluginSocCase');
Plugin::registerClass('PluginSocProfile', ['addtabtypes' => ['Profile']]);
// Add menu items
if (Session::haveRight('plugin_soc_case', READ)) {
$PLUGIN_HOOKS['menu_toadd']['soc'] = ['management' => 'PluginSocCase'];
}
// Add a tab to Changes
if (Session::haveRight('change', READ)) {
Plugin::registerClass('PluginSocCase', [
'addtabtypes' => ['Change']
]);
$PLUGIN_HOOKS['add_tab']['soc'] = [
'Change' => 'PluginSocCase',
];
}
// Add a tab to Tickets
if (Session::haveRight('ticket', READ)) {
Plugin::registerClass('PluginSocCase', [
'addtabtypes' => ['Ticket']
]);
$PLUGIN_HOOKS['add_tab']['soc'] = [
'Ticket' => 'PluginSocCase',
];
}
// Add config page
if (Session::haveRight('config', UPDATE)) {
$PLUGIN_HOOKS['config_page']['soc'] = 'front/config.form.php';
}
// Hook for item actions
$PLUGIN_HOOKS['item_add']['soc'] = ['*' => 'plugin_soc_item_add'];
$PLUGIN_HOOKS['item_update']['soc'] = ['*' => 'plugin_soc_item_update'];
$PLUGIN_HOOKS['item_delete']['soc'] = ['*' => 'plugin_soc_item_delete'];
$PLUGIN_HOOKS['item_purge']['soc'] = ['*' => 'plugin_soc_item_purge'];
// Display hooks
$PLUGIN_HOOKS['post_item_form']['soc'] = ['PluginSocCase', 'displayTabContentForItem'];
}
/**