Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
formatter.php
1<?php
2
4
6{
7 public static function format(PhoneNumber $number, $formatType, $forceNationalPrefix = false)
8 {
9 if(!$number->isValid())
10 {
11 return $number->getRawNumber();
12 }
13 if($formatType === Format::E164)
14 {
15 return '+' . $number->getCountryCode() . $number->getNationalNumber();
16 }
17
18 $countryMetadata = MetadataProvider::getInstance()->getCountryMetadata($number->getCountry());
19 $format = static::selectFormatForNumber($number, $formatType, $countryMetadata);
20
21 if($format)
22 {
23 $formattedNationalNumber = static::formatNationalNumber(
24 $number->getNationalNumber(),
25 $formatType,
26 $countryMetadata,
27 $format,
28 $forceNationalPrefix
29 );
30 }
31 else
32 {
33 $formattedNationalNumber = $number->getNationalNumber();
34 }
35
36 if($number->hasExtension())
37 {
38 $formattedNationalNumber .= $number->getExtensionSeparator() ." ". $number->getExtension();
39 }
40
41 if($formatType == Format::INTERNATIONAL)
42 {
43 return '+' . $number->getCountryCode() . ' ' . $formattedNationalNumber;
44 }
45 else if($formatType == Format::NATIONAL)
46 {
47 return $formattedNationalNumber;
48 }
49
50 return $number->getRawNumber();
51 }
52
58 public static function formatOriginal(PhoneNumber $number)
59 {
60 if(!$number->isValid())
61 return $number->getRawNumber();
62
63 $format = static::selectOriginalFormatForNumber($number);
64 if(!$format)
65 return $number->getRawNumber();
66
67 $formattedNationalNumber = static::formatNationalNumberWithOriginalFormat(
68 $number,
69 $format
70 );
71
72 if($number->hasExtension())
73 {
74 $formattedNationalNumber .= $number->getExtensionSeparator() . " " . $number->getExtension();
75 }
76
77 if($number->isInternational())
78 {
79 $formattedNumber = ($number->hasPlus() ? '+' : '') . $number->getCountryCode() . ' ' . $formattedNationalNumber;
80 }
81 else
82 {
83 $formattedNumber = $formattedNationalNumber;
84 }
85
86 // If no digit was inserted/removed/altered in a process of formatting, return the formatted number;
87 $normalizedFormattedNumber = static::stripNonNumbers($formattedNumber);
88 $normalizedRawInput = static::stripNonNumbers($number->getRawNumber());
89 if ($normalizedFormattedNumber !== $normalizedRawInput)
90 {
91 $formattedNumber = $number->getRawNumber();
92 }
93
94 return $formattedNumber;
95 }
96
97 protected static function selectFormatForNumber(PhoneNumber $number, $formatType, $countryMetadata)
98 {
99 $nationalNumber = $number->getNationalNumber();
100 $isInternational = ($formatType === Format::INTERNATIONAL);
101 $availableFormats = static::getAvailableFormats($countryMetadata);
102
103 foreach ($availableFormats as $format)
104 {
105 if($isInternational && isset($format['intlFormat']) && $format['intlFormat'] === 'NA')
106 continue;
107
108 if(isset($format['leadingDigits']) && !static::matchLeadingDigits($nationalNumber, $format['leadingDigits']))
109 {
110 continue;
111 }
112
113 $formatPatternRegex = '/^' . $format['pattern'] . '$/';
114 if(preg_match($formatPatternRegex, $nationalNumber))
115 {
116 return $format;
117 }
118 }
119 return false;
120 }
121
122 protected static function selectOriginalFormatForNumber(PhoneNumber $number)
123 {
124 $nationalNumber = $number->getNationalNumber();
125 $isInternational = $number->isInternational();
126 $hasNationalPrefix = $number->getNationalPrefix() != '';
127 $countryMetadata = MetadataProvider::getInstance()->getCountryMetadata($number->getCountry());
128 $availableFormats = static::getAvailableFormats($countryMetadata);
129
130 foreach ($availableFormats as $format)
131 {
132 if($isInternational)
133 {
134 if(isset($format['intlFormat']) && $format['intlFormat'] === 'NA')
135 {
136 continue;
137 }
138 }
139 else
140 {
141 if($hasNationalPrefix && !static::_isNationalPrefixSupported($format, $countryMetadata))
142 {
143 continue;
144 }
145 }
146
147 if(isset($format['leadingDigits']) && !static::matchLeadingDigits($nationalNumber, $format['leadingDigits']))
148 {
149 continue;
150 }
151
152 $formatPatternRegex = '/^' . $format['pattern'] . '$/';
153 if(preg_match($formatPatternRegex, $nationalNumber))
154 {
155 return $format;
156 }
157 }
158 return false;
159 }
160
167 protected static function matchLeadingDigits($phoneNumber, $leadingDigits)
168 {
169 if(is_array($leadingDigits))
170 {
171 foreach ($leadingDigits as $leadingDigitsSample)
172 {
173 $re = '/' . $leadingDigitsSample . '/A';
174 if(preg_match($re, $phoneNumber, $matches))
175 {
176 return $matches;
177 }
178 }
179 }
180 else
181 {
182 $re = '/' . $leadingDigits . '/A';
183 if(preg_match($re, $phoneNumber, $matches))
184 {
185 return $matches;
186 }
187 }
188 return false;
189 }
190
199 protected static function formatNationalNumber($nationalNumber, $formatType, $countryMetadata, $format, $forceNationalPrefix)
200 {
201 $isInternational = ($formatType === Format::INTERNATIONAL);
202 $replaceFormat = (isset($format['intlFormat']) && $isInternational) ? $format['intlFormat'] : $format['format'];
203 $patternRegex = '/' . $format['pattern'] . '/';
204
205 if(!$isInternational)
206 {
207 $nationalPrefixFormattingRule = static::getNationalPrefixFormattingRule($format, $countryMetadata);
208 if($nationalPrefixFormattingRule != '')
209 {
210 $nationalPrefixFormattingRule = str_replace(array('$NP', '$FG'), array($countryMetadata['nationalPrefix'], '$1'), $nationalPrefixFormattingRule);
211 $replaceFormat = preg_replace('/(\\$\\d)/', $nationalPrefixFormattingRule, $replaceFormat, 1);
212 }
213 else
214 {
215 $replaceFormat = $countryMetadata['nationalPrefix'] . ' ' . $replaceFormat;
216 }
217 }
218
219 return preg_replace($patternRegex, $replaceFormat, $nationalNumber);
220 }
221
222 protected static function formatNationalNumberWithOriginalFormat(PhoneNumber $number, $format)
223 {
224 $isInternational = $number->isInternational();
225 $replaceFormat = (isset($format['intlFormat']) && $isInternational) ? $format['intlFormat'] : $format['format'];
226 $patternRegex = '/' . $format['pattern'] . '/';
227 $nationalNumber = $number->getNationalNumber();
228 $countryMetadata = MetadataProvider::getInstance()->getCountryMetadata($number->getCountry());
229 $nationalPrefix = static::getNationalPrefix($countryMetadata, true);
230 $hasNationalPrefix = static::numberContainsNationalPrefix($number->getRawNumber(), $nationalPrefix, $countryMetadata);
231
232 if(!$isInternational && $hasNationalPrefix)
233 {
234 $nationalPrefixFormattingRule = static::getNationalPrefixFormattingRule($format, $countryMetadata);
235 if($nationalPrefixFormattingRule != '')
236 {
237 $nationalPrefixFormattingRule = str_replace(array('$NP', '$FG'), array($nationalPrefix, '$1'), $nationalPrefixFormattingRule);
238 $replaceFormat = preg_replace('/(\\$\\d)/', $nationalPrefixFormattingRule, $replaceFormat, 1);
239 }
240 else
241 {
242 $replaceFormat = $nationalPrefix . ' ' . $replaceFormat;
243 }
244 }
245
246 return preg_replace($patternRegex, $replaceFormat, $nationalNumber);
247 }
248
249 protected static function getNationalPrefix($countryMetadata, $stripNonDigits)
250 {
251 if(!isset($countryMetadata['nationalPrefix']))
252 {
253 return '';
254 }
255
256 $nationalPrefix = $countryMetadata['nationalPrefix'];
257 if ($stripNonDigits)
258 {
259 $nationalPrefix = static::stripNonNumbers($nationalPrefix);
260 }
261 return $nationalPrefix;
262 }
263
264 protected static function getNationalPrefixFormattingRule($format, $countryMetadata)
265 {
266 if(isset($format['nationalPrefixFormattingRule']))
267 {
268 return $format['nationalPrefixFormattingRule'];
269 }
270 else
271 {
272 $countryCode = $countryMetadata['countryCode'];
273 $countriesForCode = MetadataProvider::getInstance()->getCountriesByCode($countryCode);
274 $mainCountry = $countriesForCode[0];
275 $mainCountryMetadata = MetadataProvider::getInstance()->getCountryMetadata($mainCountry);
276 return $mainCountryMetadata['nationalPrefixFormattingRule'] ?? '';
277 }
278 }
279
280
281 protected static function getNationalPrefixOptional($countryMetadata, $format)
282 {
283 if(is_array($format) && isset($format['nationalPrefixOptionalWhenFormatting']))
284 return $format['nationalPrefixOptionalWhenFormatting'];
285 else return $countryMetadata['nationalPrefixOptionalWhenFormatting'] ?? false;
286 }
287
296 protected static function numberContainsNationalPrefix($phoneNumber, $nationalPrefix, $countryMetadata)
297 {
298 if($nationalPrefix == '')
299 {
300 return false;
301 }
302
303 if (mb_strpos($phoneNumber, $nationalPrefix) === 0)
304 {
305 // Some Japanese numbers (e.g. 00777123) might be mistaken to contain the national prefix
306 // when written without it (e.g. 0777123) if we just do prefix matching. To tackle that, we
307 // check the validity of the number if the assumed national prefix is removed (777123 won't
308 // be valid in Japan).
309 $a = mb_substr($phoneNumber, mb_strlen($nationalPrefix));
310
311 return Parser::getInstance()->parse($a, $countryMetadata['id'])->isValid();
312 }
313 else
314 {
315 return false;
316 }
317 }
318
324 protected static function getAvailableFormats($countryMetadata)
325 {
326 if (isset($countryMetadata['availableFormats']) && is_array($countryMetadata['availableFormats']))
327 {
328 return $countryMetadata['availableFormats'];
329 }
330
331 $countryCode = $countryMetadata['countryCode'] ?? '';
332 $countriesForCode = MetadataProvider::getInstance()->getCountriesByCode($countryCode);
333 $mainCountry = $countriesForCode[0] ?? '';
334 $mainCountryMetadata = MetadataProvider::getInstance()->getCountryMetadata($mainCountry);
335
336 return (
337 isset($mainCountryMetadata['availableFormats']) && is_array($mainCountryMetadata['availableFormats'])
338 ? $mainCountryMetadata['availableFormats']
339 : []
340 );
341 }
342
352 protected static function _isNationalPrefixSupported($format, $countryMetadata)
353 {
354 $nationalPrefixFormattingRule = static::getNationalPrefixFormattingRule($format, $countryMetadata);
355
356 $result = (!$nationalPrefixFormattingRule || preg_match('/\$NP/', $nationalPrefixFormattingRule));
357 return $result;
358 }
359
360 protected static function stripNonNumbers($string)
361 {
362 return preg_replace("/[^\d]/", "", $string);
363 }
364}
static getNationalPrefix($countryMetadata, $stripNonDigits)
static selectFormatForNumber(PhoneNumber $number, $formatType, $countryMetadata)
Definition formatter.php:97
static matchLeadingDigits($phoneNumber, $leadingDigits)
static numberContainsNationalPrefix($phoneNumber, $nationalPrefix, $countryMetadata)
static getNationalPrefixFormattingRule($format, $countryMetadata)
static _isNationalPrefixSupported($format, $countryMetadata)
static getAvailableFormats($countryMetadata)
static selectOriginalFormatForNumber(PhoneNumber $number)
static formatNationalNumber($nationalNumber, $formatType, $countryMetadata, $format, $forceNationalPrefix)
static formatNationalNumberWithOriginalFormat(PhoneNumber $number, $format)
static formatOriginal(PhoneNumber $number)
Definition formatter.php:58
static format(PhoneNumber $number, $formatType, $forceNationalPrefix=false)
Definition formatter.php:7
static getNationalPrefixOptional($countryMetadata, $format)