EasyCorp / EasyAdminBundle

EasyAdmin is a fast, beautiful and modern admin generator for Symfony applications.
MIT License
4.04k stars 1.02k forks source link

Autocomplete broken on v3.4.2 #4466

Closed RRoek closed 2 years ago

RRoek commented 3 years ago

Hi, I just up today from v3.0.2 to v3.4.2. I've noticed a breaking change for my AssociationFields where the autocomplete option is enabled. Here the problem I meet and the patch I've found.

Example in my crud Controller : $myVar = AssociationField::new('receiverContact', 'Contact')->autocomplete();

my private property in the entity :

  /**
     * @var Contact
     *
     * @ORM\ManyToOne(targetEntity="App\Entity\Contact")
     * @ORM\JoinColumns({
     *   @ORM\JoinColumn(name="contact_id", referencedColumnName="id", nullable=true)
     * })
     */
    private $receiverContact;

And the error printed on request, when I try the autocomplete field : _Call to a member function configureFields() on null_ in vendor/easycorp/easyadmin-bundle/src/Controller/AbstractCrudController.php (line 475)

The working solution to patch this for me was to override the autocomplete method in my AbstractController (who extend vendor/easycorp/easyadmin-bundle/src/Controller/AbstractCrudController.php) to just add this test line :

-->if(null != $autocompleteContext) {<--


    public function autocomplete(AdminContext $context): JsonResponse
    {
        $queryBuilder = $this->createIndexQueryBuilder($context->getSearch(), $context->getEntity(), FieldCollection::new([]), FilterCollection::new());

        $autocompleteContext = $context->getRequest()->get(AssociationField::PARAM_AUTOCOMPLETE_CONTEXT);

        if(null != $autocompleteContext) {
            /** @var CrudControllerInterface $controller */
            $controller = $this->get(ControllerFactory::class)->getCrudControllerInstance($autocompleteContext[EA::CRUD_CONTROLLER_FQCN], Action::INDEX, $context->getRequest());
            /** @var FieldDto $field */
            $field = FieldCollection::new($controller->configureFields($autocompleteContext['originatingPage']))->getByProperty($autocompleteContext['propertyName']);
            /** @var \Closure|null $queryBuilderCallable */
            $queryBuilderCallable = $field->getCustomOption(AssociationField::OPTION_QUERY_BUILDER_CALLABLE);

            if (null !== $queryBuilderCallable) {
                $queryBuilderCallable($queryBuilder);
            }
        }

        $paginator = $this->get(PaginatorFactory::class)->create($queryBuilder);

        return JsonResponse::fromJsonString($paginator->getResultsAsJson());
    }

Notice It's, I hope, simply a temporary fix, override method just for a line is a bit heavy...

@javiereguiluz Do you have an opinion on the subject ? Is there something I don't noticed with upgrade or is this to fix with a Pull Request ?

Best regards, RR

javiereguiluz commented 3 years ago

@RRoek I've checked and autocomplete lists keep working in my apps (I haven't tested all of them).

You did great finding a solution ... but please, investigate a bit more to find the cause. Does this fail in all autocomplete lists that match some condition/characteristics? (then it'd be an EasyAdmin bug) Does it only fail in some of your own autocomplete lists? (then it'd may be a bug in your app ... or something that EasyAdmin needs to add support to).

Thanks!

RRoek commented 3 years ago

Hi, thanks for your answer !

I have in my app 6 autocomplete fields. 3 are unidirectional ManyToOne properties like in my example

/**
   * @var Contact
   *
   * @ORM\ManyToOne(targetEntity="App\Entity\Contact")
   * @ORM\JoinColumns({
   *   @ORM\JoinColumn(name="contact_id", referencedColumnName="id", nullable=true)
   * })
   */
  private $receiverContact;

2 are unidirectional ManyToMany properties like this :

//src/Entity/Tax.php
    /**
     * @var Contact
     *
     * @ORM\ManyToMany(targetEntity="App\Entity\Administrative\BillIssued")
     * @ORM\JoinTable(name="tax_bill_issued",
     *      joinColumns={@ORM\JoinColumn(name="tax_id", referencedColumnName="id", nullable=true)},
     *      inverseJoinColumns={@ORM\JoinColumn(name="bill_issued_id", referencedColumnName="id")}
     *      )
     */
    private $billsIssued;

But one are a bidirectional ManyToOne property :

    /**
     * @var Contact
     *
     * @ORM\ManyToOne(targetEntity="App\Entity\Contact", inversedBy="children")
     * @ORM\JoinColumns({
     *   @ORM\JoinColumn(name="parent_id", nullable=true)
     * })
     */
    private $parent;

All of these properties are nullable.

I have tested to enable autocomplete on another AssociationField of a unidirectionnal ManyToOne property which is not nullable :

    /**
     * @var Society
     *
     * @ORM\ManyToOne(targetEntity="App\Entity\Society")
     * @ORM\JoinColumns({
     *   @ORM\JoinColumn(name="society_id", referencedColumnName="id", nullable=false)
     * })
     */
    private $society;

But The result is the same, the autocomplete field doesn't work and print the same error : Call to a member function configureFields() on null

I will search from other way if the problem is on my app or on the bundle and I come back to you.

Best regards, RR

javiereguiluz commented 2 years ago

We didn't receive more feedback, so this was probably fixed.