3232use Glpi \DBAL \JsonFieldInterface ;
3333use Glpi \Form \Condition \ConditionHandler \ItemAsTextConditionHandler ;
3434use Glpi \Form \Condition \ConditionHandler \ItemConditionHandler ;
35+ use Glpi \Form \Condition \ConditionHandler \MultipleChoiceFromValuesConditionHandler ;
3536use Glpi \Form \Form ;
3637use Glpi \Form \Migration \FormQuestionDataConverterInterface ;
3738use Glpi \Form \Question ;
@@ -85,6 +86,43 @@ public function formatDefaultValueForDB(mixed $value): string
8586 return json_encode ($ value );
8687 }
8788
89+ #[Override]
90+ public function prepareEndUserAnswer (Question $ question , mixed $ answer ): mixed
91+ {
92+ if ($ this ->isMultipleForQuestion ($ question )) {
93+ if (isset ($ answer ['items_id ' ]) && is_array ($ answer ['items_id ' ])) {
94+ $ answer ['items_id ' ] = array_values (array_map ('intval ' , $ answer ['items_id ' ]));
95+ }
96+ }
97+
98+ return $ answer ;
99+ }
100+
101+ #[Override]
102+ public function renderAdministrationOptionsTemplate (?Question $ question ): string
103+ {
104+ $ is_multiple = $ this ->isMultipleForQuestion ($ question );
105+
106+ $ template = <<<TWIG
107+ <div class="d-flex gap-2">
108+ <label class="form-check form-switch mb-0">
109+ <input type="hidden" name="is_multiple" value="0"
110+ data-glpi-form-editor-specific-question-extra-data>
111+ <input class="form-check-input" type="checkbox" name="is_multiple"
112+ value="1" {{ is_multiple ? 'checked' : '' }}
113+ data-glpi-form-editor-specific-question-extra-data>
114+ <span class="form-check-label">{{ label }}</span>
115+ </label>
116+ </div>
117+ TWIG ;
118+
119+ $ twig = TemplateRenderer::getInstance ();
120+ return $ twig ->renderFromStringTemplate ($ template , [
121+ 'is_multiple ' => $ is_multiple ,
122+ 'label ' => __ ('Allow multiple options ' ),
123+ ]);
124+ }
125+
88126 #[Override]
89127 public function validateExtraDataInput (array $ input ): bool
90128 {
@@ -134,14 +172,17 @@ public function renderAdministrationTemplate(?Question $question): string
134172 $ default_value = json_decode ($ question ->fields ['default_value ' ], true );
135173 }
136174
175+ $ field_data = $ current_field ->fields ;
176+ $ field_data ['multiple ' ] = $ this ->isMultipleForQuestion ($ question ) ? 1 : 0 ;
177+
137178 $ twig = TemplateRenderer::getInstance ();
138179 return $ twig ->render ('@fields/question_type_administration.html.twig ' , [
139180 'question ' => $ question ,
140181 'default_value ' => $ default_value ,
141182 'selected_field_id ' => $ current_field_id ,
142183 'available_fields ' => $ available_fields ,
143184 'item ' => new Form (),
144- 'field ' => $ current_field -> fields ,
185+ 'field ' => $ field_data ,
145186 ]);
146187 }
147188
@@ -181,10 +222,13 @@ public function renderEndUserTemplate(Question $question): string
181222 }
182223 }
183224
225+ $ field_data = $ current_field ->fields ;
226+ $ field_data ['multiple ' ] = $ this ->isMultipleForQuestion ($ question ) ? 1 : 0 ;
227+
184228 $ twig = TemplateRenderer::getInstance ();
185229 return $ twig ->render ('@fields/question_type_end_user.html.twig ' , [
186230 'question ' => $ question ,
187- 'field ' => $ current_field -> fields ,
231+ 'field ' => $ field_data ,
188232 'default_value ' => $ default_value ,
189233 'item ' => new Form (),
190234 'itemtype ' => $ itemtype ,
@@ -312,7 +356,6 @@ public function getConditionHandlers(
312356 return parent ::getConditionHandlers ($ question_config );
313357 }
314358
315- // If the question is configured with a dropdown field, we add condition handlers to handle item and item as text conditions on the dropdown options
316359 $ field = PluginFieldsField::getById ($ question_config ->getFieldId ());
317360 if ($ field && str_starts_with ((string ) $ field ->fields ['type ' ], 'dropdown ' )) {
318361 if ($ field ->fields ['type ' ] == 'dropdown ' ) {
@@ -330,11 +373,28 @@ public function getConditionHandlers(
330373 new ItemAsTextConditionHandler ($ itemtype ),
331374 ],
332375 );
376+
377+ if ($ field ->fields ['multiple ' ] || $ question_config ->isMultiple ()) {
378+ $ condition_handlers [] = new MultipleChoiceFromValuesConditionHandler (
379+ $ this ->getDropdownValuesForCondition ($ itemtype )
380+ );
381+ }
333382 }
334383
335384 return $ condition_handlers ;
336385 }
337386
387+ private function getDropdownValuesForCondition (string $ itemtype ): array
388+ {
389+ $ values = [];
390+ $ item = new $ itemtype ();
391+ $ rows = $ item ->find ([], 'name ' );
392+ foreach ($ rows as $ row ) {
393+ $ values [(string ) $ row ['id ' ]] = $ row ['name ' ];
394+ }
395+ return $ values ;
396+ }
397+
338398 /**
339399 * Retrieve the default value block from the question's extra data
340400 *
@@ -375,6 +435,31 @@ public function getDefaultValueFieldId(?Question $question): ?int
375435 return $ config ->getFieldId ();
376436 }
377437
438+ private function getFieldForQuestion (Question $ question ): ?PluginFieldsField
439+ {
440+ $ field_id = $ this ->getDefaultValueFieldId ($ question );
441+ if ($ field_id === null ) {
442+ return null ;
443+ }
444+ return PluginFieldsField::getById ($ field_id ) ?: null ;
445+ }
446+
447+ private function isMultipleForQuestion (?Question $ question ): bool
448+ {
449+ if (!$ question instanceof Question) {
450+ return false ;
451+ }
452+
453+ /** @var ?PluginFieldsQuestionTypeExtraDataConfig $config */
454+ $ config = $ this ->getExtraDataConfig (json_decode ($ question ->fields ['extra_data ' ], true ) ?? []);
455+ if ($ config !== null && $ config ->isMultiple ()) {
456+ return true ;
457+ }
458+
459+ $ field = $ this ->getFieldForQuestion ($ question );
460+ return $ field !== null && (bool ) $ field ->fields ['multiple ' ];
461+ }
462+
378463 private function getAvailableBlocks (): array
379464 {
380465 $ field_container = new PluginFieldsContainer ();
0 commit comments