Skip to content

Commit 944443d

Browse files
authored
Fix(MassiveAction): fix item2 reconciliation
1 parent 7b46cab commit 944443d

File tree

2 files changed

+161
-22
lines changed

2 files changed

+161
-22
lines changed

phpunit/functional/MassiveActionTest.php

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@
3737
use CommonDBTM;
3838
use Contract;
3939
use DbTestCase;
40+
use Location;
41+
use MassiveAction;
4042
use Notepad;
4143
use Problem;
4244
use Session;
@@ -160,6 +162,7 @@ protected function processMassiveActionsForOneItemtype(
160162
->getMock();
161163

162164
// Mock needed methods
165+
$ma->POST = $input;
163166
$ma->method('getAction')->willReturn($action_code);
164167
$ma->method('addMessage')->willReturn(null);
165168
$ma->method('getInput')->willReturn($input);
@@ -699,4 +702,124 @@ public function testaveSearchSpecificmassiveAction()
699702
);
700703
}
701704
}
705+
706+
public function testProcessMassiveActionsForOneItemtype_updateDropdownOrCommonDBConnexity()
707+
{
708+
$this->login();
709+
710+
$provider = $this->updateDropdownOrCommonDBConnexityProvider();
711+
foreach ($provider as $row) {
712+
$item = $row['item'];
713+
$input = $row['input'];
714+
$has_right = $row['has_right'];
715+
$should_work = $row['should_work'];
716+
717+
718+
$old_session = $_SESSION['glpiactiveprofile'][Ticket::$rightname] ?? 0;
719+
if ($has_right) {
720+
$_SESSION['glpiactiveprofile'][Ticket::$rightname] = UPDATE;
721+
} else {
722+
$_SESSION['glpiactiveprofile'][Ticket::$rightname] = 0;
723+
}
724+
725+
726+
727+
// Check rights set up was successful
728+
$this->assertSame(
729+
$has_right,
730+
(bool) Session::haveRight(Ticket::$rightname, UPDATE)
731+
);
732+
733+
// Default expectation: can't run
734+
$expected_ok = 0;
735+
$expected_ko = 0;
736+
737+
// Update expectation: this item should be OK
738+
if ($should_work) {
739+
$expected_ok = 1;
740+
} else {
741+
$expected_ko = 1;
742+
}
743+
744+
// Execute action
745+
$this->processMassiveActionsForOneItemtype(
746+
"update",
747+
$item,
748+
[$item->fields['id']],
749+
$input,
750+
$expected_ok,
751+
$expected_ko,
752+
MassiveAction::class
753+
);
754+
755+
// Reset rights
756+
$_SESSION['glpiactiveprofile'][Ticket::$rightname] = $old_session;
757+
}
758+
}
759+
760+
protected function updateDropdownOrCommonDBConnexityProvider()
761+
{
762+
$ticket = new Ticket();
763+
$location = new Location();
764+
$id = $ticket->add([
765+
'name' => 'test',
766+
'content' => 'test',
767+
'entities_id' => getItemByTypeName('Entity', '_test_root_entity', true),
768+
]);
769+
$ticket->getFromDB($id);
770+
$this->assertGreaterThan(0, $id);
771+
$this->assertSame($ticket->fields['entities_id'], getItemByTypeName('Entity', '_test_root_entity', true));
772+
773+
$this->createItem(
774+
\Entity::class,
775+
[
776+
'name' => '_test_root_subentity',
777+
'entities_id' => getItemByTypeName('Entity', '_test_root_entity', true),
778+
]
779+
);
780+
781+
$location = new Location();
782+
$location_id_1 = $location->add([
783+
'name' => 'test',
784+
'entities_id' => getItemByTypeName('Entity', '_test_root_entity', true),
785+
]);
786+
$this->assertGreaterThan(0, $location_id_1);
787+
788+
$location_id_2 = $location->add([
789+
'name' => 'test_sub',
790+
'entities_id' => getItemByTypeName('Entity', '_test_root_subentity', true),
791+
]);
792+
$this->assertGreaterThan(0, $location_id_2);
793+
794+
return [
795+
[
796+
// Should work
797+
'item' => $ticket,
798+
'input' => [
799+
'locations_id' => $location_id_1,
800+
'search_options' =>
801+
[
802+
$ticket->getType() => 83,
803+
],
804+
'field' => 'locations_id',
805+
],
806+
'has_right' => true,
807+
'should_work' => true,
808+
],
809+
[
810+
// Should not work
811+
'item' => $ticket,
812+
'input' => [
813+
'locations_id' => $location_id_2,
814+
'search_options' =>
815+
[
816+
$ticket->getType() => 83,
817+
],
818+
'field' => 'locations_id',
819+
],
820+
'has_right' => true,
821+
'should_work' => false, //not same entity
822+
],
823+
];
824+
}
702825
}

