Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
53.33% covered (warning)
53.33%
8 / 15
50.00% covered (danger)
50.00%
2 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
PhoneNumberFactory
53.33% covered (warning)
53.33%
8 / 15
50.00% covered (danger)
50.00%
2 / 4
11.98
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getClass
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
2
 register
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
12
 createFrom
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2namespace Apie\CountryAndPhoneNumber\Factories;
3
4use Apie\Core\Exceptions\InvalidTypeException;
5use Apie\CountryAndPhoneNumber\BelgianPhoneNumber;
6use Apie\CountryAndPhoneNumber\BritishPhoneNumber;
7use Apie\CountryAndPhoneNumber\CanadianPhoneNumber;
8use Apie\CountryAndPhoneNumber\ChinesePhoneNumber;
9use Apie\CountryAndPhoneNumber\DutchPhoneNumber;
10use Apie\CountryAndPhoneNumber\Exceptions\CountryAlreadyRegistered;
11use Apie\CountryAndPhoneNumber\FrenchPhoneNumber;
12use Apie\CountryAndPhoneNumber\GermanPhoneNumber;
13use Apie\CountryAndPhoneNumber\JapanesePhoneNumber;
14use Apie\CountryAndPhoneNumber\MexicanPhoneNumber;
15use Apie\CountryAndPhoneNumber\PhoneNumber;
16use Apie\CountryAndPhoneNumber\USPhoneNumber;
17use PrinsFrank\Standards\Country\CountryAlpha2;
18
19final class PhoneNumberFactory
20{
21    /**
22     * @var array<string, class-string<PhoneNumber>>
23     */
24    private static array $instantiatedClasses = [
25        'BE' => BelgianPhoneNumber::class,
26        'CA' => CanadianPhoneNumber::class,
27        'CN' => ChinesePhoneNumber::class,
28        'DE' => GermanPhoneNumber::class,
29        'FR' => FrenchPhoneNumber::class,
30        'GB' => BritishPhoneNumber::class,
31        'JP' => JapanesePhoneNumber::class,
32        'MX' => MexicanPhoneNumber::class,
33        'NL' => DutchPhoneNumber::class,
34        'US' => USPhoneNumber::class,
35    ];
36
37    private function __construct()
38    {
39    }
40
41    /**
42     * @return class-string<PhoneNumber>
43     */
44    private static function getClass(CountryAlpha2 $countryEnum): string
45    {
46        $country = $countryEnum->value;
47        if (!isset(self::$instantiatedClasses[$country])) {
48            // this code is evil....
49            $class = eval('return new class("", $countryEnum) extends \Apie\CountryAndPhoneNumber\PhoneNumber {
50                static private \PrinsFrank\Standards\Country\CountryAlpha2 $country;
51                static private bool $ignored = true;
52
53                public function __construct(string $input, ?\PrinsFrank\Standards\Country\CountryAlpha2 $country = null)
54                {
55                    if (self::$ignored && empty($input) && $country !== null) {
56                        self::$country = $country;
57                        self::$ignored = false;
58                        return;
59                    }
60                    parent::__construct($input);
61                }
62
63                static public function fromCountry(): \PrinsFrank\Standards\Country\CountryAlpha2 {
64                    return self::$country;
65                }
66            };');
67            self::$instantiatedClasses[$country] = get_class($class);
68        }
69        return self::$instantiatedClasses[$country];
70    }
71
72    public static function register(string $class): void
73    {
74        if (!is_a($class, PhoneNumber::class, true)) {
75            throw new InvalidTypeException($class, PhoneNumber::class);
76        }
77        $country = $class::fromCountry()->value;
78        if (isset(self::$instantiatedClasses[$country])) {
79            throw new CountryAlreadyRegistered($country);
80        }
81        self::$instantiatedClasses[$country] = $class;
82    }
83
84    public static function createFrom(string $phoneNumber, CountryAlpha2 $countryEnum): PhoneNumber
85    {
86        $class = self::getClass($countryEnum);
87        return new $class($phoneNumber);
88    }
89}