Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
77.78% covered (warning)
77.78%
7 / 9
66.67% covered (warning)
66.67%
4 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
TripMember
77.78% covered (warning)
77.78%
7 / 9
66.67% covered (warning)
66.67%
4 / 6
8.70
0.00% covered (danger)
0.00%
0 / 1
 __construct
50.00% covered (danger)
50.00%
1 / 2
0.00% covered (danger)
0.00%
0 / 1
2.50
 tripId
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 userId
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 role
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 changeRole
66.67% covered (warning)
66.67%
2 / 3
0.00% covered (danger)
0.00%
0 / 1
2.15
 createdAt
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3declare(strict_types=1);
4
5namespace App\Trip\Domain;
6
7use App\Trip\Domain\ValueObject\MemberId;
8use App\Trip\Domain\ValueObject\TripId;
9use App\Trip\Domain\ValueObject\TripRole;
10use DateTimeImmutable;
11use Doctrine\ORM\Mapping as ORM;
12use InvalidArgumentException;
13
14/**
15 * A user's editor/viewer membership on a trip. The owner is NOT a member row —
16 * it stays the Trip.ownerId column (single authoritative owner); this table
17 * holds only editor/viewer. Natural composite key (trip_id, user_id): a user
18 * has at most one role per trip, and nothing references a membership row, so no
19 * surrogate id is needed. ponytail: composite PK over a surrogate id.
20 */
21#[ORM\Entity]
22#[ORM\Table(name: 'trip_members')]
23final class TripMember
24{
25    public function __construct(
26        #[ORM\Id]
27        #[ORM\Column(name: 'trip_id', type: 'trip_id')]
28        private readonly TripId $tripId,
29        #[ORM\Id]
30        #[ORM\Column(name: 'user_id', type: 'member_id')]
31        private readonly MemberId $userId,
32        #[ORM\Column(type: 'trip_role', length: 20)]
33        private TripRole $role,
34        #[ORM\Column(name: 'created_at', type: 'datetime_immutable')]
35        private readonly DateTimeImmutable $createdAt = new DateTimeImmutable(),
36    ) {
37        if (!$role->isStorableMembership()) {
38            throw new InvalidArgumentException('A trip membership can only be editor or viewer.');
39        }
40    }
41
42    public function tripId(): TripId
43    {
44        return $this->tripId;
45    }
46
47    public function userId(): MemberId
48    {
49        return $this->userId;
50    }
51
52    public function role(): TripRole
53    {
54        return $this->role;
55    }
56
57    public function changeRole(TripRole $role): void
58    {
59        if (!$role->isStorableMembership()) {
60            throw new InvalidArgumentException('A trip membership can only be editor or viewer.');
61        }
62
63        $this->role = $role;
64    }
65
66    public function createdAt(): DateTimeImmutable
67    {
68        return $this->createdAt;
69    }
70}