src/MassiveAction.php

Lines changed: 38 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1605,34 +1605,50 @@ public static function processMassiveActionsForOneItemtype(
16051605
/// Specific entity item
16061606
$itemtable = getTableForItemType($item->getType());
16071607
$itemtype2 = getItemTypeForTable($searchopt[$index]["table"]);
1608-
if ($item2 = getItemForItemtype($itemtype2)) {
1609-
if (
1610-
($index != 80) // No entities_id fields
1611-
&& ($searchopt[$index]["table"] != $itemtable)
1612-
&& $item2->isEntityAssign()
1613-
&& $item->isEntityAssign()
1614-
) {
1615-
if ($item2->getFromDB($input[$input["field"]])) {
1616-
if (
1617-
isset($item2->fields["entities_id"])
1618-
&& ($item2->fields["entities_id"] >= 0)
1619-
) {
1608+
1609+
foreach ($ids as $key) {
1610+
1611+
if ($item2 = getItemForItemtype($itemtype2)) {
1612+
if (
1613+
($index != 80) // No entities_id fields
1614+
&& ($searchopt[$index]["table"] != $itemtable)
1615+
&& $item2->isEntityAssign()
1616+
&& $item->isEntityAssign()
1617+
) {
1618+
$related_item = null;
1619+
// Case 1: The modified field is a foreign key (ex : locations_id)
1620+
if (isForeignKeyField($input["field"])) {
1621+
// Attempt to load the related object using its ID (from the input value)
1622+
if ($item2->getFromDB($input[$input["field"]])) {
1623+
$related_item = $item2;
1624+
}
1625+
// Case 2: The field is not a foreign key, but the target class supports connexity (relations)
1626+
// Use getConnexityItem() to dynamically resolve the related object based on the main itemtype and id (items_id)
1627+
} elseif (is_a($item2, CommonDBConnexity::class, true)) {
1628+
$related_item = $item2->getConnexityItem($item->getType(), $key);
1629+
}
1630+
1631+
if (!is_null($related_item)) {
16201632
if (
1621-
isset($item2->fields["is_recursive"])
1622-
&& $item2->fields["is_recursive"]
1633+
isset($related_item->fields["entities_id"])
1634+
&& ($related_item->fields["entities_id"] >= 0)
16231635
) {
1624-
$link_entity_type = getSonsOf(
1625-
"glpi_entities",
1626-
$item2->fields["entities_id"]
1627-
);
1628-
} else {
1629-
$link_entity_type[] = $item2->fields["entities_id"];
1636+
if (
1637+
isset($related_item->fields["is_recursive"])
1638+
&& $related_item->fields["is_recursive"]
1639+
) {
1640+
$link_entity_type = getSonsOf(
1641+
"glpi_entities",
1642+
$related_item->fields["entities_id"]
1643+
);
1644+
} else {
1645+
$link_entity_type[] = $related_item->fields["entities_id"];
1646+
}
16301647
}
16311648
}
16321649
}
16331650
}
1634-
}
1635-
foreach ($ids as $key) {
1651+
16361652
if (
16371653
$item->canEdit($key)
16381654
&& $item->canMassiveAction(

0 commit comments

Comments
 (0)