1
0
mirror of https://github.com/nerzhul/ocsms.git synced 2025-06-07 16:06:15 +00:00

Updated phone formatter (#241)

* Add locale and libphonenumber libraries.

* Update country code information

Updated existing country codes, fixed incorrect NANP codes for member countries (as well as several UK based ones).

Also added in Country Name to ISO country code mapping array for use with libphonenumber.

* Convert phone number formatting to use libphonenumber

libphonenumber parses phone number more consistantly than the old regex's that mismatched number on a regular basis.
This commit is contained in:
Greg Ross 2018-06-26 03:49:22 -04:00 committed by Loïc Blot
parent d29e2b1f7f
commit 6e86c48486
1371 changed files with 636043 additions and 284 deletions

5
lib/composer.json Normal file
View File

@ -0,0 +1,5 @@
{
"require": {
"giggsey/libphonenumber-for-php": "^8.9"
}
}

View File

@ -8,6 +8,12 @@
* Reference: * Reference:
* [1] Country Codes: https://countrycode.org/ * [1] Country Codes: https://countrycode.org/
* *
* Note: The above country code list mistakenly references some countries as
* (code)+(exchance), so for example, the Cayman Islands is listed as
* "1-345", however it is really part of NANP and so it's country code
* is actually "1". The below entries correct this so that each country
* has a single country code.
*
* @author Loic Blot <loic.blot@unix-experience.fr> * @author Loic Blot <loic.blot@unix-experience.fr>
* @contributor: stagprom <https://github.com/stagprom/> * @contributor: stagprom <https://github.com/stagprom/>
* @copyright Loic Blot 2014-2017 * @copyright Loic Blot 2014-2017
@ -17,245 +23,488 @@ namespace OCA\OcSms\Lib;
class CountryCodes { class CountryCodes {
public static $codes = array( public static $codes = array(
"Afghanistan" => "+93", 'Afghanistan' => '+93',
"Albania" => "+355", 'Albania' => '+355',
"Algeria" => "+213", 'Algeria' => '+213',
"American Samoa" => "+1684", 'American Samoa' => '+1',
"Andorra" => "+376", 'Andorra' => '+376',
"Angola" => "+244", 'Angola' => '+244',
"Anguilla" => "+1264", 'Anguilla' => '+1',
"Antarctica" => "+672", 'Antarctica' => '+672',
"Antigua and Barbuda" => "+1268", 'Antigua and Barbuda' => '+1',
"Argentina" => "+54", 'Argentina' => '+54',
"Armenia" => "+374", 'Armenia' => '+374',
"Aruba" => "+297", 'Aruba' => '+297',
"Australia" => "+61", 'Australia' => '+61',
"Austria" => "+43", 'Austria' => '+43',
"Azerbaijan" => "+994", 'Azerbaijan' => '+994',
"Bahamas" => "+1242", 'Bahamas' => '+1',
"Bahrain" => "+973", 'Bahrain' => '+973',
"Bangladesh" => "+880", 'Bangladesh' => '+880',
"Barbados" => "+1246", 'Barbados' => '+1',
"Belarus" => "+375", 'Belarus' => '+375',
"Belgium" => "+32", 'Belgium' => '+32',
"Belize" => "+501", 'Belize' => '+501',
"Benin" => "+229", 'Benin' => '+229',
"Bermuda" => "+1441", 'Bermuda' => '+1',
"Bhutan" => "+975", 'Bhutan' => '+975',
"Bolivia" => "+591", 'Bolivia' => '+591',
"Bosnia and Herzegovina" => "+387", 'Bosnia and Herzegovina' => '+387',
"Botswana" => "+267", 'Botswana' => '+267',
"Brazil" => "+55", 'Brazil' => '+55',
"British Indian Ocean Territory" => "+246", 'British Indian Ocean Territory' => '+246',
"British Virgin Islands" => "+1284", 'British Virgin Islands' => '+1',
"Brunei" => "+673", 'Brunei' => '+673',
"Bulgaria" => "+359", 'Bulgaria' => '+359',
"Burkina Faso" => "+226", 'Burkina Faso' => '+226',
"Burundi" => "+257", 'Burundi' => '+257',
"Cambodia" => "+855", 'Cambodia' => '+855',
"Cameroon" => "+237", 'Cameroon' => '+237',
"Canada" => "+1", 'Canada' => '+1',
"Cape Verde" => "+238", 'Cape Verde' => '+238',
"Cayman Islands" => "+1345", 'Cayman Islands' => '+1',
"Central African Republic" => "+236", 'Central African Republic' => '+236',
"Chad" => "+235", 'Chad' => '+235',
"Chile" => "+56", 'Chile' => '+56',
"China" => "+86", 'China' => '+86',
"Christmas Island" => "+61", 'Christmas Island' => '+61',
"Cocos Islands" => "+61", 'Cocos Islands' => '+61',
"Colombia" => "+57", 'Colombia' => '+57',
"Comoros" => "+269", 'Comoros' => '+269',
"Cook Islands" => "+682", 'Cook Islands' => '+682',
"Costa Rica" => "+506", 'Costa Rica' => '+506',
"Croatia" => "+385", 'Croatia' => '+385',
"Cuba" => "+53", 'Cuba' => '+53',
"Curacao" => "+599", 'Curacao' => '+599',
"Cyprus" => "+357", 'Cyprus' => '+357',
"Czech Republic" => "+420", 'Czech Republic' => '+420',
"Democratic Republic of the Congo" => "+243", 'Democratic Republic of the Congo' => '+243',
"Denmark" => "+45", 'Denmark' => '+45',
"Djibouti" => "+253", 'Djibouti' => '+253',
"Dominica" => "+1767", 'Dominica' => '+1',
// "Dominican Republic" => "+1-809, +1-829, +1-849", 'Dominican Republic' => '+1',
"East Timor" => "+670", 'East Timor' => '+670',
"Ecuador" => "+593", 'Ecuador' => '+593',
"Egypt" => "+20", 'Egypt' => '+20',
"El Salvador" => "+503", 'El Salvador' => '+503',
"Equatorial Guinea" => "+240", 'Equatorial Guinea' => '+240',
"Eritrea" => "+291", 'Eritrea' => '+291',
"Estonia" => "+372", 'Estonia' => '+372',
"Ethiopia" => "+251", 'Ethiopia' => '+251',
"Falkland Islands" => "+500", 'Falkland Islands' => '+500',
"Faroe Islands" => "+298", 'Faroe Islands' => '+298',
"Fiji" => "+679", 'Fiji' => '+679',
"Finland" => "+358", 'Finland' => '+358',
"France" => "+33", 'France' => '+33',
"French Polynesia" => "+689", 'French Polynesia' => '+689',
"Gabon" => "+241", 'Gabon' => '+241',
"Gambia" => "+220", 'Gambia' => '+220',
"Georgia" => "+995", 'Georgia' => '+995',
"Germany" => "+49", 'Germany' => '+49',
"Ghana" => "+233", 'Ghana' => '+233',
"Gibraltar" => "+350", 'Gibraltar' => '+350',
"Greece" => "+30", 'Greece' => '+30',
"Greenland" => "+299", 'Greenland' => '+299',
"Grenada" => "+1473", 'Grenada' => '+1',
"Guam" => "+1671", 'Guam' => '+1',
"Guatemala" => "+502", 'Guatemala' => '+502',
"Guernsey" => "+441481", 'Guernsey' => '+44',
"Guinea" => "+224", 'Guinea' => '+224',
"Guinea-Bissau" => "+245", 'Guinea-Bissau' => '+245',
"Guyana" => "+592", 'Guyana' => '+592',
"Haiti" => "+509", 'Haiti' => '+509',
"Honduras" => "+504", 'Honduras' => '+504',
"Hong Kong" => "+852", 'Hong Kong' => '+852',
"Hungary" => "+36", 'Hungary' => '+36',
"Iceland" => "+354", 'Iceland' => '+354',
"India" => "+91", 'India' => '+91',
"Indonesia" => "+62", 'Indonesia' => '+62',
"Iran" => "+98", 'Iran' => '+98',
"Iraq" => "+964", 'Iraq' => '+964',
"Ireland" => "+353", 'Ireland' => '+353',
"Isle of Man" => "+441624", 'Isle of Man' => '+44',
"Israel" => "+972", 'Israel' => '+972',
"Italy" => "+39", 'Italy' => '+39',
"Ivory Coast" => "+225", 'Ivory Coast' => '+225',
"Jamaica" => "+1876", 'Jamaica' => '+1',
"Japan" => "+81", 'Japan' => '+81',
"Jersey" => "+441534", 'Jersey' => '+44',
"Jordan" => "+962", 'Jordan' => '+962',
"Kazakhstan" => "+7", 'Kazakhstan' => '+7',
"Kenya" => "+254", 'Kenya' => '+254',
"Kiribati" => "+686", 'Kiribati' => '+686',
"Kosovo" => "+383", 'Kosovo' => '+383',
"Kuwait" => "+965", 'Kuwait' => '+965',
"Kyrgyzstan" => "+996", 'Kyrgyzstan' => '+996',
"Laos" => "+856", 'Laos' => '+856',
"Latvia" => "+371", 'Latvia' => '+371',
"Lebanon" => "+961", 'Lebanon' => '+961',
"Lesotho" => "+266", 'Lesotho' => '+266',
"Liberia" => "+231", 'Liberia' => '+231',
"Libya" => "+218", 'Libya' => '+218',
"Liechtenstein" => "+423", 'Liechtenstein' => '+423',
"Lithuania" => "+370", 'Lithuania' => '+370',
"Luxembourg" => "+352", 'Luxembourg' => '+352',
"Macao" => "+853", 'Macau' => '+853',
"Macedonia" => "+389", 'Macedonia' => '+389',
"Madagascar" => "+261", 'Madagascar' => '+261',
"Malawi" => "+265", 'Malawi' => '+265',
"Malaysia" => "+60", 'Malaysia' => '+60',
"Maldives" => "+960", 'Maldives' => '+960',
"Mali" => "+223", 'Mali' => '+223',
"Malta" => "+356", 'Malta' => '+356',
"Marshall Islands" => "+692", 'Marshall Islands' => '+692',
"Mauritania" => "+222", 'Mauritania' => '+222',
"Mauritius" => "+230", 'Mauritius' => '+230',
"Mayotte" => "+262", 'Mayotte' => '+262',
"Mexico" => "+52", 'Mexico' => '+52',
"Micronesia" => "+691", 'Micronesia' => '+691',
"Moldova" => "+373", 'Moldova' => '+373',
"Monaco" => "+377", 'Monaco' => '+377',
"Mongolia" => "+976", 'Mongolia' => '+976',
"Montenegro" => "+382", 'Montenegro' => '+382',
"Montserrat" => "+1664", 'Montserrat' => '+1',
"Morocco" => "+212", 'Morocco' => '+212',
"Mozambique" => "+258", 'Mozambique' => '+258',
"Myanmar" => "+95", 'Myanmar' => '+95',
"Namibia" => "+264", 'Namibia' => '+264',
"Nauru" => "+674", 'Nauru' => '+674',
"Nepal" => "+977", 'Nepal' => '+977',
"Netherlands" => "+31", 'Netherlands' => '+31',
"Netherlands Antilles" => "+599", 'Netherlands Antilles' => '+599',
"New Caledonia" => "+687", 'New Caledonia' => '+687',
"New Zealand" => "+64", 'New Zealand' => '+64',
"Nicaragua" => "+505", 'Nicaragua' => '+505',
"Niger" => "+227", 'Niger' => '+227',
"Nigeria" => "+234", 'Nigeria' => '+234',
"Niue" => "+683", 'Niue' => '+683',
"North Korea" => "+850", 'North Korea' => '+850',
"Northern Mariana Islands" => "+1670", 'Northern Mariana Islands' => '+1',
"Norway" => "+47", 'Norway' => '+47',
"Oman" => "+968", 'Oman' => '+968',
"Pakistan" => "+92", 'Pakistan' => '+92',
"Palau" => "+680", 'Palau' => '+680',
"Palestine" => "+970", 'Palestine' => '+970',
"Panama" => "+507", 'Panama' => '+507',
"Papua New Guinea" => "+675", 'Papua New Guinea' => '+675',
"Paraguay" => "+595", 'Paraguay' => '+595',
"Peru" => "+51", 'Peru' => '+51',
"Philippines" => "+63", 'Philippines' => '+63',
"Pitcairn" => "+64", 'Pitcairn' => '+64',
"Poland" => "+48", 'Poland' => '+48',
"Portugal" => "+351", 'Portugal' => '+351',
// "Puerto Rico" => "+1-787, +1-939", 'Puerto Rico' => '+1',
"Qatar" => "+974", 'Qatar' => '+974',
"Republic of the Congo" => "+242", 'Republic of the Congo' => '+242',
"Reunion" => "+262", 'Reunion' => '+262',
"Romania" => "+40", 'Romania' => '+40',
"Russia" => "+7", 'Russia' => '+7',
"Rwanda" => "+250", 'Rwanda' => '+250',
"Saint Barthelemy" => "+590", 'Saint Barthelemy' => '+590',
"Saint Helena" => "+290", 'Saint Helena' => '+290',
"Saint Kitts and Nevis" => "+1869", 'Saint Kitts and Nevis' => '+1',
"Saint Lucia" => "+1758", 'Saint Lucia' => '+1',
"Saint Martin" => "+590", 'Saint Martin' => '+590',
"Saint Pierre and Miquelon" => "+508", 'Saint Pierre and Miquelon' => '+508',
"Saint Vincent and the Grenadines" => "+1784", 'Saint Vincent and the Grenadines' => '+1',
"Samoa" => "+685", 'Samoa' => '+685',
"San Marino" => "+378", 'San Marino' => '+378',
"Sao Tome and Principe" => "+239", 'Sao Tome and Principe' => '+239',
"Saudi Arabia" => "+966", 'Saudi Arabia' => '+966',
"Senegal" => "+221", 'Senegal' => '+221',
"Serbia" => "+381", 'Serbia' => '+381',
"Seychelles" => "+248", 'Seychelles' => '+248',
"Sierra Leone" => "+232", 'Sierra Leone' => '+232',
"Singapore" => "+65", 'Singapore' => '+65',
"Sint Maarten" => "+1721", 'Sint Maarten' => '+1',
"Slovakia" => "+421", 'Slovakia' => '+421',
"Slovenia" => "+386", 'Slovenia' => '+386',
"Solomon Islands" => "+677", 'Solomon Islands' => '+677',
"Somalia" => "+252", 'Somalia' => '+252',
"South Africa" => "+27", 'South Africa' => '+27',
"South Korea" => "+82", 'South Korea' => '+82',
"South Sudan" => "+211", 'South Sudan' => '+211',
"Spain" => "+34", 'Spain' => '+34',
"Sri Lanka" => "+94", 'Sri Lanka' => '+94',
"Sudan" => "+249", 'Sudan' => '+249',
"Suriname" => "+597", 'Suriname' => '+597',
"Svalbard and Jan Mayen" => "+47", 'Svalbard and Jan Mayen' => '+47',
"Swaziland" => "+268", 'Swaziland' => '+268',
"Sweden" => "+46", 'Sweden' => '+46',
"Switzerland" => "+41", 'Switzerland' => '+41',
"Syria" => "+963", 'Syria' => '+963',
"Taiwan" => "+886", 'Taiwan' => '+886',
"Tajikistan" => "+992", 'Tajikistan' => '+992',
"Tanzania" => "+255", 'Tanzania' => '+255',
"Thailand" => "+66", 'Thailand' => '+66',
"Togo" => "+228", 'Togo' => '+228',
"Tokelau" => "+690", 'Tokelau' => '+690',
"Tonga" => "+676", 'Tonga' => '+676',
"Trinidad and Tobago" => "+1868", 'Trinidad and Tobago' => '+1',
"Tunisia" => "+216", 'Tunisia' => '+216',
"Turkey" => "+90", 'Turkey' => '+90',
"Turkmenistan" => "+993", 'Turkmenistan' => '+993',
"Turks and Caicos Islands" => "+1649", 'Turks and Caicos Islands' => '+1',
"Tuvalu" => "+688", 'Tuvalu' => '+688',
"U.S. Virgin Islands" => "+1340", 'U.S. Virgin Islands' => '+1',
"Uganda" => "+256", 'Uganda' => '+256',
"Ukraine" => "+380", 'Ukraine' => '+380',
"United Arab Emirates" => "+971", 'United Arab Emirates' => '+971',
"United Kingdom" => "+44", 'United Kingdom' => '+44',
"United States" => "+1", 'United States' => '+1',
"Uruguay" => "+598", 'Uruguay' => '+598',
"Uzbekistan" => "+998", 'Uzbekistan' => '+998',
"Vanuatu" => "+678", 'Vanuatu' => '+678',
"Vatican" => "+379", 'Vatican' => '+379',
"Venezuela" => "+58", 'Venezuela' => '+58',
"Vietnam" => "+84", 'Vietnam' => '+84',
"Wallis and Futuna" => "+681", 'Wallis and Futuna' => '+681',
"Western Sahara" => "+212", 'Western Sahara' => '+212',
"Yemen" => "+967", 'Yemen' => '+967',
"Zambia" => "+260", 'Zambia' => '+260',
"Zimbabwe" => "+263", 'Zimbabwe' => '+263',
);
public static $countries = array(
'Afghanistan' => 'AF',
'Albania' => 'AL',
'Algeria' => 'DZ',
'American Samoa' => 'AS',
'Andorra' => 'AD',
'Angola' => 'AO',
'Anguilla' => 'AI',
'Antarctica' => 'AQ',
'Antigua and Barbuda' => 'AG',
'Argentina' => 'AR',
'Armenia' => 'AM',
'Aruba' => 'AW',
'Australia' => 'AU',
'Austria' => 'AT',
'Azerbaijan' => 'AZ',
'Bahamas' => 'BS',
'Bahrain' => 'BH',
'Bangladesh' => 'BD',
'Barbados' => 'BB',
'Belarus' => 'BY',
'Belgium' => 'BE',
'Belize' => 'BZ',
'Benin' => 'BJ',
'Bermuda' => 'BM',
'Bhutan' => 'BT',
'Bolivia' => 'BO',
'Bosnia and Herzegovina' => 'BA',
'Botswana' => 'BW',
'Brazil' => 'BR',
'British Indian Ocean Territory' => 'IO',
'British Virgin Islands' => 'VG',
'Brunei' => 'BN',
'Bulgaria' => 'BG',
'Burkina Faso' => 'BF',
'Burundi' => 'BI',
'Cambodia' => 'KH',
'Cameroon' => 'CM',
'Canada' => 'CA',
'Cape Verde' => 'CV',
'Cayman Islands' => 'KY',
'Central African Republic' => 'CF',
'Chad' => 'TD',
'Chile' => 'CL',
'China' => 'CN',
'Christmas Island' => 'CX',
'Cocos Islands' => 'CC',
'Colombia' => 'CO',
'Comoros' => 'KM',
'Cook Islands' => 'CK',
'Costa Rica' => 'CR',
'Croatia' => 'HR',
'Cuba' => 'CU',
'Curacao' => 'CW',
'Cyprus' => 'CY',
'Czech Republic' => 'CZ',
'Democratic Republic of the Congo' => 'CD',
'Denmark' => 'DK',
'Djibouti' => 'DJ',
'Dominica' => 'DM',
'Dominican Republic' => 'DO',
'East Timor' => 'TL',
'Ecuador' => 'EC',
'Egypt' => 'EG',
'El Salvador' => 'SV',
'Equatorial Guinea' => 'GQ',
'Eritrea' => 'ER',
'Estonia' => 'EE',
'Ethiopia' => 'ET',
'Falkland Islands' => 'FK',
'Faroe Islands' => 'FO',
'Fiji' => 'FJ',
'Finland' => 'FI',
'France' => 'FR',
'French Polynesia' => 'PF',
'Gabon' => 'GA',
'Gambia' => 'GM',
'Georgia' => 'GE',
'Germany' => 'DE',
'Ghana' => 'GH',
'Gibraltar' => 'GI',
'Greece' => 'GR',
'Greenland' => 'GL',
'Grenada' => 'GD',
'Guam' => 'GU',
'Guatemala' => 'GT',
'Guernsey' => 'GG',
'Guinea' => 'GN',
'Guinea-Bissau' => 'GW',
'Guyana' => 'GY',
'Haiti' => 'HT',
'Honduras' => 'HN',
'Hong Kong' => 'HK',
'Hungary' => 'HU',
'Iceland' => 'IS',
'India' => 'IN',
'Indonesia' => 'ID',
'Iran' => 'IR',
'Iraq' => 'IQ',
'Ireland' => 'IE',
'Isle of Man' => 'IM',
'Israel' => 'IL',
'Italy' => 'IT',
'Ivory Coast' => 'CI',
'Jamaica' => 'JM',
'Japan' => 'JP',
'Jersey' => 'JE',
'Jordan' => 'JO',
'Kazakhstan' => 'KZ',
'Kenya' => 'KE',
'Kiribati' => 'KI',
'Kosovo' => 'XK',
'Kuwait' => 'KW',
'Kyrgyzstan' => 'KG',
'Laos' => 'LA',
'Latvia' => 'LV',
'Lebanon' => 'LB',
'Lesotho' => 'LS',
'Liberia' => 'LR',
'Libya' => 'LY',
'Liechtenstein' => 'LI',
'Lithuania' => 'LT',
'Luxembourg' => 'LU',
'Macau' => 'MO',
'Macedonia' => 'MK',
'Madagascar' => 'MG',
'Malawi' => 'MW',
'Malaysia' => 'MY',
'Maldives' => 'MV',
'Mali' => 'ML',
'Malta' => 'MT',
'Marshall Islands' => 'MH',
'Mauritania' => 'MR',
'Mauritius' => 'MU',
'Mayotte' => 'YT',
'Mexico' => 'MX',
'Micronesia' => 'FM',
'Moldova' => 'MD',
'Monaco' => 'MC',
'Mongolia' => 'MN',
'Montenegro' => 'ME',
'Montserrat' => 'MS',
'Morocco' => 'MA',
'Mozambique' => 'MZ',
'Myanmar' => 'MM',
'Namibia' => 'NA',
'Nauru' => 'NR',
'Nepal' => 'NP',
'Netherlands' => 'NL',
'Netherlands Antilles' => 'AN',
'New Caledonia' => 'NC',
'New Zealand' => 'NZ',
'Nicaragua' => 'NI',
'Niger' => 'NE',
'Nigeria' => 'NG',
'Niue' => 'NU',
'North Korea' => 'KP',
'Northern Mariana Islands' => 'MP',
'Norway' => 'NO',
'Oman' => 'OM',
'Pakistan' => 'PK',
'Palau' => 'PW',
'Palestine' => 'PS',
'Panama' => 'PA',
'Papua New Guinea' => 'PG',
'Paraguay' => 'PY',
'Peru' => 'PE',
'Philippines' => 'PH',
'Pitcairn' => 'PN',
'Poland' => 'PL',
'Portugal' => 'PT',
'Puerto Rico' => 'PR',
'Qatar' => 'QA',
'Republic of the Congo' => 'CG',
'Reunion' => 'RE',
'Romania' => 'RO',
'Russia' => 'RU',
'Rwanda' => 'RW',
'Saint Barthelemy' => 'BL',
'Saint Helena' => 'SH',
'Saint Kitts and Nevis' => 'KN',
'Saint Lucia' => 'LC',
'Saint Martin' => 'MF',
'Saint Pierre and Miquelon' => 'PM',
'Saint Vincent and the Grenadines' => 'VC',
'Samoa' => 'WS',
'San Marino' => 'SM',
'Sao Tome and Principe' => 'ST',
'Saudi Arabia' => 'SA',
'Senegal' => 'SN',
'Serbia' => 'RS',
'Seychelles' => 'SC',
'Sierra Leone' => 'SL',
'Singapore' => 'SG',
'Sint Maarten' => 'SX',
'Slovakia' => 'SK',
'Slovenia' => 'SI',
'Solomon Islands' => 'SB',
'Somalia' => 'SO',
'South Africa' => 'ZA',
'South Korea' => 'KR',
'South Sudan' => 'SS',
'Spain' => 'ES',
'Sri Lanka' => 'LK',
'Sudan' => 'SD',
'Suriname' => 'SR',
'Svalbard and Jan Mayen' => 'SJ',
'Swaziland' => 'SZ',
'Sweden' => 'SE',
'Switzerland' => 'CH',
'Syria' => 'SY',
'Taiwan' => 'TW',
'Tajikistan' => 'TJ',
'Tanzania' => 'TZ',
'Thailand' => 'TH',
'Togo' => 'TG',
'Tokelau' => 'TK',
'Tonga' => 'TO',
'Trinidad and Tobago' => 'TT',
'Tunisia' => 'TN',
'Turkey' => 'TR',
'Turkmenistan' => 'TM',
'Turks and Caicos Islands' => 'TC',
'Tuvalu' => 'TV',
'U.S. Virgin Islands' => 'VI',
'Uganda' => 'UG',
'Ukraine' => 'UA',
'United Arab Emirates' => 'AE',
'United Kingdom' => 'GB',
'United States' => 'US',
'Uruguay' => 'UY',
'Uzbekistan' => 'UZ',
'Vanuatu' => 'VU',
'Vatican' => 'VA',
'Venezuela' => 'VE',
'Vietnam' => 'VN',
'Wallis and Futuna' => 'WF',
'Western Sahara' => 'EH',
'Yemen' => 'YE',
'Zambia' => 'ZM',
'Zimbabwe' => 'ZW',
); );
}; };

View File

@ -14,58 +14,40 @@ namespace OCA\OcSms\Lib;
use \OCA\OcSms\Lib\CountryCodes; use \OCA\OcSms\Lib\CountryCodes;
// Load the PhoneNumberUtil class and dependencies.
include( dirname(__FILE__) . '/vendor/autoload.php');
class PhoneNumberFormatter { class PhoneNumberFormatter {
public static $intlPhoneNumber_rxp = array( // match international numbers with 1,2,3 digits
'#^(00|\+)(1\d\d\d)#', // NANP
'#^(00|\+)(2[1|2|3|4|5|6|8|9]\d)#', // +2(1|2|3|4|5|6|8|9)x
'#^(00|\+)(2[0|7])#', // +2x
'#^(00|\+)(3[5|7|8]\d)#', // +3(5|7|8)x
'#^(00|\+)(3[0|1|2|3|4|6|9])#', // +3x
'#^(00|\+)(4[2]\d)#', // +4(2)x
'#^(00|\+)(4[0|1|3|4|5|6|7|8|9])#', // +4x
'#^(00|\+)(5[0|9]\d)#', // +5(0|9)x
'#^(00|\+)(5[1|2|3|4|5|6|7|8])#', // +5x
'#^(00|\+)(6[7|8|9]\d)#', // +6(7|8|9)x
'#^(00|\+)(6[0|1|2|3|4|5|6])#', // +6x
'#^(00|\+)(7)#', // +7
'#^(00|\+)(8[5|7|8|9]\d)#', // +8(5|7|8|9)x
'#^(00|\+)(8[1|2|3|4|6])#', // +8x
'#^(00|\+)(9[6|7|9]\d)#', // +9(6|7|9)x
'#^(00|\+)(9[0|1|2|3|4|5|8])#' // +9x
);
public static $localPrePhoneNumber_rxp = array(
'#(^0)([^0])#' // in germany : 0-xx[x[x]]-123456
); //
public static function format ($country, $pn) { public static function format ($country, $pn) {
// If no country or country not found into mapper, return original number // Trim the phone number.
if ($country === false || !array_key_exists($country, CountryCodes::$codes)) { $pn = trim($pn);
return trim($pn);
// If no country, country not found into mapper, or the phone number is shorter than six characters
// (aka most likely a "short" SMS service, just return the original number.
if ($country === false || !array_key_exists($country, CountryCodes::$codes) || strlen($pn) < 6) {
return $pn;
} }
$ignrxp = array( // match non digits and + // Make sure the passed in phone number looks like it could be a phone number, otherwise just return it.
'#[^\d\+\(\)\[\]\{\}]#', // everything but digit, +, (), [] or {} if (preg_match('#^[\d\+\(\[\{].*#',$pn)) { // start with digit, +, (, [ or {
'#(.+)([\(\[\{]\d*[\)\]\}])#', // braces inside the number: +49 (0) 123 456789 // Get an instance of the PhoneNumber Util class.
'#[^\d\+]#' // everything but digits and + $phoneUtil = \libphonenumber\PhoneNumberUtil::getInstance();
);
$ignrpl = array( // replacements // Try and parse the phone number
'', try {
'$1', $NumberProto = $phoneUtil->parse($pn, CountryCodes::$countries[$country]);
''
);
$lpnrpl = CountryCodes::$codes[$country].'$2'; // replace with +{countryCode} -xx[x[x]]-123456 // Reformat the returned result as an international phone number.
$ypn = $phoneUtil->format( $NumberProto, \libphonenumber\PhoneNumberFormat::INTERNATIONAL );
$tpn = trim($pn); // Strip out everything but the digits.
$ypn = preg_replace( '#[^\d]#', '', $ypn );
if (preg_match('#^[\d\+\(\[\{].*#',$tpn)) { // start with digit, +, (, [ or { } catch (\libphonenumber\NumberParseException $e) {
$fpn = preg_replace($ignrxp, $ignrpl, $tpn); // replace everything but digits/+ with '' // If something failed, just return the original string.
$xpn = preg_replace(PhoneNumberFormatter::$localPrePhoneNumber_rxp, $lpnrpl, $fpn); // replace local prenumbers $ypn = $pn;
$ypn = preg_replace(PhoneNumberFormatter::$intlPhoneNumber_rxp, '+$2', $xpn); // format to international coding +x[x[x]]..... }
} else { } else {
$ypn = $tpn; // some SMS_adresses are strings $ypn = $pn; // some SMS_adresses are strings
} }
return $ypn; return $ypn;

7
lib/vendor/autoload.php vendored Normal file
View File

@ -0,0 +1,7 @@
<?php
// autoload.php @generated by Composer
require_once __DIR__ . '/composer' . '/autoload_real.php';
return ComposerAutoloaderInit7189c2dba213d718f3503b92bd6c98f8::getLoader();

413
lib/vendor/composer/ClassLoader.php vendored Normal file
View File

@ -0,0 +1,413 @@
<?php
/*
* This file is part of Composer.
*
* (c) Nils Adermann <naderman@naderman.de>
* Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Composer\Autoload;
/**
* ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
*
* $loader = new \Composer\Autoload\ClassLoader();
*
* // register classes with namespaces
* $loader->add('Symfony\Component', __DIR__.'/component');
* $loader->add('Symfony', __DIR__.'/framework');
*
* // activate the autoloader
* $loader->register();
*
* // to enable searching the include path (eg. for PEAR packages)
* $loader->setUseIncludePath(true);
*
* In this example, if you try to use a class in the Symfony\Component
* namespace or one of its children (Symfony\Component\Console for instance),
* the autoloader will first look for the class under the component/
* directory, and it will then fallback to the framework/ directory if not
* found before giving up.
*
* This class is loosely based on the Symfony UniversalClassLoader.
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Jordi Boggiano <j.boggiano@seld.be>
* @see http://www.php-fig.org/psr/psr-0/
* @see http://www.php-fig.org/psr/psr-4/
*/
class ClassLoader
{
// PSR-4
private $prefixLengthsPsr4 = array();
private $prefixDirsPsr4 = array();
private $fallbackDirsPsr4 = array();
// PSR-0
private $prefixesPsr0 = array();
private $fallbackDirsPsr0 = array();
private $useIncludePath = false;
private $classMap = array();
private $classMapAuthoritative = false;
public function getPrefixes()
{
if (!empty($this->prefixesPsr0)) {
return call_user_func_array('array_merge', $this->prefixesPsr0);
}
return array();
}
public function getPrefixesPsr4()
{
return $this->prefixDirsPsr4;
}
public function getFallbackDirs()
{
return $this->fallbackDirsPsr0;
}
public function getFallbackDirsPsr4()
{
return $this->fallbackDirsPsr4;
}
public function getClassMap()
{
return $this->classMap;
}
/**
* @param array $classMap Class to filename map
*/
public function addClassMap(array $classMap)
{
if ($this->classMap) {
$this->classMap = array_merge($this->classMap, $classMap);
} else {
$this->classMap = $classMap;
}
}
/**
* Registers a set of PSR-0 directories for a given prefix, either
* appending or prepending to the ones previously set for this prefix.
*
* @param string $prefix The prefix
* @param array|string $paths The PSR-0 root directories
* @param bool $prepend Whether to prepend the directories
*/
public function add($prefix, $paths, $prepend = false)
{
if (!$prefix) {
if ($prepend) {
$this->fallbackDirsPsr0 = array_merge(
(array) $paths,
$this->fallbackDirsPsr0
);
} else {
$this->fallbackDirsPsr0 = array_merge(
$this->fallbackDirsPsr0,
(array) $paths
);
}
return;
}
$first = $prefix[0];
if (!isset($this->prefixesPsr0[$first][$prefix])) {
$this->prefixesPsr0[$first][$prefix] = (array) $paths;
return;
}
if ($prepend) {
$this->prefixesPsr0[$first][$prefix] = array_merge(
(array) $paths,
$this->prefixesPsr0[$first][$prefix]
);
} else {
$this->prefixesPsr0[$first][$prefix] = array_merge(
$this->prefixesPsr0[$first][$prefix],
(array) $paths
);
}
}
/**
* Registers a set of PSR-4 directories for a given namespace, either
* appending or prepending to the ones previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param array|string $paths The PSR-4 base directories
* @param bool $prepend Whether to prepend the directories
*
* @throws \InvalidArgumentException
*/
public function addPsr4($prefix, $paths, $prepend = false)
{
if (!$prefix) {
// Register directories for the root namespace.
if ($prepend) {
$this->fallbackDirsPsr4 = array_merge(
(array) $paths,
$this->fallbackDirsPsr4
);
} else {
$this->fallbackDirsPsr4 = array_merge(
$this->fallbackDirsPsr4,
(array) $paths
);
}
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
// Register directories for a new namespace.
$length = strlen($prefix);
if ('\\' !== $prefix[$length - 1]) {
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
$this->prefixDirsPsr4[$prefix] = (array) $paths;
} elseif ($prepend) {
// Prepend directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
(array) $paths,
$this->prefixDirsPsr4[$prefix]
);
} else {
// Append directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
$this->prefixDirsPsr4[$prefix],
(array) $paths
);
}
}
/**
* Registers a set of PSR-0 directories for a given prefix,
* replacing any others previously set for this prefix.
*
* @param string $prefix The prefix
* @param array|string $paths The PSR-0 base directories
*/
public function set($prefix, $paths)
{
if (!$prefix) {
$this->fallbackDirsPsr0 = (array) $paths;
} else {
$this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
}
}
/**
* Registers a set of PSR-4 directories for a given namespace,
* replacing any others previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param array|string $paths The PSR-4 base directories
*
* @throws \InvalidArgumentException
*/
public function setPsr4($prefix, $paths)
{
if (!$prefix) {
$this->fallbackDirsPsr4 = (array) $paths;
} else {
$length = strlen($prefix);
if ('\\' !== $prefix[$length - 1]) {
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
$this->prefixDirsPsr4[$prefix] = (array) $paths;
}
}
/**
* Turns on searching the include path for class files.
*
* @param bool $useIncludePath
*/
public function setUseIncludePath($useIncludePath)
{
$this->useIncludePath = $useIncludePath;
}
/**
* Can be used to check if the autoloader uses the include path to check
* for classes.
*
* @return bool
*/
public function getUseIncludePath()
{
return $this->useIncludePath;
}
/**
* Turns off searching the prefix and fallback directories for classes
* that have not been registered with the class map.
*
* @param bool $classMapAuthoritative
*/
public function setClassMapAuthoritative($classMapAuthoritative)
{
$this->classMapAuthoritative = $classMapAuthoritative;
}
/**
* Should class lookup fail if not found in the current class map?
*
* @return bool
*/
public function isClassMapAuthoritative()
{
return $this->classMapAuthoritative;
}
/**
* Registers this instance as an autoloader.
*
* @param bool $prepend Whether to prepend the autoloader or not
*/
public function register($prepend = false)
{
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
}
/**
* Unregisters this instance as an autoloader.
*/
public function unregister()
{
spl_autoload_unregister(array($this, 'loadClass'));
}
/**
* Loads the given class or interface.
*
* @param string $class The name of the class
* @return bool|null True if loaded, null otherwise
*/
public function loadClass($class)
{
if ($file = $this->findFile($class)) {
includeFile($file);
return true;
}
}
/**
* Finds the path to the file where the class is defined.
*
* @param string $class The name of the class
*
* @return string|false The path if found, false otherwise
*/
public function findFile($class)
{
// work around for PHP 5.3.0 - 5.3.2 https://bugs.php.net/50731
if ('\\' == $class[0]) {
$class = substr($class, 1);
}
// class map lookup
if (isset($this->classMap[$class])) {
return $this->classMap[$class];
}
if ($this->classMapAuthoritative) {
return false;
}
$file = $this->findFileWithExtension($class, '.php');
// Search for Hack files if we are running on HHVM
if ($file === null && defined('HHVM_VERSION')) {
$file = $this->findFileWithExtension($class, '.hh');
}
if ($file === null) {
// Remember that this class does not exist.
return $this->classMap[$class] = false;
}
return $file;
}
private function findFileWithExtension($class, $ext)
{
// PSR-4 lookup
$logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
$first = $class[0];
if (isset($this->prefixLengthsPsr4[$first])) {
foreach ($this->prefixLengthsPsr4[$first] as $prefix => $length) {
if (0 === strpos($class, $prefix)) {
foreach ($this->prefixDirsPsr4[$prefix] as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) {
return $file;
}
}
}
}
}
// PSR-4 fallback dirs
foreach ($this->fallbackDirsPsr4 as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
return $file;
}
}
// PSR-0 lookup
if (false !== $pos = strrpos($class, '\\')) {
// namespaced class name
$logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
. strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
} else {
// PEAR-like class name
$logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
}
if (isset($this->prefixesPsr0[$first])) {
foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
if (0 === strpos($class, $prefix)) {
foreach ($dirs as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
return $file;
}
}
}
}
}
// PSR-0 fallback dirs
foreach ($this->fallbackDirsPsr0 as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
return $file;
}
}
// PSR-0 include paths.
if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
return $file;
}
}
}
/**
* Scope isolated include.
*
* Prevents access to $this/self from included files.
*/
function includeFile($file)
{
include $file;
}

433
lib/vendor/composer/LICENSE vendored Normal file
View File

