diff --git a/install/migrations/update_10.0.10_to_10.0.11.php b/install/migrations/update_10.0.10_to_10.0.11.php new file mode 100644 index 00000000000..31a63979fca --- /dev/null +++ b/install/migrations/update_10.0.10_to_10.0.11.php @@ -0,0 +1,68 @@ +. + * + * --------------------------------------------------------------------- + */ + +/** + * Update from 10.0.10 to 10.0.11 + * + * @return bool for success (will die for most error) + **/ +function update10010to10011() +{ + global $DB, $migration; + + $updateresult = true; + $ADDTODISPLAYPREF = []; + $DELFROMDISPLAYPREF = []; + $update_dir = __DIR__ . '/update_10.0.10_to_10.0.11/'; + + //TRANS: %s is the number of new version + $migration->displayTitle(sprintf(__('Update to %s'), '10.0.11')); + $migration->setVersion('10.0.11'); + + $update_scripts = scandir($update_dir); + foreach ($update_scripts as $update_script) { + if (preg_match('/\.php$/', $update_script) !== 1) { + continue; + } + require $update_dir . $update_script; + } + + // ************ Keep it at the end ************** + $migration->updateDisplayPrefs($ADDTODISPLAYPREF, $DELFROMDISPLAYPREF); + + $migration->executeMigration(); + + return $updateresult; +} diff --git a/install/migrations/update_10.0.10_to_10.0.11/pendingreason.php b/install/migrations/update_10.0.10_to_10.0.11/pendingreason.php new file mode 100644 index 00000000000..f161e3aedad --- /dev/null +++ b/install/migrations/update_10.0.10_to_10.0.11/pendingreason.php @@ -0,0 +1,44 @@ +. + * + * --------------------------------------------------------------------- + */ + +/** + * @var DB $DB + * @var Migration $migration + */ + + /* Add `previous_status` to glpi_pendingreasons_items */ +if (!$DB->fieldExists('glpi_pendingreasons_items', 'previous_status')) { + $migration->addField('glpi_pendingreasons_items', 'previous_status', "int DEFAULT NULL"); +} diff --git a/install/migrations/update_10.0.10_to_10.0.11/refusedequipment.php b/install/migrations/update_10.0.10_to_10.0.11/refusedequipment.php new file mode 100644 index 00000000000..a041da33878 --- /dev/null +++ b/install/migrations/update_10.0.10_to_10.0.11/refusedequipment.php @@ -0,0 +1,53 @@ +. + * + * --------------------------------------------------------------------- + */ + +/** + * @var DB $DB + * @var Migration $migration + */ + +$migration->changeField( + RefusedEquipment::getTable(), + 'ip', + 'ip', + "text" +); + +$migration->changeField( + RefusedEquipment::getTable(), + 'mac', + 'mac', + "text" +); diff --git a/install/mysql/glpi-empty.sql b/install/mysql/glpi-empty.sql index 23dbf98ff31..8795413e092 100644 --- a/install/mysql/glpi-empty.sql +++ b/install/mysql/glpi-empty.sql @@ -8992,8 +8992,8 @@ CREATE TABLE `glpi_refusedequipments` ( `name` varchar(255) DEFAULT NULL, `itemtype` varchar(100) DEFAULT NULL, `entities_id` int unsigned NOT NULL DEFAULT '0', - `ip` varchar(255) DEFAULT NULL, - `mac` varchar(255) DEFAULT NULL, + `ip` text, + `mac` text, `rules_id` int unsigned NOT NULL DEFAULT '0', `method` varchar(255) DEFAULT NULL, `serial` varchar(255) DEFAULT NULL, @@ -9098,6 +9098,7 @@ CREATE TABLE `glpi_pendingreasons_items` ( `followups_before_resolution` int NOT NULL DEFAULT '0', `bump_count` int NOT NULL DEFAULT '0', `last_bump_date` timestamp NULL DEFAULT NULL, + `previous_status` int DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `unicity` (`items_id`,`itemtype`), KEY `pendingreasons_id` (`pendingreasons_id`), diff --git a/src/Features/ParentStatus.php b/src/Features/ParentStatus.php index 74f5d750e63..92dbd2451f2 100644 --- a/src/Features/ParentStatus.php +++ b/src/Features/ParentStatus.php @@ -65,6 +65,7 @@ public function updateParentStatus(CommonITILObject $parentitem, array $input): 'pendingreasons_id' => $input['pendingreasons_id'] ?? 0, 'followup_frequency' => $input['followup_frequency'] ?? 0, 'followups_before_resolution' => $input['followups_before_resolution'] ?? 0, + 'previous_status' => $parentitem->fields['status'], ]); PendingReason_Item::createForItem($this, [ 'pendingreasons_id' => $input['pendingreasons_id'] ?? 0, diff --git a/src/PendingReason_Item.php b/src/PendingReason_Item.php index dc44374e4ec..66f0e016960 100644 --- a/src/PendingReason_Item.php +++ b/src/PendingReason_Item.php @@ -331,7 +331,6 @@ public static function isLastTimelineItem(CommonDBTM $timeline_item): bool */ public static function handleTimelineEdits(CommonDBTM $timeline_item): array { - if (self::getForItem($timeline_item)) { // Event was already marked as pending @@ -360,14 +359,17 @@ public static function handleTimelineEdits(CommonDBTM $timeline_item): array } } } else if (!$timeline_item->input['pending'] ?? 1) { - // No longer pending, remove pending data - self::deleteForItem($timeline_item->input["_job"]); - self::deleteForItem($timeline_item); - // Change status of parent if needed if ($timeline_item->input["_job"]->fields['status'] == CommonITILObject::WAITING) { - $timeline_item->input['_status'] = CommonITILObject::ASSIGNED; + // get previous stored status for parent + if ($parent_pending = self::getForItem($timeline_item->input["_job"])) { + $timeline_item->input['_status'] = $parent_pending->fields['previous_status'] ?? CommonITILObject::ASSIGNED; + } } + + // No longer pending, remove pending data + self::deleteForItem($timeline_item->input["_job"]); + self::deleteForItem($timeline_item); } } else { // Not pending yet; did it change ? @@ -380,6 +382,7 @@ public static function handleTimelineEdits(CommonDBTM $timeline_item): array 'pendingreasons_id' => $timeline_item->input['pendingreasons_id'], 'followup_frequency' => $timeline_item->input['followup_frequency'] ?? 0, 'followups_before_resolution' => $timeline_item->input['followups_before_resolution'] ?? 0, + 'previous_status' => $timeline_item->input["_job"]->fields['status'] ]); self::createForItem($timeline_item, [ 'pendingreasons_id' => $timeline_item->input['pendingreasons_id'], diff --git a/tests/functional/PendingReason.class.php b/tests/functional/PendingReason.class.php index 775323a9904..1c6bb25d94f 100644 --- a/tests/functional/PendingReason.class.php +++ b/tests/functional/PendingReason.class.php @@ -382,4 +382,72 @@ public function testAddPendingFollowupOnAlreadyPending(): void $p_item = PendingReason_Item::getForItem($ticket); $this->boolean($p_item)->isFalse(); } + + /** + * Remove pending from timeline item should delete any linked + * PendingReason_Item objects and restore previous status + */ + public function testRemovePendingAndRevertStatus(): void + { + $this->login(); + $entity = getItemByTypeName('Entity', '_test_root_entity', true); + + // Create a pending reason and a ticket for our tests + $pending_reason = $this->createItem('PendingReason', [ + 'entities_id' => $entity, + 'name' => 'Pending reason 1', + 'followup_frequency' => 604800, + 'followups_before_resolution' => 3, + ]); + + foreach ( + [ + Ticket::class => CommonITILObject::ASSIGNED, + Change::class => CommonITILObject::EVALUATION, + Problem::class => CommonITILObject::OBSERVED + ] as $itemtype => $status + ) { + $item = $this->createItem($itemtype, [ + 'name' => $itemtype, + 'content' => "test " . $itemtype, + 'status' => $status, + '_users_id_requester' => getItemByTypeName('User', 'post-only', true), + '_users_id_assign' => getItemByTypeName('User', TU_USER, true), + 'entities_id' => $entity + ]); + + // Set the item as pending with a reason + $followup = $this->createItem('ITILFollowup', [ + 'itemtype' => $item->getType(), + 'items_id' => $item->getID(), + 'content' => 'Followup with pending reason', + 'pending' => true, + 'pendingreasons_id' => $pending_reason->getID(), + 'followup_frequency' => 604800, + 'followups_before_resolution' => 3, + ], ['pending', 'pendingreasons_id', 'followup_frequency', 'followups_before_resolution']); + + // Check that pending reason is applied to parent item + $p_item = PendingReason_Item::getForItem($item); + $this->integer($p_item->fields['pendingreasons_id'])->isEqualTo($pending_reason->getID()); + $this->integer($p_item->fields['followup_frequency'])->isEqualTo(604800); + $this->integer($p_item->fields['followups_before_resolution'])->isEqualTo(3); + $this->integer($p_item->fields['previous_status'])->isEqualTo($status); + + // Update followup and unset pending + $this->boolean($followup->update([ + 'id' => $followup->getID(), + 'content' => $followup->fields['content'], + 'pending' => false, + ]))->isTrue(); + + // Check that pending reason no longer exist + $p_item = PendingReason_Item::getForItem($item); + $this->boolean($p_item)->isFalse(); + + // Reload / Check that original status is set + $item->getFromDB($item->getID()); + $this->integer($item->fields['status'])->isEqualTo($status); + } + } }