Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
16 / 16
100.00% covered (success)
100.00%
3 / 3
CRAP
100.00% covered (success)
100.00%
1 / 1
AcceptInvitationHandler
100.00% covered (success)
100.00%
16 / 16
100.00% covered (success)
100.00%
3 / 3
6
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%
8 / 8
100.00% covered (success)
100.00%
1 / 1
1
 pendingForMe
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
4
1<?php
2
3declare(strict_types=1);
4
5namespace App\Trip\Application\Command;
6
7use App\Trip\Domain\Exceptions\InvitationNotFound;
8use App\Trip\Domain\TripInvitation;
9use App\Trip\Domain\TripInvitationRepository;
10use App\Trip\Domain\TripMember;
11use App\Trip\Domain\TripMemberRepository;
12use App\Trip\Domain\ValueObject\InvitationId;
13use App\Trip\Domain\ValueObject\MemberId;
14
15/**
16 * The invitee accepts: mints the editor/viewer member row and marks the
17 * invitation accepted. Two saves in sequence (no Messenger/UoW bus here);
18 * ponytail: fine at this scale, wrap in a transaction if it ever needs to be atomic.
19 */
20final readonly class AcceptInvitationHandler
21{
22    public function __construct(
23        private TripInvitationRepository $invitations,
24        private TripMemberRepository $members,
25    ) {
26    }
27
28    public function handle(AcceptInvitationCommand $command): void
29    {
30        $invitation = $this->pendingForMe($command);
31
32        $this->members->save(new TripMember(
33            $invitation->tripId(),
34            $invitation->inviteeId(),
35            $invitation->role(),
36        ));
37
38        $invitation->accept();
39        $this->invitations->save($invitation);
40    }
41
42    private function pendingForMe(AcceptInvitationCommand $command): TripInvitation
43    {
44        $invitationId = new InvitationId($command->invitationId);
45        $invitation = $this->invitations->ofId($invitationId);
46
47        if ($invitation === null
48            || !$invitation->inviteeId()->equals(new MemberId($command->userId))
49            || !$invitation->isPending()) {
50            throw InvitationNotFound::withId($invitationId);
51        }
52
53        return $invitation;
54    }
55}