Skip to content

Commit a2dd95b

Browse files
AdrienClairembaulttrasher
authored andcommitted
Improve migration of conditions on checkboxes
1 parent 49ccae0 commit a2dd95b

File tree

3 files changed

+100
-13
lines changed

3 files changed

+100
-13
lines changed

src/Glpi/Form/Condition/ConditionHandler/MultipleChoiceFromValuesConditionHandler.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,9 @@ public function applyValueOperator(
7979
}
8080

8181
#[Override]
82-
public function convertConditionValue(string $value): int
82+
public function convertConditionValue(string $value): array
8383
{
84-
return array_search($value, $this->values, true) ?: 0;
84+
$value = array_search($value, $this->values, true) ?: 0;
85+
return [$value];
8586
}
8687
}

src/Glpi/Form/Migration/FormMigration.php

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,9 @@
6868
use Glpi\Form\Form;
6969
use Glpi\Form\FormTranslation;
7070
use Glpi\Form\Question;
71+
use Glpi\Form\QuestionType\QuestionTypeCheckbox;
72+
use Glpi\Form\QuestionType\QuestionTypeDropdown;
73+
use Glpi\Form\QuestionType\QuestionTypeDropdownExtraDataConfig;
7174
use Glpi\Form\QuestionType\QuestionTypeEmail;
7275
use Glpi\Form\QuestionType\QuestionTypeInterface;
7376
use Glpi\Form\QuestionType\QuestionTypeLongText;
@@ -189,16 +192,41 @@ private function getCreationStrategyFromLegacy(int $creation): CreationStrategy
189192
* @param QuestionTypeInterface $question_type The question type interface
190193
* @return ValueOperator|null The corresponding value operator or null if not found
191194
*/
192-
private function getValueOperatorFromLegacy(int $value_operator, mixed $value, QuestionTypeInterface $question_type): ?ValueOperator
193-
{
195+
private function getValueOperatorFromLegacy(
196+
int $value_operator,
197+
mixed $value,
198+
QuestionTypeInterface $question_type,
199+
?JsonFieldInterface $question_config,
200+
): ?ValueOperator {
194201
// String condition handler support length comparison but with a different operator
195202
$has_string_condition_handler = in_array($question_type::class, [
196203
QuestionTypeShortText::class, QuestionTypeEmail::class, QuestionTypeLongText::class,
197204
]);
198205

206+
$is_array_condition = $question_type instanceof QuestionTypeCheckbox
207+
|| (
208+
$question_type instanceof QuestionTypeDropdown
209+
&& $question_config !== null
210+
&& $question_config instanceof QuestionTypeDropdownExtraDataConfig
211+
&& $question_config->isMultipleDropdown()
212+
)
213+
;
214+
199215
return match ($value_operator) {
200-
1 => $value === "" ? ValueOperator::EMPTY : ValueOperator::EQUALS,
201-
2 => $value === "" ? ValueOperator::NOT_EMPTY : ValueOperator::NOT_EQUALS,
216+
1 => $value === ""
217+
? ValueOperator::EMPTY
218+
: (
219+
$is_array_condition
220+
? ValueOperator::CONTAINS
221+
: ValueOperator::EQUALS
222+
),
223+
2 => $value === ""
224+
? ValueOperator::NOT_EMPTY
225+
: (
226+
$is_array_condition
227+
? ValueOperator::NOT_CONTAINS
228+
: ValueOperator::NOT_EQUALS
229+
),
202230
3 => $has_string_condition_handler ? ValueOperator::LENGTH_LESS_THAN : ValueOperator::LESS_THAN,
203231
4 => $has_string_condition_handler ? ValueOperator::LENGTH_GREATER_THAN : ValueOperator::GREATER_THAN,
204232
5 => $has_string_condition_handler ? ValueOperator::LENGTH_LESS_THAN_OR_EQUALS : ValueOperator::LESS_THAN_OR_EQUALS,
@@ -1415,7 +1443,8 @@ private function processMigrationOfVisibilityConditions(): void
14151443
$value_operator = $this->getValueOperatorFromLegacy(
14161444
$raw_condition['show_condition'],
14171445
$value,
1418-
$question_type
1446+
$question_type,
1447+
$question->getExtraDataConfig()
14191448
);
14201449

14211450
if (isset($question->fields['extra_data'])) {

tests/functional/Glpi/Form/Migration/FormMigrationTest.php

Lines changed: 63 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2691,8 +2691,8 @@ public static function provideFormMigrationForSelectableQuestions(): iterable
26912691
],
26922692
'expected_conditions' => [
26932693
[
2694-
'value_operator' => ValueOperator::EQUALS,
2695-
'value' => 3, // Index of 'Option 3' in ['Option 1', 'Option 2', 'Option 3']
2694+
'value_operator' => ValueOperator::CONTAINS,
2695+
'value' => [3], // Index of 'Option 3' in ['Option 1', 'Option 2', 'Option 3']
26962696
'logic_operator' => LogicOperator::AND,
26972697
],
26982698
],
@@ -2746,13 +2746,13 @@ public static function provideFormMigrationForSelectableQuestions(): iterable
27462746
],
27472747
'expected_conditions' => [
27482748
[
2749-
'value_operator' => ValueOperator::EQUALS,
2750-
'value' => 2, // Index of 'Option 2' in ['Option 1', 'Option 2', 'Option 3']
2749+
'value_operator' => ValueOperator::CONTAINS,
2750+
'value' => [2], // Index of 'Option 2' in ['Option 1', 'Option 2', 'Option 3']
27512751
'logic_operator' => LogicOperator::AND,
27522752
],
27532753
[
2754-
'value_operator' => ValueOperator::EQUALS,
2755-
'value' => 3, // Index of 'Option 3' in ['Option 1', 'Option 2', 'Option 3']
2754+
'value_operator' => ValueOperator::CONTAINS,
2755+
'value' => [3], // Index of 'Option 3' in ['Option 1', 'Option 2', 'Option 3']
27562756
'logic_operator' => LogicOperator::OR,
27572757
],
27582758
],
@@ -3634,6 +3634,63 @@ public function testNonVisiblePrivateFormMigration(): void
36343634
);
36353635
}
36363636

