Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]

### Fixed

- Fix error when submitting a form with an hidden question of type `Field`

## [1.23.4] - 2026-03-26

### Fixed
Expand Down
2 changes: 1 addition & 1 deletion inc/field.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -973,7 +973,7 @@ public static function showForTab($params)
$itemtypes = PluginFieldsContainer::getUsedItemtypes($type, true);

//if no dom containers defined for this itemtype, do nothing (in_array case insensitive)
if (!in_array(strtolower((string) $item::getType()), array_map(strtolower(...), $itemtypes))) {
if (!in_array(strtolower((string) $item::getType()), array_map(strtolower(...), $itemtypes), true)) {
return;
}

Expand Down
2 changes: 1 addition & 1 deletion inc/inventory.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public static function updateInventory($params = [])
) {
$availaibleItemType = ['Computer', 'Printer', 'NetworkEquipment'];
foreach (array_keys($params['inventory_data']) as $itemtype) {
if (in_array($itemtype, $availaibleItemType)) {
if (in_array($itemtype, $availaibleItemType, true)) {
$items_id = 0;
//retrieve items id switch itemtype
switch ($itemtype) {
Expand Down
2 changes: 1 addition & 1 deletion inc/migration.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ private static function getCustomFieldsInContainerTable(

return array_filter(
$fields,
fn(string $field) => !in_array($field, $basic_fields),
fn(string $field) => !in_array($field, $basic_fields, true),
);
}
}
2 changes: 1 addition & 1 deletion inc/questiontype.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ public function formatRawAnswer(mixed $answer, Question $question): string
}

$itemtype = PluginFieldsDropdown::getClassname($current_field->fields['name']);
return implode(', ', array_map(fn($opt_id) => $itemtype::getById($opt_id)->fields['name'], $answer));
return implode(', ', array_map(fn($opt_id) => $itemtype::getById($opt_id)?->fields['name'] ?? '', $answer));
case 'yesno':
return $answer ? __('Yes') : __('No');
case 'datetime':
Expand Down
8 changes: 8 additions & 0 deletions tests/FieldTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,10 @@
namespace GlpiPlugin\Field\Tests;

use DBmysql;
use Glpi\Form\Question;
use PluginFieldsContainer;
use PluginFieldsField;
use PluginFieldsQuestionType;

trait FieldTestTrait
{
Expand All @@ -47,6 +49,12 @@ public function tearDownFieldTest(): void
// Re-login to ensure we are logged in
$this->login();

// Clean all questions that use QuestionTypeField to avoid issues with foreign key constraints when deleting fields
array_map(
fn(Question $question) => $question->delete($question->fields, true),
iterator_to_array(Question::getSeveralFromDBByCrit(['type' => PluginFieldsQuestionType::class])),
);

// Clean created containers
array_map(
fn(PluginFieldsContainer $container) => $container->delete($container->fields, true),
Expand Down
15 changes: 13 additions & 2 deletions tests/QuestionTypeTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ abstract class QuestionTypeTestCase extends DbTestCase

protected ?PluginFieldsContainer $block = null;

protected ?PluginFieldsField $field = null;
/** @var PluginFieldsField[] */
protected array $fields = [];

public function createFieldAndContainer(): void
{
Expand All @@ -61,23 +62,33 @@ public function createFieldAndContainer(): void
'entities_id' => $this->getTestRootEntity(true),
]);

$this->field = $this->createField([
$this->fields['glpi_item'] = $this->createField([
'label' => 'GLPI Item',
'type' => 'glpi_item',
PluginFieldsContainer::getForeignKeyField() => $this->block->getID(),
'ranking' => 1,
'is_active' => 1,
]);

$this->fields['dropdown'] = $this->createField([
'label' => 'Dropdown',
'type' => 'dropdown',
PluginFieldsContainer::getForeignKeyField() => $this->block->getID(),
'ranking' => 1,
'is_active' => 1,
]);
}

public function setUp(): void
{
$this->createFieldAndContainer();
parent::setUp();
}

public function tearDown(): void
{
$this->tearDownFieldTest();
parent::tearDown();
}

protected function renderFormEditor(Form $form): Crawler
Expand Down
4 changes: 3 additions & 1 deletion tests/Units/FieldQuestionTypeMigrationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@

final class FieldQuestionTypeMigrationTest extends QuestionTypeTestCase
{
public array $fields;

public static function setUpBeforeClass(): void
{
global $DB;
Expand Down Expand Up @@ -104,7 +106,7 @@ public function testFieldsQuestionIsMigrated(): void
'row' => 0,
'col' => 0,
'values' => json_encode([
'dropdown_fields_field' => $this->field->fields['name'],
'dropdown_fields_field' => $this->fields['glpi_item']->fields['name'],
'blocks_field' => $this->block->getID(),
]),
],
Expand Down
39 changes: 34 additions & 5 deletions tests/Units/FieldQuestionTypeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
use GlpiPlugin\Field\Tests\QuestionTypeTestCase;
use LogicException;
use PluginFieldsContainer;
use PluginFieldsDropdown;
use PluginFieldsField;
use PluginFieldsQuestionType;
use PluginFieldsQuestionTypeCategory;
Expand Down Expand Up @@ -117,7 +118,7 @@ public function testFieldsQuestionEditorRendering(): void
$builder->addQuestion(
"My question",
PluginFieldsQuestionType::class,
extra_data: json_encode($this->getFieldExtraDataConfig()),
extra_data: json_encode($this->getFieldExtraDataConfig('glpi_item')),
);
$form = $this->createForm($builder);

Expand All @@ -137,7 +138,7 @@ public function testFieldsQuestionHelpdeskRendering(): void
$builder->addQuestion(
"My question",
PluginFieldsQuestionType::class,
extra_data: json_encode($this->getFieldExtraDataConfig()),
extra_data: json_encode($this->getFieldExtraDataConfig('glpi_item')),
);
$form = $this->createForm($builder);

Expand All @@ -148,12 +149,40 @@ public function testFieldsQuestionHelpdeskRendering(): void
$this->assertNotEmpty($crawler->filter('[data-glpi-form-renderer-fields-question-type-specific-container]'));
}

private function getFieldExtraDataConfig(): PluginFieldsQuestionTypeExtraDataConfig
public function testFieldsQuestionSubmitEmptyDropdown(): void
{
if (!$this->block instanceof PluginFieldsContainer || !$this->field instanceof PluginFieldsField) {
$this->login();

/** @var CommonDBTM $dropdown_item */
$dropdown_item = getItemForItemtype(PluginFieldsDropdown::getClassname($this->fields['dropdown']->fields['name']));
$dropdown_ids = [];
for ($i = 1; $i <= 3; $i++) {
$dropdown_ids[] = $dropdown_item->add([
'name' => 'Option ' . $i,
]);
}

// Arrange: create form with Field question
$builder = new FormBuilder("My form");
$builder->addQuestion(
"Dropdown field question",
PluginFieldsQuestionType::class,
extra_data: json_encode($this->getFieldExtraDataConfig('dropdown')),
);
$form = $this->createForm($builder);

// Act: submit form
$this->sendFormAndGetCreatedTicket($form, [
"Dropdown field question" => '0',
]);
}

private function getFieldExtraDataConfig(string $field_name): PluginFieldsQuestionTypeExtraDataConfig
{
if (!$this->block instanceof PluginFieldsContainer || !$this->fields[$field_name] instanceof PluginFieldsField) {
throw new LogicException("Field and container must be created before getting extra data config");
}

return new PluginFieldsQuestionTypeExtraDataConfig($this->block->getID(), $this->field->getID());
return new PluginFieldsQuestionTypeExtraDataConfig($this->block->getID(), $this->fields[$field_name]->getID());
}
}