Passed
Push — upstream-8.9.2 ( 6a22e8 )
by Joshua
25:34 queued 09:29
created

PhoneNumberUtilTest   D

Complexity

Total Complexity 150

Size/Duplication

Total Lines 3748
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 8

Importance

Changes 0
Metric Value
wmc 150
lcom 1
cbo 8
dl 0
loc 3748
rs 4.4102
c 0
b 0
f 0

How to fix   Complexity   

Complex Class

Complex classes like PhoneNumberUtilTest often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use PhoneNumberUtilTest, and based on these observations, apply Extract Interface, too.

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