From 61465b802d156728ec6582db08974f3b43ba4512 Mon Sep 17 00:00:00 2001 From: Rom1-B <8530352+Rom1-B@users.noreply.github.com> Date: Wed, 14 Oct 2026 14:10:43 +0200 Subject: [PATCH] Fix: return Yes/No field values as integers in search --- CHANGELOG.md | 1 + inc/container.class.php | 9 ++++-- tests/Units/ContainerTest.php | 52 +++++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c5196162..f443e1aa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Fix mandatory fields of a block hidden by its display conditions blocking the save of an item - Fix fields values updates not applying the expected checks in some cases +- Fix `Yes/No` field values returned as strings instead of integers in search results ## [1.24.6] - 2026-10-06 diff --git a/inc/container.class.php b/inc/container.class.php index 41822731..5f1f615c 100644 --- a/inc/container.class.php +++ b/inc/container.class.php @@ -2571,9 +2571,12 @@ public static function getAddSearchOptions($itemtype, $containers_id = false) && !in_array($data['type'], ['dropdown', 'glpi_item'], true) && !preg_match('/^dropdown-.+$/i', (string) $data['type']) ) { - $default_expression = in_array($data['type'], ['date', 'datetime'], true) && $data['default_value'] === 'now' - ? QueryFunction::now() - : new QueryExpression($DB::quoteValue($data['default_value'])); + $default_expression = match (true) { + in_array($data['type'], ['date', 'datetime'], true) && $data['default_value'] === 'now' => QueryFunction::now(), + // a quoted default would make COALESCE return a string instead of the INT column type + $data['type'] === 'yesno' => new QueryExpression((string) (int) $data['default_value']), + default => new QueryExpression($DB::quoteValue($data['default_value'])), + }; $opt[$i]['computation'] = QueryFunction::coalesce([ 'TABLE.' . $data['field_name'], diff --git a/tests/Units/ContainerTest.php b/tests/Units/ContainerTest.php index 6104bd40..c51a5259 100644 --- a/tests/Units/ContainerTest.php +++ b/tests/Units/ContainerTest.php @@ -623,8 +623,60 @@ public function testSearchoptionsShowsDefaultValueFieldWithoutAnyRow( '/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/', (string) $row['raw']['ITEM_Ticket_' . $so_id], ); + } elseif ($type === 'yesno') { + $this->assertSame((int) $default_value, $row['raw']['ITEM_Ticket_' . $so_id]); } else { $this->assertSame($default_value, $row['raw']['ITEM_Ticket_' . $so_id]); } } + + public function testSearchoptionsKeepsYesnoStoredValueAsInteger(): void + { + $this->login(); + $entities_id = $_SESSION['glpiactive_entity']; + + $container = $this->createFieldContainer([ + 'label' => 'Search Yesno Container', + 'type' => 'dom', + 'itemtypes' => [Ticket::class], + 'is_active' => 1, + 'entities_id' => $entities_id, + 'is_recursive' => 1, + ]); + + $field = $this->createField([ + 'label' => 'Search Yesno Field', + 'type' => 'yesno', + PluginFieldsContainer::getForeignKeyField() => $container->getID(), + 'ranking' => 1, + 'is_active' => 1, + 'is_readonly' => 0, + 'default_value' => '0', + ]); + + // Ticket created after the field, so its row stores the default value + $ticket = $this->createItem(Ticket::class, [ + 'name' => 'Search yesno ticket ' . $this->getUniqueString(), + 'content' => 'Test', + 'entities_id' => $entities_id, + ]); + $this->assertSame(0, $this->getDefaultValueStored($ticket, $container, $field->fields['name'])); + + $so_id = PluginFieldsField::SEARCH_OPTION_STARTING_INDEX + $field->getID(); + $data = Search::getDatas( + Ticket::class, + [ + 'is_deleted' => 0, + 'start' => 0, + 'criteria' => [ + ['field' => 'view', 'searchtype' => 'contains', 'value' => $ticket->fields['name']], + ], + ], + [$so_id], + ); + + $this->assertSame(1, $data['data']['totalcount']); + $row = current($data['data']['rows']); + $this->assertSame(0, $row['raw']['ITEM_Ticket_' . $so_id]); + } }