Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
22 / 22
100.00% covered (success)
100.00%
4 / 4
CRAP
100.00% covered (success)
100.00%
1 / 1
CountryAndPhoneNumber
100.00% covered (success)
100.00%
22 / 22
100.00% covered (success)
100.00%
4 / 4
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
 getFields
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 validateState
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
2
 createRandom
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2namespace Apie\CountryAndPhoneNumber;
3
4use Apie\Core\Attributes\Description;
5use Apie\Core\Attributes\FakeMethod;
6use Apie\Core\ValueObjects\CompositeValueObject;
7use Apie\Core\ValueObjects\CompositeWithOwnValidation;
8use Apie\Core\ValueObjects\Fields\FieldInterface;
9use Apie\Core\ValueObjects\Fields\FromProperty;
10use Apie\CountryAndPhoneNumber\Exceptions\PhoneNumberAndCountryMismatch;
11use Apie\CountryAndPhoneNumber\Factories\PhoneNumberFactory;
12use Apie\CountryAndPhoneNumber\Fields\DynamicPhoneNumberProperty;
13use Apie\Serializer\Exceptions\ValidationException;
14use Faker\Generator;
15use libphonenumber\PhoneNumberFormat;
16use libphonenumber\PhoneNumberUtil;
17use PrinsFrank\Standards\Country\CountryAlpha2;
18use ReflectionProperty;
19
20#[FakeMethod('createRandom')]
21#[Description('Represents a country selection and a phone field that should match the same country.')]
22final class CountryAndPhoneNumber implements CompositeWithOwnValidation
23{
24    use CompositeValueObject;
25
26    public function __construct(private CountryAlpha2 $country, private PhoneNumber $phoneNumber)
27    {
28        $this->validateState();
29    }
30
31    /**
32     * @return array<string, FieldInterface>
33     */
34    public static function getFields(): array
35    {
36        return [
37            'country' => new FromProperty(new ReflectionProperty(CountryAndPhoneNumber::class, 'country')),
38            'phoneNumber' => new DynamicPhoneNumberProperty(),
39        ];
40    }
41
42    private function validateState(): void
43    {
44        if ($this->country !== $this->phoneNumber->fromCountry()) {
45            throw ValidationException::createFromArray(
46                [
47                    'phoneNumber'  => new PhoneNumberAndCountryMismatch(
48                        $this->country,
49                        $this->phoneNumber->fromCountry()
50                    )
51                ]
52            );
53        }
54    }
55
56    public static function createRandom(Generator $generator): self
57    {
58        $phoneNumber = '';
59        do {
60            $country = $generator->randomElement(CountryAlpha2::cases());
61            $phoneNumberUtil = PhoneNumberUtil::getInstance();
62            $phoneNumberObject = $phoneNumberUtil->getExampleNumber($country->value);
63            if ($phoneNumberObject) {
64                $phoneNumber = $phoneNumberUtil->format($phoneNumberObject, PhoneNumberFormat::E164);
65            }
66        } while ($phoneNumber === '');
67        return new self($country, PhoneNumberFactory::createFrom($phoneNumber, $country));
68    }
69}