@ -0,0 +1,433 @@
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: Composer
Upstream-Contact: Jordi Boggiano <j.boggiano@seld.be>
Source: https://github.com/composer/composer
Files: *
Copyright: 2016, Nils Adermann <naderman@naderman.de>
2016, Jordi Boggiano <j.boggiano@seld.be>
License: Expat
Files: res/cacert.pem
Copyright: 2015, Mozilla Foundation
License: MPL-2.0
Files: src/Composer/Util/RemoteFilesystem.php
src/Composer/Util/TlsHelper.php
Copyright: 2016, Nils Adermann <naderman@naderman.de>
2016, Jordi Boggiano <j.boggiano@seld.be>
2013, Evan Coury <me@evancoury.com>
License: Expat and BSD-2-Clause
License: BSD-2-Clause
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
.
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
License: Expat
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
License: MPL-2.0
1. Definitions
--------------
.
1.1. "Contributor"
means each individual or legal entity that creates, contributes to
the creation of, or owns Covered Software.
.
1.2. "Contributor Version"
means the combination of the Contributions of others (if any) used
by a Contributor and that particular Contributor's Contribution.
.
1.3. "Contribution"
means Covered Software of a particular Contributor.
.
1.4. "Covered Software"
means Source Code Form to which the initial Contributor has attached
the notice in Exhibit A, the Executable Form of such Source Code
Form, and Modifications of such Source Code Form, in each case
including portions thereof.
.
1.5. "Incompatible With Secondary Licenses"
means
.
(a) that the initial Contributor has attached the notice described
in Exhibit B to the Covered Software; or
.
(b) that the Covered Software was made available under the terms of
version 1.1 or earlier of the License, but not also under the
terms of a Secondary License.
.
1.6. "Executable Form"
means any form of the work other than Source Code Form.
.
1.7. "Larger Work"
means a work that combines Covered Software with other material, in
a separate file or files, that is not Covered Software.
.
1.8. "License"
means this document.
.
1.9. "Licensable"
means having the right to grant, to the maximum extent possible,
whether at the time of the initial grant or subsequently, any and
all of the rights conveyed by this License.
.
1.10. "Modifications"
means any of the following:
.
(a) any file in Source Code Form that results from an addition to,
deletion from, or modification of the contents of Covered
Software; or
.
(b) any new file in Source Code Form that contains any Covered
Software.
.
1.11. "Patent Claims" of a Contributor
means any patent claim(s), including without limitation, method,
process, and apparatus claims, in any patent Licensable by such
Contributor that would be infringed, but for the grant of the
License, by the making, using, selling, offering for sale, having
made, import, or transfer of either its Contributions or its
Contributor Version.
.
1.12. "Secondary License"
means either the GNU General Public License, Version 2.0, the GNU
Lesser General Public License, Version 2.1, the GNU Affero General
Public License, Version 3.0, or any later versions of those
licenses.
.
1.13. "Source Code Form"
means the form of the work preferred for making modifications.
.
1.14. "You" (or "Your")
means an individual or a legal entity exercising rights under this
License. For legal entities, "You" includes any entity that
controls, is controlled by, or is under common control with You. For
purposes of this definition, "control" means (a) the power, direct
or indirect, to cause the direction or management of such entity,
whether by contract or otherwise, or (b) ownership of more than
fifty percent (50%) of the outstanding shares or beneficial
ownership of such entity.
.
2. License Grants and Conditions
--------------------------------
.
2.1. Grants
.
Each Contributor hereby grants You a world-wide, royalty-free,
non-exclusive license:
.
(a) under intellectual property rights (other than patent or trademark)
Licensable by such Contributor to use, reproduce, make available,
modify, display, perform, distribute, and otherwise exploit its
Contributions, either on an unmodified basis, with Modifications, or
as part of a Larger Work; and
.
(b) under Patent Claims of such Contributor to make, use, sell, offer
for sale, have made, import, and otherwise transfer either its
Contributions or its Contributor Version.
.
2.2. Effective Date
.
The licenses granted in Section 2.1 with respect to any Contribution
become effective for each Contribution on the date the Contributor first
distributes such Contribution.
.
2.3. Limitations on Grant Scope
.
The licenses granted in this Section 2 are the only rights granted under
this License. No additional rights or licenses will be implied from the
distribution or licensing of Covered Software under this License.
Notwithstanding Section 2.1(b) above, no patent license is granted by a
Contributor:
.
(a) for any code that a Contributor has removed from Covered Software;
or
.
(b) for infringements caused by: (i) Your and any other third party's
modifications of Covered Software, or (ii) the combination of its
Contributions with other software (except as part of its Contributor
Version); or
.
(c) under Patent Claims infringed by Covered Software in the absence of
its Contributions.
.
This License does not grant any rights in the trademarks, service marks,
or logos of any Contributor (except as may be necessary to comply with
the notice requirements in Section 3.4).
.
2.4. Subsequent Licenses
.
No Contributor makes additional grants as a result of Your choice to
distribute the Covered Software under a subsequent version of this
License (see Section 10.2) or under the terms of a Secondary License (if
permitted under the terms of Section 3.3).
.
2.5. Representation
.
Each Contributor represents that the Contributor believes its
Contributions are its original creation(s) or it has sufficient rights
to grant the rights to its Contributions conveyed by this License.
.
2.6. Fair Use
.
This License is not intended to limit any rights You have under
applicable copyright doctrines of fair use, fair dealing, or other
equivalents.
.
2.7. Conditions
.
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
in Section 2.1.
.
3. Responsibilities
-------------------
.
3.1. Distribution of Source Form
.
All distribution of Covered Software in Source Code Form, including any
Modifications that You create or to which You contribute, must be under
the terms of this License. You must inform recipients that the Source
Code Form of the Covered Software is governed by the terms of this
License, and how they can obtain a copy of this License. You may not
attempt to alter or restrict the recipients' rights in the Source Code
Form.
.
3.2. Distribution of Executable Form
.
If You distribute Covered Software in Executable Form then:
.
(a) such Covered Software must also be made available in Source Code
Form, as described in Section 3.1, and You must inform recipients of
the Executable Form how they can obtain a copy of such Source Code
Form by reasonable means in a timely manner, at a charge no more
than the cost of distribution to the recipient; and
.
(b) You may distribute such Executable Form under the terms of this
License, or sublicense it under different terms, provided that the
license for the Executable Form does not attempt to limit or alter
the recipients' rights in the Source Code Form under this License.
.
3.3. Distribution of a Larger Work
.
You may create and distribute a Larger Work under terms of Your choice,
provided that You also comply with the requirements of this License for
the Covered Software. If the Larger Work is a combination of Covered
Software with a work governed by one or more Secondary Licenses, and the
Covered Software is not Incompatible With Secondary Licenses, this
License permits You to additionally distribute such Covered Software
under the terms of such Secondary License(s), so that the recipient of
the Larger Work may, at their option, further distribute the Covered
Software under the terms of either this License or such Secondary
License(s).
.
3.4. Notices
.
You may not remove or alter the substance of any license notices
(including copyright notices, patent notices, disclaimers of warranty,
or limitations of liability) contained within the Source Code Form of
the Covered Software, except that You may alter any license notices to
the extent required to remedy known factual inaccuracies.
.
3.5. Application of Additional Terms
.
You may choose to offer, and to charge a fee for, warranty, support,
indemnity or liability obligations to one or more recipients of Covered
Software. However, You may do so only on Your own behalf, and not on
behalf of any Contributor. You must make it absolutely clear that any
such warranty, support, indemnity, or liability obligation is offered by
You alone, and You hereby agree to indemnify every Contributor for any
liability incurred by such Contributor as a result of warranty, support,
indemnity or liability terms You offer. You may include additional
disclaimers of warranty and limitations of liability specific to any
jurisdiction.
.
4. Inability to Comply Due to Statute or Regulation
---------------------------------------------------
.
If it is impossible for You to comply with any of the terms of this
License with respect to some or all of the Covered Software due to
statute, judicial order, or regulation then You must: (a) comply with
the terms of this License to the maximum extent possible; and (b)
describe the limitations and the code they affect. Such description must
be placed in a text file included with all distributions of the Covered
Software under this License. Except to the extent prohibited by statute
or regulation, such description must be sufficiently detailed for a
recipient of ordinary skill to be able to understand it.
.
5. Termination
--------------
.
5.1. The rights granted under this License will terminate automatically
if You fail to comply with any of its terms. However, if You become
compliant, then the rights granted under this License from a particular
Contributor are reinstated (a) provisionally, unless and until such
Contributor explicitly and finally terminates Your grants, and (b) on an
ongoing basis, if such Contributor fails to notify You of the
non-compliance by some reasonable means prior to 60 days after You have
come back into compliance. Moreover, Your grants from a particular
Contributor are reinstated on an ongoing basis if such Contributor
notifies You of the non-compliance by some reasonable means, this is the
first time You have received notice of non-compliance with this License
from such Contributor, and You become compliant prior to 30 days after
Your receipt of the notice.
.
5.2. If You initiate litigation against any entity by asserting a patent
infringement claim (excluding declaratory judgment actions,
counter-claims, and cross-claims) alleging that a Contributor Version
directly or indirectly infringes any patent, then the rights granted to
You by any and all Contributors for the Covered Software under Section
2.1 of this License shall terminate.
.
5.3. In the event of termination under Sections 5.1 or 5.2 above, all
end user license agreements (excluding distributors and resellers) which
have been validly granted by You or Your distributors under this License
prior to termination shall survive termination.
.
************************************************************************
* *
* 6. Disclaimer of Warranty *
* ------------------------- *
* *
* Covered Software is provided under this License on an "as is" *
* basis, without warranty of any kind, either expressed, implied, or *
* statutory, including, without limitation, warranties that the *
* Covered Software is free of defects, merchantable, fit for a *
* particular purpose or non-infringing. The entire risk as to the *
* quality and performance of the Covered Software is with You. *
* Should any Covered Software prove defective in any respect, You *
* (not any Contributor) assume the cost of any necessary servicing, *
* repair, or correction. This disclaimer of warranty constitutes an *
* essential part of this License. No use of any Covered Software is *
* authorized under this License except under this disclaimer. *
* *
************************************************************************
.
************************************************************************
* *
* 7. Limitation of Liability *
* -------------------------- *
* *
* Under no circumstances and under no legal theory, whether tort *
* (including negligence), contract, or otherwise, shall any *
* Contributor, or anyone who distributes Covered Software as *
* permitted above, be liable to You for any direct, indirect, *
* special, incidental, or consequential damages of any character *
* including, without limitation, damages for lost profits, loss of *
* goodwill, work stoppage, computer failure or malfunction, or any *
* and all other commercial damages or losses, even if such party *
* shall have been informed of the possibility of such damages. This *
* limitation of liability shall not apply to liability for death or *
* personal injury resulting from such party's negligence to the *
* extent applicable law prohibits such limitation. Some *
* jurisdictions do not allow the exclusion or limitation of *
* incidental or consequential damages, so this exclusion and *
* limitation may not apply to You. *
* *
************************************************************************
.
8. Litigation
-------------
.
Any litigation relating to this License may be brought only in the
courts of a jurisdiction where the defendant maintains its principal
place of business and such litigation shall be governed by laws of that
jurisdiction, without reference to its conflict-of-law provisions.
Nothing in this Section shall prevent a party's ability to bring
cross-claims or counter-claims.
.
9. Miscellaneous
----------------
.
This License represents the complete agreement concerning the subject
matter hereof. If any provision of this License is held to be
unenforceable, such provision shall be reformed only to the extent
necessary to make it enforceable. Any law or regulation which provides
that the language of a contract shall be construed against the drafter
shall not be used to construe this License against a Contributor.
.
10. Versions of the License
---------------------------
.
10.1. New Versions
.
Mozilla Foundation is the license steward. Except as provided in Section
10.3, no one other than the license steward has the right to modify or
publish new versions of this License. Each version will be given a
distinguishing version number.
.
10.2. Effect of New Versions
.
You may distribute the Covered Software under the terms of the version
of the License under which You originally received the Covered Software,
or under the terms of any subsequent version published by the license
steward.
.
10.3. Modified Versions
.
If you create software not governed by this License, and you want to
create a new license for such software, you may create and use a
modified version of this License if you rename the license and remove
any references to the name of the license steward (except to note that
such modified license differs from this License).
.
10.4. Distributing Source Code Form that is Incompatible With Secondary
Licenses
.
If You choose to distribute Source Code Form that is Incompatible With
Secondary Licenses under the terms of this version of the License, the
notice described in Exhibit B of this License must be attached.
.
Exhibit A - Source Code Form License Notice
-------------------------------------------
.
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
.
If it is not possible or desirable to put the notice in a particular
file, then You may include the notice in a location (such as a LICENSE
file in a relevant directory) where a recipient would be likely to look
for such a notice.
.
You may add additional accurate notices of copyright ownership.
.
Exhibit B - "Incompatible With Secondary Licenses" Notice
---------------------------------------------------------
.
This Source Code Form is "Incompatible With Secondary Licenses", as
defined by the Mozilla Public License, v. 2.0.

View File

@ -0,0 +1,9 @@
<?php
// autoload_classmap.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
);

View File

@ -0,0 +1,9 @@
<?php
// autoload_namespaces.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
);

11
lib/vendor/composer/autoload_psr4.php vendored Normal file
View File

@ -0,0 +1,11 @@
<?php
// autoload_psr4.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
'libphonenumber\\' => array($vendorDir . '/giggsey/libphonenumber-for-php/src'),
'Giggsey\\Locale\\' => array($vendorDir . '/giggsey/locale/src'),
);

45
lib/vendor/composer/autoload_real.php vendored Normal file
View File

