Skip to content

Commit

Permalink
bug #5944 Fix ChoiceField when entity is enumType and no choices were…
Browse files Browse the repository at this point in the history
… given (Uplink03, Radu Cristescu)

This PR was merged into the 4.x branch.

Discussion
----------

Fix ChoiceField when entity is enumType and no choices were given

Fix ChoiceField when entity is enumType and no choices were given explicitly

## Bugs

BUG: if `setChoices` is not called on the ChoiceField, and the backing entity field is an Enum, the dropdown displays 0, 1, 2, 3, etc., because the `$choices` array ends up like this:

```
array:2 [
  0 => App\Enum\ProjectTypeEnum {
    +name: "PHP"
    +value: "php"
  }
  1 => App\Enum\ProjectTypeEnum {
    +name: "DOCKER"
    +value: "docker"
  }
]
```

BUG: Symfony Forms attempts to convert the enum to string.

## Fixes

### Fix the ChoiceConfigurator

This PR fixes the ChoiceConfigurator to behave as if `->setChoices(MyEnum::cases())` were called.

Related to commit 65a422b of PR #5879 by `@SerheyDolgushev`

### Fix the forms

Although closed, bug #5641 was not addressed by PR #5879. Without the change suggested by the original reported, the following errors are thrown:

The EDIT action of a CRUD that contains a ChoiceField with an enum:

`Object of class App\Enum\ProjectTypeEnum could not be converted to string`

The Create action of a CRUD that contains a ChoiceField with an enum (the NEW page doesn't complain until submitted):

`Expected argument of type "App\Enum\ProjectTypeEnum", "string" given at property path "type".`

<!--
Thanks for your contribution! If you are proposing a new feature that is complex,
please open an issue first so we can discuss about it.

Note: all your contributions adhere implicitly to the MIT license
-->

Commits
-------

81175ac Updated ChoiceConfiguratorTest to work with the ChoiceConfigurator fixes
8774da3 Fix ChoiceConfigurator with enums
a91ca47 Fix ChoiceField when entity is enumType and no choices have been given explicitly
  • Loading branch information
javiereguiluz committed Oct 22, 2023
2 parents d9debe4 + 81175ac commit c30a8a0
Show file tree
Hide file tree
Showing 10 changed files with 265 additions and 10 deletions.
8 changes: 8 additions & 0 deletions .idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

93 changes: 93 additions & 0 deletions .idea/EasyAdminBundle-fork.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/encodings.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/inspectionProfiles/Project_Default.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions .idea/modules.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

113 changes: 113 additions & 0 deletions .idea/php.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/symfony2.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 5 additions & 6 deletions src/Field/Configurator/ChoiceConfigurator.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,13 @@ public function configure(FieldDto $field, EntityDto $entityDto, AdminContext $c
$enumTypeClass = $field->getDoctrineMetadata()->get('enumType');
if (0 === \count($choices) && null !== $enumTypeClass && enum_exists($enumTypeClass)) {
$choices = $enumTypeClass::cases();
} elseif ($allChoicesAreEnums) {
$allChoicesAreEnums = true;
}

if ($allChoicesAreEnums) {
$processedEnumChoices = [];
foreach ($choices as $choice) {
if ($choice instanceof \BackedEnum) {
$processedEnumChoices[$choice->name] = $choice->value;
} else {
$processedEnumChoices[$choice->name] = $choice->name;
}
$processedEnumChoices[$choice->name] = $choice;
}

$choices = $processedEnumChoices;
Expand Down
18 changes: 14 additions & 4 deletions tests/Field/Configurator/ChoiceConfiguratorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,12 @@ public function testBackedEnumTypeChoices(): void
$field = ChoiceField::new(self::PROPERTY_NAME);
$field->getAsDto()->setDoctrineMetadata(['enumType' => StatusBackedEnum::class]);

$this->assertSame($this->configure($field)->getFormTypeOption('choices'), StatusBackedEnum::cases());
$formChoices = array_combine(
array_column(StatusBackedEnum::cases(), 'name'),
StatusBackedEnum::cases(),
);

$this->assertSame($this->configure($field)->getFormTypeOption('choices'), $formChoices);
}

public function testBackedEnumChoices(): void
Expand All @@ -63,7 +68,7 @@ public function testBackedEnumChoices(): void

$expected = [];
foreach (StatusBackedEnum::cases() as $case) {
$expected[$case->name] = $case->value;
$expected[$case->name] = $case;
}

$this->assertSame($this->configure($field)->getFormTypeOption('choices'), $expected);
Expand All @@ -76,7 +81,12 @@ public function testUnitEnumTypeChoices(): void
$field = ChoiceField::new(self::PROPERTY_NAME);
$field->getAsDto()->setDoctrineMetadata(['enumType' => PriorityUnitEnum::class]);

$this->assertSame($this->configure($field)->getFormTypeOption('choices'), PriorityUnitEnum::cases());
$formChoices = array_combine(
array_column(PriorityUnitEnum::cases(), 'name'),
PriorityUnitEnum::cases(),
);

$this->assertSame($this->configure($field)->getFormTypeOption('choices'), $formChoices);
}

public function testUnitEnumChoices(): void
Expand All @@ -88,7 +98,7 @@ public function testUnitEnumChoices(): void

$expected = [];
foreach (PriorityUnitEnum::cases() as $case) {
$expected[$case->name] = $case->name;
$expected[$case->name] = $case;
}

$this->assertSame($this->configure($field)->getFormTypeOption('choices'), $expected);
Expand Down

0 comments on commit c30a8a0

Please sign in to comment.