3637+
public function testCheckboxesConditionsAreMigratedAsContains(): void
3638+
{
3639+
/** @var \DBmysql $DB */
3640+
global $DB;
3641+
3642+
// Arrange: create a form with a condition on a checkbox question
3643+
$id = $this->createSimpleFormcreatorForm(
3644+
name: "Form with checkboxes",
3645+
questions: [
3646+
[
3647+
'name' => 'My checkbox question',
3648+
'fieldtype' => 'checkboxes',
3649+
'values' => '["A","B","C","D"]',
3650+
],
3651+
[
3652+
'name' => 'My other question',
3653+
'fieldtype' => 'text',
3654+
'show_rule' => 2,
3655+
'_conditions' => [
3656+
[
3657+
'plugin_formcreator_questions_id' => 'My checkbox question',
3658+
'show_condition' => 1,
3659+
'show_value' => "A",
3660+
'show_logic' => 1,
3661+
],
3662+
],
3663+
],
3664+
],
3665+
);
3666+
3667+
// Act: import the form
3668+
$control_manager = FormAccessControlManager::getInstance();
3669+
$migration = new FormMigration(
3670+
db: $DB,
3671+
formAccessControlManager: $control_manager,
3672+
specificFormsIds: [$id],
3673+
);
3674+
$migration->execute();
3675+
3676+
// Assert: make sure the condition was expected as "Contains A", not
3677+
// "Equals "A".
3678+
// This might seem unintuitive but it match the behavior of formcreator
3679+
// for these questions.
3680+
$form = getItemByTypeName(Form::class, "Form with checkboxes");
3681+
$question_id = $this->getQuestionId($form, "My other question");
3682+
$question = Question::getById($question_id);
3683+
$condition = $question->getConfiguredConditionsData()[0];
3684+
$this->assertEquals(
3685+
ValueOperator::CONTAINS,
3686+
$condition->getValueOperator()
3687+
);
3688+
$this->assertEquals(
3689+
[1], // "A" will be assigned the first index, which is 1-based
3690+
$condition->getValue()
3691+
);
3692+
}
3693+
36373694
protected function createSimpleFormcreatorForm(
36383695
string $name,
36393696
array $questions,

0 commit comments

Comments
 (0)