Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: EasyCorp/EasyAdminBundle
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v4.24.4
Choose a base ref
...
head repository: EasyCorp/EasyAdminBundle
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v4.24.5
Choose a head ref

Commits on Feb 19, 2025

  1. Fix typo

    Shadow-Devil authored Feb 19, 2025

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    ee1f75b View commit details
  2. Bump development version

    javiereguiluz committed Feb 19, 2025
    Copy the full SHA
    2af62d7 View commit details

Commits on Feb 20, 2025

  1. Always return to index when using SAVE_AND_RETURN button

    fracsi committed Feb 20, 2025
    Copy the full SHA
    aabe86c View commit details
  2. bug #6832 Always return to index when using SAVE_AND_RETURN button (f…

    …racsi)
    
    This PR was merged into the 4.x branch.
    
    Discussion
    ----------
    
    Always return to index when using SAVE_AND_RETURN button
    
    Fixes: #6830
    
    Note: #6822 fixed the deprected usage of the getReferrer, but the getReferrer method returned empty, thus the redirect to the list was working
    
    Commits
    -------
    
    aabe86c Always return to index when using SAVE_AND_RETURN button
    javiereguiluz committed Feb 20, 2025
    1
    Copy the full SHA
    4c1c63b View commit details
  3. minor #6829 Fix typo (Shadow-Devil)

    This PR was merged into the 4.x branch.
    
    Discussion
    ----------
    
    Fix typo
    
    <!--
    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
    -------
    
    ee1f75b Fix typo
    javiereguiluz committed Feb 20, 2025
    Copy the full SHA
    be09320 View commit details
  4. Display as form for actions

    fracsi authored and javiereguiluz committed Feb 20, 2025
    Copy the full SHA
    bb11a75 View commit details
  5. feature #6831 Display as form for actions (fracsi)

    This PR was squashed before being merged into the 4.x branch.
    
    Discussion
    ----------
    
    Display as form for actions
    
    Resolves #6826
    
    It only works if the action is global.
    
    Commits
    -------
    
    bb11a75 Display as form for actions
    javiereguiluz committed Feb 20, 2025
    Copy the full SHA
    902348b View commit details

Commits on Feb 22, 2025

  1. Update dashboards.rst

    With the use of AdminDashboard we don't need this use anymore
    LaurentMarquet authored Feb 22, 2025

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    feefc42 View commit details

Commits on Feb 25, 2025

  1. fix AbstractCrudController.php

    fix #6837, similar to #6832
    eminjk authored Feb 25, 2025

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    9efdbe4 View commit details

Commits on Mar 4, 2025

  1. minor #6836 Update dashboards.rst (LaurentMarquet)

    This PR was merged into the 4.x branch.
    
    Discussion
    ----------
    
    Update dashboards.rst
    
    With the use of AdminDashboard we don't need this use anymore
    
    <!--
    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
    -------
    
    feefc42 Update dashboards.rst
    javiereguiluz committed Mar 4, 2025
    Copy the full SHA
    ae9e0da View commit details
  2. bug #6840 fix #6837 - redirection to show page after delete action (e…

    …minjk)
    
    This PR was merged into the 4.x branch.
    
    Discussion
    ----------
    
    fix #6837 - redirection to show page after delete action
    
    fix #6837, similar to #6832
    
    <!--
    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
    -------
    
    9efdbe4 fix AbstractCrudController.php
    javiereguiluz committed Mar 4, 2025
    Copy the full SHA
    4d1ae6b View commit details
  3. fix(chore): resolve problem of inherit attribute

    jorisdugue authored and javiereguiluz committed Mar 4, 2025
    Copy the full SHA
    62fb2b4 View commit details
  4. bug #6850 fix(chore): resolve problem of inherit attribute (jorisdugue)

    This PR was squashed before being merged into the 4.x branch.
    
    Discussion
    ----------
    
    fix(chore): resolve problem of inherit attribute
    
    fix #6849 #6853
    
    This pull request addresses an issue where EasyAdmin fails to handle inherited properties during global search. Specifically, the issue arises when EasyAdmin tries to reflect on a property that exists in a parent class but not in the current class. The current implementation of property reflection does not account for inherited properties in parent classes, leading to errors when performing a global search.
    
    Commits
    -------
    
    62fb2b4 fix(chore): resolve problem of inherit attribute
    javiereguiluz committed Mar 4, 2025
    Copy the full SHA
    8add1b4 View commit details
  5. Add a comment

    javiereguiluz committed Mar 4, 2025
    Copy the full SHA
    3473fca View commit details

