diff --git a/composer.json b/composer.json index 092467b8aa..4bbc7de5a7 100644 --- a/composer.json +++ b/composer.json @@ -29,6 +29,7 @@ "symfony/http-foundation": "^5.4|^6.0", "symfony/http-kernel": "^5.4|^6.0", "symfony/intl": "^5.4|^6.0", + "symfony/polyfill-php81": "^1.27", "symfony/property-access": "^5.4|^6.0", "symfony/security-bundle": "^5.4|^6.0", "symfony/string": "^5.4|^6.0", diff --git a/src/Factory/FieldFactory.php b/src/Factory/FieldFactory.php index 70d6f95b4f..3bfbae2d40 100644 --- a/src/Factory/FieldFactory.php +++ b/src/Factory/FieldFactory.php @@ -108,6 +108,13 @@ public function processFields(EntityDto $entityDto, FieldCollection $fields): vo $configurator->configure($fieldDto, $entityDto, $context); } + // check again if the field is displayed because this can change in the configurators + if (null !== $currentPage && false === $fieldDto->isDisplayedOn($currentPage)) { + $fields->unset($fieldDto); + + continue; + } + foreach ($fieldDto->getFormThemes() as $formThemePath) { $context?->getCrud()?->addFormTheme($formThemePath); } diff --git a/src/Field/Configurator/ChoiceConfigurator.php b/src/Field/Configurator/ChoiceConfigurator.php index 104b5a4ace..6e67e77bfd 100644 --- a/src/Field/Configurator/ChoiceConfigurator.php +++ b/src/Field/Configurator/ChoiceConfigurator.php @@ -10,6 +10,7 @@ use EasyCorp\Bundle\EasyAdminBundle\Field\ChoiceField; use EasyCorp\Bundle\EasyAdminBundle\Translation\TranslatableChoiceMessage; use EasyCorp\Bundle\EasyAdminBundle\Translation\TranslatableChoiceMessageCollection; +use Symfony\Component\Form\Extension\Core\Type\EnumType; use function Symfony\Component\String\u; use function Symfony\Component\Translation\t; use Symfony\Contracts\Translation\TranslatableInterface; @@ -38,7 +39,8 @@ public function configure(FieldDto $field, EntityDto $entityDto, AdminContext $c // in that case, get all the possible values of the Enum if (null === $choices && $enumsAreSupported) { $enumTypeClass = $field->getDoctrineMetadata()->get('enumType'); - if (enum_exists($enumTypeClass)) { + if (is_string($enumTypeClass) && enum_exists($enumTypeClass)) { + $field->setFormTypeOption('class', $enumTypeClass); $choices = $enumTypeClass::cases(); } } @@ -48,6 +50,7 @@ public function configure(FieldDto $field, EntityDto $entityDto, AdminContext $c } // support for enums + $allChoicesAreEnums = false; if ($enumsAreSupported) { $elementIsEnum = array_unique(array_map(static function ($element): bool { return \is_object($element) && enum_exists($element::class); @@ -55,13 +58,11 @@ public function configure(FieldDto $field, EntityDto $entityDto, AdminContext $c $allChoicesAreEnums = false === \in_array(false, $elementIsEnum, true); if ($allChoicesAreEnums) { + $field->setFormType(EnumType::class); + $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; @@ -70,7 +71,15 @@ public function configure(FieldDto $field, EntityDto $entityDto, AdminContext $c if ($areChoicesTranslatable) { $field->setFormTypeOptionIfNotSet('choices', array_keys($choices)); - $field->setFormTypeOptionIfNotSet('choice_label', fn ($value) => $choices[$value]); + $field->setFormTypeOptionIfNotSet('choice_label', static function ($value) use ($choices) { + $key = match (true) { + \is_object($value) && enum_exists($value::class) => $value->name, + \is_object($value) => (string) $value, + default => $value, + }; + + return $choices[$key]; + }); } else { $field->setFormTypeOptionIfNotSet('choices', $choices); } @@ -108,12 +117,21 @@ public function configure(FieldDto $field, EntityDto $entityDto, AdminContext $c $translationDomain = $context->getI18n()->getTranslationDomain(); $choiceMessages = []; // Translatable choice don't need to get flipped - $flippedChoices = $areChoicesTranslatable ? $choices : array_flip($this->flatten($choices)); + $flippedChoices = ($areChoicesTranslatable || $allChoicesAreEnums) ? $choices : array_flip($this->flatten($choices)); foreach ((array) $fieldValue as $selectedValue) { if (null !== $selectedLabel = $flippedChoices[$selectedValue] ?? null) { if ($selectedValue instanceof TranslatableInterface) { $choiceMessage = $selectedValue; } else { + if (\is_object($selectedLabel) && enum_exists($selectedLabel::class)) { + $selectedLabel = $selectedLabel->name; + } elseif (\is_object($selectedLabel)) { + $labelCallback = $field->getFormTypeOption('choice_label'); + if (\is_callable($labelCallback)) { + $selectedLabel = $labelCallback($selectedLabel); + } + } + $choiceMessage = t( $selectedLabel, $translationParameters,