Skip to content

Commit fe1ea3f

Browse files
authored
add verification on key to fix error on reimport (#21669)
1 parent 9b9e54c commit fe1ea3f

File tree

3 files changed

+114
-8
lines changed

3 files changed

+114
-8
lines changed

phpunit/functional/Glpi/Inventory/Assets/ComputerTest.php

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1762,4 +1762,92 @@ public function testOsCommentRuleLocation()
17621762
$this->assertTrue($computer->getFromDB($computers_id));
17631763
$this->assertSame($locations_id, $computer->fields['locations_id']);
17641764
}
1765+
1766+
/**
1767+
* Test reimport with locked states_id field.
1768+
* This test ensures that reimporting an inventory with a locked states_id field
1769+
* does not trigger an error when accessing raw_links.
1770+
*
1771+
* Scenario:
1772+
* 1. Configure a default states_id for inventory imports
1773+
* 2. Import a computer (which receives the state from inventory configuration)
1774+
* 3. Manually change the states_id (this creates a lock on the field)
1775+
* 4. Reimport the same computer (before the fix, this caused an "Undefined array key" error)
1776+
*/
1777+
public function testReimportWithLockedStatesId()
1778+
{
1779+
// Load the test fixture
1780+
$json_str = file_get_contents(GLPI_ROOT . '/tests/fixtures/inventories/computer_locked_states_id.json');
1781+
$json = json_decode($json_str);
1782+
1783+
// Create states
1784+
$state = new \State();
1785+
$states_id_inventory = $state->add([
1786+
'name' => 'State from inventory',
1787+
'entities_id' => 0,
1788+
'is_visible_computer' => 1,
1789+
]);
1790+
$this->assertGreaterThan(0, $states_id_inventory);
1791+
1792+
$states_id_manual = $state->add([
1793+
'name' => 'State manually set',
1794+
'entities_id' => 0,
1795+
'is_visible_computer' => 1,
1796+
]);
1797+
$this->assertGreaterThan(0, $states_id_manual);
1798+
1799+
// Configure inventory to set states_id from inventory
1800+
$this->login();
1801+
$conf = new \Glpi\Inventory\Conf();
1802+
$this->assertTrue(
1803+
$conf->saveConf([
1804+
'states_id_default' => $states_id_inventory,
1805+
])
1806+
);
1807+
$this->logout();
1808+
1809+
// First import - create the computer with state from inventory
1810+
$inventory = $this->doInventory($json);
1811+
$computers_id = $inventory->getItem()->fields['id'];
1812+
$this->assertGreaterThan(0, $computers_id);
1813+
1814+
$computer = new \Computer();
1815+
$this->assertTrue($computer->getFromDB($computers_id));
1816+
// Verify the computer received the state from inventory configuration
1817+
$this->assertEquals($states_id_inventory, $computer->fields['states_id']);
1818+
1819+
// Manually update states_id to create a lock
1820+
$this->assertTrue($computer->update([
1821+
'id' => $computers_id,
1822+
'states_id' => $states_id_manual,
1823+
]));
1824+
1825+
// Verify the lock was created
1826+
$lockedfield = new \Lockedfield();
1827+
$locks = $lockedfield->find([
1828+
'itemtype' => 'Computer',
1829+
'items_id' => $computers_id,
1830+
'field' => 'states_id',
1831+
]);
1832+
$this->assertCount(1, $locks);
1833+
1834+
// Reload and verify the manual state is set
1835+
$this->assertTrue($computer->getFromDB($computers_id));
1836+
$this->assertEquals($states_id_manual, $computer->fields['states_id']);
1837+
1838+
// Reimport the same inventory - this should NOT trigger an error
1839+
$inventory = $this->doInventory($json);
1840+
1841+
// Verify the computer still exists and states_id is still the manual one (locked)
1842+
$this->assertTrue($computer->getFromDB($computers_id));
1843+
$this->assertEquals($states_id_manual, $computer->fields['states_id']);
1844+
1845+
// Verify the lock is still present
1846+
$locks = $lockedfield->find([
1847+
'itemtype' => 'Computer',
1848+
'items_id' => $computers_id,
1849+
'field' => 'states_id',
1850+
]);
1851+
$this->assertCount(1, $locks);
1852+
}
17651853
}

src/Inventory/Asset/InventoryAsset.php

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -470,14 +470,14 @@ protected function handleInput(\stdClass $value, ?CommonDBTM $item = null): arra
470470
}
471471
$known_key = md5($key . $val);
472472
if (in_array($key, $locks)) {
473-
if (isset($this->known_links[$known_key])) {
474-
$input[$key] = $this->known_links[$known_key];
475-
$input['_raw' . $key] = $this->raw_links[$known_key];
476-
} else {
477-
// If $item is new and the input key is locked, we do not want to set it using the raw value.
478-
// This is because locked fields are no longer processed or sanitized during the addition process.
479-
// For more details, see: https://github.com/glpi-project/glpi/pull/19426
480-
if (!$item->isNewItem()) {
473+
if (isset($this->raw_links[$known_key])) {
474+
if (isset($this->known_links[$known_key])) {
475+
$input[$key] = $this->known_links[$known_key];
476+
$input['_raw' . $key] = $this->raw_links[$known_key];
477+
} elseif (!$item->isNewItem()) {
478+
// If $item is new and the input key is locked, we do not want to set it using the raw value.
479+
// This is because locked fields are no longer processed or sanitized during the addition process.
480+
// For more details, see: https://github.com/glpi-project/glpi/pull/19426
481481
$input[$key] = $this->raw_links[$known_key];
482482
}
483483
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"action": "inventory",
3+
"content": {
4+
"bios": {
5+
"ssn": "LOCKED-STATES-TEST-001"
6+
},
7+
"hardware": {
8+
"chassis_type": "Desktop",
9+
"name": "test-locked-states",
10+
"uuid": "test-uuid-locked-states-001",
11+
"vmsystem": "Physical"
12+
},
13+
"versionclient": "GLPI-Agent_v1.9"
14+
},
15+
"deviceid": "test-locked-states-2025-10-28",
16+
"itemtype": "Computer",
17+
"partial": false
18+
}

0 commit comments

Comments
 (0)