Commits on Mar 7, 2025

  1. Fix documentation about addColumn() method

    befresh-mweimerskirch authored Mar 7, 2025

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    cab02f0 View commit details

Commits on Mar 8, 2025

  1. Update EasyAdminBundle.zh_CN.php

    Fix batch_action_modal translation error.
    ywisax authored Mar 8, 2025

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    aa578fc View commit details

Commits on Mar 10, 2025

  1. Upgrade to PHPStan 2.x

    javiereguiluz committed Mar 10, 2025
    Copy the full SHA
    044444e View commit details
  2. minor #6855 Upgrade to PHPStan 2.x (javiereguiluz)

    This PR was squashed before being merged into the 4.x branch.
    
    Discussion
    ----------
    
    Upgrade to PHPStan 2.x
    
    There are two issues that I can't fix, even with AI help:
    
    https://github.com/EasyCorp/EasyAdminBundle/blob/4.x/src/Dto/EntityDto.php#L170-L171
    
    ```
     ------ ------------------------------------------------------------------------------------------------------------------------------------
      Line   Dto/EntityDto.php
     ------ ------------------------------------------------------------------------------------------------------------------------------------
      175    PHPDoc tag `@var` with type array|Doctrine\ORM\Mapping\FieldMapping is not subtype of native type Doctrine\ORM\Mapping\FieldMapping.
             🪪  varTag.nativeType
     ------ ------------------------------------------------------------------------------------------------------------------------------------
    ```
    
    https://github.com/EasyCorp/EasyAdminBundle/blob/3473fcab8b485506e3f112728bc4d37f8089819a/src/Intl/IntlFormatter.php#L111-L112
    
    ```
     ------ -----------------------------------------------------------------------
      Line   Intl/IntlFormatter.php
     ------ -----------------------------------------------------------------------
      112    PHPDoc tag `@var` with type string|false is not subtype of type string.
             🪪  varTag.type
     ------ -----------------------------------------------------------------------
    ```
    
    Commits
    -------
    
    044444e Upgrade to PHPStan 2.x
    javiereguiluz committed Mar 10, 2025
    Copy the full SHA
    68cdc0d View commit details
  3. minor #6858 Fix documentation about addColumn() method (befresh-mweim…

    …erskirch)
    
    This PR was merged into the 4.x branch.
    
    Discussion
    ----------
    
    Fix documentation about addColumn() method
    
    This is a minor documentation fix.
    When using addColumn() with an integer, it is transformed to col-md-N and not col-N.
    
    See https://github.com/EasyCorp/EasyAdminBundle/blob/4.x/src/Field/FormField.php#L139
    
    Commits
    -------
    
    cab02f0 Fix documentation about addColumn() method
    javiereguiluz committed Mar 10, 2025
    Copy the full SHA
    3a84de0 View commit details
  4. bug #6860 Update EasyAdminBundle.zh_CN.php (ywisax)

    This PR was merged into the 4.x branch.
    
    Discussion
    ----------
    
    Update EasyAdminBundle.zh_CN.php
    
    Fix batch_action_modal translation error.
    
    <!--
    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
    -------
    
    aa578fc Update EasyAdminBundle.zh_CN.php
    javiereguiluz committed Mar 10, 2025
    Copy the full SHA
    80caf71 View commit details
  5. Prepare 4.24.5 release

    javiereguiluz committed Mar 10, 2025
    Copy the full SHA
    9d0da6e View commit details
  6. Rebuild web assets

    javiereguiluz committed Mar 10, 2025
    Copy the full SHA
    dcc64d0 View commit details
2 changes: 1 addition & 1 deletion assets/css/easyadmin-theme/base.css
Original file line number Diff line number Diff line change
@@ -575,7 +575,7 @@ a.user-menu-wrapper .user-details:hover {
}
.content-header .page-actions:empty { display: none; }

