From 5cf9c7102bbc17fbcbdb177e26f6a91eac1352ce Mon Sep 17 00:00:00 2001 From: "a.dmitryuk" Date: Fri, 12 Dec 2025 11:34:03 +0700 Subject: [PATCH] [feature] Pass entityDto to queryBuilderCallable in AssociationField --- doc/fields/AssociationField.rst | 2 +- src/Controller/AbstractCrudController.php | 8 +++++++- src/Field/Configurator/AssociationConfigurator.php | 6 ++++-- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/doc/fields/AssociationField.rst b/doc/fields/AssociationField.rst index a5040731eb..bdf034d935 100644 --- a/doc/fields/AssociationField.rst +++ b/doc/fields/AssociationField.rst @@ -122,7 +122,7 @@ If you already define custom queries in repository methods, you can reuse them inside the callable:: yield AssociationField::new('...')->setQueryBuilder( - fn (QueryBuilder $queryBuilder): QueryBuilder => $queryBuilder->getEntityManager()->getRepository(Foo::class)->getSomeQueryBuilder(); + fn (QueryBuilder $queryBuilder, ?EntityDto $dto): QueryBuilder => $queryBuilder->getEntityManager()->getRepository(Foo::class)->getSomeQueryBuilder(); ); Alternatively, you can use the `query_builder option`_ of Symfony's diff --git a/src/Controller/AbstractCrudController.php b/src/Controller/AbstractCrudController.php index 4f6f02ed2d..492b284b77 100644 --- a/src/Controller/AbstractCrudController.php +++ b/src/Controller/AbstractCrudController.php @@ -482,7 +482,13 @@ public function autocomplete(AdminContext $context): JsonResponse $queryBuilderCallable = $field?->getCustomOption(AssociationField::OPTION_QUERY_BUILDER_CALLABLE); if (null !== $queryBuilderCallable) { - $queryBuilderCallable($queryBuilder); + $entityId = $autocompleteContext[EA::ENTITY_ID] ?? ''; + $entityFcqn = $autocompleteContext[EA::ENTITY_FQCN] ?? ''; + if ('' !== $entityId && '' !== $entityFcqn) { + $entityDto = $this->container->get(EntityFactory::class)->create($entityFcqn, $entityId); + } + + $queryBuilderCallable($queryBuilder, $entityDto ?? null); } $paginator = $this->container->get(PaginatorFactory::class)->create($queryBuilder); diff --git a/src/Field/Configurator/AssociationConfigurator.php b/src/Field/Configurator/AssociationConfigurator.php index 762aac8c00..acf3bdf1dd 100644 --- a/src/Field/Configurator/AssociationConfigurator.php +++ b/src/Field/Configurator/AssociationConfigurator.php @@ -168,6 +168,8 @@ public function configure(FieldDto $field, EntityDto $entityDto, AdminContext $c EA::CRUD_CONTROLLER_FQCN => $context->getRequest()->attributes->get(EA::CRUD_CONTROLLER_FQCN) ?? $context->getRequest()->query->get(EA::CRUD_CONTROLLER_FQCN), 'propertyName' => $propertyName, 'originatingPage' => $context->getCrud()->getCurrentPage(), + EA::ENTITY_ID => $entityDto->getPrimaryKeyValueAsString(), + EA::ENTITY_FQCN => $entityDto->getFqcn(), ]) ->generateUrl(); } catch (RouteNotFoundException $e) { @@ -177,12 +179,12 @@ public function configure(FieldDto $field, EntityDto $entityDto, AdminContext $c $field->setFormTypeOption('attr.data-ea-autocomplete-endpoint-url', $autocompleteEndpointUrl ?? null); } else { - $field->setFormTypeOptionIfNotSet('query_builder', static function (EntityRepository $repository) use ($field) { + $field->setFormTypeOptionIfNotSet('query_builder', static function (EntityRepository $repository) use ($entityDto, $field) { // TODO: should this use `createIndexQueryBuilder` instead, so we get the default ordering etc.? // it would then be identical to the one used in autocomplete action, but it is a bit complex getting it in here $queryBuilder = $repository->createQueryBuilder('entity'); if (null !== $queryBuilderCallable = $field->getCustomOption(AssociationField::OPTION_QUERY_BUILDER_CALLABLE)) { - $queryBuilderCallable($queryBuilder); + $queryBuilderCallable($queryBuilder, $entityDto); } return $queryBuilder;