Completed
Push — upstream-8.3.1 ( 732911 )
by Joshua
11:17
created

testGetNationalSignificantNumber_ManyLeadingZeros()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 14
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 14
c 0
b 0
f 0
rs 9.4285
cc 1
eloc 9
nc 1
nop 0
1
<?php
2
3
namespace libphonenumber\Tests\core;
4
5
use libphonenumber\CountryCodeSource;
6
use libphonenumber\CountryCodeToRegionCodeMapForTesting;
7
use libphonenumber\MatchType;
8
use libphonenumber\NumberFormat;
9
use libphonenumber\NumberParseException;
10
use libphonenumber\PhoneMetadata;
11
use libphonenumber\PhoneNumber;
12
use libphonenumber\PhoneNumberDesc;
13
use libphonenumber\PhoneNumberFormat;
14
use libphonenumber\PhoneNumberType;
15
use libphonenumber\PhoneNumberUtil;
16
use libphonenumber\RegionCode;
17
use libphonenumber\ValidationResult;
18
19
class PhoneNumberUtilTest extends \PHPUnit_Framework_TestCase
20
{
21
    const TEST_META_DATA_FILE_PREFIX = "../../tests/core/data/PhoneNumberMetadataForTesting";
22
    private static $bsNumber = null;
23
    private static $internationalTollFree = null;
24
    private static $sgNumber = null;
25
    private static $usShortByOneNumber = null;
26
    private static $usTollFree = null;
27
    private static $usNumber = null;
28
    private static $usLocalNumber = null;
29
    private static $usLongNumber = null;
30
    private static $nzNumber = null;
31
    private static $usPremium = null;
32
    private static $usSpoof = null;
33
    private static $usSpoofWithRawInput = null;
34
    private static $gbMobile = null;
35
    private static $bsMobile = null;
36
    private static $gbNumber = null;
37
    private static $deShortNumber = null;
38
    private static $itMobile = null;
39
    private static $itNumber = null;
40
    private static $auNumber = null;
41
    private static $arMobile = null;
42
    private static $arNumber = null;
43
    private static $mxMobile1 = null;
44
    private static $mxNumber1 = null;
45
    private static $mxMobile2 = null;
46
    private static $mxNumber2 = null;
47
    private static $deNumber = null;
48
    private static $jpStarNumber = null;
49
    private static $internationalTollFreeTooLong = null;
50
    private static $universalPremiumRate = null;
51
    private static $alphaNumericNumber = null;
52
    private static $aeUAN = null;
53
    private static $unknownCountryCodeNoRawInput = null;
54
    /**
55
     * @var PhoneNumberUtil
56
     */
57
    protected $phoneUtil;
58
59
    public function setUp()
60
    {
61
        $this->phoneUtil = self::initializePhoneUtilForTesting();
62
    }
63
64
    private static function initializePhoneUtilForTesting()
65
    {
66
        self::$bsNumber = new PhoneNumber();
67
        self::$bsNumber->setCountryCode(1)->setNationalNumber(2423651234);
68
        self::$bsMobile = new PhoneNumber();
69
        self::$bsMobile->setCountryCode(1)->setNationalNumber(2423591234);
70
        self::$internationalTollFree = new PhoneNumber();
71
        self::$internationalTollFree->setCountryCode(800)->setNationalNumber(12345678);
72
        self::$internationalTollFreeTooLong = new PhoneNumber();
73
        self::$internationalTollFreeTooLong->setCountryCode(800)->setNationalNumber(123456789);
74
        self::$universalPremiumRate = new PhoneNumber();
75
        self::$universalPremiumRate->setCountryCode(979)->setNationalNumber(123456789);
76
        self::$sgNumber = new PhoneNumber();
77
        self::$sgNumber->setCountryCode(65)->setNationalNumber(65218000);
78
        // A too-long and hence invalid US number.
79
        self::$usLongNumber = new PhoneNumber();
80
        self::$usLongNumber->setCountryCode(1)->setNationalNumber(65025300001);
81
        self::$usShortByOneNumber = new PhoneNumber();
82
        self::$usShortByOneNumber->setCountryCode(1)->setNationalNumber(650253000);
83
        self::$usTollFree = new PhoneNumber();
84
        self::$usTollFree->setCountryCode(1)->setNationalNumber(8002530000);
85
        self::$usNumber = new PhoneNumber();
86
        self::$usNumber->setCountryCode(1)->setNationalNumber(6502530000);
87
        self::$usLocalNumber = new PhoneNumber();
88
        self::$usLocalNumber->setCountryCode(1)->setNationalNumber(2530000);
89
        self::$nzNumber = new PhoneNumber();
90
        self::$nzNumber->setCountryCode(64)->setNationalNumber(33316005);
91
        self::$usPremium = new PhoneNumber();
92
        self::$usPremium->setCountryCode(1)->setNationalNumber(9002530000);
93
        self::$usSpoof = new PhoneNumber();
94
        self::$usSpoof->setCountryCode(1)->setNationalNumber(0);
95
        self::$usSpoofWithRawInput = new PhoneNumber();
96
        self::$usSpoofWithRawInput->setCountryCode(1)->setNationalNumber(0)->setRawInput("000-000-0000");
97
        self::$gbMobile = new PhoneNumber();
98
        self::$gbMobile->setCountryCode(44)->setNationalNumber(7912345678);
99
        self::$gbNumber = new PhoneNumber();
100
        self::$gbNumber->setCountryCode(44)->setNationalNumber(2070313000);
101
        self::$deShortNumber = new PhoneNumber();
102
        self::$deShortNumber->setCountryCode(49)->setNationalNumber(1234);
103
        self::$itMobile = new PhoneNumber();
104
        self::$itMobile->setCountryCode(39)->setNationalNumber(345678901);
105
        self::$itNumber = new PhoneNumber();
106
        self::$itNumber->setCountryCode(39)->setNationalNumber(236618300)->setItalianLeadingZero(true);
107
        self::$auNumber = new PhoneNumber();
108
        self::$auNumber->setCountryCode(61)->setNationalNumber(236618300);
109
        self::$arMobile = new PhoneNumber();
110
        self::$arMobile->setCountryCode(54)->setNationalNumber(91187654321);
111
        self::$arNumber = new PhoneNumber();
112
        self::$arNumber->setCountryCode(54)->setNationalNumber(1187654321);
113
114
        self::$mxMobile1 = new PhoneNumber();
115
        self::$mxMobile1->setCountryCode(52)->setNationalNumber(12345678900);
116
        self::$mxNumber1 = new PhoneNumber();
117
        self::$mxNumber1->setCountryCode(52)->setNationalNumber(3312345678);
118
        self::$mxMobile2 = new PhoneNumber();
119
        self::$mxMobile2->setCountryCode(52)->setNationalNumber(15512345678);
120
        self::$mxNumber2 = new PhoneNumber();
121
        self::$mxNumber2->setCountryCode(52)->setNationalNumber(8211234567);
122
        // Note that this is the same as the example number for DE in the metadata.
123
        self::$deNumber = new PhoneNumber();
124
        self::$deNumber->setCountryCode(49)->setNationalNumber(30123456);
125
        self::$jpStarNumber = new PhoneNumber();
126
        self::$jpStarNumber->setCountryCode(81)->setNationalNumber(2345);
127
        self::$alphaNumericNumber = new PhoneNumber();
128
        self::$alphaNumericNumber->setCountryCode(1)->setNationalNumber(80074935247);
129
        self::$aeUAN = new PhoneNumber();
130
        self::$aeUAN->setCountryCode(971)->setNationalNumber(600123456);
131
        self::$unknownCountryCodeNoRawInput = new PhoneNumber();
132
        self::$unknownCountryCodeNoRawInput->setCountryCode(2)->setNationalNumber(12345);
133
134
        PhoneNumberUtil::resetInstance();
135
        return PhoneNumberUtil::getInstance(
136
            self::TEST_META_DATA_FILE_PREFIX,
137
            CountryCodeToRegionCodeMapForTesting::$countryCodeToRegionCodeMapForTesting
138
        );
139
    }
140
141
    public function testGetSupportedRegions()
142
    {
143
        $this->assertGreaterThan(0, count($this->phoneUtil->getSupportedRegions()));
144
    }
145
146
    public function testGetSupportedGlobalNetworkCallingCodes()
147
    {
148
        $globalNetworkCallingCodes = $this->phoneUtil->getSupportedGlobalNetworkCallingCodes();
149
150
        $this->assertGreaterThan(0, count($globalNetworkCallingCodes));
151
152
        foreach ($globalNetworkCallingCodes as $callingCode) {
153
            $this->assertGreaterThan(0, $callingCode);
154
            $this->assertEquals(RegionCode::UN001, $this->phoneUtil->getRegionCodeForCountryCode($callingCode));
155
        }
156
    }
157
158
    public function testGetInstanceLoadBadMetadata()
159
    {
160
        $this->assertNull($this->phoneUtil->getMetadataForRegion("No Such Region"));
161
        $this->assertNull($this->phoneUtil->getMetadataForRegion(-1));
162
    }
163
164
    public function testGetInstanceLoadUSMetadata()
165
    {
166
        $metadata = $this->phoneUtil->getMetadataForRegion(RegionCode::US);
167
        $this->assertEquals("US", $metadata->getId());
168
        $this->assertEquals(1, $metadata->getCountryCode());
169
        $this->assertEquals("011", $metadata->getInternationalPrefix());
170
        $this->assertTrue($metadata->hasNationalPrefix());
171
        $this->assertEquals(2, $metadata->numberFormatSize());
172
        $this->assertEquals("(\\d{3})(\\d{3})(\\d{4})", $metadata->getNumberFormat(1)->getPattern());
173
        $this->assertEquals("$1 $2 $3", $metadata->getNumberFormat(1)->getFormat());
174
        $this->assertEquals("[13-689]\\d{9}|2[0-35-9]\\d{8}", $metadata->getGeneralDesc()->getNationalNumberPattern());
175
        $this->assertEquals("[13-689]\\d{9}|2[0-35-9]\\d{8}", $metadata->getFixedLine()->getNationalNumberPattern());
176
        $this->assertCount(1, $metadata->getGeneralDesc()->getPossibleLength());
177
        $possibleLength = $metadata->getGeneralDesc()->getPossibleLength();
178
        $this->assertEquals(10, $possibleLength[0]);
179
        // Possible lengths are the same as the general description, so aren't stored separately in the
180
        // toll free element as well.
181
        $this->assertCount(0, $metadata->getTollFree()->getPossibleLength());
182
        $this->assertEquals("900\\d{7}", $metadata->getPremiumRate()->getNationalNumberPattern());
183
        // No shared-cost data is available, so it should be initialised to "NA".
184
        $this->assertEquals("NA", $metadata->getSharedCost()->getNationalNumberPattern());
185
    }
186
187
    public function testGetInstanceLoadDEMetadata()
188
    {
189
        $metadata = $this->phoneUtil->getMetadataForRegion(RegionCode::DE);
190
        $this->assertEquals("DE", $metadata->getId());
191
        $this->assertEquals(49, $metadata->getCountryCode());
192
        $this->assertEquals("00", $metadata->getInternationalPrefix());
193
        $this->assertEquals("0", $metadata->getNationalPrefix());
194
        $this->assertEquals(6, $metadata->numberFormatSize());
195
        $this->assertEquals(1, $metadata->getNumberFormat(5)->leadingDigitsPatternSize());
196
        $this->assertEquals("900", $metadata->getNumberFormat(5)->getLeadingDigitsPattern(0));
197
        $this->assertEquals("(\\d{3})(\\d{3,4})(\\d{4})", $metadata->getNumberFormat(5)->getPattern());
198
        $this->assertEquals("$1 $2 $3", $metadata->getNumberFormat(5)->getFormat());
199
        $this->assertCount(2, $metadata->getGeneralDesc()->getPossibleLengthLocalOnly());
200
        $this->assertCount(8, $metadata->getGeneralDesc()->getPossibleLength());
201
        // Nothing is present for fixed-line, since it is the same as the general desc, so for
202
        // efficiency reasons we don't store an extra value.
203
        $this->assertCount(0, $metadata->getFixedLine()->getPossibleLength());
204
        $this->assertCount(2, $metadata->getMobile()->getPossibleLength());
205
206
        $this->assertEquals(
207
            "(?:[24-6]\\d{2}|3[03-9]\\d|[789](?:0[2-9]|[1-9]\\d))\\d{1,8}",
208
            $metadata->getFixedLine()->getNationalNumberPattern()
209
        );
210
        $this->assertEquals("30123456", $metadata->getFixedLine()->getExampleNumber());
211
        $this->assertContains(10, $metadata->getTollFree()->getPossibleLength());
212
        $this->assertEquals("900([135]\\d{6}|9\\d{7})", $metadata->getPremiumRate()->getNationalNumberPattern());
213
    }
214
215
    public function testGetInstanceLoadARMetadata()
216
    {
217
        $metadata = $this->phoneUtil->getMetadataForRegion(RegionCode::AR);
218
        $this->assertEquals("AR", $metadata->getId());
219
        $this->assertEquals(54, $metadata->getCountryCode());
220
        $this->assertEquals("00", $metadata->getInternationalPrefix());
221
        $this->assertEquals("0", $metadata->getNationalPrefix());
222
        $this->assertEquals("0(?:(11|343|3715)15)?", $metadata->getNationalPrefixForParsing());
223
        $this->assertEquals("9$1", $metadata->getNationalPrefixTransformRule());
224
        $this->assertEquals("$2 15 $3-$4", $metadata->getNumberFormat(2)->getFormat());
225
        $this->assertEquals("(9)(\\d{4})(\\d{2})(\\d{4})", $metadata->getNumberFormat(3)->getPattern());
226
        $this->assertEquals("(9)(\\d{4})(\\d{2})(\\d{4})", $metadata->getIntlNumberFormat(3)->getPattern());
227
        $this->assertEquals("$1 $2 $3 $4", $metadata->getIntlNumberFormat(3)->getFormat());
228
    }
229
230
    public function testGetInstanceLoadInternationalTollFreeMetadata()
231
    {
232
        $metadata = $this->phoneUtil->getMetadataForNonGeographicalRegion(800);
233
        $this->assertEquals("001", $metadata->getId());
234
        $this->assertEquals(800, $metadata->getCountryCode());
235
        $this->assertEquals("$1 $2", $metadata->getNumberFormat(0)->getFormat());
236
        $this->assertEquals("(\\d{4})(\\d{4})", $metadata->getNumberFormat(0)->getPattern());
237
        $this->assertCount(0, $metadata->getGeneralDesc()->getPossibleLengthLocalOnly());
238
        $this->assertCount(1, $metadata->getGeneralDesc()->getPossibleLength());
239
        $this->assertEquals("12345678", $metadata->getTollFree()->getExampleNumber());
240
    }
241
242
    public function testIsNumberGeographical()
243
    {
244
        $this->assertFalse($this->phoneUtil->isNumberGeographical(self::$bsMobile)); // Bahamas, mobile phone number.
245
        $this->assertTrue($this->phoneUtil->isNumberGeographical(self::$auNumber)); // Australian fixed line number.
246
        $this->assertFalse($this->phoneUtil->isNumberGeographical(self::$internationalTollFree)); // International toll
247
        // free number
248
    }
249
250
    public function testIsLeadingZeroPossible()
251
    {
252
        $this->assertTrue($this->phoneUtil->isLeadingZeroPossible(39)); // Italy
253
        $this->assertFalse($this->phoneUtil->isLeadingZeroPossible(1)); // USA
254
        $this->assertTrue($this->phoneUtil->isLeadingZeroPossible(800)); // International toll free numbers
255
        $this->assertFalse($this->phoneUtil->isLeadingZeroPossible(979)); // International premium-rate
256
        $this->assertFalse(
257
            $this->phoneUtil->isLeadingZeroPossible(888)
258
        ); // Not in metadata file, just default to false.
259
    }
260
261
    public function testGetLengthOfGeographicalAreaCode()
262
    {
263
        // Google MTV, which has area code "650".
264
        $this->assertEquals(3, $this->phoneUtil->getLengthOfGeographicalAreaCode(self::$usNumber));
265
266
        // A North America toll-free number, which has no area code.
267
        $this->assertEquals(0, $this->phoneUtil->getLengthOfGeographicalAreaCode(self::$usTollFree));
268
269
        // Google London, which has area code "20".
270
        $this->assertEquals(2, $this->phoneUtil->getLengthOfGeographicalAreaCode(self::$gbNumber));
271
272
        // A mobile number in the UK does not have an area code (by default, mobile numbers do not,
273
        // unless they have been added to our list of exceptions).
274
        $this->assertEquals(0, $this->phoneUtil->getLengthOfGeographicalAreaCode(self::$gbMobile));
275
276
        // A UK mobile phone, which has no area code.
277
        $this->assertEquals(0, $this->phoneUtil->getLengthOfGeographicalAreaCode(self::$gbMobile));
278
279
        // Google Buenos Aires, which has area code "11".
280
        $this->assertEquals(2, $this->phoneUtil->getLengthOfGeographicalAreaCode(self::$arNumber));
281
282
        // A mobile number in Argentina also has an area code.
283
        $this->assertEquals(3, $this->phoneUtil->getLengthOfGeographicalAreaCode(self::$arMobile));
284
285
        // Google Sydney, which has area code "2".
286
        $this->assertEquals(1, $this->phoneUtil->getLengthOfGeographicalAreaCode(self::$auNumber));
287
288
        // Italian numbers - there is no national prefix, but it still has an area code.
289
        $this->assertEquals(2, $this->phoneUtil->getLengthOfGeographicalAreaCode(self::$itNumber));
290
291
        // Google Singapore. Singapore has no area code and no national prefix.
292
        $this->assertEquals(0, $this->phoneUtil->getLengthOfGeographicalAreaCode(self::$sgNumber));
293
294
        // An invalid US number (1 digit shorter), which has no area code.
295
        $this->assertEquals(0, $this->phoneUtil->getLengthOfGeographicalAreaCode(self::$usShortByOneNumber));
296
297
        // An international toll free number, which has no area code.
298
        $this->assertEquals(0, $this->phoneUtil->getLengthOfGeographicalAreaCode(self::$internationalTollFree));
299
300
        // A mobile number from China is geographical, but does not have an area code.
301
        $cnMobile = new PhoneNumber();
302
        $cnMobile->setCountryCode(86)->setNationalNumber('18912341234');
303
304
        $this->assertEquals(0, $this->phoneUtil->getLengthOfGeographicalAreaCode($cnMobile));
305
    }
306
307
    public function testGetLengthOfNationalDestinationCode()
308
    {
309
        // Google MTV, which has national destination code (NDC) "650".
310
        $this->assertEquals(3, $this->phoneUtil->getLengthOfNationalDestinationCode(self::$usNumber));
311
312
        // A North America toll-free number, which has NDC "800".
313
        $this->assertEquals(3, $this->phoneUtil->getLengthOfNationalDestinationCode(self::$usTollFree));
314
315
        // Google London, which has NDC "20".
316
        $this->assertEquals(2, $this->phoneUtil->getLengthOfNationalDestinationCode(self::$gbNumber));
317
318
        // A UK mobile phone, which has NDC "7912".
319
        $this->assertEquals(4, $this->phoneUtil->getLengthOfNationalDestinationCode(self::$gbMobile));
320
321
        // Google Buenos Aires, which has NDC "11".
322
        $this->assertEquals(2, $this->phoneUtil->getLengthOfNationalDestinationCode(self::$arNumber));
323
324
        // An Argentinian mobile which has NDC "911".
325
        $this->assertEquals(3, $this->phoneUtil->getLengthOfNationalDestinationCode(self::$arMobile));
326
327
        // Google Sydney, which has NDC "2".
328
        $this->assertEquals(1, $this->phoneUtil->getLengthOfNationalDestinationCode(self::$auNumber));
329
330
        // Google Singapore, which has NDC "6521".
331
        $this->assertEquals(4, $this->phoneUtil->getLengthOfNationalDestinationCode(self::$sgNumber));
332
333
        // An invalid US number (1 digit shorter), which has no NDC.
334
        $this->assertEquals(0, $this->phoneUtil->getLengthOfNationalDestinationCode(self::$usShortByOneNumber));
335
336
        // A number containing an invalid country calling code, which shouldn't have any NDC.
337
        $number = new PhoneNumber();
338
        $number->setCountryCode(123)->setNationalNumber(6502530000);
339
        $this->assertEquals(0, $this->phoneUtil->getLengthOfNationalDestinationCode($number));
340
341
        // An international toll free number, which has NDC "1234".
342
        $this->assertEquals(4, $this->phoneUtil->getLengthOfNationalDestinationCode(self::$internationalTollFree));
343
344
        // A mobile number from China is geographical, but does not have an area code: however it still
345
        // can be considered to have a national destination code.
346
        $cnMobile= new PhoneNumber();
347
        $cnMobile->setCountryCode(86)->setNationalNumber('18912341234');
348
349
        $this->assertEquals(3, $this->phoneUtil->getLengthOfNationalDestinationCode($cnMobile));
350
    }
351
352
    public function testGetCountryMobileToken()
353
    {
354
        $this->assertEquals(
355
            "1",
356
            PhoneNumberUtil::getCountryMobileToken($this->phoneUtil->getCountryCodeForRegion(RegionCode::MX))
357
        );
358
359
        // Country calling code for Sweden, which has no mobile token.
360
        $this->assertEquals(
361
            "",
362
            PhoneNumberUtil::getCountryMobileToken($this->phoneUtil->getCountryCodeForRegion(RegionCode::SE))
363
        );
364
    }
365
366
    public function testGetNationalSignificantNumber()
367
    {
368
        $this->assertEquals("6502530000", $this->phoneUtil->getNationalSignificantNumber(self::$usNumber));
369
370
        // An Italian mobile number.
371
        $this->assertEquals("345678901", $this->phoneUtil->getNationalSignificantNumber(self::$itMobile));
372
373
        // An Italian fixed line number.
374
        $this->assertEquals("0236618300", $this->phoneUtil->getNationalSignificantNumber(self::$itNumber));
375
376
        $this->assertEquals("12345678", $this->phoneUtil->getNationalSignificantNumber(self::$internationalTollFree));
377
    }
378
379
    public function testGetNationalSignificantNumber_ManyLeadingZeros()
380
    {
381
        $number = new PhoneNumber();
382
        $number->setCountryCode(1);
383
        $number->setNationalNumber(650);
384
        $number->setItalianLeadingZero(true);
385
        $number->setNumberOfLeadingZeros(2);
386
387
        $this->assertEquals('00650', $this->phoneUtil->getNationalSignificantNumber($number));
388
389
        // Set a bad value; we shouldn't crash; we shouldn't output any leading zeros at all;
390
        $number->setNumberOfLeadingZeros(-3);
391
        $this->assertEquals('650', $this->phoneUtil->getNationalSignificantNumber($number));
392
    }
393
394
    public function testGetExampleNumber()
395
    {
396
        $this->assertEquals(self::$deNumber, $this->phoneUtil->getExampleNumber(RegionCode::DE));
397
398
        $this->assertEquals(
399
            self::$deNumber,
400
            $this->phoneUtil->getExampleNumberForType(RegionCode::DE, PhoneNumberType::FIXED_LINE)
401
        );
402
        $this->assertEquals(null, $this->phoneUtil->getExampleNumberForType(RegionCode::DE, PhoneNumberType::MOBILE));
403
        $this->assertNotNull($this->phoneUtil->getExampleNumberForType(RegionCode::US, PhoneNumberType::FIXED_LINE));
404
        $this->assertNotNull($this->phoneUtil->getExampleNumberForType(RegionCode::US, PhoneNumberType::MOBILE));
405
        // CS is an invalid region, so we have no data for it.
406
        $this->assertNull($this->phoneUtil->getExampleNumberForType(RegionCode::CS, PhoneNumberType::MOBILE));
407
        // RegionCode 001 is reserved for supporting non-geographical country calling code. We don't
408
        // support getting an example number for it with this method.
409
        $this->assertEquals(null, $this->phoneUtil->getExampleNumber(RegionCode::UN001));
410
    }
411
412
    public function testGetExampleNumberForNonGeoEntity()
413
    {
414
        $this->assertEquals(self::$internationalTollFree, $this->phoneUtil->getExampleNumberForNonGeoEntity(800));
415
        $this->assertEquals(self::$universalPremiumRate, $this->phoneUtil->getExampleNumberForNonGeoEntity(979));
416
    }
417
418
    public function testConvertAlphaCharactersInNumber()
419
    {
420
        $input = "1800-ABC-DEF";
421
        // Alpha chars are converted to digits; everything else is left untouched.
422
        $expectedOutput = "1800-222-333";
423
        $this->assertEquals($expectedOutput, PhoneNumberUtil::convertAlphaCharactersInNumber($input));
424
    }
425
426
    public function testNormaliseRemovePunctuation()
427
    {
428
        $inputNumber = "034-56&+#2" . pack('H*', 'c2ad') . "34";
429
        $expectedOutput = "03456234";
430
        $this->assertEquals(
431
            $expectedOutput,
432
            PhoneNumberUtil::normalize($inputNumber),
433
            "Conversion did not correctly remove punctuation"
434
        );
435
    }
436
437
    public function testNormaliseReplaceAlphaCharacters()
438
    {
439
        $inputNumber = "034-I-am-HUNGRY";
440
        $expectedOutput = "034426486479";
441
        $this->assertEquals(
442
            $expectedOutput,
443
            PhoneNumberUtil::normalize($inputNumber),
444
            "Conversion did not correctly replace alpha characters"
445
        );
446
    }
447
448
    public function testNormaliseOtherDigits()
449
    {
450
        $inputNumber = "\xEF\xBC\x92" . "5\xD9\xA5" /* "25٥" */
451
        ;
452
        $expectedOutput = "255";
453
        $this->assertEquals(
454
            $expectedOutput,
455
            PhoneNumberUtil::normalize($inputNumber),
456
            "Conversion did not correctly replace non-latin digits"
457
        );
458
        // Eastern-Arabic digits.
459
        $inputNumber = "\xDB\xB5" . "2\xDB\xB0" /* "۵2۰" */
460
        ;
461
        $expectedOutput = "520";
462
        $this->assertEquals(
463
            $expectedOutput,
464
            PhoneNumberUtil::normalize($inputNumber),
465
            "Conversion did not correctly replace non-latin digits"
466
        );
467
    }
468
469
    public function testNormaliseStripAlphaCharacters()
470
    {
471
        $inputNumber = "034-56&+a#234";
472
        $expectedOutput = "03456234";
473
        $this->assertEquals(
474
            $expectedOutput,
475
            PhoneNumberUtil::normalizeDigitsOnly($inputNumber),
476
            "Conversion did not correctly remove alpha character"
477
        );
478
    }
479
480
    public function testNormaliseStripNonDiallableCharacters()
481
    {
482
        $inputNumber = "03*4-56&+1a#234";
483
        $expectedOutput = "03*456+1#234";
484
        $this->assertEquals(
485
            $expectedOutput,
486
            PhoneNumberUtil::normalizeDiallableCharsOnly($inputNumber),
487
            "Conversion did not correctly remove non-diallable characters"
488
        );
489
    }
490
491
    public function testFormatUSNumber()
492
    {
493
        $this->assertEquals("650 253 0000", $this->phoneUtil->format(self::$usNumber, PhoneNumberFormat::NATIONAL));
494
        $this->assertEquals(
495
            "+1 650 253 0000",
496
            $this->phoneUtil->format(self::$usNumber, PhoneNumberFormat::INTERNATIONAL)
497
        );
498
499
        $this->assertEquals("800 253 0000", $this->phoneUtil->format(self::$usTollFree, PhoneNumberFormat::NATIONAL));
500
        $this->assertEquals(
501
            "+1 800 253 0000",
502
            $this->phoneUtil->format(self::$usTollFree, PhoneNumberFormat::INTERNATIONAL)
503
        );
504
505
        $this->assertEquals("900 253 0000", $this->phoneUtil->format(self::$usPremium, PhoneNumberFormat::NATIONAL));
506
        $this->assertEquals(
507
            "+1 900 253 0000",
508
            $this->phoneUtil->format(self::$usPremium, PhoneNumberFormat::INTERNATIONAL)
509
        );
510
        $this->assertEquals(
511
            "tel:+1-900-253-0000",
512
            $this->phoneUtil->format(self::$usPremium, PhoneNumberFormat::RFC3966)
513
        );
514
        // Numbers with all zeros in the national number part will be formatted by using the raw_input
515
        // if that is available no matter which format is specified.
516
        $this->assertEquals(
517
            "000-000-0000",
518
            $this->phoneUtil->format(self::$usSpoofWithRawInput, PhoneNumberFormat::NATIONAL)
519
        );
520
        $this->assertEquals("0", $this->phoneUtil->format(self::$usSpoof, PhoneNumberFormat::NATIONAL));
521
    }
522
523
    public function testFormatBSNumber()
524
    {
525
        $this->assertEquals("242 365 1234", $this->phoneUtil->format(self::$bsNumber, PhoneNumberFormat::NATIONAL));
526
        $this->assertEquals(
527
            "+1 242 365 1234",
528
            $this->phoneUtil->format(self::$bsNumber, PhoneNumberFormat::INTERNATIONAL)
529
        );
530
    }
531
532
    public function testFormatGBNumber()
533
    {
534
        $this->assertEquals("(020) 7031 3000", $this->phoneUtil->format(self::$gbNumber, PhoneNumberFormat::NATIONAL));
535
        $this->assertEquals(
536
            "+44 20 7031 3000",
537
            $this->phoneUtil->format(self::$gbNumber, PhoneNumberFormat::INTERNATIONAL)
538
        );
539
540
        $this->assertEquals("(07912) 345 678", $this->phoneUtil->format(self::$gbMobile, PhoneNumberFormat::NATIONAL));
541
        $this->assertEquals(
542
            "+44 7912 345 678",
543
            $this->phoneUtil->format(self::$gbMobile, PhoneNumberFormat::INTERNATIONAL)
544
        );
545
    }
546
547
    public function testFormatDENumber()
548
    {
549
        $deNumber = new PhoneNumber();
550
        $deNumber->setCountryCode(49)->setNationalNumber(301234);
551
        $this->assertEquals("030/1234", $this->phoneUtil->format($deNumber, PhoneNumberFormat::NATIONAL));
552
        $this->assertEquals("+49 30/1234", $this->phoneUtil->format($deNumber, PhoneNumberFormat::INTERNATIONAL));
553
        $this->assertEquals("tel:+49-30-1234", $this->phoneUtil->format($deNumber, PhoneNumberFormat::RFC3966));
554
555
        $deNumber->clear();
556
        $deNumber->setCountryCode(49)->setNationalNumber(291123);
557
        $this->assertEquals("0291 123", $this->phoneUtil->format($deNumber, PhoneNumberFormat::NATIONAL));
558
        $this->assertEquals("+49 291 123", $this->phoneUtil->format($deNumber, PhoneNumberFormat::INTERNATIONAL));
559
560
        $deNumber->clear();
561
        $deNumber->setCountryCode(49)->setNationalNumber(29112345678);
562
        $this->assertEquals("0291 12345678", $this->phoneUtil->format($deNumber, PhoneNumberFormat::NATIONAL));
563
        $this->assertEquals("+49 291 12345678", $this->phoneUtil->format($deNumber, PhoneNumberFormat::INTERNATIONAL));
564
565
        $deNumber->clear();
566
        $deNumber->setCountryCode(49)->setNationalNumber(912312345);
567
        $this->assertEquals("09123 12345", $this->phoneUtil->format($deNumber, PhoneNumberFormat::NATIONAL));
568
        $this->assertEquals("+49 9123 12345", $this->phoneUtil->format($deNumber, PhoneNumberFormat::INTERNATIONAL));
569
        $deNumber->clear();
570
        $deNumber->setCountryCode(49)->setNationalNumber(80212345);
571
        $this->assertEquals("08021 2345", $this->phoneUtil->format($deNumber, PhoneNumberFormat::NATIONAL));
572
        $this->assertEquals("+49 8021 2345", $this->phoneUtil->format($deNumber, PhoneNumberFormat::INTERNATIONAL));
573
        // Note this number is correctly formatted without national prefix. Most of the numbers that
574
        // are treated as invalid numbers by the library are short numbers, and they are usually not
575
        // dialed with national prefix.
576
        $this->assertEquals("1234", $this->phoneUtil->format(self::$deShortNumber, PhoneNumberFormat::NATIONAL));
577
        $this->assertEquals(
578
            "+49 1234",
579
            $this->phoneUtil->format(self::$deShortNumber, PhoneNumberFormat::INTERNATIONAL)
580
        );
581
582
        $deNumber->clear();
583
        $deNumber->setCountryCode(49)->setNationalNumber(41341234);
584
        $this->assertEquals("04134 1234", $this->phoneUtil->format($deNumber, PhoneNumberFormat::NATIONAL));
585
    }
586
587
    public function testFormatITNumber()
588
    {
589
        $this->assertEquals("02 3661 8300", $this->phoneUtil->format(self::$itNumber, PhoneNumberFormat::NATIONAL));
590
        $this->assertEquals(
591
            "+39 02 3661 8300",
592
            $this->phoneUtil->format(self::$itNumber, PhoneNumberFormat::INTERNATIONAL)
593
        );
594
        $this->assertEquals("+390236618300", $this->phoneUtil->format(self::$itNumber, PhoneNumberFormat::E164));
595
596
        $this->assertEquals("345 678 901", $this->phoneUtil->format(self::$itMobile, PhoneNumberFormat::NATIONAL));
597
        $this->assertEquals(
598
            "+39 345 678 901",
599
            $this->phoneUtil->format(self::$itMobile, PhoneNumberFormat::INTERNATIONAL)
600
        );
601
        $this->assertEquals("+39345678901", $this->phoneUtil->format(self::$itMobile, PhoneNumberFormat::E164));
602
    }
603
604
    public function testFormatAUNumber()
605
    {
606
        $this->assertEquals("02 3661 8300", $this->phoneUtil->format(self::$auNumber, PhoneNumberFormat::NATIONAL));
607
        $this->assertEquals(
608
            "+61 2 3661 8300",
609
            $this->phoneUtil->format(self::$auNumber, PhoneNumberFormat::INTERNATIONAL)
610
        );
611
        $this->assertEquals("+61236618300", $this->phoneUtil->format(self::$auNumber, PhoneNumberFormat::E164));
612
613
        $auNumber = new PhoneNumber();
614
        $auNumber->setCountryCode(61)->setNationalNumber(1800123456);
615
        $this->assertEquals("1800 123 456", $this->phoneUtil->format($auNumber, PhoneNumberFormat::NATIONAL));
616
        $this->assertEquals("+61 1800 123 456", $this->phoneUtil->format($auNumber, PhoneNumberFormat::INTERNATIONAL));
617
        $this->assertEquals("+611800123456", $this->phoneUtil->format($auNumber, PhoneNumberFormat::E164));
618
    }
619
620
    public function testFormatARNumber()
621
    {
622
        $this->assertEquals("011 8765-4321", $this->phoneUtil->format(self::$arNumber, PhoneNumberFormat::NATIONAL));
623
        $this->assertEquals(
624
            "+54 11 8765-4321",
625
            $this->phoneUtil->format(self::$arNumber, PhoneNumberFormat::INTERNATIONAL)
626
        );
627
        $this->assertEquals("+541187654321", $this->phoneUtil->format(self::$arNumber, PhoneNumberFormat::E164));
628
629
        $this->assertEquals("011 15 8765-4321", $this->phoneUtil->format(self::$arMobile, PhoneNumberFormat::NATIONAL));
630
        $this->assertEquals(
631
            "+54 9 11 8765 4321",
632
            $this->phoneUtil->format(self::$arMobile, PhoneNumberFormat::INTERNATIONAL)
633
        );
634
        $this->assertEquals("+5491187654321", $this->phoneUtil->format(self::$arMobile, PhoneNumberFormat::E164));
635
    }
636
637
    public function testFormatMXNumber()
638
    {
639
        $this->assertEquals(
640
            "045 234 567 8900",
641
            $this->phoneUtil->format(self::$mxMobile1, PhoneNumberFormat::NATIONAL)
642
        );
643
        $this->assertEquals(
644
            "+52 1 234 567 8900",
645
            $this->phoneUtil->format(self::$mxMobile1, PhoneNumberFormat::INTERNATIONAL)
646
        );
647
        $this->assertEquals("+5212345678900", $this->phoneUtil->format(self::$mxMobile1, PhoneNumberFormat::E164));
648
649
        $this->assertEquals(
650
            "045 55 1234 5678",
651
            $this->phoneUtil->format(self::$mxMobile2, PhoneNumberFormat::NATIONAL)
652
        );
653
        $this->assertEquals(
654
            "+52 1 55 1234 5678",
655
            $this->phoneUtil->format(self::$mxMobile2, PhoneNumberFormat::INTERNATIONAL)
656
        );
657
        $this->assertEquals("+5215512345678", $this->phoneUtil->format(self::$mxMobile2, PhoneNumberFormat::E164));
658
659
        $this->assertEquals("01 33 1234 5678", $this->phoneUtil->format(self::$mxNumber1, PhoneNumberFormat::NATIONAL));
660
        $this->assertEquals(
661
            "+52 33 1234 5678",
662
            $this->phoneUtil->format(self::$mxNumber1, PhoneNumberFormat::INTERNATIONAL)
663
        );
664
        $this->assertEquals("+523312345678", $this->phoneUtil->format(self::$mxNumber1, PhoneNumberFormat::E164));
665
666
        $this->assertEquals("01 821 123 4567", $this->phoneUtil->format(self::$mxNumber2, PhoneNumberFormat::NATIONAL));
667
        $this->assertEquals(
668
            "+52 821 123 4567",
669
            $this->phoneUtil->format(self::$mxNumber2, PhoneNumberFormat::INTERNATIONAL)
670
        );
671
        $this->assertEquals("+528211234567", $this->phoneUtil->format(self::$mxNumber2, PhoneNumberFormat::E164));
672
    }
673
674
    public function testFormatOutOfCountryCallingNumber()
675
    {
676
        $this->assertEquals(
677
            "00 1 900 253 0000",
678
            $this->phoneUtil->formatOutOfCountryCallingNumber(self::$usPremium, RegionCode::DE)
679
        );
680
        $this->assertEquals(
681
            "1 650 253 0000",
682
            $this->phoneUtil->formatOutOfCountryCallingNumber(self::$usNumber, RegionCode::BS)
683
        );
684
685
        $this->assertEquals(
686
            "00 1 650 253 0000",
687
            $this->phoneUtil->formatOutOfCountryCallingNumber(self::$usNumber, RegionCode::PL)
688
        );
689
690
        $this->assertEquals(
691
            "011 44 7912 345 678",
692
            $this->phoneUtil->formatOutOfCountryCallingNumber(self::$gbMobile, RegionCode::US)
693
        );
694
695
        $this->assertEquals(
696
            "00 49 1234",
697
            $this->phoneUtil->formatOutOfCountryCallingNumber(self::$deShortNumber, RegionCode::GB)
698
        );
699
        // Note this number is correctly formatted without national prefix. Most of the numbers that
700
        // are treated as invalid numbers by the library are short numbers, and they are usually not
701
        // dialed with national prefix.
702
        $this->assertEquals(
703
            "1234",
704
            $this->phoneUtil->formatOutOfCountryCallingNumber(self::$deShortNumber, RegionCode::DE)
705
        );
706
707
        $this->assertEquals(
708
            "011 39 02 3661 8300",
709
            $this->phoneUtil->formatOutOfCountryCallingNumber(self::$itNumber, RegionCode::US)
710
        );
711
        $this->assertEquals(
712
            "02 3661 8300",
713
            $this->phoneUtil->formatOutOfCountryCallingNumber(self::$itNumber, RegionCode::IT)
714
        );
715
        $this->assertEquals(
716
            "+39 02 3661 8300",
717
            $this->phoneUtil->formatOutOfCountryCallingNumber(self::$itNumber, RegionCode::SG)
718
        );
719
720
        $this->assertEquals(
721
            "6521 8000",
722
            $this->phoneUtil->formatOutOfCountryCallingNumber(self::$sgNumber, RegionCode::SG)
723
        );
724
725
        $this->assertEquals(
726
            "011 54 9 11 8765 4321",
727
            $this->phoneUtil->formatOutOfCountryCallingNumber(self::$arMobile, RegionCode::US)
728
        );
729
        $this->assertEquals(
730
            "011 800 1234 5678",
731
            $this->phoneUtil->formatOutOfCountryCallingNumber(self::$internationalTollFree, RegionCode::US)
732
        );
733
734
        $arNumberWithExtn = new PhoneNumber();
735
        $arNumberWithExtn->mergeFrom(self::$arMobile)->setExtension("1234");
736
        $this->assertEquals(
737
            "011 54 9 11 8765 4321 ext. 1234",
738
            $this->phoneUtil->formatOutOfCountryCallingNumber($arNumberWithExtn, RegionCode::US)
739
        );
740
        $this->assertEquals(
741
            "0011 54 9 11 8765 4321 ext. 1234",
742
            $this->phoneUtil->formatOutOfCountryCallingNumber($arNumberWithExtn, RegionCode::AU)
743
        );
744
        $this->assertEquals(
745
            "011 15 8765-4321 ext. 1234",
746
            $this->phoneUtil->formatOutOfCountryCallingNumber($arNumberWithExtn, RegionCode::AR)
747
        );
748
    }
749
750
    public function testFormatOutOfCountryWithInvalidRegion()
751
    {
752
        // AQ/Antarctica isn't a valid region code for phone number formatting,
753
        // so this falls back to intl formatting.
754
        $this->assertEquals(
755
            "+1 650 253 0000",
756
            $this->phoneUtil->formatOutOfCountryCallingNumber(self::$usNumber, RegionCode::AQ)
757
        );
758
        // For region code 001, the out-of-country format always turns into the international format.
759
        $this->assertEquals(
760
            "+1 650 253 0000",
761
            $this->phoneUtil->formatOutOfCountryCallingNumber(self::$usNumber, RegionCode::UN001)
762
        );
763
    }
764
765
    public function testFormatOutOfCountryWithPreferredIntlPrefix()
766
    {
767
        // This should use 0011, since that is the preferred international prefix (both 0011 and 0012
768
        // are accepted as possible international prefixes in our test metadta.)
769
        $this->assertEquals(
770
            "0011 39 02 3661 8300",
771
            $this->phoneUtil->formatOutOfCountryCallingNumber(self::$itNumber, RegionCode::AU)
772
        );
773
    }
774
775
    public function testFormatOutOfCountryKeepingAlphaChars()
776
    {
777
        $alphaNumericNumber = new PhoneNumber();
778
        $alphaNumericNumber->setCountryCode(1)->setNationalNumber(8007493524)->setRawInput("1800 six-flag");
779
        $this->assertEquals(
780
            "0011 1 800 SIX-FLAG",
781
            $this->phoneUtil->formatOutOfCountryKeepingAlphaChars($alphaNumericNumber, RegionCode::AU)
782
        );
783
784
        $alphaNumericNumber->setRawInput("1-800-SIX-flag");
785
        $this->assertEquals(
786
            "0011 1 800-SIX-FLAG",
787
            $this->phoneUtil->formatOutOfCountryKeepingAlphaChars($alphaNumericNumber, RegionCode::AU)
788
        );
789
790
        $alphaNumericNumber->setRawInput("Call us from UK: 00 1 800 SIX-flag");
791
        $this->assertEquals(
792
            "0011 1 800 SIX-FLAG",
793
            $this->phoneUtil->formatOutOfCountryKeepingAlphaChars($alphaNumericNumber, RegionCode::AU)
794
        );
795
796
        $alphaNumericNumber->setRawInput("800 SIX-flag");
797
        $this->assertEquals(
798
            "0011 1 800 SIX-FLAG",
799
            $this->phoneUtil->formatOutOfCountryKeepingAlphaChars($alphaNumericNumber, RegionCode::AU)
800
        );
801
802
        // Formatting from within the NANPA region.
803
        $this->assertEquals(
804
            "1 800 SIX-FLAG",
805
            $this->phoneUtil->formatOutOfCountryKeepingAlphaChars($alphaNumericNumber, RegionCode::US)
806
        );
807
808
        $this->assertEquals(
809
            "1 800 SIX-FLAG",
810
            $this->phoneUtil->formatOutOfCountryKeepingAlphaChars($alphaNumericNumber, RegionCode::BS)
811
        );
812
813
        // Testing that if the raw input doesn't exist, it is formatted using
814
        // formatOutOfCountryCallingNumber.
815
        $alphaNumericNumber->clearRawInput();
816
        $this->assertEquals(
817
            "00 1 800 749 3524",
818
            $this->phoneUtil->formatOutOfCountryKeepingAlphaChars($alphaNumericNumber, RegionCode::DE)
819
        );
820
821
        // Testing AU alpha number formatted from Australia.
822
        $alphaNumericNumber->setCountryCode(61)->setNationalNumber(827493524)->setRawInput("+61 82749-FLAG");
823
        // This number should have the national prefix fixed.
824
        $this->assertEquals(
825
            "082749-FLAG",
826
            $this->phoneUtil->formatOutOfCountryKeepingAlphaChars($alphaNumericNumber, RegionCode::AU)
827
        );
828
829
        $alphaNumericNumber->setRawInput("082749-FLAG");
830
        $this->assertEquals(
831
            "082749-FLAG",
832
            $this->phoneUtil->formatOutOfCountryKeepingAlphaChars($alphaNumericNumber, RegionCode::AU)
833
        );
834
835
        $alphaNumericNumber->setNationalNumber(18007493524)->setRawInput("1-800-SIX-flag");
836
        // This number should not have the national prefix prefixed, in accordance with the override for
837
        // this specific formatting rule.
838
        $this->assertEquals(
839
            "1-800-SIX-FLAG",
840
            $this->phoneUtil->formatOutOfCountryKeepingAlphaChars($alphaNumericNumber, RegionCode::AU)
841
        );
842
843
        // The metadata should not be permanently changed, since we copied it before modifying patterns.
844
        // Here we check this.
845
        $alphaNumericNumber->setNationalNumber(1800749352);
846
        $this->assertEquals(
847
            "1800 749 352",
848
            $this->phoneUtil->formatOutOfCountryCallingNumber($alphaNumericNumber, RegionCode::AU)
849
        );
850
851
        // Testing a region with multiple international prefixes.
852
        $this->assertEquals(
853
            "+61 1-800-SIX-FLAG",
854
            $this->phoneUtil->formatOutOfCountryKeepingAlphaChars($alphaNumericNumber, RegionCode::SG)
855
        );
856
        // Testing the case of calling from a non-supported region.
857
        $this->assertEquals(
858
            "+61 1-800-SIX-FLAG",
859
            $this->phoneUtil->formatOutOfCountryKeepingAlphaChars($alphaNumericNumber, RegionCode::AQ)
860
        );
861
862
        // Testing the case with an invalid country calling code.
863
        $alphaNumericNumber->setCountryCode(0)->setNationalNumber(18007493524)->setRawInput("1-800-SIX-flag");
864
        // Uses the raw input only.
865
        $this->assertEquals(
866
            "1-800-SIX-flag",
867
            $this->phoneUtil->formatOutOfCountryKeepingAlphaChars($alphaNumericNumber, RegionCode::DE)
868
        );
869
870
        // Testing the case of an invalid alpha number.
871
        $alphaNumericNumber->setCountryCode(1)->setNationalNumber(80749)->setRawInput("180-SIX");
872
        // No country-code stripping can be done.
873
        $this->assertEquals(
874
            "00 1 180-SIX",
875
            $this->phoneUtil->formatOutOfCountryKeepingAlphaChars($alphaNumericNumber, RegionCode::DE)
876
        );
877
878
        // Testing the case of calling from a non-supported region.
879
        $alphaNumericNumber->setCountryCode(1)->setNationalNumber(80749)->setRawInput("180-SIX");
880
        // No country-code stripping can be done since the number is invalid.
881
        $this->assertEquals(
882
            "+1 180-SIX",
883
            $this->phoneUtil->formatOutOfCountryKeepingAlphaChars($alphaNumericNumber, RegionCode::AQ)
884
        );
885
    }
886
887
    public function testFormatWithCarrierCode()
888
    {
889
        // We only support this for AR in our test metadata, and only for mobile numbers starting with
890
        // certain values.
891
        $arMobile = new PhoneNumber();
892
        $arMobile->setCountryCode(54)->setNationalNumber(92234654321);
893
        $this->assertEquals("02234 65-4321", $this->phoneUtil->format($arMobile, PhoneNumberFormat::NATIONAL));
894
        // Here we force 14 as the carrier code.
895
        $this->assertEquals(
896
            "02234 14 65-4321",
897
            $this->phoneUtil->formatNationalNumberWithCarrierCode($arMobile, "14")
898
        );
899
        // Here we force the number to be shown with no carrier code.
900
        $this->assertEquals(
901
            "02234 65-4321",
902
            $this->phoneUtil->formatNationalNumberWithCarrierCode($arMobile, "")
903
        );
904
        // Here the international rule is used, so no carrier code should be present.
905
        $this->assertEquals("+5492234654321", $this->phoneUtil->format($arMobile, PhoneNumberFormat::E164));
906
        // We don't support this for the US so there should be no change.
907
        $this->assertEquals(
908
            "650 253 0000",
909
            $this->phoneUtil->formatNationalNumberWithCarrierCode(self::$usNumber, "15")
910
        );
911
912
        // Invalid country code should just get the NSN.
913
        $this->assertEquals(
914
            "12345",
915
            $this->phoneUtil->formatNationalNumberWithCarrierCode(self::$unknownCountryCodeNoRawInput, "89")
916
        );
917
    }
918
919
    public function testFormatWithPreferredCarrierCode()
920
    {
921
        // We only support this for AR in our test metadata.
922
        $arNumber = new PhoneNumber();
923
        $arNumber->setCountryCode(54)->setNationalNumber(91234125678);
924
        // Test formatting with no preferred carrier code stored in the number itself.
925
        $this->assertEquals(
926
            "01234 15 12-5678",
927
            $this->phoneUtil->formatNationalNumberWithPreferredCarrierCode($arNumber, "15")
928
        );
929
        $this->assertEquals(
930
            "01234 12-5678",
931
            $this->phoneUtil->formatNationalNumberWithPreferredCarrierCode($arNumber, "")
932
        );
933
        // Test formatting with preferred carrier code present.
934
        $arNumber->setPreferredDomesticCarrierCode("19");
935
        $this->assertEquals("01234 12-5678", $this->phoneUtil->format($arNumber, PhoneNumberFormat::NATIONAL));
936
        $this->assertEquals(
937
            "01234 19 12-5678",
938
            $this->phoneUtil->formatNationalNumberWithPreferredCarrierCode($arNumber, "15")
939
        );
940
        $this->assertEquals(
941
            "01234 19 12-5678",
942
            $this->phoneUtil->formatNationalNumberWithPreferredCarrierCode($arNumber, "")
943
        );
944
        // When the preferred_domestic_carrier_code is present (even when it is just a space), use it
945
        // instead of the default carrier code passed in.
946
        $arNumber->setPreferredDomesticCarrierCode(" ");
947
        $this->assertEquals(
948
            "01234   12-5678",
949
            $this->phoneUtil->formatNationalNumberWithPreferredCarrierCode($arNumber, "15")
950
        );
951
        // When the preferred_domestic_carrier_code is present but empty, treat it as unset and use
952
        // instead of the default carrier code passed in.
953
        $arNumber->setPreferredDomesticCarrierCode("");
954
        $this->assertEquals(
955
            "01234 15 12-5678",
956
            $this->phoneUtil->formatNationalNumberWithPreferredCarrierCode($arNumber, "15")
957
        );
958
        // We don't support this for the US so there should be no change.
959
        $usNumber = new PhoneNumber();
960
        $usNumber->setCountryCode(1)->setNationalNumber(4241231234)->setPreferredDomesticCarrierCode("99");
961
        $this->assertEquals("424 123 1234", $this->phoneUtil->format($usNumber, PhoneNumberFormat::NATIONAL));
962
        $this->assertEquals(
963
            "424 123 1234",
964
            $this->phoneUtil->formatNationalNumberWithPreferredCarrierCode($usNumber, "15")
965
        );
966
    }
967
968
    public function testFormatNumberForMobileDialing()
969
    {
970
        // Numbers are normally dialed in national format in-country, and international format from
971
        // outside the country.
972
        $this->assertEquals(
973
            "030123456",
974
            $this->phoneUtil->formatNumberForMobileDialing(self::$deNumber, RegionCode::DE, false)
975
        );
976
        $this->assertEquals(
977
            "+4930123456",
978
            $this->phoneUtil->formatNumberForMobileDialing(self::$deNumber, RegionCode::CH, false)
979
        );
980
        $this->assertEquals(
981
            "+4930123456",
982
            $this->phoneUtil->formatNumberForMobileDialing(self::$deNumber, RegionCode::CH, false)
983
        );
984
        $deNumberWithExtn = new PhoneNumber();
985
        $deNumberWithExtn->mergeFrom(self::$deNumber)->setExtension("1234");
986
        $this->assertEquals(
987
            "030123456",
988
            $this->phoneUtil->formatNumberForMobileDialing($deNumberWithExtn, RegionCode::DE, false)
989
        );
990
        $this->assertEquals(
991
            "+4930123456",
992
            $this->phoneUtil->formatNumberForMobileDialing($deNumberWithExtn, RegionCode::CH, false)
993
        );
994
995
        // US toll free numbers are marked as noInternationalDialling in the test metadata for testing
996
        // purposes. For such numbers, we expect nothing to be returned when the region code is not the
997
        // same one.
998
        $this->assertEquals(
999
            "800 253 0000",
1000
            $this->phoneUtil->formatNumberForMobileDialing(
1001
                self::$usTollFree,
1002
                RegionCode::US,
1003
                true /*  keep formatting */
1004
            )
1005
        );
1006
        $this->assertEquals(
1007
            "",
1008
            $this->phoneUtil->formatNumberForMobileDialing(self::$usTollFree, RegionCode::CN, true)
1009
        );
1010
        $this->assertEquals(
1011
            "+1 650 253 0000",
1012
            $this->phoneUtil->formatNumberForMobileDialing(self::$usNumber, RegionCode::US, true)
1013
        );
1014
        $usNumberWithExtn = new PhoneNumber();
1015
        $usNumberWithExtn->mergeFrom(self::$usNumber)->setExtension("1234");
1016
        $this->assertEquals(
1017
            "+1 650 253 0000",
1018
            $this->phoneUtil->formatNumberForMobileDialing($usNumberWithExtn, RegionCode::US, true)
1019
        );
1020
1021
        $this->assertEquals(
1022
            "8002530000",
1023
            $this->phoneUtil->formatNumberForMobileDialing(
1024
                self::$usTollFree,
1025
                RegionCode::US,
1026
                false /* remove formatting */
1027
            )
1028
        );
1029
        $this->assertEquals(
1030
            "",
1031
            $this->phoneUtil->formatNumberForMobileDialing(self::$usTollFree, RegionCode::CN, false)
1032
        );
1033
        $this->assertEquals(
1034
            "+16502530000",
1035
            $this->phoneUtil->formatNumberForMobileDialing(self::$usNumber, RegionCode::US, false)
1036
        );
1037
        $this->assertEquals(
1038
            "+16502530000",
1039
            $this->phoneUtil->formatNumberForMobileDialing($usNumberWithExtn, RegionCode::US, false)
1040
        );
1041
1042
        // An invalid US number, which is one digit too long.
1043
        $this->assertEquals(
1044
            "+165025300001",
1045
            $this->phoneUtil->formatNumberForMobileDialing(self::$usLongNumber, RegionCode::US, false)
1046
        );
1047
        $this->assertEquals(
1048
            "+1 65025300001",
1049
            $this->phoneUtil->formatNumberForMobileDialing(self::$usLongNumber, RegionCode::US, true)
1050
        );
1051
1052
        // Star numbers. In real life they appear in Israel, but we have them in JP in our test
1053
        // metadata.
1054
        $this->assertEquals(
1055
            "*2345",
1056
            $this->phoneUtil->formatNumberForMobileDialing(self::$jpStarNumber, RegionCode::JP, false)
1057
        );
1058
        $this->assertEquals(
1059
            "*2345",
1060
            $this->phoneUtil->formatNumberForMobileDialing(self::$jpStarNumber, RegionCode::JP, true)
1061
        );
1062
1063
        $this->assertEquals(
1064
            "+80012345678",
1065
            $this->phoneUtil->formatNumberForMobileDialing(self::$internationalTollFree, RegionCode::JP, false)
1066
        );
1067
        $this->assertEquals(
1068
            "+800 1234 5678",
1069
            $this->phoneUtil->formatNumberForMobileDialing(self::$internationalTollFree, RegionCode::JP, true)
1070
        );
1071
1072
        // UAE numbers beginning with 600 (classified as UAN) need to be dialled without +971 locally.
1073
        $this->assertEquals(
1074
            "+971600123456",
1075
            $this->phoneUtil->formatNumberForMobileDialing(self::$aeUAN, RegionCode::JP, false)
1076
        );
1077
        $this->assertEquals(
1078
            "600123456",
1079
            $this->phoneUtil->formatNumberForMobileDialing(self::$aeUAN, RegionCode::AE, false)
1080
        );
1081
1082
        $this->assertEquals(
1083
            "+523312345678",
1084
            $this->phoneUtil->formatNumberForMobileDialing(self::$mxNumber1, RegionCode::MX, false)
1085
        );
1086
        $this->assertEquals(
1087
            "+523312345678",
1088
            $this->phoneUtil->formatNumberForMobileDialing(self::$mxNumber1, RegionCode::US, false)
1089
        );
1090
1091
        // Non-geographical numbers should always be dialed in international format.
1092
        $this->assertEquals(
1093
            "+80012345678",
1094
            $this->phoneUtil->formatNumberForMobileDialing(self::$internationalTollFree, RegionCode::US, false)
1095
        );
1096
        $this->assertEquals(
1097
            "+80012345678",
1098
            $this->phoneUtil->formatNumberForMobileDialing(self::$internationalTollFree, RegionCode::UN001, false)
1099
        );
1100
1101
        // Test that a short number is formatted correctly for mobile dialing within the region,
1102
        // and is not diallable from outside the region.
1103
        $deShortNumber = new PhoneNumber();
1104
        $deShortNumber->setCountryCode(49)->setNationalNumber(123);
1105
        $this->assertEquals(
1106
            "123",
1107
            $this->phoneUtil->formatNumberForMobileDialing($deShortNumber, RegionCode::DE, false)
1108
        );
1109
        $this->assertEquals("", $this->phoneUtil->formatNumberForMobileDialing($deShortNumber, RegionCode::IT, false));
1110
1111
        // Test the special logic for Hungary, where the national prefix must be added before dialing
1112
        // from a mobile phone for regular length numbers, but not for short numbers.
1113
        $huRegularNumber = new PhoneNumber();
1114
        $huRegularNumber->setCountryCode(36)->setNationalNumber(301234567);
1115
        $this->assertEquals(
1116
            "06301234567",
1117
            $this->phoneUtil->formatNumberForMobileDialing($huRegularNumber, RegionCode::HU, false)
1118
        );
1119
        $this->assertEquals(
1120
            "+36301234567",
1121
            $this->phoneUtil->formatNumberForMobileDialing($huRegularNumber, RegionCode::JP, false)
1122
        );
1123
        $huShortNumber = new PhoneNumber();
1124
        $huShortNumber->setCountryCode(36)->setNationalNumber(104);
1125
        $this->assertEquals(
1126
            "104",
1127
            $this->phoneUtil->formatNumberForMobileDialing($huShortNumber, RegionCode::HU, false)
1128
        );
1129
        $this->assertEquals("", $this->phoneUtil->formatNumberForMobileDialing($huShortNumber, RegionCode::JP, false));
1130
1131
        // Test the special logic for NANPA countries, for which regular length phone numbers are always
1132
        // output in international format, but short numbers are in national format.
1133
        $this->assertEquals(
1134
            "+16502530000",
1135
            $this->phoneUtil->formatNumberForMobileDialing(self::$usNumber, RegionCode::US, false)
1136
        );
1137
        $this->assertEquals(
1138
            "+16502530000",
1139
            $this->phoneUtil->formatNumberForMobileDialing(self::$usNumber, RegionCode::CA, false)
1140
        );
1141
        $this->assertEquals(
1142
            "+16502530000",
1143
            $this->phoneUtil->formatNumberForMobileDialing(self::$usNumber, RegionCode::BR, false)
1144
        );
1145
        $usShortNumber = new PhoneNumber();
1146
        $usShortNumber->setCountryCode(1)->setNationalNumber(911);
1147
        $this->assertEquals(
1148
            "911",
1149
            $this->phoneUtil->formatNumberForMobileDialing($usShortNumber, RegionCode::US, false)
1150
        );
1151
        $this->assertEquals("", $this->phoneUtil->formatNumberForMobileDialing($usShortNumber, RegionCode::CA, false));
1152
        $this->assertEquals("", $this->phoneUtil->formatNumberForMobileDialing($usShortNumber, RegionCode::BR, false));
1153
1154
        // Test that the Australian emergency number 000 is formatted correctly.
1155
        $auNumber = new PhoneNumber();
1156
        $auNumber->setCountryCode(61)->setNationalNumber(0)->setItalianLeadingZero(true)->setNumberOfLeadingZeros(2);
1157
        $this->assertEquals("000", $this->phoneUtil->formatNumberForMobileDialing($auNumber, RegionCode::AU, false));
1158
        $this->assertEquals("", $this->phoneUtil->formatNumberForMobileDialing($auNumber, RegionCode::NZ, false));
1159
    }
1160
1161
    public function testFormatByPattern()
1162
    {
1163
        $newNumFormat = new NumberFormat();
1164
        $newNumFormat->setPattern("(\\d{3})(\\d{3})(\\d{4})");
1165
        $newNumFormat->setFormat("($1) $2-$3");
1166
        $newNumberFormats = array();
1167
        $newNumberFormats[] = $newNumFormat;
1168
1169
        $this->assertEquals(
1170
            "(650) 253-0000",
1171
            $this->phoneUtil->formatByPattern(
1172
                self::$usNumber,
1173
                PhoneNumberFormat::NATIONAL,
1174
                $newNumberFormats
1175
            )
1176
        );
1177
        $this->assertEquals(
1178
            "+1 (650) 253-0000",
1179
            $this->phoneUtil->formatByPattern(
1180
                self::$usNumber,
1181
                PhoneNumberFormat::INTERNATIONAL,
1182
                $newNumberFormats
1183
            )
1184
        );
1185
        $this->assertEquals(
1186
            "tel:+1-650-253-0000",
1187
            $this->phoneUtil->formatByPattern(
1188
                self::$usNumber,
1189
                PhoneNumberFormat::RFC3966,
1190
                $newNumberFormats
1191
            )
1192
        );
1193
1194
        // $NP is set to '1' for the US. Here we check that for other NANPA countries the US rules are
1195
        // followed.
1196
        $newNumFormat->setNationalPrefixFormattingRule('$NP ($FG)');
1197
        $newNumFormat->setFormat("$1 $2-$3");
1198
        $this->assertEquals(
1199
            "1 (242) 365-1234",
1200
            $this->phoneUtil->formatByPattern(
1201
                self::$bsNumber,
1202
                PhoneNumberFormat::NATIONAL,
1203
                $newNumberFormats
1204
            )
1205
        );
1206
        $this->assertEquals(
1207
            "+1 242 365-1234",
1208
            $this->phoneUtil->formatByPattern(
1209
                self::$bsNumber,
1210
                PhoneNumberFormat::INTERNATIONAL,
1211
                $newNumberFormats
1212
            )
1213
        );
1214
1215
        $newNumFormat->setPattern("(\\d{2})(\\d{5})(\\d{3})");
1216
        $newNumFormat->setFormat("$1-$2 $3");
1217
        $newNumberFormats[0] = $newNumFormat;
1218
1219
        $this->assertEquals(
1220
            "02-36618 300",
1221
            $this->phoneUtil->formatByPattern(
1222
                self::$itNumber,
1223
                PhoneNumberFormat::NATIONAL,
1224
                $newNumberFormats
1225
            )
1226
        );
1227
        $this->assertEquals(
1228
            "+39 02-36618 300",
1229
            $this->phoneUtil->formatByPattern(
1230
                self::$itNumber,
1231
                PhoneNumberFormat::INTERNATIONAL,
1232
                $newNumberFormats
1233
            )
1234
        );
1235
1236
        $newNumFormat->setNationalPrefixFormattingRule('$NP$FG');
1237
        $newNumFormat->setPattern("(\\d{2})(\\d{4})(\\d{4})");
1238
        $newNumFormat->setFormat("$1 $2 $3");
1239
        $newNumberFormats[0] = $newNumFormat;
1240
        $this->assertEquals(
1241
            "020 7031 3000",
1242
            $this->phoneUtil->formatByPattern(
1243
                self::$gbNumber,
1244
                PhoneNumberFormat::NATIONAL,
1245
                $newNumberFormats
1246
            )
1247
        );
1248
1249
        $newNumFormat->setNationalPrefixFormattingRule('($NP$FG)');
1250
        $this->assertEquals(
1251
            "(020) 7031 3000",
1252
            $this->phoneUtil->formatByPattern(
1253
                self::$gbNumber,
1254
                PhoneNumberFormat::NATIONAL,
1255
                $newNumberFormats
1256
            )
1257
        );
1258
1259
        $newNumFormat->setNationalPrefixFormattingRule("");
1260
        $this->assertEquals(
1261
            "20 7031 3000",
1262
            $this->phoneUtil->formatByPattern(
1263
                self::$gbNumber,
1264
                PhoneNumberFormat::NATIONAL,
1265
                $newNumberFormats
1266
            )
1267
        );
1268
1269
        $this->assertEquals(
1270
            "+44 20 7031 3000",
1271
            $this->phoneUtil->formatByPattern(
1272
                self::$gbNumber,
1273
                PhoneNumberFormat::INTERNATIONAL,
1274
                $newNumberFormats
1275
            )
1276
        );
1277
    }
1278
1279
    public function testFormatE164Number()
1280
    {
1281
        $this->assertEquals("+16502530000", $this->phoneUtil->format(self::$usNumber, PhoneNumberFormat::E164));
1282
        $this->assertEquals("+4930123456", $this->phoneUtil->format(self::$deNumber, PhoneNumberFormat::E164));
1283
        $this->assertEquals(
1284
            "+80012345678",
1285
            $this->phoneUtil->format(self::$internationalTollFree, PhoneNumberFormat::E164)
1286
        );
1287
    }
1288
1289
    public function testFormatNumberWithExtension()
1290
    {
1291
        $nzNumber = new PhoneNumber();
1292
        $nzNumber->mergeFrom(self::$nzNumber)->setExtension("1234");
1293
        // Uses default extension prefix:
1294
        $this->assertEquals("03-331 6005 ext. 1234", $this->phoneUtil->format($nzNumber, PhoneNumberFormat::NATIONAL));
1295
        // Uses RFC 3966 syntax.
1296
        $this->assertEquals(
1297
            "tel:+64-3-331-6005;ext=1234",
1298
            $this->phoneUtil->format($nzNumber, PhoneNumberFormat::RFC3966)
1299
        );
1300
        // Extension prefix overridden in the territory information for the US:
1301
        $usNumberWithExtension = new PhoneNumber();
1302
        $usNumberWithExtension->mergeFrom(self::$usNumber)->setExtension("4567");
1303
        $this->assertEquals(
1304
            "650 253 0000 extn. 4567",
1305
            $this->phoneUtil->format($usNumberWithExtension, PhoneNumberFormat::NATIONAL)
1306
        );
1307
    }
1308
1309
    public function testFormatInOriginalFormat()
1310
    {
1311
        $number1 = $this->phoneUtil->parseAndKeepRawInput("+442087654321", RegionCode::GB);
1312
        $this->assertEquals("+44 20 8765 4321", $this->phoneUtil->formatInOriginalFormat($number1, RegionCode::GB));
1313
1314
        $number2 = $this->phoneUtil->parseAndKeepRawInput("02087654321", RegionCode::GB);
1315
        $this->assertEquals("(020) 8765 4321", $this->phoneUtil->formatInOriginalFormat($number2, RegionCode::GB));
1316
1317
        $number3 = $this->phoneUtil->parseAndKeepRawInput("011442087654321", RegionCode::US);
1318
        $this->assertEquals("011 44 20 8765 4321", $this->phoneUtil->formatInOriginalFormat($number3, RegionCode::US));
1319
1320
        $number4 = $this->phoneUtil->parseAndKeepRawInput("442087654321", RegionCode::GB);
1321
        $this->assertEquals("44 20 8765 4321", $this->phoneUtil->formatInOriginalFormat($number4, RegionCode::GB));
1322
1323
        $number5 = $this->phoneUtil->parse("+442087654321", RegionCode::GB);
1324
        $this->assertEquals("(020) 8765 4321", $this->phoneUtil->formatInOriginalFormat($number5, RegionCode::GB));
1325
1326
        // Invalid numbers that we have a formatting pattern for should be formatted properly. Note area
1327
        // codes starting with 7 are intentionally excluded in the test metadata for testing purposes.
1328
        $number6 = $this->phoneUtil->parseAndKeepRawInput("7345678901", RegionCode::US);
1329
        $this->assertEquals("734 567 8901", $this->phoneUtil->formatInOriginalFormat($number6, RegionCode::US));
1330
1331
        // US is not a leading zero country, and the presence of the leading zero leads us to format the
1332
        // number using raw_input.
1333
        $number7 = $this->phoneUtil->parseAndKeepRawInput("0734567 8901", RegionCode::US);
1334
        $this->assertEquals("0734567 8901", $this->phoneUtil->formatInOriginalFormat($number7, RegionCode::US));
1335
1336
        // This number is valid, but we don't have a formatting pattern for it. Fall back to the raw
1337
        // input.
1338
        $number8 = $this->phoneUtil->parseAndKeepRawInput("02-4567-8900", RegionCode::KR);
1339
        $this->assertEquals("02-4567-8900", $this->phoneUtil->formatInOriginalFormat($number8, RegionCode::KR));
1340
1341
        $number9 = $this->phoneUtil->parseAndKeepRawInput("01180012345678", RegionCode::US);
1342
        $this->assertEquals("011 800 1234 5678", $this->phoneUtil->formatInOriginalFormat($number9, RegionCode::US));
1343
1344
        $number10 = $this->phoneUtil->parseAndKeepRawInput("+80012345678", RegionCode::KR);
1345
        $this->assertEquals("+800 1234 5678", $this->phoneUtil->formatInOriginalFormat($number10, RegionCode::KR));
1346
1347
        // US local numbers are formatted correctly, as we have formatting patterns for them.
1348
        $localNumberUS = $this->phoneUtil->parseAndKeepRawInput("2530000", RegionCode::US);
1349
        $this->assertEquals("253 0000", $this->phoneUtil->formatInOriginalFormat($localNumberUS, RegionCode::US));
1350
1351
        $numberWithNationalPrefixUS =
1352
            $this->phoneUtil->parseAndKeepRawInput("18003456789", RegionCode::US);
1353
        $this->assertEquals(
1354
            "1 800 345 6789",
1355
            $this->phoneUtil->formatInOriginalFormat($numberWithNationalPrefixUS, RegionCode::US)
1356
        );
1357
1358
        $numberWithoutNationalPrefixGB =
1359
            $this->phoneUtil->parseAndKeepRawInput("2087654321", RegionCode::GB);
1360
        $this->assertEquals(
1361
            "20 8765 4321",
1362
            $this->phoneUtil->formatInOriginalFormat($numberWithoutNationalPrefixGB, RegionCode::GB)
1363
        );
1364
        // Make sure no metadata is modified as a result of the previous function call.
1365
        $this->assertEquals("(020) 8765 4321", $this->phoneUtil->formatInOriginalFormat($number5, RegionCode::GB));
1366
1367
        $numberWithNationalPrefixMX =
1368
            $this->phoneUtil->parseAndKeepRawInput("013312345678", RegionCode::MX);
1369
        $this->assertEquals(
1370
            "01 33 1234 5678",
1371
            $this->phoneUtil->formatInOriginalFormat($numberWithNationalPrefixMX, RegionCode::MX)
1372
        );
1373
1374
        $numberWithoutNationalPrefixMX =
1375
            $this->phoneUtil->parseAndKeepRawInput("3312345678", RegionCode::MX);
1376
        $this->assertEquals(
1377
            "33 1234 5678",
1378
            $this->phoneUtil->formatInOriginalFormat($numberWithoutNationalPrefixMX, RegionCode::MX)
1379
        );
1380
1381
        $italianFixedLineNumber =
1382
            $this->phoneUtil->parseAndKeepRawInput("0212345678", RegionCode::IT);
1383
        $this->assertEquals(
1384
            "02 1234 5678",
1385
            $this->phoneUtil->formatInOriginalFormat($italianFixedLineNumber, RegionCode::IT)
1386
        );
1387
1388
        $numberWithNationalPrefixJP =
1389
            $this->phoneUtil->parseAndKeepRawInput("00777012", RegionCode::JP);
1390
        $this->assertEquals(
1391
            "0077-7012",
1392
            $this->phoneUtil->formatInOriginalFormat($numberWithNationalPrefixJP, RegionCode::JP)
1393
        );
1394
1395
        $numberWithoutNationalPrefixJP =
1396
            $this->phoneUtil->parseAndKeepRawInput("0777012", RegionCode::JP);
1397
        $this->assertEquals(
1398
            "0777012",
1399
            $this->phoneUtil->formatInOriginalFormat($numberWithoutNationalPrefixJP, RegionCode::JP)
1400
        );
1401
1402
        $numberWithCarrierCodeBR =
1403
            $this->phoneUtil->parseAndKeepRawInput("012 3121286979", RegionCode::BR);
1404
        $this->assertEquals(
1405
            "012 3121286979",
1406
            $this->phoneUtil->formatInOriginalFormat($numberWithCarrierCodeBR, RegionCode::BR)
1407
        );
1408
1409
        // The default national prefix used in this case is 045. When a number with national prefix 044
1410
        // is entered, we return the raw input as we don't want to change the number entered.
1411
        $numberWithNationalPrefixMX1 =
1412
            $this->phoneUtil->parseAndKeepRawInput("044(33)1234-5678", RegionCode::MX);
1413
        $this->assertEquals(
1414
            "044(33)1234-5678",
1415
            $this->phoneUtil->formatInOriginalFormat($numberWithNationalPrefixMX1, RegionCode::MX)
1416
        );
1417
1418
        $numberWithNationalPrefixMX2 =
1419
            $this->phoneUtil->parseAndKeepRawInput("045(33)1234-5678", RegionCode::MX);
1420
        $this->assertEquals(
1421
            "045 33 1234 5678",
1422
            $this->phoneUtil->formatInOriginalFormat($numberWithNationalPrefixMX2, RegionCode::MX)
1423
        );
1424
1425
        // The default international prefix used in this case is 0011. When a number with international
1426
        // prefix 0012 is entered, we return the raw input as we don't want to change the number
1427
        // entered.
1428
        $outOfCountryNumberFromAU1 =
1429
            $this->phoneUtil->parseAndKeepRawInput("0012 16502530000", RegionCode::AU);
1430
        $this->assertEquals(
1431
            "0012 16502530000",
1432
            $this->phoneUtil->formatInOriginalFormat($outOfCountryNumberFromAU1, RegionCode::AU)
1433
        );
1434
1435
        $outOfCountryNumberFromAU2 =
1436
            $this->phoneUtil->parseAndKeepRawInput("0011 16502530000", RegionCode::AU);
1437
        $this->assertEquals(
1438
            "0011 1 650 253 0000",
1439
            $this->phoneUtil->formatInOriginalFormat($outOfCountryNumberFromAU2, RegionCode::AU)
1440
        );
1441
1442
        // Test the star sign is not removed from or added to the original input by this method.
1443
        $starNumber = $this->phoneUtil->parseAndKeepRawInput("*1234", RegionCode::JP);
1444
        $this->assertEquals("*1234", $this->phoneUtil->formatInOriginalFormat($starNumber, RegionCode::JP));
1445
        $numberWithoutStar = $this->phoneUtil->parseAndKeepRawInput("1234", RegionCode::JP);
1446
        $this->assertEquals("1234", $this->phoneUtil->formatInOriginalFormat($numberWithoutStar, RegionCode::JP));
1447
1448
        // Test an invalid national number without raw input is just formatted as the national number.
1449
        $this->assertEquals(
1450
            "650253000",
1451
            $this->phoneUtil->formatInOriginalFormat(self::$usShortByOneNumber, RegionCode::US)
1452
        );
1453
    }
1454
1455
    public function testIsPremiumRate()
1456
    {
1457
        $this->assertEquals(PhoneNumberType::PREMIUM_RATE, $this->phoneUtil->getNumberType(self::$usPremium));
1458
1459
        $premiumRateNumber = new PhoneNumber();
1460
        $premiumRateNumber->setCountryCode(39)->setNationalNumber(892123);
1461
        $this->assertEquals(
1462
            PhoneNumberType::PREMIUM_RATE,
1463
            $this->phoneUtil->getNumberType($premiumRateNumber)
1464
        );
1465
1466
        $premiumRateNumber->clear();
1467
        $premiumRateNumber->setCountryCode(44)->setNationalNumber(9187654321);
1468
        $this->assertEquals(
1469
            PhoneNumberType::PREMIUM_RATE,
1470
            $this->phoneUtil->getNumberType($premiumRateNumber)
1471
        );
1472
1473
        $premiumRateNumber->clear();
1474
        $premiumRateNumber->setCountryCode(49)->setNationalNumber(9001654321);
1475
        $this->assertEquals(
1476
            PhoneNumberType::PREMIUM_RATE,
1477
            $this->phoneUtil->getNumberType($premiumRateNumber)
1478
        );
1479
1480
        $premiumRateNumber->clear();
1481
        $premiumRateNumber->setCountryCode(49)->setNationalNumber(90091234567);
1482
        $this->assertEquals(
1483
            PhoneNumberType::PREMIUM_RATE,
1484
            $this->phoneUtil->getNumberType($premiumRateNumber)
1485
        );
1486
    }
1487
1488
    public function testIsTollFree()
1489
    {
1490
        $tollFreeNumber = new PhoneNumber();
1491
1492
        $tollFreeNumber->setCountryCode(1)->setNationalNumber(8881234567);
1493
        $this->assertEquals(
1494
            PhoneNumberType::TOLL_FREE,
1495
            $this->phoneUtil->getNumberType($tollFreeNumber)
1496
        );
1497
1498
        $tollFreeNumber->clear();
1499
        $tollFreeNumber->setCountryCode(39)->setNationalNumber(803123);
1500
        $this->assertEquals(
1501
            PhoneNumberType::TOLL_FREE,
1502
            $this->phoneUtil->getNumberType($tollFreeNumber)
1503
        );
1504
1505
        $tollFreeNumber->clear();
1506
        $tollFreeNumber->setCountryCode(44)->setNationalNumber(8012345678);
1507
        $this->assertEquals(
1508
            PhoneNumberType::TOLL_FREE,
1509
            $this->phoneUtil->getNumberType($tollFreeNumber)
1510
        );
1511
1512
        $tollFreeNumber->clear();
1513
        $tollFreeNumber->setCountryCode(49)->setNationalNumber(8001234567);
1514
        $this->assertEquals(
1515
            PhoneNumberType::TOLL_FREE,
1516
            $this->phoneUtil->getNumberType($tollFreeNumber)
1517
        );
1518
1519
        $this->assertEquals(
1520
            PhoneNumberType::TOLL_FREE,
1521
            $this->phoneUtil->getNumberType(self::$internationalTollFree)
1522
        );
1523
    }
1524
1525
    public function testIsMobile()
1526
    {
1527
        $this->assertEquals(PhoneNumberType::MOBILE, $this->phoneUtil->getNumberType(self::$bsMobile));
1528
        $this->assertEquals(PhoneNumberType::MOBILE, $this->phoneUtil->getNumberType(self::$gbMobile));
1529
        $this->assertEquals(PhoneNumberType::MOBILE, $this->phoneUtil->getNumberType(self::$itMobile));
1530
        $this->assertEquals(PhoneNumberType::MOBILE, $this->phoneUtil->getNumberType(self::$arMobile));
1531
1532
        $mobileNumber = new PhoneNumber();
1533
        $mobileNumber->setCountryCode(49)->setNationalNumber(15123456789);
1534
        $this->assertEquals(PhoneNumberType::MOBILE, $this->phoneUtil->getNumberType($mobileNumber));
1535
    }
1536
1537
    public function testIsFixedLine()
1538
    {
1539
        $this->assertEquals(PhoneNumberType::FIXED_LINE, $this->phoneUtil->getNumberType(self::$bsNumber));
1540
        $this->assertEquals(PhoneNumberType::FIXED_LINE, $this->phoneUtil->getNumberType(self::$itNumber));
1541
        $this->assertEquals(PhoneNumberType::FIXED_LINE, $this->phoneUtil->getNumberType(self::$gbNumber));
1542
        $this->assertEquals(PhoneNumberType::FIXED_LINE, $this->phoneUtil->getNumberType(self::$deNumber));
1543
    }
1544
1545
    public function testIsFixedLineAndMobile()
1546
    {
1547
        $this->assertEquals(PhoneNumberType::FIXED_LINE_OR_MOBILE, $this->phoneUtil->getNumberType(self::$usNumber));
1548
1549
        $fixedLineAndMobileNumber = new PhoneNumber();
1550
        $fixedLineAndMobileNumber->setCountryCode(54)->setNationalNumber(1987654321);
1551
        $this->assertEquals(
1552
            PhoneNumberType::FIXED_LINE_OR_MOBILE,
1553
            $this->phoneUtil->getNumberType($fixedLineAndMobileNumber)
1554
        );
1555
    }
1556
1557
    public function testIsSharedCost()
1558
    {
1559
        $gbNumber = new PhoneNumber();
1560
        $gbNumber->setCountryCode(44)->setNationalNumber(8431231234);
1561
        $this->assertEquals(PhoneNumberType::SHARED_COST, $this->phoneUtil->getNumberType($gbNumber));
1562
    }
1563
1564
    public function testIsVoip()
1565
    {
1566
        $gbNumber = new PhoneNumber();
1567
        $gbNumber->setCountryCode(44)->setNationalNumber(5631231234);
1568
        $this->assertEquals(PhoneNumberType::VOIP, $this->phoneUtil->getNumberType($gbNumber));
1569
    }
1570
1571
    public function testIsPersonalNumber()
1572
    {
1573
        $gbNumber = new PhoneNumber();
1574
        $gbNumber->setCountryCode(44)->setNationalNumber(7031231234);
1575
        $this->assertEquals(PhoneNumberType::PERSONAL_NUMBER, $this->phoneUtil->getNumberType($gbNumber));
1576
    }
1577
1578
    public function testIsUnknown()
1579
    {
1580
        // Invalid numbers should be of type UNKNOWN.
1581
        $this->assertEquals(PhoneNumberType::UNKNOWN, $this->phoneUtil->getNumberType(self::$usLocalNumber));
1582
    }
1583
1584
    public function testIsValidNumber()
1585
    {
1586
        $this->assertTrue($this->phoneUtil->isValidNumber(self::$usNumber));
1587
        $this->assertTrue($this->phoneUtil->isValidNumber(self::$itNumber));
1588
        $this->assertTrue($this->phoneUtil->isValidNumber(self::$gbMobile));
1589
        $this->assertTrue($this->phoneUtil->isValidNumber(self::$internationalTollFree));
1590
        $this->assertTrue($this->phoneUtil->isValidNumber(self::$universalPremiumRate));
1591
1592
        $nzNumber = new PhoneNumber();
1593
        $nzNumber->setCountryCode(64)->setNationalNumber(21387835);
1594
        $this->assertTrue($this->phoneUtil->isValidNumber($nzNumber));
1595
    }
1596
1597
    public function testIsValidForRegion()
1598
    {
1599
        // This number is valid for the Bahamas, but is not a valid US number.
1600
        $this->assertTrue($this->phoneUtil->isValidNumber(self::$bsNumber));
1601
        $this->assertTrue($this->phoneUtil->isValidNumberForRegion(self::$bsNumber, RegionCode::BS));
1602
        $this->assertFalse($this->phoneUtil->isValidNumberForRegion(self::$bsNumber, RegionCode::US));
1603
        $bsInvalidNumber = new PhoneNumber();
1604
        $bsInvalidNumber->setCountryCode(1)->setNationalNumber(2421232345);
1605
        // This number is no longer valid.
1606
        $this->assertFalse($this->phoneUtil->isValidNumber($bsInvalidNumber));
1607
1608
        // La Mayotte and Reunion use 'leadingDigits' to differentiate them.
1609
        $reNumber = new PhoneNumber();
1610
        $reNumber->setCountryCode(262)->setNationalNumber(262123456);
1611
        $this->assertTrue($this->phoneUtil->isValidNumber($reNumber));
1612
        $this->assertTrue($this->phoneUtil->isValidNumberForRegion($reNumber, RegionCode::RE));
1613
        $this->assertFalse($this->phoneUtil->isValidNumberForRegion($reNumber, RegionCode::YT));
1614
        // Now change the number to be a number for La Mayotte.
1615
        $reNumber->setNationalNumber(269601234);
1616
        $this->assertTrue($this->phoneUtil->isValidNumberForRegion($reNumber, RegionCode::YT));
1617
        $this->assertFalse($this->phoneUtil->isValidNumberForRegion($reNumber, RegionCode::RE));
1618
        // This number is no longer valid for La Reunion.
1619
        $reNumber->setNationalNumber(269123456);
1620
        $this->assertFalse($this->phoneUtil->isValidNumberForRegion($reNumber, RegionCode::YT));
1621
        $this->assertFalse($this->phoneUtil->isValidNumberForRegion($reNumber, RegionCode::RE));
1622
        $this->assertFalse($this->phoneUtil->isValidNumber($reNumber));
1623
        // However, it should be recognised as from La Mayotte, since it is valid for this region.
1624
        $this->assertEquals(RegionCode::YT, $this->phoneUtil->getRegionCodeForNumber($reNumber));
1625
        // This number is valid in both places.
1626
        $reNumber->setNationalNumber(800123456);
1627
        $this->assertTrue($this->phoneUtil->isValidNumberForRegion($reNumber, RegionCode::YT));
1628
        $this->assertTrue($this->phoneUtil->isValidNumberForRegion($reNumber, RegionCode::RE));
1629
        $this->assertTrue($this->phoneUtil->isValidNumberForRegion(self::$internationalTollFree, RegionCode::UN001));
1630
        $this->assertFalse($this->phoneUtil->isValidNumberForRegion(self::$internationalTollFree, RegionCode::US));
1631
        $this->assertFalse($this->phoneUtil->isValidNumberForRegion(self::$internationalTollFree, RegionCode::ZZ));
1632
1633
        $invalidNumber = new PhoneNumber();
1634
        // Invalid country calling codes.
1635
        $invalidNumber->setCountryCode(3923)->setNationalNumber(2366);
1636
        $this->assertFalse($this->phoneUtil->isValidNumberForRegion($invalidNumber, RegionCode::ZZ));
1637
        $this->assertFalse($this->phoneUtil->isValidNumberForRegion($invalidNumber, RegionCode::UN001));
1638
        $invalidNumber->setCountryCode(0);
1639
        $this->assertFalse($this->phoneUtil->isValidNumberForRegion($invalidNumber, RegionCode::UN001));
1640
        $this->assertFalse($this->phoneUtil->isValidNumberForRegion($invalidNumber, RegionCode::ZZ));
1641
    }
1642
1643
    public function testIsNotValidNumber()
1644
    {
1645
        $this->assertFalse($this->phoneUtil->isValidNumber(self::$usLocalNumber));
1646
1647
        $invalidNumber = new PhoneNumber();
1648
        $invalidNumber->setCountryCode(39)->setNationalNumber(23661830000)->setItalianLeadingZero(true);
1649
        $this->assertFalse($this->phoneUtil->isValidNumber($invalidNumber));
1650
1651
        $invalidNumber->clear();
1652
        $invalidNumber->setCountryCode(44)->setNationalNumber(791234567);
1653
        $this->assertFalse($this->phoneUtil->isValidNumber($invalidNumber));
1654
1655
        $invalidNumber->clear();
1656
        $invalidNumber->setCountryCode(49)->setNationalNumber(1234);
1657
        $this->assertFalse($this->phoneUtil->isValidNumber($invalidNumber));
1658
1659
        $invalidNumber->clear();
1660
        $invalidNumber->setCountryCode(64)->setNationalNumber(3316005);
1661
        $this->assertFalse($this->phoneUtil->isValidNumber($invalidNumber));
1662
1663
        $invalidNumber->clear();
1664
        // Invalid country calling codes.
1665
        $invalidNumber->setCountryCode(3923)->setNationalNumber(2366);
1666
        $this->assertFalse($this->phoneUtil->isValidNumber($invalidNumber));
1667
        $invalidNumber->setCountryCode(0);
1668
        $this->assertFalse($this->phoneUtil->isValidNumber($invalidNumber));
1669
1670
        $this->assertFalse($this->phoneUtil->isValidNumber(self::$internationalTollFreeTooLong));
1671
    }
1672
1673
    public function testGetRegionCodeForCountryCode()
1674
    {
1675
        $this->assertEquals(RegionCode::US, $this->phoneUtil->getRegionCodeForCountryCode(1));
1676
        $this->assertEquals(RegionCode::GB, $this->phoneUtil->getRegionCodeForCountryCode(44));
1677
        $this->assertEquals(RegionCode::DE, $this->phoneUtil->getRegionCodeForCountryCode(49));
1678
        $this->assertEquals(RegionCode::UN001, $this->phoneUtil->getRegionCodeForCountryCode(800));
1679
        $this->assertEquals(RegionCode::UN001, $this->phoneUtil->getRegionCodeForCountryCode(979));
1680
    }
1681
1682
    public function testGetRegionCodeForNumber()
1683
    {
1684
        $this->assertEquals(RegionCode::BS, $this->phoneUtil->getRegionCodeForNumber(self::$bsNumber));
1685
        $this->assertEquals(RegionCode::US, $this->phoneUtil->getRegionCodeForNumber(self::$usNumber));
1686
        $this->assertEquals(RegionCode::GB, $this->phoneUtil->getRegionCodeForNumber(self::$gbMobile));
1687
        $this->assertEquals(RegionCode::UN001, $this->phoneUtil->getRegionCodeForNumber(self::$internationalTollFree));
1688
        $this->assertEquals(RegionCode::UN001, $this->phoneUtil->getRegionCodeForNumber(self::$universalPremiumRate));
1689
    }
1690
1691
    public function testGetRegionCodesForCountryCode()
1692
    {
1693
        $regionCodesForNANPA = $this->phoneUtil->getRegionCodesForCountryCode(1);
1694
        $this->assertContains(RegionCode::US, $regionCodesForNANPA);
1695
        $this->assertContains(RegionCode::BS, $regionCodesForNANPA);
1696
        $this->assertContains(RegionCode::GB, $this->phoneUtil->getRegionCodesForCountryCode(44));
1697
        $this->assertContains(RegionCode::DE, $this->phoneUtil->getRegionCodesForCountryCode(49));
1698
        $this->assertContains(RegionCode::UN001, $this->phoneUtil->getRegionCodesForCountryCode(800));
1699
        // Test with invalid country calling code.
1700
        $this->assertEmpty($this->phoneUtil->getRegionCodesForCountryCode(-1));
1701
    }
1702
1703
    public function testGetCountryCodeForRegion()
1704
    {
1705
        $this->assertEquals(1, $this->phoneUtil->getCountryCodeForRegion(RegionCode::US));
1706
        $this->assertEquals(64, $this->phoneUtil->getCountryCodeForRegion(RegionCode::NZ));
1707
        $this->assertEquals(0, $this->phoneUtil->getCountryCodeForRegion(null));
1708
        $this->assertEquals(0, $this->phoneUtil->getCountryCodeForRegion(RegionCode::ZZ));
1709
        $this->assertEquals(0, $this->phoneUtil->getCountryCodeForRegion(RegionCode::UN001));
1710
        // CS is already deprecated so the library doesn't support it
1711
        $this->assertEquals(0, $this->phoneUtil->getCountryCodeForRegion(RegionCode::CS));
1712
    }
1713
1714
    public function testGetNationalDiallingPrefixForRegion()
1715
    {
1716
        $this->assertEquals("1", $this->phoneUtil->getNddPrefixForRegion(RegionCode::US, false));
1717
        // Test non-main country to see it gets the national dialling prefix for the main country with
1718
        // that country calling code.
1719
        $this->assertEquals("1", $this->phoneUtil->getNddPrefixForRegion(RegionCode::BS, false));
1720
        $this->assertEquals("0", $this->phoneUtil->getNddPrefixForRegion(RegionCode::NZ, false));
1721
        // Test case with non digit in the national prefix.
1722
        $this->assertEquals("0~0", $this->phoneUtil->getNddPrefixForRegion(RegionCode::AO, false));
1723
        $this->assertEquals("00", $this->phoneUtil->getNddPrefixForRegion(RegionCode::AO, true));
1724
        // Test cases with invalid regions.
1725
        $this->assertNull($this->phoneUtil->getNddPrefixForRegion(null, false));
1726
        $this->assertNull($this->phoneUtil->getNddPrefixForRegion(RegionCode::ZZ, false));
1727
        $this->assertNull($this->phoneUtil->getNddPrefixForRegion(RegionCode::UN001, false));
1728
        // CS is already deprecated so the library doesn't support it.
1729
        $this->assertNull($this->phoneUtil->getNddPrefixForRegion(RegionCode::CS, false));
1730
    }
1731
1732
    public function testIsNANPACountry()
1733
    {
1734
        $this->assertTrue($this->phoneUtil->isNANPACountry(RegionCode::US));
1735
        $this->assertTrue($this->phoneUtil->isNANPACountry(RegionCode::BS));
1736
        $this->assertFalse($this->phoneUtil->isNANPACountry(RegionCode::DE));
1737
        $this->assertFalse($this->phoneUtil->isNANPACountry(RegionCode::ZZ));
1738
        $this->assertFalse($this->phoneUtil->isNANPACountry(RegionCode::UN001));
1739
        $this->assertFalse($this->phoneUtil->isNANPACountry(null));
1740
    }
1741
1742
    public function testIsPossibleNumber()
1743
    {
1744
        $this->assertTrue($this->phoneUtil->isPossibleNumber(self::$usNumber));
1745
        $this->assertTrue($this->phoneUtil->isPossibleNumber(self::$usLocalNumber));
1746
        $this->assertTrue($this->phoneUtil->isPossibleNumber(self::$gbNumber));
1747
        $this->assertTrue($this->phoneUtil->isPossibleNumber(self::$internationalTollFree));
1748
1749
        $this->assertTrue($this->phoneUtil->isPossibleNumber("+1 650 253 0000", RegionCode::US));
1750
        $this->assertTrue($this->phoneUtil->isPossibleNumber("+1 650 GOO OGLE", RegionCode::US));
1751
        $this->assertTrue($this->phoneUtil->isPossibleNumber("(650) 253-0000", RegionCode::US));
1752
        $this->assertTrue($this->phoneUtil->isPossibleNumber("253-0000", RegionCode::US));
1753
        $this->assertTrue($this->phoneUtil->isPossibleNumber("+1 650 253 0000", RegionCode::GB));
1754
        $this->assertTrue($this->phoneUtil->isPossibleNumber("+44 20 7031 3000", RegionCode::GB));
1755
        $this->assertTrue($this->phoneUtil->isPossibleNumber("(020) 7031 300", RegionCode::GB));
1756
        $this->assertTrue($this->phoneUtil->isPossibleNumber("7031 3000", RegionCode::GB));
1757
        $this->assertTrue($this->phoneUtil->isPossibleNumber("3331 6005", RegionCode::NZ));
1758
        $this->assertTrue($this->phoneUtil->isPossibleNumber("+800 1234 5678", RegionCode::UN001));
1759
    }
1760
1761
    public function testIsPossibleNumberWithReason()
1762
    {
1763
        // National numbers for country calling code +1 that are within 7 to 10 digits are possible.
1764
        $this->assertEquals(
1765
            ValidationResult::IS_POSSIBLE,
1766
            $this->phoneUtil->isPossibleNumberWithReason(self::$usNumber)
1767
        );
1768
1769
        $this->assertEquals(
1770
            ValidationResult::IS_POSSIBLE,
1771
            $this->phoneUtil->isPossibleNumberWithReason(self::$usLocalNumber)
1772
        );
1773
1774
        $this->assertEquals(
1775
            ValidationResult::TOO_LONG,
1776
            $this->phoneUtil->isPossibleNumberWithReason(self::$usLongNumber)
1777
        );
1778
1779
        $number = new PhoneNumber();
1780
        $number->setCountryCode(0)->setNationalNumber(2530000);
1781
        $this->assertEquals(
1782
            ValidationResult::INVALID_COUNTRY_CODE,
1783
            $this->phoneUtil->isPossibleNumberWithReason($number)
1784
        );
1785
1786
        $number->clear();
1787
        $number->setCountryCode(1)->setNationalNumber(253000);
1788
        $this->assertEquals(ValidationResult::TOO_SHORT, $this->phoneUtil->isPossibleNumberWithReason($number));
1789
1790
        $number->clear();
1791
        $number->setCountryCode(65)->setNationalNumber(1234567890);
1792
        $this->assertEquals(ValidationResult::IS_POSSIBLE, $this->phoneUtil->isPossibleNumberWithReason($number));
1793
1794
        $this->assertEquals(
1795
            ValidationResult::TOO_LONG,
1796
            $this->phoneUtil->isPossibleNumberWithReason(self::$internationalTollFreeTooLong)
1797
        );
1798
    }
1799
1800
    public function testIsNotPossibleNumber()
1801
    {
1802
        $this->assertFalse($this->phoneUtil->isPossibleNumber(self::$usLongNumber));
1803
        $this->assertFalse($this->phoneUtil->isPossibleNumber(self::$internationalTollFreeTooLong));
1804
1805
        $number = new PhoneNumber();
1806
        $number->setCountryCode(1)->setNationalNumber(253000);
1807
        $this->assertFalse($this->phoneUtil->isPossibleNumber($number));
1808
1809
        $number->clear();
1810
        $number->setCountryCode(44)->setNationalNumber(300);
1811
        $this->assertFalse($this->phoneUtil->isPossibleNumber($number));
1812
        $this->assertFalse($this->phoneUtil->isPossibleNumber("+1 650 253 00000", RegionCode::US));
1813
        $this->assertFalse($this->phoneUtil->isPossibleNumber("(650) 253-00000", RegionCode::US));
1814
        $this->assertFalse($this->phoneUtil->isPossibleNumber("I want a Pizza", RegionCode::US));
1815
        $this->assertFalse($this->phoneUtil->isPossibleNumber("253-000", RegionCode::US));
1816
        $this->assertFalse($this->phoneUtil->isPossibleNumber("1 3000", RegionCode::GB));
1817
        $this->assertFalse($this->phoneUtil->isPossibleNumber("+44 300", RegionCode::GB));
1818
        $this->assertFalse($this->phoneUtil->isPossibleNumber("+800 1234 5678 9", RegionCode::UN001));
1819
    }
1820
1821
    public function testTruncateTooLongNumber()
1822
    {
1823
        // GB number 080 1234 5678, but entered with 4 extra digits at the end.
1824
        $tooLongNumber = new PhoneNumber();
1825
        $tooLongNumber->setCountryCode(44)->setNationalNumber(80123456780123);
1826
        $validNumber = new PhoneNumber();
1827
        $validNumber->setCountryCode(44)->setNationalNumber(8012345678);
1828
        $this->assertTrue($this->phoneUtil->truncateTooLongNumber($tooLongNumber));
1829
        $this->assertEquals($validNumber, $tooLongNumber);
1830
1831
        // IT number 022 3456 7890, but entered with 3 extra digits at the end.
1832
        $tooLongNumber->clear();
1833
        $tooLongNumber->setCountryCode(39)->setNationalNumber(2234567890123)->setItalianLeadingZero(true);
1834
        $validNumber->clear();
1835
        $validNumber->setCountryCode(39)->setNationalNumber(2234567890)->setItalianLeadingZero(true);
1836
        $this->assertTrue($this->phoneUtil->truncateTooLongNumber($tooLongNumber));
1837
        $this->assertEquals($validNumber, $tooLongNumber);
1838
1839
        // US number 650-253-0000, but entered with one additional digit at the end.
1840
        $tooLongNumber->clear();
1841
        $tooLongNumber->mergeFrom(self::$usLongNumber);
1842
        $this->assertTrue($this->phoneUtil->truncateTooLongNumber($tooLongNumber));
1843
        $this->assertEquals(self::$usNumber, $tooLongNumber);
1844
1845
        $tooLongNumber->clear();
1846
        $tooLongNumber->mergeFrom(self::$internationalTollFreeTooLong);
1847
        $this->assertTrue($this->phoneUtil->truncateTooLongNumber($tooLongNumber));
1848
        $this->assertEquals(self::$internationalTollFree, $tooLongNumber);
1849
1850
        // Tests what happens when a valid number is passed in.
1851
        $validNumberCopy = new PhoneNumber();
1852
        $validNumberCopy->mergeFrom($validNumber);
1853
        $this->assertTrue($this->phoneUtil->truncateTooLongNumber($validNumber));
1854
1855
        // Tests the number is not modified.
1856
        $this->assertEquals($validNumberCopy, $validNumber);
1857
1858
        // Tests what happens when a number with invalid prefix is passed in.
1859
        $numberWithInvalidPrefix = new PhoneNumber();
1860
        // The test metadata says US numbers cannot have prefix 240.
1861
        $numberWithInvalidPrefix->setCountryCode(1)->setNationalNumber(2401234567);
1862
        $invalidNumberCopy = new PhoneNumber();
1863
        $invalidNumberCopy->mergeFrom($numberWithInvalidPrefix);
1864
        $this->assertFalse($this->phoneUtil->truncateTooLongNumber($numberWithInvalidPrefix));
1865
        // Tests the number is not modified.
1866
        $this->assertEquals($invalidNumberCopy, $numberWithInvalidPrefix);
1867
1868
        // Tests what happens when a too short number is passed in.
1869
        $tooShortNumber = new PhoneNumber();
1870
        $tooShortNumber->setCountryCode(1)->setNationalNumber(1234);
1871
        $tooShortNumberCopy = new PhoneNumber();
1872
        $tooShortNumberCopy->mergeFrom($tooShortNumber);
1873
        $this->assertFalse($this->phoneUtil->truncateTooLongNumber($tooShortNumber));
1874
        // Tests the number is not modified.
1875
        $this->assertEquals($tooShortNumberCopy, $tooShortNumber);
1876
    }
1877
1878
    public function testIsViablePhoneNumber()
1879
    {
1880
        $this->assertFalse(PhoneNumberUtil::isViablePhoneNumber("1"));
1881
        // Only one or two digits before strange non-possible punctuation.
1882
        $this->assertFalse(PhoneNumberUtil::isViablePhoneNumber("1+1+1"));
1883
        $this->assertFalse(PhoneNumberUtil::isViablePhoneNumber("80+0"));
1884
        // Two digits is viable.
1885
        $this->assertTrue(PhoneNumberUtil::isViablePhoneNumber("00"));
1886
        $this->assertTrue(PhoneNumberUtil::isViablePhoneNumber("111"));
1887
        // Alpha numbers.
1888
        $this->assertTrue(PhoneNumberUtil::isViablePhoneNumber("0800-4-pizza"));
1889
        $this->assertTrue(PhoneNumberUtil::isViablePhoneNumber("0800-4-PIZZA"));
1890
1891
        // We need at least three digits before any alpha characters.
1892
        $this->assertFalse(PhoneNumberUtil::isViablePhoneNumber("08-PIZZA"));
1893
        $this->assertFalse(PhoneNumberUtil::isViablePhoneNumber("8-PIZZA"));
1894
        $this->assertFalse(PhoneNumberUtil::isViablePhoneNumber("12. March"));
1895
    }
1896
1897
    public function testIsViablePhoneNumberNonAscii()
1898
    {
1899
        // Only one or two digits before possible punctuation followed by more digits.
1900
        $this->assertTrue(PhoneNumberUtil::isViablePhoneNumber("1" . pack('H*', 'e38080') . "34"));
1901
        $this->assertFalse(PhoneNumberUtil::isViablePhoneNumber("1" . pack('H*', 'e38080') . "3+4"));
1902
        // Unicode variants of possible starting character and other allowed punctuation/digits.
1903
        $this->assertTrue(
1904
            PhoneNumberUtil::isViablePhoneNumber(
1905
                pack('H*', 'efbc88') . "1" . pack("H*", 'efbc89') . pack('H*', 'e38080') . "3456789"
1906
            )
1907
        );
1908
        // Testing a leading + is okay.
1909
        $this->assertTrue(
1910
            PhoneNumberUtil::isViablePhoneNumber("+1" . pack("H*", 'efbc89') . pack('H*', 'e38080') . "3456789")
1911
        );
1912
    }
1913
1914
    public function testExtractPossibleNumber()
1915
    {
1916
        // Removes preceding funky punctuation and letters but leaves the rest untouched.
1917
        $this->assertEquals("0800-345-600", PhoneNumberUtil::extractPossibleNumber("Tel:0800-345-600"));
1918
        $this->assertEquals("0800 FOR PIZZA", PhoneNumberUtil::extractPossibleNumber("Tel:0800 FOR PIZZA"));
1919
        // Should not remove plus sign
1920
        $this->assertEquals("+800-345-600", PhoneNumberUtil::extractPossibleNumber("Tel:+800-345-600"));
1921
        // Should recognise wide digits as possible start values.
1922
        $this->assertEquals(
1923
            pack("H*", 'efbc90') . pack("H*", 'efbc92') . pack("H*", 'efbc93'),
1924
            PhoneNumberUtil::extractPossibleNumber(pack("H*", 'efbc90') . pack("H*", 'efbc92') . pack("H*", 'efbc93'))
1925
        );
1926
        // Dashes are not possible start values and should be removed.
1927
        $this->assertEquals(
1928
            pack("H*", 'efbc91') . pack("H*", 'efbc92') . pack("H*", 'efbc93'),
1929
            PhoneNumberUtil::extractPossibleNumber(
1930
                "Num-" . pack("H*", 'efbc91') . pack("H*", 'efbc92') . pack("H*", 'efbc93')
1931
            )
1932
        );
1933
        // If not possible number present, return empty string.
1934
        $this->assertEquals("", PhoneNumberUtil::extractPossibleNumber("Num-...."));
1935
        // Leading brackets are stripped - these are not used when parsing.
1936
        $this->assertEquals("650) 253-0000", PhoneNumberUtil::extractPossibleNumber("(650) 253-0000"));
1937
1938
        // Trailing non-alpha-numeric characters should be removed.
1939
        $this->assertEquals("650) 253-0000", PhoneNumberUtil::extractPossibleNumber("(650) 253-0000..- .."));
1940
        $this->assertEquals("650) 253-0000", PhoneNumberUtil::extractPossibleNumber("(650) 253-0000."));
1941
        // This case has a trailing RTL char.
1942
        $this->assertEquals(
1943
            "650) 253-0000",
1944
            PhoneNumberUtil::extractPossibleNumber("(650) 253-0000" . pack("H*", 'e2808f'))
1945
        );
1946
    }
1947
1948
    public function testMaybeStripNationalPrefix()
1949
    {
1950
        $metadata = new PhoneMetadata();
1951
        $metadata->setNationalPrefixForParsing("34");
1952
        $phoneNumberDesc = new PhoneNumberDesc();
1953
        $phoneNumberDesc->setNationalNumberPattern("\\d{4,8}");
1954
        $metadata->setGeneralDesc($phoneNumberDesc);
1955
1956
        $numberToStrip = "34356778";
1957
        $strippedNumber = "356778";
1958
1959
        $carrierCode = null;
1960
1961
        $this->assertTrue(
1962
            $this->phoneUtil->maybeStripNationalPrefixAndCarrierCode($numberToStrip, $metadata, $carrierCode)
1963
        );
1964
        $this->assertEquals($strippedNumber, $numberToStrip, "Should have had national prefix stripped.");
1965
        // Retry stripping - now the number should not start with the national prefix, so no more
1966
        // stripping should occur.
1967
        $carrierCode = null;
1968
        $this->assertFalse(
1969
            $this->phoneUtil->maybeStripNationalPrefixAndCarrierCode($numberToStrip, $metadata, $carrierCode)
1970
        );
1971
        $this->assertEquals($strippedNumber, $numberToStrip, "Should have had no change - no national prefix present.");
1972
1973
        // Some countries have no national prefix. Repeat test with none specified.
1974
        $metadata->setNationalPrefixForParsing("");
1975
        $carrierCode = null;
1976
        $this->assertFalse(
1977
            $this->phoneUtil->maybeStripNationalPrefixAndCarrierCode($numberToStrip, $metadata, $carrierCode)
1978
        );
1979
        $this->assertEquals($strippedNumber, $numberToStrip, "Should not strip anything with empty national prefix.");
1980
1981
        // If the resultant number doesn't match the national rule, it shouldn't be stripped.
1982
        $metadata->setNationalPrefixForParsing("3");
1983
        $numberToStrip = "3123";
1984
        $strippedNumber = "3123";
1985
        $carrierCode = null;
1986
        $this->assertFalse(
1987
            $this->phoneUtil->maybeStripNationalPrefixAndCarrierCode($numberToStrip, $metadata, $carrierCode)
1988
        );
1989
        $this->assertEquals(
1990
            $strippedNumber,
1991
            $numberToStrip,
1992
            "Should have had no change - after stripping, it wouldn't have matched the national rule."
1993
        );
1994
1995
        // Test extracting carrier selection code.
1996
        $metadata->setNationalPrefixForParsing("0(81)?");
1997
        $numberToStrip = "08122123456";
1998
        $strippedNumber = "22123456";
1999
        $carrierCode = "";
2000
        $this->assertTrue(
2001
            $this->phoneUtil->maybeStripNationalPrefixAndCarrierCode($numberToStrip, $metadata, $carrierCode)
2002
        );
2003
        $this->assertEquals("81", $carrierCode);
2004
        $this->assertEquals(
2005
            $strippedNumber,
2006
            $numberToStrip,
2007
            "Should have had national prefix and carrier code stripped."
2008
        );
2009
2010
        // If there was a transform rule, check it was applied.
2011
        $metadata->setNationalPrefixTransformRule("5\${1}5");
2012
        // Note that a capturing group is present here.
2013
        $metadata->setNationalPrefixForParsing("0(\\d{2})");
2014
        $numberToStrip = "031123";
2015
        $transformedNumber = "5315123";
2016
        $carrierCode = null;
2017
        $this->assertTrue(
2018
            $this->phoneUtil->maybeStripNationalPrefixAndCarrierCode($numberToStrip, $metadata, $carrierCode)
2019
        );
2020
        $this->assertEquals($transformedNumber, $numberToStrip, "Should transform the 031 to a 5315.");
2021
    }
2022
2023
    public function testMaybeStripInternationalPrefix()
2024
    {
2025
        $internationalPrefix = "00[39]";
2026
        $numberToStrip = "0034567700-3898003";
2027
        // Note the dash is removed as part of the normalization.
2028
        $strippedNumber = "45677003898003";
2029
        $this->assertEquals(
2030
            CountryCodeSource::FROM_NUMBER_WITH_IDD,
2031
            $this->phoneUtil->maybeStripInternationalPrefixAndNormalize($numberToStrip, $internationalPrefix)
2032
        );
2033
        $this->assertEquals(
2034
            $strippedNumber,
2035
            $numberToStrip,
2036
            "The number supplied was not stripped of its international prefix."
2037
        );
2038
2039
        // Now the number no longer starts with an IDD prefix, so it should now report
2040
        // FROM_DEFAULT_COUNTRY.
2041
        $this->assertEquals(
2042
            CountryCodeSource::FROM_DEFAULT_COUNTRY,
2043
            $this->phoneUtil->maybeStripInternationalPrefixAndNormalize($numberToStrip, $internationalPrefix)
2044
        );
2045
2046
        $numberToStrip = "00945677003898003";
2047
        $this->assertEquals(
2048
            CountryCodeSource::FROM_NUMBER_WITH_IDD,
2049
            $this->phoneUtil->maybeStripInternationalPrefixAndNormalize($numberToStrip, $internationalPrefix)
2050
        );
2051
        $this->assertEquals(
2052
            $strippedNumber,
2053
            $numberToStrip,
2054
            "The number supplied was not stripped of its international prefix."
2055
        );
2056
2057
        // Test it works when the international prefix is broken up by spaces.
2058
        $numberToStrip = "00 9 45677003898003";
2059
        $this->assertEquals(
2060
            CountryCodeSource::FROM_NUMBER_WITH_IDD,
2061
            $this->phoneUtil->maybeStripInternationalPrefixAndNormalize($numberToStrip, $internationalPrefix)
2062
        );
2063
        $this->assertEquals(
2064
            $strippedNumber,
2065
            $numberToStrip,
2066
            "The number supplied was not stripped of its international prefix."
2067
        );
2068
2069
        // Now the number no longer starts with an IDD prefix, so it should now report
2070
        // FROM_DEFAULT_COUNTRY.
2071
        $this->assertEquals(
2072
            CountryCodeSource::FROM_DEFAULT_COUNTRY,
2073
            $this->phoneUtil->maybeStripInternationalPrefixAndNormalize($numberToStrip, $internationalPrefix)
2074
        );
2075
2076
        // Test the + symbol is also recognised and stripped.
2077
        $numberToStrip = "+45677003898003";
2078
        $strippedNumber = "45677003898003";
2079
        $this->assertEquals(
2080
            CountryCodeSource::FROM_NUMBER_WITH_PLUS_SIGN,
2081
            $this->phoneUtil->maybeStripInternationalPrefixAndNormalize($numberToStrip, $internationalPrefix)
2082
        );
2083
        $this->assertEquals(
2084
            $strippedNumber,
2085
            $numberToStrip,
2086
            "The number supplied was not stripped of the plus symbol."
2087
        );
2088
2089
        // If the number afterwards is a zero, we should not strip this - no country calling code begins
2090
        // with 0.
2091
        $numberToStrip = "0090112-3123";
2092
        $strippedNumber = "00901123123";
2093
        $this->assertEquals(
2094
            CountryCodeSource::FROM_DEFAULT_COUNTRY,
2095
            $this->phoneUtil->maybeStripInternationalPrefixAndNormalize($numberToStrip, $internationalPrefix)
2096
        );
2097
        $this->assertEquals(
2098
            $strippedNumber,
2099
            $numberToStrip,
2100
            "The number supplied had a 0 after the match so shouldn't be stripped."
2101
        );
2102
2103
        // Here the 0 is separated by a space from the IDD.
2104
        $numberToStrip = "009 0-112-3123";
2105
        $this->assertEquals(
2106
            CountryCodeSource::FROM_DEFAULT_COUNTRY,
2107
            $this->phoneUtil->maybeStripInternationalPrefixAndNormalize($numberToStrip, $internationalPrefix)
2108
        );
2109
    }
2110
2111
    public function testMaybeExtractCountryCode()
2112
    {
2113
        $number = new PhoneNumber();
2114
        $metadata = $this->phoneUtil->getMetadataForRegion(RegionCode::US);
2115
        // Note that for the US, the IDD is 011.
2116
        try {
2117
            $phoneNumber = "011112-3456789";
2118
            $strippedNumber = "123456789";
2119
            $countryCallingCode = 1;
2120
            $numberToFill = "";
2121
            $this->assertEquals(
2122
                $countryCallingCode,
2123
                $this->phoneUtil->maybeExtractCountryCode($phoneNumber, $metadata, $numberToFill, true, $number),
2124
                "Did not extract country calling code " . $countryCallingCode . " correctly."
2125
            );
2126
            $this->assertEquals(
2127
                CountryCodeSource::FROM_NUMBER_WITH_IDD,
2128
                $number->getCountryCodeSource(),
2129
                "Did not figure out CountryCodeSource correctly"
2130
            );
2131
            // Should strip and normalize national significant number.
2132
            $this->assertEquals(
2133
                $strippedNumber,
2134
                $numberToFill,
2135
                "Did not strip off the country calling code correctly."
2136
            );
2137
        } catch (NumberParseException $e) {
2138
            $this->fail("Should not have thrown an exception: " . $e->getMessage());
2139
        }
2140
        $number->clear();
2141
        try {
2142
            $phoneNumber = "+6423456789";
2143
            $countryCallingCode = 64;
2144
            $numberToFill = "";
2145
            $this->assertEquals(
2146
                $countryCallingCode,
2147
                $this->phoneUtil->maybeExtractCountryCode($phoneNumber, $metadata, $numberToFill, true, $number),
2148
                "Did not extract country calling code " . $countryCallingCode . " correctly."
2149
            );
2150
            $this->assertEquals(
2151
                CountryCodeSource::FROM_NUMBER_WITH_PLUS_SIGN,
2152
                $number->getCountryCodeSource(),
2153
                "Did not figure out CountryCodeSource correctly"
2154
            );
2155
        } catch (NumberParseException $e) {
2156
            $this->fail("Should not have thrown an exception: " . $e->getMessage());
2157
        }
2158
        $number->clear();
2159
        try {
2160
            $phoneNumber = "+80012345678";
2161
            $countryCallingCode = 800;
2162
            $numberToFill = "";
2163
            $this->assertEquals(
2164
                $countryCallingCode,
2165
                $this->phoneUtil->maybeExtractCountryCode($phoneNumber, $metadata, $numberToFill, true, $number),
2166
                "Did not extract country calling code " . $countryCallingCode . " correctly."
2167
            );
2168
            $this->assertEquals(
2169
                CountryCodeSource::FROM_NUMBER_WITH_PLUS_SIGN,
2170
                $number->getCountryCodeSource(),
2171
                "Did not figure out CountryCodeSource correctly"
2172
            );
2173
        } catch (NumberParseException $e) {
2174
            $this->fail("Should not have thrown an exception: " . $e->getMessage());
2175
        }
2176
        $number->clear();
2177
        try {
2178
            $phoneNumber = "2345-6789";
2179
            $numberToFill = "";
2180
            $this->assertEquals(
2181
                0,
2182
                $this->phoneUtil->maybeExtractCountryCode($phoneNumber, $metadata, $numberToFill, true, $number),
2183
                "Should not have extracted a country calling code - no international prefix present."
2184
            );
2185
            $this->assertEquals(
2186
                CountryCodeSource::FROM_DEFAULT_COUNTRY,
2187
                $number->getCountryCodeSource(),
2188
                "Did not figure out CountryCodeSource correctly"
2189
            );
2190
        } catch (NumberParseException $e) {
2191
            $this->fail("Should not have thrown an exception: " . $e->getMessage());
2192
        }
2193
        $number->clear();
2194
        try {
2195
            $phoneNumber = "0119991123456789";
2196
            $numberToFill = "";
2197
            $this->phoneUtil->maybeExtractCountryCode($phoneNumber, $metadata, $numberToFill, true, $number);
2198
            $this->fail("Should have thrown an exception, no valid country calling code present.");
2199
        } catch (NumberParseException $e) {
2200
            // Expected.
2201
            $this->assertEquals(
2202
                NumberParseException::INVALID_COUNTRY_CODE,
2203
                $e->getErrorType(),
2204
                "Wrong error type stored in exception."
2205
            );
2206
        }
2207
        $number->clear();
2208
        try {
2209
            $phoneNumber = "(1 610) 619 4466";
2210
            $countryCallingCode = 1;
2211
            $numberToFill = "";
2212
            $this->assertEquals(
2213
                $countryCallingCode,
2214
                $this->phoneUtil->maybeExtractCountryCode($phoneNumber, $metadata, $numberToFill, true, $number),
2215
                "Should have extracted the country calling code of the region passed in"
2216
            );
2217
            $this->assertEquals(
2218
                CountryCodeSource::FROM_NUMBER_WITHOUT_PLUS_SIGN,
2219
                $number->getCountryCodeSource(),
2220
                "Did not figure out CountryCodeSource correctly"
2221
            );
2222
        } catch (NumberParseException $e) {
2223
            $this->fail("Should not have thrown an exception: " . $e->getMessage());
2224
        }
2225
        $number->clear();
2226
        try {
2227
            $phoneNumber = "(1 610) 619 4466";
2228
            $countryCallingCode = 1;
2229
            $numberToFill = "";
2230
            $this->assertEquals(
2231
                $countryCallingCode,
2232
                $this->phoneUtil->maybeExtractCountryCode($phoneNumber, $metadata, $numberToFill, false, $number),
2233
                "Should have extracted the country calling code of the region passed in"
2234
            );
2235
            $this->assertFalse($number->hasCountryCodeSource(), "Should not contain CountryCodeSource");
2236
        } catch (NumberParseException $e) {
2237
            $this->fail("Should not have thrown an exception: " . $e->getMessage());
2238
        }
2239
        $number->clear();
2240
        try {
2241
            $phoneNumber = "(1 610) 619 446";
2242
            $numberToFill = "";
2243
            $this->assertEquals(
2244
                0,
2245
                $this->phoneUtil->maybeExtractCountryCode($phoneNumber, $metadata, $numberToFill, false, $number),
2246
                "Should not have extracted a country calling code - invalid number after extraction of uncertain country calling code."
2247
            );
2248
            $this->assertFalse($number->hasCountryCodeSource(), "Should not contain CountryCodeSource");
2249
        } catch (NumberParseException $e) {
2250
            $this->fail("Should not have thrown an exception: " . $e->getMessage());
2251
        }
2252
        $number->clear();
2253
        try {
2254
            $phoneNumber = "(1 610) 619";
2255
            $numberToFill = "";
2256
            $this->assertEquals(
2257
                0,
2258
                $this->phoneUtil->maybeExtractCountryCode($phoneNumber, $metadata, $numberToFill, true, $number),
2259
                "Should not have extracted a country calling code - too short number both before and after extraction of uncertain country calling code."
2260
            );
2261
            $this->assertEquals(
2262
                CountryCodeSource::FROM_DEFAULT_COUNTRY,
2263
                $number->getCountryCodeSource(),
2264
                "Did not figure out CountryCodeSource correctly"
2265
            );
2266
        } catch (NumberParseException $e) {
2267
            $this->fail("Should not have thrown an exception: " . $e->getMessage());
2268
        }
2269
    }
2270
2271
    public function testParseNationalNumber()
2272
    {
2273
        // National prefix attached.
2274
        $this->assertEquals(self::$nzNumber, $this->phoneUtil->parse("033316005", RegionCode::NZ));
2275
        $this->assertEquals(self::$nzNumber, $this->phoneUtil->parse("33316005", RegionCode::NZ));
2276
        // National prefix attached and some formatting present.
2277
        $this->assertEquals(self::$nzNumber, $this->phoneUtil->parse("03-331 6005", RegionCode::NZ));
2278
        $this->assertEquals(self::$nzNumber, $this->phoneUtil->parse("03 331 6005", RegionCode::NZ));
2279
2280
        // Test parsing RFC3966 format with a phone context.
2281
        $this->assertEquals(
2282
            self::$nzNumber,
2283
            $this->phoneUtil->parse("tel:03-331-6005;phone-context=+64", RegionCode::NZ)
2284
        );
2285
        $this->assertEquals(
2286
            self::$nzNumber,
2287
            $this->phoneUtil->parse("tel:331-6005;phone-context=+64-3", RegionCode::NZ)
2288
        );
2289
        $this->assertEquals(
2290
            self::$nzNumber,
2291
            $this->phoneUtil->parse("tel:331-6005;phone-context=+64-3", RegionCode::US)
2292
        );
2293
        $this->assertEquals(
2294
            self::$nzNumber,
2295
            $this->phoneUtil->parse("My number is tel:03-331-6005;phone-context=+64", RegionCode::NZ)
2296
        );
2297
        // Test parsing RFC3966 format with optional user-defined parameters. The parameters will appear
2298
        // after the context if present.
2299
        $this->assertEquals(
2300
            self::$nzNumber,
2301
            $this->phoneUtil->parse("tel:03-331-6005;phone-context=+64;a=%A1", RegionCode::NZ)
2302
        );
2303
        // Test parsing RFC3966 with an ISDN subaddress.
2304
        $this->assertEquals(
2305
            self::$nzNumber,
2306
            $this->phoneUtil->parse("tel:03-331-6005;isub=12345;phone-context=+64", RegionCode::NZ)
2307
        );
2308
        $this->assertEquals(self::$nzNumber, $this->phoneUtil->parse("tel:+64-3-331-6005;isub=12345", RegionCode::NZ));
2309
2310
        // Test parsing RFC3966 with "tel:" missing
2311
        $this->assertEquals(self::$nzNumber, $this->phoneUtil->parse("03-331-6005;phone-context=+64", RegionCode::NZ));
2312
2313
        // Testing international prefixes.
2314
        // Should strip country calling code.
2315
        $this->assertEquals(self::$nzNumber, $this->phoneUtil->parse("0064 3 331 6005", RegionCode::NZ));
2316
        // Try again, but this time we have an international number with Region Code US. It should
2317
        // recognise the country calling code and parse accordingly.
2318
        $this->assertEquals(self::$nzNumber, $this->phoneUtil->parse("01164 3 331 6005", RegionCode::US));
2319
        $this->assertEquals(self::$nzNumber, $this->phoneUtil->parse("+64 3 331 6005", RegionCode::US));
2320
        // We should ignore the leading plus here, since it is not followed by a valid country code but
2321
        // instead is followed by the IDD for the US.
2322
        $this->assertEquals(self::$nzNumber, $this->phoneUtil->parse("+01164 3 331 6005", RegionCode::US));
2323
        $this->assertEquals(self::$nzNumber, $this->phoneUtil->parse("+0064 3 331 6005", RegionCode::NZ));
2324
        $this->assertEquals(self::$nzNumber, $this->phoneUtil->parse("+ 00 64 3 331 6005", RegionCode::NZ));
2325
2326
        $this->assertEquals(
2327
            self::$usLocalNumber,
2328
            $this->phoneUtil->parse("tel:253-0000;phone-context=www.google.com", RegionCode::US)
2329
        );
2330
        $this->assertEquals(
2331
            self::$usLocalNumber,
2332
            $this->phoneUtil->parse("tel:253-0000;isub=12345;phone-context=www.google.com", RegionCode::US)
2333
        );
2334
        // This is invalid because no "+" sign is present as part of phone-context. The phone context
2335
        // is simply ignored in this case just as if it contains a domain.
2336
        $this->assertEquals(
2337
            self::$usLocalNumber,
2338
            $this->phoneUtil->parse("tel:2530000;isub=12345;phone-context=1-650", RegionCode::US)
2339
        );
2340
        $this->assertEquals(
2341
            self::$usLocalNumber,
2342
            $this->phoneUtil->parse("tel:2530000;isub=12345;phone-context=1234.com", RegionCode::US)
2343
        );
2344
2345
        $nzNumber = new PhoneNumber();
2346
        $nzNumber->setCountryCode(64)->setNationalNumber(64123456);
2347
        $this->assertEquals($nzNumber, $this->phoneUtil->parse("64(0)64123456", RegionCode::NZ));
2348
        // Check that using a "/" is fine in a phone number.
2349
        $this->assertEquals(self::$deNumber, $this->phoneUtil->parse("301/23456", RegionCode::DE));
2350
2351
        $usNumber = new PhoneNumber();
2352
        // Check it doesn't use the '1' as a country calling code when parsing if the phone number was
2353
        // already possible.
2354
        $usNumber->setCountryCode(1)->setNationalNumber(1234567890);
2355
        $this->assertEquals($usNumber, $this->phoneUtil->parse("123-456-7890", RegionCode::US));
2356
2357
        // Test star numbers. Although this is not strictly valid, we would like to make sure we can
2358
        // parse the output we produce when formatting the number.
2359
        $this->assertEquals(self::$jpStarNumber, $this->phoneUtil->parse("+81 *2345", RegionCode::JP));
2360
2361
        $shortNumber = new PhoneNumber();
2362
        $shortNumber->setCountryCode(64)->setNationalNumber(12);
2363
        $this->assertEquals($shortNumber, $this->phoneUtil->parse("12", RegionCode::NZ));
2364
    }
2365
2366
    public function testParseNumberWithAlphaCharacters()
2367
    {
2368
        // Test case with alpha characters.
2369
        $tollFreeNumber = new PhoneNumber();
2370
        $tollFreeNumber->setCountryCode(64)->setNationalNumber(800332005);
2371
        $this->assertEquals($tollFreeNumber, $this->phoneUtil->parse("0800 DDA 005", RegionCode::NZ));
2372
2373
        $premiumNumber = new PhoneNumber();
2374
        $premiumNumber->setCountryCode(64)->setNationalNumber(9003326005);
2375
        $this->assertEquals($premiumNumber, $this->phoneUtil->parse("0900 DDA 6005", RegionCode::NZ));
2376
2377
        // Not enough alpha characters for them to be considered intentional, so they are stripped.
2378
        $this->assertEquals($premiumNumber, $this->phoneUtil->parse("0900 332 6005a", RegionCode::NZ));
2379
        $this->assertEquals($premiumNumber, $this->phoneUtil->parse("0900 332 600a5", RegionCode::NZ));
2380
        $this->assertEquals($premiumNumber, $this->phoneUtil->parse("0900 332 600A5", RegionCode::NZ));
2381
        $this->assertEquals($premiumNumber, $this->phoneUtil->parse("0900 a332 600A5", RegionCode::NZ));
2382
    }
2383
2384
    public function testParseMaliciousInput()
2385
    {
2386
        // Lots of leading + signs before the possible number.
2387
        $maliciousNumber = str_repeat("+", 6000);
2388
        $maliciousNumber .= "12222-33-244 extensioB 343+";
2389
2390
        try {
2391
            $this->phoneUtil->parse($maliciousNumber, RegionCode::US);
2392
            $this->fail("This should not parse without throwing an exception " . $maliciousNumber);
2393
        } catch (NumberParseException $e) {
2394
            // Expected this exception.
2395
            $this->assertEquals(
2396
                NumberParseException::TOO_LONG,
2397
                $e->getErrorType(),
2398
                "Wrong error type stored in exception."
2399
            );
2400
        }
2401
2402
        $maliciousNumberWithAlmostExt = str_repeat("200", 350);
2403
        $maliciousNumberWithAlmostExt .= " extensiOB 345";
2404
        try {
2405
            $this->phoneUtil->parse($maliciousNumberWithAlmostExt, RegionCode::US);
2406
            $this->fail("This should not parse without throwing an exception " . $maliciousNumberWithAlmostExt);
2407
        } catch (NumberParseException $e) {
2408
            // Expected this exception.
2409
            $this->assertEquals(
2410
                NumberParseException::TOO_LONG,
2411
                $e->getErrorType(),
2412
                "Wrong error type stored in exception."
2413
            );
2414
        }
2415
    }
2416
2417
    public function testParseWithInternationalPrefixes()
2418
    {
2419
        $this->assertEquals(self::$usNumber, $this->phoneUtil->parse("+1 (650) 253-0000", RegionCode::NZ));
2420
        $this->assertEquals(self::$internationalTollFree, $this->phoneUtil->parse("011 800 1234 5678", RegionCode::US));
2421
        $this->assertEquals(self::$usNumber, $this->phoneUtil->parse("1-650-253-0000", RegionCode::US));
2422
        // Calling the US number from Singapore by using different service providers
2423
        // 1st test: calling using SingTel IDD service (IDD is 001)
2424
        $this->assertEquals(self::$usNumber, $this->phoneUtil->parse("0011-650-253-0000", RegionCode::SG));
2425
        // 2nd test: calling using StarHub IDD service (IDD is 008)
2426
        $this->assertEquals(self::$usNumber, $this->phoneUtil->parse("0081-650-253-0000", RegionCode::SG));
2427
        // 3rd test: calling using SingTel V019 service (IDD is 019)
2428
        $this->assertEquals(self::$usNumber, $this->phoneUtil->parse("0191-650-253-0000", RegionCode::SG));
2429
        // Calling the US number from Poland
2430
        $this->assertEquals(self::$usNumber, $this->phoneUtil->parse("0~01-650-253-0000", RegionCode::PL));
2431
        // Using "++" at the start.
2432
        $this->assertEquals(self::$usNumber, $this->phoneUtil->parse("++1 (650) 253-0000", RegionCode::PL));
2433
    }
2434
2435
    public function testParseNonAscii()
2436
    {
2437
        // Using a full-width plus sign.
2438
        $this->assertEquals(
2439
            self::$usNumber,
2440
            $this->phoneUtil->parse(pack("H*", 'efbc8b') . "1 (650) 253-0000", RegionCode::SG)
2441
        );
2442
        // Using a soft hyphen U+00AD.
2443
        $this->assertEquals(
2444
            self::$usNumber,
2445
            $this->phoneUtil->parse("1 (650) 253" . pack("H*", 'c2ad') . "-0000", RegionCode::US)
2446
        );
2447
        // The whole number, including punctuation, is here represented in full-width form.
2448
        $this->assertEquals(
2449
            self::$usNumber,
2450
            $this->phoneUtil->parse(
2451
                pack("H*", 'efbc8b') . pack("H*", 'efbc91') . pack("H*", 'e38080') .
2452
                pack("H*", 'efbc88') . pack("H*", 'efbc96') . pack("H*", 'efbc95') . pack("H*", 'efbc90') . pack(
2453
                    "H*",
2454
                    'efbc89'
2455
                ) .
2456
                pack("H*", 'e38080') . pack("H*", 'efbc92') . pack("H*", 'efbc95') . pack("H*", 'efbc93') . pack(
2457
                    "H*",
2458
                    'efbc8d'
2459
                ) .
2460
                pack("H*", 'efbc90') . pack("H*", 'efbc90') . pack("H*", 'efbc90') . pack("H*", 'efbc90'),
2461
                RegionCode::SG
2462
            )
2463
        );
2464
        // Using U+30FC dash instead.
2465
        $this->assertEquals(
2466
            self::$usNumber,
2467
            $this->phoneUtil->parse(
2468
                pack("H*", 'efbc8b') . pack("H*", 'efbc91') . pack("H*", 'e38080') .
2469
                pack("H*", 'efbc88') . pack("H*", 'efbc96') . pack("H*", 'efbc95') . pack("H*", 'efbc90') . pack(
2470
                    "H*",
2471
                    'efbc89'
2472
                ) .
2473
                pack("H*", 'e38080') . pack("H*", 'efbc92') . pack("H*", 'efbc95') . pack("H*", 'efbc93') . pack(
2474
                    "H*",
2475
                    'e383bc'
2476
                ) .
2477
                pack("H*", 'efbc90') . pack("H*", 'efbc90') . pack("H*", 'efbc90') . pack("H*", 'efbc90'),
2478
                RegionCode::SG
2479
            )
2480
        );
2481
        // Using a very strange decimal digit range (Mongolian digits).
2482
        $this->assertEquals(
2483
            self::$usNumber,
2484
            $this->phoneUtil->parse(
2485
                pack('H*', 'e1a091') . " "
2486
                . pack('H*', 'e1a096') . pack('H*', 'e1a095') . pack('H*', 'e1a090') . " "
2487
                . pack('H*', 'e1a092') . pack('H*', 'e1a095') . pack('H*', 'e1a093') . " "
2488
                . pack('H*', 'e1a090') . pack('H*', 'e1a090') . pack('H*', 'e1a090') . pack('H*', 'e1a090'),
2489
                RegionCode::US
2490
            )
2491
        );
2492
    }
2493
2494
    public function testParseWithLeadingZero()
2495
    {
2496
        $this->assertEquals(self::$itNumber, $this->phoneUtil->parse("+39 02-36618 300", RegionCode::NZ));
2497
        $this->assertEquals(self::$itNumber, $this->phoneUtil->parse("02-36618 300", RegionCode::IT));
2498
2499
        $this->assertEquals(self::$itMobile, $this->phoneUtil->parse("345 678 901", RegionCode::IT));
2500
    }
2501
2502
    public function testParseNationalNumberArgentina()
2503
    {
2504
        // Test parsing mobile numbers of Argentina.
2505
        $arNumber = new PhoneNumber();
2506
        $arNumber->setCountryCode(54)->setNationalNumber(93435551212);
2507
        $this->assertEquals($arNumber, $this->phoneUtil->parse("+54 9 343 555 1212", RegionCode::AR));
2508
        $this->assertEquals($arNumber, $this->phoneUtil->parse("0343 15 555 1212", RegionCode::AR));
2509
2510
        $arNumber->clear();
2511
        $arNumber->setCountryCode(54)->setNationalNumber(93715654320);
2512
        $this->assertEquals($arNumber, $this->phoneUtil->parse("+54 9 3715 65 4320", RegionCode::AR));
2513
        $this->assertEquals($arNumber, $this->phoneUtil->parse("03715 15 65 4320", RegionCode::AR));
2514
        $this->assertEquals(self::$arMobile, $this->phoneUtil->parse("911 876 54321", RegionCode::AR));
2515
2516
        // Test parsing fixed-line numbers of Argentina.
2517
        $this->assertEquals(self::$arNumber, $this->phoneUtil->parse("+54 11 8765 4321", RegionCode::AR));
2518
        $this->assertEquals(self::$arNumber, $this->phoneUtil->parse("011 8765 4321", RegionCode::AR));
2519
2520
        $arNumber->clear();
2521
        $arNumber->setCountryCode(54)->setNationalNumber(3715654321);
2522
        $this->assertEquals($arNumber, $this->phoneUtil->parse("+54 3715 65 4321", RegionCode::AR));
2523
        $this->assertEquals($arNumber, $this->phoneUtil->parse("03715 65 4321", RegionCode::AR));
2524
2525
        $arNumber->clear();
2526
        $arNumber->setCountryCode(54)->setNationalNumber(2312340000);
2527
        $this->assertEquals($arNumber, $this->phoneUtil->parse("+54 23 1234 0000", RegionCode::AR));
2528
        $this->assertEquals($arNumber, $this->phoneUtil->parse("023 1234 0000", RegionCode::AR));
2529
    }
2530
2531
    public function testParseWithXInNumber()
2532
    {
2533
        // Test that having an 'x' in the phone number at the start is ok and that it just gets removed.
2534
        $this->assertEquals(self::$arNumber, $this->phoneUtil->parse("01187654321", RegionCode::AR));
2535
        $this->assertEquals(self::$arNumber, $this->phoneUtil->parse("(0) 1187654321", RegionCode::AR));
2536
        $this->assertEquals(self::$arNumber, $this->phoneUtil->parse("0 1187654321", RegionCode::AR));
2537
        $this->assertEquals(self::$arNumber, $this->phoneUtil->parse("(0xx) 1187654321", RegionCode::AR));
2538
2539
        $arFromUs = new PhoneNumber();
2540
        $arFromUs->setCountryCode(54)->setNationalNumber(81429712);
2541
        // This test is intentionally constructed such that the number of digit after xx is larger than
2542
        // 7, so that the number won't be mistakenly treated as an extension, as we allow extensions up
2543
        // to 7 digits. This assumption is okay for now as all the countries where a carrier selection
2544
        // code is written in the form of xx have a national significant number of length larger than 7.
2545
        $this->assertEquals($arFromUs, $this->phoneUtil->parse("011xx5481429712", RegionCode::US));
2546
    }
2547
2548
    public function testParseNumbersMexico()
2549
    {
2550
        // Test parsing fixed-line numbers of Mexico.
2551
        $mxNumber = new PhoneNumber();
2552
        $mxNumber->setCountryCode(52)->setNationalNumber(4499780001);
2553
        $this->assertEquals($mxNumber, $this->phoneUtil->parse("+52 (449)978-0001", RegionCode::MX));
2554
        $this->assertEquals($mxNumber, $this->phoneUtil->parse("01 (449)978-0001", RegionCode::MX));
2555
        $this->assertEquals($mxNumber, $this->phoneUtil->parse("(449)978-0001", RegionCode::MX));
2556
2557
        // Test parsing mobile numbers of Mexico.
2558
        $mxNumber->clear();
2559
        $mxNumber->setCountryCode(52)->setNationalNumber(13312345678);
2560
        $this->assertEquals($mxNumber, $this->phoneUtil->parse("+52 1 33 1234-5678", RegionCode::MX));
2561
        $this->assertEquals($mxNumber, $this->phoneUtil->parse("044 (33) 1234-5678", RegionCode::MX));
2562
        $this->assertEquals($mxNumber, $this->phoneUtil->parse("045 33 1234-5678", RegionCode::MX));
2563
    }
2564
2565
    public function testFailedParseOnInvalidNumbers()
2566
    {
2567
        try {
2568
            $sentencePhoneNumber = "This is not a phone number";
2569
            $this->phoneUtil->parse($sentencePhoneNumber, RegionCode::NZ);
2570
            $this->fail("This should not parse without throwing an exception " . $sentencePhoneNumber);
2571
        } catch (NumberParseException $e) {
2572
            // Expected this exception.
2573
            $this->assertEquals(
2574
                NumberParseException::NOT_A_NUMBER,
2575
                $e->getErrorType(),
2576
                "Wrong error type stored in exception."
2577
            );
2578
        }
2579
2580
        try {
2581
            $sentencePhoneNumber = "1 Still not a number";
2582
            $this->phoneUtil->parse($sentencePhoneNumber, RegionCode::NZ);
2583
            $this->fail("This should not parse without throwing an exception " . $sentencePhoneNumber);
2584
        } catch (NumberParseException $e) {
2585
            // Expected this exception.
2586
            $this->assertEquals(
2587
                NumberParseException::NOT_A_NUMBER,
2588
                $e->getErrorType(),
2589
                "Wrong error type stored in exception."
2590
            );
2591
        }
2592
2593
        try {
2594
            $sentencePhoneNumber = "1 MICROSOFT";
2595
            $this->phoneUtil->parse($sentencePhoneNumber, RegionCode::NZ);
2596
            $this->fail("This should not parse without throwing an exception " . $sentencePhoneNumber);
2597
        } catch (NumberParseException $e) {
2598
            // Expected this exception.
2599
            $this->assertEquals(
2600
                NumberParseException::NOT_A_NUMBER,
2601
                $e->getErrorType(),
2602
                "Wrong error type stored in exception."
2603
            );
2604
        }
2605
2606
        try {
2607
            $sentencePhoneNumber = "12 MICROSOFT";
2608
            $this->phoneUtil->parse($sentencePhoneNumber, RegionCode::NZ);
2609
            $this->fail("This should not parse without throwing an exception " . $sentencePhoneNumber);
2610
        } catch (NumberParseException $e) {
2611
            // Expected this exception.
2612
            $this->assertEquals(
2613
                NumberParseException::NOT_A_NUMBER,
2614
                $e->getErrorType(),
2615
                "Wrong error type stored in exception."
2616
            );
2617
        }
2618
2619
        try {
2620
            $tooLongPhoneNumber = "01495 72553301873 810104";
2621
            $this->phoneUtil->parse($tooLongPhoneNumber, RegionCode::GB);
2622
            $this->fail("This should not parse without throwing an exception " . $tooLongPhoneNumber);
2623
        } catch (NumberParseException $e) {
2624
            // Expected this exception.
2625
            $this->assertEquals(
2626
                NumberParseException::TOO_LONG,
2627
                $e->getErrorType(),
2628
                "Wrong error type stored in exception."
2629
            );
2630
        }
2631
2632
        try {
2633
            $plusMinusPhoneNumber = "+---";
2634
            $this->phoneUtil->parse($plusMinusPhoneNumber, RegionCode::DE);
2635
            $this->fail("This should not parse without throwing an exception " . $plusMinusPhoneNumber);
2636
        } catch (NumberParseException $e) {
2637
            // Expected this exception.
2638
            $this->assertEquals(
2639
                NumberParseException::NOT_A_NUMBER,
2640
                $e->getErrorType(),
2641
                "Wrong error type stored in exception."
2642
            );
2643
        }
2644
2645
        try {
2646
            $plusStar = "+***";
2647
            $this->phoneUtil->parse($plusStar, RegionCode::DE);
2648
            $this->fail("This should not parse without throwing an exception " . $plusStar);
2649
        } catch (NumberParseException $e) {
2650
            // Expected this exception.
2651
            $this->assertEquals(
2652
                NumberParseException::NOT_A_NUMBER,
2653
                $e->getErrorType(),
2654
                "Wrong error type stored in exception."
2655
            );
2656
        }
2657
2658
        try {
2659
            $plusStarPhoneNumber = "+*******91";
2660
            $this->phoneUtil->parse($plusStarPhoneNumber, RegionCode::DE);
2661
            $this->fail("This should not parse without throwing an exception " . $plusStarPhoneNumber);
2662
        } catch (NumberParseException $e) {
2663
            // Expected this exception.
2664
            $this->assertEquals(
2665
                NumberParseException::NOT_A_NUMBER,
2666
                $e->getErrorType(),
2667
                "Wrong error type stored in exception."
2668
            );
2669
        }
2670
2671
        try {
2672
            $tooShortPhoneNumber = "+49 0";
2673
            $this->phoneUtil->parse($tooShortPhoneNumber, RegionCode::DE);
2674
            $this->fail("This should not parse without throwing an exception " . $tooShortPhoneNumber);
2675
        } catch (NumberParseException $e) {
2676
            // Expected this exception.
2677
            $this->assertEquals(
2678
                NumberParseException::TOO_SHORT_NSN,
2679
                $e->getErrorType(),
2680
                "Wrong error type stored in exception."
2681
            );
2682
        }
2683
2684
        try {
2685
            $invalidCountryCode = "+210 3456 56789";
2686
            $this->phoneUtil->parse($invalidCountryCode, RegionCode::NZ);
2687
            $this->fail("This is not a recognised region code: should fail: " . $invalidCountryCode);
2688
        } catch (NumberParseException $e) {
2689
            // Expected this exception.
2690
            $this->assertEquals(
2691
                NumberParseException::INVALID_COUNTRY_CODE,
2692
                $e->getErrorType(),
2693
                "Wrong error type stored in exception."
2694
            );
2695
        }
2696
2697
        try {
2698
            $plusAndIddAndInvalidCountryCode = "+ 00 210 3 331 6005";
2699
            $this->phoneUtil->parse($plusAndIddAndInvalidCountryCode, RegionCode::NZ);
2700
            $this->fail("This should not parse without throwing an exception " . $plusAndIddAndInvalidCountryCode);
2701
        } catch (NumberParseException $e) {
2702
            // Expected this exception. 00 is a correct IDD, but 210 is not a valid country code.
2703
            $this->assertEquals(
2704
                NumberParseException::INVALID_COUNTRY_CODE,
2705
                $e->getErrorType(),
2706
                "Wrong error type stored in exception."
2707
            );
2708
        }
2709
2710
        try {
2711
            $someNumber = "123 456 7890";
2712
            $this->phoneUtil->parse($someNumber, RegionCode::ZZ);
2713
            $this->fail("'Unknown' region code not allowed: should fail.");
2714
        } catch (NumberParseException $e) {
2715
            // Expected this exception.
2716
            $this->assertEquals(
2717
                NumberParseException::INVALID_COUNTRY_CODE,
2718
                $e->getErrorType(),
2719
                "Wrong error type stored in exception."
2720
            );
2721
        }
2722
2723
        try {
2724
            $someNumber = "123 456 7890";
2725
            $this->phoneUtil->parse($someNumber, RegionCode::CS);
2726
            $this->fail("Deprecated region code not allowed: should fail.");
2727
        } catch (NumberParseException $e) {
2728
            // Expected this exception.
2729
            $this->assertEquals(
2730
                NumberParseException::INVALID_COUNTRY_CODE,
2731
                $e->getErrorType(),
2732
                "Wrong error type stored in exception."
2733
            );
2734
        }
2735
2736
        try {
2737
            $someNumber = "123 456 7890";
2738
            $this->phoneUtil->parse($someNumber, null);
2739
            $this->fail("Null region code not allowed: should fail.");
2740
        } catch (NumberParseException $e) {
2741
            // Expected this exception.
2742
            $this->assertEquals(
2743
                NumberParseException::INVALID_COUNTRY_CODE,
2744
                $e->getErrorType(),
2745
                "Wrong error type stored in exception."
2746
            );
2747
        }
2748
2749
        try {
2750
            $someNumber = "0044------";
2751
            $this->phoneUtil->parse($someNumber, RegionCode::GB);
2752
            $this->fail("No number provided, only region code: should fail");
2753
        } catch (NumberParseException $e) {
2754
            // Expected this exception.
2755
            $this->assertEquals(
2756
                NumberParseException::TOO_SHORT_AFTER_IDD,
2757
                $e->getErrorType(),
2758
                "Wrong error type stored in exception."
2759
            );
2760
        }
2761
2762
        try {
2763
            $someNumber = "0044";
2764
            $this->phoneUtil->parse($someNumber, RegionCode::GB);
2765
            $this->fail("No number provided, only region code: should fail");
2766
        } catch (NumberParseException $e) {
2767
            // Expected this exception.
2768
            $this->assertEquals(
2769
                NumberParseException::TOO_SHORT_AFTER_IDD,
2770
                $e->getErrorType(),
2771
                "Wrong error type stored in exception."
2772
            );
2773
        }
2774
2775
        try {
2776
            $someNumber = "011";
2777
            $this->phoneUtil->parse($someNumber, RegionCode::US);
2778
            $this->fail("Only IDD provided - should fail.");
2779
        } catch (NumberParseException $e) {
2780
            // Expected this exception.
2781
            $this->assertEquals(
2782
                NumberParseException::TOO_SHORT_AFTER_IDD,
2783
                $e->getErrorType(),
2784
                "Wrong error type stored in exception."
2785
            );
2786
        }
2787
2788
        try {
2789
            $someNumber = "0119";
2790
            $this->phoneUtil->parse($someNumber, RegionCode::US);
2791
            $this->fail("Only IDD provided and then 9 - should fail.");
2792
        } catch (NumberParseException $e) {
2793
            // Expected this exception.
2794
            $this->assertEquals(
2795
                NumberParseException::TOO_SHORT_AFTER_IDD,
2796
                $e->getErrorType(),
2797
                "Wrong error type stored in exception."
2798
            );
2799
        }
2800
2801
        try {
2802
            $emptyNumber = "";
2803
            // Invalid region.
2804
            $this->phoneUtil->parse($emptyNumber, RegionCode::ZZ);
2805
            $this->fail("Empty string - should fail.");
2806
        } catch (NumberParseException $e) {
2807
            // Expected this exception.
2808
            $this->assertEquals(
2809
                NumberParseException::NOT_A_NUMBER,
2810
                $e->getErrorType(),
2811
                "Wrong error type stored in exception."
2812
            );
2813
        }
2814
2815
        try {
2816
            $nullNumber = null;
2817
            // Invalid region.
2818
            $this->phoneUtil->parse($nullNumber, RegionCode::ZZ);
2819
            $this->fail("Null string - should fail.");
2820
        } catch (NumberParseException $e) {
2821
            // Expected this exception.
2822
            $this->assertEquals(
2823
                NumberParseException::NOT_A_NUMBER,
2824
                $e->getErrorType(),
2825
                "Wrong error type stored in exception."
2826
            );
2827
        }
2828
2829
        try {
2830
            $nullNumber = null;
2831
            $this->phoneUtil->parse($nullNumber, RegionCode::US);
2832
            $this->fail("Null string - should fail.");
2833
        } catch (NumberParseException $e) {
2834
            // Expected this exception.
2835
            $this->assertEquals(
2836
                NumberParseException::NOT_A_NUMBER,
2837
                $e->getErrorType(),
2838
                "Wrong error type stored in exception."
2839
            );
2840
        }
2841
2842
        try {
2843
            $domainRfcPhoneContext = "tel:555-1234;phone-context=www.google.com";
2844
            $this->phoneUtil->parse($domainRfcPhoneContext, RegionCode::ZZ);
2845
            $this->fail("'Unknown' region code not allowed: should fail.");
2846
        } catch (NumberParseException $e) {
2847
            // Expected this exception.
2848
            $this->assertEquals(
2849
                NumberParseException::INVALID_COUNTRY_CODE,
2850
                $e->getErrorType(),
2851
                "Wrong error type stored in exception."
2852
            );
2853
        }
2854
2855
        try {
2856
            // This is invalid because no "+" sign is present as part of phone-context. This should not
2857
            // succeed in being parsed.
2858
            $invalidRfcPhoneContext = "tel:555-1234;phone-context=1-331";
2859
            $this->phoneUtil->parse($invalidRfcPhoneContext, RegionCode::ZZ);
2860
            $this->fail("'Unknown' region code not allowed: should fail.");
2861
        } catch (NumberParseException $e) {
2862
            // Expected this exception.
2863
            $this->assertEquals(
2864
                NumberParseException::INVALID_COUNTRY_CODE,
2865
                $e->getErrorType(),
2866
                "Wrong error type stored in exception."
2867
            );
2868
        }
2869
    }
2870
2871
    public function testParseNumbersWithPlusWithNoRegion()
2872
    {
2873
        // RegionCode.ZZ is allowed only if the number starts with a '+' - then the country calling code
2874
        // can be calculated.
2875
        $this->assertEquals(self::$nzNumber, $this->phoneUtil->parse("+64 3 331 6005", RegionCode::ZZ));
2876
        // Test with full-width plus.
2877
        $this->assertEquals(self::$nzNumber, $this->phoneUtil->parse("+64 3 331 6005", RegionCode::ZZ));
2878
        // Test with normal plus but leading characters that need to be stripped.
2879
        $this->assertEquals(self::$nzNumber, $this->phoneUtil->parse("Tel: +64 3 331 6005", RegionCode::ZZ));
2880
        $this->assertEquals(self::$nzNumber, $this->phoneUtil->parse("+64 3 331 6005", null));
2881
        $this->assertEquals(self::$internationalTollFree, $this->phoneUtil->parse("+800 1234 5678", null));
2882
        $this->assertEquals(self::$universalPremiumRate, $this->phoneUtil->parse("+979 123 456 789", null));
2883
2884
        // Test parsing RFC3966 format with a phone context.
2885
        $this->assertEquals(
2886
            self::$nzNumber,
2887
            $this->phoneUtil->parse("tel:03-331-6005;phone-context=+64", RegionCode::ZZ)
2888
        );
2889
        $this->assertEquals(
2890
            self::$nzNumber,
2891
            $this->phoneUtil->parse("  tel:03-331-6005;phone-context=+64", RegionCode::ZZ)
2892
        );
2893
        $this->assertEquals(
2894
            self::$nzNumber,
2895
            $this->phoneUtil->parse("tel:03-331-6005;isub=12345;phone-context=+64", RegionCode::ZZ)
2896
        );
2897
2898
        $nzNumberWithRawInput = new PhoneNumber();
2899
        $nzNumberWithRawInput->mergeFrom(self::$nzNumber);
2900
        $nzNumberWithRawInput->setRawInput("+64 3 331 6005");
2901
        $nzNumberWithRawInput->setCountryCodeSource(CountryCodeSource::FROM_NUMBER_WITH_PLUS_SIGN);
2902
        $this->assertEquals(
2903
            $nzNumberWithRawInput,
2904
            $this->phoneUtil->parseAndKeepRawInput("+64 3 331 6005", RegionCode::ZZ)
2905
        );
2906
2907
        // Null is also allowed for the region code in these cases.
2908
        $this->assertEquals($nzNumberWithRawInput, $this->phoneUtil->parseAndKeepRawInput("+64 3 331 6005", null));
2909
    }
2910
2911
    public function testParseNumberTooShortIfNationalPrefixStripped()
2912
    {
2913
        // Test that a number whose first digits happen to coincide with the national prefix does not
2914
        // get them stripped if doing so would result in a number too short to be a possible (regular
2915
        // length) phone number for that region.
2916
        $byNumber = new PhoneNumber();
2917
        $byNumber->setCountryCode(375)->setNationalNumber(8123);
2918
        $this->assertEquals($byNumber, $this->phoneUtil->parse("8123", RegionCode::BY));
2919
        $byNumber->setNationalNumber(81234);
2920
        $this->assertEquals($byNumber, $this->phoneUtil->parse("81234", RegionCode::BY));
2921
2922
        // The prefix doesn't get stripped, since the input is a viable 6-digit number, whereas the
2923
        // result of stripping is only 5 digits.
2924
        $byNumber->setNationalNumber(812345);
2925
        $this->assertEquals($byNumber, $this->phoneUtil->parse("812345", RegionCode::BY));
2926
2927
        // The prefix gets stripped, since only 6-digit numbers are possible.
2928
        $byNumber->setNationalNumber(123456);
2929
        $this->assertEquals($byNumber, $this->phoneUtil->parse("8123456", RegionCode::BY));
2930
    }
2931
2932
    public function testParseExtensions()
2933
    {
2934
        $nzNumber = new PhoneNumber();
2935
        $nzNumber->setCountryCode(64)->setNationalNumber(33316005)->setExtension("3456");
2936
        $this->assertEquals($nzNumber, $this->phoneUtil->parse("03 331 6005 ext 3456", RegionCode::NZ));
2937
        $this->assertEquals($nzNumber, $this->phoneUtil->parse("03-3316005x3456", RegionCode::NZ));
2938
        $this->assertEquals($nzNumber, $this->phoneUtil->parse("03-3316005 int.3456", RegionCode::NZ));
2939
        $this->assertEquals($nzNumber, $this->phoneUtil->parse("03 3316005 #3456", RegionCode::NZ));
2940
        // Test the following do not extract extensions:
2941
        $this->assertEquals(self::$alphaNumericNumber, $this->phoneUtil->parse("1800 six-flags", RegionCode::US));
2942
        $this->assertEquals(self::$alphaNumericNumber, $this->phoneUtil->parse("1800 SIX FLAGS", RegionCode::US));
2943
        $this->assertEquals(self::$alphaNumericNumber, $this->phoneUtil->parse("0~0 1800 7493 5247", RegionCode::PL));
2944
        $this->assertEquals(self::$alphaNumericNumber, $this->phoneUtil->parse("(1800) 7493.5247", RegionCode::US));
2945
        // Check that the last instance of an extension token is matched.
2946
        $extnNumber = new PhoneNumber();
2947
        $extnNumber->mergeFrom(self::$alphaNumericNumber)->setExtension("1234");
2948
        $this->assertEquals($extnNumber, $this->phoneUtil->parse("0~0 1800 7493 5247 ~1234", RegionCode::PL));
2949
        // Verifying bug-fix where the last digit of a number was previously omitted if it was a 0 when
2950
        // extracting the extension. Also verifying a few different cases of extensions.
2951
        $ukNumber = new PhoneNumber();
2952
        $ukNumber->setCountryCode(44)->setNationalNumber(2034567890)->setExtension("456");
2953
        $this->assertEquals($ukNumber, $this->phoneUtil->parse("+44 2034567890x456", RegionCode::NZ));
2954
        $this->assertEquals($ukNumber, $this->phoneUtil->parse("+44 2034567890x456", RegionCode::GB));
2955
        $this->assertEquals($ukNumber, $this->phoneUtil->parse("+44 2034567890 x456", RegionCode::GB));
2956
        $this->assertEquals($ukNumber, $this->phoneUtil->parse("+44 2034567890 X456", RegionCode::GB));
2957
        $this->assertEquals($ukNumber, $this->phoneUtil->parse("+44 2034567890 X 456", RegionCode::GB));
2958
        $this->assertEquals($ukNumber, $this->phoneUtil->parse("+44 2034567890 X  456", RegionCode::GB));
2959
        $this->assertEquals($ukNumber, $this->phoneUtil->parse("+44 2034567890 x 456  ", RegionCode::GB));
2960
        $this->assertEquals($ukNumber, $this->phoneUtil->parse("+44 2034567890  X 456", RegionCode::GB));
2961
        $this->assertEquals($ukNumber, $this->phoneUtil->parse("+44-2034567890;ext=456", RegionCode::GB));
2962
        $this->assertEquals(
2963
            $ukNumber,
2964
            $this->phoneUtil->parse("tel:2034567890;ext=456;phone-context=+44", RegionCode::ZZ)
2965
        );
2966
2967
        // Full-width extension, "extn" only.
2968
        $this->assertEquals($ukNumber, $this->phoneUtil->parse("+442034567890extn456", RegionCode::GB));
2969
        // "xtn" only.
2970
        $this->assertEquals($ukNumber, $this->phoneUtil->parse("+442034567890xtn456", RegionCode::GB));
2971
        // "xt" only.
2972
        $this->assertEquals($ukNumber, $this->phoneUtil->parse("+442034567890xt456", RegionCode::GB));
2973
2974
        $usWithExtension = new PhoneNumber();
2975
        $usWithExtension->setCountryCode(1)->setNationalNumber(8009013355)->setExtension("7246433");
2976
        $this->assertEquals($usWithExtension, $this->phoneUtil->parse("(800) 901-3355 x 7246433", RegionCode::US));
2977
        $this->assertEquals($usWithExtension, $this->phoneUtil->parse("(800) 901-3355 , ext 7246433", RegionCode::US));
2978
        $this->assertEquals($usWithExtension, $this->phoneUtil->parse("(800) 901-3355 ; 7246433", RegionCode::US));
2979
        // To test an extension character without surrounding spaces.
2980
        $this->assertEquals($usWithExtension, $this->phoneUtil->parse("(800) 901-3355;7246433", RegionCode::US));
2981
        $this->assertEquals(
2982
            $usWithExtension,
2983
            $this->phoneUtil->parse("(800) 901-3355 ,extension 7246433", RegionCode::US)
2984
        );
2985
        $this->assertEquals(
2986
            $usWithExtension,
2987
            $this->phoneUtil->parse("(800) 901-3355 ,extensi" . pack("H*", 'c3b3') . "n 7246433", RegionCode::US)
2988
        );
2989
        // Repeat with the small letter o with acute accent created by combining characters.
2990
        $this->assertEquals(
2991
            $usWithExtension,
2992
            $this->phoneUtil->parse("(800) 901-3355 ,extensio" . pack('H*', 'cc81') . "n 7246433", RegionCode::US)
2993
        );
2994
        $this->assertEquals($usWithExtension, $this->phoneUtil->parse("(800) 901-3355 , 7246433", RegionCode::US));
2995
        $this->assertEquals($usWithExtension, $this->phoneUtil->parse("(800) 901-3355 ext: 7246433", RegionCode::US));
2996
2997
        // Test that if a number has two extensions specified, we ignore the second.
2998
        $usWithTwoExtensionsNumber = new PhoneNumber();
2999
        $usWithTwoExtensionsNumber->setCountryCode(1)->setNationalNumber(2121231234)->setExtension("508");
3000
        $this->assertEquals(
3001
            $usWithTwoExtensionsNumber,
3002
            $this->phoneUtil->parse("(212)123-1234 x508/x1234", RegionCode::US)
3003
        );
3004
        $this->assertEquals(
3005
            $usWithTwoExtensionsNumber,
3006
            $this->phoneUtil->parse("(212)123-1234 x508/ x1234", RegionCode::US)
3007
        );
3008
        $this->assertEquals(
3009
            $usWithTwoExtensionsNumber,
3010
            $this->phoneUtil->parse("(212)123-1234 x508\\x1234", RegionCode::US)
3011
        );
3012
3013
        // Test parsing numbers in the form (645) 123-1234-910# works, where the last 3 digits before
3014
        // the # are an extension.
3015
        $usWithExtension->clear();
3016
        $usWithExtension->setCountryCode(1)->setNationalNumber(6451231234)->setExtension("910");
3017
        $this->assertEquals($usWithExtension, $this->phoneUtil->parse("+1 (645) 123 1234-910#", RegionCode::US));
3018
        // Retry with the same number in a slightly different format.
3019
        $this->assertEquals($usWithExtension, $this->phoneUtil->parse("+1 (645) 123 1234 ext. 910#", RegionCode::US));
3020
    }
3021
3022
    public function testParseAndKeepRaw()
3023
    {
3024
        $alphaNumericNumber = new PhoneNumber();
3025
        $alphaNumericNumber->mergeFrom(self::$alphaNumericNumber);
3026
        $alphaNumericNumber->setRawInput("800 six-flags");
3027
        $alphaNumericNumber->setCountryCodeSource(CountryCodeSource::FROM_DEFAULT_COUNTRY);
3028
        $this->assertEquals(
3029
            $alphaNumericNumber,
3030
            $this->phoneUtil->parseAndKeepRawInput("800 six-flags", RegionCode::US)
3031
        );
3032
3033
        $shorterAlphaNumber = new PhoneNumber();
3034
        $shorterAlphaNumber->setCountryCode(1)->setNationalNumber(8007493524);
3035
        $shorterAlphaNumber
3036
            ->setRawInput("1800 six-flag")
3037
            ->setCountryCodeSource(CountryCodeSource::FROM_NUMBER_WITHOUT_PLUS_SIGN);
3038
        $this->assertEquals(
3039
            $shorterAlphaNumber,
3040
            $this->phoneUtil->parseAndKeepRawInput("1800 six-flag", RegionCode::US)
3041
        );
3042
3043
        $shorterAlphaNumber->setRawInput("+1800 six-flag")->setCountryCodeSource(
3044
            CountryCodeSource::FROM_NUMBER_WITH_PLUS_SIGN
3045
        );
3046
        $this->assertEquals(
3047
            $shorterAlphaNumber,
3048
            $this->phoneUtil->parseAndKeepRawInput("+1800 six-flag", RegionCode::NZ)
3049
        );
3050
3051
        $shorterAlphaNumber->setRawInput("001800 six-flag")->setCountryCodeSource(
3052
            CountryCodeSource::FROM_NUMBER_WITH_IDD
3053
        );
3054
        $this->assertEquals(
3055
            $shorterAlphaNumber,
3056
            $this->phoneUtil->parseAndKeepRawInput("001800 six-flag", RegionCode::NZ)
3057
        );
3058
3059
        // Invalid region code supplied.
3060
        try {
3061
            $this->phoneUtil->parseAndKeepRawInput("123 456 7890", RegionCode::CS);
3062
            $this->fail("Deprecated region code not allowed: should fail.");
3063
        } catch (NumberParseException $e) {
3064
            // Expected this exception.
3065
            $this->assertEquals(
3066
                NumberParseException::INVALID_COUNTRY_CODE,
3067
                $e->getErrorType(),
3068
                "Wrong error type stored in exception."
3069
            );
3070
        }
3071
3072
        $koreanNumber = new PhoneNumber();
3073
        $koreanNumber->setCountryCode(82)->setNationalNumber(22123456)->setRawInput(
3074
            "08122123456"
3075
        )->setCountryCodeSource(CountryCodeSource::FROM_DEFAULT_COUNTRY)->setPreferredDomesticCarrierCode("81");
3076
        $this->assertEquals($koreanNumber, $this->phoneUtil->parseAndKeepRawInput("08122123456", RegionCode::KR));
3077
    }
3078
3079
    public function testParseItalianLeadingZeros()
3080
    {
3081
        // Test the number "011".
3082
        $oneZero = new PhoneNumber();
3083
        $oneZero->setCountryCode(61)->setNationalNumber(11)->setItalianLeadingZero(true);
3084
        $this->assertEquals($oneZero, $this->phoneUtil->parse("011", RegionCode::AU));
3085
3086
        // Test the number "001".
3087
        $twoZeros = new PhoneNumber();
3088
        $twoZeros->setCountryCode(61)->setNationalNumber(1)->setItalianLeadingZero(true)->setNumberOfLeadingZeros(2);
3089
        $this->assertEquals($twoZeros, $this->phoneUtil->parse("001", RegionCode::AU));
3090
3091
        // Test the number "000". This number has 2 leading zeros.
3092
        $stillTwoZeros = new PhoneNumber();
3093
        $stillTwoZeros->setCountryCode(61)->setNationalNumber(0)->setItalianLeadingZero(true)->setNumberOfLeadingZeros(
3094
            2
3095
        );
3096
        $this->assertEquals($stillTwoZeros, $this->phoneUtil->parse("000", RegionCode::AU));
3097
3098
        // Test the number "0000". This number has 3 leading zeros.
3099
        $threeZeros = new PhoneNumber();
3100
        $threeZeros->setCountryCode(61)->setNationalNumber(0)->setItalianLeadingZero(true)->setNumberOfLeadingZeros(3);
3101
        $this->assertEquals($threeZeros, $this->phoneUtil->parse("0000", RegionCode::AU));
3102
    }
3103
3104
    public function testCountryWithNoNumberDesc()
3105
    {
3106
        // Andorra is a country where we don't have PhoneNumberDesc info in the metadata.
3107
        $adNumber = new PhoneNumber();
3108
        $adNumber->setCountryCode(376)->setNationalNumber(12345);
3109
3110
        $this->assertEquals("+376 12345", $this->phoneUtil->format($adNumber, PhoneNumberFormat::INTERNATIONAL));
3111
        $this->assertEquals("+37612345", $this->phoneUtil->format($adNumber, PhoneNumberFormat::E164));
3112
        $this->assertEquals("12345", $this->phoneUtil->format($adNumber, PhoneNumberFormat::NATIONAL));
3113
        $this->assertEquals(PhoneNumberType::UNKNOWN, $this->phoneUtil->getNumberType($adNumber));
3114
        $this->assertFalse($this->phoneUtil->isValidNumber($adNumber));
3115
3116
        // Test dialing a US number from within Andorra.
3117
        $this->assertEquals(
3118
            "00 1 650 253 0000",
3119
            $this->phoneUtil->formatOutOfCountryCallingNumber(self::$usNumber, RegionCode::AD)
3120
        );
3121
    }
3122
3123
    public function testUnknownCountryCallingCode()
3124
    {
3125
        $this->assertFalse($this->phoneUtil->isValidNumber(self::$unknownCountryCodeNoRawInput));
3126
        // It's not very well defined as to what the E164 representation for a number with an invalid
3127
        // country calling code is, but just prefixing the country code and national number is about
3128
        // the best we can do.
3129
        $this->assertEquals(
3130
            "+212345",
3131
            $this->phoneUtil->format(self::$unknownCountryCodeNoRawInput, PhoneNumberFormat::E164)
3132
        );
3133
    }
3134
3135
    public function testIsNumberMatchMatches()
3136
    {
3137
        // Test simple matches where formatting is different, or leading zeros, or country calling code
3138
        // has been specified.
3139
        $this->assertEquals(
3140
            MatchType::EXACT_MATCH,
3141
            $this->phoneUtil->isNumberMatch("+64 3 331 6005", "+64 03 331 6005")
3142
        );
3143
        $this->assertEquals(MatchType::EXACT_MATCH, $this->phoneUtil->isNumberMatch("+800 1234 5678", "+80012345678"));
3144
        $this->assertEquals(
3145
            MatchType::EXACT_MATCH,
3146
            $this->phoneUtil->isNumberMatch("+64 03 331-6005", "+64 03331 6005")
3147
        );
3148
        $this->assertEquals(MatchType::EXACT_MATCH, $this->phoneUtil->isNumberMatch("+643 331-6005", "+64033316005"));
3149
        $this->assertEquals(MatchType::EXACT_MATCH, $this->phoneUtil->isNumberMatch("+643 331-6005", "+6433316005"));
3150
        $this->assertEquals(MatchType::EXACT_MATCH, $this->phoneUtil->isNumberMatch("+64 3 331-6005", "+6433316005"));
3151
        $this->assertEquals(
3152
            MatchType::EXACT_MATCH,
3153
            $this->phoneUtil->isNumberMatch("+64 3 331-6005", "tel:+64-3-331-6005;isub=123")
3154
        );
3155
        // Test alpha numbers.
3156
        $this->assertEquals(
3157
            MatchType::EXACT_MATCH,
3158
            $this->phoneUtil->isNumberMatch("+1800 siX-Flags", "+1 800 7493 5247")
3159
        );
3160
        // Test numbers with extensions.
3161
        $this->assertEquals(
3162
            MatchType::EXACT_MATCH,
3163
            $this->phoneUtil->isNumberMatch("+64 3 331-6005 extn 1234", "+6433316005#1234")
3164
        );
3165
        $this->assertEquals(
3166
            MatchType::EXACT_MATCH,
3167
            $this->phoneUtil->isNumberMatch("+64 3 331-6005 ext. 1234", "+6433316005;1234")
3168
        );
3169
        // Test proto buffers.
3170
        $this->assertEquals(MatchType::EXACT_MATCH, $this->phoneUtil->isNumberMatch(self::$nzNumber, "+6403 331 6005"));
3171
3172
        $nzNumber = new PhoneNumber();
3173
        $nzNumber->mergeFrom(self::$nzNumber)->setExtension("3456");
3174
        $this->assertEquals(
3175
            MatchType::EXACT_MATCH,
3176
            $this->phoneUtil->isNumberMatch($nzNumber, "+643 331 6005 ext 3456")
3177
        );
3178
3179
        // Check empty extensions are ignored.
3180
        $nzNumber->setExtension("");
3181
        $this->assertEquals(MatchType::EXACT_MATCH, $this->phoneUtil->isNumberMatch($nzNumber, "+6403 331 6005"));
3182
        // Check variant with two proto buffers.
3183
        $this->assertEquals(
3184
            MatchType::EXACT_MATCH,
3185
            $this->phoneUtil->isNumberMatch($nzNumber, self::$nzNumber),
3186
            "Number " . (string)$nzNumber . " did not match " . (string)self::$nzNumber
3187
        );
3188
    }
3189
3190
    public function testIsNumberMatchShortMatchIfDiffNumLeadingZeros()
3191
    {
3192
        $nzNumberOne = new PhoneNumber();
3193
        $nzNumberTwo = new PhoneNumber();
3194
        $nzNumberOne->setCountryCode(64)->setNationalNumber(33316005)->setItalianLeadingZero(true);
3195
        $nzNumberTwo->setCountryCode(64)->setNationalNumber(33316005)->setItalianLeadingZero(true)->setNumberOfLeadingZeros(2);
3196
3197
        $this->assertEquals(MatchType::SHORT_NSN_MATCH, $this->phoneUtil->isNumberMatch($nzNumberOne, $nzNumberTwo));
3198
3199
        $nzNumberOne->setItalianLeadingZero(false)->setNumberOfLeadingZeros(1);
3200
        $nzNumberTwo->setItalianLeadingZero(true)->setNumberOfLeadingZeros(1);
3201
3202
        // Since one doesn't have the Italian leading zero set to true, we ignore the number of leading zeros present
3203
        // (1 is in any case the default value)
3204
        $this->assertEquals(MatchType::SHORT_NSN_MATCH, $this->phoneUtil->isNumberMatch($nzNumberOne, $nzNumberTwo));
3205
    }
3206
3207
    public function testIsNumberMatchAcceptsProtoDefaultsAsMatch()
3208
    {
3209
        $nzNumberOne = new PhoneNumber();
3210
        $nzNumberTwo = new PhoneNumber();
3211
3212
        $nzNumberOne->setCountryCode(64)->setNationalNumber(33316005)->setItalianLeadingZero(true);
3213
        // The default for number of leading zeros is 1, so it shouldn't normally be set, however if it
3214
        // is it should be considered equivalent.
3215
        $nzNumberTwo->setCountryCode(64)->setNationalNumber(33316005)->setItalianLeadingZero(true)->setNumberOfLeadingZeros(1);
3216
3217
        $this->assertEquals(MatchType::EXACT_MATCH, $this->phoneUtil->isNumberMatch($nzNumberOne, $nzNumberTwo));
3218
    }
3219
3220
    public function testIsNumberMatchMatchesDiffLeadingZerosIfItalianLeadingZeroFalse()
3221
    {
3222
        $nzNumberOne = new PhoneNumber();
3223
        $nzNumberTwo = new PhoneNumber();
3224
3225
        $nzNumberOne->setCountryCode(64)->setNationalNumber(33316005);
3226
        // The default for number of leading zeros is 1, so it shouldn't normally be set, however if it
3227
        // is it should be considered equivalent
3228
        $nzNumberTwo->setCountryCode(64)->setNationalNumber(33316005)->setNumberOfLeadingZeros(1);
3229
3230
        $this->assertEquals(MatchType::EXACT_MATCH, $this->phoneUtil->isNumberMatch($nzNumberOne, $nzNumberTwo));
3231
3232
        // Even if it is set to ten, it is still equivalent because in both cases
3233
        // italian leading zero is not true
3234
        $nzNumberTwo->setNumberOfLeadingZeros(10);
3235
        $this->assertEquals(MatchType::EXACT_MATCH, $this->phoneUtil->isNumberMatch($nzNumberOne, $nzNumberTwo));
3236
    }
3237
3238
    public function testIsNumberMatchIgnoresSomeFields()
3239
    {
3240
        // Check raw_input, country_code_source and preferred_domestic_carrier_code are ignored.
3241
        $brNumberOne = new PhoneNumber();
3242
        $brNumberTwo = new PhoneNumber();
3243
        $brNumberOne->setCountryCode(55)->setNationalNumber(3121286979)
3244
            ->setCountryCodeSource(CountryCodeSource::FROM_NUMBER_WITH_PLUS_SIGN)
3245
            ->setPreferredDomesticCarrierCode("12")->setRawInput("012 3121286979");
3246
        $brNumberTwo->setCountryCode(55)->setNationalNumber(3121286979)
3247
            ->setCountryCodeSource(CountryCodeSource::FROM_DEFAULT_COUNTRY)
3248
            ->setPreferredDomesticCarrierCode("14")->setRawInput("143121286979");
3249
3250
        $this->assertEquals(MatchType::EXACT_MATCH, $this->phoneUtil->isNumberMatch($brNumberOne, $brNumberTwo));
3251
    }
3252
3253
    public function testIsNumberMatchNonMatches()
3254
    {
3255
        // Non-matches.
3256
        $this->assertEquals(MatchType::NO_MATCH, $this->phoneUtil->isNumberMatch("03 331 6005", "03 331 6006"));
3257
        $this->assertEquals(MatchType::NO_MATCH, $this->phoneUtil->isNumberMatch("+800 1234 5678", "+1 800 1234 5678"));
3258
        // Different country calling code, partial number match.
3259
        $this->assertEquals(MatchType::NO_MATCH, $this->phoneUtil->isNumberMatch("+64 3 331-6005", "+16433316005"));
3260
        // Different country calling code, same number.
3261
        $this->assertEquals(MatchType::NO_MATCH, $this->phoneUtil->isNumberMatch("+64 3 331-6005", "+6133316005"));
3262
        // Extension different, all else the same.
3263
        $this->assertEquals(
3264
            MatchType::NO_MATCH,
3265
            $this->phoneUtil->isNumberMatch("+64 3 331-6005 extn 1234", "0116433316005#1235")
3266
        );
3267
        $this->assertEquals(
3268
            MatchType::NO_MATCH,
3269
            $this->phoneUtil->isNumberMatch("+64 3 331-6005 extn 1234", "tel:+64-3-331-6005;ext=1235")
3270
        );
3271
        // NSN matches, but extension is different - not the same number.
3272
        $this->assertEquals(
3273
            MatchType::NO_MATCH,
3274
            $this->phoneUtil->isNumberMatch("+64 3 331-6005 ext.1235", "3 331 6005#1234")
3275
        );
3276
3277
        // Invalid numbers that can't be parsed.
3278
        $this->assertEquals(MatchType::NOT_A_NUMBER, $this->phoneUtil->isNumberMatch("4", "3 331 6043"));
3279
        $this->assertEquals(MatchType::NOT_A_NUMBER, $this->phoneUtil->isNumberMatch("+43", "+64 3 331 6005"));
3280
        $this->assertEquals(MatchType::NOT_A_NUMBER, $this->phoneUtil->isNumberMatch("+43", "64 3 331 6005"));
3281
        $this->assertEquals(MatchType::NOT_A_NUMBER, $this->phoneUtil->isNumberMatch("Dog", "64 3 331 6005"));
3282
    }
3283
3284
    public function testIsNumberMatchNsnMatches()
3285
    {
3286
        // NSN matches.
3287
        $this->assertEquals(MatchType::NSN_MATCH, $this->phoneUtil->isNumberMatch("+64 3 331-6005", "03 331 6005"));
3288
        $this->assertEquals(
3289
            MatchType::NSN_MATCH,
3290
            $this->phoneUtil->isNumberMatch("+64 3 331-6005", "tel:03-331-6005;isub=1234;phone-context=abc.nz")
3291
        );
3292
        $this->assertEquals(MatchType::NSN_MATCH, $this->phoneUtil->isNumberMatch(self::$nzNumber, "03 331 6005"));
3293
        // Here the second number possibly starts with the country calling code for New Zealand,
3294
        // although we are unsure.
3295
        $unchangedNzNumber = new PhoneNumber();
3296
        $unchangedNzNumber->mergeFrom(self::$nzNumber);
3297
        $this->assertEquals(
3298
            MatchType::NSN_MATCH,
3299
            $this->phoneUtil->isNumberMatch($unchangedNzNumber, "(64-3) 331 6005")
3300
        );
3301
        // Check the phone number proto was not edited during the method call.
3302
        $this->assertEquals(self::$nzNumber, $unchangedNzNumber);
3303
3304
        // Here, the 1 might be a national prefix, if we compare it to the US number, so the resultant
3305
        // match is an NSN match.
3306
        $this->assertEquals(MatchType::NSN_MATCH, $this->phoneUtil->isNumberMatch(self::$usNumber, "1-650-253-0000"));
3307
        $this->assertEquals(MatchType::NSN_MATCH, $this->phoneUtil->isNumberMatch(self::$usNumber, "6502530000"));
3308
        $this->assertEquals(MatchType::NSN_MATCH, $this->phoneUtil->isNumberMatch("+1 650-253 0000", "1 650 253 0000"));
3309
        $this->assertEquals(MatchType::NSN_MATCH, $this->phoneUtil->isNumberMatch("1 650-253 0000", "1 650 253 0000"));
3310
        $this->assertEquals(MatchType::NSN_MATCH, $this->phoneUtil->isNumberMatch("1 650-253 0000", "+1 650 253 0000"));
3311
        // For this case, the match will be a short NSN match, because we cannot assume that the 1 might
3312
        // be a national prefix, so don't remove it when parsing.
3313
        $randomNumber = new PhoneNumber();
3314
        $randomNumber->setCountryCode(41)->setNationalNumber(6502530000);
3315
        $this->assertEquals(
3316
            MatchType::SHORT_NSN_MATCH,
3317
            $this->phoneUtil->isNumberMatch($randomNumber, "1-650-253-0000")
3318
        );
3319
    }
3320
3321
    public function testIsNumberMatchShortNsnMatches()
3322
    {
3323
        // Short NSN matches with the country not specified for either one or both numbers.
3324
        $this->assertEquals(MatchType::SHORT_NSN_MATCH, $this->phoneUtil->isNumberMatch("+64 3 331-6005", "331 6005"));
3325
        $this->assertEquals(
3326
            MatchType::SHORT_NSN_MATCH,
3327
            $this->phoneUtil->isNumberMatch("+64 3 331-6005", "tel:331-6005;phone-context=abc.nz")
3328
        );
3329
        $this->assertEquals(
3330
            MatchType::SHORT_NSN_MATCH,
3331
            $this->phoneUtil->isNumberMatch("+64 3 331-6005", "tel:331-6005;isub=1234;phone-context=abc.nz")
3332
        );
3333
        $this->assertEquals(
3334
            MatchType::SHORT_NSN_MATCH,
3335
            $this->phoneUtil->isNumberMatch("+64 3 331-6005", "tel:331-6005;isub=1234;phone-context=abc.nz;a=%A1")
3336
        );
3337
3338
        // We did not know that the "0" was a national prefix since neither number has a country code,
3339
        // so this is considered a SHORT_NSN_MATCH.
3340
        $this->assertEquals(MatchType::SHORT_NSN_MATCH, $this->phoneUtil->isNumberMatch("3 331-6005", "03 331 6005"));
3341
        $this->assertEquals(MatchType::SHORT_NSN_MATCH, $this->phoneUtil->isNumberMatch("3 331-6005", "331 6005"));
3342
        $this->assertEquals(
3343
            MatchType::SHORT_NSN_MATCH,
3344
            $this->phoneUtil->isNumberMatch("3 331-6005", "tel:331-6005;phone-context=abc.nz")
3345
        );
3346
        $this->assertEquals(MatchType::SHORT_NSN_MATCH, $this->phoneUtil->isNumberMatch("3 331-6005", "+64 331 6005"));
3347
3348
        // Short NSN match with the country specified.
3349
        $this->assertEquals(MatchType::SHORT_NSN_MATCH, $this->phoneUtil->isNumberMatch("03 331-6005", "331 6005"));
3350
        $this->assertEquals(MatchType::SHORT_NSN_MATCH, $this->phoneUtil->isNumberMatch("1 234 345 6789", "345 6789"));
3351
        $this->assertEquals(
3352
            MatchType::SHORT_NSN_MATCH,
3353
            $this->phoneUtil->isNumberMatch("+1 (234) 345 6789", "345 6789")
3354
        );
3355
        // NSN matches, country calling code omitted for one number, extension missing for one.
3356
        $this->assertEquals(
3357
            MatchType::SHORT_NSN_MATCH,
3358
            $this->phoneUtil->isNumberMatch("+64 3 331-6005", "3 331 6005#1234")
3359
        );
3360
        // One has Italian leading zero, one does not.
3361
        $italianNumberOne = new PhoneNumber();
3362
        $italianNumberOne->setCountryCode(39)->setNationalNumber(1234)->setItalianLeadingZero(true);
3363
        $italianNumberTwo = new PhoneNumber();
3364
        $italianNumberTwo->setCountryCode(39)->setNationalNumber(1234);
3365
        $this->assertEquals(
3366
            MatchType::SHORT_NSN_MATCH,
3367
            $this->phoneUtil->isNumberMatch($italianNumberOne, $italianNumberTwo)
3368
        );
3369
        // One has an extension, the other has an extension of "".
3370
        $italianNumberOne->setExtension("1234")->clearItalianLeadingZero();
3371
        $italianNumberTwo->setExtension("");
3372
        $this->assertEquals(
3373
            MatchType::SHORT_NSN_MATCH,
3374
            $this->phoneUtil->isNumberMatch($italianNumberOne, $italianNumberTwo)
3375
        );
3376
    }
3377
3378
    public function testCanBeInternationallyDialled()
3379
    {
3380
        // We have no-international-dialling rules for the US in our test metadata that say that
3381
        // toll-free numbers cannot be dialled internationally.
3382
        $this->assertFalse($this->phoneUtil->canBeInternationallyDialled(self::$usTollFree));
3383
        // Normal US numbers can be internationally dialled.
3384
        $this->assertTrue($this->phoneUtil->canBeInternationallyDialled(self::$usNumber));
3385
3386
        // Invalid number.
3387
        $this->assertTrue($this->phoneUtil->canBeInternationallyDialled(self::$usLocalNumber));
3388
3389
        // We have no data for NZ - should return true.
3390
        $this->assertTrue($this->phoneUtil->canBeInternationallyDialled(self::$nzNumber));
3391
        $this->assertTrue($this->phoneUtil->canBeInternationallyDialled(self::$internationalTollFree));
3392
    }
3393
3394
    public function testIsAlphaNumber()
3395
    {
3396
        $this->assertTrue($this->phoneUtil->isAlphaNumber("1800 six-flags"));
3397
        $this->assertTrue($this->phoneUtil->isAlphaNumber("1800 six-flags ext. 1234"));
3398
        $this->assertTrue($this->phoneUtil->isAlphaNumber("+800 six-flags"));
3399
        $this->assertTrue($this->phoneUtil->isAlphaNumber("180 six-flags"));
3400
        $this->assertFalse($this->phoneUtil->isAlphaNumber("1800 123-1234"));
3401
        $this->assertFalse($this->phoneUtil->isAlphaNumber("1 six-flags"));
3402
        $this->assertFalse($this->phoneUtil->isAlphaNumber("18 six-flags"));
3403
        $this->assertFalse($this->phoneUtil->isAlphaNumber("1800 123-1234 extension: 1234"));
3404
        $this->assertFalse($this->phoneUtil->isAlphaNumber("+800 1234-1234"));
3405
    }
3406
3407
    public function testIsMobileNumberPortableRegion()
3408
    {
3409
        $this->assertTrue($this->phoneUtil->isMobileNumberPortableRegion(RegionCode::US));
3410
        $this->assertTrue($this->phoneUtil->isMobileNumberPortableRegion(RegionCode::GB));
3411
        $this->assertFalse($this->phoneUtil->isMobileNumberPortableRegion(RegionCode::AE));
3412
        $this->assertFalse($this->phoneUtil->isMobileNumberPortableRegion(RegionCode::BS));
3413
    }
3414
}
3415