.content-header .page-actions .btn + .btn {
.content-header .page-actions :is(.btn,form:has(.btn)) + :is(.btn,form:has(.btn)) {
margin-inline-start: 10px;
}

10 changes: 5 additions & 5 deletions composer.json
Original file line number Diff line number Diff line change
@@ -44,11 +44,11 @@
},
"require-dev": {
"doctrine/doctrine-fixtures-bundle": "^3.4|3.5.x-dev",
"phpstan/extension-installer": "^1.2",
"phpstan/phpstan": "^1.9",
"phpstan/phpstan-phpunit": "^1.2",
"phpstan/phpstan-strict-rules": "^1.4",
"phpstan/phpstan-symfony": "^1.2",
"phpstan/extension-installer": "^1.4",
"phpstan/phpstan": "^2.0",
"phpstan/phpstan-phpunit": "^2.0",
"phpstan/phpstan-strict-rules": "^2.0",
"phpstan/phpstan-symfony": "^2.0",
"psr/log": "^1.0",
"symfony/browser-kit": "^5.4|^6.0|^7.0",
"symfony/css-selector": "^5.4|^6.0|^7.0",
3 changes: 1 addition & 2 deletions doc/dashboards.rst
Original file line number Diff line number Diff line change
@@ -86,7 +86,6 @@ Now, define the main route of your dashboard class using the following PHP attri
use EasyCorp\Bundle\EasyAdminBundle\Config\Dashboard;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractDashboardController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;

#[AdminDashboard(routePath: '/admin', routeName: 'admin')]
class DashboardController extends AbstractDashboardController
@@ -144,7 +143,7 @@ Defining the Route in the ``index()`` Method
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Using the ``#[AdminDashboard]`` attribute is the recommended way to define the
dashboard route. However, you can also define the dashboard route aplying the
dashboard route. However, you can also define the dashboard route applying the
``#[Route]`` attribute on the ``index()`` method::

// ...
4 changes: 2 additions & 2 deletions doc/fields.rst
Original file line number Diff line number Diff line change
@@ -388,8 +388,8 @@ The arguments of the ``addColumn()`` method are:

* ``$cols``: (type: ``int|string``) the width of the column defined as any value
compatible with the `Bootstrap grid system`_ (e.g. ``'col-6'``, ``'col-md-6 col-xl-4'``,
etc.). Integer values are transformed like this: N -> 'col-N' (e.g. ``8`` is
transformed to ``col-8``);
etc.). Integer values are transformed like this: N -> 'col-md-N' (e.g. ``8`` is
transformed to ``col-md-8``);
* ``$label``: (type: ``TranslatableInterface|string|false|null``) an optional title
that is displayed at the top of the column. If you pass ``false``, ``null``
or an empty string, no title is displayed. You can also pass ``string`` and
1 change: 1 addition & 0 deletions phpstan.neon.dist
Original file line number Diff line number Diff line change
@@ -8,6 +8,7 @@ parameters:
excludePaths:
analyse:
- src/ArgumentResolver
- src/Test/Trait/CrudTestFormAsserts.php
bootstrapFiles:
- vendor/bin/.phpunit/phpunit/vendor/autoload.php
ignoreErrors:
2 changes: 1 addition & 1 deletion public/app.62f32d02.css → public/app.842ae134.css

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion public/entrypoints.json
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@
"entrypoints": {
"app": {
"css": [
"/app.62f32d02.css"
"/app.842ae134.css"
],
"js": [
"/app.1ecd6d7a.js"
2 changes: 1 addition & 1 deletion public/manifest.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"app.css": "app.62f32d02.css",
"app.css": "app.842ae134.css",
"app.js": "app.1ecd6d7a.js",
"form.js": "form.bcec6c2a.js",
"page-layout.js": "page-layout.3347892e.js",
7 changes: 7 additions & 0 deletions src/Config/Action.php
Original file line number Diff line number Diff line change
@@ -158,6 +158,13 @@ public function displayAsButton(): self
return $this;
}

public function displayAsForm(): self
{
$this->dto->setHtmlElement('form');

return $this;
}

public function setHtmlAttributes(array $attributes): self
{
$this->dto->setHtmlAttributes($attributes);
7 changes: 1 addition & 6 deletions src/Controller/AbstractCrudController.php
Original file line number Diff line number Diff line change
@@ -387,10 +387,6 @@ public function delete(AdminContext $context)
return $event->getResponse();
}

if (null !== $referrer = $context->getRequest()->headers->get('referer')) {
return $this->redirect($referrer);
}

return $this->redirect($this->container->get(AdminUrlGenerator::class)->setController($context->getCrud()->getControllerFqcn())->setAction(Action::INDEX)->unset(EA::ENTITY_ID)->generateUrl());
}

@@ -639,8 +635,7 @@ protected function getRedirectResponseAfterSave(AdminContext $context, string $a
->setAction(Action::EDIT)
->setEntityId($context->getEntity()->getPrimaryKeyValue())
->generateUrl(),
Action::SAVE_AND_RETURN => $context->getRequest()->headers->get('referer')
?? $this->container->get(AdminUrlGenerator::class)->setAction(Action::INDEX)->generateUrl(),
Action::SAVE_AND_RETURN => $this->container->get(AdminUrlGenerator::class)->setAction(Action::INDEX)->generateUrl(),
Action::SAVE_AND_ADD_ANOTHER => $this->container->get(AdminUrlGenerator::class)->setAction(Action::NEW)->generateUrl(),
default => $this->generateUrl($context->getDashboardRouteName()),
};
4 changes: 3 additions & 1 deletion src/Dto/ActionDto.php
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@ final class ActionDto
{
private ?string $type = null;
private ?string $name = null;
/** @var TranslatableInterface|string|(callable(object): string)|null */
/** @var TranslatableInterface|string|(callable(object): string)|false|null */
private mixed $label = null;
private ?string $icon = null;
private string $cssClass = '';
@@ -293,6 +293,8 @@ public function getAsConfigObject(): Action

if ('a' === $this->htmlElement) {
$action->displayAsLink();
} elseif ('form' === $this->htmlElement) {
$action->displayAsForm();
} else {
$action->displayAsButton();
}
7 changes: 6 additions & 1 deletion src/Dto/EntityDto.php
Original file line number Diff line number Diff line change
@@ -5,9 +5,13 @@
use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\Mapping\FieldMapping;
use Doctrine\ORM\Mapping\ManyToManyAssociationMapping;
use Doctrine\ORM\Mapping\ManyToManyInverseSideMapping;
use Doctrine\ORM\Mapping\ManyToManyOwningSideMapping;
use Doctrine\ORM\Mapping\ManyToOneAssociationMapping;
use Doctrine\ORM\Mapping\OneToManyAssociationMapping;
use Doctrine\ORM\Mapping\OneToOneAssociationMapping;
use Doctrine\ORM\Mapping\OneToOneInverseSideMapping;
use Doctrine\ORM\Mapping\OneToOneOwningSideMapping;
use EasyCorp\Bundle\EasyAdminBundle\Collection\ActionCollection;
use EasyCorp\Bundle\EasyAdminBundle\Collection\FieldCollection;
use EasyCorp\Bundle\EasyAdminBundle\Config\KeyValueStore;
@@ -168,6 +172,7 @@ public function getPropertyMetadata(string $propertyName): KeyValueStore
{
if (\array_key_exists($propertyName, $this->metadata->fieldMappings)) {
/** @var FieldMapping|array $fieldMapping */
/** @phpstan-ignore-next-line */
$fieldMapping = $this->metadata->fieldMappings[$propertyName];
// Doctrine ORM 2.x returns an array and Doctrine ORM 3.x returns a FieldMapping object
if ($fieldMapping instanceof FieldMapping) {
@@ -178,7 +183,7 @@ public function getPropertyMetadata(string $propertyName): KeyValueStore
}

if (\array_key_exists($propertyName, $this->metadata->associationMappings)) {
/** @var OneToOneAssociationMapping|OneToManyAssociationMapping|ManyToOneAssociationMapping|ManyToManyAssociationMapping|array $associationMapping */
/** @var OneToOneOwningSideMapping|OneToOneInverseSideMapping|ManyToOneAssociationMapping|OneToManyAssociationMapping|ManyToManyOwningSideMapping|ManyToManyInverseSideMapping $associationMapping */
$associationMapping = $this->metadata->associationMappings[$propertyName];
// Doctrine ORM 2.x returns an array and Doctrine ORM 3.x returns one of the many *Mapping objects
// there's not a single interface implemented by all of them, so let's only check if it's an object
2 changes: 1 addition & 1 deletion src/EasyAdminBundle.php
Original file line number Diff line number Diff line change
@@ -11,7 +11,7 @@
*/
class EasyAdminBundle extends Bundle
{
public const VERSION = '4.24.4';
public const VERSION = '4.24.5';

public function build(ContainerBuilder $container): void
{
2 changes: 1 addition & 1 deletion src/Factory/ActionFactory.php
Original file line number Diff line number Diff line change
@@ -166,7 +166,7 @@ private function processActionLabel(ActionDto $actionDto, ?EntityDto $entityDto,
}

if (\is_callable($label) && $label instanceof \Closure) {
$label = \call_user_func_array($label, array_filter([$entityDto?->getInstance()]));
$label = \call_user_func_array($label, array_filter([$entityDto?->getInstance()], static fn ($item): bool => null !== $item));

if (!\is_string($label) && !$label instanceof TranslatableInterface) {
throw new \RuntimeException(sprintf('The callable used to define the label of the "%s" action label %s must return a string or a %s instance but it returned a(n) "%s" value instead.', $actionDto->getName(), null !== $entityDto ? 'in the "'.$entityDto->getName().'" entity' : '', TranslatableInterface::class, \gettype($label)));
73 changes: 32 additions & 41 deletions src/Field/Configurator/ChoiceConfigurator.php
Original file line number Diff line number Diff line change
@@ -33,53 +33,46 @@ public function configure(FieldDto $field, EntityDto $entityDto, AdminContext $c
$choicesSupportTranslatableInterface = false;
$isExpanded = true === $field->getCustomOption(ChoiceField::OPTION_RENDER_EXPANDED);
$isMultipleChoice = true === $field->getCustomOption(ChoiceField::OPTION_ALLOW_MULTIPLE_CHOICES);
// Initialize the variable since we are using it outside the $enumsAreSupported condition
$allChoicesAreEnums = false;

$choices = $this->getChoices($field->getCustomOption(ChoiceField::OPTION_CHOICES), $entityDto, $field);

// using a more precise check like 'function_exists('enum_exists');' messes with IDEs like PhpStorm
$enumsAreSupported = \PHP_VERSION_ID >= 80100;

if (null === $choices) {
$choices = [];
}

// support for enums
if ($enumsAreSupported) {
$elementIsEnum = array_unique(array_map(static function ($element): bool {
return \is_object($element) && enum_exists($element::class);
}, $choices));
$allChoicesAreEnums = false === \in_array(false, $elementIsEnum, true);

// if no choices are passed to the field, check if it's related to an Enum;
// in that case, get all the possible values of the Enum (Doctrine supports only BackedEnum as enumType)
$enumTypeClass = $field->getDoctrineMetadata()->get('enumType');
if (0 === \count($choices) && null !== $enumTypeClass && enum_exists($enumTypeClass)) {
$choices = $enumTypeClass::cases();
$allChoicesAreEnums = true;
}
$elementIsEnum = array_unique(array_map(static function ($element): bool {
return \is_object($element) && enum_exists($element::class);
}, $choices));
$allChoicesAreEnums = false === \in_array(false, $elementIsEnum, true);

// if no choices are passed to the field, check if it's related to an Enum;
// in that case, get all the possible values of the Enum (Doctrine supports only BackedEnum as enumType)
$enumTypeClass = $field->getDoctrineMetadata()->get('enumType');
if (0 === \count($choices) && null !== $enumTypeClass && enum_exists($enumTypeClass)) {
$choices = $enumTypeClass::cases();
$allChoicesAreEnums = true;
}

// SF 6.4 and up has native support for translatable enums, we should respect that too
if (is_subclass_of($enumTypeClass, TranslatableInterface::class)) {
$areChoicesTranslatable = $choicesSupportTranslatableInterface = true;
}
// SF 6.4 and up has native support for translatable enums, we should respect that too
if (is_subclass_of($enumTypeClass, TranslatableInterface::class)) {
$areChoicesTranslatable = $choicesSupportTranslatableInterface = true;
}

if ($allChoicesAreEnums && array_is_list($choices) && \count($choices) > 0) {
$processedEnumChoices = [];
foreach ($choices as $choice) {
$processedEnumChoices[$choice->name] = $choice;
}
if ($allChoicesAreEnums && array_is_list($choices) && \count($choices) > 0) {
$processedEnumChoices = [];
foreach ($choices as $choice) {
$processedEnumChoices[$choice->name] = $choice;
}

$choices = $processedEnumChoices;
$choices = $processedEnumChoices;

// Update form type to be EnumType if current form type is still ChoiceType
// Leave the form type as is if user set something else explicitly
if (ChoiceType::class === $field->getFormType()) {
$field->setFormType(EnumType::class);
}
$field->setFormTypeOptionIfNotSet('class', $enumTypeClass);
// Update form type to be EnumType if current form type is still ChoiceType
// Leave the form type as is if user set something else explicitly
if (ChoiceType::class === $field->getFormType()) {
$field->setFormType(EnumType::class);
}
$field->setFormTypeOptionIfNotSet('class', $enumTypeClass);
}

if ($areChoicesTranslatable && !$choicesSupportTranslatableInterface) {
@@ -115,13 +108,11 @@ public function configure(FieldDto $field, EntityDto $entityDto, AdminContext $c
return;
}

if ($enumsAreSupported) {
// Backed enum converted to array result in array [enum->name, enum->value] as done in the loop bellow
// That results in grid displaying two values when single enum is a selected value
// This makes sure we pass an array of enums as selected value when single enum is selected
if ($fieldValue instanceof \UnitEnum) {
$fieldValue = [$fieldValue];
}
// Backed enum converted to array result in array [enum->name, enum->value] as done in the loop bellow
// That results in grid displaying two values when single enum is a selected value
// This makes sure we pass an array of enums as selected value when single enum is selected
if ($fieldValue instanceof \UnitEnum) {
$fieldValue = [$fieldValue];
}

$badgeSelector = $field->getCustomOption(ChoiceField::OPTION_RENDER_AS_BADGES);
4 changes: 2 additions & 2 deletions src/Form/EventListener/FormLayoutSubscriber.php
Original file line number Diff line number Diff line change
@@ -6,9 +6,9 @@
use EasyCorp\Bundle\EasyAdminBundle\Field\FormField;
use EasyCorp\Bundle\EasyAdminBundle\Form\Type\Layout\EaFormTabListType;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Form\Form;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormInterface;

/**
* Handles some logic related to the form layout, like error counters in tabs.
@@ -31,7 +31,7 @@ public static function getSubscribedEvents(): array
public function handleTabErrors(FormEvent $event)
{
$formTabs = [];
/** @var Form $child */
/** @var FormInterface $child */
foreach ($event->getForm() as $child) {
/** @var FieldDto $fieldDto */
if (null === $fieldDto = $child->getConfig()->getAttribute('ea_field')) {
1 change: 0 additions & 1 deletion src/Intl/IntlFormatter.php
Original file line number Diff line number Diff line change
@@ -108,7 +108,6 @@ final class IntlFormatter implements IntlFormatterInterface
public function formatCurrency($amount, string $currency, array $attrs = [], ?string $locale = null): string
{
$formatter = $this->createNumberFormatter($locale, 'currency', $attrs);
/** @var string|false $formattedCurrency */
$formattedCurrency = $formatter->formatCurrency($amount, $currency);
if (false === $formattedCurrency) {
throw new RuntimeError('Unable to format the given number as a currency.');
15 changes: 14 additions & 1 deletion src/Orm/EntityRepository.php
Original file line number Diff line number Diff line change
@@ -309,10 +309,23 @@ private function getSearchablePropertiesConfig(QueryBuilder $queryBuilder, Searc
? $associatedEntityDto->getFqcn()
: $entityDto->getFqcn()
;

/** @var \ReflectionNamedType|\ReflectionUnionType|null $idClassType */
$idClassType = (new \ReflectionProperty($entityFqcn, $propertyName))->getType();
$idClassType = null;
$reflectionClass = new \ReflectionClass($entityFqcn);

// this is needed to handle inherited properties
while (false !== $reflectionClass) {
if ($reflectionClass->hasProperty($propertyName)) {
$reflection = $reflectionClass->getProperty($propertyName);
$idClassType = $reflection->getType();
break;
}
$reflectionClass = $reflectionClass->getParentClass();
}

if (null !== $idClassType) {
/** @var \ReflectionNamedType|\ReflectionUnionType $idClassType */
$idClassName = $idClassType->getName();

if (class_exists($idClassName)) {
2 changes: 1 addition & 1 deletion src/Router/AdminUrlGenerator.php
Original file line number Diff line number Diff line change
@@ -369,7 +369,7 @@ private function initialize(): void
EA::CRUD_CONTROLLER_FQCN => $adminContext->getRequest()->attributes->get(EA::CRUD_CONTROLLER_FQCN),
EA::CRUD_ACTION => $adminContext->getRequest()->attributes->get(EA::CRUD_ACTION),
EA::ENTITY_ID => $adminContext->getRequest()->attributes->get(EA::ENTITY_ID),
]);
], static fn ($value): bool => null !== $value);
$currentRouteParameters = $routeParametersForReferrer = array_merge($routeParameters, $adminContext->getRequest()->query->all());
unset($routeParametersForReferrer[EA::REFERRER]);
$this->currentPageReferrer = sprintf('%s%s?%s', $adminContext->getRequest()->getBaseUrl(), $adminContext->getRequest()->getPathInfo(), http_build_query($routeParametersForReferrer));
2 changes: 1 addition & 1 deletion src/Twig/Component/Flag.php
Original file line number Diff line number Diff line change
@@ -26,6 +26,6 @@ public function getFlagAsSvg(): string
return sprintf('<svg xmlns="http://www.w3.org/2000/svg" class="country-flag" height="%d" viewBox="0 0 25 17"><title>You are not seeing a country flag here because the "%s.svg" file associated to given the "%s" country code does not exist in the assets/icons/flags/ directory of EasyAdmin.</title><rect width="100%%" height="%d" fill="#ff0000"/></svg>', $this->height, $this->countryCode, $this->countryCode, $this->height);
}

return str_replace(['__HEIGHT__', '__COUNTRY_NAME__'], [$this->height, $this->getCountryName()], file_get_contents($flagSvgFilePath));
return str_replace(['__HEIGHT__', '__COUNTRY_NAME__'], [(string) $this->height, $this->getCountryName()], file_get_contents($flagSvgFilePath));
}
}
4 changes: 1 addition & 3 deletions src/Twig/EasyAdminTwigExtension.php
Original file line number Diff line number Diff line change
@@ -110,9 +110,7 @@ public function fileSize(int $bytes): string
public function applyFilterIfExists(Environment $environment, $value, string $filterName, ...$filterArguments)
{
/**
* Twig v2 will return TwigFilter|false.
*
* @var TwigFilter|false|null $filter
* @var TwigFilter|null $filter
*/
$filter = $environment->getFilter($filterName);
if (null === $filter || false === $filter) {
11 changes: 11 additions & 0 deletions templates/crud/action.html.twig
Original file line number Diff line number Diff line change
@@ -15,4 +15,15 @@
{%- if action.label is not empty -%}<span class="action-label">{{ action.label|trans|raw }}</span>{%- endif -%}
</span>
</button>
{% elseif 'form' == action.htmlElement %}
{%- set form_id = 'form-' ~ action.name ~ '-' ~ random() -%}
{%- do action.setHtmlAttribute('form', form_id) -%}
<form action="{{ action.linkUrl }}" method="POST" id="{{ form_id }}">
<button class="{{ action.cssClass }}" {% for name, value in action.htmlAttributes %}{{ name }}="{{ (value.trans is defined ? value|trans : value)|e('html') }}" {% endfor %}>
<span class="btn-label">
{%- if action.icon %}<twig:ea:Icon name="{{ action.icon }}"/> {% endif -%}
{%- if action.label is not empty -%}<span class="action-label">{{ action.label|trans|raw }}</span>{%- endif -%}
</span>
</button>
</form>
{% endif %}
Loading