diff --git a/features/app/src/EventListener/ForgotPasswordEventListener.php b/features/app/src/EventListener/ForgotPasswordEventListener.php index d5f2cb8..7f61b36 100644 --- a/features/app/src/EventListener/ForgotPasswordEventListener.php +++ b/features/app/src/EventListener/ForgotPasswordEventListener.php @@ -15,6 +15,7 @@ use App\Entity\User; use CoopTilleuls\ForgotPasswordBundle\Event\CreateTokenEvent; +use CoopTilleuls\ForgotPasswordBundle\Event\ForgotPasswordEvent; use CoopTilleuls\ForgotPasswordBundle\Event\UpdatePasswordEvent; use Doctrine\Bundle\DoctrineBundle\Registry; use Doctrine\ORM\EntityManagerInterface; @@ -56,6 +57,9 @@ public static function getSubscribedEvents() return [ CreateTokenEvent::class => 'onCreateToken', UpdatePasswordEvent::class => 'onUpdatePassword', + // Symfony 4.3 and inferior + ForgotPasswordEvent::CREATE_TOKEN => 'onCreateToken', + ForgotPasswordEvent::UPDATE_PASSWORD => 'onUpdatePassword', ]; } diff --git a/src/Event/ForgotPasswordEvent.php b/src/Event/ForgotPasswordEvent.php index b6614d5..e44bf0d 100644 --- a/src/Event/ForgotPasswordEvent.php +++ b/src/Event/ForgotPasswordEvent.php @@ -14,15 +14,17 @@ namespace CoopTilleuls\ForgotPasswordBundle\Event; use CoopTilleuls\ForgotPasswordBundle\Entity\AbstractPasswordToken; -use Symfony\Contracts\EventDispatcher\Event; /** * @author Vincent CHALAMON * * @deprecated Use CreateTokenEvent and UpdatePasswordEvent instead */ -class ForgotPasswordEvent extends Event +class ForgotPasswordEvent extends PolyfillEvent { + public const CREATE_TOKEN = 'coop_tilleuls_forgot_password.create_token'; + public const UPDATE_PASSWORD = 'coop_tilleuls_forgot_password.update_password'; + protected $passwordToken; protected $password; diff --git a/src/Event/PolyfillEvent.php b/src/Event/PolyfillEvent.php new file mode 100644 index 0000000..668668e --- /dev/null +++ b/src/Event/PolyfillEvent.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace CoopTilleuls\ForgotPasswordBundle\Event; + +use Symfony\Component\EventDispatcher\Event; +use Symfony\Component\EventDispatcher\EventDispatcher; +use Symfony\Contracts\EventDispatcher\Event as ContractsEvent; +use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; + +if (is_subclass_of(EventDispatcher::class, EventDispatcherInterface::class)) { + // Symfony 4.4 and upper + abstract class PolyfillEvent extends ContractsEvent + { + } +} else { + // Symfony 4.3 and inferior + abstract class PolyfillEvent extends Event + { + } +} diff --git a/src/Manager/ForgotPasswordManager.php b/src/Manager/ForgotPasswordManager.php index b629a74..ec55908 100644 --- a/src/Manager/ForgotPasswordManager.php +++ b/src/Manager/ForgotPasswordManager.php @@ -15,9 +15,11 @@ use CoopTilleuls\ForgotPasswordBundle\Entity\AbstractPasswordToken; use CoopTilleuls\ForgotPasswordBundle\Event\CreateTokenEvent; +use CoopTilleuls\ForgotPasswordBundle\Event\ForgotPasswordEvent; use CoopTilleuls\ForgotPasswordBundle\Event\UpdatePasswordEvent; use CoopTilleuls\ForgotPasswordBundle\Manager\Bridge\ManagerInterface; -use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Contracts\EventDispatcher\EventDispatcherInterface as ContractsEventDispatcherInterface; /** * @author Vincent CHALAMON @@ -63,7 +65,11 @@ public function resetPassword($propertyName, $value): void } // Generate password token - $this->dispatcher->dispatch(new CreateTokenEvent($token)); + if ($this->dispatcher instanceof ContractsEventDispatcherInterface) { + $this->dispatcher->dispatch(new CreateTokenEvent($token)); + } else { + $this->dispatcher->dispatch(ForgotPasswordEvent::CREATE_TOKEN, new CreateTokenEvent($token)); + } } /** @@ -74,7 +80,11 @@ public function resetPassword($propertyName, $value): void public function updatePassword(AbstractPasswordToken $passwordToken, $password) { // Update user password - $this->dispatcher->dispatch(new UpdatePasswordEvent($passwordToken, $password)); + if ($this->dispatcher instanceof ContractsEventDispatcherInterface) { + $this->dispatcher->dispatch(new UpdatePasswordEvent($passwordToken, $password)); + } else { + $this->dispatcher->dispatch(ForgotPasswordEvent::UPDATE_PASSWORD, new UpdatePasswordEvent($passwordToken, $password)); + } // Remove PasswordToken $this->manager->remove($passwordToken); diff --git a/tests/Manager/ForgotPasswordManagerTest.php b/tests/Manager/ForgotPasswordManagerTest.php index b49b940..447283d 100644 --- a/tests/Manager/ForgotPasswordManagerTest.php +++ b/tests/Manager/ForgotPasswordManagerTest.php @@ -15,6 +15,7 @@ use CoopTilleuls\ForgotPasswordBundle\Entity\AbstractPasswordToken; use CoopTilleuls\ForgotPasswordBundle\Event\CreateTokenEvent; +use CoopTilleuls\ForgotPasswordBundle\Event\ForgotPasswordEvent; use CoopTilleuls\ForgotPasswordBundle\Event\UpdatePasswordEvent; use CoopTilleuls\ForgotPasswordBundle\Manager\Bridge\ManagerInterface; use CoopTilleuls\ForgotPasswordBundle\Manager\ForgotPasswordManager; @@ -22,8 +23,9 @@ use CoopTilleuls\ForgotPasswordBundle\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; use Prophecy\Argument; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\Security\Core\User\UserInterface; -use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; +use Symfony\Contracts\EventDispatcher\EventDispatcherInterface as ContractsEventDispatcherInterface; /** * @author Vincent CHALAMON @@ -75,9 +77,15 @@ public function testResetPasswordWithNoPreviousToken(): void $this->managerMock->findOneBy('App\Entity\User', ['email' => 'foo@example.com'])->willReturn($this->userMock->reveal())->shouldBeCalledOnce(); $this->passwordManagerMock->findOneByUser($this->userMock->reveal())->willReturn(null)->shouldBeCalledOnce(); $this->passwordManagerMock->createPasswordToken($this->userMock->reveal())->willReturn($tokenMock->reveal())->shouldBeCalledOnce(); - $this->eventDispatcherMock->dispatch(Argument::that(function ($event) use ($tokenMock) { - return $event instanceof CreateTokenEvent && null === $event->getPassword() && $tokenMock->reveal() === $event->getPasswordToken(); - }))->shouldBeCalledOnce(); + if ($this->eventDispatcherMock->reveal() instanceof ContractsEventDispatcherInterface) { + $this->eventDispatcherMock->dispatch(Argument::that(function ($event) use ($tokenMock) { + return $event instanceof CreateTokenEvent && null === $event->getPassword() && $tokenMock->reveal() === $event->getPasswordToken(); + }))->shouldBeCalledOnce(); + } else { + $this->eventDispatcherMock->dispatch(ForgotPasswordEvent::CREATE_TOKEN, Argument::that(function ($event) use ($tokenMock) { + return $event instanceof CreateTokenEvent && null === $event->getPassword() && $tokenMock->reveal() === $event->getPasswordToken(); + }))->shouldBeCalledOnce(); + } $this->manager->resetPassword('email', 'foo@example.com'); } @@ -90,9 +98,15 @@ public function testResetPasswordWithExpiredPreviousToken(): void $this->passwordManagerMock->findOneByUser($this->userMock->reveal())->willReturn($this->tokenMock->reveal())->shouldBeCalledOnce(); $this->tokenMock->isExpired()->willReturn(true)->shouldBeCalledOnce(); $this->passwordManagerMock->createPasswordToken($this->userMock->reveal())->willReturn($tokenMock->reveal())->shouldBeCalledOnce(); - $this->eventDispatcherMock->dispatch(Argument::that(function ($event) use ($tokenMock) { - return $event instanceof CreateTokenEvent && null === $event->getPassword() && $tokenMock->reveal() === $event->getPasswordToken(); - }))->shouldBeCalledOnce(); + if ($this->eventDispatcherMock->reveal() instanceof ContractsEventDispatcherInterface) { + $this->eventDispatcherMock->dispatch(Argument::that(function ($event) use ($tokenMock) { + return $event instanceof CreateTokenEvent && null === $event->getPassword() && $tokenMock->reveal() === $event->getPasswordToken(); + }))->shouldBeCalledOnce(); + } else { + $this->eventDispatcherMock->dispatch(ForgotPasswordEvent::CREATE_TOKEN, Argument::that(function ($event) use ($tokenMock) { + return $event instanceof CreateTokenEvent && null === $event->getPassword() && $tokenMock->reveal() === $event->getPasswordToken(); + }))->shouldBeCalledOnce(); + } $this->manager->resetPassword('email', 'foo@example.com'); } @@ -114,9 +128,15 @@ public function testResetPasswordWithUnexpiredTokenHttp(): void $this->managerMock->findOneBy('App\Entity\User', ['email' => 'foo@example.com'])->willReturn($this->userMock->reveal())->shouldBeCalledOnce(); $this->passwordManagerMock->findOneByUser($this->userMock->reveal())->willReturn($token)->shouldBeCalledOnce(); - $this->eventDispatcherMock->dispatch(Argument::that(function ($event) use ($token) { - return $event instanceof CreateTokenEvent && null === $event->getPassword() && $token === $event->getPasswordToken(); - }))->shouldBeCalledOnce(); + if ($this->eventDispatcherMock->reveal() instanceof ContractsEventDispatcherInterface) { + $this->eventDispatcherMock->dispatch(Argument::that(function ($event) use ($token) { + return $event instanceof CreateTokenEvent && null === $event->getPassword() && $token === $event->getPasswordToken(); + }))->shouldBeCalledOnce(); + } else { + $this->eventDispatcherMock->dispatch(ForgotPasswordEvent::CREATE_TOKEN, Argument::that(function ($event) use ($token) { + return $event instanceof CreateTokenEvent && null === $event->getPassword() && $token === $event->getPasswordToken(); + }))->shouldBeCalledOnce(); + } $this->manager->resetPassword('email', 'foo@example.com'); } @@ -125,9 +145,15 @@ public function testUpdatePassword(): void { $token = $this->tokenMock->reveal(); - $this->eventDispatcherMock->dispatch(Argument::that(function ($event) use ($token) { - return $event instanceof UpdatePasswordEvent && 'bar' === $event->getPassword() && $token === $event->getPasswordToken(); - }))->shouldBeCalledOnce(); + if ($this->eventDispatcherMock->reveal() instanceof ContractsEventDispatcherInterface) { + $this->eventDispatcherMock->dispatch(Argument::that(function ($event) use ($token) { + return $event instanceof UpdatePasswordEvent && 'bar' === $event->getPassword() && $token === $event->getPasswordToken(); + }))->shouldBeCalledOnce(); + } else { + $this->eventDispatcherMock->dispatch(ForgotPasswordEvent::UPDATE_PASSWORD, Argument::that(function ($event) use ($token) { + return $event instanceof UpdatePasswordEvent && 'bar' === $event->getPassword() && $token === $event->getPasswordToken(); + }))->shouldBeCalledOnce(); + } $this->managerMock->remove($token)->shouldBeCalledOnce(); $this->manager->updatePassword($token, 'bar');