diff --git a/CHANGELOG.md b/CHANGELOG.md index 18dfb309..f1418224 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Fixed - Fix error when submitting a form with an hidden question of type `Field` +- Fixed a bug where a field was deleted when at least one question in a form was linked to another field ## [1.23.4] - 2026-03-26 diff --git a/inc/field.class.php b/inc/field.class.php index 9a0da95b..6ff05e1d 100644 --- a/inc/field.class.php +++ b/inc/field.class.php @@ -355,9 +355,10 @@ public function pre_deleteItem() $question = new Question(); $found = $question->find([ 'type' => PluginFieldsQuestionType::class, - $this->fields['id'] => new QueryExpression(sprintf( - "JSON_VALUE(%s, '$.field_id')", + new QueryExpression(sprintf( + "JSON_VALUE(%s, '$.field_id') = %s", DBmysql::quoteName('extra_data'), + DBmysql::quoteValue((int) $this->fields['id']), )), ]); if (!empty($found)) { diff --git a/tests/Units/FieldQuestionTypeTest.php b/tests/Units/FieldQuestionTypeTest.php index 50dd95e9..afccf7f6 100644 --- a/tests/Units/FieldQuestionTypeTest.php +++ b/tests/Units/FieldQuestionTypeTest.php @@ -188,6 +188,60 @@ public function testFieldsQuestionSubmitEmptyDropdown(): void ]); } + public function testFieldDeletionWhenUsedInForm(): void + { + $this->login(); + + // Arrange: create form with Field question + $builder = new FormBuilder("My form"); + $builder->addQuestion( + "My question", + PluginFieldsQuestionType::class, + extra_data: json_encode($this->getFieldExtraDataConfig('glpi_item')), + ); + $this->createForm($builder); + + // Act: try to delete field + $response = $this->fields['glpi_item']->delete($this->fields['glpi_item']->fields); + + // Assert: deletion is blocked with appropriate message + $this->assertFalse($response); + $this->hasSessionMessageThatContains('The field "GLPI Item" cannot be deleted because it is used in a form question', ERROR); + } + + public function testFieldDeletionWhenNotUsedInForm(): void + { + $this->login(); + + // Act: try to delete field + $response = $this->fields['glpi_item']->delete($this->fields['glpi_item']->fields); + + // Assert: deletion is successful + $this->assertTrue($response); + $this->hasNoSessionMessage(ERROR); + } + + public function testFieldDeletionWhenAnotherFieldUsedInForm(): void + { + $this->login(); + + // Arrange: create form with Field question using dropdown field + $builder = new FormBuilder("My form"); + $builder->addQuestion( + "My question", + PluginFieldsQuestionType::class, + extra_data: json_encode($this->getFieldExtraDataConfig('dropdown')), + ); + $this->createForm($builder); + + // Act: try to delete glpi_item field which isn't used in form but exists + $response = $this->fields['glpi_item']->delete($this->fields['glpi_item']->fields); + + // Assert: deletion is successful and not blocked by the fact that another field is used in form + $this->assertTrue($response); + $this->hasNoSessionMessage(ERROR); + } + public function testGetConditionHandlersForDropdownFieldIncludesItemHandlers(): void { $question_type = new PluginFieldsQuestionType();