@ -0,0 +1,45 @@
<?php
// autoload_real.php @generated by Composer
class ComposerAutoloaderInit7189c2dba213d718f3503b92bd6c98f8
{
private static $loader;
public static function loadClassLoader($class)
{
if ('Composer\Autoload\ClassLoader' === $class) {
require __DIR__ . '/ClassLoader.php';
}
}
public static function getLoader()
{
if (null !== self::$loader) {
return self::$loader;
}
spl_autoload_register(array('ComposerAutoloaderInit7189c2dba213d718f3503b92bd6c98f8', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
spl_autoload_unregister(array('ComposerAutoloaderInit7189c2dba213d718f3503b92bd6c98f8', 'loadClassLoader'));
$map = require __DIR__ . '/autoload_namespaces.php';
foreach ($map as $namespace => $path) {
$loader->set($namespace, $path);
}
$map = require __DIR__ . '/autoload_psr4.php';
foreach ($map as $namespace => $path) {
$loader->setPsr4($namespace, $path);
}
$classMap = require __DIR__ . '/autoload_classmap.php';
if ($classMap) {
$loader->addClassMap($classMap);
}
$loader->register(true);
return $loader;
}
}

123
lib/vendor/composer/installed.json vendored Normal file
View File

@ -0,0 +1,123 @@
[
{
"name": "giggsey/locale",
"version": "1.5",
"version_normalized": "1.5.0.0",
"source": {
"type": "git",
"url": "https://github.com/giggsey/Locale.git",
"reference": "3c9cc23c15851c54cb3ccd41a00fd4b5a89feeff"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/giggsey/Locale/zipball/3c9cc23c15851c54cb3ccd41a00fd4b5a89feeff",
"reference": "3c9cc23c15851c54cb3ccd41a00fd4b5a89feeff",
"shasum": ""
},
"require": {
"php": ">=5.3.2"
},
"require-dev": {
"pear/pear-core-minimal": "^1.9",
"pear/pear_exception": "^1.0",
"pear/versioncontrol_git": "^0.5",
"phing/phing": "~2.7",
"phpunit/phpunit": "^4.8|^5.0",
"satooshi/php-coveralls": "^1.0",
"symfony/console": "^2.8|^3.0|^4.0",
"symfony/filesystem": "^2.8|^3.0|^4.0",
"symfony/finder": "^2.8|^3.0|^4.0",
"symfony/process": "^2.8|^3.0|^4.0"
},
"time": "2018-04-03 15:53:12",
"type": "library",
"installation-source": "dist",
"autoload": {
"psr-4": {
"Giggsey\\Locale\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Joshua Gigg",
"email": "giggsey@gmail.com",
"homepage": "http://giggsey.com/"
}
],
"description": "Locale functions required by libphonenumber-for-php"
},
{
"name": "giggsey/libphonenumber-for-php",
"version": "8.9.7",
"version_normalized": "8.9.7.0",
"source": {
"type": "git",
"url": "https://github.com/giggsey/libphonenumber-for-php.git",
"reference": "cc4ec7cd91e6bc629f868dd4564aa74bbcd8dd34"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/giggsey/libphonenumber-for-php/zipball/cc4ec7cd91e6bc629f868dd4564aa74bbcd8dd34",
"reference": "cc4ec7cd91e6bc629f868dd4564aa74bbcd8dd34",
"shasum": ""
},
"require": {
"ext-mbstring": "*",
"giggsey/locale": "^1.2",
"php": ">=5.3.2"
},
"require-dev": {
"pear/pear-core-minimal": "^1.9",
"pear/pear_exception": "^1.0",
"pear/versioncontrol_git": "^0.5",
"phing/phing": "^2.7",
"phpunit/phpunit": "^4.8|^5.0",
"satooshi/php-coveralls": "^1.0|^2.0",
"symfony/console": "^2.8|^3.0"
},
"time": "2018-05-29 11:52:24",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "8.x-dev"
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
"libphonenumber\\": "src/"
},
"exclude-from-classmap": [
"/src/data/",
"/src/carrier/data/",
"/src/geocoding/data/",
"/src/timezone/data/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache-2.0"
],
"authors": [
{
"name": "Joshua Gigg",
"email": "giggsey@gmail.com",
"homepage": "https://giggsey.com/"
}
],
"description": "PHP Port of Google's libphonenumber",
"homepage": "https://github.com/giggsey/libphonenumber-for-php",
"keywords": [
"geocoding",
"geolocation",
"libphonenumber",
"mobile",
"phonenumber",
"validation"
]
}
]

View File

@ -0,0 +1,177 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS

View File

@ -0,0 +1,5 @@
# This file specifies the revision of the metadata to build from
# It can be a commit, branch or tag of the https://github.com/googlei18n/libphonenumber project
#
# For more information, look at the phing tasks in build.xml
v8.9.7

View File

@ -0,0 +1,258 @@
# libphonenumber for PHP [![Build Status](https://img.shields.io/travis/giggsey/libphonenumber-for-php.svg?style=flat-square)](https://travis-ci.org/giggsey/libphonenumber-for-php) [![Coverage Status](https://img.shields.io/coveralls/giggsey/libphonenumber-for-php.svg?style=flat-square)](https://coveralls.io/r/giggsey/libphonenumber-for-php?branch=master)
[![Total Downloads](https://poser.pugx.org/giggsey/libphonenumber-for-php/downloads?format=flat-square)](https://packagist.org/packages/giggsey/libphonenumber-for-php)
[![Downloads per month](https://img.shields.io/packagist/dm/giggsey/libphonenumber-for-php.svg?style=flat-square)](https://packagist.org/packages/giggsey/libphonenumber-for-php)
[![Latest Stable Version](https://img.shields.io/packagist/v/giggsey/libphonenumber-for-php.svg?style=flat-square)](https://packagist.org/packages/giggsey/libphonenumber-for-php)
[![License](http://img.shields.io/badge/license-Apache%202.0-red.svg?style=flat-square)](https://packagist.org/packages/giggsey/libphonenumber-for-php)
## What is it?
A PHP library for parsing, formatting, storing and validating international phone numbers. This library is based on Google's [libphonenumber](https://github.com/googlei18n/libphonenumber).
- [Installation](#installation)
- [Documentation](#documentation)
- [Online Demo](#online-demo)
- [Highlights of functionality](#highlights-of-functionality)
- [Versioning](#versioning)
- [Quick Examples](#quick-examples)
- [Geocoder](#geocoder)
- [ShortNumberInfo](#shortnumberinfo)
- [Mapping Phone Numbers to carrier](#mapping-phone-numbers-to-carrier)
- [Mapping Phone Numbers to TimeZones](#mapping-phone-numbers-to-timezones)
- [FAQ](#faq)
- [Problems with Invalid Numbers?](#problems-with-invalid-numbers)
- [Generating data](#generating-data)
- [Integration with frameworks](#integration-with-frameworks)
## Installation
PHP versions 5.3 up to PHP 7.2 are currently supported. HHVM is also supported.
The PECL [mbstring](http://php.net/mbstring) extension is required.
It is recommended to use [composer](https://getcomposer.org) to install the library.
```bash
$ composer require giggsey/libphonenumber-for-php
```
You can also use any other [PSR-4](http://www.php-fig.org/psr/psr-4/) compliant autoloader.
If you do not use composer, ensure that you also load any dependencies that this project has, such as [giggsey/locale](https://github.com/giggsey/Locale).
## Documentation
- [PhoneNumber Util](docs/PhoneNumberUtil.md)
- [ShortNumber Info](docs/ShortNumberInfo.md)
- [Phone Number Geolocation](docs/PhoneNumberOfflineGeocoder.md)
- [Phone Number to Carrier Mapping](docs/PhoneNumberToCarrierMapper.md)
- [Phone Number to Timezone Mapping](docs/PhoneNumberToTimeZonesMapper.md)
- [Phone Number Matcher](docs/PhoneNumberMatcher.md)
- [As You Type Formatter](docs/AsYouTypeFormatter.md)
## Online Demo
An [online demo](http://giggsey.com/libphonenumber/) is available, and the source can be found at [giggsey/libphonenumber-example](https://github.com/giggsey/libphonenumber-example).
# Highlights of functionality
* Parsing/formatting/validating phone numbers for all countries/regions of the world.
* `getNumberType` - gets the type of the number based on the number itself; able to distinguish Fixed-line, Mobile, Toll-free, Premium Rate, Shared Cost, VoIP and Personal Numbers (whenever feasible).
* `isNumberMatch` - gets a confidence level on whether two numbers could be the same.
* `getExampleNumber`/`getExampleNumberByType` - provides valid example numbers for all countries/regions, with the option of specifying which type of example phone number is needed.
* `isValidNumber` - full validation of a phone number for a region using length and prefix information.
* `PhoneNumberOfflineGeocoder` - provides geographical information related to a phone number.
* `PhoneNumberToTimeZonesMapper` - provides timezone information related to a phone number.
* `PhoneNumberToCarrierMapper` - provides carrier information related to a phone number.
## Versioning
This library will try to follow the same version numbers as Google. There could be additional releases where needed to fix critical issues that can not wait until the next release from Google.
This does mean that this project may not follow [Semantic Versioning](http://semver.org/), but instead Google's version policy. As a result, jumps in major versions may not actually contain any backwards
incompatible changes. Please read the release notes for such releases.
Google try to release their versions according to Semantic Versioning, as laid out of in their [Versioning Guide](https://github.com/googlei18n/libphonenumber#versioning-and-announcements).
## Quick Examples
Let's say you have a string representing a phone number from Switzerland. This is how you parse/normalize it into a PhoneNumber object:
```php
$swissNumberStr = "044 668 18 00";
$phoneUtil = \libphonenumber\PhoneNumberUtil::getInstance();
try {
$swissNumberProto = $phoneUtil->parse($swissNumberStr, "CH");
var_dump($swissNumberProto);
} catch (\libphonenumber\NumberParseException $e) {
var_dump($e);
}
```
At this point, swissNumberProto contains:
class libphonenumber\PhoneNumber#9 (7) {
private $countryCode =>
int(41)
private $nationalNumber =>
double(446681800)
private $extension =>
NULL
private $italianLeadingZero =>
NULL
private $rawInput =>
NULL
private $countryCodeSource =>
NULL
private $preferredDomesticCarrierCode =>
NULL
}
Now let us validate whether the number is valid:
```php
$isValid = $phoneUtil->isValidNumber($swissNumberProto);
var_dump($isValid); // true
```
There are a few formats supported by the formatting method, as illustrated below:
```php
// Produces "+41446681800"
echo $phoneUtil->format($swissNumberProto, \libphonenumber\PhoneNumberFormat::E164);
// Produces "044 668 18 00"
echo $phoneUtil->format($swissNumberProto, \libphonenumber\PhoneNumberFormat::NATIONAL);
// Produces "+41 44 668 18 00"
echo $phoneUtil->format($swissNumberProto, \libphonenumber\PhoneNumberFormat::INTERNATIONAL);
```
You could also choose to format the number in the way it is dialled from another country:
```php
// Produces "011 41 44 668 1800", the number when it is dialled in the United States.
echo $phoneUtil->formatOutOfCountryCallingNumber($swissNumberProto, "US");
// Produces "00 41 44 668 18 00", the number when it is dialled in Great Britain.
echo $phoneUtil->formatOutOfCountryCallingNumber($swissNumberProto, "GB");
```
### Geocoder
```php
$phoneUtil = \libphonenumber\PhoneNumberUtil::getInstance();
$swissNumberProto = $phoneUtil->parse("044 668 18 00", "CH");
$usNumberProto = $phoneUtil->parse("+1 650 253 0000", "US");
$gbNumberProto = $phoneUtil->parse("0161 496 0000", "GB");
$geocoder = \libphonenumber\geocoding\PhoneNumberOfflineGeocoder::getInstance();
// Outputs "Zurich"
echo $geocoder->getDescriptionForNumber($swissNumberProto, "en_US");
// Outputs "Zürich"
echo $geocoder->getDescriptionForNumber($swissNumberProto, "de_DE");
// Outputs "Zurigo"
echo $geocoder->getDescriptionForNumber($swissNumberProto, "it_IT");
// Outputs "Mountain View, CA"
echo $geocoder->getDescriptionForNumber($usNumberProto, "en_US");
// Outputs "Mountain View, CA"
echo $geocoder->getDescriptionForNumber($usNumberProto, "de_DE");
// Outputs "미국" (Korean for United States)
echo $geocoder->getDescriptionForNumber($usNumberProto, "ko-KR");
// Outputs "Manchester"
echo $geocoder->getDescriptionForNumber($gbNumberProto, "en_GB");
// Outputs "영국" (Korean for United Kingdom)
echo $geocoder->getDescriptionForNumber($gbNumberProto, "ko-KR");
```
### ShortNumberInfo
```php
$shortNumberInfo = \libphonenumber\ShortNumberInfo::getInstance();
// true
var_dump($shortNumberInfo->isEmergencyNumber("999", "GB"));
// true
var_dump($shortNumberInfo->connectsToEmergencyNumber("999", "GB"));
// false
var_dump($shortNumberInfo->connectsToEmergencyNumber("911", "GB"));
// true
var_dump($shortNumberInfo->isEmergencyNumber("911", "US"));
// true
var_dump($shortNumberInfo->connectsToEmergencyNumber("911", "US"));
// false
var_dump($shortNumberInfo->isEmergencyNumber("911123", "US"));
// true
var_dump($shortNumberInfo->connectsToEmergencyNumber("911123", "US"));
```
### Mapping Phone Numbers to carrier
```php
$phoneUtil = \libphonenumber\PhoneNumberUtil::getInstance();
$swissNumberProto = $phoneUtil->parse("798765432", "CH");
$carrierMapper = \libphonenumber\PhoneNumberToCarrierMapper::getInstance();
// Outputs "Swisscom"
echo $carrierMapper->getNameForNumber($swissNumberProto, "en");
```
### Mapping Phone Numbers to TimeZones
```php
$phoneUtil = \libphonenumber\PhoneNumberUtil::getInstance();
$swissNumberProto = $phoneUtil->parse("798765432", "CH");
$timeZoneMapper = \libphonenumber\PhoneNumberToTimeZonesMapper::getInstance();
// returns array("Europe/Zurich")
$timeZones = $timeZoneMapper->getTimeZonesForNumber($swissNumberProto);
```
## FAQ
#### Problems with Invalid Numbers?
This library uses phone number metadata from Google's [libphonenumber](https://github.com/googlei18n/libphonenumber). If this library is working as intended, it should provide the same result as the Java version of Google's project.
If you believe that a phone number is returning an incorrect result, first test it with [libphonenumber](https://github.com/googlei18n/libphonenumber) via their [Online Demo](https://libphonenumber.appspot.com/). If that returns the same result as this project, and you feel it is in error, raise it as an Issue with the libphonenumber project.
If Google's [Online Demo](https://libphonenumber.appspot.com/) gives a different result to the [libphonenumber-for-php demo](http://giggsey.com/libphonenumber/), then please raise an Issue here.
## Generating data
Generating the data is not normally needed, as this repository will generally always have the up to data metadata.
If you do need to generate the data, the commands are provided by [Phing](https://www.phing.info). Ensure you have all the dev composer dependencies installed, then run
```bash
$ vendor/bin/phing compile
```
This compile process clones the [libphonenumber](https://github.com/googlei18n/libphonenumber) project at the version specified in [METADATA-VERSION.txt](METADATA-VERSION.txt).
## Integration with frameworks
Other packages exist that integrate libphonenumber-for-php into frameworks.
| Framework | Packages |
| --------- |:-------------:|
|Symfony|[PhoneNumberBundle](https://github.com/misd-service-development/phone-number-bundle)|
|Laravel|[Laravel Phone](https://github.com/Propaganistas/Laravel-Phone)|
|Yii2|[PhoneInput](https://github.com/Borales/yii2-phone-input)|
|Kohana|[PhoneNumber](https://github.com/softmediadev/kohana-phonenumber)|
These packages are supplied by third parties, and their quality can not be guaranteed.

View File

@ -0,0 +1,79 @@
{
"name": "giggsey/libphonenumber-for-php",
"type": "library",
"description": "PHP Port of Google's libphonenumber",
"keywords": [
"phonenumber",
"libphonenumber",
"mobile",
"validation",
"geocoding",
"geolocation"
],
"homepage": "https://github.com/giggsey/libphonenumber-for-php",
"license": "Apache-2.0",
"support": {
"irc": "irc://irc.appliedirc.com/lobby",
"source": "https://github.com/giggsey/libphonenumber-for-php",
"issues": "https://github.com/giggsey/libphonenumber-for-php/issues"
},
"authors": [
{
"name": "Joshua Gigg",
"email": "giggsey@gmail.com",
"homepage": "https://giggsey.com/"
}
],
"autoload": {
"psr-4": {
"libphonenumber\\": "src/"
},
"exclude-from-classmap": [
"/src/data/",
"/src/carrier/data/",
"/src/geocoding/data/",
"/src/timezone/data/"
]
},
"autoload-dev": {
"psr-4": {
"libphonenumber\\buildtools\\": "build/",
"libphonenumber\\Tests\\": "tests/"
}
},
"archive": {
"exclude": [
"build/",
"docs/",
"tests/",
".editorconfig",
".gitattributes",
".gitignore",
".styleci.yml",
".travis.yml",
"build.xml",
"libphonenumber-for-php.spec",
"phpunit.xml.dist"
]
},
"require": {
"php": ">=5.3.2",
"ext-mbstring": "*",
"giggsey/locale": "^1.2"
},
"require-dev": {
"phing/phing": "^2.7",
"pear/versioncontrol_git": "^0.5",
"pear/pear-core-minimal": "^1.9",
"pear/pear_exception": "^1.0",
"phpunit/phpunit": "^4.8|^5.0",
"symfony/console": "^2.8|^3.0",
"satooshi/php-coveralls": "^1.0|^2.0"
},
"extra": {
"branch-alias": {
"dev-master": "8.x-dev"
}
}
}

View File

@ -0,0 +1,69 @@
<?php
/**
* This file has been @generated by a phing task by {@link BuildMetadataPHPFromXml}.
* See [README.md](README.md#generating-data) for more information.
*
* Pull requests changing data in these files will not be accepted. See the
* [FAQ in the README](README.md#problems-with-invalid-numbers] on how to make
* metadata changes.
*
* Do not modify this file directly!
*/
namespace libphonenumber;
class AlternateFormatsCountryCodeSet {
// A set of all country codes for which data is available.
public static $alternateFormatsCountryCodeSet = array (
0 => 7,
1 => 27,
2 => 30,
3 => 31,
4 => 34,
5 => 36,
6 => 39,
7 => 43,
8 => 44,
9 => 49,
10 => 52,
11 => 54,
12 => 55,
13 => 58,
14 => 61,
15 => 62,
16 => 63,
17 => 64,
18 => 66,
19 => 81,
20 => 84,
21 => 90,
22 => 91,
23 => 94,
24 => 95,
25 => 255,
26 => 350,
27 => 351,
28 => 352,
29 => 358,
30 => 359,
31 => 372,
32 => 373,
33 => 380,
34 => 381,
35 => 385,
36 => 505,
37 => 506,
38 => 595,
39 => 675,
40 => 676,
41 => 679,
42 => 855,
43 => 856,
44 => 971,
45 => 972,
46 => 995,
);
}

View File

@ -0,0 +1,841 @@
<?php
namespace libphonenumber;
/**
* Class AsYouTypeFormatter
* A formatter which formats phone numbers as they are entered.
*
* An AsYouTypeFormatter instance can be created by invoking PhoneNumberUtil::getAsYouTypeFormatter().
* After that, digits can be added by invoking inputDigit() on the formatter instance, and the partially
* formatted phone number will be returned each time a digit is added. clear() can be invokved before
* formatting a new number.
*/
class AsYouTypeFormatter
{
/**
* @var string
*/
private $currentOutput;
/**
* @var string
*/
private $formattingTemplate;
/**
* The pattern from numberFormat that is currently used to create formattingTemplate.
* @var string
*/
private $currentFormattingPattern;
/**
* @var string
*/
private $accruedInput;
/**
* @var string
*/
private $accruedInputWithoutFormatting;
/**
* This indicated whether AsYouTypeFormatter is currently doing the formatting
* @var bool
*/
private $ableToFormat = true;
/**
* Set to true when users enter their own formatting. AsYouTypeFormatter will do no formatting at
* all when this is set to true
* @var bool
*/
private $inputHasFormatting = false;
/**
* This is set to true when we know the user is entering a full national significant number, since
* we have either detected a national prefix or an international dialing prefix. When this is
* true, we will no longer use local formatting patterns.
* @var bool
*/
private $isCompleteNumber = false;
/**
* @var bool
*/
private $isExpectingCountryCallingCode = false;
/**
* @var PhoneNumberUtil
*/
private $phoneUtil;
/**
* @var string
*/
private $defaultCountry;
/**
* @var PhoneMetadata
*/
private $defaultMetadata;
/**
* @var PhoneMetadata
*/
private $currentMetadata;
/**
* @var NumberFormat[]
*/
private $possibleFormats = array();
/**
* @var int
*/
private $lastMatchPosition = 0;
/**
* The position of a digit upon which inputDigitAndRememberPosition is most recently invoked,
* as found in the original sequence of characters the user entered.
* @var int
*/
private $originalPosition = 0;
/**
* The position of a digit upon which inputDigitAndRememberPosition is most recently invoked,
* as found in accruedInputWithoutFormatting
* @var int
*/
private $positionToRemember = 0;
/**
* This contains anything that has been entered so far preceding the national significant number,
* and it is formatted (e.g. with space inserted). For example, this can contain IDD, country code,
* and/or NDD, etc.
* @var string
*/
private $prefixBeforeNationalNumber;
/**
* @var bool
*/
private $shouldAddSpaceAfterNationalPrefix = false;
/**
* This contains the national prefix that has been extracted. It contains only digits without
* formatting
* @var string
*/
private $extractedNationalPrefix = "";
/**
* @var string
*/
private $nationalNumber;
/**
* @var bool
*/
private static $initialised = false;
/**
* Character used when appropriate to separate a prefix, such as a long NDD or a country
* calling code, from the national number.
* @var string
*/
private static $seperatorBeforeNationalNumber = ' ';
/**
* @var PhoneMetadata
*/
private static $emptyMetadata;
/**
* A pattern that is used to match character classes in regular expressions. An example of a
* character class is [1-4]
* @var string
*/
private static $characterClassPattern = "\\[([^\\[\\]])*\\]";
/**
* Any digit in a regular expression that actually denotes a digit. For example, in the regular
* expression 800[0-2]\d{6,10}, the first 2 digits (8 and 0) are standalone digits, but the rest
* are not.
* Two look-aheads are needed before the number following \\d could be a two-digit number, since
* the phone number can be a long as 15 digits.
* @var string
*/
private static $standaloneDigitPattern = "\\d(?=[^,}][^,}])";
/**
* A pattern that is used to determine if a numberFormat under availableFormats is eligible
* to be used by the AYTF. It is eligible when the format element under numberFormat contains
* groups of the dollar sign followed by a single digit, separated by valid phone number punctuation.
* This prevents invalid punctuation (such as the star sign in Israeli star numbers) getting
* into the output of the AYTF.
* @var string
*/
private static $eligibleFormatPattern;
/**
* A set of characters that, if found in the national prefix formatting rules, are an indicator
* to us that we should separate the national prefix from the numbers when formatting.
* @var string
*/
private static $nationalPrefixSeparatorsPattern = "[- ]";
/**
* This is the minimum length of national number accrued that is required to trigger the
* formatter. The first element of the leadingDigitsPattern of each numberFormat contains
* a regular expression that matches up to this number of digits.
* @var int
*/
private static $minLeadingDigitsLength = 3;
/**
* The digits that have not been entered yet will be represented by a \u2008, the punctuation
* space.
* @var string
*/
private static $digitPattern = "\xE2\x80\x88";
private static function init()
{
if (self::$initialised === false) {
self::$initialised = true;
self::$emptyMetadata = new PhoneMetadata();
self::$emptyMetadata->setInternationalPrefix("NA");
self::$eligibleFormatPattern = "[" . PhoneNumberUtil::VALID_PUNCTUATION . "]*"
. "(\\$\\d" . "[" . PhoneNumberUtil::VALID_PUNCTUATION . "]*)+";
}
}
/**
* Constructs as as-you-type formatter. Should be obtained from PhoneNumberUtil->getAsYouTypeFormatter()
* @param string $regionCode The country/region where the phone number is being entered
*/
public function __construct($regionCode)
{
self::init();
$this->phoneUtil = PhoneNumberUtil::getInstance();
$this->defaultCountry = $regionCode;
$this->currentMetadata = $this->getMetadataForRegion($this->defaultCountry);
$this->defaultMetadata = $this->currentMetadata;
}
/**
* The metadata needed by this class is the same for all regions sharing the same country calling
* code. Therefore, we return the metadata for the 'main' region for this country calling code.
* @param string $regionCode
* @return PhoneMetadata
*/
private function getMetadataForRegion($regionCode)
{
$countryCallingCode = $this->phoneUtil->getCountryCodeForRegion($regionCode);
$mainCountry = $this->phoneUtil->getRegionCodeForCountryCode($countryCallingCode);
$metadata = $this->phoneUtil->getMetadataForRegion($mainCountry);
if ($metadata !== null) {
return $metadata;
}
// Set to a default instance of teh metadata. This allows us to function with an incorrect
// region code, even if the formatting only works for numbers specified with "+".
return self::$emptyMetadata;
}
/**
* Returns true if a new template is created as opposed to reusing the existing template.
* @return bool
*/
private function maybeCreateNewTemplate()
{
// When there are multiple available formats, the formatter uses the first format where a
// formatting template could be created.
foreach ($this->possibleFormats as $key => $numberFormat) {
$pattern = $numberFormat->getPattern();
if ($this->currentFormattingPattern == $pattern) {
return false;
}
if ($this->createFormattingTemplate($numberFormat)) {
$this->currentFormattingPattern = $pattern;
$nationalPrefixSeparatorsMatcher = new Matcher(self::$nationalPrefixSeparatorsPattern,
$numberFormat->getNationalPrefixFormattingRule());
$this->shouldAddSpaceAfterNationalPrefix = $nationalPrefixSeparatorsMatcher->find();
// With a new formatting template, the matched position using the old template
// needs to be reset.
$this->lastMatchPosition = 0;
return true;
} else {
// Remove the current number format from $this->possibleFormats
unset($this->possibleFormats[$key]);
}
}
$this->ableToFormat = false;
return false;
}
/**
* @param string $leadingDigits
*/
private function getAvailableFormats($leadingDigits)
{
$formatList = ($this->isCompleteNumber && $this->currentMetadata->intlNumberFormatSize() > 0)
? $this->currentMetadata->intlNumberFormats()
: $this->currentMetadata->numberFormats();
$nationalPrefixIsUsedByCountry = $this->currentMetadata->hasNationalPrefix();
foreach ($formatList as $format) {
if (!$nationalPrefixIsUsedByCountry
|| $this->isCompleteNumber
|| $format->getNationalPrefixOptionalWhenFormatting()
|| PhoneNumberUtil::formattingRuleHasFirstGroupOnly($format->getNationalPrefixFormattingRule())
) {
if ($this->isFormatEligible($format->getFormat())) {
$this->possibleFormats[] = $format;
}
}
}
$this->narrowDownPossibleFormats($leadingDigits);
}
/**
* @param string $format
* @return bool
*/
private function isFormatEligible($format)
{
$eligibleFormatMatcher = new Matcher(self::$eligibleFormatPattern, $format);
return $eligibleFormatMatcher->matches();
}
/**
* @param $leadingDigits
*/
private function narrowDownPossibleFormats($leadingDigits)
{
$indexOfLeadingDigitsPattern = mb_strlen($leadingDigits) - self::$minLeadingDigitsLength;
foreach ($this->possibleFormats as $key => $format) {
if ($format->leadingDigitsPatternSize() === 0) {
// Keep everything that isn't restricted by leading digits.
continue;
}
$lastLeadingDigitsPattern = min($indexOfLeadingDigitsPattern, $format->leadingDigitsPatternSize() - 1);
$leadingDigitsPattern = $format->getLeadingDigitsPattern($lastLeadingDigitsPattern);
$m = new Matcher($leadingDigitsPattern, $leadingDigits);
if (!$m->lookingAt()) {
unset($this->possibleFormats[$key]);
}
}
}
/**
* @param NumberFormat $format
* @return bool
*/
private function createFormattingTemplate(NumberFormat $format)
{
$numberPattern = $format->getPattern();
// The formatter doesn't format numbers when numberPattern contains "|", e.g.
// (20|3)\d{4}. In those cases we quickly return.
if (mb_stripos('|', $numberPattern) !== false) {
return false;
}
// replace anything in the form of [..] with \d
$characterClassMatcher = new Matcher(self::$characterClassPattern, $numberPattern);
$numberPattern = $characterClassMatcher->replaceAll("\\\\d");
// Replace any standalone digit (not the one in d{}) with \d
$standAloneDigitMatcher = new Matcher(self::$standaloneDigitPattern, $numberPattern);
$numberPattern = $standAloneDigitMatcher->replaceAll("\\\\d");
$this->formattingTemplate = "";
$tempTemplate = $this->getFormattingTemplate($numberPattern, $format->getFormat());
if (mb_strlen($tempTemplate) > 0) {
$this->formattingTemplate .= $tempTemplate;
return true;
}
return false;
}
/**
* Gets a formatting template which can be used to efficiently format a partial number where
* digits are added one by one.
* @param string $numberPattern
* @param string $numberFormat
* @return string
*/
private function getFormattingTemplate($numberPattern, $numberFormat)
{
// Creates a phone number consisting only of the digit 9 that matches the
// numberPattern by applying the pattern to the longestPhoneNumber string.
$longestPhoneNumber = "999999999999999";
$m = new Matcher($numberPattern, $longestPhoneNumber);
$m->find();
$aPhoneNumber = $m->group();
// No formatting template can be created if the number of digits entered entered so far
// is longer than the maximum the current formatting rule can accommodate.
if (mb_strlen($aPhoneNumber) < mb_strlen($this->nationalNumber)) {
return "";
}
// Formats the number according to $numberFormat
$template = preg_replace('/' . $numberPattern . '/' . PhoneNumberUtil::REGEX_FLAGS, $numberFormat, $aPhoneNumber);
// Replaces each digit with character self::$digitPlattern
$template = preg_replace("/9/", self::$digitPattern, $template);
return $template;
}
/**
* Clears the internal state of the formatter, so it can be reused.
*/
public function clear()
{
$this->currentOutput = "";
$this->accruedInput = "";
$this->accruedInputWithoutFormatting = "";
$this->formattingTemplate = "";
$this->lastMatchPosition = 0;
$this->currentFormattingPattern = "";
$this->prefixBeforeNationalNumber = "";
$this->extractedNationalPrefix = "";
$this->nationalNumber = "";
$this->ableToFormat = true;
$this->inputHasFormatting = false;
$this->positionToRemember = 0;
$this->originalPosition = 0;
$this->isCompleteNumber = false;
$this->isExpectingCountryCallingCode = false;
$this->possibleFormats = array();
$this->shouldAddSpaceAfterNationalPrefix = false;
if ($this->currentMetadata !== $this->defaultMetadata) {
$this->currentMetadata = $this->getMetadataForRegion($this->defaultCountry);
}
}
/**
* Formats a phone number on-the-fly as each digit is entered.
*
* @param string $nextChar the most recently entered digit of a phone number. Formatting characters
* are allowed, but as soon as they are encountered this method foramts the number as entered
* and not "as you type" anymore. Full width digits and Arabic-indic digits are allowed, and will
* be shown as they are.
* @return string The partially formatted phone number
*/
public function inputDigit($nextChar)
{
$this->currentOutput = $this->inputDigitWithOptionToRememberPosition($nextChar, false);
return $this->currentOutput;
}
/**
* Same as $this->inputDigit(), but remembers the position where $nextChar is inserted, so
* that is can be retrieved later by using $this->getRememberedPosition(). The remembered
* position will be automatically adjusted if additional formatting characters are later
* inserted/removed in front of $nextChar
* @param string $nextChar
* @return string
*/
public function inputDigitAndRememberPosition($nextChar)
{
$this->currentOutput = $this->inputDigitWithOptionToRememberPosition($nextChar, true);
return $this->currentOutput;
}
/**
* @param string $nextChar
* @param bool $rememberPosition
* @return string
*/
private function inputDigitWithOptionToRememberPosition($nextChar, $rememberPosition)
{
$this->accruedInput .= $nextChar;
if ($rememberPosition) {
$this->originalPosition = mb_strlen($this->accruedInput);
}
// We do formatting on-the-fly only when each character entered is either a digit, or a plus
// sign (accepted at the start of the number only).
if (!$this->isDigitOrLeadingPlusSign($nextChar)) {
$this->ableToFormat = false;
$this->inputHasFormatting = true;
} else {
$nextChar = $this->normalizeAndAccrueDigitsAndPlusSign($nextChar, $rememberPosition);
}
if (!$this->ableToFormat) {
// When we are unable to format because of reasons other than that formatting chars have been
// entered, it can be due to really long IDDs or NDDs. If that is the case, we might be able
// to do formatting again after extracting them.
if ($this->inputHasFormatting) {
return $this->accruedInput;
} elseif ($this->attemptToExtractIdd()) {
if ($this->attemptToExtractCountryCallingCode()) {
return $this->attemptToChoosePatternWithPrefixExtracted();
}
} elseif ($this->ableToExtractLongerNdd()) {
// Add an additional space to separate long NDD and national significant number for
// readability. We don't set shouldAddSpaceAfterNationalPrefix to true, since we don't want
// this to change later when we choose formatting templates.
$this->prefixBeforeNationalNumber .= self::$seperatorBeforeNationalNumber;
return $this->attemptToChoosePatternWithPrefixExtracted();
}
return $this->accruedInput;
}
// We start to attempt to format only when at least MIN_LEADING_DIGITS_LENGTH digits (the plus
// sign is counted as a digit as well for this purpose) have been entered.
switch (mb_strlen($this->accruedInputWithoutFormatting)) {
case 0:
case 1:
case 2:
return $this->accruedInput;
/** @noinspection PhpMissingBreakStatementInspection */
case 3:
if ($this->attemptToExtractIdd()) {
$this->isExpectingCountryCallingCode = true;
} else {
// No IDD or plus sign is found, might be entering in national format.
$this->extractedNationalPrefix = $this->removeNationalPrefixFromNationalNumber();
return $this->attemptToChooseFormattingPattern();
}
// fall through
default:
if ($this->isExpectingCountryCallingCode) {
if ($this->attemptToExtractCountryCallingCode()) {
$this->isExpectingCountryCallingCode = false;
}
return $this->prefixBeforeNationalNumber . $this->nationalNumber;
}
if (count($this->possibleFormats) > 0) {
// The formatting patterns are already chosen.
$tempNationalNumber = $this->inputDigitHelper($nextChar);
// See if the accrued digits can be formatted properly already. If not, use the results
// from inputDigitHelper, which does formatting based on the formatting pattern chosen.
$formattedNumber = $this->attemptToFormatAccruedDigits();
if (mb_strlen($formattedNumber) > 0) {
return $formattedNumber;
}
$this->narrowDownPossibleFormats($this->nationalNumber);
if ($this->maybeCreateNewTemplate()) {
return $this->inputAccruedNationalNumber();
}
return $this->ableToFormat
? $this->appendNationalNumber($tempNationalNumber)
: $this->accruedInput;
} else {
return $this->attemptToChooseFormattingPattern();
}
}
}
/**
* @return string
*/
private function attemptToChoosePatternWithPrefixExtracted()
{
$this->ableToFormat = true;
$this->isExpectingCountryCallingCode = false;
$this->possibleFormats = array();
$this->lastMatchPosition = 0;
$this->formattingTemplate = "";
$this->currentFormattingPattern = "";
return $this->attemptToChooseFormattingPattern();
}
/**
* @return string
* @internal
*/
public function getExtractedNationalPrefix()
{
return $this->extractedNationalPrefix;
}
/**
* Some national prefixes are a substring of others. If extracting the shorter NDD doesn't result
* in a number we can format, we try to see if we can extract a longer version here.
* @return bool
*/
private function ableToExtractLongerNdd()
{
if (mb_strlen($this->extractedNationalPrefix) > 0) {
// Put the extracted NDD back to the national number before attempting to extract a new NDD.
$this->nationalNumber = $this->extractedNationalPrefix . $this->nationalNumber;
// Remove the previously extracted NDD from prefixBeforeNationalNumber. We cannot simply set
// it to empty string because people sometimes incorrectly enter national prefix after the
// country code, e.g. +44 (0)20-1234-5678.
$indexOfPreviousNdd = mb_strrpos($this->prefixBeforeNationalNumber, $this->extractedNationalPrefix);
$this->prefixBeforeNationalNumber = mb_substr(str_pad($this->prefixBeforeNationalNumber, $indexOfPreviousNdd), 0, $indexOfPreviousNdd);
}
return ($this->extractedNationalPrefix !== $this->removeNationalPrefixFromNationalNumber());
}
/**
* @param string $nextChar
* @return bool
*/
private function isDigitOrLeadingPlusSign($nextChar)
{
$plusCharsMatcher = new Matcher(PhoneNumberUtil::$PLUS_CHARS_PATTERN, $nextChar);
return preg_match('/' . PhoneNumberUtil::DIGITS . '/' . PhoneNumberUtil::REGEX_FLAGS, $nextChar)
|| (mb_strlen($this->accruedInput) === 1 &&
$plusCharsMatcher->matches());
}
/**
* Checks to see if there is an exact pattern match for these digits. If so, we should use this
* instead of any other formatting template whose leadingDigitsPattern also matches the input.
* @return string
*/
public function attemptToFormatAccruedDigits()
{
foreach ($this->possibleFormats as $numberFormat) {
$m = new Matcher($numberFormat->getPattern(), $this->nationalNumber);
if ($m->matches()) {
$nationalPrefixSeparatorsMatcher = new Matcher(self::$nationalPrefixSeparatorsPattern, $numberFormat->getNationalPrefixFormattingRule());
$this->shouldAddSpaceAfterNationalPrefix = $nationalPrefixSeparatorsMatcher->find();
$formattedNumber = $m->replaceAll($numberFormat->getFormat());
return $this->appendNationalNumber($formattedNumber);
}
}
return "";
}
/**
* returns the current position in the partially formatted phone number of the character which was
* previously passed in as a parameter of $this->inputDigitAndRememberPosition().
* @return int
*/
public function getRememberedPosition()
{
if (!$this->ableToFormat) {
return $this->originalPosition;
}
$accruedInputIndex = 0;
$currentOutputIndex = 0;
$currentOutputLength = mb_strlen($this->currentOutput);
while ($accruedInputIndex < $this->positionToRemember && $currentOutputIndex < $currentOutputLength) {
if (mb_substr($this->accruedInputWithoutFormatting, $accruedInputIndex, 1) == mb_substr($this->currentOutput, $currentOutputIndex, 1)) {
$accruedInputIndex++;
}
$currentOutputIndex++;
}
return $currentOutputIndex;
}
/**
* Combines the national number with any prefix (IDD/+ and country code or national prefix) that
* was collected. A space will be inserted between them if the current formatting template
* indicates this to be suitable.
* @param string $nationalNumber
* @return string
*/
private function appendNationalNumber($nationalNumber)
{
$prefixBeforeNationalNumberLength = mb_strlen($this->prefixBeforeNationalNumber);
if ($this->shouldAddSpaceAfterNationalPrefix && $prefixBeforeNationalNumberLength > 0
&& mb_substr($this->prefixBeforeNationalNumber, $prefixBeforeNationalNumberLength - 1, 1)
!= self::$seperatorBeforeNationalNumber
) {
// We want to add a space after the national prefix if the national prefix formatting rule
// indicates that this would normally be done, with the exception of the case where we already
// appended a space because the NDD was surprisingly long.
return $this->prefixBeforeNationalNumber . self::$seperatorBeforeNationalNumber . $nationalNumber;
} else {
return $this->prefixBeforeNationalNumber . $nationalNumber;
}
}
/**
* Attempts to set the formatting template and returns a string which contains the formatted
* version of the digits entered so far.
* @return string
*/
private function attemptToChooseFormattingPattern()
{
// We start to attempt to format only when at least MIN_LEADING_DIGITS_LENGTH digits of national
// number (excluding national prefix) have been entered.
if (mb_strlen($this->nationalNumber) >= self::$minLeadingDigitsLength) {
$this->getAvailableFormats($this->nationalNumber);
// See if the accrued digits can be formatted properly already.
$formattedNumber = $this->attemptToFormatAccruedDigits();
if (mb_strlen($formattedNumber) > 0) {
return $formattedNumber;
}
return $this->maybeCreateNewTemplate() ? $this->inputAccruedNationalNumber() : $this->accruedInput;
} else {
return $this->appendNationalNumber($this->nationalNumber);
}
}
/**
* Invokes inputDigitHelper on each digit of the national number accrued, and returns a formatted
* string in the end
* @return string
*/
private function inputAccruedNationalNumber()
{
$lengthOfNationalNumber = mb_strlen($this->nationalNumber);
if ($lengthOfNationalNumber > 0) {
$tempNationalNumber = "";
for ($i = 0; $i < $lengthOfNationalNumber; $i++) {
$tempNationalNumber = $this->inputDigitHelper(mb_substr($this->nationalNumber, $i, 1));
}
return $this->ableToFormat ? $this->appendNationalNumber($tempNationalNumber) : $this->accruedInput;
} else {
return $this->prefixBeforeNationalNumber;
}
}
/**
* Returns true if the current country is a NANPA country and the national number beings with
* the national prefix
* @return bool
*/
private function isNanpaNumberWithNationalPrefix()
{
// For NANPA numbers beginning with 1[2-9], treat the 1 as the national prefix. The reason is
// that national significant numbers in NANPA always start with [2-9] after the national prefix.
// Numbers beginning with 1[01] can only be short/emergency numbers, which don't need the
// national prefix.
return ($this->currentMetadata->getCountryCode() == 1) && (mb_substr($this->nationalNumber, 0, 1) == '1')
&& (mb_substr($this->nationalNumber, 1, 1) != '0') && (mb_substr($this->nationalNumber, 1, 1) != '1');
}
/**
* Returns the national prefix extracted, or an empty string if it is not present.
* @return string
*/
private function removeNationalPrefixFromNationalNumber()
{
$startOfNationalNumber = 0;
if ($this->isNanpaNumberWithNationalPrefix()) {
$startOfNationalNumber = 1;
$this->prefixBeforeNationalNumber .= "1" . self::$seperatorBeforeNationalNumber;
$this->isCompleteNumber = true;
} elseif ($this->currentMetadata->hasNationalPrefixForParsing()) {
$m = new Matcher($this->currentMetadata->getNationalPrefixForParsing(), $this->nationalNumber);
// Since some national prefix patterns are entirely optional, check that a national prefix
// could actually be extracted.
if ($m->lookingAt() && $m->end() > 0) {
// When the national prefix is detected, we use international formatting rules instead of
// national ones, because national formatting rules could contain local formatting rules
// for numbers entered without area code.
$this->isCompleteNumber = true;
$startOfNationalNumber = $m->end();
$this->prefixBeforeNationalNumber .= mb_substr($this->nationalNumber, 0, $startOfNationalNumber);
}
}
$nationalPrefix = mb_substr($this->nationalNumber, 0, $startOfNationalNumber);
$this->nationalNumber = mb_substr($this->nationalNumber, $startOfNationalNumber);
return $nationalPrefix;
}
/**
* Extracts IDD and plus sign to $this->prefixBeforeNationalNumber when they are available, and places
* the remaining input into $this->nationalNumber.
* @return bool true when $this->accruedInputWithoutFormatting begins with the plus sign or valid IDD
* for $this->defaultCountry.
*/
private function attemptToExtractIdd()
{
$internationalPrefix = "\\" . PhoneNumberUtil::PLUS_SIGN . '|' . $this->currentMetadata->getInternationalPrefix();
$iddMatcher = new Matcher($internationalPrefix, $this->accruedInputWithoutFormatting);
if ($iddMatcher->lookingAt()) {
$this->isCompleteNumber = true;
$startOfCountryCallingCode = $iddMatcher->end();
$this->nationalNumber = mb_substr($this->accruedInputWithoutFormatting, $startOfCountryCallingCode);
$this->prefixBeforeNationalNumber = mb_substr($this->accruedInputWithoutFormatting, 0, $startOfCountryCallingCode);
if (mb_substr($this->accruedInputWithoutFormatting, 0, 1) != PhoneNumberUtil::PLUS_SIGN) {
$this->prefixBeforeNationalNumber .= self::$seperatorBeforeNationalNumber;
}
return true;
}
return false;
}
/**
* Extracts the country calling code from the beginning of $this->nationalNumber to
* $this->prefixBeforeNationalNumber when they are available, and places the remaining input
* into $this->>nationalNumber.
* @return bool true when a valid country calling code can be found
*/
private function attemptToExtractCountryCallingCode()
{
if (mb_strlen($this->nationalNumber) == 0) {
return false;
}
$numberWithoutCountryCallingCode = "";
$countryCode = $this->phoneUtil->extractCountryCode($this->nationalNumber, $numberWithoutCountryCallingCode);
if ($countryCode === 0) {
return false;
}
$this->nationalNumber = $numberWithoutCountryCallingCode;
$newRegionCode = $this->phoneUtil->getRegionCodeForCountryCode($countryCode);
if (PhoneNumberUtil::REGION_CODE_FOR_NON_GEO_ENTITY == $newRegionCode) {
$this->currentMetadata = $this->phoneUtil->getMetadataForNonGeographicalRegion($countryCode);
} elseif ($newRegionCode != $this->defaultCountry) {
$this->currentMetadata = $this->getMetadataForRegion($newRegionCode);
}
$countryCodeString = (string)$countryCode;
$this->prefixBeforeNationalNumber .= $countryCodeString . self::$seperatorBeforeNationalNumber;
// When we have successfully extracted the IDD, the previously extracted NDD should be cleared
// because it is no longer valid.
$this->extractedNationalPrefix = "";
return true;
}
/**
* Accrues digits and the plus sign to $this->accruedInputWithoutFormatting for later use. If
* $nextChar contains a digit in non-ASCII format (e.g. the full-width version of digits), it
* is first normalized to the ASCII version. The return value is $nextChar itself, or its
* normalized version, if $nextChar is a digit in non-ASCII format. This method assumes its
* input is either a digit or the plus sign.
* @param string $nextChar
* @param bool $rememberPosition
* @return string
*/
private function normalizeAndAccrueDigitsAndPlusSign($nextChar, $rememberPosition)
{
if ($nextChar == PhoneNumberUtil::PLUS_SIGN) {
$normalizedChar = $nextChar;
$this->accruedInputWithoutFormatting .= $nextChar;
} else {
$normalizedChar = PhoneNumberUtil::normalizeDigits($nextChar, false);
$this->accruedInputWithoutFormatting .= $normalizedChar;
$this->nationalNumber .= $normalizedChar;
}
if ($rememberPosition) {
$this->positionToRemember = mb_strlen($this->accruedInputWithoutFormatting);
}
return $normalizedChar;
}
/**
* @param string $nextChar
* @return string
*/
private function inputDigitHelper($nextChar)
{
// Note that formattingTemplate is not guaranteed to have a value, it could be empty, e.g.
// when the next digit is entered after extracting an IDD or NDD.
$digitMatcher = new Matcher(self::$digitPattern, $this->formattingTemplate);
if ($digitMatcher->find($this->lastMatchPosition)) {
$tempTemplate = $digitMatcher->replaceFirst($nextChar);
$this->formattingTemplate = $tempTemplate . mb_substr($this->formattingTemplate, mb_strlen($tempTemplate, "UTF-8"), null, "UTF-8");
$this->lastMatchPosition = $digitMatcher->start();
return mb_substr($this->formattingTemplate, 0, $this->lastMatchPosition + 1);
} else {
if (count($this->possibleFormats) === 1) {
// More digits are entered than we could handle, and there are no other valid patterns to
// try.
$this->ableToFormat = false;
} // else, we just reset the formatting pattern.
$this->currentFormattingPattern = "";
return $this->accruedInput;
}
}
}

View File

@ -0,0 +1,34 @@
<?php
namespace libphonenumber;
/**
* Country code source from number
*/
class CountryCodeSource
{
/**
* The country_code is derived based on a phone number with a leading "+", e.g. the French
* number "+33 1 42 68 53 00".
*/
const FROM_NUMBER_WITH_PLUS_SIGN = 0;
/**
* The country_code is derived based on a phone number with a leading IDD, e.g. the French
* number "011 33 1 42 68 53 00", as it is dialled from US.
*/
const FROM_NUMBER_WITH_IDD = 1;
/**
* The country_code is derived based on a phone number without a leading "+", e.g. the French
* number "33 1 42 68 53 00" when defaultCountry is supplied as France.
*/
const FROM_NUMBER_WITHOUT_PLUS_SIGN = 2;
/**
* The country_code is derived NOT based on the phone number itself, but from the defaultCountry
* parameter provided in the parsing function by the clients. This happens mostly for numbers
* written in the national format (without country code). For example, this would be set when
* parsing the French number "01 42 68 53 00", when defaultCountry is supplied as France.
*/
const FROM_DEFAULT_COUNTRY = 3;
const UNSPECIFIED = 4;
}

View File

@ -0,0 +1,924 @@
<?php
/**
* This file has been @generated by a phing task by {@link BuildMetadataPHPFromXml}.
* See [README.md](README.md#generating-data) for more information.
*
* Pull requests changing data in these files will not be accepted. See the
* [FAQ in the README](README.md#problems-with-invalid-numbers] on how to make
* metadata changes.
*
* Do not modify this file directly!
*/
namespace libphonenumber;
class CountryCodeToRegionCodeMap {
// A mapping from a country code to the region codes which denote the
// country/region represented by that country code. In the case of multiple
// countries sharing a calling code, such as the NANPA countries, the one
// indicated with "isMainCountryForCode" in the metadata should be first.
public static $countryCodeToRegionCodeMap = array (
1 =>
array (
0 => 'US',
1 => 'AG',
2 => 'AI',
3 => 'AS',
4 => 'BB',
5 => 'BM',
6 => 'BS',
7 => 'CA',
8 => 'DM',
9 => 'DO',
10 => 'GD',
11 => 'GU',
12 => 'JM',
13 => 'KN',
14 => 'KY',
15 => 'LC',
16 => 'MP',
17 => 'MS',
18 => 'PR',
19 => 'SX',
20 => 'TC',
21 => 'TT',
22 => 'VC',
23 => 'VG',
24 => 'VI',
),
7 =>
array (
0 => 'RU',
1 => 'KZ',
),
20 =>
array (
0 => 'EG',
),
27 =>
array (
0 => 'ZA',
),
30 =>
array (
0 => 'GR',
),
31 =>
array (
0 => 'NL',
),
32 =>
array (
0 => 'BE',
),
33 =>
array (
0 => 'FR',
),
34 =>
array (
0 => 'ES',
),
36 =>
array (
0 => 'HU',
),
39 =>
array (
0 => 'IT',
1 => 'VA',
),
40 =>
array (
0 => 'RO',
),
41 =>
array (
0 => 'CH',
),
43 =>
array (
0 => 'AT',
),
44 =>
array (
0 => 'GB',
1 => 'GG',
2 => 'IM',
3 => 'JE',
),
45 =>
array (
0 => 'DK',
),
46 =>
array (
0 => 'SE',
),
47 =>
array (
0 => 'NO',
1 => 'SJ',
),
48 =>
array (
0 => 'PL',
),
49 =>
array (
0 => 'DE',
),
51 =>
array (
0 => 'PE',
),
52 =>
array (
0 => 'MX',
),
53 =>
array (
0 => 'CU',
),
54 =>
array (
0 => 'AR',
),
55 =>
array (
0 => 'BR',
),
56 =>
array (
0 => 'CL',
),
57 =>
array (
0 => 'CO',
),
58 =>
array (
0 => 'VE',
),
60 =>
array (
0 => 'MY',
),
61 =>
array (
0 => 'AU',
1 => 'CC',
2 => 'CX',
),
62 =>
array (
0 => 'ID',
),
63 =>
array (
0 => 'PH',
),
64 =>
array (
0 => 'NZ',
),
65 =>
array (
0 => 'SG',
),
66 =>
array (
0 => 'TH',
),
81 =>
array (
0 => 'JP',
),
82 =>
array (
0 => 'KR',
),
84 =>
array (
0 => 'VN',
),
86 =>
array (
0 => 'CN',
),
90 =>
array (
0 => 'TR',
),
91 =>
array (
0 => 'IN',
),
92 =>
array (
0 => 'PK',
),
93 =>
array (
0 => 'AF',
),
94 =>
array (
0 => 'LK',
),
95 =>
array (
0 => 'MM',
),
98 =>
array (
0 => 'IR',
),
211 =>
array (
0 => 'SS',
),
212 =>
array (
0 => 'MA',
1 => 'EH',
),
213 =>
array (
0 => 'DZ',
),
216 =>
array (
0 => 'TN',
),
218 =>
array (
0 => 'LY',
),
220 =>
array (
0 => 'GM',
),
221 =>
array (
0 => 'SN',
),
222 =>
array (
0 => 'MR',
),
223 =>
array (
0 => 'ML',
),
224 =>
array (
0 => 'GN',
),
225 =>
array (
0 => 'CI',
),
226 =>
array (
0 => 'BF',
),
227 =>
array (
0 => 'NE',
),
228 =>
array (
0 => 'TG',
),
229 =>
array (
0 => 'BJ',
),
230 =>
array (
0 => 'MU',
),
231 =>
array (
0 => 'LR',
),
232 =>
array (
0 => 'SL',
),
233 =>
array (
0 => 'GH',
),
234 =>
array (
0 => 'NG',
),
235 =>
array (
0 => 'TD',
),
236 =>
array (
0 => 'CF',
),
237 =>
array (
0 => 'CM',
),
238 =>
array (
0 => 'CV',
),
239 =>
array (
0 => 'ST',
),
240 =>
array (
0 => 'GQ',
),
241 =>
array (
0 => 'GA',
),
242 =>
array (
0 => 'CG',
),
243 =>
array (
0 => 'CD',
),
244 =>
array (
0 => 'AO',
),
245 =>
array (
0 => 'GW',
),
246 =>
array (
0 => 'IO',
),
247 =>
array (
0 => 'AC',
),
248 =>
array (
0 => 'SC',
),
249 =>
array (
0 => 'SD',
),
250 =>
array (
0 => 'RW',
),
251 =>
array (
0 => 'ET',
),
252 =>
array (
0 => 'SO',
),
253 =>
array (
0 => 'DJ',
),
254 =>
array (
0 => 'KE',
),
255 =>
array (
0 => 'TZ',
),
256 =>
array (
0 => 'UG',
),
257 =>
array (
0 => 'BI',
),
258 =>
array (
0 => 'MZ',
),
260 =>
array (
0 => 'ZM',
),
261 =>
array (
0 => 'MG',
),
262 =>
array (
0 => 'RE',
1 => 'YT',
),
263 =>
array (
0 => 'ZW',
),
264 =>
array (
0 => 'NA',
),
265 =>
array (
0 => 'MW',
),
266 =>
array (
0 => 'LS',
),
267 =>
array (
0 => 'BW',
),
268 =>
array (
0 => 'SZ',
),
269 =>
array (
0 => 'KM',
),
290 =>
array (
0 => 'SH',
1 => 'TA',
),
291 =>
array (
0 => 'ER',
),
297 =>
array (
0 => 'AW',
),
298 =>
array (
0 => 'FO',
),
299 =>
array (
0 => 'GL',
),
350 =>
array (
0 => 'GI',
),
351 =>
array (
0 => 'PT',
),
352 =>
array (
0 => 'LU',
),
353 =>
array (
0 => 'IE',
),
354 =>
array (
0 => 'IS',
),
355 =>
array (
0 => 'AL',
),
356 =>
array (
0 => 'MT',
),
357 =>
array (
0 => 'CY',
),
358 =>
array (
0 => 'FI',
1 => 'AX',
),
359 =>
array (
0 => 'BG',
),
370 =>
array (
0 => 'LT',
),
371 =>
array (
0 => 'LV',
),
372 =>
array (
0 => 'EE',
),
373 =>
array (
0 => 'MD',
),
374 =>
array (
0 => 'AM',
),
375 =>
array (
0 => 'BY',
),
376 =>
array (
0 => 'AD',
),
377 =>
array (
0 => 'MC',
),
378 =>
array (
0 => 'SM',
),
380 =>
array (
0 => 'UA',
),
381 =>
array (
0 => 'RS',
),
382 =>
array (
0 => 'ME',
),
383 =>
array (
0 => 'XK',
),
385 =>
array (
0 => 'HR',
),
386 =>
array (
0 => 'SI',
),
387 =>
array (
0 => 'BA',
),
389 =>
array (
0 => 'MK',
),
420 =>
array (
0 => 'CZ',
),
421 =>
array (
0 => 'SK',
),
423 =>
array (
0 => 'LI',
),
500 =>
array (
0 => 'FK',
),
501 =>
array (
0 => 'BZ',
),
502 =>
array (
0 => 'GT',
),
503 =>
array (
0 => 'SV',
),
504 =>
array (
0 => 'HN',
),
505 =>
array (
0 => 'NI',
),
506 =>
array (
0 => 'CR',
),
507 =>
array (
0 => 'PA',
),
508 =>
array (
0 => 'PM',
),
509 =>
array (
0 => 'HT',
),
590 =>
array (
0 => 'GP',
1 => 'BL',
2 => 'MF',
),
591 =>
array (
0 => 'BO',
),
592 =>
array (
0 => 'GY',
),
593 =>
array (
0 => 'EC',
),
594 =>
array (
0 => 'GF',
),
595 =>
array (
0 => 'PY',
),
596 =>
array (
0 => 'MQ',
),
597 =>
array (
0 => 'SR',
),
598 =>
array (
0 => 'UY',
),
599 =>
array (
0 => 'CW',
1 => 'BQ',
),
670 =>
array (
0 => 'TL',
),
672 =>
array (
0 => 'NF',
),
673 =>
array (
0 => 'BN',
),
674 =>
array (
0 => 'NR',
),
675 =>
array (
0 => 'PG',
),
676 =>
array (
0 => 'TO',
),
677 =>
array (
0 => 'SB',
),
678 =>
array (
0 => 'VU',
),
679 =>
array (
0 => 'FJ',
),
680 =>
array (
0 => 'PW',
),
681 =>
array (
0 => 'WF',
),
682 =>
array (
0 => 'CK',
),
683 =>
array (
0 => 'NU',
),
685 =>
array (
0 => 'WS',
),
686 =>
array (
0 => 'KI',
),
687 =>
array (
0 => 'NC',
),
688 =>
array (
0 => 'TV',
),
689 =>
array (
0 => 'PF',
),
690 =>
array (
0 => 'TK',
),
691 =>
array (
0 => 'FM',
),
692 =>
array (
0 => 'MH',
),
800 =>
array (
0 => '001',
),
808 =>
array (
0 => '001',
),
850 =>
array (
0 => 'KP',
),
852 =>
array (
0 => 'HK',
),
853 =>
array (
0 => 'MO',
),
855 =>
array (
0 => 'KH',
),
856 =>
array (
0 => 'LA',
),
870 =>
array (
0 => '001',
),
878 =>
array (
0 => '001',
),
880 =>
array (
0 => 'BD',
),
881 =>
array (
0 => '001',
),
882 =>
array (
0 => '001',
),
883 =>
array (
0 => '001',
),
886 =>
array (
0 => 'TW',
),
888 =>
array (
0 => '001',
),
960 =>
array (
0 => 'MV',
),
961 =>
array (
0 => 'LB',
),
962 =>
array (
0 => 'JO',
),
963 =>
array (
0 => 'SY',
),
964 =>
array (
0 => 'IQ',
),
965 =>
array (
0 => 'KW',
),
966 =>
array (
0 => 'SA',
),
967 =>
array (
0 => 'YE',
),
968 =>
array (
0 => 'OM',
),
970 =>
array (
0 => 'PS',
),
971 =>
array (
0 => 'AE',
),
972 =>
array (
0 => 'IL',
),
973 =>
array (
0 => 'BH',
),
974 =>
array (
0 => 'QA',
),
975 =>
array (
0 => 'BT',
),
976 =>
array (
0 => 'MN',
),
977 =>
array (
0 => 'NP',
),
979 =>
array (
0 => '001',
),
992 =>
array (
0 => 'TJ',
),
993 =>
array (
0 => 'TM',
),
994 =>
array (
0 => 'AZ',
),
995 =>
array (
0 => 'GE',
),
996 =>
array (
0 => 'KG',
),
998 =>
array (
0 => 'UZ',
),
);
}

View File

@ -0,0 +1,144 @@
<?php
/**
* This file has been @generated by a phing task by {@link BuildMetadataPHPFromXml}.
* See [README.md](README.md#generating-data) for more information.
*
* Pull requests changing data in these files will not be accepted. See the
* [FAQ in the README](README.md#problems-with-invalid-numbers] on how to make
* metadata changes.
*
* Do not modify this file directly!
*/
namespace libphonenumber;
class CountryCodeToRegionCodeMapForTesting {
// A mapping from a country code to the region codes which denote the
// country/region represented by that country code. In the case of multiple
// countries sharing a calling code, such as the NANPA countries, the one
// indicated with "isMainCountryForCode" in the metadata should be first.
public static $countryCodeToRegionCodeMapForTesting = array (
1 =>
array (
0 => 'US',
1 => 'BB',
2 => 'BS',
3 => 'CA',
),
33 =>
array (
0 => 'FR',
),
36 =>
array (
0 => 'HU',
),
39 =>
array (
0 => 'IT',
),
44 =>
array (
0 => 'GB',
1 => 'GG',
),
46 =>
array (
0 => 'SE',
),
48 =>
array (
0 => 'PL',
),
49 =>
array (
0 => 'DE',
),
52 =>
array (
0 => 'MX',
),
54 =>
array (
0 => 'AR',
),
55 =>
array (
0 => 'BR',
),
61 =>
array (
0 => 'AU',
1 => 'CC',
2 => 'CX',
),
64 =>
array (
0 => 'NZ',
),
65 =>
array (
0 => 'SG',
),
81 =>
array (
0 => 'JP',
),
82 =>
array (
0 => 'KR',
),
86 =>
array (
0 => 'CN',
),
244 =>
array (
0 => 'AO',
),
262 =>
array (
0 => 'RE',
1 => 'YT',
),
290 =>
array (
0 => 'TA',
),
374 =>
array (
0 => 'AM',
),
375 =>
array (
0 => 'BY',
),
376 =>
array (
0 => 'AD',
),
800 =>
array (
0 => '001',
),
882 =>
array (
0 => '001',
),
971 =>
array (
0 => 'AE',
),
979 =>
array (
0 => '001',
),
998 =>
array (
0 => 'UZ',
),
);
}

View File

@ -0,0 +1,11 @@
<?php
namespace libphonenumber;
class DefaultMetadataLoader implements MetadataLoaderInterface
{
public function loadMetadata($metadataFileName)
{
return include $metadataFileName;
}
}

View File

@ -0,0 +1,31 @@
<?php
namespace libphonenumber;
use libphonenumber\Leniency\Possible;
use libphonenumber\Leniency\StrictGrouping;
use libphonenumber\Leniency\Valid;
use libphonenumber\Leniency\ExactGrouping;
class Leniency
{
public static function POSSIBLE()
{
return new Possible;
}
public static function VALID()
{
return new Valid;
}
public static function STRICT_GROUPING()
{
return new StrictGrouping;
}
public static function EXACT_GROUPING()
{
return new ExactGrouping;
}
}

View File

@ -0,0 +1,54 @@
<?php
namespace libphonenumber\Leniency;
use libphonenumber\PhoneNumber;
use libphonenumber\PhoneNumberUtil;
abstract class AbstractLeniency
{
/**
* Integer level to compare 'ENUMs'
* @var int
*/
protected static $level;
/**
* Returns true if $number is a verified number according to this leniency
*
* @param PhoneNumber $number
* @param string $candidate
* @param PhoneNumberUtil $util
* @return bool
* @codeCoverageIgnore
*/
public static function verify(PhoneNumber $number, $candidate, PhoneNumberUtil $util)
{
// This can not be called directly
throw new \BadMethodCallException;
}
/**
* Compare against another Leniency
* @param AbstractLeniency $leniency
* @return int
*/
public static function compareTo(AbstractLeniency $leniency)
{
return static::getLevel() - $leniency::getLevel();
}
protected static function getLevel()
{
if (static::$level === null) {
throw new \RuntimeException('$level should be defined');
}
return static::$level;
}
public function __toString()
{
return str_replace('libphonenumber\\Leniency\\', '', get_class($this));
}
}

View File

@ -0,0 +1,46 @@
<?php
namespace libphonenumber\Leniency;
use libphonenumber\PhoneNumber;
use libphonenumber\PhoneNumberMatcher;
use libphonenumber\PhoneNumberUtil;
class ExactGrouping extends AbstractLeniency
{
protected static $level = 4;
/**
* Phone numbers accepted are PhoneNumberUtil::isValidNumber() valid and are grouped
* in the same way that we would have formatted it, or as a single block. For example,
* a US number written as "650 2530000" is not accepted at this leniency level, whereas
* "650 253 0000" or "6502530000" are.
* Numbers with more than one '/' symbol are also dropped at this level.
*
* Warning: This level might result in lower coverage especially for regions outside of country
* code "+1". If you are not sure about which level to use, email the discussion group
* libphonenumber-discuss@googlegroups.com.
*
* @param PhoneNumber $number
* @param string $candidate
* @param PhoneNumberUtil $util
* @return bool
*/
public static function verify(PhoneNumber $number, $candidate, PhoneNumberUtil $util)
{
if (!$util->isValidNumber($number)
|| !PhoneNumberMatcher::containsOnlyValidXChars($number, $candidate, $util)
|| PhoneNumberMatcher::containsMoreThanOneSlashInNationalNumber($number, $candidate)
|| !PhoneNumberMatcher::isNationalPrefixPresentIfRequired($number, $util)
) {
return false;
}
return PhoneNumberMatcher::checkNumberGroupingIsValid($number, $candidate, $util,
function (PhoneNumberUtil $util, PhoneNumber $number, $normalizedCandidate, $expectedNumberGroups) {
return PhoneNumberMatcher::allNumberGroupsAreExactlyPresent(
$util, $number, $normalizedCandidate, $expectedNumberGroups
);
});
}
}

View File

@ -0,0 +1,25 @@
<?php
namespace libphonenumber\Leniency;
use libphonenumber\PhoneNumber;
use libphonenumber\PhoneNumberUtil;
class Possible extends AbstractLeniency
{
protected static $level = 1;
/**
* Phone numbers accepted are PhoneNumberUtil::isPossibleNumber(), but not necessarily
* PhoneNumberUtil::isValidNumber().
*
* @param PhoneNumber $number
* @param string $candidate
* @param PhoneNumberUtil $util
* @return bool
*/
public static function verify(PhoneNumber $number, $candidate, PhoneNumberUtil $util)
{
return $util->isPossibleNumber($number);
}
}

View File

@ -0,0 +1,48 @@
<?php
namespace libphonenumber\Leniency;
use libphonenumber\PhoneNumber;
use libphonenumber\PhoneNumberMatcher;
use libphonenumber\PhoneNumberUtil;
class StrictGrouping extends AbstractLeniency
{
protected static $level = 3;
/**
* Phone numbers accepted are PhoneNumberUtil::isValidNumber() and are grouped
* in a possible way for this locale. For example, a US number written as
* "65 02 53 00 00" and "650253 0000" are not accepted at this leniency level, whereas
* "650 253 0000", "650 2530000" or "6502530000" are.
* Numbers with more than one '/' symbol in the national significant number are also dropped at
* this level.
*
* Warning: This level might result in lower coverage especially for regions outside of country
* code "+1". If you are not sure about which level to use, email the discussion group
* libphonenumber-discuss@googlegroups.com.
*
* @param PhoneNumber $number
* @param string $candidate
* @param PhoneNumberUtil $util
* @return bool
*/
public static function verify(PhoneNumber $number, $candidate, PhoneNumberUtil $util)
{
if (!$util->isValidNumber($number)
|| !PhoneNumberMatcher::containsOnlyValidXChars($number, $candidate, $util)
|| PhoneNumberMatcher::containsMoreThanOneSlashInNationalNumber($number, $candidate)
|| !PhoneNumberMatcher::isNationalPrefixPresentIfRequired($number, $util)
) {
return false;
}
return PhoneNumberMatcher::checkNumberGroupingIsValid(
$number, $candidate, $util,
function (PhoneNumberUtil $util, PhoneNumber $number, $normalizedCandidate, $expectedNumberGroups) {
return PhoneNumberMatcher::allNumberGroupsRemainGrouped(
$util, $number, $normalizedCandidate, $expectedNumberGroups
);
});
}
}

View File

@ -0,0 +1,32 @@
<?php
namespace libphonenumber\Leniency;
use libphonenumber\PhoneNumber;
use libphonenumber\PhoneNumberMatcher;
use libphonenumber\PhoneNumberUtil;
class Valid extends AbstractLeniency
{
protected static $level = 2;
/**
* Phone numbers accepted are PhoneNumberUtil::isPossibleNumber() and PhoneNumberUtil::isValidNumber().
* Numbers written in national format must have their national-prefix present if it is usually written
* for a number of this type.
*
* @param PhoneNumber $number
* @param string $candidate
* @param PhoneNumberUtil $util
* @return bool
*/
public static function verify(PhoneNumber $number, $candidate, PhoneNumberUtil $util)
{
if (!$util->isValidNumber($number)
|| !PhoneNumberMatcher::containsOnlyValidXChars($number, $candidate, $util)) {
return false;
}
return PhoneNumberMatcher::isNationalPrefixPresentIfRequired($number, $util);
}
}

View File

@ -0,0 +1,16 @@
<?php
namespace libphonenumber;
/**
* Types of phone number matches
* See detailed description beside the isNumberMatch() method
*/
class MatchType
{
const NOT_A_NUMBER = 0;
const NO_MATCH = 1;
const SHORT_NSN_MATCH = 2;
const NSN_MATCH = 3;
const EXACT_MATCH = 4;
}

View File

@ -0,0 +1,191 @@
<?php
namespace libphonenumber;
/**
* Matcher for various regex matching
*
* Note that this is NOT the same as google's java PhoneNumberMatcher class.
* This class is a minimal port of java's built-in matcher class, whereas PhoneNumberMatcher
* is designed to recognize phone numbers embedded in any text.
*
* @internal
*/
class Matcher
{
/**
* @var string
*/
protected $pattern;
/**
* @var string
*/
protected $subject;
/**
* @var array
*/
protected $groups = array();
private $searchIndex = 0;
/**
* @param string $pattern
* @param string $subject
*/
public function __construct($pattern, $subject)
{
$this->pattern = str_replace('/', '\/', $pattern);
$this->subject = $subject;
}
protected function doMatch($type = 'find', $offset = 0)
{
$final_pattern = '(?:' . $this->pattern . ')';
switch ($type) {
case 'matches':
$final_pattern = '^' . $final_pattern . '$';
break;
case 'lookingAt':
$final_pattern = '^' . $final_pattern;
break;
case 'find':
default:
// no changes
break;
}
$final_pattern = '/' . $final_pattern . '/ui';
$search = mb_substr($this->subject, $offset);
$result = preg_match($final_pattern, $search, $groups, PREG_OFFSET_CAPTURE);
if ($result === 1) {
// Expand $groups into $this->groups, but being multi-byte aware
$positions = array();
foreach ($groups as $group) {
$positions[] = array(
$group[0],
$offset + mb_strlen(mb_strcut($search, 0, $group[1]))
);
}
$this->groups = $positions;
}
return ($result === 1);
}
/**
* @return bool
*/
public function matches()
{
return $this->doMatch('matches');
}
/**
* @return bool
*/
public function lookingAt()
{
return $this->doMatch('lookingAt');
}
/**
* @return bool
*/
public function find($offset = null)
{
if ($offset === null) {
$offset = $this->searchIndex;
}
// Increment search index for the next time we call this
$this->searchIndex++;
return $this->doMatch('find', $offset);
}
/**
* @return int
*/
public function groupCount()
{
if (empty($this->groups)) {
return null;
} else {
return count($this->groups) - 1;
}
}
/**
* @param int $group
* @return string
*/
public function group($group = null)
{
if (!isset($group) || $group === null) {
$group = 0;
}
return (isset($this->groups[$group][0])) ? $this->groups[$group][0] : null;
}
/**
* @param int|null $group
* @return int
*/
public function end($group = null)
{
if (!isset($group) || $group === null) {
$group = 0;
}
if (!isset($this->groups[$group])) {
return null;
}
return $this->groups[$group][1] + mb_strlen($this->groups[$group][0]);
}
public function start($group = null)
{
if (!isset($group) || $group === null) {
$group = 0;
}
if (!isset($this->groups[$group])) {
return null;
}
return $this->groups[$group][1];
}
/**
* @param string $replacement
* @return string
*/
public function replaceFirst($replacement)
{
return preg_replace('/' . $this->pattern . '/x', $replacement, $this->subject, 1);
}
/**
* @param string $replacement
* @return string
*/
public function replaceAll($replacement)
{
return preg_replace('/' . $this->pattern . '/x', $replacement, $this->subject);
}
/**
* @param string $input
* @return Matcher
*/
public function reset($input = "")
{
$this->subject = $input;
return $this;
}
}

View File

@ -0,0 +1,26 @@
<?php
namespace libphonenumber;
/**
* Interface MatcherAPIInterface
*
* Internal phonenumber matching API used to isolate the underlying implementation of the
* matcher and allow different implementations to be swapped in easily.
*
* @package libphonenumber
* @internal
*/
interface MatcherAPIInterface
{
/**
* Returns whether the given national number (a string containing only decimal digits) matches
* the national number pattern defined in the given {@code PhoneNumberDesc} message.
*
* @param string $number
* @param PhoneNumberDesc $numberDesc
* @param boolean $allowPrefixMatch
* @return boolean
*/
public function matchNationalNumber($number, PhoneNumberDesc $numberDesc, $allowPrefixMatch);
}

View File

@ -0,0 +1,12 @@
<?php
namespace libphonenumber;
interface MetadataLoaderInterface
{
/**
* @param string $metadataFileName File name (including path) of metadata to load.
* @return mixed
*/
public function loadMetadata($metadataFileName);
}

View File

@ -0,0 +1,20 @@
<?php
namespace libphonenumber;
interface MetadataSourceInterface
{
/**
* Gets phone metadata for a region.
* @param string $regionCode the region code.
* @return PhoneMetadata the phone metadata for that region, or null if there is none.
*/
public function getMetadataForRegion($regionCode);
/**
* Gets phone metadata for a non-geographical region.
* @param int $countryCallingCode the country calling code.
* @return PhoneMetadata the phone metadata for that region, or null if there is none.
*/
public function getMetadataForNonGeographicalRegion($countryCallingCode);
}

View File

@ -0,0 +1,107 @@
<?php
/**
*
*
* @author joshuag
* @created: 04/08/2015 09:03
* @project libphonenumber-for-php
*/
namespace libphonenumber;
class MultiFileMetadataSourceImpl implements MetadataSourceInterface
{
protected static $metaDataFilePrefix = PhoneNumberUtil::META_DATA_FILE_PREFIX;
/**
* A mapping from a region code to the PhoneMetadata for that region.
* @var PhoneMetadata[]
*/
protected $regionToMetadataMap = array();
/**
* A mapping from a country calling code for a non-geographical entity to the PhoneMetadata for
* that country calling code. Examples of the country calling codes include 800 (International
* Toll Free Service) and 808 (International Shared Cost Service).
* @var PhoneMetadata[]
*/
protected $countryCodeToNonGeographicalMetadataMap = array();
/**
* The prefix of the metadata files from which region data is loaded.
* @var String
*/
protected $currentFilePrefix;
/**
* The metadata loader used to inject alternative metadata sources.
* @var MetadataLoaderInterface
*/
protected $metadataLoader;
/**
* @param MetadataLoaderInterface $metadataLoader
* @param string|null $currentFilePrefix
*/
public function __construct(MetadataLoaderInterface $metadataLoader, $currentFilePrefix = null)
{
if ($currentFilePrefix === null) {
$currentFilePrefix = static::$metaDataFilePrefix;
}
$this->currentFilePrefix = $currentFilePrefix;
$this->metadataLoader = $metadataLoader;
}
/**
* @inheritdoc
*/
public function getMetadataForRegion($regionCode)
{
if (!array_key_exists($regionCode, $this->regionToMetadataMap)) {
// The regionCode here will be valid and won't be '001', so we don't need to worry about
// what to pass in for the country calling code.
$this->loadMetadataFromFile($this->currentFilePrefix, $regionCode, 0, $this->metadataLoader);
}
return $this->regionToMetadataMap[$regionCode];
}
/**
* @inheritdoc
*/
public function getMetadataForNonGeographicalRegion($countryCallingCode)
{
if (!array_key_exists($countryCallingCode, $this->countryCodeToNonGeographicalMetadataMap)) {
$this->loadMetadataFromFile($this->currentFilePrefix, PhoneNumberUtil::REGION_CODE_FOR_NON_GEO_ENTITY, $countryCallingCode, $this->metadataLoader);
}
return $this->countryCodeToNonGeographicalMetadataMap[$countryCallingCode];
}
/**
* @param string $filePrefix
* @param string $regionCode
* @param int $countryCallingCode
* @param MetadataLoaderInterface $metadataLoader
* @throws \RuntimeException
*/
public function loadMetadataFromFile($filePrefix, $regionCode, $countryCallingCode, MetadataLoaderInterface $metadataLoader)
{
$isNonGeoRegion = PhoneNumberUtil::REGION_CODE_FOR_NON_GEO_ENTITY === $regionCode;
$fileName = $filePrefix . '_' . ($isNonGeoRegion ? $countryCallingCode : $regionCode) . '.php';
if (!is_readable($fileName)) {
throw new \RuntimeException('missing metadata: ' . $fileName);
} else {
$data = $metadataLoader->loadMetadata($fileName);
$metadata = new PhoneMetadata();
$metadata->fromArray($data);
if ($isNonGeoRegion) {
$this->countryCodeToNonGeographicalMetadataMap[$countryCallingCode] = $metadata;
} else {
$this->regionToMetadataMap[$regionCode] = $metadata;
}
}
}
}

View File

@ -0,0 +1,295 @@
<?php
namespace libphonenumber;
/**
* Number Format
*/
class NumberFormat
{
protected $pattern = null;
protected $format = null;
protected $leadingDigitsPattern = array();
protected $nationalPrefixFormattingRule = null;
/**
* @var bool
*/
protected $nationalPrefixOptionalWhenFormatting = false;
protected $domesticCarrierCodeFormattingRule = null;
public function __construct()
{
$this->clear();
}
/**
* @return NumberFormat
*/
public function clear()
{
$this->pattern = "";
$this->format = "";
$this->leadingDigitsPattern = array();
$this->nationalPrefixFormattingRule = "";
$this->nationalPrefixOptionalWhenFormatting = false;
$this->domesticCarrierCodeFormattingRule = "";
return $this;
}
/**
* @return boolean
*/
public function hasPattern()
{
return isset($this->pattern);
}
/**
* @return string
*/
public function getPattern()
{
return $this->pattern;
}
/**
* @param string $value
* @return NumberFormat
*/
public function setPattern($value)
{
$this->pattern = $value;
return $this;
}
/**
* @return boolean
*/
public function hasNationalPrefixOptionalWhenFormatting()
{
return isset($this->nationalPrefixOptionalWhenFormatting);
}
/**
* @return boolean
*/
public function getNationalPrefixOptionalWhenFormatting()
{
return $this->nationalPrefixOptionalWhenFormatting;
}
/**
* @param boolean $nationalPrefixOptionalWhenFormatting
*/
public function setNationalPrefixOptionalWhenFormatting($nationalPrefixOptionalWhenFormatting)
{
$this->nationalPrefixOptionalWhenFormatting = $nationalPrefixOptionalWhenFormatting;
}
/**
* @return boolean
*/
public function hasFormat()
{
return ($this->format);
}
/**
* @return string
*/
public function getFormat()
{
return $this->format;
}
/**
* @param string $value
* @return NumberFormat
*/
public function setFormat($value)
{
$this->format = $value;
return $this;
}
/**
* @return string
*/
public function leadingDigitPatterns()
{
return $this->leadingDigitsPattern;
}
/**
* @return int
*/
public function leadingDigitsPatternSize()
{
return count($this->leadingDigitsPattern);
}
/**
* @param int $index
* @return string
*/
public function getLeadingDigitsPattern($index)
{
return $this->leadingDigitsPattern[$index];
}
/**
* @param string $value
* @return NumberFormat
*/
public function addLeadingDigitsPattern($value)
{
$this->leadingDigitsPattern[] = $value;
return $this;
}
/**
* @return boolean
*/
public function hasNationalPrefixFormattingRule()
{
return isset($this->nationalPrefixFormattingRule);
}
/**
* @return string
*/
public function getNationalPrefixFormattingRule()
{
return $this->nationalPrefixFormattingRule;
}
/**
* @param string $value
* @return NumberFormat
*/
public function setNationalPrefixFormattingRule($value)
{
$this->nationalPrefixFormattingRule = $value;
return $this;
}
/**
* @return NumberFormat
*/
public function clearNationalPrefixFormattingRule()
{
$this->nationalPrefixFormattingRule = null;
return $this;
}
/**
* @return boolean
*/
public function hasDomesticCarrierCodeFormattingRule()
{
return isset($this->domesticCarrierCodeFormattingRule);
}
/**
* @return string
*/
public function getDomesticCarrierCodeFormattingRule()
{
return $this->domesticCarrierCodeFormattingRule;
}
/**
* @param string $value
* @return NumberFormat
*/
public function setDomesticCarrierCodeFormattingRule($value)
{
$this->domesticCarrierCodeFormattingRule = $value;
return $this;
}
/**
* @param NumberFormat $other
* @return NumberFormat
*/
public function mergeFrom(NumberFormat $other)
{
if ($other->hasPattern()) {
$this->setPattern($other->getPattern());
}
if ($other->hasFormat()) {
$this->setFormat($other->getFormat());
}
$leadingDigitsPatternSize = $other->leadingDigitsPatternSize();
for ($i = 0; $i < $leadingDigitsPatternSize; $i++) {
$this->addLeadingDigitsPattern($other->getLeadingDigitsPattern($i));
}
if ($other->hasNationalPrefixFormattingRule()) {
$this->setNationalPrefixFormattingRule($other->getNationalPrefixFormattingRule());
}
if ($other->hasDomesticCarrierCodeFormattingRule()) {
$this->setDomesticCarrierCodeFormattingRule($other->getDomesticCarrierCodeFormattingRule());
}
if ($other->hasNationalPrefixOptionalWhenFormatting()) {
$this->setNationalPrefixOptionalWhenFormatting($other->getNationalPrefixOptionalWhenFormatting());
}
return $this;
}
/**
* @return array
*/
public function toArray()
{
$output = array();
$output['pattern'] = $this->getPattern();
$output['format'] = $this->getFormat();
$output['leadingDigitsPatterns'] = $this->leadingDigitPatterns();
if ($this->hasNationalPrefixFormattingRule()) {
$output['nationalPrefixFormattingRule'] = $this->getNationalPrefixFormattingRule();
}
if ($this->hasDomesticCarrierCodeFormattingRule()) {
$output['domesticCarrierCodeFormattingRule'] = $this->getDomesticCarrierCodeFormattingRule();
}
if ($this->hasNationalPrefixOptionalWhenFormatting()) {
$output['nationalPrefixOptionalWhenFormatting'] = $this->getNationalPrefixOptionalWhenFormatting();
}
return $output;
}
/**
* @param array $input
*/
public function fromArray(array $input)
{
$this->setPattern($input['pattern']);
$this->setFormat($input['format']);
foreach ($input['leadingDigitsPatterns'] as $leadingDigitsPattern) {
$this->addLeadingDigitsPattern($leadingDigitsPattern);
}
if (isset($input['nationalPrefixFormattingRule'])) {
$this->setNationalPrefixFormattingRule($input['nationalPrefixFormattingRule']);
}
if (isset($input['domesticCarrierCodeFormattingRule'])) {
$this->setDomesticCarrierCodeFormattingRule($input['domesticCarrierCodeFormattingRule']);
}
if (isset($input['nationalPrefixOptionalWhenFormatting'])) {
$this->setNationalPrefixOptionalWhenFormatting($input['nationalPrefixOptionalWhenFormatting']);
}
}
}

View File

@ -0,0 +1,47 @@
<?php
namespace libphonenumber;
/**
* Generic exception class for errors encountered when parsing phone numbers.
* @author Lara Rennie
*/
class NumberParseException extends \Exception
{
const INVALID_COUNTRY_CODE = 0;
// This generally indicates the string passed in had less than 3 digits in it. More
// specifically, the number failed to match the regular expression VALID_PHONE_NUMBER in
// PhoneNumberUtil.
const NOT_A_NUMBER = 1;
// This indicates the string started with an international dialing prefix, but after this was
// stripped from the number, had less digits than any valid phone number (including country
// code) could have.
const TOO_SHORT_AFTER_IDD = 2;
// This indicates the string, after any country code has been stripped, had less digits than any
// valid phone number could have.
const TOO_SHORT_NSN = 3;
// This indicates the string had more digits than any valid phone number could have.
const TOO_LONG = 4;
protected $errorType;
public function __construct($errorType, $message, $previous = null)
{
parent::__construct($message, $errorType, $previous);
$this->message = $message;
$this->errorType = $errorType;
}
/**
* Returns the error type of the exception that has been thrown.
*/
public function getErrorType()
{
return $this->errorType;
}
public function __toString()
{
return "Error type: " . $this->errorType . ". " . $this->message;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,604 @@
<?php
namespace libphonenumber;
class PhoneNumber implements \Serializable
{
/**
* The country calling code for this number, as defined by the International Telecommunication Union
* (ITU). For example, this would be 1 for NANPA countries, and 33 for France.
*
* @var int|null
*/
protected $countryCode = null;
/**
* National (significant) Number is defined in International Telecommunication Union (ITU)
* Recommendation E.164. It is a language/country-neutral representation of a phone number at a
* country level. For countries which have the concept of an "area code" or "national destination
* code", this is included in the National (significant) Number. Although the ITU says the maximum
* length should be 15, we have found longer numbers in some countries e.g. Germany.
*
* Note that the National (significant) Number does not contain the National(trunk) prefix.
*
* @var string|null
*/
protected $nationalNumber = null;
/**
* Extension is not standardized in ITU recommendations, except for being defined as a series of
* numbers with a maximum length of 40 digits. It is defined as a string here to accommodate for the
* possible use of a leading zero in the extension (organizations have complete freedom to do so,
* as there is no standard defined). However, only ASCII digits should be stored here.
*
* @var string|null
*/
protected $extension = null;
/**
* In some countries, the national (significant) number starts with one or more "0"s without this
* being a national prefix or trunk code of some kind. For example, the leading zero in the national
* (significant) number of an Italian phone number indicates the number is a fixed-line number.
* There have been plans to migrate fixed-line numbers to start with the digit two since December
* 2000, but it has not happened yet. See http://en.wikipedia.org/wiki/%2B39 for more details.
*
* These fields can be safely ignored (there is no need to set them) for most countries. Some
* limited number of countries behave like Italy - for these cases, if the leading zero(s) of a
* number would be retained even when dialling internationally, set this flag to true, and also
* set the number of leading zeros.
*
* Clients who use the parsing functionality of the i18n phone number libraries
* will have these fields set if necessary automatically.
*
* @var bool|null
*/
protected $italianLeadingZero = null;
/**
* This field is used to store the raw input string containing phone numbers before it was
* canonicalized by the library. For example, it could be used to store alphanumerical numbers
* such as "1-800-GOOG-411".
*
* @var string|null
*/
protected $rawInput = null;
/**
* The source from which the country_code is derived. This is not set in the general parsing method,
* but in the method that parses and keeps raw_input. New fields could be added upon request.
*
* @see CountryCodeSource
*
* This must be one of the CountryCodeSource constants.
*
* @var int|null
*/
protected $countryCodeSource = CountryCodeSource::UNSPECIFIED;
/**
* The carrier selection code that is preferred when calling this phone number domestically. This
* also includes codes that need to be dialed in some countries when calling from landlines to
* mobiles or vice versa. For example, in Columbia, a "3" needs to be dialed before the phone number
* itself when calling from a mobile phone to a domestic landline phone and vice versa.
*
* Note this is the "preferred" code, which means other codes may work as well.
*
* @var string|null
*/
protected $preferredDomesticCarrierCode = null;
/**
* Whether this phone number has a number of leading zeros set.
*
* @var bool
*/
protected $hasNumberOfLeadingZeros = false;
/**
* The number of leading zeros of this phone number.
*
* @var int
*/
protected $numberOfLeadingZeros = 1;
/**
* Clears this phone number.
*
* This effectively resets this phone number to the state of a new instance.
*
* @return PhoneNumber This PhoneNumber instance, for chaining method calls.
*/
public function clear()
{
$this->clearCountryCode();
$this->clearNationalNumber();
$this->clearExtension();
$this->clearItalianLeadingZero();
$this->clearNumberOfLeadingZeros();
$this->clearRawInput();
$this->clearCountryCodeSource();
$this->clearPreferredDomesticCarrierCode();
return $this;
}
/**
* Clears the country code of this phone number.
*
* @return PhoneNumber This PhoneNumber instance, for chaining method calls.
*/
public function clearCountryCode()
{
$this->countryCode = null;
return $this;
}
/**
* Clears the national number of this phone number.
*
* @return PhoneNumber This PhoneNumber instance, for chaining method calls.
*/
public function clearNationalNumber()
{
$this->nationalNumber = null;
return $this;
}
/**
* Clears the extension of this phone number.
*
* @return PhoneNumber This PhoneNumber instance, for chaining method calls.
*/
public function clearExtension()
{
$this->extension = null;
return $this;
}
/**
* Clears the italian leading zero information of this phone number.
*
* @return PhoneNumber This PhoneNumber instance, for chaining method calls.
*/
public function clearItalianLeadingZero()
{
$this->italianLeadingZero = null;
return $this;
}
/**
* Clears the number of leading zeros of this phone number.
*
* @return PhoneNumber This PhoneNumber instance, for chaining method calls.
*/
public function clearNumberOfLeadingZeros()
{
$this->hasNumberOfLeadingZeros = false;
$this->numberOfLeadingZeros = 1;
return $this;
}
/**
* Clears the raw input of this phone number.
*
* @return PhoneNumber This PhoneNumber instance, for chaining method calls.
*/
public function clearRawInput()
{
$this->rawInput = null;
return $this;
}
/**
* Clears the country code source of this phone number.
*
* @return PhoneNumber This PhoneNumber instance, for chaining method calls.
*/
public function clearCountryCodeSource()
{
$this->countryCodeSource = CountryCodeSource::UNSPECIFIED;
return $this;
}
/**
* Clears the preferred domestic carrier code of this phone number.
*
* @return PhoneNumber This PhoneNumber instance, for chaining method calls.
*/
public function clearPreferredDomesticCarrierCode()
{
$this->preferredDomesticCarrierCode = null;
return $this;
}
/**
* Merges the information from another phone number into this phone number.
*
* @param PhoneNumber $other The phone number to copy.
*
* @return PhoneNumber This PhoneNumber instance, for chaining method calls.
*/
public function mergeFrom(PhoneNumber $other)
{
if ($other->hasCountryCode()) {
$this->setCountryCode($other->getCountryCode());
}
if ($other->hasNationalNumber()) {
$this->setNationalNumber($other->getNationalNumber());
}
if ($other->hasExtension()) {
$this->setExtension($other->getExtension());
}
if ($other->hasItalianLeadingZero()) {
$this->setItalianLeadingZero($other->isItalianLeadingZero());
}
if ($other->hasNumberOfLeadingZeros()) {
$this->setNumberOfLeadingZeros($other->getNumberOfLeadingZeros());
}
if ($other->hasRawInput()) {
$this->setRawInput($other->getRawInput());
}
if ($other->hasCountryCodeSource()) {
$this->setCountryCodeSource($other->getCountryCodeSource());
}
if ($other->hasPreferredDomesticCarrierCode()) {
$this->setPreferredDomesticCarrierCode($other->getPreferredDomesticCarrierCode());
}
return $this;
}
/**
* Returns whether this phone number has a country code set.
*
* @return bool True if a country code is set, false otherwise.
*/
public function hasCountryCode()
{
return isset($this->countryCode);
}
/**
* Returns the country code of this phone number.
*
* @return int|null The country code, or null if not set.
*/
public function getCountryCode()
{
return $this->countryCode;
}
/**
* Sets the country code of this phone number.
*
* @param int $value The country code.
*
* @return PhoneNumber This PhoneNumber instance, for chaining method calls.
*/
public function setCountryCode($value)
{
$this->countryCode = (int) $value;
return $this;
}
/**
* Returns whether this phone number has a national number set.
*
* @return bool True if a national number is set, false otherwise.
*/
public function hasNationalNumber()
{
return isset($this->nationalNumber);
}
/**
* Returns the national number of this phone number.
*
* @return string|null The national number, or null if not set.
*/
public function getNationalNumber()
{
return $this->nationalNumber;
}
/**
* Sets the national number of this phone number.
*
* @param string $value The national number.
*
* @return PhoneNumber This PhoneNumber instance, for chaining method calls.
*/
public function setNationalNumber($value)
{
$this->nationalNumber = (string) $value;
return $this;
}
/**
* Returns whether this phone number has an extension set.
*
* @return bool True if an extension is set, false otherwise.
*/
public function hasExtension()
{
return isset($this->extension);
}
/**
* Returns the extension of this phone number.
*
* @return string|null The extension, or null if not set.
*/
public function getExtension()
{
return $this->extension;
}
/**
* Sets the extension of this phone number.
*
* @param string $value The extension.
*
* @return PhoneNumber This PhoneNumber instance, for chaining method calls.
*/
public function setExtension($value)
{
$this->extension = (string) $value;
return $this;
}
/**
* Returns whether this phone number has the italian leading zero information set.
*
* @return bool
*/
public function hasItalianLeadingZero()
{
return isset($this->italianLeadingZero);
}
/**
* Sets whether this phone number uses an italian leading zero.
*
* @param bool $value True to use italian leading zero, false otherwise.
*
* @return PhoneNumber This PhoneNumber instance, for chaining method calls.
*/
public function setItalianLeadingZero($value)
{
$this->italianLeadingZero = (bool) $value;
return $this;
}
/**
* Returns whether this phone number uses an italian leading zero.
*
* @return bool|null True if it uses an italian leading zero, false it it does not, null if not set.
*/
public function isItalianLeadingZero()
{
return $this->italianLeadingZero;
}
/**
* Returns whether this phone number has a number of leading zeros set.
*
* @return bool True if a number of leading zeros is set, false otherwise.
*/
public function hasNumberOfLeadingZeros()
{
return $this->hasNumberOfLeadingZeros;
}
/**
* Returns the number of leading zeros of this phone number.
*
* @return int The number of leading zeros.
*/
public function getNumberOfLeadingZeros()
{
return $this->numberOfLeadingZeros;
}
/**
* Sets the number of leading zeros of this phone number.
*
* @param int $value The number of leading zeros.
*
* @return PhoneNumber This PhoneNumber instance, for chaining method calls.
*/
public function setNumberOfLeadingZeros($value)
{
$this->hasNumberOfLeadingZeros = true;
$this->numberOfLeadingZeros = (int) $value;
return $this;
}
/**
* Returns whether this phone number has a raw input.
*
* @return bool True if a raw input is set, false otherwise.
*/
public function hasRawInput()
{
return isset($this->rawInput);
}
/**
* Returns the raw input of this phone number.
*
* @return string|null The raw input, or null if not set.
*/
public function getRawInput()
{
return $this->rawInput;
}
/**
* Sets the raw input of this phone number.
*
* @param string $value The raw input.
*
* @return PhoneNumber This PhoneNumber instance, for chaining method calls.
*/
public function setRawInput($value)
{
$this->rawInput = (string) $value;
return $this;
}
/**
* Returns whether this phone number has a country code source.
*
* @return bool True if a country code source is set, false otherwise.
*/
public function hasCountryCodeSource()
{
return $this->countryCodeSource !== CountryCodeSource::UNSPECIFIED;
}
/**
* Returns the country code source of this phone number.
*
* @return int|null A CountryCodeSource constant, or null if not set.
*/
public function getCountryCodeSource()
{
return $this->countryCodeSource;
}
/**
* Sets the country code source of this phone number.
*
* @param int $value A CountryCodeSource constant.
*
* @return PhoneNumber This PhoneNumber instance, for chaining method calls.
*/
public function setCountryCodeSource($value)
{
$this->countryCodeSource = (int) $value;
return $this;
}
/**
* Returns whether this phone number has a preferred domestic carrier code.
*
* @return bool True if a preferred domestic carrier code is set, false otherwise.
*/
public function hasPreferredDomesticCarrierCode()
{
return isset($this->preferredDomesticCarrierCode);
}
/**
* Returns the preferred domestic carrier code of this phone number.
*
* @return string|null The preferred domestic carrier code, or null if not set.
*/
public function getPreferredDomesticCarrierCode()
{
return $this->preferredDomesticCarrierCode;
}
/**
* Sets the preferred domestic carrier code of this phone number.
*
* @param string $value The preferred domestic carrier code.
*
* @return PhoneNumber This PhoneNumber instance, for chaining method calls.
*/
public function setPreferredDomesticCarrierCode($value)
{
$this->preferredDomesticCarrierCode = (string) $value;
return $this;
}
/**
* Returns whether this phone number is equal to another.
*
* @param PhoneNumber $other The phone number to compare.
*
* @return bool True if the phone numbers are equal, false otherwise.
*/
public function equals(PhoneNumber $other)
{
$sameType = get_class($other) == get_class($this);
$sameCountry = $this->hasCountryCode() == $other->hasCountryCode() &&
(!$this->hasCountryCode() || $this->getCountryCode() == $other->getCountryCode());
$sameNational = $this->hasNationalNumber() == $other->hasNationalNumber() &&
(!$this->hasNationalNumber() || $this->getNationalNumber() == $other->getNationalNumber());
$sameExt = $this->hasExtension() == $other->hasExtension() &&
(!$this->hasExtension() || $this->hasExtension() == $other->hasExtension());
$sameLead = $this->hasItalianLeadingZero() == $other->hasItalianLeadingZero() &&
(!$this->hasItalianLeadingZero() || $this->isItalianLeadingZero() == $other->isItalianLeadingZero());
$sameZeros = $this->getNumberOfLeadingZeros() == $other->getNumberOfLeadingZeros();
$sameRaw = $this->hasRawInput() == $other->hasRawInput() &&
(!$this->hasRawInput() || $this->getRawInput() == $other->getRawInput());
$sameCountrySource = $this->hasCountryCodeSource() == $other->hasCountryCodeSource() &&
(!$this->hasCountryCodeSource() || $this->getCountryCodeSource() == $other->getCountryCodeSource());
$samePrefCar = $this->hasPreferredDomesticCarrierCode() == $other->hasPreferredDomesticCarrierCode() &&
(!$this->hasPreferredDomesticCarrierCode() || $this->getPreferredDomesticCarrierCode(
) == $other->getPreferredDomesticCarrierCode());
return $sameType && $sameCountry && $sameNational && $sameExt && $sameLead && $sameZeros && $sameRaw && $sameCountrySource && $samePrefCar;
}
/**
* Returns a string representation of this phone number.
* @return string
*/
public function __toString()
{
$outputString = '';
$outputString .= 'Country Code: ' . $this->countryCode;
$outputString .= ' National Number: ' . $this->nationalNumber;
if ($this->hasItalianLeadingZero()) {
$outputString .= ' Leading Zero(s): true';
}
if ($this->hasNumberOfLeadingZeros()) {
$outputString .= ' Number of leading zeros: ' . $this->numberOfLeadingZeros;
}
if ($this->hasExtension()) {
$outputString .= ' Extension: ' . $this->extension;
}
if ($this->hasCountryCodeSource()) {
$outputString .= ' Country Code Source: ' . $this->countryCodeSource;
}
if ($this->hasPreferredDomesticCarrierCode()) {
$outputString .= ' Preferred Domestic Carrier Code: ' . $this->preferredDomesticCarrierCode;
}
return $outputString;
}
/**
* @inheritDoc
*/
public function serialize()
{
return serialize(
array(
$this->countryCode,
$this->nationalNumber,
$this->extension,
$this->italianLeadingZero,
$this->numberOfLeadingZeros,
$this->rawInput,
$this->countryCodeSource,
$this->preferredDomesticCarrierCode
)
);
}
/**
* @inheritDoc
*/
public function unserialize($serialized)
{
$data = unserialize($serialized);
list(
$this->countryCode,
$this->nationalNumber,
$this->extension,
$this->italianLeadingZero,
$this->numberOfLeadingZeros,
$this->rawInput,
$this->countryCodeSource,
$this->preferredDomesticCarrierCode
) = $data;
if ($this->numberOfLeadingZeros > 1) {
$this->hasNumberOfLeadingZeros = true;
}
}
}

View File

@ -0,0 +1,238 @@
<?php
namespace libphonenumber;
/**
* Phone Number Description
*/
class PhoneNumberDesc
{
protected $hasNationalNumberPattern = false;
protected $nationalNumberPattern = "";
protected $hasExampleNumber = false;
protected $exampleNumber = "";
/**
* @var array
*/
protected $possibleLength;
/**
* @var array
*/
protected $possibleLengthLocalOnly;
public function __construct()
{
$this->clear();
}
/**
* @return PhoneNumberDesc
*/
public function clear()
{
$this->clearNationalNumberPattern();
$this->clearPossibleLength();
$this->clearPossibleLengthLocalOnly();
$this->clearExampleNumber();
return $this;
}
/**
* @return array
*/
public function getPossibleLength()
{
return $this->possibleLength;
}
/**
* @param array $possibleLength
*/
public function setPossibleLength($possibleLength)
{
$this->possibleLength = $possibleLength;
}
public function addPossibleLength($possibleLength)
{
if (!in_array($possibleLength, $this->possibleLength)) {
$this->possibleLength[] = $possibleLength;
}
}
public function clearPossibleLength()
{
$this->possibleLength = array();
}
/**
* @return array
*/
public function getPossibleLengthLocalOnly()
{
return $this->possibleLengthLocalOnly;
}
/**
* @param array $possibleLengthLocalOnly
*/
public function setPossibleLengthLocalOnly($possibleLengthLocalOnly)
{
$this->possibleLengthLocalOnly = $possibleLengthLocalOnly;
}
public function addPossibleLengthLocalOnly($possibleLengthLocalOnly)
{
if (!in_array($possibleLengthLocalOnly, $this->possibleLengthLocalOnly)) {
$this->possibleLengthLocalOnly[] = $possibleLengthLocalOnly;
}
}
public function clearPossibleLengthLocalOnly()
{
$this->possibleLengthLocalOnly = array();
}
/**
* @return boolean
*/
public function hasNationalNumberPattern()
{
return $this->hasNationalNumberPattern;
}
/**
* @return string
*/
public function getNationalNumberPattern()
{
return $this->nationalNumberPattern;
}
/**
* @param string $value
* @return PhoneNumberDesc
*/
public function setNationalNumberPattern($value)
{
$this->hasNationalNumberPattern = true;
$this->nationalNumberPattern = $value;
return $this;
}
/**
* @return PhoneNumberDesc
*/
public function clearNationalNumberPattern()
{
$this->hasNationalNumberPattern = false;
$this->nationalNumberPattern = '';
return $this;
}
/**
* @return string
*/
public function hasExampleNumber()
{
return $this->hasExampleNumber;
}
/**
* @return string
*/
public function getExampleNumber()
{
return $this->exampleNumber;
}
/**
* @param string $value
* @return PhoneNumberDesc
*/
public function setExampleNumber($value)
{
$this->hasExampleNumber = true;
$this->exampleNumber = $value;
return $this;
}
/**
* @return PhoneNumberDesc
*/
public function clearExampleNumber()
{
$this->hasExampleNumber = false;
$this->exampleNumber = '';
return $this;
}
/**
* @param PhoneNumberDesc $other
* @return PhoneNumberDesc
*/
public function mergeFrom(PhoneNumberDesc $other)
{
if ($other->hasNationalNumberPattern()) {
$this->setNationalNumberPattern($other->getNationalNumberPattern());
}
if ($other->hasExampleNumber()) {
$this->setExampleNumber($other->getExampleNumber());
}
$this->setPossibleLength($other->getPossibleLength());
$this->setPossibleLengthLocalOnly($other->getPossibleLengthLocalOnly());
return $this;
}
/**
* @param PhoneNumberDesc $other
* @return boolean
*/
public function exactlySameAs(PhoneNumberDesc $other)
{
return $this->nationalNumberPattern === $other->nationalNumberPattern &&
$this->exampleNumber === $other->exampleNumber;
}
/**
* @return array
*/
public function toArray()
{
$data = array();
if ($this->hasNationalNumberPattern()) {
$data['NationalNumberPattern'] = $this->getNationalNumberPattern();
}
if ($this->hasExampleNumber()) {
$data['ExampleNumber'] = $this->getExampleNumber();
}
$data['PossibleLength'] = $this->getPossibleLength();
$data['PossibleLengthLocalOnly'] = $this->getPossibleLengthLocalOnly();
return $data;
}
/**
* @param array $input
* @return PhoneNumberDesc
*/
public function fromArray(array $input)
{
if (isset($input['NationalNumberPattern']) && $input['NationalNumberPattern'] != '') {
$this->setNationalNumberPattern($input['NationalNumberPattern']);
}
if (isset($input['ExampleNumber']) && $input['NationalNumberPattern'] != '') {
$this->setExampleNumber($input['ExampleNumber']);
}
$this->setPossibleLength($input['PossibleLength']);
$this->setPossibleLengthLocalOnly($input['PossibleLengthLocalOnly']);
return $this;
}
}

View File

@ -0,0 +1,23 @@
<?php
namespace libphonenumber;
/**
* INTERNATIONAL and NATIONAL formats are consistent with the definition in ITU-T Recommendation
* E123. For example, the number of the Google Switzerland office will be written as
* "+41 44 668 1800" in INTERNATIONAL format, and as "044 668 1800" in NATIONAL format.
* E164 format is as per INTERNATIONAL format but with no formatting applied, e.g.
* "+41446681800". RFC3966 is as per INTERNATIONAL format, but with all spaces and other
* separating symbols replaced with a hyphen, and with any phone number extension appended with
* ";ext=". It also will have a prefix of "tel:" added, e.g. "tel:+41-44-668-1800".
*
* Note: If you are considering storing the number in a neutral format, you are highly advised to
* use the PhoneNumber class.
*/
class PhoneNumberFormat
{
const E164 = 0;
const INTERNATIONAL = 1;
const NATIONAL = 2;
const RFC3966 = 3;
}

View File

@ -0,0 +1,88 @@
<?php
namespace libphonenumber;
class PhoneNumberMatch
{
/**
* The start index into the text.
* @var int
*/
private $start;
/**
* The raw substring matched.
* @var string
*/
private $rawString;
/**
* The matched phone number.
* @var PhoneNumber
*/
private $number;
/**
* Creates a new match
*
* @param int $start The start index into the target text
* @param string $rawString The matched substring of the target text
* @param PhoneNumber $number The matched phone number
* @throws \NullPointerException
*/
public function __construct($start, $rawString, PhoneNumber $number)
{
if ($start < 0) {
throw new \InvalidArgumentException("Start index must be >= 0.");
}
if ($rawString === null) {
throw new \NullPointerException;
}
$this->start = $start;
$this->rawString = $rawString;
$this->number = $number;
}
/**
* Returns the phone number matched by the receiver.
* @return PhoneNumber
*/
public function number()
{
return $this->number;
}
/**
* Returns the start index of the matched phone number within the searched text.
* @return int
*/
public function start()
{
return $this->start;
}
/**
* Returns the exclusive end index of the matched phone number within the searched text.
* @return int
*/
public function end()
{
return $this->start + mb_strlen($this->rawString);
}
/**
* Returns the raw string matched as a phone number in the searched text.
* @return string
*/
public function rawString()
{
return $this->rawString;
}
public function __toString()
{
return "PhoneNumberMatch [{$this->start()},{$this->end()}) {$this->rawString}";
}
}

View File

@ -0,0 +1,937 @@
<?php
namespace libphonenumber;
use libphonenumber\Leniency\AbstractLeniency;
/**
* A class that finds and extracts telephone numbers from $text.
* Instances can be created using PhoneNumberUtil::findNumbers()
*
* Vanity numbers (phone numbers using alphabetic digits such as '1-800-SIX-FLAGS' are
* not found.
*
* @package libphonenumber
*/
class PhoneNumberMatcher implements \Iterator
{
protected static $initialized = false;
/**
* The phone number pattern used by $this->find(), similar to
* PhoneNumberUtil::VALID_PHONE_NUMBER, but with the following differences:
* <ul>
* <li>All captures are limited in order to place an upper bound to the text matched by the
* pattern.
* <ul>
* <li>Leading punctuation / plus signs are limited.
* <li>Consecutive occurrences of punctuation are limited.
* <li>Number of digits is limited.
* </ul>
* <li>No whitespace is allowed at the start or end.
* <li>No alpha digits (vanity numbers such as 1-800-SIX-FLAGS) are currently supported.
* </ul>
*
* @var string
*/
protected static $pattern;
/**
* Matches strings that look like publication pages. Example:
* <pre>Computing Complete Answers to Queries in the Presence of Limited Access Patterns.
* Chen Li. VLDB J. 12(3): 211-227 (2003).</pre>
*
* The string "211-227 (2003)" is not a telephone number.
*
* @var string
*/
protected static $pubPages = "\\d{1,5}-+\\d{1,5}\\s{0,4}\\(\\d{1,4}";
/**
* Matches strings that look like dates using "/" as a separator. Examples 3/10/2011, 31/10/2011 or
* 08/31/95.
*
* @var string
*/
protected static $slashSeparatedDates = "(?:(?:[0-3]?\\d/[01]?\\d)|(?:[01]?\\d/[0-3]?\\d))/(?:[12]\\d)?\\d{2}";
/**
* Matches timestamps. Examples: "2012-01-02 08:00". Note that the reg-ex does not include the
* trailing ":\d\d" -- that is covered by timeStampsSuffix.
*
* @var string
*/
protected static $timeStamps = "[12]\\d{3}[-/]?[01]\\d[-/]?[0-3]\\d +[0-2]\\d$";
protected static $timeStampsSuffix = ":[0-5]\\d";
/**
* Pattern to check that brackets match. Opening brackets should be closed within a phone number.
* This also checks that there is something inside the brackets. Having no brackets at all is also
* fine.
*
* @var string
*/
protected static $matchingBrackets;
/**
* Patterns used to extract phone numbers from a larger phone-number-like pattern. These are
* ordered according to specificity. For example, white-space is last since that is frequently
* used in numbers, not just to separate two numbers. We have separate patterns since we don't
* want to break up the phone-number-like text on more than one different kind of symbol at one
* time, although symbols of the same type (e.g. space) can be safely grouped together.
*
* Note that if there is a match, we will always check any text found up to the first match as
* well.
*
* @var string[]
*/
protected static $innerMatches = array();
/**
* Punctuation that may be at the start of a phone number - brackets and plus signs.
*
* @var string
*/
protected static $leadClass;
/**
* Prefix of the files
* @var string
*/
protected static $alternateFormatsFilePrefix;
const META_DATA_FILE_PREFIX = 'PhoneNumberAlternateFormats';
protected static function init()
{
static::$alternateFormatsFilePrefix = dirname(__FILE__) . '/data/' . static::META_DATA_FILE_PREFIX;
static::$innerMatches = array(
// Breaks on the slash - e.g. "651-234-2345/332-445-1234"
"/+(.*)",
// Note that the bracket here is inside the capturing group, since we consider it part of the
// phone number. Will match a pattern like "(650) 223 3345 (754) 223 3321".
"(\\([^(]*)",
// Breaks on a hyphen - e.g. "12345 - 332-445-1234 is my number."
// We require a space on either side of the hyphen for it to be considered a separator.
"(?:\\p{Z}-|-\\p{Z})\\p{Z}*(.+)",
// Various types of wide hyphens. Note we have decided not to enforce a space here, since it's
// possible that it's supposed to be used to break two numbers without spaces, and we haven't
// seen many instances of it used within a number.
"[-―-]\\p{Z}*(.+)",
// Breaks on a full stop - e.g. "12345. 332-445-1234 is my number."
"\\.+\\p{Z}*([^.]+)",
// Breaks on space - e.g. "3324451234 8002341234"
"\\p{Z}+(\\P{Z}+)"
);
/*
* Builds the matchingBrackets and pattern regular expressions. The building blocks exist
* to make the pattern more easily understood.
*/
$openingParens = "(\\[\xEF\xBC\x88\xEF\xBC\xBB";
$closingParens = ")\\]\xEF\xBC\x89\xEF\xBC\xBD";
$nonParens = "[^" . $openingParens . $closingParens . "]";
// Limit on the number of pairs of brackets in a phone number.
$bracketPairLimit = static::limit(0, 3);
/*
* An opening bracket at the beginning may not be closed, but subsequent ones should be. It's
* also possible that the leading bracket was dropped, so we shouldn't be surprised if we see a
* closing bracket first. We limit the sets of brackets in a phone number to four.
*/
static::$matchingBrackets =
"(?:[" . $openingParens . "])?" . "(?:" . $nonParens . "+" . "[" . $closingParens . "])?"
. $nonParens . "+"
. "(?:[" . $openingParens . "]" . $nonParens . "+[" . $closingParens . "])" . $bracketPairLimit
. $nonParens . "*";
// Limit on the number of leading (plus) characters.
$leadLimit = static::limit(0, 2);
// Limit on the number of consecutive punctuation characters.
$punctuationLimit = static::limit(0, 4);
/*
* The maximum number of digits allowed in a digit-separated block. As we allow all digits in a
* single block, set high enough to accommodate the entire national number and the international
* country code
*/
$digitBlockLimit = PhoneNumberUtil::MAX_LENGTH_FOR_NSN + PhoneNumberUtil::MAX_LENGTH_COUNTRY_CODE;
/*
* Limit on the number of blocks separated by the punctuation. Uses digitBlockLimit since some
* formats use spaces to separate each digit
*/
$blockLimit = static::limit(0, $digitBlockLimit);
// A punctuation sequence allowing white space
$punctuation = '[' . PhoneNumberUtil::VALID_PUNCTUATION . ']' . $punctuationLimit;
// A digits block without punctuation.
$digitSequence = "\\p{Nd}" . static::limit(1, $digitBlockLimit);
$leadClassChars = $openingParens . PhoneNumberUtil::PLUS_CHARS;
$leadClass = '[' . $leadClassChars . ']';
static::$leadClass = $leadClass;
// Init extension patterns from PhoneNumberUtil
PhoneNumberUtil::initCapturingExtnDigits();
PhoneNumberUtil::initExtnPatterns();
// Phone number pattern allowing optional punctuation.
static::$pattern = "(?:" . $leadClass . $punctuation . ")" . $leadLimit
. $digitSequence . "(?:" . $punctuation . $digitSequence . ")" . $blockLimit
. "(?:" . PhoneNumberUtil::$EXTN_PATTERNS_FOR_MATCHING . ")?";
static::$initialized = true;
}
/**
* Helper function to generate regular expression with an upper and lower limit.
*
* @param int $lower
* @param int $upper
* @return string
*/
protected static function limit($lower, $upper)
{
if (($lower < 0) || ($upper <= 0) || ($upper < $lower)) {
throw new \InvalidArgumentException();
}
return '{' . $lower . ',' . $upper . '}';
}
/**
* The phone number utility.
* @var PhoneNumberUtil
*/
protected $phoneUtil;
/**
* The text searched for phone numbers.
* @var string
*/
protected $text;
/**
* The region (country) to assume for phone numbers without an international prefix, possibly
* null.
* @var string
*/
protected $preferredRegion;
/**
* The degrees of validation requested.
* @var AbstractLeniency
*/
protected $leniency;
/**
* The maximum number of retires after matching an invalid number.
* @var int
*/
protected $maxTries;
/**
* One of:
* - NOT_READY
* - READY
* - DONE
* @var string
*/
protected $state = 'NOT_READY';
/**
* The last successful match, null unless $this->state = READY
* @var PhoneNumberMatch
*/
protected $lastMatch;
/**
* The next index to start searching at. Undefined when $this->state = DONE
* @var int
*/
protected $searchIndex = 0;
/**
* Creates a new instance. See the factory methods in PhoneNumberUtil on how to obtain a new instance.
*
*
* @param PhoneNumberUtil $util The Phone Number Util to use
* @param string|null $text The text that we will search, null for no text
* @param string|null $country The country to assume for phone numbers not written in international format.
* (with a leading plus, or with the international dialling prefix of the specified region).
* May be null, or "ZZ" if only numbers with a leading plus should be considered.
* @param AbstractLeniency $leniency The leniency to use when evaluating candidate phone numbers
* @param int $maxTries The maximum number of invalid numbers to try before giving up on the text.
* This is to cover degenerate cases where the text has a lot of false positives in it. Must be >= 0
* @throws \NullPointerException
* @throws \InvalidArgumentException
*/
public function __construct(PhoneNumberUtil $util, $text, $country, AbstractLeniency $leniency, $maxTries)
{
if ($maxTries < 0) {
throw new \InvalidArgumentException();
}
$this->phoneUtil = $util;
$this->text = ($text !== null) ? $text : "";
$this->preferredRegion = $country;
$this->leniency = $leniency;
$this->maxTries = $maxTries;
if (static::$initialized === false) {
static::init();
}
}
/**
* Attempts to find the next subsequence in the searched sequence on or after {@code searchIndex}
* that represents a phone number. Returns the next match, null if none was found.
*
* @param int $index The search index to start searching at
* @return PhoneNumberMatch|null The Phone Number Match found, null if none can be found
*/
protected function find($index)
{
$matcher = new Matcher(static::$pattern, $this->text);
while (($this->maxTries > 0) && $matcher->find($index)) {
$start = $matcher->start();
$cutLength = $matcher->end() - $start;
$candidate = mb_substr($this->text, $start, $cutLength);
// Check for extra numbers at the end.
// TODO: This is the place to start when trying to support extraction of multiple phone number
// from split notations (+41 49 123 45 67 / 68).
$candidate = static::trimAfterFirstMatch(PhoneNumberUtil::$SECOND_NUMBER_START_PATTERN, $candidate);
$match = $this->extractMatch($candidate, $start);
if ($match !== null) {
return $match;
}
$index = $start + mb_strlen($candidate);
$this->maxTries--;
}
return null;
}
/**
* Trims away any characters after the first match of $pattern in $candidate,
* returning the trimmed version.
*
* @param string $pattern
* @param string $candidate
* @return string
*/
protected static function trimAfterFirstMatch($pattern, $candidate)
{
$trailingCharsMatcher = new Matcher($pattern, $candidate);
if ($trailingCharsMatcher->find()) {
$startChar = $trailingCharsMatcher->start();
$candidate = mb_substr($candidate, 0, $startChar);
}
return $candidate;
}
/**
* Helper method to determine if a character is a Latin-script letter or not. For our purposes,
* combining marks should also return true since we assume they have been added to a preceding
* Latin character.
*
* @param string $letter
* @return bool
* @internal
*/
public static function isLatinLetter($letter)
{
// Combining marks are a subset of non-spacing-mark.
if (preg_match('/\p{L}/u', $letter) !== 1 && preg_match('/\p{Mn}/u', $letter) !== 1) {
return false;
}
return (preg_match('/\p{Latin}/u', $letter) === 1)
|| (preg_match('/\pM+/u', $letter) === 1);
}
/**
* @param string $character
* @return bool
*/
protected static function isInvalidPunctuationSymbol($character)
{
return $character == '%' || preg_match('/\p{Sc}/u', $character);
}
/**
* Attempts to extract a match from a $candidate.
*
* @param string $candidate The candidate text that might contain a phone number
* @param int $offset The offset of $candidate within $this->text
* @return PhoneNumberMatch|null The match found, null if none can be found
*/
protected function extractMatch($candidate, $offset)
{
// Skip a match that is more likely to be a date.
$dateMatcher = new Matcher(static::$slashSeparatedDates, $candidate);
if ($dateMatcher->find()) {
return null;
}
// Skip potential time-stamps.
$timeStampMatcher = new Matcher(static::$timeStamps, $candidate);
if ($timeStampMatcher->find()) {
$followingText = mb_substr($this->text, $offset + mb_strlen($candidate));
$timeStampSuffixMatcher = new Matcher(static::$timeStampsSuffix, $followingText);
if ($timeStampSuffixMatcher->lookingAt()) {
return null;
}
}
// Try to come up with a valid match given the entire candidate.
$match = $this->parseAndVerify($candidate, $offset);
if ($match !== null) {
return $match;
}
// If that failed, try to find an "inner match" - there might be a phone number within this
// candidate.
return $this->extractInnerMatch($candidate, $offset);
}
/**
* Attempts to extract a match from $candidate if the whole candidate does not qualify as a
* match.
*
* @param string $candidate The candidate text that might contact a phone number
* @param int $offset The current offset of $candidate within $this->text
* @return PhoneNumberMatch|null The match found, null if none can be found
*/
protected function extractInnerMatch($candidate, $offset)
{
foreach (static::$innerMatches as $possibleInnerMatch) {
$groupMatcher = new Matcher($possibleInnerMatch, $candidate);
$isFirstMatch = true;
while ($groupMatcher->find() && $this->maxTries > 0) {
if ($isFirstMatch) {
// We should handle any group before this one too.
$group = static::trimAfterFirstMatch(PhoneNumberUtil::$UNWANTED_END_CHAR_PATTERN,
mb_substr($candidate, 0, $groupMatcher->start()));
$match = $this->parseAndVerify($group, $offset);
if ($match !== null) {
return $match;
}
$this->maxTries--;
$isFirstMatch = false;
}
$group = static::trimAfterFirstMatch(PhoneNumberUtil::$UNWANTED_END_CHAR_PATTERN,
$groupMatcher->group(1));
$match = $this->parseAndVerify($group, $offset + $groupMatcher->start(1));
if ($match !== null) {
return $match;
}
$this->maxTries--;
}
}
return null;
}
/**
* Parses a phone number from the $candidate} using PhoneNumberUtil::parse() and
* verifies it matches the requested leniency. If parsing and verification succeed, a
* corresponding PhoneNumberMatch is returned, otherwise this method returns null.
*
* @param string $candidate The candidate match
* @param int $offset The offset of $candidate within $this->text
* @return PhoneNumberMatch|null The parsed and validated phone number match, or null
*/
protected function parseAndVerify($candidate, $offset)
{
try {
// Check the candidate doesn't contain any formatting which would indicate that it really
// isn't a phone number
$matchingBracketsMatcher = new Matcher(static::$matchingBrackets, $candidate);
$pubPagesMatcher = new Matcher(static::$pubPages, $candidate);
if (!$matchingBracketsMatcher->matches() || $pubPagesMatcher->find()) {
return null;
}
// If leniency is set to VALID or stricter, we also want to skip numbers that are surrounded
// by Latin alphabetic characters, to skip cases like abc8005001234 or 8005001234def.
if ($this->leniency->compareTo(Leniency::VALID()) >= 0) {
// If the candidate is not at the start of the text, and does not start with phone-number
// punctuation, check the previous character.
$leadClassMatcher = new Matcher(static::$leadClass, $candidate);
if ($offset > 0 && !$leadClassMatcher->lookingAt()) {
$previousChar = mb_substr($this->text, $offset - 1, 1);
// We return null if it is a latin letter or an invalid punctuation symbol.
if (static::isInvalidPunctuationSymbol($previousChar) || static::isLatinLetter($previousChar)) {
return null;
}
}
$lastCharIndex = $offset + mb_strlen($candidate);
if ($lastCharIndex < mb_strlen($this->text)) {
$nextChar = mb_substr($this->text, $lastCharIndex, 1);
if (static::isInvalidPunctuationSymbol($nextChar) || static::isLatinLetter($nextChar)) {
return null;
}
}
}
$number = $this->phoneUtil->parseAndKeepRawInput($candidate, $this->preferredRegion);
// Check Israel * numbers: these are a special case in that they are four-digit numbers that
// our library supports, but they can only be dialled with a leading *. Since we don't
// actually store or detect the * in our phone number library, this means in practice we
// detect most four digit numbers as being valid for Israel. We are considering moving these
// numbers to ShortNumberInfo instead, in which case this problem would go away, but in the
// meantime we want to restrict the false matches so we only allow these numbers if they are
// preceded by a star. We enforce this for all leniency levels even though these numbers are
// technically accepted by isPossibleNumber and isValidNumber since we consider it to be a
// deficiency in those methods that they accept these numbers without the *.
// TODO: Remove this or make it significantly less hacky once we've decided how to
// handle these short codes going forward in ShortNumberInfo. We could use the formatting
// rules for instance, but that would be slower.
if ($this->phoneUtil->getRegionCodeForCountryCode($number->getCountryCode()) == "IL"
&& mb_strlen($this->phoneUtil->getNationalSignificantNumber($number)) === 4
&& ($offset === 0 || ($offset > 0 && mb_substr($this->text, $offset - 1, 1) != '*'))
) {
// No match.
return null;
}
if ($this->leniency->verify($number, $candidate, $this->phoneUtil)) {
// We used parseAndKeepRawInput to create this number, but for now we don't return the extra
// values parsed. TODO: stop clearing all values here and switch all users over
// to using rawInput() rather than the rawString() of PhoneNumberMatch
$number->clearCountryCodeSource();
$number->clearRawInput();
$number->clearPreferredDomesticCarrierCode();
return new PhoneNumberMatch($offset, $candidate, $number);
}
} catch (NumberParseException $e) {
// ignore and continue
}
return null;
}
/**
* @param PhoneNumberUtil $util
* @param PhoneNumber $number
* @param string $normalizedCandidate
* @param string[] $formattedNumberGroups
* @return bool
*/
public static function allNumberGroupsRemainGrouped(
PhoneNumberUtil $util,
PhoneNumber $number,
$normalizedCandidate,
$formattedNumberGroups
) {
$fromIndex = 0;
if ($number->getCountryCodeSource() !== CountryCodeSource::FROM_DEFAULT_COUNTRY) {
// First skip the country code if the normalized candidate contained it.
$countryCode = $number->getCountryCode();
$fromIndex = mb_strpos($normalizedCandidate, $countryCode) + mb_strlen($countryCode);
}
// Check each group of consecutive digits are not broken into separate groupings in the
// $normalizedCandidate string.
$formattedNumberGroupsLength = count($formattedNumberGroups);
for ($i = 0; $i < $formattedNumberGroupsLength; $i++) {
// Fails if the substring of $normalizedCandidate starting from $fromIndex
// doesn't contain the consecutive digits in $formattedNumberGroups[$i].
$fromIndex = mb_strpos($normalizedCandidate, $formattedNumberGroups[$i], $fromIndex);
if ($fromIndex === false) {
return false;
}
// Moves $fromIndex forward.
$fromIndex += mb_strlen($formattedNumberGroups[$i]);
if ($i === 0 && $fromIndex < mb_strlen($normalizedCandidate)) {
// We are at the position right after the NDC. We get the region used for formatting
// information based on the country code in the phone number, rather than the number itself,
// as we do not need to distinguish between different countries with the same country
// calling code and this is faster.
$region = $util->getRegionCodeForCountryCode($number->getCountryCode());
if ($util->getNddPrefixForRegion($region, true) !== null
&& is_int(mb_substr($normalizedCandidate, $fromIndex, 1))
) {
// This means there is no formatting symbol after the NDC. In this case, we only
// accept the number if there is no formatting symbol at all in the number, except
// for extensions. This is only important for countries with national prefixes.
$nationalSignificantNumber = $util->getNationalSignificantNumber($number);
return mb_substr(
mb_substr($normalizedCandidate, $fromIndex - mb_strlen($formattedNumberGroups[$i])),
mb_strlen($nationalSignificantNumber)
) === $nationalSignificantNumber;
}
}
}
// The check here makes sure that we haven't mistakenly already used the extension to
// match the last group of the subscriber number. Note the extension cannot have
// formatting in-between digits
if ($number->hasExtension()) {
return mb_strpos(mb_substr($normalizedCandidate, $fromIndex), $number->getExtension()) !== false;
}
return true;
}
/**
* @param PhoneNumberUtil $util
* @param PhoneNumber $number
* @param string $normalizedCandidate
* @param string[] $formattedNumberGroups
* @return bool
*/
public static function allNumberGroupsAreExactlyPresent(
PhoneNumberUtil $util,
PhoneNumber $number,
$normalizedCandidate,
$formattedNumberGroups
) {
$candidateGroups = preg_split(PhoneNumberUtil::NON_DIGITS_PATTERN, $normalizedCandidate);
// Set this to the last group, skipping it if the number has an extension.
$candidateNumberGroupIndex = $number->hasExtension() ? count($candidateGroups) - 2 : count($candidateGroups) - 1;
// First we check if the national significant number is formatted as a block.
// We use contains and not equals, since the national significant number may be present with
// a prefix such as a national number prefix, or the country code itself.
if (count($candidateGroups) == 1
|| mb_strpos($candidateGroups[$candidateNumberGroupIndex],
$util->getNationalSignificantNumber($number)) !== false
) {
return true;
}
// Starting from the end, go through in reverse, excluding the first group, and check the
// candidate and number groups are the same.
for ($formattedNumberGroupIndex = (count($formattedNumberGroups) - 1);
$formattedNumberGroupIndex > 0 && $candidateNumberGroupIndex >= 0;
$formattedNumberGroupIndex--, $candidateNumberGroupIndex--) {
if ($candidateGroups[$candidateNumberGroupIndex] != $formattedNumberGroups[$formattedNumberGroupIndex]) {
return false;
}
}
// Now check the first group. There may be a national prefix at the start, so we only check
// that the candidate group ends with the formatted number group.
return ($candidateNumberGroupIndex >= 0
&& mb_substr($candidateGroups[$candidateNumberGroupIndex],
-mb_strlen($formattedNumberGroups[0])) == $formattedNumberGroups[0]);
}
/**
* Helper method to get the national-number part of a number, formatted without any national
* prefix, and return it as a set of digit blocks that would be formatted together.
*
* @param PhoneNumberUtil $util
* @param PhoneNumber $number
* @param NumberFormat $formattingPattern
* @return string[]
*/
protected static function getNationalNumberGroups(
PhoneNumberUtil $util,
PhoneNumber $number,
NumberFormat $formattingPattern = null
) {
if ($formattingPattern === null) {
// This will be in the format +CC-DG;ext=EXT where DG represents groups of digits.
$rfc3966Format = $util->format($number, PhoneNumberFormat::RFC3966);
// We remove the extension part from the formatted string before splitting it into different
// groups.
$endIndex = mb_strpos($rfc3966Format, ';');
if ($endIndex === false) {
$endIndex = mb_strlen($rfc3966Format);
}
// The country-code will have a '-' following it.
$startIndex = mb_strpos($rfc3966Format, '-') + 1;
return explode('-', mb_substr($rfc3966Format, $startIndex, $endIndex - $startIndex));
} else {
// We format the NSN only, and split that according to the separator.
$nationalSignificantNumber = $util->getNationalSignificantNumber($number);
return explode('-', $util->formatNsnUsingPattern($nationalSignificantNumber, $formattingPattern,
PhoneNumberFormat::RFC3966));
}
}
/**
* @param PhoneNumber $number
* @param string $candidate
* @param PhoneNumberUtil $util
* @param \Closure $checker
* @return bool
*/
public static function checkNumberGroupingIsValid(
PhoneNumber $number,
$candidate,
PhoneNumberUtil $util,
\Closure $checker
) {
// TODO: Evaluate how this works for other locales (testing has been limited to NANPA regions)
// and optimise if necessary.
$normalizedCandidate = PhoneNumberUtil::normalizeDigits($candidate, true /* keep non-digits */);
$formattedNumberGroups = static::getNationalNumberGroups($util, $number, null);
if ($checker($util, $number, $normalizedCandidate, $formattedNumberGroups)) {
return true;
}
// If this didn't pass, see if there are any alternative formats, and try them instead.
$alternateFormats = static::getAlternateFormatsForCountry($number->getCountryCode());
if ($alternateFormats !== null) {
foreach ($alternateFormats->numberFormats() as $alternateFormat) {
$formattedNumberGroups = static::getNationalNumberGroups($util, $number, $alternateFormat);
if ($checker($util, $number, $normalizedCandidate, $formattedNumberGroups)) {
return true;
}
}
}
return false;
}
/**
* @param PhoneNumber $number
* @param string $candidate
* @return bool
*/
public static function containsMoreThanOneSlashInNationalNumber(PhoneNumber $number, $candidate)
{
$firstSlashInBodyIndex = mb_strpos($candidate, '/');
if ($firstSlashInBodyIndex === false) {
// No slashes, this is okay
return false;
}
// Now look for a second one.
$secondSlashInBodyIndex = mb_strpos($candidate, '/', $firstSlashInBodyIndex + 1);
if ($secondSlashInBodyIndex === false) {
// Only one slash, this is okay
return false;
}
// If the first slash is after the country calling code, this is permitted
$candidateHasCountryCode = ($number->getCountryCodeSource() === CountryCodeSource::FROM_NUMBER_WITH_PLUS_SIGN
|| $number->getCountryCodeSource() === CountryCodeSource::FROM_NUMBER_WITHOUT_PLUS_SIGN);
if ($candidateHasCountryCode
&& PhoneNumberUtil::normalizeDigitsOnly(
mb_substr($candidate, 0, $firstSlashInBodyIndex)
) == $number->getCountryCode()
) {
// Any more slashes and this is illegal
return (mb_strpos(mb_substr($candidate, $secondSlashInBodyIndex + 1), '/') !== false);
}
return true;
}
/**
* @param PhoneNumber $number
* @param string $candidate
* @param PhoneNumberUtil $util
* @return bool
*/
public static function containsOnlyValidXChars(PhoneNumber $number, $candidate, PhoneNumberUtil $util)
{
// The characters 'x' and 'X' can be (1) a carrier code, in which case they always precede the
// national significant number or (2) an extension sign, in which case they always precede the
// extension number. We assume a carrier code is more than 1 digit, so the first case has to
// have more than 1 consecutive 'x' or 'X', whereas the second case can only have exactly 1 'x'
// or 'X'. We ignore the character if it appears as the last character of the string.
$candidateLength = mb_strlen($candidate);
for ($index = 0; $index < $candidateLength - 1; $index++) {
$charAtIndex = mb_substr($candidate, $index, 1);
if ($charAtIndex == 'x' || $charAtIndex == 'X') {
$charAtNextIndex = mb_substr($candidate, $index + 1, 1);
if ($charAtNextIndex == 'x' || $charAtNextIndex == 'X') {
// This is the carrier code case, in which the 'X's always precede the national
// significant number.
$index++;
if ($util->isNumberMatch($number, mb_substr($candidate, $index)) != MatchType::NSN_MATCH) {
return false;
}
} elseif (!PhoneNumberUtil::normalizeDigitsOnly(mb_substr($candidate,
$index)) == $number->getExtension()
) {
// This is the extension sign case, in which the 'x' or 'X' should always precede the
// extension number
return false;
}
}
}
return true;
}
/**
* @param PhoneNumber $number
* @param PhoneNumberUtil $util
* @return bool
*/
public static function isNationalPrefixPresentIfRequired(PhoneNumber $number, PhoneNumberUtil $util)
{
// First, check how we deduced the country code. If it was written in international format, then
// the national prefix is not required.
if ($number->getCountryCodeSource() !== CountryCodeSource::FROM_DEFAULT_COUNTRY) {
return true;
}
$phoneNumberRegion = $util->getRegionCodeForCountryCode($number->getCountryCode());
$metadata = $util->getMetadataForRegion($phoneNumberRegion);
if ($metadata === null) {
return true;
}
// Check if a national prefix should be present when formatting this number.
$nationalNumber = $util->getNationalSignificantNumber($number);
$formatRule = $util->chooseFormattingPatternForNumber($metadata->numberFormats(), $nationalNumber);
// To do this, we check that a national prefix formatting rule was present and that it wasn't
// just the first-group symbol ($1) with punctuation.
if (($formatRule !== null) && mb_strlen($formatRule->getNationalPrefixFormattingRule()) > 0) {
if ($formatRule->getNationalPrefixOptionalWhenFormatting()) {
// The national-prefix is optional in these cases, so we don't need to check if it was
// present.
return true;
}
if (PhoneNumberUtil::formattingRuleHasFirstGroupOnly($formatRule->getNationalPrefixFormattingRule())) {
// National Prefix not needed for this number.
return true;
}
// Normalize the remainder.
$rawInputCopy = PhoneNumberUtil::normalizeDigitsOnly($number->getRawInput());
$rawInput = $rawInputCopy;
// Check if we found a national prefix and/or carrier code at the start of the raw input, and
// return the result.
$carrierCode = null;
return $util->maybeStripNationalPrefixAndCarrierCode($rawInput, $metadata, $carrierCode);
}
return true;
}
/**
* Storage for Alternate Formats
* @var PhoneMetadata[]
*/
protected static $callingCodeToAlternateFormatsMap = array();
/**
* @param $countryCallingCode
* @return PhoneMetadata|null
*/
protected static function getAlternateFormatsForCountry($countryCallingCode)
{
$countryCodeSet = AlternateFormatsCountryCodeSet::$alternateFormatsCountryCodeSet;
if (!in_array($countryCallingCode, $countryCodeSet)) {
return null;
}
if (!isset(static::$callingCodeToAlternateFormatsMap[$countryCallingCode])) {
static::loadAlternateFormatsMetadataFromFile($countryCallingCode);
}
return static::$callingCodeToAlternateFormatsMap[$countryCallingCode];
}
/**
* @param string $countryCallingCode
* @throws \Exception
*/
protected static function loadAlternateFormatsMetadataFromFile($countryCallingCode)
{
$fileName = static::$alternateFormatsFilePrefix . '_' . $countryCallingCode . '.php';
if (!is_readable($fileName)) {
throw new \Exception('missing metadata: ' . $fileName);
}
$metadataLoader = new DefaultMetadataLoader();
$data = $metadataLoader->loadMetadata($fileName);
$metadata = new PhoneMetadata();
$metadata->fromArray($data);
static::$callingCodeToAlternateFormatsMap[$countryCallingCode] = $metadata;
}
/**
* Return the current element
* @link http://php.net/manual/en/iterator.current.php
* @return PhoneNumberMatch|null
*/
public function current()
{
return $this->lastMatch;
}
/**
* Move forward to next element
* @link http://php.net/manual/en/iterator.next.php
* @return void Any returned value is ignored.
*/
public function next()
{
$this->lastMatch = $this->find($this->searchIndex);
if ($this->lastMatch === null) {
$this->state = 'DONE';
} else {
$this->searchIndex = $this->lastMatch->end();
$this->state = 'READY';
}
$this->searchIndex++;
}
/**
* Return the key of the current element
* @link http://php.net/manual/en/iterator.key.php
* @return mixed scalar on success, or null on failure.
* @since 5.0.0
*/
public function key()
{
return $this->searchIndex;
}
/**
* Checks if current position is valid
* @link http://php.net/manual/en/iterator.valid.php
* @return boolean The return value will be casted to boolean and then evaluated.
* Returns true on success or false on failure.
* @since 5.0.0
*/
public function valid()
{
return $this->state === 'READY';
}
/**
* Rewind the Iterator to the first element
* @link http://php.net/manual/en/iterator.rewind.php
* @return void Any returned value is ignored.
* @since 5.0.0
*/
public function rewind()
{
$this->searchIndex = 0;
$this->next();
}
}

View File

@ -0,0 +1,131 @@
<?php
/**
*
*
* @author giggsey
* @created: 02/10/13 16:52
* @project libphonenumber-for-php
*/
namespace libphonenumber;
use Giggsey\Locale\Locale;
use libphonenumber\prefixmapper\PrefixFileReader;
class PhoneNumberToCarrierMapper
{
/**
* @var PhoneNumberToCarrierMapper[]
*/
protected static $instance = array();
const MAPPING_DATA_DIRECTORY = '/carrier/data/';
/**
* @var PhoneNumberUtil
*/
protected $phoneUtil;
/**
* @var PrefixFileReader
*/
protected $prefixFileReader;
protected function __construct($phonePrefixDataDirectory)
{
$this->prefixFileReader = new PrefixFileReader(__DIR__ . DIRECTORY_SEPARATOR . $phonePrefixDataDirectory);
$this->phoneUtil = PhoneNumberUtil::getInstance();
}
/**
* Gets a {@link PhoneNumberToCarrierMapper} instance to carry out international carrier lookup.
*
* <p> The {@link PhoneNumberToCarrierMapper} is implemented as a singleton. Therefore, calling
* this method multiple times will only result in one instance being created.
*
* @param string $mappingDir
* @return PhoneNumberToCarrierMapper
*/
public static function getInstance($mappingDir = self::MAPPING_DATA_DIRECTORY)
{
if (!array_key_exists($mappingDir, static::$instance)) {
static::$instance[$mappingDir] = new static($mappingDir);
}
return static::$instance[$mappingDir];
}
/**
* Returns a carrier name for the given phone number, in the language provided. The carrier name
* is the one the number was originally allocated to, however if the country supports mobile
* number portability the number might not belong to the returned carrier anymore. If no mapping
* is found an empty string is returned.
*
* <p>This method assumes the validity of the number passed in has already been checked, and that
* the number is suitable for carrier lookup. We consider mobile and pager numbers possible
* candidates for carrier lookup.
*
* @param PhoneNumber $number a valid phone number for which we want to get a carrier name
* @param string $languageCode the language code in which the name should be written
* @return string a carrier name for the given phone number
*/
public function getNameForValidNumber(PhoneNumber $number, $languageCode)
{
$languageStr = Locale::getPrimaryLanguage($languageCode);
$scriptStr = "";
$regionStr = Locale::getRegion($languageCode);
return $this->prefixFileReader->getDescriptionForNumber($number, $languageStr, $scriptStr, $regionStr);
}
/**
* Gets the name of the carrier for the given phone number, in the language provided. As per
* {@link #getNameForValidNumber(PhoneNumber, Locale)} but explicitly checks the validity of
* the number passed in.
*
* @param PhoneNumber $number The phone number for which we want to get a carrier name
* @param string $languageCode Language code for which the description should be written
* @return string a carrier name for the given phone number, or empty string if the number passed in is
* invalid
*/
public function getNameForNumber(PhoneNumber $number, $languageCode)
{
$numberType = $this->phoneUtil->getNumberType($number);
if ($this->isMobile($numberType)) {
return $this->getNameForValidNumber($number, $languageCode);
}
return "";
}
/**
* Gets the name of the carrier for the given phone number only when it is 'safe' to display to
* users. A carrier name is considered safe if the number is valid and for a region that doesn't
* support
* {@linkplain http://en.wikipedia.org/wiki/Mobile_number_portability mobile number portability}.
*
* @param $number PhoneNumber the phone number for which we want to get a carrier name
* @param $languageCode String the language code in which the name should be written
* @return string a carrier name that is safe to display to users, or the empty string
*/
public function getSafeDisplayName(PhoneNumber $number, $languageCode)
{
if ($this->phoneUtil->isMobileNumberPortableRegion($this->phoneUtil->getRegionCodeForNumber($number))) {
return "";
}
return $this->getNameForNumber($number, $languageCode);
}
/**
* Checks if the supplied number type supports carrier lookup.
* @param int $numberType A PhoneNumberType int
* @return bool
*/
protected function isMobile($numberType)
{
return ($numberType === PhoneNumberType::MOBILE ||
$numberType === PhoneNumberType::FIXED_LINE_OR_MOBILE ||
$numberType === PhoneNumberType::PAGER
);
}
}

View File

@ -0,0 +1,141 @@
<?php
/**
* Created by PhpStorm.
* User: giggsey
* Date: 14/10/13
* Time: 16:00
*/
namespace libphonenumber;
use libphonenumber\prefixmapper\PrefixTimeZonesMap;
class PhoneNumberToTimeZonesMapper
{
const UNKNOWN_TIMEZONE = 'Etc/Unknown';
const MAPPING_DATA_DIRECTORY = '/timezone/data/';
const MAPPING_DATA_FILE_NAME = "map_data.php";
/**
* @var PhoneNumberToTimeZonesMapper
*/
protected static $instance = null;
protected $unknownTimeZoneList = array();
/**
* @var PhoneNumberUtil
*/
protected $phoneUtil;
protected $prefixTimeZonesMap;
protected function __construct($phonePrefixDataDirectory)
{
$this->prefixTimeZonesMap = static::loadPrefixTimeZonesMapFromFile(
dirname(__FILE__) . $phonePrefixDataDirectory . DIRECTORY_SEPARATOR . static::MAPPING_DATA_FILE_NAME
);
$this->phoneUtil = PhoneNumberUtil::getInstance();
$this->unknownTimeZoneList[] = static::UNKNOWN_TIMEZONE;
}
protected static function loadPrefixTimeZonesMapFromFile($path)
{
if (!is_readable($path)) {
throw new \InvalidArgumentException("Mapping file can not be found");
}
$data = require $path;
$map = new PrefixTimeZonesMap($data);
return $map;
}
/**
* Gets a {@link PhoneNumberToTimeZonesMapper} instance.
*
* <p> The {@link PhoneNumberToTimeZonesMapper} is implemented as a singleton. Therefore, calling
* this method multiple times will only result in one instance being created.
*
* @param $mappingDir
* @return PhoneNumberToTimeZonesMapper instance
*/
public static function getInstance($mappingDir = self::MAPPING_DATA_DIRECTORY)
{
if (static::$instance === null) {
static::$instance = new static($mappingDir);
}
return static::$instance;
}
/**
* Returns a String with the ICU unknown time zone.
* @return string
*/
public static function getUnknownTimeZone()
{
return static::UNKNOWN_TIMEZONE;
}
/**
* As per {@link #getTimeZonesForGeographicalNumber(PhoneNumber)} but explicitly checks
* the validity of the number passed in.
*
* @param $number PhoneNumber the phone number for which we want to get the time zones to which it belongs
* @return array a list of the corresponding time zones or a single element list with the default
* unknown time zone if no other time zone was found or if the number was invalid
*/
public function getTimeZonesForNumber(PhoneNumber $number)
{
$numberType = $this->phoneUtil->getNumberType($number);
if ($numberType === PhoneNumberType::UNKNOWN) {
return $this->unknownTimeZoneList;
} elseif (!PhoneNumberUtil::getInstance()->isNumberGeographical($numberType, $number->getCountryCode())) {
return $this->getCountryLevelTimeZonesforNumber($number);
}
return $this->getTimeZonesForGeographicalNumber($number);
}
/**
* Returns the list of time zones corresponding to the country calling code of {@code number}.
*
* @param $number PhoneNumber the phone number to look up
* @return array the list of corresponding time zones or a single element list with the default
* unknown time zone if no other time zone was found
*/
protected function getCountryLevelTimeZonesforNumber(PhoneNumber $number)
{
$timezones = $this->prefixTimeZonesMap->lookupCountryLevelTimeZonesForNumber($number);
return (count($timezones) == 0) ? $this->unknownTimeZoneList : $timezones;
}
/**
* Returns a list of time zones to which a phone number belongs.
*
* <p>This method assumes the validity of the number passed in has already been checked, and that
* the number is geo-localizable. We consider fixed-line and mobile numbers possible candidates
* for geo-localization.
*
* @param $number PhoneNumber a valid phone number for which we want to get the time zones to which it belongs
* @return array a list of the corresponding time zones or a single element list with the default
* unknown time zone if no other time zone was found or if the number was invalid
*/
public function getTimeZonesForGeographicalNumber(PhoneNumber $number)
{
return $this->getTimeZonesForGeocodableNumber($number);
}
/**
* Returns a list of time zones to which a geocodable phone number belongs.
*
* @param PhoneNumber $number The phone number for which we want to get the time zones to which it belongs
* @return array the list of correspondiing time zones or a single element list with the default
* unknown timezone if no other time zone was found or if the number was invalid
*/
protected function getTimeZonesForGeocodableNumber(PhoneNumber $number)
{
$timezones = $this->prefixTimeZonesMap->lookupTimeZonesForNumber($number);
return (count($timezones) == 0) ? $this->unknownTimeZoneList : $timezones;
}
}

View File

@ -0,0 +1,68 @@
<?php
namespace libphonenumber;
/**
* Type of phone numbers.
*/
class PhoneNumberType
{
const FIXED_LINE = 0;
const MOBILE = 1;
// In some regions (e.g. the USA), it is impossible to distinguish between fixed-line and
// mobile numbers by looking at the phone number itself.
const FIXED_LINE_OR_MOBILE = 2;
// Freephone lines
const TOLL_FREE = 3;
const PREMIUM_RATE = 4;
// The cost of this call is shared between the caller and the recipient, and is hence typically
// less than PREMIUM_RATE calls. See // http://en.wikipedia.org/wiki/Shared_Cost_Service for
// more information.
const SHARED_COST = 5;
// Voice over IP numbers. This includes TSoIP (Telephony Service over IP).
const VOIP = 6;
// A personal number is associated with a particular person, and may be routed to either a
// MOBILE or FIXED_LINE number. Some more information can be found here:
// http://en.wikipedia.org/wiki/Personal_Numbers
const PERSONAL_NUMBER = 7;
const PAGER = 8;
// Used for "Universal Access Numbers" or "Company Numbers". They may be further routed to
// specific offices, but allow one number to be used for a company.
const UAN = 9;
// A phone number is of type UNKNOWN when it does not fit any of the known patterns for a
// specific region.
const UNKNOWN = 10;
// Emergency
const EMERGENCY = 27;
// Voicemail
const VOICEMAIL = 28;
// Short Code
const SHORT_CODE = 29;
// Standard Rate
const STANDARD_RATE = 30;
public static function values()
{
return array(
self::FIXED_LINE => 'FIXED_LINE',
self::MOBILE => 'MOBILE',
self::FIXED_LINE_OR_MOBILE => 'FIXED_LINE_OR_MOBILE',
self::TOLL_FREE => 'TOLL_FREE',
self::PREMIUM_RATE => 'PREMIUM_RATE',
self::SHARED_COST => 'SHARED_COST',
self::VOIP => 'VOIP',
self::PERSONAL_NUMBER => 'PERSONAL_NUMBER',
self::PAGER => 'PAGER',
self::UAN => 'UAN',
self::UNKNOWN => 'UNKNOWN',
self::EMERGENCY => 'EMERGENCY',
self::VOICEMAIL => 'VOICEMAIL',
self::SHORT_CODE => 'SHORT_CODE',
self::STANDARD_RATE => 'STANDARD_RATE',
);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,56 @@
<?php
namespace libphonenumber;
/**
* Class RegexBasedMatcher
* @package libphonenumber
* @internal
*/
class RegexBasedMatcher implements MatcherAPIInterface
{
public static function create()
{
return new static();
}
/**
* Returns whether the given national number (a string containing only decimal digits) matches
* the national number pattern defined in the given {@code PhoneNumberDesc} message.
*
* @param string $number
* @param PhoneNumberDesc $numberDesc
* @param boolean $allowPrefixMatch
* @return boolean
*/
public function matchNationalNumber($number, PhoneNumberDesc $numberDesc, $allowPrefixMatch)
{
$nationalNumberPattern = $numberDesc->getNationalNumberPattern();
// We don't want to consider it a prefix match when matching non-empty input against an empty
// pattern
if (strlen($nationalNumberPattern) === 0) {
return false;
}
return $this->match($number, $nationalNumberPattern, $allowPrefixMatch);
}
/**
* @param string $number
* @param string $pattern
* @param $allowPrefixMatch
* @return bool
*/
private function match($number, $pattern, $allowPrefixMatch)
{
$matcher = new Matcher($pattern, $number);
if (!$matcher->lookingAt()) {
return false;
} else {
return ($matcher->matches()) ? true : $allowPrefixMatch;
}
}
}

View File

@ -0,0 +1,64 @@
<?php
/*
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
namespace libphonenumber;
/**
* Class containing string constants of region codes for easier testing.
*/
class RegionCode
{
// Region code for global networks (e.g. +800 numbers).
const UN001 = "001";
const AD = "AD";
const AE = "AE";
const AM = "AM";
const AO = "AO";
const AQ = "AQ";
const AR = "AR";
const AU = "AU";
const BB = "BB";
const BR = "BR";
const BS = "BS";
const BY = "BY";
const CA = "CA";
const CH = "CH";
const CL = "CL";
const CN = "CN";
const CS = "CS";
const CX = "CX";
const DE = "DE";
const FR = "FR";
const GB = "GB";
const HU = "HU";
const IT = "IT";
const JP = "JP";
const KR = "KR";
const MX = "MX";
const NZ = "NZ";
const PG = "PG";
const PL = "PL";
const RE = "RE";
const SE = "SE";
const SG = "SG";
const US = "US";
const UZ = 'UZ';
const YT = "YT";
const ZW = "ZW";
// Official code for the unknown region.
const ZZ = "ZZ";
}

View File

@ -0,0 +1,15 @@
<?php
namespace libphonenumber;
/**
* Cost categories of short numbers
* @package libphonenumber
*/
class ShortNumberCost
{
const TOLL_FREE = 3;
const PREMIUM_RATE = 4;
const STANDARD_RATE = 30;
const UNKNOWN_COST = 10;
}

View File

@ -0,0 +1,650 @@
<?php
/**
* Methods for getting information about short phone numbers, such as short codes and emergency
* numbers. Note that most commercial short numbers are not handled here, but by the
* {@link PhoneNumberUtil}.
*
* @author Shaopeng Jia
* @author David Yonge-Mallo
* @since 5.8
*/
namespace libphonenumber;
class ShortNumberInfo
{
const META_DATA_FILE_PREFIX = 'ShortNumberMetadata';
/**
* @var ShortNumberInfo
*/
protected static $instance = null;
/**
* @var MatcherAPIInterface
*/
protected $matcherAPI;
protected $currentFilePrefix;
protected $regionToMetadataMap = array();
protected $countryCallingCodeToRegionCodeMap = array();
protected $countryCodeToNonGeographicalMetadataMap = array();
protected static $regionsWhereEmergencyNumbersMustBeExact = array(
'BR',
'CL',
'NI',
);
protected function __construct(MatcherAPIInterface $matcherAPI)
{
$this->matcherAPI = $matcherAPI;
// TODO: Create ShortNumberInfo for a given map
$this->countryCallingCodeToRegionCodeMap = CountryCodeToRegionCodeMap::$countryCodeToRegionCodeMap;
$this->currentFilePrefix = dirname(__FILE__) . '/data/' . static::META_DATA_FILE_PREFIX;
// Initialise PhoneNumberUtil to make sure regex's are setup correctly
PhoneNumberUtil::getInstance();
}
/**
* Returns the singleton instance of ShortNumberInfo
*
* @return \libphonenumber\ShortNumberInfo
*/
public static function getInstance()
{
if (null === static::$instance) {
static::$instance = new self(RegexBasedMatcher::create());
}
return static::$instance;
}
public static function resetInstance()
{
static::$instance = null;
}
/**
* Returns a list with teh region codes that match the specific country calling code. For
* non-geographical country calling codes, the region code 001 is returned. Also, in the case
* of no region code being found, an empty list is returned.
*
* @param int $countryCallingCode
* @return array
*/
protected function getRegionCodesForCountryCode($countryCallingCode)
{
if (!array_key_exists($countryCallingCode, $this->countryCallingCodeToRegionCodeMap)) {
$regionCodes = null;
} else {
$regionCodes = $this->countryCallingCodeToRegionCodeMap[$countryCallingCode];
}
return ($regionCodes === null) ? array() : $regionCodes;
}
/**
* Helper method to check that the country calling code of the number matches the region it's
* being dialed from.
* @param PhoneNumber $number
* @param string $regionDialingFrom
* @return bool
*/
protected function regionDialingFromMatchesNumber(PhoneNumber $number, $regionDialingFrom)
{
$regionCodes = $this->getRegionCodesForCountryCode($number->getCountryCode());
return in_array($regionDialingFrom, $regionCodes);
}
public function getSupportedRegions()
{
return ShortNumbersRegionCodeSet::$shortNumbersRegionCodeSet;
}
/**
* Gets a valid short number for the specified region.
*
* @param $regionCode String the region for which an example short number is needed
* @return string a valid short number for the specified region. Returns an empty string when the
* metadata does not contain such information.
*/
public function getExampleShortNumber($regionCode)
{
$phoneMetadata = $this->getMetadataForRegion($regionCode);
if ($phoneMetadata === null) {
return "";
}
/** @var PhoneNumberDesc $desc */
$desc = $phoneMetadata->getShortCode();
if ($desc !== null && $desc->hasExampleNumber()) {
return $desc->getExampleNumber();
}
return "";
}
/**
* @param $regionCode
* @return PhoneMetadata|null
*/
public function getMetadataForRegion($regionCode)
{
if (!in_array($regionCode, ShortNumbersRegionCodeSet::$shortNumbersRegionCodeSet)) {
return null;
}
if (!isset($this->regionToMetadataMap[$regionCode])) {
// The regionCode here will be valid and won't be '001', so we don't need to worry about
// what to pass in for the country calling code.
$this->loadMetadataFromFile($this->currentFilePrefix, $regionCode, 0);
}
return isset($this->regionToMetadataMap[$regionCode]) ? $this->regionToMetadataMap[$regionCode] : null;
}
protected function loadMetadataFromFile($filePrefix, $regionCode, $countryCallingCode)
{
$isNonGeoRegion = PhoneNumberUtil::REGION_CODE_FOR_NON_GEO_ENTITY === $regionCode;
$fileName = $filePrefix . '_' . ($isNonGeoRegion ? $countryCallingCode : $regionCode) . '.php';
if (!is_readable($fileName)) {
throw new \Exception('missing metadata: ' . $fileName);
}
$metadataLoader = new DefaultMetadataLoader();
$data = $metadataLoader->loadMetadata($fileName);
$metadata = new PhoneMetadata();
$metadata->fromArray($data);
if ($isNonGeoRegion) {
$this->countryCodeToNonGeographicalMetadataMap[$countryCallingCode] = $metadata;
} else {
$this->regionToMetadataMap[$regionCode] = $metadata;
}
}
/**
* Gets a valid short number for the specified cost category.
*
* @param string $regionCode the region for which an example short number is needed
* @param int $cost the cost category of number that is needed
* @return string a valid short number for the specified region and cost category. Returns an empty string
* when the metadata does not contain such information, or the cost is UNKNOWN_COST.
*/
public function getExampleShortNumberForCost($regionCode, $cost)
{
$phoneMetadata = $this->getMetadataForRegion($regionCode);
if ($phoneMetadata === null) {
return "";
}
/** @var PhoneNumberDesc $desc */
$desc = null;
switch ($cost) {
case ShortNumberCost::TOLL_FREE:
$desc = $phoneMetadata->getTollFree();
break;
case ShortNumberCost::STANDARD_RATE:
$desc = $phoneMetadata->getStandardRate();
break;
case ShortNumberCost::PREMIUM_RATE:
$desc = $phoneMetadata->getPremiumRate();
break;
default:
// UNKNOWN_COST numbers are computed by the process of elimination from the other cost categories
break;
}
if ($desc !== null && $desc->hasExampleNumber()) {
return $desc->getExampleNumber();
}
return "";
}
/**
* Returns true if the given number, exactly as dialed, might be used to connect to an emergency
* service in the given region.
* <p>
* This method accepts a string, rather than a PhoneNumber, because it needs to distinguish
* cases such as "+1 911" and "911", where the former may not connect to an emergency service in
* all cases but the latter would. This method takes into account cases where the number might
* contain formatting, or might have additional digits appended (when it is okay to do that in
* the specified region).
*
* @param string $number the phone number to test
* @param string $regionCode the region where the phone number if being dialled
* @return boolean whether the number might be used to connect to an emergency service in the given region
*/
public function connectsToEmergencyNumber($number, $regionCode)
{
return $this->matchesEmergencyNumberHelper($number, $regionCode, true /* allows prefix match */);
}
/**
* @param string $number
* @param string $regionCode
* @param bool $allowPrefixMatch
* @return bool
*/
protected function matchesEmergencyNumberHelper($number, $regionCode, $allowPrefixMatch)
{
$number = PhoneNumberUtil::extractPossibleNumber($number);
$matcher = new Matcher(PhoneNumberUtil::$PLUS_CHARS_PATTERN, $number);
if ($matcher->lookingAt()) {
// Returns false if the number starts with a plus sign. We don't believe dialing the country
// code before emergency numbers (e.g. +1911) works, but later, if that proves to work, we can
// add additional logic here to handle it.
return false;
}
$metadata = $this->getMetadataForRegion($regionCode);
if ($metadata === null || !$metadata->hasEmergency()) {
return false;
}
$normalizedNumber = PhoneNumberUtil::normalizeDigitsOnly($number);
$emergencyDesc = $metadata->getEmergency();
$allowPrefixMatchForRegion = ($allowPrefixMatch
&& !in_array($regionCode, static::$regionsWhereEmergencyNumbersMustBeExact)
);
return $this->matcherAPI->matchNationalNumber($normalizedNumber, $emergencyDesc, $allowPrefixMatchForRegion);
}
/**
* Given a valid short number, determines whether it is carrier-specific (however, nothing is
* implied about its validity). Carrier-specific numbers may connect to a different end-point, or
* not connect at all, depending on the user's carrier. If it is important that the number is
* valid, then its validity must first be checked using {@link #isValidShortNumber} or
* {@link #isValidShortNumberForRegion}.
*
* @param PhoneNumber $number the valid short number to check
* @return boolean whether the short number is carrier-specific, assuming the input was a valid short
* number
*/
public function isCarrierSpecific(PhoneNumber $number)
{
$regionCodes = $this->getRegionCodesForCountryCode($number->getCountryCode());
$regionCode = $this->getRegionCodeForShortNumberFromRegionList($number, $regionCodes);
$nationalNumber = $this->getNationalSignificantNumber($number);
$phoneMetadata = $this->getMetadataForRegion($regionCode);
return ($phoneMetadata !== null) && ($this->matchesPossibleNumberAndNationalNumber(
$nationalNumber,
$phoneMetadata->getCarrierSpecific()
));
}
/**
* Given a valid short number, determines whether it is carrier-specific when dialed from the
* given region (however, nothing is implied about its validity). Carrier-specific numbers may
* connect to a different end-point, or not connect at all, depending on the user's carrier. If
* it is important that the number is valid, then its validity must first be checked using
* {@link #isValidShortNumber} or {@link #isValidShortNumberForRegion}. Returns false if the
* number doesn't match the region provided.
* @param PhoneNumber $number The valid short number to check
* @param string $regionDialingFrom The region from which the number is dialed
* @return bool Whether the short number is carrier-specific in the provided region, assuming the
* input was a valid short number
*/
public function isCarrierSpecificForRegion(PhoneNumber $number, $regionDialingFrom)
{
if (!$this->regionDialingFromMatchesNumber($number, $regionDialingFrom)) {
return false;
}
$nationalNumber = $this->getNationalSignificantNumber($number);
$phoneMetadata = $this->getMetadataForRegion($regionDialingFrom);
return ($phoneMetadata !== null)
&& ($this->matchesPossibleNumberAndNationalNumber($nationalNumber, $phoneMetadata->getCarrierSpecific()));
}
/**
* Given a valid short number, determines whether it is an SMS service (however, nothing is
* implied about its validity). An SMS service is where the primary or only intended usage is to
* receive and/or send text messages (SMSs). This includes MMS as MMS numbers downgrade to SMS if
* the other party isn't MMS-capable. If it is important that the number is valid, then its
* validity must first be checked using {@link #isValidShortNumber} or {@link
* #isValidShortNumberForRegion}. Returns false if the number doesn't match the region provided.
*
* @param PhoneNumber $number The valid short number to check
* @param string $regionDialingFrom The region from which the number is dialed
* @return bool Whether the short number is an SMS service in the provided region, assuming the input
* was a valid short number.
*/
public function isSmsServiceForRegion(PhoneNumber $number, $regionDialingFrom)
{
if (!$this->regionDialingFromMatchesNumber($number, $regionDialingFrom)) {
return false;
}
$phoneMetadata = $this->getMetadataForRegion($regionDialingFrom);
return ($phoneMetadata !== null)
&& $this->matchesPossibleNumberAndNationalNumber(
$this->getNationalSignificantNumber($number),
$phoneMetadata->getSmsServices()
);
}
/**
* Helper method to get the region code for a given phone number, from a list of possible region
* codes. If the list contains more than one region, the first region for which the number is
* valid is returned.
*
* @param PhoneNumber $number
* @param $regionCodes
* @return String|null Region Code (or null if none are found)
*/
protected function getRegionCodeForShortNumberFromRegionList(PhoneNumber $number, $regionCodes)
{
if (count($regionCodes) == 0) {
return null;
} elseif (count($regionCodes) == 1) {
return $regionCodes[0];
}
$nationalNumber = $this->getNationalSignificantNumber($number);
foreach ($regionCodes as $regionCode) {
$phoneMetadata = $this->getMetadataForRegion($regionCode);
if ($phoneMetadata !== null
&& $this->matchesPossibleNumberAndNationalNumber($nationalNumber, $phoneMetadata->getShortCode())
) {
// The number is valid for this region.
return $regionCode;
}
}
return null;
}
/**
* Check whether a short number is a possible number. If a country calling code is shared by
* multiple regions, this returns true if it's possible in any of them. This provides a more
* lenient check than {@link #isValidShortNumber}. See {@link
* #IsPossibleShortNumberForRegion(PhoneNumber, String)} for details.
*
* @param $number PhoneNumber the short number to check
* @return boolean whether the number is a possible short number
*/
public function isPossibleShortNumber(PhoneNumber $number)
{
$regionCodes = $this->getRegionCodesForCountryCode($number->getCountryCode());
$shortNumberLength = strlen($this->getNationalSignificantNumber($number));
foreach ($regionCodes as $region) {
$phoneMetadata = $this->getMetadataForRegion($region);
if ($phoneMetadata === null) {
continue;
}
if (in_array($shortNumberLength, $phoneMetadata->getGeneralDesc()->getPossibleLength())) {
return true;
}
}
return false;
}
/**
* Check whether a short number is a possible number when dialled from a region, given the number
* in the form of a string, and the region where the number is dialled from. This provides a more
* lenient check than {@link #isValidShortNumber}.
*
* @param PhoneNumber $shortNumber The short number to check
* @param string $regionDialingFrom Region dialing From
* @return boolean whether the number is a possible short number
*/
public function isPossibleShortNumberForRegion(PhoneNumber $shortNumber, $regionDialingFrom)
{
if (!$this->regionDialingFromMatchesNumber($shortNumber, $regionDialingFrom)) {
return false;
}
$phoneMetadata = $this->getMetadataForRegion($regionDialingFrom);
if ($phoneMetadata === null) {
return false;
}
$numberLength = strlen($this->getNationalSignificantNumber($shortNumber));
return in_array($numberLength, $phoneMetadata->getGeneralDesc()->getPossibleLength());
}
/**
* Tests whether a short number matches a valid pattern. If a country calling code is shared by
* multiple regions, this returns true if it's valid in any of them. Note that this doesn't verify
* the number is actually in use, which is impossible to tell by just looking at the number
* itself. See {@link #isValidShortNumberForRegion(PhoneNumber, String)} for details.
*
* @param $number PhoneNumber the short number for which we want to test the validity
* @return boolean whether the short number matches a valid pattern
*/
public function isValidShortNumber(PhoneNumber $number)
{
$regionCodes = $this->getRegionCodesForCountryCode($number->getCountryCode());
$regionCode = $this->getRegionCodeForShortNumberFromRegionList($number, $regionCodes);
if (count($regionCodes) > 1 && $regionCode !== null) {
// If a matching region had been found for the phone number from among two or more regions,
// then we have already implicitly verified its validity for that region.
return true;
}
return $this->isValidShortNumberForRegion($number, $regionCode);
}
/**
* Tests whether a short number matches a valid pattern in a region. Note that this doesn't verify
* the number is actually in use, which is impossible to tell by just looking at the number
* itself.
*
* @param PhoneNumber $number The Short number for which we want to test the validity
* @param string $regionDialingFrom the region from which the number is dialed
* @return boolean whether the short number matches a valid pattern
*/
public function isValidShortNumberForRegion(PhoneNumber $number, $regionDialingFrom)
{
if (!$this->regionDialingFromMatchesNumber($number, $regionDialingFrom)) {
return false;
}
$phoneMetadata = $this->getMetadataForRegion($regionDialingFrom);
if ($phoneMetadata === null) {
return false;
}
$shortNumber = $this->getNationalSignificantNumber($number);
$generalDesc = $phoneMetadata->getGeneralDesc();
if (!$this->matchesPossibleNumberAndNationalNumber($shortNumber, $generalDesc)) {
return false;
}
$shortNumberDesc = $phoneMetadata->getShortCode();
return $this->matchesPossibleNumberAndNationalNumber($shortNumber, $shortNumberDesc);
}
/**
* Gets the expected cost category of a short number when dialled from a region (however, nothing is
* implied about its validity). If it is important that the number is valid, then its validity
* must first be checked using {@link isValidShortNumberForRegion}. Note that emergency numbers
* are always considered toll-free.
* Example usage:
* <pre>{@code
* $shortInfo = ShortNumberInfo::getInstance();
* $shortNumber = PhoneNumberUtil::parse("110", "US);
* $regionCode = "FR";
* if ($shortInfo->isValidShortNumberForRegion($shortNumber, $regionCode)) {
* $cost = $shortInfo->getExpectedCostForRegion($shortNumber, $regionCode);
* // Do something with the cost information here.
* }}</pre>
*
* @param PhoneNumber $number the short number for which we want to know the expected cost category,
* as a string
* @param string $regionDialingFrom the region from which the number is dialed
* @return int the expected cost category for that region of the short number. Returns UNKNOWN_COST if
* the number does not match a cost category. Note that an invalid number may match any cost
* category.
*/
public function getExpectedCostForRegion(PhoneNumber $number, $regionDialingFrom)
{
if (!$this->regionDialingFromMatchesNumber($number, $regionDialingFrom)) {
return ShortNumberCost::UNKNOWN_COST;
}
// Note that regionDialingFrom may be null, in which case phoneMetadata will also be null.
$phoneMetadata = $this->getMetadataForRegion($regionDialingFrom);
if ($phoneMetadata === null) {
return ShortNumberCost::UNKNOWN_COST;
}
$shortNumber = $this->getNationalSignificantNumber($number);
// The possible lengths are not present for a particular sub-type if they match the general
// description; for this reason, we check the possible lengths against the general description
// first to allow an early exit if possible.
if (!in_array(strlen($shortNumber), $phoneMetadata->getGeneralDesc()->getPossibleLength())) {
return ShortNumberCost::UNKNOWN_COST;
}
// The cost categories are tested in order of decreasing expense, since if for some reason the
// patterns overlap the most expensive matching cost category should be returned.
if ($this->matchesPossibleNumberAndNationalNumber($shortNumber, $phoneMetadata->getPremiumRate())) {
return ShortNumberCost::PREMIUM_RATE;
}
if ($this->matchesPossibleNumberAndNationalNumber($shortNumber, $phoneMetadata->getStandardRate())) {
return ShortNumberCost::STANDARD_RATE;
}
if ($this->matchesPossibleNumberAndNationalNumber($shortNumber, $phoneMetadata->getTollFree())) {
return ShortNumberCost::TOLL_FREE;
}
if ($this->isEmergencyNumber($shortNumber, $regionDialingFrom)) {
// Emergency numbers are implicitly toll-free.
return ShortNumberCost::TOLL_FREE;
}
return ShortNumberCost::UNKNOWN_COST;
}
/**
* Gets the expected cost category of a short number (however, nothing is implied about its
* validity). If the country calling code is unique to a region, this method behaves exactly the
* same as {@link #getExpectedCostForRegion(PhoneNumber, String)}. However, if the country calling
* code is shared by multiple regions, then it returns the highest cost in the sequence
* PREMIUM_RATE, UNKNOWN_COST, STANDARD_RATE, TOLL_FREE. The reason for the position of
* UNKNOWN_COST in this order is that if a number is UNKNOWN_COST in one region but STANDARD_RATE
* or TOLL_FREE in another, its expected cost cannot be estimated as one of the latter since it
* might be a PREMIUM_RATE number.
*
* <p>
* For example, if a number is STANDARD_RATE in the US, but TOLL_FREE in Canada, the expected
* cost returned by this method will be STANDARD_RATE, since the NANPA countries share the same
* country calling code.
* </p>
*
* Note: If the region from which the number is dialed is known, it is highly preferable to call
* {@link #getExpectedCostForRegion(PhoneNumber, String)} instead.
*
* @param PhoneNumber $number the short number for which we want to know the expected cost category
* @return int the highest expected cost category of the short number in the region(s) with the given
* country calling code
*/
public function getExpectedCost(PhoneNumber $number)
{
$regionCodes = $this->getRegionCodesForCountryCode($number->getCountryCode());
if (count($regionCodes) == 0) {
return ShortNumberCost::UNKNOWN_COST;
}
if (count($regionCodes) == 1) {
return $this->getExpectedCostForRegion($number, $regionCodes[0]);
}
$cost = ShortNumberCost::TOLL_FREE;
foreach ($regionCodes as $regionCode) {
$costForRegion = $this->getExpectedCostForRegion($number, $regionCode);
switch ($costForRegion) {
case ShortNumberCost::PREMIUM_RATE:
return ShortNumberCost::PREMIUM_RATE;
case ShortNumberCost::UNKNOWN_COST:
$cost = ShortNumberCost::UNKNOWN_COST;
break;
case ShortNumberCost::STANDARD_RATE:
if ($cost != ShortNumberCost::UNKNOWN_COST) {
$cost = ShortNumberCost::STANDARD_RATE;
}
break;
case ShortNumberCost::TOLL_FREE:
// Do nothing
break;
}
}
return $cost;
}
/**
* Returns true if the given number exactly matches an emergency service number in the given
* region.
* <p>
* This method takes into account cases where the number might contain formatting, but doesn't
* allow additional digits to be appended. Note that {@code isEmergencyNumber(number, region)}
* implies {@code connectsToEmergencyNumber(number, region)}.
*
* @param string $number the phone number to test
* @param string $regionCode the region where the phone number is being dialled
* @return boolean whether the number exactly matches an emergency services number in the given region
*/
public function isEmergencyNumber($number, $regionCode)
{
return $this->matchesEmergencyNumberHelper($number, $regionCode, false /* doesn't allow prefix match */);
}
/**
* Gets the national significant number of the a phone number. Note a national significant number
* doesn't contain a national prefix or any formatting.
* <p>
* This is a temporary duplicate of the {@code getNationalSignificantNumber} method from
* {@code PhoneNumberUtil}. Ultimately a canonical static version should exist in a separate
* utility class (to prevent {@code ShortNumberInfo} needing to depend on PhoneNumberUtil).
*
* @param PhoneNumber $number the phone number for which the national significant number is needed
* @return string the national significant number of the PhoneNumber object passed in
*/
protected function getNationalSignificantNumber(PhoneNumber $number)
{
// If leading zero(s) have been set, we prefix this now. Note this is not a national prefix.
$nationalNumber = '';
if ($number->isItalianLeadingZero()) {
$zeros = str_repeat('0', $number->getNumberOfLeadingZeros());
$nationalNumber .= $zeros;
}
$nationalNumber .= $number->getNationalNumber();
return $nationalNumber;
}
/**
* TODO: Once we have benchmarked ShortnumberInfo, consider if it is worth keeping
* this performance optimization.
* @param string $number
* @param PhoneNumberDesc $numberDesc
* @return bool
*/
protected function matchesPossibleNumberAndNationalNumber($number, PhoneNumberDesc $numberDesc)
{
if (count($numberDesc->getPossibleLength()) > 0 && !in_array(strlen($number), $numberDesc->getPossibleLength())) {
return false;
}
return $this->matcherAPI->matchNationalNumber($number, $numberDesc, false);
}
}

View File

@ -0,0 +1,262 @@
<?php
/**
* This file has been @generated by a phing task by {@link BuildMetadataPHPFromXml}.
* See [README.md](README.md#generating-data) for more information.
*
* Pull requests changing data in these files will not be accepted. See the
* [FAQ in the README](README.md#problems-with-invalid-numbers] on how to make
* metadata changes.
*
* Do not modify this file directly!
*/
namespace libphonenumber;
class ShortNumbersRegionCodeSet {
// A set of all region codes for which data is available.
public static $shortNumbersRegionCodeSet = array (
0 => 'AC',
1 => 'AD',
2 => 'AE',
3 => 'AF',
4 => 'AG',
5 => 'AI',
6 => 'AL',
7 => 'AM',
8 => 'AO',
9 => 'AR',
10 => 'AS',
11 => 'AT',
12 => 'AU',
13 => 'AW',
14 => 'AX',
15 => 'AZ',
16 => 'BA',
17 => 'BB',
18 => 'BD',
19 => 'BE',
20 => 'BF',
21 => 'BG',
22 => 'BH',
23 => 'BI',
24 => 'BJ',
25 => 'BL',
26 => 'BM',
27 => 'BN',
28 => 'BO',
29 => 'BQ',
30 => 'BR',
31 => 'BS',
32 => 'BT',
33 => 'BW',
34 => 'BY',
35 => 'BZ',
36 => 'CA',
37 => 'CC',
38 => 'CD',
39 => 'CF',
40 => 'CG',
41 => 'CH',
42 => 'CI',
43 => 'CK',
44 => 'CL',
45 => 'CM',
46 => 'CN',
47 => 'CO',
48 => 'CR',
49 => 'CU',
50 => 'CV',
51 => 'CW',
52 => 'CX',
53 => 'CY',
54 => 'CZ',
55 => 'DE',
56 => 'DJ',
57 => 'DK',
58 => 'DM',
59 => 'DO',
60 => 'DZ',
61 => 'EC',
62 => 'EE',
63 => 'EG',
64 => 'EH',
65 => 'ER',
66 => 'ES',
67 => 'ET',
68 => 'FI',
69 => 'FJ',
70 => 'FK',
71 => 'FM',
72 => 'FO',
73 => 'FR',
74 => 'GA',
75 => 'GB',
76 => 'GD',
77 => 'GE',
78 => 'GF',
79 => 'GG',
80 => 'GH',
81 => 'GI',
82 => 'GL',
83 => 'GM',
84 => 'GN',
85 => 'GP',
86 => 'GR',
87 => 'GT',
88 => 'GU',
89 => 'GW',
90 => 'GY',
91 => 'HK',
92 => 'HN',
93 => 'HR',
94 => 'HT',
95 => 'HU',
96 => 'ID',
97 => 'IE',
98 => 'IL',
99 => 'IM',
100 => 'IN',
101 => 'IQ',
102 => 'IR',
103 => 'IS',
104 => 'IT',
105 => 'JE',
106 => 'JM',
107 => 'JO',
108 => 'JP',
109 => 'KE',
110 => 'KG',
111 => 'KH',
112 => 'KI',
113 => 'KM',
114 => 'KN',
115 => 'KP',
116 => 'KR',
117 => 'KW',
118 => 'KY',
119 => 'KZ',
120 => 'LA',
121 => 'LB',
122 => 'LC',
123 => 'LI',
124 => 'LK',
125 => 'LR',
126 => 'LS',
127 => 'LT',
128 => 'LU',
129 => 'LV',
130 => 'LY',
131 => 'MA',
132 => 'MC',
133 => 'MD',
134 => 'ME',
135 => 'MF',
136 => 'MG',
137 => 'MH',
138 => 'MK',
139 => 'ML',
140 => 'MM',
141 => 'MN',
142 => 'MO',
143 => 'MP',
144 => 'MQ',
145 => 'MR',
146 => 'MS',
147 => 'MT',
148 => 'MU',
149 => 'MV',
150 => 'MW',
151 => 'MX',
152 => 'MY',
153 => 'MZ',
154 => 'NA',
155 => 'NC',
156 => 'NE',
157 => 'NF',
158 => 'NG',
159 => 'NI',
160 => 'NL',
161 => 'NO',
162 => 'NP',
163 => 'NR',
164 => 'NU',
165 => 'NZ',
166 => 'OM',
167 => 'PA',
168 => 'PE',
169 => 'PF',
170 => 'PG',
171 => 'PH',
172 => 'PK',
173 => 'PL',
174 => 'PM',
175 => 'PS',
176 => 'PR',
177 => 'PT',
178 => 'PW',
179 => 'PY',
180 => 'QA',
181 => 'RE',
182 => 'RO',
183 => 'RS',
184 => 'RU',
185 => 'RW',
186 => 'SA',
187 => 'SB',
188 => 'SC',
189 => 'SD',
190 => 'SE',
191 => 'SG',
192 => 'SH',
193 => 'SI',
194 => 'SJ',
195 => 'SK',
196 => 'SL',
197 => 'SM',
198 => 'SN',
199 => 'SO',
200 => 'SR',
201 => 'ST',
202 => 'SV',
203 => 'SX',
204 => 'SY',
205 => 'SZ',
206 => 'TC',
207 => 'TD',
208 => 'TG',
209 => 'TH',
210 => 'TJ',
211 => 'TL',
212 => 'TM',
213 => 'TN',
214 => 'TO',
215 => 'TR',
216 => 'TT',
217 => 'TV',
218 => 'TW',
219 => 'TZ',
220 => 'UA',
221 => 'UG',
222 => 'US',
223 => 'UY',
224 => 'UZ',
225 => 'VA',
226 => 'VC',
227 => 'VE',
228 => 'VG',
229 => 'VI',
230 => 'VN',
231 => 'VU',
232 => 'WF',
233 => 'WS',
234 => 'XK',
235 => 'YE',
236 => 'YT',
237 => 'ZA',
238 => 'ZM',
239 => 'ZW',
);
}

View File

@ -0,0 +1,45 @@
<?php
namespace libphonenumber;
/**
* Possible outcomes when testing if a PhoneNumber is possible.
*/
class ValidationResult
{
/**
* The number length matches that of valid numbers for this region
*/
const IS_POSSIBLE = 0;
/**
* The number has an invalid country calling code.
*/
const INVALID_COUNTRY_CODE = 1;
/**
* The number is shorter than all valid numbers for this region.
*/
const TOO_SHORT = 2;
/**
* The number is longer than all valid numbers for this region.
*/
const TOO_LONG = 3;
/**
* The number length matches that of local numbers for this region only (i.e. numbers that may
* be able to be dialled within an area, but do not have all the information to be dialled from
* anywhere inside or outside the country).
*/
const IS_POSSIBLE_LOCAL_ONLY = 4;
/**
* The number is longer than the shortest valid numbers for this region, shorter than the
* longest valid numbers for this region, and does not itself have a number length that matches
* valid numbers for this region. This can also be returned in the case where
* isPossibleNumberForTypeWithReason was called, and there are no numbers of this type at all
* for this region.
*/
const INVALID_LENGTH = 5;
}

View File

@ -0,0 +1,228 @@
<?php
/**
* This file has been @generated by a phing task by {@link GeneratePhonePrefixData}.
* See [README.md](README.md#generating-data) for more information.
*
* Pull requests changing data in these files will not be accepted. See the
* [FAQ in the README](README.md#problems-with-invalid-numbers] on how to make
* metadata changes.
*
* Do not modify this file directly!
*/
return array (
'ar' =>
array (
0 => 965,
),
'be' =>
array (
0 => 375,
),
'en' =>
array (
0 => 1,
1 => 20,
2 => 211,
3 => 212,
4 => 213,
5 => 216,
6 => 220,
7 => 221,
8 => 222,
9 => 223,
10 => 224,
11 => 225,
12 => 226,
13 => 227,
14 => 228,
15 => 229,
16 => 230,
17 => 231,
18 => 232,
19 => 233,
20 => 234,
21 => 235,
22 => 236,
23 => 237,
24 => 238,
25 => 239,
26 => 240,
27 => 241,
28 => 242,
29 => 243,
30 => 244,
31 => 245,
32 => 248,
33 => 249,
34 => 250,
35 => 251,
36 => 252,
37 => 253,
38 => 254,
39 => 255,
40 => 256,
41 => 257,
42 => 258,
43 => 260,
44 => 261,
45 => 262,
46 => 263,
47 => 264,
48 => 265,
49 => 267,
50 => 268,
51 => 269,
52 => 27,
53 => 297,
54 => 298,
55 => 299,
56 => 30,
57 => 31,
58 => 32,
59 => 33,
60 => 34,
61 => 350,
62 => 351,
63 => 352,
64 => 353,
65 => 354,
66 => 355,
67 => 356,
68 => 357,
69 => 358,
70 => 359,
71 => 36,
72 => 370,
73 => 372,
74 => 373,
75 => 374,
76 => 375,
77 => 376,
78 => 380,
79 => 381,
80 => 382,
81 => 383,
82 => 385,
83 => 386,
84 => 387,
85 => 389,
86 => 39,
87 => 40,
88 => 41,
89 => 420,
90 => 421,
91 => 423,
92 => 43,
93 => 44,
94 => 45,
95 => 47,
96 => 48,
97 => 49,
98 => 501,
99 => 502,
100 => 503,
101 => 505,
102 => 506,
103 => 507,
104 => 508,
105 => 509,
106 => 51,
107 => 53,
108 => 54,
109 => 55,
110 => 56,
111 => 57,
112 => 58,
113 => 590,
114 => 591,
115 => 592,
116 => 593,
117 => 594,
118 => 595,
119 => 596,
120 => 597,
121 => 598,
122 => 599,
123 => 60,
124 => 61,
125 => 62,
126 => 63,
127 => 64,
128 => 65,
129 => 66,
130 => 670,
131 => 673,
132 => 674,
133 => 675,
134 => 676,
135 => 677,
136 => 678,
137 => 679,
138 => 680,
139 => 685,
140 => 686,
141 => 688,
142 => 689,
143 => 7,
144 => 84,
145 => 852,
146 => 853,
147 => 855,
148 => 856,
149 => 86,
150 => 880,
151 => 886,
152 => 90,
153 => 91,
154 => 92,
155 => 93,
156 => 94,
157 => 95,
158 => 960,
159 => 961,
160 => 962,
161 => 963,
162 => 964,
163 => 965,
164 => 966,
165 => 967,
166 => 968,
167 => 970,
168 => 971,
169 => 972,
170 => 973,
171 => 974,
172 => 975,
173 => 976,
174 => 977,
175 => 98,
176 => 992,
177 => 993,
178 => 994,
179 => 995,
180 => 996,
181 => 998,
),
'fa' =>
array (
0 => 93,
1 => 98,
),
'ru' =>
array (
0 => 374,
1 => 375,
2 => 7,
),
'zh' =>
array (
0 => 852,
1 => 86,
),
'zh_Hant' =>
array (
0 => 852,
1 => 86,
),
);

View File

@ -0,0 +1,17 @@
<?php
/**
* This file has been @generated by a phing task by {@link GeneratePhonePrefixData}.
* See [README.md](README.md#generating-data) for more information.
*
* Pull requests changing data in these files will not be accepted. See the
* [FAQ in the README](README.md#problems-with-invalid-numbers] on how to make
* metadata changes.
*
* Do not modify this file directly!
*/
return array (
9655 => 'فيفا',
9656 => 'الوطنية',
9659 => 'زين',
);

View File

@ -0,0 +1,21 @@
<?php
/**
* This file has been @generated by a phing task by {@link GeneratePhonePrefixData}.
* See [README.md](README.md#generating-data) for more information.
*
* Pull requests changing data in these files will not be accepted. See the
* [FAQ in the README](README.md#problems-with-invalid-numbers] on how to make
* metadata changes.
*
* Do not modify this file directly!
*/
return array (
37525 => 'БеСТ',
375292 => 'МТС',
375294 => 'БелСел',
375295 => 'МТС',
375297 => 'МТС',
375298 => 'МТС',
37533 => 'МТС',
);

View File

@ -0,0 +1,740 @@
<?php
/**
* This file has been @generated by a phing task by {@link GeneratePhonePrefixData}.
* See [README.md](README.md#generating-data) for more information.
*
* Pull requests changing data in these files will not be accepted. See the
* [FAQ in the README](README.md#problems-with-invalid-numbers] on how to make
* metadata changes.
*
* Do not modify this file directly!
*/
return array (
1242357 => 'BaTelCo',
1242359 => 'BaTelCo',
1242375 => 'BaTelCo',
1242376 => 'BaTelCo',
1242395 => 'BaTelCo',
1242421 => 'BaTelCo',
1242422 => 'BaTelCo',
1242423 => 'BaTelCo',
1242424 => 'BaTelCo',
1242425 => 'BaTelCo',
1242426 => 'BaTelCo',
1242427 => 'BaTelCo',
1242428 => 'BaTelCo',
1242429 => 'BaTelCo',
1242431 => 'BaTelCo',
1242432 => 'BaTelCo',
1242433 => 'BaTelCo',
1242434 => 'BaTelCo',
1242435 => 'BaTelCo',
1242436 => 'BaTelCo',
1242437 => 'BaTelCo',
1242438 => 'BaTelCo',
1242439 => 'BaTelCo',
1242441 => 'BaTelCo',
1242442 => 'BaTelCo',
1242443 => 'BaTelCo',
1242445 => 'BaTelCo',
1242446 => 'BaTelCo',
1242447 => 'BaTelCo',
1242448 => 'BaTelCo',
1242449 => 'BaTelCo',
1242451 => 'BaTelCo',
1242452 => 'BaTelCo',
1242453 => 'BaTelCo',
1242454 => 'BaTelCo',
1242455 => 'BaTelCo',
1242456 => 'BaTelCo',
1242457 => 'BaTelCo',
1242458 => 'BaTelCo',
1242462 => 'BaTelCo',
1242463 => 'BaTelCo',
1242464 => 'BaTelCo',
1242465 => 'BaTelCo',
1242466 => 'BaTelCo',
1242467 => 'BaTelCo',
1242468 => 'BaTelCo',
124247 => 'BaTelCo',
1242481 => 'BaTelCo',
1242524 => 'BaTelCo',
1242525 => 'BaTelCo',
1242533 => 'BaTelCo',
1242535 => 'BaTelCo',
1242544 => 'BaTelCo',
1242551 => 'BaTelCo',
1242552 => 'BaTelCo',
1242553 => 'BaTelCo',
1242554 => 'BaTelCo',
1242556 => 'BaTelCo',
1242557 => 'BaTelCo',
1242558 => 'BaTelCo',
1242559 => 'BaTelCo',
1242565 => 'BaTelCo',
1242577 => 'BaTelCo',
1242636 => 'BaTelCo',
1242646 => 'BaTelCo',
1242727 => 'BaTelCo',
1242738 => 'aliv',
1242801 => 'aliv',
1242802 => 'aliv',
1242803 => 'aliv',
1242804 => 'aliv',
1242805 => 'aliv',
1242806 => 'aliv',
1242807 => 'aliv',
1242808 => 'aliv',
1242809 => 'aliv',
1242810 => 'aliv',
1242812 => 'aliv',
1242813 => 'aliv',
1242814 => 'aliv',
1242815 => 'aliv',
1242816 => 'aliv',
1242817 => 'aliv',
1242818 => 'aliv',
1242819 => 'aliv',
124282 => 'aliv',
1242889 => 'aliv',
1242899 => 'aliv',
124623 => 'LIME',
124624 => 'LIME',
1246250 => 'LIME',
1246251 => 'LIME',
1246252 => 'LIME',
1246253 => 'LIME',
1246254 => 'LIME',
1246255 => 'LIME',
1246256 => 'Digicel',
1246257 => 'Digicel',
1246258 => 'Digicel',
1246259 => 'Digicel',
124626 => 'Digicel',
124628 => 'LIME',
124645 => 'Sunbeach Communications',
1246695 => 'Ozone',
1246696 => 'Ozone',
1246697 => 'Ozone',
124682 => 'Digicel',
124683 => 'Digicel',
124684 => 'Digicel',
124685 => 'Digicel',
1246883 => 'Digicel',
1264536 => 'Weblinks Limited',
1264537 => 'Weblinks Limited',
1264538 => 'Weblinks Limited',
1264539 => 'Weblinks Limited',
1264581 => 'Digicel',
1264582 => 'Digicel',
1264583 => 'Digicel',
1264584 => 'Digicel',
1264729 => 'Cable & Wireless',
1264772 => 'Cable & Wireless',
1268713 => 'Digicel',
1268714 => 'Digicel',
1268715 => 'Digicel',
1268716 => 'Digicel',
1268717 => 'Digicel',
1268718 => 'Digicel',
1268719 => 'Digicel',
1268720 => 'Digicel',
1268721 => 'Digicel',
1268722 => 'Digicel',
1268724 => 'Digicel',
1268725 => 'Digicel',
1268726 => 'Digicel',
1268727 => 'APUA',
1268729 => 'APUA',
1268732 => 'Digicel',
1268734 => 'Digicel',
1268736 => 'Digicel',
1268773 => 'APUA',
1268774 => 'APUA',
1268775 => 'APUA',
1268780 => 'APUA',
1268781 => 'APUA',
1268783 => 'Digicel',
1268785 => 'Digicel',
1268788 => 'Digicel',
1284300 => 'Digicel',
1284340 => 'Digicel',
1284341 => 'Digicel',
1284342 => 'Digicel',
1284343 => 'Digicel',
1284344 => 'Digicel',
1284345 => 'Digicel',
1284346 => 'Digicel',
1284347 => 'Digicel',
1284368 => 'Digicel',
1284393 => 'Digicel',
1284394 => 'Digicel',
1284440 => 'CCT',
1284441 => 'CCT',
1284442 => 'CCT',
1284443 => 'CCT',
1284444 => 'CCT',
1284445 => 'CCT',
1284446 => 'CCT',
12844689 => 'CCT',
12844966 => 'CCT',
12844967 => 'CCT',
12844968 => 'CCT',
12844969 => 'CCT',
1284499 => 'CCT',
1345321 => 'Digicel',
1345322 => 'Digicel',
1345323 => 'Digicel',
1345324 => 'Digicel',
1345325 => 'Digicel',
1345326 => 'Digicel',
1345327 => 'Digicel',
1345328 => 'Digicel',
1345329 => 'Digicel',
1345516 => 'Digicel',
1345517 => 'Digicel',
1345525 => 'Digicel',
1345526 => 'Digicel',
1345527 => 'Digicel',
1345529 => 'Digicel',
1345546 => 'Digicel',
1345547 => 'Digicel',
1345548 => 'Digicel',
1345549 => 'Digicel',
1345550 => 'Digicel',
1345649 => 'Digicel',
14413 => 'Mobility',
144150 => 'Digicel Bermuda',
144151 => 'Digicel Bermuda',
144152 => 'Digicel Bermuda',
144153 => 'Digicel Bermuda',
144159 => 'Digicel Bermuda',
14417 => 'Cellular One',
1473402 => 'Affordable Island Communications',
147341 => 'Digicel Grenada',
1473420 => 'Digicel Grenada',
1473421 => 'Digicel Grenada',
1473422 => 'Digicel Grenada',
1473423 => 'Digicel Grenada',
1473424 => 'Digicel Grenada',
1473425 => 'Digicel Grenada',
1473520 => 'Affordable Island Communications',
1473521 => 'Affordable Island Communications',
147353 => 'AWS Grenada',
1473901 => 'Affordable Island Communications',
164923 => 'C&W',
164924 => 'C&W',
164933 => 'Digicel',
164934 => 'Digicel',
164943 => 'Islandcom',
1671480 => 'GTA',
1671482 => 'GTA',
1671483 => 'GTA',
1671486 => 'GTA',
1671487 => 'GTA',
1671488 => 'GTA',
1671489 => 'GTA',
1671747 => 'PTI PACIFICA',
1671838 => 'i CAN_GSM',
1671848 => 'i CAN_GSM',
1671858 => 'i CAN_GSM',
1671864 => 'GTA',
1671868 => 'Choice Phone',
1671878 => 'Choice Phone',
1671888 => 'Choice Phone',
1671898 => 'Choice Phone',
1684252 => 'Blue Sky',
1684254 => 'Blue Sky',
1684256 => 'Blue Sky',
1684258 => 'Blue Sky',
1684272 => 'Blue Sky',
1684731 => 'ASTCA',
1684733 => 'ASTCA',
1684770 => 'ASTCA',
175828 => 'Cable & Wireless',
1758384 => 'Cable & Wireless',
1758460 => 'Cable & Wireless',
1758461 => 'Cable & Wireless',
1758484 => 'Cable & Wireless',
1758485 => 'Cable & Wireless',
1758486 => 'Cable & Wireless',
1758487 => 'Cable & Wireless',
1758488 => 'Cable & Wireless',
1758489 => 'Cable & Wireless',
175851 => 'AT&T',
1758518 => 'Digicel',
1758519 => 'Digicel',
175852 => 'AT&T',
1758520 => 'Digicel',
1758584 => 'Cable & Wireless',
17587 => 'Digicel',
1767225 => 'Cable & Wireless',
1767235 => 'Cable & Wireless',
1767245 => 'Cable & Wireless',
1767265 => 'Cable & Wireless',
1767275 => 'Cable & Wireless',
1767276 => 'Cable & Wireless',
1767277 => 'Cable & Wireless',
1767285 => 'Cable & Wireless',
1767295 => 'Cable & Wireless',
1767315 => 'Digicel',
1767316 => 'Digicel',
1767317 => 'Digicel',
1767611 => 'Digicel',
1767612 => 'Digicel',
1767613 => 'Digicel',
1767614 => 'Digicel',
1767615 => 'Digicel',
1767616 => 'Digicel',
1767617 => 'Digicel',
1784430 => 'AT&T',
1784431 => 'AT&T',
1784432 => 'AT&T',
1784433 => 'Digicel',
1784434 => 'Digicel',
1784435 => 'Digicel',
1784454 => 'Cable & Wireless',
1784455 => 'Cable & Wireless',
1784489 => 'Cable & Wireless',
1784490 => 'Cable & Wireless',
1784491 => 'Cable & Wireless',
1784492 => 'Cable & Wireless',
1784493 => 'Cable & Wireless',
1784494 => 'Cable & Wireless',
1784495 => 'Cable & Wireless',
1784526 => 'Digicel',
1784527 => 'Digicel',
1784528 => 'Digicel',
1784529 => 'Digicel',
1784530 => 'Digicel',
1784531 => 'Digicel',
1784532 => 'Digicel',
1784533 => 'Digicel',
1784534 => 'Digicel',
1787203 => 'Claro',
1787210 => 'SunCom Wireless Puerto Rico',
1787212 => 'Claro',
1787213 => 'Claro',
1787214 => 'Claro',
1787215 => 'Claro',
1787216 => 'Claro',
1787217 => 'Claro',
1787218 => 'Claro',
1787219 => 'Claro',
1787220 => 'CENTENNIAL',
1787221 => 'CENTENNIAL',
1787222 => 'CENTENNIAL',
1787223 => 'CENTENNIAL',
1787224 => 'CENTENNIAL',
1787225 => 'SunCom Wireless Puerto Rico',
1787226 => 'SunCom Wireless Puerto Rico',
1787227 => 'CENTENNIAL',
1787229 => 'CENTENNIAL',
1787253 => 'Claro',
1787254 => 'Claro',
1787255 => 'Claro',
1787256 => 'Claro',
1787257 => 'Claro',
1787258 => 'Claro',
1787259 => 'Claro',
1787260 => 'Claro',
1787291 => 'CENTENNIAL',
1787299 => 'SunCom Wireless Puerto Rico',
1787300 => 'CENTENNIAL',
1787310 => 'SunCom Wireless Puerto Rico',
1787312 => 'Claro',
1787313 => 'Claro',
1787314 => 'Claro',
1787315 => 'Claro',
1787316 => 'Claro',
1787317 => 'Claro',
1787318 => 'Claro',
17873191 => 'Claro',
17873192 => 'Claro',
17873193 => 'Claro',
17873194 => 'Claro',
17873195 => 'Claro',
17873196 => 'Claro',
17873197 => 'Claro',
17873198 => 'Claro',
17873199 => 'Claro',
1787341 => 'SunCom Wireless Puerto Rico',
1787344 => 'SunCom Wireless Puerto Rico',
1787346 => 'SunCom Wireless Puerto Rico',
1787355 => 'CENTENNIAL',
1787357 => 'CENTENNIAL',
1787359 => 'SunCom Wireless Puerto Rico',
1787367 => 'SunCom Wireless Puerto Rico',
1787368 => 'SunCom Wireless Puerto Rico',
1787369 => 'CENTENNIAL',
1787371 => 'Claro',
1787372 => 'Claro',
1787374 => 'Claro',
1787375 => 'Claro',
1787376 => 'Claro',
1787380 => 'Claro',
1787381 => 'Claro',
1787382 => 'Claro',
1787383 => 'Claro',
1787384 => 'Claro',
1787385 => 'Claro',
1787389 => 'Claro',
1787390 => 'Claro',
1787391 => 'Claro',
1787392 => 'Claro',
1787400 => 'CENTENNIAL',
1787410 => 'SunCom Wireless Puerto Rico',
1787434 => 'CENTENNIAL',
1787447 => 'CENTENNIAL',
1787448 => 'CENTENNIAL',
1787449 => 'CENTENNIAL',
1787450 => 'Claro',
1787453 => 'Claro',
1787454 => 'SunCom Wireless Puerto Rico',
1787458 => 'SunCom Wireless Puerto Rico',
1787459 => 'SunCom Wireless Puerto Rico',
1787460 => 'SunCom Wireless Puerto Rico',
1787462 => 'SunCom Wireless Puerto Rico',
1787463 => 'SunCom Wireless Puerto Rico',
1787465 => 'CENTENNIAL',
1787466 => 'SunCom Wireless Puerto Rico',
1787471 => 'CENTENNIAL',
1787473 => 'CENTENNIAL',
1787474 => 'CENTENNIAL',
1787478 => 'SunCom Wireless Puerto Rico',
1787479 => 'CENTENNIAL',
1787481 => 'Claro',
1787484 => 'Claro',
1787485 => 'Claro',
1787486 => 'Claro',
1787487 => 'Claro',
1787513 => 'SunCom Wireless Puerto Rico',
1787514 => 'Claro',
1787515 => 'Claro',
1787516 => 'Claro',
1787517 => 'Claro',
1787518 => 'Claro',
1787519 => 'Claro',
1787520 => 'CENTENNIAL',
1787521 => 'CENTENNIAL',
1787522 => 'CENTENNIAL',
1787523 => 'CENTENNIAL',
1787528 => 'SunCom Wireless Puerto Rico',
1787534 => 'CENTENNIAL',
1787535 => 'CENTENNIAL',
1787537 => 'CENTENNIAL',
1787544 => 'CENTENNIAL',
1787545 => 'CENTENNIAL',
1787546 => 'SunCom Wireless Puerto Rico',
1787551 => 'CENTENNIAL',
1787553 => 'Claro',
1787561 => 'CENTENNIAL',
1787563 => 'CENTENNIAL',
1787568 => 'SunCom Wireless Puerto Rico',
1787569 => 'CENTENNIAL',
1787579 => 'Claro',
1787580 => 'CENTENNIAL',
1787585 => 'CENTENNIAL',
1787588 => 'CENTENNIAL',
1787589 => 'CENTENNIAL',
1787595 => 'SunCom Wireless Puerto Rico',
1787597 => 'SunCom Wireless Puerto Rico',
1787598 => 'SunCom Wireless Puerto Rico',
1787601 => 'SunCom Wireless Puerto Rico',
1787602 => 'CENTENNIAL',
1787604 => 'SunCom Wireless Puerto Rico',
1787605 => 'SunCom Wireless Puerto Rico',
1787607 => 'CENTENNIAL',
1787608 => 'CENTENNIAL',
1787609 => 'CENTENNIAL',
1787612 => 'Claro',
1787613 => 'Claro',
1787614 => 'Claro',
1787615 => 'Claro',
1787616 => 'Claro',
1787617 => 'Claro',
1787619 => 'SunCom Wireless Puerto Rico',
1787620 => 'CENTENNIAL',
1787621 => 'CENTENNIAL',
1787622 => 'CENTENNIAL',
1787623 => 'CENTENNIAL',
1787624 => 'CENTENNIAL',
1787625 => 'CENTENNIAL',
1787626 => 'CENTENNIAL',
1787628 => 'CENTENNIAL',
1787629 => 'SunCom Wireless Puerto Rico',
178764 => 'CENTENNIAL',
178765 => 'CENTENNIAL',
1787662 => 'SunCom Wireless Puerto Rico',
1787666 => 'SunCom Wireless Puerto Rico',
1787673 => 'SunCom Wireless Puerto Rico',
1787675 => 'CENTENNIAL',
1787678 => 'SunCom Wireless Puerto Rico',
1787686 => 'CENTENNIAL',
1787687 => 'CENTENNIAL',
1787689 => 'CENTENNIAL',
1787690 => 'CENTENNIAL',
1787692 => 'CENTENNIAL',
1787693 => 'CENTENNIAL',
1787695 => 'CENTENNIAL',
1787717 => 'CENTENNIAL',
1787719 => 'CENTENNIAL',
1787901 => 'SunCom Wireless Puerto Rico',
1787903 => 'CENTENNIAL',
1787904 => 'SunCom Wireless Puerto Rico',
1787908 => 'CENTENNIAL',
1787912 => 'CENTENNIAL',
1787915 => 'CENTENNIAL',
1787916 => 'CENTENNIAL',
1787917 => 'CENTENNIAL',
1787922 => 'SunCom Wireless Puerto Rico',
1787923 => 'SunCom Wireless Puerto Rico',
1787924 => 'CENTENNIAL',
1787926 => 'CENTENNIAL',
1787927 => 'CENTENNIAL',
1787928 => 'CENTENNIAL',
1787933 => 'CENTENNIAL',
1787935 => 'CENTENNIAL',
1787937 => 'CENTENNIAL',
1787940 => 'CENTENNIAL',
1787947 => 'CENTENNIAL',
1787949 => 'SunCom Wireless Puerto Rico',
1787952 => 'CENTENNIAL',
1787953 => 'CENTENNIAL',
1787954 => 'CENTENNIAL',
1787957 => 'CENTENNIAL',
1787961 => 'CENTENNIAL',
1787968 => 'CENTENNIAL',
1787969 => 'CENTENNIAL',
1787971 => 'CENTENNIAL',
1787975 => 'CENTENNIAL',
1787978 => 'CENTENNIAL',
1787992 => 'CENTENNIAL',
1787993 => 'CENTENNIAL',
1787998 => 'CENTENNIAL',
1787999 => 'CENTENNIAL',
180920 => 'Tricom',
180922 => 'Claro',
180923 => 'Claro',
180924 => 'Claro',
180925 => 'Claro',
180926 => 'Claro',
180927 => 'Claro',
180928 => 'Claro',
180929 => 'Tricom',
180930 => 'Viva',
180931 => 'Tricom',
180932 => 'Tricom',
180933 => 'Claro',
180934 => 'Tricom',
180935 => 'Claro',
180936 => 'Claro',
180937 => 'Claro',
180938 => 'Claro',
180939 => 'Claro',
180941 => 'Viva',
180942 => 'Claro',
180943 => 'Viva',
180944 => 'Viva',
180945 => 'Claro',
180947 => 'Tricom',
180948 => 'Claro',
180949 => 'Claro',
180951 => 'Claro',
180954 => 'Claro',
180960 => 'Claro',
180962 => 'Tricom',
180963 => 'Tricom',
180964 => 'Tricom',
180965 => 'Tricom',
180967 => 'Claro',
180969 => 'Claro',
180970 => 'Claro',
180971 => 'Claro',
180972 => 'Claro',
180974 => 'Claro',
180975 => 'Claro',
180976 => 'Claro',
180977 => 'Viva',
180978 => 'Claro',
180979 => 'Claro',
180980 => 'Orange',
180981 => 'Viva',
180982 => 'Claro',
180983 => 'Claro',
180984 => 'Orange',
180985 => 'Orange',
180986 => 'Orange',
180987 => 'Tricom',
180988 => 'Orange',
180989 => 'Orange',
180991 => 'Orange',
180992 => 'Tricom',
180993 => 'Tricom',
180994 => 'Tricom',
180995 => 'Claro',
180997 => 'Orange',
180998 => 'Orange',
180999 => 'Tricom',
1868266 => 'bmobile',
1868267 => 'bmobile',
1868268 => 'bmobile',
1868269 => 'bmobile',
186827 => 'bmobile',
186828 => 'bmobile',
186829 => 'bmobile',
18683 => 'Digicel',
18684 => 'bmobile',
18686 => 'bmobile',
18687 => 'bmobile',
1869556 => 'CariGlobe St. Kitts',
1869557 => 'CariGlobe St. Kitts',
1869558 => 'CariGlobe St. Kitts',
1869565 => 'The Cable St. Kitts',
1869566 => 'The Cable St. Kitts',
1869567 => 'The Cable St. Kitts',
1869660 => 'Cable & Wireless',
1869661 => 'Cable & Wireless',
1869662 => 'Cable & Wireless',
1869663 => 'Cable & Wireless',
1869664 => 'Cable & Wireless',
1869665 => 'Cable & Wireless',
1869667 => 'Cable & Wireless',
1869668 => 'Cable & Wireless',
1869669 => 'Cable & Wireless',
1869760 => 'Digicel',
1869762 => 'Digicel',
1869763 => 'Digicel',
1869764 => 'Digicel',
1869765 => 'Digicel',
1869766 => 'Digicel',
187624 => 'Digicel',
187625 => 'Digicel',
187626 => 'Digicel',
1876275 => 'Digicel',
1876276 => 'Digicel',
1876277 => 'Digicel',
1876278 => 'Digicel',
1876279 => 'Digicel',
187628 => 'Digicel',
187629 => 'Digicel',
187630 => 'Digicel',
187635 => 'Digicel',
187636 => 'Digicel',
187637 => 'Digicel',
187638 => 'Digicel',
187639 => 'Digicel',
187640 => 'Digicel',
187641 => 'Digicel',
187642 => 'Digicel',
187643 => 'Digicel',
1876440 => 'Digicel',
1876441 => 'Digicel',
1876442 => 'Digicel',
1876443 => 'Digicel',
1876445 => 'Digicel',
1876446 => 'Digicel',
1876447 => 'Digicel',
1876448 => 'Digicel',
1876449 => 'Digicel',
187645 => 'Digicel',
187646 => 'Digicel',
187647 => 'Digicel',
187648 => 'Digicel',
187649 => 'Digicel',
1876503 => 'Digicel',
1876504 => 'Digicel',
1876505 => 'Digicel',
1876506 => 'Digicel',
1876507 => 'Digicel',
1876508 => 'Digicel',
1876509 => 'Digicel',
187652 => 'Digicel',
1876550 => 'Digicel',
1876551 => 'Digicel',
1876552 => 'Digicel',
1876553 => 'Digicel',
1876554 => 'Digicel',
1876556 => 'Digicel',
1876557 => 'Digicel',
1876558 => 'Digicel',
1876559 => 'Digicel',
1876560 => 'Digicel',
1876561 => 'Digicel',
1876562 => 'Digicel',
1876564 => 'Digicel',
1876565 => 'Digicel',
1876566 => 'Digicel',
1876567 => 'Digicel',
1876568 => 'Digicel',
1876569 => 'Digicel',
187657 => 'Digicel',
187658 => 'Digicel',
187659 => 'Digicel',
187684 => 'Digicel',
187685 => 'Digicel',
187686 => 'Digicel',
187687 => 'Digicel',
187688 => 'Digicel',
187689 => 'Digicel',
1939201 => 'CENTENNIAL',
1939212 => 'CENTENNIAL',
1939214 => 'CENTENNIAL',
1939240 => 'SunCom Wireless Puerto Rico',
19392410 => 'Claro',
19392411 => 'Claro',
19392412 => 'Claro',
19392413 => 'Claro',
19392414 => 'Claro',
19392415 => 'Claro',
19392416 => 'Claro',
193924199 => 'Claro',
1939242 => 'Claro',
19392433 => 'Claro',
19392434 => 'Claro',
19392435 => 'Claro',
19392436 => 'Claro',
19392437 => 'Claro',
19392438 => 'Claro',
19392439 => 'Claro',
1939244 => 'Claro',
1939245 => 'Claro',
1939246 => 'Claro',
1939247 => 'Claro',
1939248 => 'Claro',
1939249 => 'Claro',
1939250 => 'Claro',
1939251 => 'Claro',
1939252 => 'CENTENNIAL',
1939253 => 'Claro',
1939254 => 'Claro',
1939255 => 'Claro',
1939256 => 'Claro',
1939257 => 'Claro',
1939258 => 'Claro',
1939259 => 'Claro',
1939307 => 'CENTENNIAL',
1939325 => 'SunCom Wireless Puerto Rico',
1939329 => 'CENTENNIAL',
1939334 => 'Claro',
1939339 => 'SunCom Wireless Puerto Rico',
1939394 => 'CENTENNIAL',
1939440 => 'CENTENNIAL',
1939628 => 'CENTENNIAL',
1939630 => 'CENTENNIAL',
1939639 => 'CENTENNIAL',
1939640 => 'CENTENNIAL',
1939642 => 'CENTENNIAL',
1939644 => 'CENTENNIAL',
1939645 => 'CENTENNIAL',
1939697 => 'CENTENNIAL',
1939717 => 'CENTENNIAL',
1939731 => 'CENTENNIAL',
1939777 => 'Claro',
1939865 => 'SunCom Wireless Puerto Rico',
1939891 => 'SunCom Wireless Puerto Rico',
1939910 => 'CENTENNIAL',
1939940 => 'CENTENNIAL',
1939969 => 'CENTENNIAL',
);

View File

@ -0,0 +1,18 @@
<?php
/**
* This file has been @generated by a phing task by {@link GeneratePhonePrefixData}.
* See [README.md](README.md#generating-data) for more information.
*
* Pull requests changing data in these files will not be accepted. See the
* [FAQ in the README](README.md#problems-with-invalid-numbers] on how to make
* metadata changes.
*
* Do not modify this file directly!
*/
return array (
2010 => 'Vodafone',
2011 => 'Etisalat',
2012 => 'Orange',
2015 => 'TE',
);

View File

@ -0,0 +1,18 @@
<?php
/**
* This file has been @generated by a phing task by {@link GeneratePhonePrefixData}.
* See [README.md](README.md#generating-data) for more information.
*
* Pull requests changing data in these files will not be accepted. See the
* [FAQ in the README](README.md#problems-with-invalid-numbers] on how to make
* metadata changes.
*
* Do not modify this file directly!
*/
return array (
21191 => 'Zain',
21192 => 'MTN',
21195 => 'Vivacell',
21197 => 'Gemtel',
);

View File

@ -0,0 +1,122 @@
<?php
/**
* This file has been @generated by a phing task by {@link GeneratePhonePrefixData}.
* See [README.md](README.md#generating-data) for more information.
*
* Pull requests changing data in these files will not be accepted. See the
* [FAQ in the README](README.md#problems-with-invalid-numbers] on how to make
* metadata changes.
*
* Do not modify this file directly!
*/
return array (
212600 => 'Inwi',
212601 => 'Inwi',
212602 => 'Inwi',
212603 => 'Inwi',
212604 => 'Inwi',
212605 => 'Inwi',
212606 => 'Inwi',
212607 => 'Inwi',
212608 => 'Inwi',
212609 => 'Inwi',
212610 => 'Maroc Telecom',
212611 => 'Maroc Telecom',
212612 => 'Méditel',
212613 => 'Maroc Telecom',
212614 => 'Méditel',
212615 => 'Maroc Telecom',
212616 => 'Maroc Telecom',
212617 => 'Méditel',
212618 => 'Maroc Telecom',
212619 => 'Méditel',
212620 => 'Méditel',
212621 => 'Méditel',
212622 => 'Maroc Telecom',
212623 => 'Maroc Telecom',
212624 => 'Maroc Telecom',
212625 => 'Méditel',
212626 => 'Inwi',
212627 => 'Inwi',
212628 => 'Maroc Telecom',
212629 => 'Inwi',
212630 => 'Inwi',
212631 => 'Méditel',
212632 => 'Méditel',
212633 => 'Inwi',
212634 => 'Inwi',
212635 => 'Inwi',
212636 => 'Maroc Telecom',
212637 => 'Maroc Telecom',
212638 => 'Inwi',
212639 => 'Maroc Telecom',
212640 => 'Inwi',
212641 => 'Maroc Telecom',
212642 => 'Maroc Telecom',
212643 => 'Maroc Telecom',
212644 => 'Méditel',
212645 => 'Méditel',
212646 => 'Inwi',
212647 => 'Inwi',
212648 => 'Maroc Telecom',
212649 => 'Méditel',
212650 => 'Maroc Telecom',
212651 => 'Maroc Telecom',
212652 => 'Maroc Telecom',
212653 => 'Maroc Telecom',
212654 => 'Maroc Telecom',
212655 => 'Maroc Telecom',
212656 => 'Méditel',
212657 => 'Méditel',
212658 => 'Maroc Telecom',
212659 => 'Maroc Telecom',
212660 => 'Méditel',
212661 => 'Maroc Telecom',
212662 => 'Maroc Telecom',
212663 => 'Méditel',
212664 => 'Méditel',
212665 => 'Méditel',
212666 => 'Maroc Telecom',
212667 => 'Maroc Telecom',
212668 => 'Maroc Telecom',
212669 => 'Méditel',
212670 => 'Maroc Telecom',
212671 => 'Maroc Telecom',
212672 => 'Maroc Telecom',
212673 => 'Maroc Telecom',
212674 => 'Méditel',
212675 => 'Méditel',
212676 => 'Maroc Telecom',
212677 => 'Maroc Telecom',
212678 => 'Maroc Telecom',
212679 => 'Méditel',
212680 => 'Inwi',
212681 => 'Inwi',
212682 => 'Maroc Telecom',
212684 => 'Méditel',
212687 => 'Inwi',
212688 => 'Méditel',
212689 => 'Maroc Telecom',
212690 => 'Inwi',
212691 => 'Méditel',
2126921 => 'Al Hourria Telecom',
2126922 => 'Al Hourria Telecom',
212693 => 'Méditel',
212694 => 'Méditel',
212695 => 'Inwi',
212696 => 'Maroc Telecom',
212697 => 'Maroc Telecom',
212698 => 'Inwi',
212699 => 'Inwi',
212700 => 'Inwi',
212706 => 'Inwi',
212707 => 'Inwi',
212761 => 'Maroc Telecom',
212762 => 'Maroc Telecom',
212766 => 'Maroc Telecom',
212767 => 'Maroc Telecom',
212770 => 'Méditel',
212771 => 'Méditel',
212777 => 'Méditel',
);

View File

@ -0,0 +1,20 @@
<?php
/**
* This file has been @generated by a phing task by {@link GeneratePhonePrefixData}.
* See [README.md](README.md#generating-data) for more information.
*
* Pull requests changing data in these files will not be accepted. See the
* [FAQ in the README](README.md#problems-with-invalid-numbers] on how to make
* metadata changes.
*
* Do not modify this file directly!
*/
return array (
21354 => 'Ooredoo',
21355 => 'Ooredoo',
21356 => 'Ooredoo',
2136 => 'Mobilis',
21377 => 'Djezzy',
21379 => 'Djezzy',
);

View File

@ -0,0 +1,24 @@
<?php
/**
* This file has been @generated by a phing task by {@link GeneratePhonePrefixData}.
* See [README.md](README.md#generating-data) for more information.
*
* Pull requests changing data in these files will not be accepted. See the
* [FAQ in the README](README.md#problems-with-invalid-numbers] on how to make
* metadata changes.
*
* Do not modify this file directly!
*/
return array (
2162 => 'Ooredoo',
21640 => 'Tunisie Telecom',
21641 => 'Tunisie Telecom',
21642 => 'Tunisie Telecom',
21643 => 'Lyca Mobile',
21644 => 'Tunisie Telecom',
21645 => 'Watany Ettisalat',
21646 => 'Ooredoo',
2165 => 'Orange',
2169 => 'Tunisie Telecom',
);

View File

@ -0,0 +1,19 @@
<?php
/**
* This file has been @generated by a phing task by {@link GeneratePhonePrefixData}.
* See [README.md](README.md#generating-data) for more information.
*
* Pull requests changing data in these files will not be accepted. See the
* [FAQ in the README](README.md#problems-with-invalid-numbers] on how to make
* metadata changes.
*
* Do not modify this file directly!
*/
return array (
2202 => 'Africell',
2203 => 'QCell',
2206 => 'Comium',
2207 => 'Africell',
2209 => 'Gamcel',
);

View File

@ -0,0 +1,20 @@
<?php
/**
* This file has been @generated by a phing task by {@link GeneratePhonePrefixData}.
* See [README.md](README.md#generating-data) for more information.
*
* Pull requests changing data in these files will not be accepted. See the
* [FAQ in the README](README.md#problems-with-invalid-numbers] on how to make
* metadata changes.
*
* Do not modify this file directly!
*/
return array (
22170 => 'Expresso',
22172 => 'HAYO',
22176 => 'Tigo',
22177 => 'Orange',
22178 => 'Orange',
22179 => 'ADIE',
);

View File

@ -0,0 +1,17 @@
<?php
/**
* This file has been @generated by a phing task by {@link GeneratePhonePrefixData}.
* See [README.md](README.md#generating-data) for more information.
*
* Pull requests changing data in these files will not be accepted. See the
* [FAQ in the README](README.md#problems-with-invalid-numbers] on how to make
* metadata changes.
*
* Do not modify this file directly!
*/
return array (
2222 => 'Chinguitel',
2223 => 'Mattel',
2224 => 'Mauritel',
);

View File

@ -0,0 +1,32 @@
<?php
/**
* This file has been @generated by a phing task by {@link GeneratePhonePrefixData}.
* See [README.md](README.md#generating-data) for more information.
*
* Pull requests changing data in these files will not be accepted. See the
* [FAQ in the README](README.md#problems-with-invalid-numbers] on how to make
* metadata changes.
*
* Do not modify this file directly!
*/
return array (
2232079 => 'Sotelma',
223217 => 'Sotelma',
22350 => 'Atel',
2236 => 'Sotelma',
2237 => 'Orange',
22382 => 'Orange',
22383 => 'Orange',
22389 => 'Sotelma',
22390 => 'Orange',
22391 => 'Orange',
22392 => 'Orange',
22393 => 'Orange',
22394 => 'Orange',
22395 => 'Sotelma',
22396 => 'Sotelma',
22397 => 'Sotelma',
22398 => 'Sotelma',
22399 => 'Sotelma',
);

View File

@ -0,0 +1,19 @@
<?php
/**
* This file has been @generated by a phing task by {@link GeneratePhonePrefixData}.
* See [README.md](README.md#generating-data) for more information.
*
* Pull requests changing data in these files will not be accepted. See the
* [FAQ in the README](README.md#problems-with-invalid-numbers] on how to make
* metadata changes.
*
* Do not modify this file directly!
*/
return array (
22460 => 'Sotelgui',
22462 => 'Orange',
22463 => 'Intercel',
22465 => 'Cellcom',
22466 => 'Areeba',
);

View File

@ -0,0 +1,65 @@
<?php
/**
* This file has been @generated by a phing task by {@link GeneratePhonePrefixData}.
* See [README.md](README.md#generating-data) for more information.
*
* Pull requests changing data in these files will not be accepted. See the
* [FAQ in the README](README.md#problems-with-invalid-numbers] on how to make
* metadata changes.
*
* Do not modify this file directly!
*/
return array (
22501 => 'Moov',
22502 => 'Moov',
22503 => 'Moov',
22504 => 'MTN',
22505 => 'MTN',
22506 => 'MTN',
22507 => 'Orange',
22508 => 'Orange',
22509 => 'Orange',
22540 => 'Moov',
22541 => 'Moov',
22542 => 'Moov',
22543 => 'Moov',
22544 => 'MTN',
22545 => 'MTN',
22546 => 'MTN',
22547 => 'Orange',
22548 => 'Orange',
22549 => 'Orange',
22550 => 'Moov',
22551 => 'Moov',
22552 => 'Moov',
22553 => 'Moov',
22554 => 'MTN',
22555 => 'MTN',
22556 => 'MTN',
22557 => 'Orange',
22558 => 'Orange',
22559 => 'Orange',
22560 => 'GreenN',
22561 => 'GreenN',
22564 => 'MTN',
22565 => 'MTN',
22566 => 'MTN',
22567 => 'Orange',
22568 => 'Orange',
22569 => 'Aircom',
22571 => 'Moov',
22572 => 'Moov',
22574 => 'MTN',
22575 => 'MTN',
22576 => 'MTN',
22577 => 'Orange',
22578 => 'Orange',
22579 => 'Orange',
22584 => 'MTN',
22585 => 'MTN',
22586 => 'MTN',
22587 => 'Orange',
22588 => 'Orange',
22589 => 'Orange',
);

View File

@ -0,0 +1,41 @@
<?php
/**
* This file has been @generated by a phing task by {@link GeneratePhonePrefixData}.
* See [README.md](README.md#generating-data) for more information.
*
* Pull requests changing data in these files will not be accepted. See the
* [FAQ in the README](README.md#problems-with-invalid-numbers] on how to make
* metadata changes.
*
* Do not modify this file directly!
*/
return array (
22651 => 'Telmob',
22652 => 'Telmob',
22654 => 'Orange',
22655 => 'Airtel',
22656 => 'Airtel',
22657 => 'Orange',
22658 => 'Telecel Faso',
22660 => 'Telmob',
22661 => 'Telmob',
22662 => 'Telmob',
22663 => 'Telmob',
22664 => 'Airtel',
22665 => 'Airtel',
22666 => 'Airtel',
22667 => 'Airtel',
22668 => 'Telecel Faso',
22669 => 'Telecel Faso',
22670 => 'Telmob',
22671 => 'Telmob',
22672 => 'Telmob',
22673 => 'Telmob',
22674 => 'Airtel',
22675 => 'Airtel',
22676 => 'Airtel',
22677 => 'Airtel',
22678 => 'Telecel Faso',
22679 => 'Telecel Faso',
);

View File

@ -0,0 +1,26 @@
<?php
/**
* This file has been @generated by a phing task by {@link GeneratePhonePrefixData}.
* See [README.md](README.md#generating-data) for more information.
*
* Pull requests changing data in these files will not be accepted. See the
* [FAQ in the README](README.md#problems-with-invalid-numbers] on how to make
* metadata changes.
*
* Do not modify this file directly!
*/
return array (
22780 => 'Orange',
22788 => 'Airtel',
22789 => 'Airtel',
22790 => 'Orange',
22791 => 'Orange',
22792 => 'Orange',
22794 => 'Moov',
22795 => 'Moov',
22796 => 'Airtel',
22797 => 'Airtel',
22798 => 'Airtel',
22799 => 'Airtel',
);

View File

@ -0,0 +1,24 @@
<?php
/**
* This file has been @generated by a phing task by {@link GeneratePhonePrefixData}.
* See [README.md](README.md#generating-data) for more information.
*
* Pull requests changing data in these files will not be accepted. See the
* [FAQ in the README](README.md#problems-with-invalid-numbers] on how to make
* metadata changes.
*
* Do not modify this file directly!
*/
return array (
22870 => 'TOGOCEL',
22879 => 'Moov',
22890 => 'TOGOCEL',
22891 => 'TOGOCEL',
22892 => 'TOGOCEL',
22893 => 'TOGOCEL',
22896 => 'Moov',
22897 => 'TOGOCEL',
22898 => 'Moov',
22899 => 'Moov',
);

View File

@ -0,0 +1,31 @@
<?php
/**
* This file has been @generated by a phing task by {@link GeneratePhonePrefixData}.
* See [README.md](README.md#generating-data) for more information.
*
* Pull requests changing data in these files will not be accepted. See the
* [FAQ in the README](README.md#problems-with-invalid-numbers] on how to make
* metadata changes.
*
* Do not modify this file directly!
*/
return array (
22960 => 'Moov',
22961 => 'MTN',
22962 => 'MTN',
22963 => 'Moov',
22964 => 'Moov',
22965 => 'Moov',
22966 => 'MTN',
22967 => 'MTN',
22968 => 'Moov',
22969 => 'MTN',
22990 => 'Libercom',
22993 => 'BLK',
22994 => 'Moov',
22995 => 'Moov',
22997 => 'MTN',
22998 => 'Moov',
22999 => 'Moov',
);

View File

@ -0,0 +1,66 @@
<?php
/**
* This file has been @generated by a phing task by {@link GeneratePhonePrefixData}.
* See [README.md](README.md#generating-data) for more information.
*
* Pull requests changing data in these files will not be accepted. See the
* [FAQ in the README](README.md#problems-with-invalid-numbers] on how to make
* metadata changes.
*
* Do not modify this file directly!
*/
return array (
230525 => 'Cellplus',
230528 => 'MTML',
230529 => 'MTML',
2305421 => 'Emtel',
2305422 => 'Emtel',
2305423 => 'Emtel',
2305428 => 'Emtel',
2305429 => 'Emtel',
230544 => 'Emtel',
2305471 => 'Cellplus',
2305472 => 'Emtel',
2305473 => 'Emtel',
2305474 => 'Emtel',
2305475 => 'Emtel',
2305476 => 'Emtel',
2305477 => 'Emtel',
2305478 => 'Emtel',
2305479 => 'Emtel',
230548 => 'Emtel',
230549 => 'Emtel',
230570 => 'Cellplus',
230571 => 'Emtel',
230572 => 'Emtel',
230573 => 'Emtel',
230574 => 'Emtel',
230575 => 'Cellplus',
230576 => 'Cellplus',
230577 => 'Cellplus',
230578 => 'Cellplus',
230579 => 'Cellplus',
230580 => 'Cellplus',
230581 => 'Cellplus',
230582 => 'Cellplus',
230583 => 'Cellplus',
230584 => 'Emtel',
230585 => 'Emtel',
230586 => 'MTML',
2305871 => 'MTML',
2305875 => 'Cellplus',
2305876 => 'Cellplus',
2305877 => 'Cellplus',
2305878 => 'Cellplus',
230589 => 'MTML',
230590 => 'Cellplus',
230591 => 'Cellplus',
230592 => 'Cellplus',
230593 => 'Emtel',
230594 => 'Cellplus',
230595 => 'MTML',
230596 => 'MTML',
230597 => 'Emtel',
230598 => 'Emtel',
);

View File

@ -0,0 +1,19 @@
<?php
/**
* This file has been @generated by a phing task by {@link GeneratePhonePrefixData}.
* See [README.md](README.md#generating-data) for more information.
*
* Pull requests changing data in these files will not be accepted. See the
* [FAQ in the README](README.md#problems-with-invalid-numbers] on how to make
* metadata changes.
*
* Do not modify this file directly!
*/
return array (
23120 => 'LIBTELCO',
231330 => 'West Africa Telecom',
231555 => 'Novafone',
23177 => 'Cellcom',
23188 => 'Lonestar Cell',
);

View File

@ -0,0 +1,34 @@
<?php
/**
* This file has been @generated by a phing task by {@link GeneratePhonePrefixData}.
* See [README.md](README.md#generating-data) for more information.
*
* Pull requests changing data in these files will not be accepted. See the
* [FAQ in the README](README.md#problems-with-invalid-numbers] on how to make
* metadata changes.
*
* Do not modify this file directly!
*/
return array (
23221 => 'Sierratel',
23225 => 'Sierratel',
23230 => 'Africell',
23231 => 'QCELL',
23233 => 'Comium',
23234 => 'QCELL',
23235 => 'IPTEL',
23240 => 'Datatel/Cellcom',
23244 => 'Intergroup',
23250 => 'Datatel/Cellcom',
23255 => 'AFCOM',
23266 => 'Onlime',
23275 => 'Orange',
23276 => 'Airtel',
23277 => 'Africell',
23278 => 'Airtel',
23279 => 'Airtel',
23280 => 'Africell',
23288 => 'Africell',
23299 => 'Africell',
);

View File

@ -0,0 +1,31 @@
<?php
/**
* This file has been @generated by a phing task by {@link GeneratePhonePrefixData}.
* See [README.md](README.md#generating-data) for more information.
*
* Pull requests changing data in these files will not be accepted. See the
* [FAQ in the README](README.md#problems-with-invalid-numbers] on how to make
* metadata changes.
*
* Do not modify this file directly!
*/
return array (
23320 => 'Vodafone',
23323 => 'Globacom (Zain)',
23324 => 'MTN',
23326 => 'Airtel',
23327 => 'tiGO',
23328 => 'Expresso',
23350 => 'Vodafone',
23354 => 'MTN',
233553 => 'MTN',
233554 => 'MTN',
233555 => 'MTN',
233556 => 'MTN',
233557 => 'MTN',
233558 => 'MTN',
233560 => 'Airtel',
233561 => 'Airtel',
23357 => 'tiGO',
);

View File

@ -0,0 +1,257 @@
<?php
/**
* This file has been @generated by a phing task by {@link GeneratePhonePrefixData}.
* See [README.md](README.md#generating-data) for more information.
*
* Pull requests changing data in these files will not be accepted. See the
* [FAQ in the README](README.md#problems-with-invalid-numbers] on how to make
* metadata changes.
*
* Do not modify this file directly!
*/
return array (
234173 => 'Starcomms',
234174 => 'Starcomms',
2341804 => 'Starcomms',
234181 => 'Starcomms',
234182 => 'Starcomms',
234184 => 'Starcomms',
234185 => 'Starcomms',
234187 => 'Starcomms',
2341880 => 'Starcomms',
2341881 => 'Starcomms',
2341882 => 'Starcomms',
2341883 => 'Starcomms',
234189 => 'Starcomms',
234195 => 'Starcomms',
2342870 => 'Starcomms',
2342871 => 'Starcomms',
2342872 => 'Starcomms',
2342873 => 'Starcomms',
2342874 => 'Starcomms',
2342875 => 'Starcomms',
2342876 => 'Starcomms',
2342877 => 'Starcomms',
2343181 => 'Starcomms',
2343182 => 'Starcomms',
2343183 => 'Starcomms',
2343184 => 'Starcomms',
2343185 => 'Starcomms',
2343186 => 'Starcomms',
2343187 => 'Starcomms',
2343188 => 'Starcomms',
2343880 => 'Starcomms',
2343881 => 'Starcomms',
2343882 => 'Starcomms',
2343883 => 'Starcomms',
2343884 => 'Starcomms',
2343885 => 'Starcomms',
2343886 => 'Starcomms',
2343887 => 'Starcomms',
2343961 => 'Starcomms',
2343962 => 'Starcomms',
2343963 => 'Starcomms',
2343964 => 'Starcomms',
2343965 => 'Starcomms',
2343985 => 'Starcomms',
2343986 => 'Starcomms',
2343987 => 'Starcomms',
2343988 => 'Starcomms',
2343989 => 'Starcomms',
2344280 => 'Starcomms',
2344281 => 'Starcomms',
2344282 => 'Starcomms',
2344671 => 'Starcomms',
2344672 => 'Starcomms',
2344673 => 'Starcomms',
2344674 => 'Starcomms',
2344675 => 'Starcomms',
2344676 => 'Starcomms',
2344677 => 'Starcomms',
2344678 => 'Starcomms',
2344679 => 'Starcomms',
2344680 => 'Starcomms',
2344682 => 'Starcomms',
2344683 => 'Starcomms',
2344684 => 'Starcomms',
2344687 => 'Starcomms',
2344880 => 'Starcomms',
2344881 => 'Starcomms',
2344882 => 'Starcomms',
2345277 => 'Starcomms',
2345278 => 'Starcomms',
2345279 => 'Starcomms',
234528 => 'Starcomms',
2345381 => 'Starcomms',
2345382 => 'Starcomms',
2345383 => 'Starcomms',
2345384 => 'Starcomms',
2345385 => 'Starcomms',
2345386 => 'Starcomms',
2345387 => 'Starcomms',
2345389 => 'Starcomms',
2345480 => 'Starcomms',
2345481 => 'Starcomms',
2345482 => 'Starcomms',
2345483 => 'Starcomms',
2345484 => 'Starcomms',
2345485 => 'Starcomms',
2345486 => 'Starcomms',
2345487 => 'Starcomms',
2345684 => 'Starcomms',
2345685 => 'Starcomms',
2345686 => 'Starcomms',
2345687 => 'Starcomms',
2346277 => 'Starcomms',
2346278 => 'Starcomms',
2346279 => 'Starcomms',
234628 => 'Starcomms',
2346437 => 'Starcomms',
2346438 => 'Starcomms',
2346439 => 'Starcomms',
2346461 => 'Starcomms',
2346462 => 'Starcomms',
2346469 => 'Starcomms',
2346470 => 'Starcomms',
2346474 => 'Starcomms',
2346475 => 'Starcomms',
2346476 => 'Starcomms',
2346479 => 'Starcomms',
2346481 => 'Starcomms',
2346482 => 'Starcomms',
2346489 => 'Starcomms',
2346491 => 'Starcomms',
2346492 => 'Starcomms',
2346493 => 'Starcomms',
2346494 => 'Starcomms',
2346495 => 'Starcomms',
2346496 => 'Starcomms',
2346497 => 'Starcomms',
2346498 => 'Starcomms',
2346580 => 'Starcomms',
2346581 => 'Starcomms',
2346582 => 'Starcomms',
2346987 => 'Starcomms',
2346988 => 'Starcomms',
2346989 => 'Starcomms',
234701 => 'Airtel',
2347020 => 'Smile',
2347021 => 'Ntel',
2347022 => 'Ntel',
2347023 => 'Zoom',
2347024 => 'Prestel',
2347025 => 'Visafone',
2347026 => 'Visafone',
2347027 => 'Multilinks',
2347028 => 'Starcomms',
2347029 => 'Starcomms',
234703 => 'MTN',
234704 => 'Visafone',
234705 => 'Glo',
234706 => 'MTN',
234707 => 'Zoom',
234708 => 'Airtel',
234709 => 'Multilinks',
2347380 => 'Starcomms',
2347381 => 'Starcomms',
2347382 => 'Starcomms',
2347383 => 'Starcomms',
2347384 => 'Starcomms',
2347385 => 'Starcomms',
2347386 => 'Starcomms',
2347387 => 'Starcomms',
2347691 => 'Starcomms',
2347692 => 'Starcomms',
2347693 => 'Starcomms',
2347694 => 'Starcomms',
2347695 => 'Starcomms',
2347696 => 'Starcomms',
2347697 => 'Starcomms',
2347698 => 'Starcomms',
2347782 => 'Starcomms',
2347783 => 'Starcomms',
2347784 => 'Starcomms',
2348010 => 'Megatech',
2348011 => 'Megatech',
234802 => 'Airtel',
234803 => 'MTN',
234804 => 'Ntel',
234805 => 'Glo',
234806 => 'MTN',
234807 => 'Glo',
234808 => 'Airtel',
234809 => '9mobile',
234810 => 'MTN',
234811 => 'Glo',
234812 => 'Airtel',
234813 => 'MTN',
234814 => 'MTN',
234815 => 'Glo',
234816 => 'MTN',
234817 => '9mobile',
234818 => '9mobile',
2348190 => 'Starcomms',
2348191 => 'Starcomms',
2348283 => 'Starcomms',
2348284 => 'Starcomms',
2348285 => 'Starcomms',
2348286 => 'Starcomms',
2348287 => 'Starcomms',
2348288 => 'Starcomms',
2348380 => 'Starcomms',
2348381 => 'Starcomms',
2348382 => 'Starcomms',
2348421 => 'Starcomms',
2348422 => 'Starcomms',
2348431 => 'Starcomms',
2348434 => 'Starcomms',
2348437 => 'Starcomms',
2348438 => 'Starcomms',
2348439 => 'Starcomms',
2348453 => 'Starcomms',
2348454 => 'Starcomms',
2348456 => 'Starcomms',
2348474 => 'Starcomms',
2348475 => 'Starcomms',
2348476 => 'Starcomms',
2348477 => 'Starcomms',
2348478 => 'Starcomms',
2348479 => 'Starcomms',
2348480 => 'Starcomms',
2348481 => 'Starcomms',
2348484 => 'Starcomms',
2348485 => 'Starcomms',
2348486 => 'Starcomms',
2348488 => 'Starcomms',
2348489 => 'Starcomms',
2348490 => 'Starcomms',
2348581 => 'Starcomms',
2348582 => 'Starcomms',
2348583 => 'Starcomms',
2348584 => 'Starcomms',
2348585 => 'Starcomms',
2348586 => 'Starcomms',
2348587 => 'Starcomms',
2348588 => 'Starcomms',
2348782 => 'Starcomms',
2348783 => 'Starcomms',
2348784 => 'Starcomms',
2348785 => 'Starcomms',
2348786 => 'Starcomms',
2348787 => 'Starcomms',
2348788 => 'Starcomms',
2348789 => 'Starcomms',
2348885 => 'Starcomms',
2348886 => 'Starcomms',
2348887 => 'Starcomms',
234902 => 'Airtel',
234903 => 'MTN',
234905 => 'Glo',
234906 => 'MTN',
234907 => 'Airtel',
234908 => '9mobile',
234909 => '9mobile',
234980 => 'Starcomms',
234987 => 'Starcomms',
);

View File

@ -0,0 +1,17 @@
<?php
/**
* This file has been @generated by a phing task by {@link GeneratePhonePrefixData}.
* See [README.md](README.md#generating-data) for more information.
*
* Pull requests changing data in these files will not be accepted. See the
* [FAQ in the README](README.md#problems-with-invalid-numbers] on how to make
* metadata changes.
*
* Do not modify this file directly!
*/
return array (
2356 => 'Airtel',
23577 => 'Sotel',
2359 => 'Millicom',
);

View File

@ -0,0 +1,18 @@
<?php
/**
* This file has been @generated by a phing task by {@link GeneratePhonePrefixData}.
* See [README.md](README.md#generating-data) for more information.
*
* Pull requests changing data in these files will not be accepted. See the
* [FAQ in the README](README.md#problems-with-invalid-numbers] on how to make
* metadata changes.
*
* Do not modify this file directly!
*/
return array (
23670 => 'TC',
23672 => 'Orange',
23675 => 'CTP',
23677 => 'Nationlink',
);

View File

@ -0,0 +1,28 @@
<?php
/**
* This file has been @generated by a phing task by {@link GeneratePhonePrefixData}.
* See [README.md](README.md#generating-data) for more information.
*
* Pull requests changing data in these files will not be accepted. See the
* [FAQ in the README](README.md#problems-with-invalid-numbers] on how to make
* metadata changes.
*
* Do not modify this file directly!
*/
return array (
237650 => 'MTN Cameroon',
237651 => 'MTN Cameroon',
237652 => 'MTN Cameroon',
237653 => 'MTN Cameroon',
237654 => 'MTN Cameroon',
237655 => 'Orange',
237656 => 'Orange',
237657 => 'Orange',
237658 => 'Orange',
237659 => 'Orange',
23766 => 'NEXTTEL',
23767 => 'MTN Cameroon',
23768 => 'MTN Cameroon',
23769 => 'Orange',
);

View File

@ -0,0 +1,30 @@
<?php
/**
* This file has been @generated by a phing task by {@link GeneratePhonePrefixData}.
* See [README.md](README.md#generating-data) for more information.
*
* Pull requests changing data in these files will not be accepted. See the
* [FAQ in the README](README.md#problems-with-invalid-numbers] on how to make
* metadata changes.
*
* Do not modify this file directly!
*/
return array (
23833 => 'T+',
23836 => 'CVMOVEL',
23843 => 'T+',
23846 => 'CVMOVEL',
23851 => 'T+',
23852 => 'T+',
23853 => 'T+',
23858 => 'CVMOVEL',
23859 => 'CVMOVEL',
23891 => 'T+',
23892 => 'T+',
23893 => 'T+',
23895 => 'CVMOVEL',
23897 => 'CVMOVEL',
23898 => 'CVMOVEL',
23899 => 'CVMOVEL',
);

View File

@ -0,0 +1,17 @@
<?php
/**
* This file has been @generated by a phing task by {@link GeneratePhonePrefixData}.
* See [README.md](README.md#generating-data) for more information.
*
* Pull requests changing data in these files will not be accepted. See the
* [FAQ in the README](README.md#problems-with-invalid-numbers] on how to make
* metadata changes.
*
* Do not modify this file directly!
*/
return array (
23990 => 'Unitel',
23998 => 'CSTmovel',
23999 => 'CSTmovel',
);

View File

@ -0,0 +1,17 @@
<?php
/**
* This file has been @generated by a phing task by {@link GeneratePhonePrefixData}.
* See [README.md](README.md#generating-data) for more information.
*
* Pull requests changing data in these files will not be accepted. See the
* [FAQ in the README](README.md#problems-with-invalid-numbers] on how to make
* metadata changes.
*
* Do not modify this file directly!
*/
return array (
2405 => 'Orange GQ',
2406 => 'Orange GQ',
2407 => 'Orange GQ',
);

View File

@ -0,0 +1,35 @@
<?php
/**
* This file has been @generated by a phing task by {@link GeneratePhonePrefixData}.
* See [README.md](README.md#generating-data) for more information.
*
* Pull requests changing data in these files will not be accepted. See the
* [FAQ in the README](README.md#problems-with-invalid-numbers] on how to make
* metadata changes.
*
* Do not modify this file directly!
*/
return array (
24104 => 'Airtel',
24105 => 'Moov',
24106 => 'Libertis',
24107 => 'Airtel',
24110 => 'Libertis',
24111 => 'Libertis',
24120 => 'Libertis',
24121 => 'Libertis',
24122 => 'Libertis',
24123 => 'Libertis',
24124 => 'Libertis',
24125 => 'Libertis',
24126 => 'Libertis',
24127 => 'Libertis',
2413 => 'Libertis',
2414 => 'Airtel',
2415 => 'Moov',
2416 => 'Libertis',
2417 => 'Airtel',
24195 => 'Libertis',
24197 => 'Libertis',
);

View File

@ -0,0 +1,19 @@
<?php
/**
* This file has been @generated by a phing task by {@link GeneratePhonePrefixData}.
* See [README.md](README.md#generating-data) for more information.
*
* Pull requests changing data in these files will not be accepted. See the
* [FAQ in the README](README.md#problems-with-invalid-numbers] on how to make
* metadata changes.
*
* Do not modify this file directly!
*/
return array (
24201 => 'Equateur Telecom',
24204 => 'Warid',
24205 => 'Celtel',
24206 => 'MTN',
2428001 => 'Hightech Pro',
);

View File

@ -0,0 +1,25 @@
<?php
/**
* This file has been @generated by a phing task by {@link GeneratePhonePrefixData}.
* See [README.md](README.md#generating-data) for more information.
*
* Pull requests changing data in these files will not be accepted. See the
* [FAQ in the README](README.md#problems-with-invalid-numbers] on how to make
* metadata changes.
*
* Do not modify this file directly!
*/
return array (
24380 => 'Supercell',
24381 => 'Vodacom',
24382 => 'Vodacom',
24384 => 'CCT',
24388 => 'Yozma Timeturns sprl -YTT',
24389 => 'Tigo',
24390 => 'Africell',
24391 => 'Africell',
24397 => 'Zain',
24398 => 'Zain',
24399 => 'Zain',
);

View File

@ -0,0 +1,19 @@
<?php
/**
* This file has been @generated by a phing task by {@link GeneratePhonePrefixData}.
* See [README.md](README.md#generating-data) for more information.
*
* Pull requests changing data in these files will not be accepted. See the
* [FAQ in the README](README.md#problems-with-invalid-numbers] on how to make
* metadata changes.
*
* Do not modify this file directly!
*/
return array (
24491 => 'Movicel',
24492 => 'UNITEL',
24493 => 'UNITEL',
24494 => 'UNITEL',
24499 => 'Movicel',
);

View File

@ -0,0 +1,19 @@
<?php
/**
* This file has been @generated by a phing task by {@link GeneratePhonePrefixData}.
* See [README.md](README.md#generating-data) for more information.
*
* Pull requests changing data in these files will not be accepted. See the
* [FAQ in the README](README.md#problems-with-invalid-numbers] on how to make
* metadata changes.
*
* Do not modify this file directly!
*/
return array (
24595 => 'Orange',
245965 => 'Spacetel',
245966 => 'Spacetel',
245969 => 'Spacetel',
245977 => 'Guinetel',
);

View File

@ -0,0 +1,18 @@
<?php
/**
* This file has been @generated by a phing task by {@link GeneratePhonePrefixData}.
* See [README.md](README.md#generating-data) for more information.
*
* Pull requests changing data in these files will not be accepted. See the
* [FAQ in the README](README.md#problems-with-invalid-numbers] on how to make
* metadata changes.
*
* Do not modify this file directly!
*/
return array (
24825 => 'CWS',
24826 => 'CWS',
24827 => 'Airtel',
24828 => 'Airtel',
);

View File

@ -0,0 +1,24 @@
<?php
/**
* This file has been @generated by a phing task by {@link GeneratePhonePrefixData}.
* See [README.md](README.md#generating-data) for more information.
*
* Pull requests changing data in these files will not be accepted. See the
* [FAQ in the README](README.md#problems-with-invalid-numbers] on how to make
* metadata changes.
*
* Do not modify this file directly!
*/
return array (
24910 => 'Sudatel',
24911 => 'Sudatel',
24912 => 'Sudatel',
24990 => 'Zain',
24991 => 'Zain',
24992 => 'MTN',
24993 => 'MTN',
24995 => 'Network of The World Ltd',
24996 => 'Zain',
24999 => 'MTN',
);

View File

@ -0,0 +1,17 @@
<?php
/**
* This file has been @generated by a phing task by {@link GeneratePhonePrefixData}.
* See [README.md](README.md#generating-data) for more information.
*
* Pull requests changing data in these files will not be accepted. See the
* [FAQ in the README](README.md#problems-with-invalid-numbers] on how to make
* metadata changes.
*
* Do not modify this file directly!
*/
return array (
25072 => 'TIGO',
25073 => 'Airtel',
25078 => 'MTN',
);

View File

@ -0,0 +1,15 @@
<?php
/**
* This file has been @generated by a phing task by {@link GeneratePhonePrefixData}.
* See [README.md](README.md#generating-data) for more information.
*
* Pull requests changing data in these files will not be accepted. See the
* [FAQ in the README](README.md#problems-with-invalid-numbers] on how to make
* metadata changes.
*
* Do not modify this file directly!
*/
return array (
2519 => 'Ethio Telecom',
);

View File

@ -0,0 +1,41 @@
<?php
/**
* This file has been @generated by a phing task by {@link GeneratePhonePrefixData}.
* See [README.md](README.md#generating-data) for more information.
*
* Pull requests changing data in these files will not be accepted. See the
* [FAQ in the README](README.md#problems-with-invalid-numbers] on how to make
* metadata changes.
*
* Do not modify this file directly!
*/
return array (
25224 => 'Telesom',
25228 => 'Nationlink',
25235 => 'AirSom',
25239 => 'AirSom',
25248 => 'AirSom',
25249 => 'AirSom',
25262 => 'Somtel',
25263 => 'Telesom',
25264 => 'Somali Networks',
25265 => 'Somtel',
25266 => 'Somtel',
25267 => 'Nationlink',
25268 => 'Nationlink',
25269 => 'Nationlink',
25279 => 'Somtel',
25280 => 'Somali Networks',
25288 => 'Somali Networks',
252906 => 'Golis Telecom',
252907 => 'Golis Telecom',
25292 => 'STG',
25293 => 'STG',
25294 => 'STG',
25295 => 'STG',
25296 => 'STG',
25297 => 'STG',
25298 => 'STG',
25299 => 'STG',
);

View File

@ -0,0 +1,15 @@
<?php
/**
* This file has been @generated by a phing task by {@link GeneratePhonePrefixData}.
* See [README.md](README.md#generating-data) for more information.
*
* Pull requests changing data in these files will not be accepted. See the
* [FAQ in the README](README.md#problems-with-invalid-numbers] on how to make
* metadata changes.
*
* Do not modify this file directly!
*/
return array (
25377 => 'Evatis',
);

View File

@ -0,0 +1,65 @@
<?php
/**
* This file has been @generated by a phing task by {@link GeneratePhonePrefixData}.
* See [README.md](README.md#generating-data) for more information.
*
* Pull requests changing data in these files will not be accepted. See the
* [FAQ in the README](README.md#problems-with-invalid-numbers] on how to make
* metadata changes.
*
* Do not modify this file directly!
*/
return array (
25470 => 'Safaricom',
25471 => 'Safaricom',
25472 => 'Safaricom',
25473 => 'Airtel',
254740 => 'Safaricom',
254741 => 'Safaricom',
254742 => 'Safaricom',
254743 => 'Safaricom',
254744 => 'Homeland Media',
254745 => 'Safaricom',
254746 => 'Safaricom',
254747 => 'JTL',
254748 => 'Safaricom',
254749 => 'WiAfrica',
254750 => 'Airtel',
254751 => 'Airtel',
254752 => 'Airtel',
254753 => 'Airtel',
254754 => 'Airtel',
254755 => 'Airtel',
254756 => 'Airtel',
254757 => 'Safaricom',
254760 => 'Mobile Pay',
254761 => 'Airtel',
254762 => 'Airtel',
254763 => 'Finserve',
254764 => 'Finserve',
254765 => 'Finserve',
254766 => 'Finserve',
254767 => 'Sema Mobile',
254768 => 'Airtel',
254769 => 'Airtel',
254770 => 'Telkom',
254771 => 'Telkom',
254772 => 'Telkom',
254773 => 'Telkom',
254774 => 'Telkom',
254775 => 'Telkom',
254776 => 'Telkom',
254777 => 'Telkom',
254778 => 'Telkom',
254779 => 'Telkom',
254780 => 'Airtel',
254781 => 'Airtel',
254782 => 'Airtel',
254785 => 'Airtel',
254786 => 'Airtel',
254787 => 'Airtel',
254788 => 'Airtel',
254789 => 'Airtel',
25479 => 'Safaricom',
);

View File

@ -0,0 +1,29 @@
<?php
/**
* This file has been @generated by a phing task by {@link GeneratePhonePrefixData}.
* See [README.md](README.md#generating-data) for more information.
*
* Pull requests changing data in these files will not be accepted. See the
* [FAQ in the README](README.md#problems-with-invalid-numbers] on how to make
* metadata changes.
*
* Do not modify this file directly!
*/
return array (
25562 => 'Viettel',
25563 => 'MTC',
25564 => 'Cootel',
25565 => 'tiGO',
25566 => 'SMILE',
25567 => 'tiGO',
25568 => 'Airtel',
25571 => 'tiGO',
25573 => 'Tanzania Telecom',
25574 => 'Vodacom',
25575 => 'Vodacom',
25576 => 'Vodacom',
25577 => 'Zantel',
25578 => 'Airtel',
25579 => 'Benson Informatics',
);

View File

@ -0,0 +1,25 @@
<?php
/**
* This file has been @generated by a phing task by {@link GeneratePhonePrefixData}.
* See [README.md](README.md#generating-data) for more information.
*
* Pull requests changing data in these files will not be accepted. See the
* [FAQ in the README](README.md#problems-with-invalid-numbers] on how to make
* metadata changes.
*
* Do not modify this file directly!
*/
return array (
25670 => 'Airtel',
25671 => 'UTL',
256720 => 'Smile',
256723 => 'Afrimax',
2567260 => 'Tangerine',
256730 => 'K2',
25674 => 'Sure Telecom',
25675 => 'Airtel',
25677 => 'MTN',
25678 => 'MTN',
25679 => 'Africell',
);

View File

@ -0,0 +1,26 @@
<?php
/**
* This file has been @generated by a phing task by {@link GeneratePhonePrefixData}.
* See [README.md](README.md#generating-data) for more information.
*
* Pull requests changing data in these files will not be accepted. See the
* [FAQ in the README](README.md#problems-with-invalid-numbers] on how to make
* metadata changes.
*
* Do not modify this file directly!
*/
return array (
25729 => 'Leo',
25731 => 'Viettel',
25761 => 'Viettel',
25768 => 'Viettel',
25769 => 'Viettel',
25771 => 'Leo',
25772 => 'Leo',
25775 => 'Smart Mobile',
25776 => 'Leo',
25777 => 'Onatel',
25778 => 'Smart Mobile',
25779 => 'Leo',
);

View File

@ -0,0 +1,20 @@
<?php
/**
* This file has been @generated by a phing task by {@link GeneratePhonePrefixData}.
* See [README.md](README.md#generating-data) for more information.
*
* Pull requests changing data in these files will not be accepted. See the
* [FAQ in the README](README.md#problems-with-invalid-numbers] on how to make
* metadata changes.
*
* Do not modify this file directly!
*/
return array (
25882 => 'mcel',
25883 => 'mcel',
25884 => 'Vodacom',
25885 => 'Vodacom',
25886 => 'Movitel',
25887 => 'Movitel',
);

View File

@ -0,0 +1,17 @@
<?php
/**
* This file has been @generated by a phing task by {@link GeneratePhonePrefixData}.
* See [README.md](README.md#generating-data) for more information.
*
* Pull requests changing data in these files will not be accepted. See the
* [FAQ in the README](README.md#problems-with-invalid-numbers] on how to make
* metadata changes.
*
* Do not modify this file directly!
*/
return array (
26095 => 'ZAMTEL',
26096 => 'MTN',
26097 => 'Airtel',
);

View File

@ -0,0 +1,18 @@
<?php
/**
* This file has been @generated by a phing task by {@link GeneratePhonePrefixData}.
* See [README.md](README.md#generating-data) for more information.
*
* Pull requests changing data in these files will not be accepted. See the
* [FAQ in the README](README.md#problems-with-invalid-numbers] on how to make
* metadata changes.
*
* Do not modify this file directly!
*/
return array (
26132 => 'Orange',
26133 => 'Airtel',
26134 => 'Telma',
26139 => 'Blueline',
);

View File

@ -0,0 +1,122 @@
<?php
/**
* This file has been @generated by a phing task by {@link GeneratePhonePrefixData}.
* See [README.md](README.md#generating-data) for more information.
*
* Pull requests changing data in these files will not be accepted. See the
* [FAQ in the README](README.md#problems-with-invalid-numbers] on how to make
* metadata changes.
*
* Do not modify this file directly!
*/
return array (
26263900 => 'Orange',
26263901 => 'Orange',
26263902 => 'Orange',
26263903 => 'Only',
26263904 => 'Only',
26263905 => 'Only',
26263906 => 'Only',
26263907 => 'Only',
26263909 => 'SFR',
26263910 => 'SFR',
26263911 => 'SFR',
26263919 => 'Only',
2626392 => 'SFR',
26263926 => 'Only',
26263930 => 'BJT',
26263939 => 'Only',
26263940 => 'SFR',
26263950 => 'BJT',
26263960 => 'Orange',
26263961 => 'Orange',
26263962 => 'Orange',
26263963 => 'Orange',
26263964 => 'Orange',
26263965 => 'SFR',
26263966 => 'SFR',
26263967 => 'SFR',
26263968 => 'SFR',
26263969 => 'SFR',
26263970 => 'BJT',
26263971 => 'Only',
26263972 => 'Only',
26263973 => 'Only',
26263974 => 'Only',
26263975 => 'Only',
26263976 => 'Orange',
26263990 => 'BJT',
26263994 => 'Only',
26263995 => 'Only',
26263996 => 'Only',
26263997 => 'Only',
26263999 => 'Orange',
2626920 => 'Orange',
26269206 => 'SFR',
2626921 => 'SFR',
2626922 => 'Orange',
2626923 => 'Orange',
26269240 => 'Orange',
26269241 => 'Orange',
26269242 => 'Orange',
26269243 => 'Orange',
26269244 => 'Orange',
26269245 => 'SFR',
26269246 => 'SFR',
26269247 => 'SFR',
26269248 => 'SFR',
26269249 => 'SFR',
2626925 => 'SFR',
2626926 => 'SFR',
2626927 => 'SFR',
2626928 => 'SFR',
26269290 => 'SFR',
26269291 => 'SFR',
26269292 => 'Only',
26269293 => 'Only',
26269294 => 'Only',
26269295 => 'SFR',
26269296 => 'SFR',
26269297 => 'SFR',
26269298 => 'SFR',
26269299 => 'SFR',
26269300 => 'Orange',
26269301 => 'SFR',
26269302 => 'SFR',
26269303 => 'SFR',
26269304 => 'SFR',
26269306 => 'Orange',
26269310 => 'SFR',
26269311 => 'Orange',
26269313 => 'SFR',
26269320 => 'SFR',
26269321 => 'Orange',
26269322 => 'Orange',
26269330 => 'Only',
26269331 => 'Only',
26269332 => 'Only',
26269333 => 'Orange',
26269339 => 'Orange',
2626934 => 'Only',
26269350 => 'Only',
26269355 => 'Orange',
26269360 => 'Only',
26269366 => 'Orange',
26269370 => 'Only',
26269371 => 'Only',
26269372 => 'Only',
26269377 => 'Orange',
26269380 => 'Only',
26269381 => 'Only',
26269382 => 'Only',
26269383 => 'Only',
26269388 => 'Orange',
26269390 => 'Orange',
26269391 => 'Orange',
26269392 => 'Orange',
26269393 => 'Orange',
26269394 => 'SFR',
26269397 => 'SFR',
26269399 => 'Orange',
);

Some files were not shown because too many files have changed in this diff Show More