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