Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,3 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).

## [unreleased]


86 changes: 86 additions & 0 deletions src/Config.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
use Entity;
use Glpi\Application\View\TemplateRenderer;
use Migration;
use Plugin;
use Session;

class Config extends CommonDBTM
Expand Down Expand Up @@ -192,6 +193,90 @@ public static function getSelectableActorGroup(): array
];
}

/**
* Escalade provides the same feature ("Use the technician's group") with a
* global configuration, while this plugin configures it per entity. When the
* Escalade option is effectively enabled, it takes precedence over ours.
*/
public static function isTechnicianGroupHandledByEscalade(): bool
Comment thread
Lainow marked this conversation as resolved.
{
if (!Plugin::isPluginActive('escalade')) {
return false;
}

$escalade_config = self::getEscaladeConfig();
if ($escalade_config === null) {
return false;
}

// The main option only selects which groups are used: the feature stays
// inert unless it is also enabled on creation and/or on modification.
if ((int) ($escalade_config['use_assign_user_group'] ?? 0) === 0) {
return false;
}

// Older Escalade versions have no sub-options: the main one was enough.
$on_creation = (int) ($escalade_config['use_assign_user_group_creation'] ?? 1) !== 0;
$on_modification = (int) ($escalade_config['use_assign_user_group_modification'] ?? 1) !== 0;

// On creation, Escalade steps aside when the Behaviors plugin owns the
// feature (see PluginEscaladeTicket::assignUserGroup()).
if ($on_creation && self::isTechnicianGroupHandledByBehaviors()) {
$on_creation = false;
}

return $on_creation || $on_modification;
}

/**
* Get the Escalade configuration, from the session when available, from the
* database otherwise (CLI, tests, ...).
*
* @return array<string, mixed>|null
*/
private static function getEscaladeConfig(): ?array
{
/** @var \DBmysql $DB */
global $DB;

if (isset($_SESSION['glpi_plugins']['escalade']['config']) && is_array($_SESSION['glpi_plugins']['escalade']['config'])) {
return $_SESSION['glpi_plugins']['escalade']['config'];
}

$table = 'glpi_plugin_escalade_configs';
if (!$DB->tableExists($table) || !$DB->fieldExists($table, 'use_assign_user_group')) {
return null;
}

$fields = ['use_assign_user_group'];
foreach (['use_assign_user_group_creation', 'use_assign_user_group_modification'] as $field) {
if ($DB->fieldExists($table, $field)) {
$fields[] = $field;
}
}

$escalade_config = $DB->request([
'SELECT' => $fields,
'FROM' => $table,
'LIMIT' => 1,
])->current();

return is_array($escalade_config) ? $escalade_config : null;
}

/**
* The Behaviors plugin provides the same feature too, and Escalade gives it
* precedence on ticket creation.
*/
private static function isTechnicianGroupHandledByBehaviors(): bool
{
if (!Plugin::isPluginActive('behaviors') || !class_exists(\GlpiPlugin\Behaviors\Config::class)) {
return false;
}

return (int) \GlpiPlugin\Behaviors\Config::getInstance()->getField('use_assign_user_group') !== 0;
}

