Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
2 / 2
CRAP
100.00% covered (success)
100.00%
1 / 1
GoogleIdentity
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
2 / 2
7
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
 nameParts
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
6
1<?php
2
3declare(strict_types=1);
4
5namespace App\Identity\Application\Port;
6
7use App\Identity\Domain\ValueObject\Email;
8
9use function count;
10
11/**
12 * A verified Google account: the claims we keep out of a validated ID token.
13 * The name claims are optional (Google only returns them with the `profile`
14 * scope, and tokeninfo does not document them), hence the fallback chain in
15 * nameParts().
16 */
17final readonly class GoogleIdentity
18{
19    public function __construct(
20        public string $subject,
21        public Email $email,
22        public ?string $givenName = null,
23        public ?string $familyName = null,
24        public ?string $fullName = null,
25    ) {
26    }
27
28    /**
29     * Name and surnames for auto-provisioning, degrading claim by claim down to
30     * the email local part. Both are always non-empty, so User::sanitizeName()
31     * can never reject them — the user edits them afterwards anyway.
32     *
33     * @return array{0: string, 1: string}
34     */
35    public function nameParts(): array
36    {
37        $words = preg_split('/\s+/', trim((string) $this->fullName), -1, PREG_SPLIT_NO_EMPTY) ?: [];
38
39        // A validated email always has a non-empty local part, so this last
40        // fallback can never be empty itself.
41        $localPart = strstr($this->email->value(), '@', true) ?: $this->email->value();
42
43        $given = trim((string) $this->givenName);
44        $family = trim((string) $this->familyName);
45
46        return [
47            $given !== '' ? $given : ($words[0] ?? $localPart),
48            $family !== '' ? $family : (count($words) > 1 ? implode(' ', array_slice($words, 1)) : $localPart),
49        ];
50    }
51}