Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
2 / 2
CRAP
100.00% covered (success)
100.00%
1 / 1
DeleteUserHandler
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
2 / 2
3
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 handle
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2
3declare(strict_types=1);
4
5namespace App\Identity\Application\Command;
6
7use App\Identity\Application\AuthenticatedUserFinder;
8use App\Identity\Application\Port\PreUserDeletion;
9use App\Identity\Domain\UserRepository;
10use App\Identity\Domain\ValueObject\UserId;
11use Symfony\Component\DependencyInjection\Attribute\AutowireIterator;
12
13final readonly class DeleteUserHandler
14{
15    /** @param iterable<PreUserDeletion> $preDeletionReactors */
16    public function __construct(
17        private AuthenticatedUserFinder $finder,
18        private UserRepository $users,
19        #[AutowireIterator('app.pre_user_deletion')]
20        private iterable $preDeletionReactors,
21    ) {
22    }
23
24    public function handle(DeleteUserCommand $command): void
25    {
26        $user = $this->finder->getOrFail(new UserId($command->userId));
27
28        // Let other contexts react (e.g. Trip reassigns shared trips) before the
29        // row — and its FK cascade to trips -> expenses — is removed.
30        foreach ($this->preDeletionReactors as $reactor) {
31            $reactor->onUserDeletion($command->userId);
32        }
33
34        $this->users->remove($user);
35    }
36}