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

PhoneNumberMatcherTest   D

Complexity

Total Complexity 85

Size/Duplication

Total Lines 1106
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 7

Importance

Changes 0
Metric Value
wmc 85
lcom 2
cbo 7
dl 0
loc 1106
rs 4.4102
c 0
b 0
f 0

How to fix   Complexity   

Complex Class

Complex classes like PhoneNumberMatcherTest 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 PhoneNumberMatcherTest, 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\Leniency;
8
use libphonenumber\PhoneNumber;
9
use libphonenumber\PhoneNumberMatch;
10
use libphonenumber\PhoneNumberMatcher;
11
use libphonenumber\PhoneNumberUtil;
12
use libphonenumber\RegionCode;
13
14
class PhoneNumberMatcherTest extends \PHPUnit_Framework_TestCase
15
{
16
    /**
17
     * @var PhoneNumberUtil
18
     */
19
    protected $phoneUtil;
20
21
    public function setUp()
22
    {
23
        PhoneNumberUtil::resetInstance();
24
        $this->phoneUtil = PhoneNumberUtil::getInstance(
25
            PhoneNumberUtilTest::TEST_META_DATA_FILE_PREFIX,
26
            CountryCodeToRegionCodeMapForTesting::$countryCodeToRegionCodeMapForTesting
27
        );
28
    }
29
30
    public function testContainsMoreThanOneSlashInNationalNumber()
31
    {
32
        // A date should return true.
33
        $number = new PhoneNumber();
34
        $number->setCountryCode(1);
35
        $number->setCountryCodeSource(CountryCodeSource::FROM_DEFAULT_COUNTRY);
36
        $candidate = "1/05/2013";
37
        $this->assertTrue(PhoneNumberMatcher::containsMoreThanOneSlashInNationalNumber($number, $candidate));
38
39
        // Here, the country code source thinks it started with a country calling code, but this is not
40
        // the same as the part before the slash, so it's still true.
41
        $number = new PhoneNumber();
42
        $number->setCountryCodeSource(274);
43
        $number->setCountryCodeSource(CountryCodeSource::FROM_NUMBER_WITHOUT_PLUS_SIGN);
44
        $candidate = "27/4/2013";
45
        $this->assertTrue(PhoneNumberMatcher::containsMoreThanOneSlashInNationalNumber($number, $candidate));
46
47
        // Now it should be false, because the first slash is after the country calling code.
48
        $number = new PhoneNumber();
49
        $number->setCountryCode(49);
50
        $number->setCountryCodeSource(CountryCodeSource::FROM_NUMBER_WITH_PLUS_SIGN);
51
        $candidate = "49/69/2013";
52
        $this->assertFalse(PhoneNumberMatcher::containsMoreThanOneSlashInNationalNumber($number, $candidate));
53
54
        $number = new PhoneNumber();
55
        $number->setCountryCode(49);
56
        $number->setCountryCodeSource(CountryCodeSource::FROM_NUMBER_WITHOUT_PLUS_SIGN);
57
        $candidate = "+49/69/2013";
58
        $this->assertFalse(PhoneNumberMatcher::containsMoreThanOneSlashInNationalNumber($number, $candidate));
59
60
        $candidate = "+ 49/69/2013";
61
        $this->assertFalse(PhoneNumberMatcher::containsMoreThanOneSlashInNationalNumber($number, $candidate));
62
63
        $candidate = "+ 49/69/20/13";
64
        $this->assertTrue(PhoneNumberMatcher::containsMoreThanOneSlashInNationalNumber($number, $candidate));
65
66
        // Here, the first group is not assumed to be the country calling code, even though it is the
67
        // same as it, so this should return true.
68
        $number = new PhoneNumber();
69
        $number->setCountryCode(49);
70
        $number->setCountryCodeSource(CountryCodeSource::FROM_DEFAULT_COUNTRY);
71
        $candidate = "49/69/2013";
72
        $this->assertTrue(PhoneNumberMatcher::containsMoreThanOneSlashInNationalNumber($number, $candidate));
73
    }
74
75
    public function testFindNationalNumber()
76
    {
77
        // same cases as in testParseNationalNumber
78
        $this->doTestFindInContext("033316005", RegionCode::NZ);
79
        // ("33316005", RegionCode.NZ) is omitted since the national prefix is obligatory for these
80
        // types of numbers in New Zealand.
81
        // National prefix attached and some formatting present.
82
        $this->doTestFindInContext("03-331 6005", RegionCode::NZ);
83
        $this->doTestFindInContext("03 331 6005", RegionCode::NZ);
84
        // Testing international prefixes.
85
        // Should strip country code.
86
        $this->doTestFindInContext("0064 3 331 6005", RegionCode::NZ);
87
        // Try again, but this time we have an international number with Region Code US. It should
88
        // recognize the country code and parse accordingly.
89
        $this->doTestFindInContext("01164 3 331 6005", RegionCode::US);
90
        $this->doTestFindInContext("+64 3 331 6005", RegionCode::US);
91
92
        $this->doTestFindInContext("64(0)64123456", RegionCode::NZ);
93
        // Check that using a "/" is fine in a phone number.
94
        // Note that real Polish numbers do *not* start with a 0.
95
        $this->doTestFindInContext("0123/456789", RegionCode::PL);
96
        $this->doTestFindInContext("123-456-7890", RegionCode::US);
97
    }
98
99
    public function testFindWithInternationalPrefixes()
100
    {
101
        $this->doTestFindInContext("+1 (650) 333-6000", RegionCode::NZ);
102
        $this->doTestFindInContext("1-650-333-6000", RegionCode::US);
103
        // Calling the US number from Singapore by using different service providers
104
        // 1st test: calling using SingTel IDD service (IDD is 001)
105
        $this->doTestFindInContext("0011-650-333-6000", RegionCode::SG);
106
        // 2nd test: calling using StarHub IDD service (IDD is 008)
107
        $this->doTestFindInContext("0081-650-333-6000", RegionCode::SG);
108
        // 3rd test: calling using SingTel V019 service (IDD is 019)
109
        $this->doTestFindInContext("0191-650-333-6000", RegionCode::SG);
110
        // Calling the US number from Poland
111
        $this->doTestFindInContext("0~01-650-333-6000", RegionCode::PL);
112
        // Using "++" at the start.
113
        $this->doTestFindInContext("++1 (650) 333-6000", RegionCode::PL);
114
        // Using a full-width plus sign.
115
        $this->doTestFindInContext("\xEF\xBC\x8B1 (650) 333-6000", RegionCode::SG);
116
        // The whole number, including punctuation, is here represented in full-width form.
117
        $this->doTestFindInContext("+1 (650) 333-6000", RegionCode::SG);
118
    }
119
120
    public function testFindWithLeadingZero()
121
    {
122
        $this->doTestFindInContext("+39 02-36618 300", RegionCode::NZ);
123
        $this->doTestFindInContext("02-36618 300", RegionCode::IT);
124
        $this->doTestFindInContext("312 345 678", RegionCode::IT);
125
    }
126
127
    public function testFindNationalNumberArgentina()
128
    {
129
        // Test parsing mobile numbers of Argentina.
130
        $this->doTestFindInContext("+54 9 343 555 1212", RegionCode::AR);
131
        $this->doTestFindInContext("0343 15 555 1212", RegionCode::AR);
132
133
        $this->doTestFindInContext("+54 9 3715 65 4320", RegionCode::AR);
134
        $this->doTestFindInContext("03715 15 65 4320", RegionCode::AR);
135
136
        // Test parsing fixed-line numbers of Argentina.
137
        $this->doTestFindInContext("+54 11 3797 0000", RegionCode::AR);
138
        $this->doTestFindInContext("011 3797 0000", RegionCode::AR);
139
140
        $this->doTestFindInContext("+54 3715 65 4321", RegionCode::AR);
141
        $this->doTestFindInContext("03715 65 4321", RegionCode::AR);
142
143
        $this->doTestFindInContext("+54 23 1234 0000", RegionCode::AR);
144
        $this->doTestFindInContext("023 1234 0000", RegionCode::AR);
145
    }
146
147
    public function testFindWithXInNumber()
148
    {
149
        $this->doTestFindInContext("(0xx) 123456789", RegionCode::AR);
150
        // A case where x denotes both carrier codes and extension symbol.
151
        $this->doTestFindInContext("(0xx) 123456789 x 1234", RegionCode::AR);
152
153
        // This test is intentionally constructed such that the number of digit after xx is larger than
154
        // 7, so that the number won't be mistakenly treated as an extension, as we allow extensions up
155
        // to 7 digits. This assumption is okay for now as all the countries where a carrier selection
156
        // code is written in the form of xx have a national significant number of length larger than 7.
157
        $this->doTestFindInContext("011xx5481429712", RegionCode::US);
158
    }
159
160
    public function testFindNumbersMexico()
161
    {
162
        // Test parsing fixed-line numbers of Mexico.
163
        $this->doTestFindInContext("+52 (449)978-0001", RegionCode::MX);
164
        $this->doTestFindInContext("01 (449)978-0001", RegionCode::MX);
165
        $this->doTestFindInContext("(449)978-0001", RegionCode::MX);
166
167
        // Test parsing mobile numbers of Mexico.
168
        $this->doTestFindInContext("+52 1 33 1234-5678", RegionCode::MX);
169
        $this->doTestFindInContext("044 (33) 1234-5678", RegionCode::MX);
170
        $this->doTestFindInContext("045 33 1234-5678", RegionCode::MX);
171
    }
172
173
    public function testFindNumbersWithPlusWithNoRegion()
174
    {
175
        // RegionCode.ZZ is allowed only if the number starts with a '+' - then the country code can be
176
        // calculated.
177
        $this->doTestFindInContext("+64 3 331 6005", RegionCode::ZZ);
178
        // Null is also allowed for the region code in these cases.
179
        $this->doTestFindInContext("+64 3 331 6005", null);
180
    }
181
182
    public function testFindExtensions()
183
    {
184
        $this->doTestFindInContext("03 331 6005 ext 3456", RegionCode::NZ);
185
        $this->doTestFindInContext("03-3316005x3456", RegionCode::NZ);
186
        $this->doTestFindInContext("03-3316005 int.3456", RegionCode::NZ);
187
        $this->doTestFindInContext("03 3316005 #3456", RegionCode::NZ);
188
        $this->doTestFindInContext("0~0 1800 7493 524", RegionCode::PL);
189
        $this->doTestFindInContext("(1800) 7493.524", RegionCode::US);
190
        // Check that the last instance of an extension token is matched.
191
        $this->doTestFindInContext("0~0 1800 7493 524 ~1234", RegionCode::PL);
192
        // Verifying bug-fix where the last digit of a number was previously omitted if it was a 0 when
193
        // extracting the extension. Also verifying a few different cases of extensions.
194
        $this->doTestFindInContext("+44 2034567890x456", RegionCode::NZ);
195
        $this->doTestFindInContext("+44 2034567890x456", RegionCode::GB);
196
        $this->doTestFindInContext("+44 2034567890 x456", RegionCode::GB);
197
        $this->doTestFindInContext("+44 2034567890 X456", RegionCode::GB);
198
        $this->doTestFindInContext("+44 2034567890 X 456", RegionCode::GB);
199
        $this->doTestFindInContext("+44 2034567890 X  456", RegionCode::GB);
200
        $this->doTestFindInContext("+44 2034567890  X 456", RegionCode::GB);
201
202
        $this->doTestFindInContext("(800) 901-3355 x 7246433", RegionCode::US);
203
        $this->doTestFindInContext("(800) 901-3355 , ext 7246433", RegionCode::US);
204
        $this->doTestFindInContext("(800) 901-3355 ,extension 7246433", RegionCode::US);
205
        // The next test differs from PhoneNumberUtil -> when matching we don't consider a lone comma to
206
        // indicate an extension, although we accept it when parsing.
207
        $this->doTestFindInContext("(800) 901-3355 ,x 7246433", RegionCode::US);
208
        $this->doTestFindInContext("(800) 901-3355 ext: 7246433", RegionCode::US);
209
    }
210
211
    public function testFindInterspersedWithSpace()
212
    {
213
        $this->doTestFindInContext("0 3   3 3 1   6 0 0 5", RegionCode::NZ);
214
    }
215
216
    /**
217
     * Test matching behaviour when starting in the middle of a phone number.
218
     */
219
    public function testIntermediateParsePositions()
220
    {
221
        $text = "Call 033316005  or 032316005!";
222
        //       |    |    |    |    |    |
223
        //       0    5   10   15   20   25
224
225
        // Iterate over all possible indices.
226
        for ($i = 0; $i <= 5; $i++) {
227
            $this->assertEqualRange($text, $i, 5, 14);
228
        }
229
        // 7 and 8 digits in a row are still parsed as number.
230
        $this->assertEqualRange($text, 6, 6, 14);
231
        $this->assertEqualRange($text, 7, 7, 14);
232
        // Anything smaller is skipped to the second instance.
233
        for ($i = 8; $i <= 19; $i++) {
234
            $this->assertEqualRange($text, $i, 19, 28);
235
        }
236
    }
237
238
    public function testFourMatchesInARow()
239
    {
240
        $number1 = "415-666-7777";
241
        $number2 = "800-443-1223";
242
        $number3 = "212-443-1223";
243
        $number4 = "650-443-1223";
244
        $text = $number1 . " - " . $number2 . " - " . $number3 . " - " . $number4;
245
246
        $iterator = $this->phoneUtil->findNumbers($text, RegionCode::US);
247
248
        $iterator->next();
249
        $match = $iterator->current();
250
        $this->assertMatchProperties($match, $text, $number1, RegionCode::US);
251
252
        $iterator->next();
253
        $match = $iterator->current();
254
        $this->assertMatchProperties($match, $text, $number2, RegionCode::US);
255
256
        $iterator->next();
257
        $match = $iterator->current();
258
        $this->assertMatchProperties($match, $text, $number3, RegionCode::US);
259
260
        $iterator->next();
261
        $match = $iterator->current();
262
        $this->assertMatchProperties($match, $text, $number4, RegionCode::US);
263
    }
264
265
    public function testMatchesFoundWithMultipleSpaces()
266
    {
267
        $number1 = "(415) 666-7777";
268
        $number2 = "(800) 443-1223";
269
        $text = $number1 . " " . $number2;
270
271
        $iterator = $this->phoneUtil->findNumbers($text, RegionCode::US);
272
273
        $iterator->next();
274
        $match = $iterator->current();
275
        $this->assertMatchProperties($match, $text, $number1, RegionCode::US);
276
277
        $iterator->next();
278
        $match = $iterator->current();
279
        $this->assertMatchProperties($match, $text, $number2, RegionCode::US);
280
    }
281
282
    public function testMatchWithSurroundingZipcodes()
283
    {
284
        $number = "415-666-7777";
285
        $zipPreceding = "My address is CA 34215 - " . $number . " is my number.";
286
287
        $iterator = $this->phoneUtil->findNumbers($zipPreceding, RegionCode::US);
288
289
        $iterator->next();
290
        $match = $iterator->current();
291
        $this->assertMatchProperties($match, $zipPreceding, $number, RegionCode::US);
292
293
        // Now repeat, but this time the phone number has spaces in it. It should still be found.
294
        $number = "(415) 666 7777";
295
296
        $zipFollowing = "My number is " . $number . ". 34215 is my zip-code.";
297
298
        $iterator = $this->phoneUtil->findNumbers($zipFollowing, RegionCode::US);
299
300
        $iterator->next();
301
        $match = $iterator->current();
302
        $this->assertMatchProperties($match, $zipFollowing, $number, RegionCode::US);
303
    }
304
305
    public function dataLatinLetters()
306
    {
307
        return array(
308
            array('c', true),
309
            array('C', true),
310
            array("\xC3\x89", true),
311
            array("\xCC\x81", true), // Combining acute accent
312
            // Punctuation, digits and white-space are not considered "latin letters".
313
            array(':', false),
314
            array('5', false),
315
            array('-', false),
316
            array('.', false),
317
            array(' ', false),
318
            array("\xE6\x88\x91", false),  // Chinese character
319
            array("\xE3\x81\xAE", false),  // Hiragana letter no
320
        );
321
    }
322
323
    /**
324
     * @dataProvider dataLatinLetters
325
     * @param string $letter
326
     * @param string $expectedResult
327
     */
328
    public function testIsLatinLetter($letter, $expectedResult)
329
    {
330
        $this->assertEquals($expectedResult, PhoneNumberMatcher::isLatinLetter($letter),
331
            "{$letter} should return {$expectedResult}");
332
    }
333
334
    public function testMatchesWithSurroundingLatinChars()
335
    {
336
        $possibleOnlyContexts = array();
337
        $possibleOnlyContexts[] = array("abc", "def");
338
        $possibleOnlyContexts[] = array("abc", "");
339
        $possibleOnlyContexts[] = array("", "def");
340
        // Latin capital letter e with an acute accent.
341
        $possibleOnlyContexts[] = array("\xC3\x89", "");
342
        // e with an acute accent decomposed (with combining mark).
343
        $possibleOnlyContexts[] = array("e\xCC\x81", "");
344
345
        // Numbers should not be considered valid, if they are surrounded by Latin characters, but
346
        // should be considered possible.
347
        $this->findMatchesInContexts($possibleOnlyContexts, false, true);
348
    }
349
350
    public function testMoneyNotSeenAsPhoneNumber()
351
    {
352
        $possibleOnlyContexts = array();
353
        $possibleOnlyContexts[] = array("$", "");
354
        $possibleOnlyContexts[] = array("", "$");
355
        $possibleOnlyContexts[] = array("\xC2\xA3", "");  // Pound sign
356
        $possibleOnlyContexts[] = array("\xC2\xA5", "");  // Yen sign
357
358
        $this->findMatchesInContexts($possibleOnlyContexts, false, true);
359
    }
360
361
    public function testPercentageNotSeenAsPhoneNumber()
362
    {
363
        $possibleOnlyContexts = array();
364
        $possibleOnlyContexts[] = array("", "%");
365
        // Numbers followed by % should be dropped
366
        $this->findMatchesInContexts($possibleOnlyContexts, false, true);
367
    }
368
369
    public function testPhoneNumberWithLeadingOrTrailingMoneyMatches()
370
    {
371
        // Because of the space after the 20 (or before the 100) these dollar amounts should not stop
372
        // the actual number from being found.
373
        $contexts = array();
374
        $contexts[] = array('$20 ', '');
375
        $contexts[] = array('', ' 100$');
376
377
        $this->findMatchesInContexts($contexts, true, true);
378
    }
379
380
    public function testMatchesWithSurroundingLatinCharsAndLeadingPunctuation()
381
    {
382
        // Contexts with trailing characters. Leading characters are okay here since the numbers we will
383
        // insert start with punctuation, but trailing characters are still not allowed.
384
        $possibleOnlyContexts = array();
385
        $possibleOnlyContexts[] = array("abc", "def");
386
        $possibleOnlyContexts[] = array("", "def");
387
        $possibleOnlyContexts[] = array("", "\xC3\x89");
388
389
        // Numbers should not be considered valid, if they have trailing Latin characters, but should be
390
        // considered possible.
391
        $numberWithPlus = "+14156667777";
392
        $numberWithBrackets = "(415)6667777";
393
        $this->findMatchesInContexts($possibleOnlyContexts, false, true, RegionCode::US, $numberWithPlus);
394
        $this->findMatchesInContexts($possibleOnlyContexts, false, true, RegionCode::US, $numberWithBrackets);
395
396
        $validContexts = array();
397
        $validContexts[] = array("abc", "");
398
        $validContexts[] = array("\xC3\x89", "");
399
        $validContexts[] = array("\xC3\x89", "."); // Trailing punctuation.
400
        $validContexts[] = array("\xC3\x89", " def"); // Trailing white space.
401
402
        // Numbers should be considered valid, since they start with punctuation.
403
        $this->findMatchesInContexts($validContexts, true, true, RegionCode::US, $numberWithPlus);
404
        $this->findMatchesInContexts($validContexts, true, true, RegionCode::US, $numberWithBrackets);
405
    }
406
407
    public function testMatchesWithSurroundingChineseChars()
408
    {
409
        $validContexts = array();
410
        $validContexts[] = array("我的电话号码是", "");
411
        $validContexts[] = array("", "是我的电话号码");
412
        $validContexts[] = array("请拨打", "我在明天");
413
414
        // Numbers should be considered valid, since they are surrounded by Chinese.
415
        $this->findMatchesInContexts($validContexts, true, true);
416
    }
417
418
    public function testMatchesWithSurroundingPunctuation()
419
    {
420
        $validContexts = array();
421
        $validContexts[] = array("My number-", ""); // At end of text
422
        $validContexts[] = array("", ".Nice day."); // At start of text
423
        $validContexts[] = array("Tel:", "."); // Punctuation surrounds number.
424
        $validContexts[] = array("Tel: ", " on Saturdays."); // White-space is also fine.
425
426
        // Numbers should be considered valid, since they are surrounded by punctuation.
427
        $this->findMatchesInContexts($validContexts, true, true);
428
    }
429
430
    public function testMatchesMultiplePhoneNumbersSeparatedByPhoneNumberPunctuation()
431
    {
432
        $text = "Call 650-253-4561 -- 455-234-3451";
433
        $region = RegionCode::US;
434
435
        $number1 = new PhoneNumber();
436
        $number1->setCountryCode($this->phoneUtil->getCountryCodeForRegion($region));
437
        $number1->setNationalNumber(6502534561);
438
        $match1 = new PhoneNumberMatch(5, "650-253-4561", $number1);
439
440
        $number2 = new PhoneNumber();
441
        $number2->setCountryCode($this->phoneUtil->getCountryCodeForRegion($region));
442
        $number2->setNationalNumber(4552343451);
443
        $match2 = new PhoneNumberMatch(21, "455-234-3451", $number2);
444
445
        $matches = $this->phoneUtil->findNumbers($text, $region);
446
447
        $matches->next();
448
        $this->assertEquals($match1, $matches->current());
449
450
        $matches->next();
451
        $this->assertEquals($match2, $matches->current());
452
    }
453
454
    public function testDoesNotMatchMultiplePhoneNumbersSeparatedWithNoWhiteSpace()
455
    {
456
        // No white-space found between numbers - neither is found.
457
        $text = "Call 650-253-4561--455-234-3451";
458
        $region = RegionCode::US;
459
460
        $this->assertTrue($this->hasNoMatches($this->phoneUtil->findNumbers($text, $region)));
461
    }
462
463
    /**
464
     * Strings with number-like things that shouldn't be found under any level.
465
     * @return array
466
     */
467
    public function dataImpossibleCases()
468
    {
469
        return array(
470
            array("12345", RegionCode::US),
471
            array("23456789", RegionCode::US),
472
            array("234567890112", RegionCode::US),
473
            array("650+253+1234", RegionCode::US),
474
            array("3/10/1984", RegionCode::CA),
475
            array("03/27/2011", RegionCode::US),
476
            array("31/8/2011", RegionCode::US),
477
            array("1/12/2011", RegionCode::US),
478
            array("10/12/82", RegionCode::DE),
479
            array("650x2531234", RegionCode::US),
480
            array("2012-01-02 08:00", RegionCode::US),
481
            array("2012/01/02 08:00", RegionCode::US),
482
            array("20120102 08:00", RegionCode::US),
483
            array("2014-04-12 04:04 PM", RegionCode::US),
484
            array("2014-04-12 &nbsp;04:04 PM", RegionCode::US),
485
            array("2014-04-12 &nbsp;04:04 PM", RegionCode::US),
486
            array("2014-04-12  04:04 PM", RegionCode::US),
487
        );
488
    }
489
490
    /**
491
     * Strings with number-like things that should only be found under "possible".
492
     * @return array
493
     */
494
    public function dataPossibleOnlyCases()
495
    {
496
        return array(
497
            // US numbers cannot start with 7 in the test metadata to be valid.
498
            array("7121115678", RegionCode::US),
499
            // 'X' should not be found in numbers at leniencies stricter than POSSIBLE, unless it represents
500
            // a carrier code or extension.
501
            array("1650 x 253 - 1234", RegionCode::US),
502
            array("650 x 253 - 1234", RegionCode::US),
503
            array("6502531x234", RegionCode::US),
504
            array("(20) 3346 1234", RegionCode::GB),  // Non-optional NP omitted
505
        );
506
    }
507
508
    /**
509
     * Strings with number-like things that should only be found up to and including the "valid"
510
     * leniency level.
511
     * @return array
512
     */
513
    public function dataValidCases()
514
    {
515
        return array(
516
            array("65 02 53 00 00", RegionCode::US),
517
            array("6502 538365", RegionCode::US),
518
            array("650//253-1234", RegionCode::US),  // 2 slashes are illegal at higher levels
519
            array("650/253/1234", RegionCode::US),
520
            array("9002309. 158", RegionCode::US),
521
            array("12 7/8 - 14 12/34 - 5", RegionCode::US),
522
            array("12.1 - 23.71 - 23.45", RegionCode::US),
523
            array("800 234 1 111x1111", RegionCode::US),
524
            array("1979-2011 100", RegionCode::US),
525
            array("+494949-4-94", RegionCode::DE),  // National number in wrong format
526
            array("4156666-777", RegionCode::US),
527
            array("2012-0102 08", RegionCode::US),  // Very strange formatting.
528
            array("2012-01-02 08", RegionCode::US),
529
            // Breakdown assistance number with unexpected formatting.
530
            array("1800-1-0-10 22", RegionCode::AU),
531
            array("030-3-2 23 12 34", RegionCode::DE),
532
            array("03 0 -3 2 23 12 34", RegionCode::DE),
533
            array("(0)3 0 -3 2 23 12 34", RegionCode::DE),
534
            array("0 3 0 -3 2 23 12 34", RegionCode::DE),
535
        );
536
    }
537
538
    /**
539
     * Strings with number-like things that should only be found up to and including the
540
     * "strict_grouping" leniency level.
541
     * @return array
542
     */
543
    public function dataStrictGroupingCases()
544
    {
545
        return array(
546
            array("(415) 6667777", RegionCode::US),
547
            array("415-6667777", RegionCode::US),
548
            // Should be found by strict grouping but not exact grouping, as the last two groups are
549
            // formatted together as a block.
550
            array("0800-2491234", RegionCode::DE),
551
            // Doesn't match any formatting in the test file, but almost matches an alternate format (the
552
            // last two groups have been squashed together here).
553
            array("0900-1 123123", RegionCode::DE),
554
            array("(0)900-1 123123", RegionCode::DE),
555
            array("0 900-1 123123", RegionCode::DE),
556
            // NDC also found as part of the country calling code; this shouldn't ruin the grouping
557
            // expectations.
558
            array("+33 3 34 2312", RegionCode::FR),
559
        );
560
    }
561
562
    /**
563
     * Strings with number-like things that should be found at all levels.
564
     * @return array
565
     */
566
    public function dataExactGroupingCases()
567
    {
568
        return array(
569
            array("4156667777", RegionCode::US),
570
            array("415-666-7777", RegionCode::US),
571
            array("4156667777", RegionCode::US),
572
            array("4156667777 x 123", RegionCode::US),
573
            array("415-666-7777", RegionCode::US),
574
            array("415/666-7777", RegionCode::US),
575
            array("415-666-7777 ext. 503", RegionCode::US),
576
            array("1 415 666 7777 x 123", RegionCode::US),
577
            array("+1 415-666-7777", RegionCode::US),
578
            array("+494949 49", RegionCode::DE),
579
            array("+49-49-34", RegionCode::DE),
580
            array("+49-4931-49", RegionCode::DE),
581
            array("04931-49", RegionCode::DE),  // With National Prefix
582
            array("+49-494949", RegionCode::DE),  // One group with country code
583
            array("+49-494949 ext. 49", RegionCode::DE),
584
            array("+49494949 ext. 49", RegionCode::DE),
585
            array("0494949", RegionCode::DE),
586
            array("0494949 ext. 49", RegionCode::DE),
587
            array("01 (33) 3461 2234", RegionCode::MX),  // Optional NP present
588
            array("(33) 3461 2234", RegionCode::MX),  // Optional NP omitted
589
            array("1800-10-10 22", RegionCode::AU),  // Breakdown assistance number.
590
            // Doesn't match any formatting in the test file, but matches an alternate format exactly.
591
            array("0900-1 123 123", RegionCode::DE),
592
            array("(0)900-1 123 123", RegionCode::DE),
593
            array("0 900-1 123 123", RegionCode::DE),
594
            array("+33 3 34 23 12", RegionCode::FR),
595
        );
596
    }
597
598
    public function data_testMatchesWithPossibleLeniency()
599
    {
600
        return $this->dataStrictGroupingCases()
601
        + $this->dataExactGroupingCases()
602
        + $this->dataValidCases()
603
        + $this->dataPossibleOnlyCases();
604
    }
605
606
    /**
607
     * @param string $rawString
608
     * @param string $region
609
     * @dataProvider data_testMatchesWithPossibleLeniency
610
     */
611
    public function testMatchesWithPossibleLeniency($rawString, $region)
612
    {
613
        $this->doTestNumberMatchesForLeniency($rawString, $region, Leniency::POSSIBLE());
614
    }
615
616
    /**
617
     * @param string $rawString
618
     * @param string $region
619
     * @dataProvider dataImpossibleCases
620
     */
621
    public function testNonMatchesWithPossibleLeniency($rawString, $region)
622
    {
623
        $this->doTestNumberNonMatchesForLeniency($rawString, $region, Leniency::POSSIBLE());
624
    }
625
626
    public function data_testMatchesWithValidLeniency()
627
    {
628
        return $this->dataStrictGroupingCases()
629
        + $this->dataExactGroupingCases()
630
        + $this->dataValidCases();
631
    }
632
633
    /**
634
     * @param string $rawString
635
     * @param string $region
636
     * @dataProvider data_testMatchesWithValidLeniency
637
     */
638
    public function testMatchesWithValidLeniency($rawString, $region)
639
    {
640
        $this->doTestNumberMatchesForLeniency($rawString, $region, Leniency::VALID());
641
    }
642
643
    public function data_testNonMatchesWithValidLeniency()
644
    {
645
        return $this->dataImpossibleCases()
646
            + $this->dataPossibleOnlyCases();
647
    }
648
649
    /**
650
     * @param $rawString
651
     * @param $region
652
     * @dataProvider data_testNonMatchesWithValidLeniency
653
     */
654
    public function testNonMatchesWithValidLeniency($rawString, $region)
655
    {
656
        $this->doTestNumberNonMatchesForLeniency($rawString, $region, Leniency::VALID());
657
    }
658
659
    public function data_testMatchesWithStrictGroupingLeniency()
660
    {
661
        return $this->dataStrictGroupingCases()
662
            + $this->dataExactGroupingCases();
663
    }
664
665
    /**
666
     * @param string $rawString
667
     * @param string $region
668
     * @dataProvider data_testMatchesWithStrictGroupingLeniency
669
     */
670
    public function testMatchesWithStrictGroupingLeniency($rawString, $region)
671
    {
672
        $this->doTestNumberMatchesForLeniency($rawString, $region, Leniency::STRICT_GROUPING());
673
    }
674
675
    public function data_testNonMatchesWithStrictGroupLeniency()
676
    {
677
        return $this->dataImpossibleCases()
678
            + $this->dataPossibleOnlyCases()
679
            + $this->dataValidCases();
680
    }
681
682
    /**
683
     * @param string $rawString
684
     * @param string $region
685
     * @dataProvider data_testNonMatchesWithStrictGroupLeniency
686
     */
687
    public function testNonMatchesWithStrictGroupLeniency($rawString, $region)
688
    {
689
        $this->doTestNumberNonMatchesForLeniency($rawString, $region, Leniency::STRICT_GROUPING());
690
    }
691
692
    /**
693
     * @param string $rawString
694
     * @param string $region
695
     * @dataProvider dataExactGroupingCases
696
     */
697
    public function testMatchesWithExactGroupingLeniency($rawString, $region)
698
    {
699
        $this->doTestNumberMatchesForLeniency($rawString, $region, Leniency::EXACT_GROUPING());
700
    }
701
702
    public function data_testNonMatchesExactGroupLeniency()
703
    {
704
        return $this->dataImpossibleCases()
705
            + $this->dataPossibleOnlyCases()
706
            + $this->dataValidCases()
707
            + $this->dataStrictGroupingCases();
708
    }
709
710
    /**
711
     * @param string $rawString
712
     * @param string $region
713
     * @dataProvider data_testNonMatchesExactGroupLeniency
714
     */
715
    public function testNonMatchesExactGroupLeniency($rawString, $region)
716
    {
717
        $this->doTestNumberNonMatchesForLeniency($rawString, $region, Leniency::EXACT_GROUPING());
718
    }
719
720
    protected function doTestNumberMatchesForLeniency($string, $region, Leniency\AbstractLeniency $leniency)
721
    {
722
        $iterator = $this->findNumbersForLeniency($string, $region, $leniency);
723
724
        $iterator->next();
725
        $match = $iterator->current();
726
727
        $this->assertNotNull($match, "No match found in {$string} ({$region}) for leniency {$leniency}");
728
        $this->assertEquals($string, $match->rawString(), "Found wrong match in test {$string} ({$region}). Found {$match->rawString()}");
729
    }
730
731
    protected function doTestNumberNonMatchesForLeniency($string, $region, Leniency\AbstractLeniency $leniency)
732
    {
733
        $iterator = $this->findNumbersForLeniency($string, $region, $leniency);
734
735
        $iterator->next();
736
        $match = $iterator->current();
737
738
        $this->assertNull($match, "Match found in {$string} ({$region}) for leniency {$leniency}");
739
    }
740
741
    /**
742
     * Helper method which tests the contexts provided and ensures that:
743
     * -- if isValid is true, they all find a test number inserted in the middle when leniency of
744
     *  matching is set to VALID; else no test number should be extracted at that leniency level
745
     * -- if isPossible is true, they all find a test number inserted in the middle when leniency of
746
     *  matching is set to POSSIBLE; else no test number should be extracted at that leniency level
747
     *
748
     *
749
     * @param array $contexts
750
     * @param bool $isValid
751
     * @param bool $isPossible
752
     * @param string $region
753
     * @param string $number
754
     */
755
    protected function findMatchesInContexts($contexts, $isValid, $isPossible, $region = RegionCode::US, $number = "415-666-7777")
756
    {
757
        if ($isValid) {
758
            $this->doTestInContext($number, $region, $contexts, Leniency::VALID());
759
        } else {
760
            foreach ($contexts as $context) {
761
                $text = $context[0] . $number . $context[1];
762
                $this->assertTrue($this->hasNoMatches($this->phoneUtil->findNumbers($text, $region)),
763
                    "Should not have found a number in {$text}");
764
            }
765
        }
766
767
        if ($isPossible) {
768
            $this->doTestInContext($number, $region, $contexts, Leniency::POSSIBLE());
769
        } else {
770
            foreach ($contexts as $context) {
771
                $text = $context[0] . $number . $context[1];
772
                $this->assertTrue($this->hasNoMatches($this->phoneUtil->findNumbers($text, $region)),
773
                    "Should not have found a number in {$text}");
774
            }
775
        }
776
    }
777
778
    public function testNonMatchingBracketsAreInvalid()
779
    {
780
        // The digits up to the ", " form a valid US number, but it shouldn't be matched as one since
781
        // there was a non-matching bracket present.
782
        $this->assertTrue($this->hasNoMatches($this->phoneUtil->findNumbers(
783
            "80.585 [79.964, 81.191]", RegionCode::US)));
784
785
        // The trailing "]" is thrown away before parsing, so the resultant number, while a valid US
786
        // number, does not have matching brackets.
787
        $this->assertTrue($this->hasNoMatches($this->phoneUtil->findNumbers(
788
            "80.585 [79.964]", RegionCode::US)));
789
790
        $this->assertTrue($this->hasNoMatches($this->phoneUtil->findNumbers(
791
            "80.585 ((79.964)", RegionCode::US)));
792
793
        // This case has too many sets of brackets to be valid.
794
        $this->assertTrue($this->hasNoMatches($this->phoneUtil->findNumbers(
795
            "(80).(585) (79).(9)64", RegionCode::US)));
796
    }
797
798
    public function testNoMatchIfRegionIsNull()
799
    {
800
        // Fail on non-international prefix if region code is null.
801
        $this->assertTrue($this->hasNoMatches($this->phoneUtil->findNumbers(
802
            "Random text body - number is 0331 6005, see you there", null)));
803
    }
804
805
    public function testNoMatchInEmptyString()
806
    {
807
        $this->assertTrue($this->hasNoMatches($this->phoneUtil->findNumbers("", RegionCode::US)));
808
        $this->assertTrue($this->hasNoMatches($this->phoneUtil->findNumbers("  ", RegionCode::US)));
809
    }
810
811
    public function testNoMatchIfNoNumber()
812
    {
813
        $this->assertTrue($this->hasNoMatches($this->phoneUtil->findNumbers(
814
            "Random text body - number is foobar, see you there", RegionCode::US)));
815
    }
816
817
    public function testSequences()
818
    {
819
        // Test multiple occurrences.
820
        $text = "Call 033316005  or 032316005!";
821
        $region = RegionCode::NZ;
822
823
        $number1 = new PhoneNumber();
824
        $number1->setCountryCode($this->phoneUtil->getCountryCodeForRegion($region));
825
        $number1->setNationalNumber(33316005);
826
        $match1 = new PhoneNumberMatch(5, "033316005", $number1);
827
828
        $number2 = new PhoneNumber();
829
        $number2->setCountryCode($this->phoneUtil->getCountryCodeForRegion($region));
830
        $number2->setNationalNumber(32316005);
831
        $match2 = new PhoneNumberMatch(19, "032316005", $number2);
832
833
        $matches = $this->phoneUtil->findNumbers($text, $region, Leniency::POSSIBLE());
834
835
        $matches->next();
836
        $this->assertEquals($match1, $matches->current());
837
838
        $matches->next();
839
        $this->assertEquals($match2, $matches->current());
840
    }
841
842
    public function testNullInput()
843
    {
844
        $this->assertTrue($this->hasNoMatches($this->phoneUtil->findNumbers(null, RegionCode::US)));
845
        $this->assertTrue($this->hasNoMatches($this->phoneUtil->findNumbers(null, null)));
846
    }
847
848
    public function testMaxMatches()
849
    {
850
        // Set up text with 100 valid phone numbers.
851
        $numbers = str_repeat("My info: 415-666-7777,", 100);
852
853
        // Matches all 100. Max only applies to failed cases.
854
        $number = $this->phoneUtil->parse("+14156667777", null);
855
        $expected = array_fill(0, 100, $number);
856
857
        $iterable = $this->phoneUtil->findNumbers($numbers, RegionCode::US, Leniency::VALID(), 10);
858
        $actual = array();
859
        foreach ($iterable as $match) {
860
            $actual[] = $match->number();
861
        }
862
863
        $this->assertEquals($expected, $actual);
864
    }
865
866
    public function testMaxMatchesInvalid()
867
    {
868
        // Set up text with 10 invalid phone numbers followed by 100 valid.
869
        $numbers = "";
870
        for ($i = 0; $i < 10; $i++) {
871
            $numbers .= "My address is 949-8945-0";
872
        }
873
        for ($i = 0; $i < 100; $i++) {
874
            $numbers .= "My info: 415-666-7777,";
875
        }
876
877
        $iterable = $this->phoneUtil->findNumbers($numbers, RegionCode::US, Leniency::VALID(), 10);
878
        $iterable->next();
879
        $this->assertNull($iterable->current());
880
    }
881
882
    public function testMaxMatchesMixed()
883
    {
884
        // Set up text with 100 valid numbers inside an invalid number.
885
        $numbers = "";
886
        for ($i = 0; $i < 100; $i++) {
887
            $numbers .= "My info: 415-666-7777 123 fake street";
888
        }
889
890
        // Only matches the first 10 despite there being 100 numbers due to max matches
891
        $number = $this->phoneUtil->parse("+14156667777", null);
892
        $expected = array_fill(0, 10, $number);
893
894
        $iterable = $this->phoneUtil->findNumbers($numbers, RegionCode::US, Leniency::VALID(), 10);
895
896
        $actual = array();
897
        foreach ($iterable as $match) {
898
            $actual[] = $match->number();
899
        }
900
901
        $this->assertEquals($expected, $actual);
902
    }
903
904
    public function testNonPlusPrefixedNumbersNotFoundForInvalidRegion()
905
    {
906
        // Does not start with a "+", we won't match it.
907
        $iterable = $this->phoneUtil->findNumbers("1 456 764 156", RegionCode::ZZ);
908
909
        $iterable->next();
910
        $this->assertFalse($iterable->valid());
911
    }
912
913
    public function testEmptyIteration()
914
    {
915
        $iterable = $this->phoneUtil->findNumbers("", RegionCode::ZZ);
916
917
        $iterable->next();
918
        $this->assertFalse($iterable->valid());
919
    }
920
921
    public function testSingleIteration()
922
    {
923
        $iterable = $this->phoneUtil->findNumbers("+14156667777", RegionCode::ZZ);
924
925
        $iterable->next();
926
        $this->assertTrue($iterable->valid());
927
        $this->assertNotNull($iterable->current());
928
929
        $iterable->next();
930
        $this->assertFalse($iterable->valid());
931
        $this->assertNull($iterable->current());
932
    }
933
934
    public function testDoubleIteration()
935
    {
936
        $iterable = $this->phoneUtil->findNumbers("+14156667777 foobar +14156667777 ", RegionCode::ZZ);
937
938
        $iterable->next();
939
        $this->assertTrue($iterable->valid());
940
        $this->assertNotNull($iterable->current());
941
942
        $iterable->next();
943
        $this->assertTrue($iterable->valid());
944
        $this->assertNotNull($iterable->current());
945
946
        $iterable->next();
947
        $this->assertFalse($iterable->valid());
948
        $this->assertNull($iterable->current());
949
    }
950
951
    /**
952
     * Asserts that the expected match is non-null, and that the raw string and expected
953
     * proto buffer are set appropriately
954
     *
955
     * @param PhoneNumberMatch $match
956
     * @param string $text
957
     * @param string $number
958
     * @param string $region
959
     */
960
    protected function assertMatchProperties(PhoneNumberMatch $match, $text, $number, $region)
961
    {
962
        $expectedResult = $this->phoneUtil->parse($number, $region);
963
        $this->assertNotNull($match, "Did not find a number in {$text}; expected {$number}");
964
        $this->assertEquals($expectedResult, $match->number());
965
        $this->assertEquals($number, $match->rawString());
966
    }
967
968
    /**
969
     * Asserts that another number can be found in $text starting at $index, and that its
970
     * corresponding range in $start to $end
971
     *
972
     * @param string $text
973
     * @param int $index
974
     * @param int $start
975
     * @param int $end
976
     */
977
    protected function assertEqualRange($text, $index, $start, $end)
978
    {
979
        $sub = mb_substr($text, $index, mb_strlen($text) - $index);
980
        $matches = $this->phoneUtil->findNumbers($sub, RegionCode::NZ, Leniency::POSSIBLE(), PHP_INT_MAX);
981
982
        $matches->next();
983
        $this->assertTrue($matches->valid());
984
985
        $match = $matches->current();
986
987
        $this->assertEquals($start - $index, $match->start());
988
        $this->assertEquals($end - $index, $match->end());
989
        $this->assertEquals(mb_substr($sub, $match->start(), $match->end() - $match->start()), $match->rawString());
990
    }
991
992
    /**
993
     * Tests numbers found by PhoneNumberUtil->findNumbers in various
994
     * textual contexts
995
     *
996
     * @param string $number The number to test
997
     * @param string $defaultCountry The corresponding region code
998
     */
999
    protected function doTestFindInContext($number, $defaultCountry)
1000
    {
1001
        $this->findPossibleInContext($number, $defaultCountry);
1002
1003
        $parsed = $this->phoneUtil->parse($number, $defaultCountry);
1004
        if ($this->phoneUtil->isValidNumber($parsed)) {
1005
            $this->findValidInContext($number, $defaultCountry);
1006
        }
1007
    }
1008
1009
    /**
1010
     * Tests valid numbers in contexts that should pass for Leniency::POSSIBLE()
1011
     * @param $number
1012
     * @param $defaultCountry
1013
     */
1014
    protected function findPossibleInContext($number, $defaultCountry)
1015
    {
1016
        $contextPairs = array();
1017
        $contextPairs[] = array("", ""); // no content
1018
        $contextPairs[] = array("   ", "\t");  // whitespace only
1019
        $contextPairs[] = array("Hello ", ""); // no context at end
1020
        $contextPairs[] = array("", " to call me!"); // no context at start
1021
        $contextPairs[] = array("Hi there, call ", " to reach me!"); // no context at start
1022
        $contextPairs[] = array("Hi here, call ", " , or don't"); // with commas
1023
        // Three examples without whitespace around the number
1024
        $contextPairs[] = array("Hi call", "");
1025
        $contextPairs[] = array("", "forme");
1026
        $contextPairs[] = array("Hi call", "forme");
1027
        // With other small numbers.
1028
        $contextPairs[] = array("It's cheap! Call ", " before 6:30");
1029
        // With a second number later.
1030
        $contextPairs[] = array("Call ", " or +1800-123-4567!");
1031
        $contextPairs[] = array("Call me on June 2 at", ""); // with a Month-Day date
1032
        // With publication pages
1033
        $contextPairs[] = array("As quoted by Alfonso 12-15 (2009), you may call me at ", "");
1034
        $contextPairs[] = array("As quoted by Alfonso et al. 12-15 (2009), you may call me at ", "");
1035
        // With dates, written in the American style.
1036
        $contextPairs[] = array("As I said on 03/10/2011, you may call be at ", "");
1037
        // With trailing numbers after a comma. The 45 should not be considered an extension
1038
        $contextPairs[] = array("", ", 45 days a year");
1039
        // When matching we don't consider semicolon along with legitimate extension symbol to indicate
1040
        // an extension. The 7246433 should not be considered an extension.
1041
        $contextPairs[] = array("", ";x 7246433");
1042
        // With a postfix stripped off as it looks like the start of another number.
1043
        $contextPairs[] = array("Call ", "/x12 more");
1044
1045
        $this->doTestInContext($number, $defaultCountry, $contextPairs, Leniency::POSSIBLE());
1046
    }
1047
1048
    /**
1049
     * Tests valid numbers in contexts that fail for Leniency::POSSIBLE() but are valid for
1050
     * Leniency::VALID()
1051
     *
1052
     * @param string $number
1053
     * @param string $defaultCountry
1054
     */
1055
    protected function findValidInContext($number, $defaultCountry)
1056
    {
1057
        $contextPairs = array();
1058
        // With other small numbers
1059
        $contextPairs[] = array("It's only 9.99! Call ", " to buy");
1060
        // with a number Day.Month.Year date.
1061
        $contextPairs[] = array("Call me on 21.6.1984 at ", "");
1062
        // With a number Month/Day date.
1063
        $contextPairs[] = array("Call me on 06/21 at ", "");
1064
        // With a number Day.Month date.
1065
        $contextPairs[] = array("Call me on 21.6. at ", "");
1066
        // With a number Month/Day/Year date.
1067
        $contextPairs[] = array("Call me on 06/21/84 at ", "");
1068
1069
        $this->doTestInContext($number, $defaultCountry, $contextPairs, Leniency::VALID());
1070
    }
1071
1072
    protected function doTestInContext($number, $defaultCountry, $contextPairs, Leniency\AbstractLeniency $leniency)
1073
    {
1074
        foreach ($contextPairs as $context) {
1075
            $prefix = $context[0];
1076
            $text = $prefix . $number . $context[1];
1077
1078
            $start = mb_strlen($prefix);
1079
            $end = $start + mb_strlen($number);
1080
1081
            $iterator = $this->phoneUtil->findNumbers($text, $defaultCountry, $leniency, PHP_INT_MAX);
1082
1083
            $iterator->next();
1084
            $match = $iterator->current();
1085
            $this->assertNotNull($match, "Did not find number in '{$text}'; expected '{$number}'");
1086
1087
            $extracted = mb_substr($text, $match->start(), $match->end() - $match->start());
1088
            $this->assertEquals($start, $match->start(), "Unexpected phone region in '{$text}'; extracted '{$extracted}'");
1089
            $this->assertEquals($end, $match->end(), "Unexpected phone region in '{$text}'; extracted '{$extracted}'");
1090
            $this->assertEquals($number, $extracted);
1091
            $this->assertEquals($extracted, $match->rawString());
1092
1093
            $this->ensureTermination($text, $defaultCountry, $leniency);
1094
        }
1095
    }
1096
1097
    protected function ensureTermination($text, $defaultCountry, Leniency\AbstractLeniency $leniency)
1098
    {
1099
        $textLength = mb_strlen($text);
1100
        for ($index = 0; $index <= $textLength; $index++) {
1101
            $sub = mb_substr($text, $index);
1102
            $matches = "";
1103
            // Iterates over all matches.
1104
            foreach ($this->phoneUtil->findNumbers($sub, $defaultCountry, $leniency, PHP_INT_MAX) as $match) {
1105
                $matches .= ", " . $match;
1106
            }
1107
        }
1108
    }
1109
1110
    protected function findNumbersForLeniency($text, $defaultCountry, Leniency\AbstractLeniency $leniency)
1111
    {
1112
        return $this->phoneUtil->findNumbers($text, $defaultCountry, $leniency, PHP_INT_MAX);
1113
    }
1114
1115
    protected function hasNoMatches(PhoneNumberMatcher $match)
1116
    {
1117
        return !$match->valid();
1118
    }
1119
}
1120