api-platform / api-platform

🕸️ Create REST and GraphQL APIs, scaffold Jamstack webapps, stream changes in real-time.
https://api-platform.com
MIT License
8.68k stars 962 forks source link

[Tests] Alice doesn't trigger autowired EventSubscriber #1914

Open artandor opened 3 years ago

artandor commented 3 years ago

Hi,

I'm using Alice 2.9.0 with phpunit 8.5.

I just realised that when loading fixtures, Alice doesn't trigger EventSubscribers that are autowired through EventSubscriberInterface.

It works when the service is declared manually :

config/services.yaml

    App\EventSubscriber\HashPasswordSubscriber:
        tags:
            - { name: doctrine.event_subscriber }

src/EventSubscriber/HashPasswordSubscriber.php

<?php
declare(strict_types=1);

namespace App\EventSubscriber;

use App\Entity\User;
use Doctrine\Common\EventSubscriber;
use Doctrine\ORM\Event\LifecycleEventArgs;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;

class HashPasswordSubscriber implements EventSubscriber
{

    private UserPasswordEncoderInterface $passwordEncoder;

    public function __construct(UserPasswordEncoderInterface $passwordEncoder)
    {
        $this->passwordEncoder = $passwordEncoder;
    }

    /**
     * @return array
     */
    public function getSubscribedEvents(): array
    {
        return ['prePersist', 'preUpdate'];
    }

    public function prePersist(LifecycleEventArgs $args): void
    {
        $entity = $args->getEntity();
        if (!$entity instanceof User) {
            return;
        }
        $this->encodePassword($entity);
    }

    /**
     * @param User $entity
     */
    private function encodePassword(User $entity): void
    {
        if (!$entity->getPlainPassword()) {
            return;
        }
        $encoded = $this->passwordEncoder->encodePassword(
            $entity,
            $entity->getPlainPassword()
        );
        $entity->setPassword($encoded);
    }

    public function preUpdate(LifecycleEventArgs $args): void
    {
        $entity = $args->getEntity();
        if (!$entity instanceof User) {
            return;
        }
        $this->encodePassword($entity);
        // necessary to force the update to see the change
        $em = $args->getEntityManager();
        $meta = $em->getClassMetadata(User::class);
        $em->getUnitOfWork()->recomputeSingleEntityChangeSet($meta, $entity);
    }
}

But when the subscriber is autowired it doesn't

<?php
declare(strict_types=1);

namespace App\EventSubscriber;

use App\Entity\User;
use Doctrine\ORM\Event\LifecycleEventArgs;
use Doctrine\ORM\Events;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;

class HashPasswordSubscriber implements EventSubscriberInterface
{
    public function __construct(private UserPasswordEncoderInterface $passwordEncoder)
    {
    }

    /**
     * @return array
     */
    public static function getSubscribedEvents(): array
    {
        return [
            Events::prePersist => ['prePersist'],
            Events::preUpdate => ['preUpdate'],
        ];
    }

    public function prePersist(LifecycleEventArgs $args): void
    {
        $entity = $args->getEntity();
        if (!$entity instanceof User) {
            return;
        }
        $this->encodePassword($entity);
    }

    /**
     * @param User $entity
     */
    private function encodePassword(User $entity): void
    {
        if (!$entity->getPlainPassword()) {
            return;
        }
        $encoded = $this->passwordEncoder->encodePassword(
            $entity,
            $entity->getPlainPassword()
        );
        $entity->setPassword($encoded);
    }

    public function preUpdate(LifecycleEventArgs $args): void
    {
        $entity = $args->getEntity();
        if (!$entity instanceof User) {
            return;
        }
        $this->encodePassword($entity);
        // necessary to force the update to see the change
        $em = $args->getEntityManager();
        $meta = $em->getClassMetadata(User::class);
        $em->getUnitOfWork()->recomputeSingleEntityChangeSet($meta, $entity);
    }
}

Is it normal by default or is it a bug ? If it's normal, what can i do to ensure Alice go through autowired events ?

Chris53897 commented 3 years ago

Hi. Is this related to API-Platform? Otherwise please open an issue on Alice-Repo

artandor commented 3 years ago

The way I configure the event impacts on wether or not it is transmitted to Alice. But I'm not sure if it's an issue about the autoloader, Alice conf, or smthing else.That's why I submit this issueLe 10 juil. 2021 20:26, chris @.***> a écrit : Hi. Is this related to API-Platform? Otherwise please open an issue on Alice-Repo

—You are receiving this because you authored the thread.Reply to this email directly, view it on GitHub, or unsubscribe.