public static function showForEntity(Entity $item): void
{
$moconfig = new self();
Expand All @@ -217,6 +302,7 @@ public static function showForEntity(Entity $item): void
'dropdown_options' => self::getSelectableActorGroup(),
'inheritance_labels' => $inheritance_labels,
'config_parent' => self::CONFIG_PARENT,
'escalade_takes_technician_group' => self::isTechnicianGroupHandledByEscalade(),
'params' => [
'canedit' => self::canUpdate(),
],
Expand Down
19 changes: 17 additions & 2 deletions src/Controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,12 @@ public static function useConfig(CommonDBTM $item): void
}
} elseif ($item->fields['type'] == \CommonITILActor::ASSIGN) {
if ($moconfig->fields['take_technician_group_ticket'] != 0) {
if (Config::isTechnicianGroupHandledByEscalade()) {
// Escalade handles the same feature with a global
// configuration: it takes precedence over ours, so we
// just skip our own processing.
return;
}
self::addGroupsForActorType($item, $moconfig, \CommonITILActor::ASSIGN, 'take_technician_group_ticket', 'Ticket');
}
}
Expand Down Expand Up @@ -209,6 +215,15 @@ private static function addGroupsForActorType(CommonDBTM $item, Config $moconfig

$object->getFromDB($item->fields[$idField]);

// Escalade reacts to every technician group assignment: it would keep only
// the last group added and unassign the technicians. This flag asks it to
// skip its own processing for the assignments we make here, which also means
// no group cleanup, no escalation history entry and no automatic status
// change on its side.
$escalade_options = $groupClass === Group_Ticket::class
? ['_plugin_escalade_rules_only' => true]
: [];

$actors = $object->getActorsForType($actorType);
foreach ($actors as $actor) {
if (!is_array($actor) || !isset($actor['itemtype']) || $actor['itemtype'] !== 'User') {
Expand All @@ -229,7 +244,7 @@ private static function addGroupsForActorType(CommonDBTM $item, Config $moconfig
];

if (!$t_group->getFromDBByCrit($criteria)) {
$t_group->add($criteria);
$t_group->add($criteria + $escalade_options);
}
} else {
// Use all groups of the user
Expand All @@ -250,7 +265,7 @@ private static function addGroupsForActorType(CommonDBTM $item, Config $moconfig
];

if (!$t_group->getFromDBByCrit($criteria)) {
$t_group->add($criteria);
$t_group->add($criteria + $escalade_options);
}
}
}
Expand Down
12 changes: 11 additions & 1 deletion templates/config.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,16 @@
{% set dropdown_options_with_inherit = inherit_option + dropdown_options %}
{% set cell_options = {'no_label': true, 'field_class': 'col-12'} %}

{# Escalade owns the same feature with a global configuration: our per-entity option is then inoperative #}
{% set escalade_takes_technician_group = escalade_takes_technician_group|default(false) %}
{% set escalade_technician_group_warning %}
{% if escalade_takes_technician_group %}
<div class="text-warning small mt-1">
<i class="ti ti-alert-triangle me-1"></i>{{ __('The "Use the technician\'s group" option from Escalade is enabled and takes precedence over this one.', 'moreoptions') }}
</div>
{% endif %}
{% endset %}

<div class="asset">
<form action="{{ path('plugins/moreoptions/front/config.form.php') }}" method="post">
{% set item_has_pictures = item.hasItemtypeOrModelPictures() %}
Expand Down Expand Up @@ -81,7 +91,7 @@
</tr>
<tr>
<td>{{ __('Take the technician group', 'moreoptions') }}</td>
<td>{{ fields.dropdownArrayField('take_technician_group_ticket', item.fields['take_technician_group_ticket'], dropdown_options_with_inherit, '', cell_options|merge({'add_field_html': inheritance_labels['take_technician_group_ticket']|default(null)})) }}</td>
<td>{{ fields.dropdownArrayField('take_technician_group_ticket', item.fields['take_technician_group_ticket'], dropdown_options_with_inherit, '', cell_options|merge({'disabled': escalade_takes_technician_group, 'add_field_html': (inheritance_labels['take_technician_group_ticket']|default('')) ~ escalade_technician_group_warning})) }}</td>
<td>{{ fields.dropdownArrayField('take_technician_group_change', item.fields['take_technician_group_change'], dropdown_options_with_inherit, '', cell_options|merge({'add_field_html': inheritance_labels['take_technician_group_change']|default(null)})) }}</td>
<td>{{ fields.dropdownArrayField('take_technician_group_problem', item.fields['take_technician_group_problem'], dropdown_options_with_inherit, '', cell_options|merge({'add_field_html': inheritance_labels['take_technician_group_problem']|default(null)})) }}</td>
</tr>
Expand Down