Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
90.00% covered (success)
90.00%
18 / 20
77.78% covered (warning)
77.78%
7 / 9
CRAP
0.00% covered (danger)
0.00%
0 / 1
DynamicPhoneNumberProperty
90.00% covered (success)
90.00%
18 / 20
77.78% covered (warning)
77.78%
7 / 9
12.14
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getTypehint
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 isOptional
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 fromNative
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
4
 fillField
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 fillMissingField
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 isInitialized
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getValue
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 toNative
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2namespace Apie\CountryAndPhoneNumber\Fields;
3
4use Apie\Core\Exceptions\InvalidTypeException;
5use Apie\Core\ValueObjects\Exceptions\InvalidStringForValueObjectException;
6use Apie\Core\ValueObjects\Fields\FieldInterface;
7use Apie\Core\ValueObjects\Interfaces\ValueObjectInterface;
8use Apie\Core\ValueObjects\Utils;
9use Apie\CountryAndPhoneNumber\CountryAndPhoneNumber;
10use Apie\CountryAndPhoneNumber\Exceptions\PhoneNumberAndCountryMismatch;
11use Apie\CountryAndPhoneNumber\Factories\PhoneNumberFactory;
12use Apie\CountryAndPhoneNumber\InternationalPhoneNumber;
13use Apie\CountryAndPhoneNumber\PhoneNumber;
14use Exception;
15use ReflectionProperty;
16
17final class DynamicPhoneNumberProperty implements FieldInterface
18{
19    private ReflectionProperty $property;
20    private ReflectionProperty $countryProperty;
21
22    public function __construct()
23    {
24        $this->property = new ReflectionProperty(CountryAndPhoneNumber::class, 'phoneNumber');
25        $this->countryProperty = new ReflectionProperty(CountryAndPhoneNumber::class, 'country');
26    }
27
28    public function getTypehint(): string
29    {
30        return PhoneNumber::class;
31    }
32
33    public function isOptional(): bool
34    {
35        return false;
36    }
37
38    public function fromNative(ValueObjectInterface $instance, mixed $value): void
39    {
40        // validation of country property is hit, ignore this error
41        if (!$this->countryProperty->isInitialized($instance)) {
42            return;
43        }
44        $country = $this->countryProperty->getValue($instance);
45        try {
46            $phoneNumber = PhoneNumberFactory::createFrom($value, $country);
47        } catch (InvalidStringForValueObjectException $error) {
48            $phoneNumberCountry = null;
49            try {
50                $phoneNumberCountry = InternationalPhoneNumber::fromNative($value)->toPhoneNumber()->fromCountry();
51            } catch (Exception $ignored) {
52                // fallthrough
53            }
54
55            throw new PhoneNumberAndCountryMismatch($country, $phoneNumberCountry, $error);
56        }
57        self::fillField($instance, $phoneNumber);
58    }
59
60    public function fillField(ValueObjectInterface $instance, mixed $value): void
61    {
62        $this->property->setValue($instance, $value);
63    }
64
65    public function fillMissingField(ValueObjectInterface $instance): void
66    {
67        throw new InvalidTypeException('(missing value)', $this->getTypehint());
68    }
69
70    public function isInitialized(ValueObjectInterface $instance): bool
71    {
72        return $this->property->isInitialized($instance);
73    }
74
75    public function getValue(ValueObjectInterface $instance): mixed
76    {
77        return $this->property->getValue($instance);
78    }
79
80    public function toNative(ValueObjectInterface $instance): string
81    {
82        $value = $this->getValue($instance);
83        return Utils::toNative($value);
84    }
85}