Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
d2a048e
Fix header
Lainow Sep 15, 2025
da9563e
Add units tests and PR template
Lainow Sep 15, 2025
5dcb974
Update tests/units/ConfigTest.php
Lainow Sep 15, 2025
2b7ae74
Fix comments
Lainow Sep 15, 2025
95f0cd3
Fix units tests
Lainow Sep 15, 2025
4f2b093
Fix units tests
Lainow Sep 15, 2025
ca8b5c6
Fix phpstan
Lainow Sep 15, 2025
746ad07
Fix phpstan
Lainow Sep 15, 2025
f53756f
Fix phpstan and gitignore
Lainow Sep 16, 2025
bb315c9
Fix phpstan
Lainow Sep 16, 2025
4365e83
Fix phpstan
Lainow Sep 16, 2025
d51bbb3
Fix phpstan
Lainow Sep 16, 2025
08be56e
Fix phpstan
Lainow Sep 16, 2025
71ee797
Remove tests files
Lainow Sep 16, 2025
c84656d
Assign item group to technician group
Lainow Sep 18, 2025
f4e7aa4
Add mandatory field to change and problem
Lainow Sep 18, 2025
1f0d0d9
Add index
Lainow Sep 18, 2025
296e37e
Fix units tests
Lainow Sep 18, 2025
f12a2d2
Implement suggestions
Lainow Sep 18, 2025
f4becd5
Implement suggestions
Lainow Sep 18, 2025
9db8fec
Update src/Controller.php
Lainow Sep 22, 2025
298fa17
Implement assign technical group ans manager when category changed
Lainow Sep 22, 2025
f660911
Fix phpstan
Lainow Sep 23, 2025
3fcee53
Add recursivity
Lainow Sep 25, 2025
d305879
Fix lints
Lainow Sep 25, 2025
8e2674c
Fix php cs
Lainow Sep 25, 2025
20bbe93
FIx php units
Lainow Sep 25, 2025
4eec0e3
Merge branch 'main' into fix-recursivity
Lainow Oct 2, 2025
2c83424
Fix lint
Lainow Oct 2, 2025
7fb0d2e
Fix units tests
Lainow Oct 6, 2025
4c90d0b
Apply suggestions from code review
Lainow Oct 6, 2025
627def4
Fix units tests
Lainow Oct 6, 2025
8022516
Use getConfig
Lainow Oct 7, 2025
1a20c84
Update src/Config.php
Lainow Nov 13, 2025
0c0fe50
Fix units tests
Lainow Nov 27, 2025
f235b89
Fix units tests
Lainow Nov 27, 2025
edabf7a
Use createItem and updateItem
Lainow Nov 27, 2025
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
69 changes: 50 additions & 19 deletions src/Config.php
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ public static function preItemUpdate(CommonDBTM $item): CommonDBTM
public static function getItilConfigFields(): array
{
return [
'use_parent_entity',
'take_item_group_ticket',
'take_item_group_change',
'take_item_group_problem',
Expand Down Expand Up @@ -169,31 +170,28 @@ public static function getSelectableActorGroup(): array

public static function showForEntity(Entity $item): void
{
// $parents = getAncestorsOf(Entity::getTable(), $item->getID());
// if (!empty($parents)) {
// foreach ($parents as $parent) {
// $pconfig = new Config();
// $pconfig->getFromDBByCrit([
// 'entities_id' => $parent,
// ]);
// if ($pconfig->getField('is_active') == 1) {
// $pentity = $parent;
// }
// }
// $csconfig = new self();
// $csconfig->getFromDBByCrit([
// 'entities_id' => $pentity ?? 0,
// ]);
// }
$moconfig = new self();
$moconfig->getFromDBByCrit([
'entities_id' => $item->getID(),
]);

// Get effective configuration to show which entity's config is actually used
$effectiveConfig = self::getConfig($item->getID(), true);
$parentEntityInfo = null;

if (($moconfig->fields['use_parent_entity'] ?? false) && ($effectiveConfig->fields['entities_id'] != $item->getID())) {
$parentEntity = new Entity();
if ($parentEntity->getFromDB($effectiveConfig->fields['entities_id'])) {
$parentEntityInfo = $parentEntity->getName();
}
}

TemplateRenderer::getInstance()->display(
'@moreoptions/config.html.twig',
[
'item' => $moconfig,
'dropdown_options' => self::getSelectableActorGroup(),
'parent_entity_info' => $parentEntityInfo,
'params' => [
'canedit' => true,
],
Expand All @@ -215,12 +213,34 @@ public static function addConfig(CommonDBTM $item): void
]);
}

public static function getCurrentConfig(): self
/**
* Get configuration for an entity
*
* @param int|null $entityId Entity ID (null = current active entity)
* @param bool $useInheritance Whether to follow parent entity inheritance (default: true)
* @return self
*/
public static function getConfig(?int $entityId = null, bool $useInheritance = true): self
{
// Use current entity if not specified
if ($entityId === null) {
$entityId = Session::getActiveEntity();
}

$moconfig = new self();
$moconfig->getFromDBByCrit([
'entities_id' => Session::getActiveEntity(),
'entities_id' => $entityId,
]);

// If inheritance is enabled, use_parent_entity is set, and we're not at root entity
if ($useInheritance && ($moconfig->fields['use_parent_entity'] ?? false) && $entityId > 0) {
$entity = new Entity();
if ($entity->getFromDB($entityId)) {
$parentId = $entity->fields['entities_id'];
return self::getConfig($parentId, true);
}
}

return $moconfig;
}

Expand All @@ -235,7 +255,8 @@ public static function install(Migration $migration): void
`id` int unsigned NOT NULL AUTO_INCREMENT,
`is_active` tinyint NOT NULL DEFAULT '1',
`entities_id` int unsigned NOT NULL DEFAULT '0',
`take_item_group_ticket` tinyint NOT NULL DEFAULT '0',
`use_parent_entity` tinyint NOT NULL DEFAULT '0',
`take_item_group_ticket` tinyint NOT NULL DEFAULT '-2',
`take_item_group_change` tinyint NOT NULL DEFAULT '0',
`take_item_group_problem` tinyint NOT NULL DEFAULT '0',
`take_requester_group_ticket` int unsigned NOT NULL DEFAULT '0',
Expand Down Expand Up @@ -280,6 +301,16 @@ public static function install(Migration $migration): void
$DB->doQuery($query);
}

// Migration: Add use_parent_entity column if it doesn't exist
if (!$DB->fieldExists($table, 'use_parent_entity')) {
$migration->displayMessage("Adding use_parent_entity field to $table");
$migration->addField($table, 'use_parent_entity', 'tinyint', [
'after' => 'entities_id',
'value' => 0,
'nodefault' => false,
]);
}

$entities = new Entity();
foreach ($entities->find() as $entity) {
if (is_array($entity) && isset($entity['id'])) {
Expand Down
15 changes: 6 additions & 9 deletions src/Controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,7 @@ public static function useConfig(CommonDBTM $item): void
if ($item->fields['type'] == \CommonITILActor::OBSERVER) {
return;
}
$moconfig = new Config();
$moconfig->getFromDBByCrit([
'entities_id' => Session::getActiveEntity(),
]);
$moconfig = Config::getConfig();

if ($moconfig->fields['is_active'] != 1) {
return;
Expand Down Expand Up @@ -134,7 +131,7 @@ public static function useConfig(CommonDBTM $item): void

public static function addItemGroups(CommonDBTM $item): void
{
$conf = Config::getCurrentConfig();
$conf = Config::getConfig();
if ($conf->fields['is_active'] != 1) {
return;
}
Expand Down Expand Up @@ -307,7 +304,7 @@ public static function beforeCloseITILObject(CommonITILObject $item): void

public static function preventClosure(CommonDBTM $item): void
{
$conf = Config::getCurrentConfig();
$conf = Config::getConfig();
if ($conf->fields['is_active'] != 1) {
return;
}
Expand Down Expand Up @@ -344,7 +341,7 @@ public static function preventClosure(CommonDBTM $item): void

public static function requireFieldsToClose(CommonITILObject $item): void
{
$conf = Config::getCurrentConfig();
$conf = Config::getConfig();
if ($conf->fields['is_active'] != 1) {
return;
}
Expand Down Expand Up @@ -436,7 +433,7 @@ public static function requireFieldsToClose(CommonITILObject $item): void

public static function checkTaskRequirements(CommonDBTM $item): CommonDBTM
{
$conf = Config::getCurrentConfig();
$conf = Config::getConfig();
if ($conf->fields['is_active'] != 1) {
return $item;
}
Expand Down Expand Up @@ -477,7 +474,7 @@ public static function checkTaskRequirements(CommonDBTM $item): CommonDBTM

public static function updateItemActors(CommonITILObject $item): CommonITILObject
{
$conf = Config::getCurrentConfig();
$conf = Config::getConfig();
if ($conf->fields['is_active'] != 1) {
return $item;
}
Expand Down
36 changes: 36 additions & 0 deletions templates/config.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,19 @@
__('Active on this entity', 'moreoptions')
) }}

{% if item.fields['entities_id'] != 0 %}
{{ fields.checkboxField(
'use_parent_entity',
item.fields['use_parent_entity'],
__('Use parent entity configuration', 'moreoptions'),
{'helper': __('When enabled, this entity will inherit configuration from its parent entity', 'moreoptions')}
) }}

{% if parent_entity_info %}
{{ alerts.alert_info(__('Configuration is inherited from parent entity: %s', 'moreoptions')|format(parent_entity_info)) }}
{% endif %}
{% endif %}

<div class="moreoptions-config">
<table class="table table-hover border card-table" id="config_table">
<thead>
Expand Down Expand Up @@ -257,6 +270,29 @@

<script>
$(document).ready(function() {
// Handle use parent entity option
function toggleConfigOptions() {
const useParentEntity = document.querySelector('input[name="use_parent_entity"]');
const configDiv = document.querySelector('.moreoptions-config');

if (useParentEntity && configDiv) {
if (useParentEntity.checked) {
configDiv.style.display = 'none';
} else {
configDiv.style.display = 'block';
}
}
}

// Initialize on load
toggleConfigOptions();

// Listen for changes
const useParentEntityCheckbox = document.querySelector('input[name="use_parent_entity"]');
if (useParentEntityCheckbox) {
useParentEntityCheckbox.addEventListener('change', toggleConfigOptions);
}

// Take item group all functionality
const takeItemGroupAll = document.querySelector('input[id="take_item_group_all"]');
const takeItemGroupCheckboxes = document.querySelectorAll('input[type="checkbox"][id*="take_item_group"]');
Expand Down
41 changes: 6 additions & 35 deletions tests/MoreOptionsTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,38 +34,15 @@
namespace GlpiPlugin\Moreoptions\Tests;

use Auth;
use DbTestCase;
use GlpiPlugin\Moreoptions\Config;
use PHPUnit\Framework\TestCase;
use Session;

abstract class MoreOptionsTestCase extends TestCase
abstract class MoreOptionsTestCase extends DbTestCase

Check failure on line 41 in tests/MoreOptionsTestCase.php

View workflow job for this annotation

GitHub Actions / GLPI 11.0.x - php:8.4 - mariadb:11.4 / Continuous integration

Class GlpiPlugin\Moreoptions\Tests\MoreOptionsTestCase extends unknown class DbTestCase.

Check failure on line 41 in tests/MoreOptionsTestCase.php

View workflow job for this annotation

GitHub Actions / GLPI 11.0.x - php:8.2 - mariadb:10.6 / Continuous integration

Class GlpiPlugin\Moreoptions\Tests\MoreOptionsTestCase extends unknown class DbTestCase.
{
public const TU_USER = 'glpi';
public const TU_PASS = 'glpi';

protected function setUp(): void
{
global $DB;

// Start a transaction for each test
$DB->beginTransaction();

// Connect the test user
$this->login();

parent::setUp();
}

protected function tearDown(): void
{
global $DB;

// Rollback the transaction to clean up the database
$DB->rollback();

parent::tearDown();
}

/**
* Login with the test user
*/
Expand All @@ -79,7 +56,7 @@
Session::start();

$auth = new Auth();
$this->assertEquals($expected, $auth->login($user_name, $user_pass, $noauto));

Check failure on line 59 in tests/MoreOptionsTestCase.php

View workflow job for this annotation

GitHub Actions / GLPI 11.0.x - php:8.4 - mariadb:11.4 / Continuous integration

Call to an undefined method GlpiPlugin\Moreoptions\Tests\MoreOptionsTestCase::assertEquals().

Check failure on line 59 in tests/MoreOptionsTestCase.php

View workflow job for this annotation

GitHub Actions / GLPI 11.0.x - php:8.2 - mariadb:10.6 / Continuous integration

Call to an undefined method GlpiPlugin\Moreoptions\Tests\MoreOptionsTestCase::assertEquals().

return $auth;
}
Expand All @@ -102,8 +79,6 @@
*/
protected function createTestConfig(array $options = []): Config
{
$config = new Config();

$default_config = [
'is_active' => 1,
'entities_id' => 0,
Expand Down Expand Up @@ -132,28 +107,24 @@

$input = array_merge($default_config, $options);

$result = $config->add($input);
$this->assertGreaterThan(0, $result, 'Failed to create test config');

return $config;
return $this->createItem(Config::class, $input);

Check failure on line 110 in tests/MoreOptionsTestCase.php

View workflow job for this annotation

GitHub Actions / GLPI 11.0.x - php:8.4 - mariadb:11.4 / Continuous integration

Call to an undefined method GlpiPlugin\Moreoptions\Tests\MoreOptionsTestCase::createItem().

Check failure on line 110 in tests/MoreOptionsTestCase.php

View workflow job for this annotation

GitHub Actions / GLPI 11.0.x - php:8.2 - mariadb:10.6 / Continuous integration

Call to an undefined method GlpiPlugin\Moreoptions\Tests\MoreOptionsTestCase::createItem().
}

/**
* Update the test configuration
* @param array<string, mixed> $updates
*/
protected function updateTestConfig(Config $config, array $updates): bool
protected function updateTestConfig(Config $config, array $updates): Config
{
$input = array_merge(['id' => $config->getID()], $updates);
return $config->update($input);
return $this->updateItem(Config::class, $config->getID(), $updates);

Check failure on line 119 in tests/MoreOptionsTestCase.php

View workflow job for this annotation

GitHub Actions / GLPI 11.0.x - php:8.4 - mariadb:11.4 / Continuous integration

Call to an undefined method GlpiPlugin\Moreoptions\Tests\MoreOptionsTestCase::updateItem().

Check failure on line 119 in tests/MoreOptionsTestCase.php

View workflow job for this annotation

GitHub Actions / GLPI 11.0.x - php:8.2 - mariadb:10.6 / Continuous integration

Call to an undefined method GlpiPlugin\Moreoptions\Tests\MoreOptionsTestCase::updateItem().
}

/**
* Get the current configuration or create one
*/
protected function getCurrentConfig(): Config
{
$config = Config::getCurrentConfig();
$config = Config::getConfig();
if (empty($config->fields) || $config->isNewItem()) {
$config = $this->createTestConfig();
}
Expand Down
Loading
Loading