Issues (7)

src/PhoneHelper.php (1 issue)

Labels
Severity
1
<?php
2
3
namespace LeKoala\PhoneNumber;
4
5
use SilverStripe\i18n\i18n;
6
use libphonenumber\PhoneNumberUtil;
7
use libphonenumber\NumberParseException;
8
use SilverStripe\i18n\Data\Intl\IntlLocales;
9
10
/**
11
 * Helps dealing with phone and countries
12
 */
13
class PhoneHelper
14
{
15
    const DEFAULT_FORMAT = 'NATIONAL';
16
17
    /**
18
     *
19
     * @var array<string>
20
     */
21
    protected static $valid_formats = [
22
        'E164',
23
        'INTERNATIONAL',
24
        'NATIONAL',
25
        'RFC3966'
26
    ];
27
28
    /**
29
     * Alias of PhoneNumberUtil::getInstance
30
     * @return PhoneNumberUtil
31
     */
32
    public static function getPhoneNumberUtil()
33
    {
34
        return PhoneNumberUtil::getInstance();
35
    }
36
37
    /**
38
     * @return string
39
     */
40
    public static function getDefaultCountryCode()
41
    {
42
        return substr(i18n::get_locale(), 3, 2);
43
    }
44
45
    /**
46
     * @param string $code
47
     * @return int|null
48
     */
49
    public static function convertCountryCodeToPrefix($code)
50
    {
51
        $code = strtoupper($code);
52
        $list  = self::listCountryPrefixes();
53
        return $list[$code] ?? null;
54
    }
55
56
    /**
57
     * @return array<string,int>
58
     */
59
    public static function listCountryPrefixes()
60
    {
61
        $countries = self::getCountriesList();
62
        $util = self::getPhoneNumberUtil();
63
        $map = [];
64
        foreach ($countries as $countryCode => $countryName) {
65
            $map[$countryCode] = $util->getCountryCodeForRegion($countryCode);
66
        }
67
        return $map;
68
    }
69
70
    /**
71
     * Get the country list, using IntlLocales
72
     *
73
     * Keys are set to UPPERCASE to match ISO standards
74
     *
75
     * @return array<string,string>
76
     */
77
    public static function getCountriesList()
78
    {
79
        $intl = new IntlLocales;
80
        $countries = $intl->getCountries();
81
        $countries = array_change_key_case($countries, CASE_UPPER);
82
        return $countries;
83
    }
84
85
    /**
86
     * Validate phone number. Error in formatting result in an NumberParseException
87
     * that you must catch yourself.
88
     *
89
     * @throws NumberParseException
90
     * @param string $value
91
     * @param ?string $country An ISO 3166-1 two letter country code (=> UPPERCASE).
92
     * @return bool
93
     */
94
    public static function validatePhoneNumber($value, $country = null)
95
    {
96
        $util = self::getPhoneNumberUtil();
97
98
        // Default country
99
        if ($country === null) {
100
            $country = self::getDefaultCountryCode();
101
        }
102
103
        // It's an international number, let the parser define the country
104
        if (strpos($value, '+') === 0) {
105
            $country = null;
106
        }
107
108
        $number = $util->parse($value, $country);
109
        return $util->isValidNumber($number);
110
    }
111
112
    /**
113
     * Format phone number. Error in formatting result in an NumberParseException
114
     * that you must catch yourself.
115
     *
116
     * @param string $value
117
     * @param string $country An ISO 3166-1 two letter country code.
118
     * @param string|int|null $format NATIONAL by default (=> UPPERCASE)
119
     * @return string
120
     */
121
    public static function formatPhoneNumber($value, $country = null, $format = null)
122
    {
123
        if (empty($value)) {
124
            return '';
125
        }
126
        $util = self::getPhoneNumberUtil();
127
128
        // Default country
129
        if ($country === null) {
130
            $country = self::getDefaultCountryCode();
131
        }
132
133
        // Format
134
        if ($format === null) {
135
            $format = self::DEFAULT_FORMAT;
136
        }
137
        if (is_string($format)) {
138
            $format = strtoupper($format);
139
            if (!(in_array($format, self::$valid_formats))) {
140
                $format = self::DEFAULT_FORMAT;
141
            }
142
            $format = constant("libphonenumber\PhoneNumberFormat::$format");
143
        }
144
145
        // It's an international number, let the parser define the country
146
        if (strpos($value, '+') === 0) {
147
            $country = null;
148
        }
149
150
        // Don't fail
151
        try {
152
            $number = $util->parse($value, $country);
153
        } catch (NumberParseException $e) {
154
            return $value;
155
        }
156
157
        // It's not valid, simply return the given value
158
        if (!$util->isValidNumber($number)) {
159
            return $value;
160
        }
161
162
        return $util->format($number, $format);
0 ignored issues
show
It seems like $format can also be of type string; however, parameter $numberFormat of libphonenumber\PhoneNumberUtil::format() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

162
        return $util->format($number, /** @scrutinizer ignore-type */ $format);
Loading history...
163
    }
164
}
165