Fix bin/publish: copy docs.dist from project root

Fix bin/publish: use correct .env path for rspade_system
Fix bin/publish script: prevent grep exit code 1 from terminating script

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
root
2025-10-21 02:08:33 +00:00
commit f6fac6c4bc
79758 changed files with 10547827 additions and 0 deletions

View File

@@ -0,0 +1,65 @@
<?php
/**
* libphonenumber-for-php-lite data file
* This file has been @generated from libphonenumber data
* Do not modify!
* @internal
*/
namespace libphonenumber;
class AlternateFormatsCountryCodeSet
{
// A set of all country codes for which data is available.
public static $alternateFormatsCountryCodeSet = [
7,
27,
30,
31,
34,
36,
39,
43,
44,
49,
52,
54,
55,
58,
61,
62,
64,
66,
81,
84,
90,
91,
94,
95,
255,
350,
351,
352,
358,
359,
372,
373,
380,
381,
385,
505,
506,
595,
675,
676,
679,
855,
856,
971,
972,
995,
];
}

View File

@@ -0,0 +1,844 @@
<?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 invoked 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 = [];
/**
* @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 $separatorBeforeNationalNumber = ' ';
/**
* @var PhoneMetadata
*/
private static $emptyMetadata;
/**
* 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. We require that the first group is present in the output pattern to ensure
* no data is lost while formatting; when we format as you type, this should always be the case.
* @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 . ']*'
. '\$1' . '[' . 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 = strtoupper($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 the 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;
}
// Remove the current number format from $this->possibleFormats
unset($this->possibleFormats[$key]);
}
$this->ableToFormat = false;
return false;
}
/**
* @param string $leadingDigits
*/
private function getAvailableFormats($leadingDigits)
{
// First decide whether we should use international or national number rules.
$isInternationalNumber = $this->isCompleteNumber && $this->extractedNationalPrefix === '';
$formatList = ($isInternationalNumber && $this->currentMetadata->intlNumberFormatSize() > 0)
? $this->currentMetadata->intlNumberFormats()
: $this->currentMetadata->numberFormats();
foreach ($formatList as $format) {
// Discard a few formats that we know are not relevant based on the presence of the national
// prefix.
if ($this->extractedNationalPrefix !== ''
&& PhoneNumberUtil::formattingRuleHasFirstGroupOnly(
$format->getNationalPrefixFormattingRule()
)
&& !$format->getNationalPrefixOptionalWhenFormatting()
&& !$format->hasDomesticCarrierCodeFormattingRule()) {
// If it is a national number that had a national prefix, any rules that aren't valid with a
// national prefix should be excluded. A rule that has a carrier-code formatting rule is
// kept since the national prefix might actually be an extracted carrier code - we don't
// distinguish between these when extracting it in the AYTF.
continue;
}
if ($this->extractedNationalPrefix === ''
&& !$this->isCompleteNumber
&& !PhoneNumberUtil::formattingRuleHasFirstGroupOnly(
$format->getNationalPrefixFormattingRule()
)
&& !$format->getNationalPrefixOptionalWhenFormatting()) {
// This number was entered without a national prefix, and this formatting rule requires one,
// so we discard it.
continue;
}
$eligibleFormatMatcher = new Matcher(self::$eligibleFormatPattern, $format->getFormat());
if ($eligibleFormatMatcher->matches()) {
$this->possibleFormats[] = $format;
}
}
$this->narrowDownPossibleFormats($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]);
}
}
}
/**
* @return bool
*/
private function createFormattingTemplate(NumberFormat $format)
{
$numberPattern = $format->getPattern();
$this->formattingTemplate = '';
$tempTemplate = $this->getFormattingTemplate($numberPattern, $format->getFormat());
if ($tempTemplate !== '') {
$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 = [];
$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;
}
if ($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::$separatorBeforeNationalNumber;
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
// no break
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 ($formattedNumber !== '') {
return $formattedNumber;
}
$this->narrowDownPossibleFormats($this->nationalNumber);
if ($this->maybeCreateNewTemplate()) {
return $this->inputAccruedNationalNumber();
}
return $this->ableToFormat
? $this->appendNationalNumber($tempNationalNumber)
: $this->accruedInput;
}
return $this->attemptToChooseFormattingPattern();
}
}
/**
* @return string
*/
private function attemptToChoosePatternWithPrefixExtracted()
{
$this->ableToFormat = true;
$this->isExpectingCountryCallingCode = false;
$this->possibleFormats = [];
$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());
// Check that we did not remove nor add any extra digits when we matched
// this formatting pattern. This usually happens after we entered the last
// digit during AYTF. Eg: In case of MX, we swallow mobile token (1) when
// formatted but AYTF should retain all the number entered and not change
// in order to match a format (of same leading digits and length) display
// in that way.
$fullOutput = $this->appendNationalNumber($formattedNumber);
$formattedNumberDigitsOnly = PhoneNumberUtil::normalizeDiallableCharsOnly($fullOutput);
if ($formattedNumberDigitsOnly === $this->accruedInputWithoutFormatting) {
// If it's the same (i.e entered number and format is same), then it's
// safe to return this in formatted number as nothing is lost / added.
return $fullOutput;
}
}
}
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::$separatorBeforeNationalNumber
) {
// 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::$separatorBeforeNationalNumber . $nationalNumber;
}
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 ($formattedNumber !== '') {
return $formattedNumber;
}
return $this->maybeCreateNewTemplate() ? $this->inputAccruedNationalNumber() : $this->accruedInput;
}
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;
}
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::$separatorBeforeNationalNumber;
$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::$separatorBeforeNationalNumber;
}
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 ($this->nationalNumber === '') {
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::$separatorBeforeNationalNumber;
// 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);
}
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".
*/
public 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.
*/
public 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.
*/
public 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.
*/
public const FROM_DEFAULT_COUNTRY = 3;
public const UNSPECIFIED = 4;
}

View File

@@ -0,0 +1,706 @@
<?php
/**
* libphonenumber-for-php-lite data file
* This file has been @generated from libphonenumber data
* Do not modify!
* @internal
*/
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 = [
1 => [
'US',
'AG',
'AI',
'AS',
'BB',
'BM',
'BS',
'CA',
'DM',
'DO',
'GD',
'GU',
'JM',
'KN',
'KY',
'LC',
'MP',
'MS',
'PR',
'SX',
'TC',
'TT',
'VC',
'VG',
'VI',
],
7 => [
'RU',
'KZ',
],
20 => [
'EG',
],
27 => [
'ZA',
],
30 => [
'GR',
],
[
'NL',
],
[
'BE',
],
[
'FR',
],
[
'ES',
],
36 => [
'HU',
],
39 => [
'IT',
'VA',
],
[
'RO',
],
[
'CH',
],
43 => [
'AT',
],
[
'GB',
'GG',
'IM',
'JE',
],
[
'DK',
],
[
'SE',
],
[
'NO',
'SJ',
],
[
'PL',
],
[
'DE',
],
51 => [
'PE',
],
[
'MX',
],
[
'CU',
],
[
'AR',
],
[
'BR',
],
[
'CL',
],
[
'CO',
],
[
'VE',
],
60 => [
'MY',
],
[
'AU',
'CC',
'CX',
],
[
'ID',
],
[
'PH',
],
[
'NZ',
],
[
'SG',
],
[
'TH',
],
81 => [
'JP',
],
[
'KR',
],
84 => [
'VN',
],
86 => [
'CN',
],
90 => [
'TR',
],
[
'IN',
],
[
'PK',
],
[
'AF',
],
[
'LK',
],
[
'MM',
],
98 => [
'IR',
],
211 => [
'SS',
],
[
'MA',
'EH',
],
[
'DZ',
],
216 => [
'TN',
],
218 => [
'LY',
],
220 => [
'GM',
],
[
'SN',
],
[
'MR',
],
[
'ML',
],
[
'GN',
],
[
'CI',
],
[
'BF',
],
[
'NE',
],
[
'TG',
],
[
'BJ',
],
[
'MU',
],
[
'LR',
],
[
'SL',
],
[
'GH',
],
[
'NG',
],
[
'TD',
],
[
'CF',
],
[
'CM',
],
[
'CV',
],
[
'ST',
],
[
'GQ',
],
[
'GA',
],
[
'CG',
],
[
'CD',
],
[
'AO',
],
[
'GW',
],
[
'IO',
],
[
'AC',
],
[
'SC',
],
[
'SD',
],
[
'RW',
],
[
'ET',
],
[
'SO',
],
[
'DJ',
],
[
'KE',
],
[
'TZ',
],
[
'UG',
],
[
'BI',
],
[
'MZ',
],
260 => [
'ZM',
],
[
'MG',
],
[
'RE',
'YT',
],
[
'ZW',
],
[
'NA',
],
[
'MW',
],
[
'LS',
],
[
'BW',
],
[
'SZ',
],
[
'KM',
],
290 => [
'SH',
'TA',
],
[
'ER',
],
297 => [
'AW',
],
[
'FO',
],
[
'GL',
],
350 => [
'GI',
],
[
'PT',
],
[
'LU',
],
[
'IE',
],
[
'IS',
],
[
'AL',
],
[
'MT',
],
[
'CY',
],
[
'FI',
'AX',
],
[
'BG',
],
370 => [
'LT',
],
[
'LV',
],
[
'EE',
],
[
'MD',
],
[
'AM',
],
[
'BY',
],
[
'AD',
],
[
'MC',
],
[
'SM',
],
380 => [
'UA',
],
[
'RS',
],
[
'ME',
],
[
'XK',
],
385 => [
'HR',
],
[
'SI',
],
[
'BA',
],
389 => [
'MK',
],
420 => [
'CZ',
],
[
'SK',
],
423 => [
'LI',
],
500 => [
'FK',
],
[
'BZ',
],
[
'GT',
],
[
'SV',
],
[
'HN',
],
[
'NI',
],
[
'CR',
],
[
'PA',
],
[
'PM',
],
[
'HT',
],
590 => [
'GP',
'BL',
'MF',
],
[
'BO',
],
[
'GY',
],
[
'EC',
],
[
'GF',
],
[
'PY',
],
[
'MQ',
],
[
'SR',
],
[
'UY',
],
[
'CW',
'BQ',
],
670 => [
'TL',
],
672 => [
'NF',
],
[
'BN',
],
[
'NR',
],
[
'PG',
],
[
'TO',
],
[
'SB',
],
[
'VU',
],
[
'FJ',
],
[
'PW',
],
[
'WF',
],
[
'CK',
],
[
'NU',
],
685 => [
'WS',
],
[
'KI',
],
[
'NC',
],
[
'TV',
],
[
'PF',
],
[
'TK',
],
[
'FM',
],
[
'MH',
],
800 => [
'001',
],
808 => [
'001',
],
850 => [
'KP',
],
852 => [
'HK',
],
[
'MO',
],
855 => [
'KH',
],
[
'LA',
],
870 => [
'001',
],
878 => [
'001',
],
880 => [
'BD',
],
[
'001',
],
[
'001',
],
[
'001',
],
886 => [
'TW',
],
888 => [
'001',
],
960 => [
'MV',
],
[
'LB',
],
[
'JO',
],
[
'SY',
],
[
'IQ',
],
[
'KW',
],
[
'SA',
],
[
'YE',
],
[
'OM',
],
970 => [
'PS',
],
[
'AE',
],
[
'IL',
],
[
'BH',
],
[
'QA',
],
[
'BT',
],
[
'MN',
],
[
'NP',
],
979 => [
'001',
],
992 => [
'TJ',
],
[
'TM',
],
[
'AZ',
],
[
'GE',
],
[
'KG',
],
998 => [
'UZ',
],
];
}

View File

@@ -0,0 +1,14 @@
<?php
namespace libphonenumber;
/**
* @internal
*/
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,51 @@
<?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 string $candidate
* @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
* @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,51 @@
<?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 string $candidate
* @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,23 @@
<?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 string $candidate
* @return bool
*/
public static function verify(PhoneNumber $number, $candidate, PhoneNumberUtil $util)
{
return $util->isPossibleNumber($number);
}
}

View File

@@ -0,0 +1,52 @@
<?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 string $candidate
* @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,30 @@
<?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 string $candidate
* @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
{
public const NOT_A_NUMBER = 0;
public const NO_MATCH = 1;
public const SHORT_NSN_MATCH = 2;
public const NSN_MATCH = 3;
public 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 = [];
private $searchIndex = 0;
/**
* @param string $pattern
* @param string $subject
*/
public function __construct($pattern, $subject)
{
$this->pattern = str_replace('/', '\/', (string) $pattern);
$this->subject = (string) $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 = [];
foreach ($groups as $group) {
$positions[] = [
$group[0],
$offset + mb_strlen(substr($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;
}
return count($this->groups) - 1;
}
/**
* @param int $group
* @return string
*/
public function group($group = null)
{
if ($group === null) {
$group = 0;
}
return $this->groups[$group][0] ?? null;
}
/**
* @param int|null $group
* @return int
*/
public function end($group = null)
{
if ($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 ($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,25 @@
<?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 boolean $allowPrefixMatch
* @return boolean
*/
public function matchNationalNumber($number, PhoneNumberDesc $numberDesc, $allowPrefixMatch);
}

View File

@@ -0,0 +1,15 @@
<?php
namespace libphonenumber;
/**
* @internal
*/
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,109 @@
<?php
/**
* @author joshuag
* @created: 04/08/2015 09:03
* @project libphonenumber-for-php
*/
namespace libphonenumber;
/**
* @internal
*/
class MultiFileMetadataSourceImpl implements MetadataSourceInterface
{
/**
* A mapping from a region code to the PhoneMetadata for that region.
* @var PhoneMetadata[]
*/
protected $regionToMetadataMap = [];
/**
* 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 = [];
/**
* 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 string|null $currentFilePrefix
*/
public function __construct(MetadataLoaderInterface $metadataLoader, $currentFilePrefix = null)
{
if ($currentFilePrefix === null) {
$currentFilePrefix = __DIR__ . '/data/PhoneNumberMetadata';
}
$this->currentFilePrefix = $currentFilePrefix;
$this->metadataLoader = $metadataLoader;
}
/**
*
*/
public function getMetadataForRegion($regionCode)
{
$regionCode = strtoupper($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];
}
/**
*
*/
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
* @throws \RuntimeException
*/
public function loadMetadataFromFile($filePrefix, $regionCode, $countryCallingCode, MetadataLoaderInterface $metadataLoader)
{
$regionCode = strtoupper($regionCode);
$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);
}
$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,351 @@
<?php
namespace libphonenumber;
/**
* Number Format
*/
class NumberFormat
{
/**
* @var string
*/
protected $pattern;
/**
* @var bool
*/
protected $hasPattern = false;
/**
* @var string
*/
protected $format;
/**
* @var bool
*/
protected $hasFormat = false;
/**
* @var array
*/
protected $leadingDigitsPattern = [];
/**
* @var string
*/
protected $nationalPrefixFormattingRule = '';
/**
* @var bool
*/
protected $hasNationalPrefixFormattingRule = false;
/**
* @var bool
*/
protected $nationalPrefixOptionalWhenFormatting = false;
/**
* @var bool
*/
protected $hasNationalPrefixOptionalWhenFormatting = false;
/**
* @var string
*/
protected $domesticCarrierCodeFormattingRule = '';
/**
* @var bool
*/
protected $hasDomesticCarrierCodeFormattingRule = false;
public function __construct()
{
$this->clear();
}
/**
* @return NumberFormat
*/
public function clear()
{
$this->hasPattern = false;
$this->pattern = null;
$this->hasFormat = false;
$this->format = null;
$this->leadingDigitsPattern = [];
$this->hasNationalPrefixFormattingRule = false;
$this->nationalPrefixFormattingRule = '';
$this->hasNationalPrefixOptionalWhenFormatting = false;
$this->nationalPrefixOptionalWhenFormatting = false;
$this->hasDomesticCarrierCodeFormattingRule = false;
$this->domesticCarrierCodeFormattingRule = '';
return $this;
}
/**
* @return boolean
*/
public function hasPattern()
{
return $this->hasPattern;
}
/**
* @return string
*/
public function getPattern()
{
return $this->pattern;
}
/**
* @param string $value
* @return NumberFormat
*/
public function setPattern($value)
{
$this->hasPattern = true;
$this->pattern = $value;
return $this;
}
/**
* @return boolean
*/
public function hasNationalPrefixOptionalWhenFormatting()
{
return $this->hasNationalPrefixOptionalWhenFormatting;
}
/**
* @return boolean
*/
public function getNationalPrefixOptionalWhenFormatting()
{
return $this->nationalPrefixOptionalWhenFormatting;
}
/**
* @param boolean $nationalPrefixOptionalWhenFormatting
*/
public function setNationalPrefixOptionalWhenFormatting($nationalPrefixOptionalWhenFormatting)
{
$this->hasNationalPrefixOptionalWhenFormatting = true;
$this->nationalPrefixOptionalWhenFormatting = $nationalPrefixOptionalWhenFormatting;
}
/**
* @return boolean
*/
public function hasFormat()
{
return $this->hasFormat;
}
/**
* @return string
*/
public function getFormat()
{
return $this->format;
}
/**
* @param string $value
* @return NumberFormat
*/
public function setFormat($value)
{
$this->hasFormat = true;
$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 $this->hasNationalPrefixFormattingRule;
}
/**
* @return string
*/
public function getNationalPrefixFormattingRule()
{
return $this->nationalPrefixFormattingRule;
}
/**
* @param string $value
* @return NumberFormat
*/
public function setNationalPrefixFormattingRule($value)
{
$this->hasNationalPrefixFormattingRule = true;
$this->nationalPrefixFormattingRule = (string) $value;
return $this;
}
/**
* @return NumberFormat
*/
public function clearNationalPrefixFormattingRule()
{
$this->nationalPrefixFormattingRule = '';
return $this;
}
/**
* @return boolean
*/
public function hasDomesticCarrierCodeFormattingRule()
{
return $this->hasDomesticCarrierCodeFormattingRule;
}
/**
* @return string
*/
public function getDomesticCarrierCodeFormattingRule()
{
return $this->domesticCarrierCodeFormattingRule;
}
/**
* @param string $value
* @return NumberFormat
*/
public function setDomesticCarrierCodeFormattingRule($value)
{
$this->hasDomesticCarrierCodeFormattingRule = true;
$this->domesticCarrierCodeFormattingRule = (string) $value;
return $this;
}
/**
* @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 = [];
$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;
}
/**
*/
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']) && $input['nationalPrefixFormattingRule'] !== '') {
$this->setNationalPrefixFormattingRule($input['nationalPrefixFormattingRule']);
}
if (isset($input['domesticCarrierCodeFormattingRule']) && $input['domesticCarrierCodeFormattingRule'] !== '') {
$this->setDomesticCarrierCodeFormattingRule($input['domesticCarrierCodeFormattingRule']);
}
if (isset($input['nationalPrefixOptionalWhenFormatting'])) {
$this->setNationalPrefixOptionalWhenFormatting($input['nationalPrefixOptionalWhenFormatting']);
}
}
}

View File

@@ -0,0 +1,59 @@
<?php
namespace libphonenumber;
/**
* Generic exception class for errors encountered when parsing phone numbers.
* @author Lara Rennie
*/
class NumberParseException extends \Exception
{
/**
* The country code supplied did not belong to a supported country or non-geographical entity.
*/
public const INVALID_COUNTRY_CODE = 0;
/**
* This indicates the string passed is not a valid number. Either the string had less than 3
* digits in it or had an invalid phone-context parameter. More specifically, the number failed
* to match the regular expression VALID_PHONE_NUMBER, RFC3966_GLOBAL_NUMBER_DIGITS, or
* RFC3966_DOMAINNAME in PhoneNumberUtil
*/
public 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.
*/
public 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.
*/
public const TOO_SHORT_NSN = 3;
/**
* This indicates the string had more digits than any valid phone number could have.
*/
public 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;
}
}

View File

@@ -0,0 +1,968 @@
<?php
namespace libphonenumber;
/**
* Class PhoneMetadata
* @package libphonenumber
* @internal Used internally, and can change at any time
*/
class PhoneMetadata
{
/**
* @var string
*/
protected $id;
/**
* @var int
*/
protected $countryCode;
protected $leadingDigits;
protected $internationalPrefix;
protected $preferredInternationalPrefix;
protected $nationalPrefixForParsing;
protected $nationalPrefixTransformRule;
protected $nationalPrefix;
protected $preferredExtnPrefix;
protected $mainCountryForCode = false;
protected $mobileNumberPortableRegion = false;
protected $generalDesc;
/**
* @var PhoneNumberDesc
*/
protected $mobile;
protected $premiumRate;
protected $fixedLine;
protected $sameMobileAndFixedLinePattern = false;
protected $numberFormat = [];
protected $tollFree;
protected $sharedCost;
protected $personalNumber;
protected $voip;
protected $pager;
protected $uan;
protected $emergency;
protected $voicemail;
/**
* @var PhoneNumberDesc
*/
protected $short_code;
/**
* @var PhoneNumberDesc
*/
protected $standard_rate;
/**
* @var PhoneNumberDesc
*/
protected $carrierSpecific;
/**
* @var PhoneNumberDesc
*/
protected $smsServices;
/**
* @var PhoneNumberDesc
*/
protected $noInternationalDialling;
/**
* @var NumberFormat[]
*/
protected $intlNumberFormat = [];
/**
* @return boolean
*/
public function hasId()
{
return $this->id !== null;
}
/**
* @return boolean
*/
public function hasCountryCode()
{
return $this->countryCode !== null;
}
public function hasInternationalPrefix()
{
return $this->internationalPrefix !== null;
}
public function hasMainCountryForCode()
{
return $this->mainCountryForCode !== null;
}
public function isMainCountryForCode()
{
return $this->mainCountryForCode;
}
public function getMainCountryForCode()
{
return $this->mainCountryForCode;
}
public function setMainCountryForCode($value)
{
$this->mainCountryForCode = $value;
return $this;
}
public function clearMainCountryForCode()
{
$this->mainCountryForCode = false;
return $this;
}
public function hasMobileNumberPortableRegion()
{
return $this->mobileNumberPortableRegion !== null;
}
public function hasSameMobileAndFixedLinePattern()
{
return $this->sameMobileAndFixedLinePattern !== null;
}
public function numberFormatSize()
{
return \count($this->numberFormat);
}
/**
* @param int $index
* @return NumberFormat
*/
public function getNumberFormat($index)
{
return $this->numberFormat[$index];
}
public function intlNumberFormatSize()
{
return \count($this->intlNumberFormat);
}
public function getIntlNumberFormat($index)
{
return $this->intlNumberFormat[$index];
}
public function clearIntlNumberFormat()
{
$this->intlNumberFormat = [];
return $this;
}
public function toArray()
{
$output = [];
if ($this->hasGeneralDesc()) {
$output['generalDesc'] = $this->getGeneralDesc()->toArray();
}
if ($this->hasFixedLine()) {
$output['fixedLine'] = $this->getFixedLine()->toArray();
}
if ($this->hasMobile()) {
$output['mobile'] = $this->getMobile()->toArray();
}
if ($this->hasTollFree()) {
$output['tollFree'] = $this->getTollFree()->toArray();
}
if ($this->hasPremiumRate()) {
$output['premiumRate'] = $this->getPremiumRate()->toArray();
}
if ($this->hasPremiumRate()) {
$output['premiumRate'] = $this->getPremiumRate()->toArray();
}
if ($this->hasSharedCost()) {
$output['sharedCost'] = $this->getSharedCost()->toArray();
}
if ($this->hasPersonalNumber()) {
$output['personalNumber'] = $this->getPersonalNumber()->toArray();
}
if ($this->hasVoip()) {
$output['voip'] = $this->getVoip()->toArray();
}
if ($this->hasPager()) {
$output['pager'] = $this->getPager()->toArray();
}
if ($this->hasUan()) {
$output['uan'] = $this->getUan()->toArray();
}
if ($this->hasEmergency()) {
$output['emergency'] = $this->getEmergency()->toArray();
}
if ($this->hasVoicemail()) {
$output['voicemail'] = $this->getVoicemail()->toArray();
}
if ($this->hasShortCode()) {
$output['shortCode'] = $this->getShortCode()->toArray();
}
if ($this->hasStandardRate()) {
$output['standardRate'] = $this->getStandardRate()->toArray();
}
if ($this->hasCarrierSpecific()) {
$output['carrierSpecific'] = $this->getCarrierSpecific()->toArray();
}
if ($this->hasSmsServices()) {
$output['smsServices'] = $this->getSmsServices()->toArray();
}
if ($this->hasNoInternationalDialling()) {
$output['noInternationalDialling'] = $this->getNoInternationalDialling()->toArray();
}
$output['id'] = $this->getId();
if ($this->hasCountryCode()) {
$output['countryCode'] = $this->getCountryCode();
}
if ($this->hasInternationalPrefix()) {
$output['internationalPrefix'] = $this->getInternationalPrefix();
}
if ($this->hasPreferredInternationalPrefix()) {
$output['preferredInternationalPrefix'] = $this->getPreferredInternationalPrefix();
}
if ($this->hasNationalPrefix()) {
$output['nationalPrefix'] = $this->getNationalPrefix();
}
if ($this->hasPreferredExtnPrefix()) {
$output['preferredExtnPrefix'] = $this->getPreferredExtnPrefix();
}
if ($this->hasNationalPrefixForParsing()) {
$output['nationalPrefixForParsing'] = $this->getNationalPrefixForParsing();
}
if ($this->hasNationalPrefixTransformRule()) {
$output['nationalPrefixTransformRule'] = $this->getNationalPrefixTransformRule();
}
if ($this->hasSameMobileAndFixedLinePattern()) {
$output['sameMobileAndFixedLinePattern'] = $this->getSameMobileAndFixedLinePattern();
}
$output['numberFormat'] = [];
foreach ($this->numberFormats() as $numberFormat) {
$output['numberFormat'][] = $numberFormat->toArray();
}
$output['intlNumberFormat'] = [];
foreach ($this->intlNumberFormats() as $intlNumberFormat) {
$output['intlNumberFormat'][] = $intlNumberFormat->toArray();
}
$output['mainCountryForCode'] = $this->getMainCountryForCode();
if ($this->hasLeadingDigits()) {
$output['leadingDigits'] = $this->getLeadingDigits();
}
if ($this->hasMobileNumberPortableRegion()) {
$output['mobileNumberPortableRegion'] = $this->isMobileNumberPortableRegion();
}
return $output;
}
public function hasGeneralDesc()
{
return $this->generalDesc !== null;
}
/**
* @return PhoneNumberDesc
*/
public function getGeneralDesc()
{
return $this->generalDesc;
}
public function setGeneralDesc(PhoneNumberDesc $value)
{
$this->generalDesc = $value;
return $this;
}
public function hasFixedLine()
{
return $this->fixedLine !== null;
}
/**
* @return PhoneNumberDesc
*/
public function getFixedLine()
{
return $this->fixedLine;
}
public function setFixedLine(PhoneNumberDesc $value)
{
$this->fixedLine = $value;
return $this;
}
public function hasMobile()
{
return $this->mobile !== null;
}
/**
* @return PhoneNumberDesc
*/
public function getMobile()
{
return $this->mobile;
}
public function setMobile(PhoneNumberDesc $value)
{
$this->mobile = $value;
return $this;
}
public function hasTollFree()
{
return $this->tollFree !== null;
}
/**
* @return PhoneNumberDesc
*/
public function getTollFree()
{
return $this->tollFree;
}
public function setTollFree(PhoneNumberDesc $value)
{
$this->tollFree = $value;
return $this;
}
public function hasPremiumRate()
{
return $this->premiumRate !== null;
}
/**
* @return PhoneNumberDesc
*/
public function getPremiumRate()
{
return $this->premiumRate;
}
public function setPremiumRate(PhoneNumberDesc $value)
{
$this->premiumRate = $value;
return $this;
}
public function hasSharedCost()
{
return $this->sharedCost !== null;
}
/**
* @return PhoneNumberDesc
*/
public function getSharedCost()
{
return $this->sharedCost;
}
public function setSharedCost(PhoneNumberDesc $value)
{
$this->sharedCost = $value;
return $this;
}
public function hasPersonalNumber()
{
return $this->personalNumber !== null;
}
/**
* @return PhoneNumberDesc
*/
public function getPersonalNumber()
{
return $this->personalNumber;
}
public function setPersonalNumber(PhoneNumberDesc $value)
{
$this->personalNumber = $value;
return $this;
}
public function hasVoip()
{
return $this->voip !== null;
}
/**
* @return PhoneNumberDesc
*/
public function getVoip()
{
return $this->voip;
}
public function setVoip(PhoneNumberDesc $value)
{
$this->voip = $value;
return $this;
}
public function hasPager()
{
return $this->pager !== null;
}
/**
* @return PhoneNumberDesc
*/
public function getPager()
{
return $this->pager;
}
public function setPager(PhoneNumberDesc $value)
{
$this->pager = $value;
return $this;
}
public function hasUan()
{
return $this->uan !== null;
}
/**
* @return PhoneNumberDesc
*/
public function getUan()
{
return $this->uan;
}
public function setUan(PhoneNumberDesc $value)
{
$this->uan = $value;
return $this;
}
public function hasEmergency()
{
return $this->emergency !== null;
}
/**
* @return PhoneNumberDesc
*/
public function getEmergency()
{
return $this->emergency;
}
public function setEmergency(PhoneNumberDesc $value)
{
$this->emergency = $value;
return $this;
}
public function hasVoicemail()
{
return $this->voicemail !== null;
}
/**
* @return PhoneNumberDesc
*/
public function getVoicemail()
{
return $this->voicemail;
}
public function setVoicemail(PhoneNumberDesc $value)
{
$this->voicemail = $value;
return $this;
}
public function hasShortCode()
{
return $this->short_code !== null;
}
public function getShortCode()
{
return $this->short_code;
}
public function setShortCode(PhoneNumberDesc $value)
{
$this->short_code = $value;
return $this;
}
public function hasStandardRate()
{
return $this->standard_rate !== null;
}
public function getStandardRate()
{
return $this->standard_rate;
}
public function setStandardRate(PhoneNumberDesc $value)
{
$this->standard_rate = $value;
return $this;
}
public function hasCarrierSpecific()
{
return $this->carrierSpecific !== null;
}
public function getCarrierSpecific()
{
return $this->carrierSpecific;
}
public function setCarrierSpecific(PhoneNumberDesc $value)
{
$this->carrierSpecific = $value;
return $this;
}
public function hasSmsServices()
{
return $this->smsServices !== null;
}
public function getSmsServices()
{
return $this->smsServices;
}
public function setSmsServices(PhoneNumberDesc $value)
{
$this->smsServices = $value;
return $this;
}
public function hasNoInternationalDialling()
{
return $this->noInternationalDialling !== null;
}
public function getNoInternationalDialling()
{
return $this->noInternationalDialling;
}
public function setNoInternationalDialling(PhoneNumberDesc $value)
{
$this->noInternationalDialling = $value;
return $this;
}
/**
* @return string
*/
public function getId()
{
return $this->id;
}
/**
* @param string $value
* @return PhoneMetadata
*/
public function setId($value)
{
$this->id = $value;
return $this;
}
/**
* @return int
*/
public function getCountryCode()
{
return $this->countryCode;
}
/**
* @param int $value
* @return PhoneMetadata
*/
public function setCountryCode($value)
{
$this->countryCode = $value;
return $this;
}
public function getInternationalPrefix()
{
return $this->internationalPrefix;
}
public function setInternationalPrefix($value)
{
$this->internationalPrefix = $value;
return $this;
}
public function hasPreferredInternationalPrefix()
{
return ($this->preferredInternationalPrefix !== null);
}
public function getPreferredInternationalPrefix()
{
return $this->preferredInternationalPrefix;
}
public function setPreferredInternationalPrefix($value)
{
$this->preferredInternationalPrefix = $value;
return $this;
}
public function clearPreferredInternationalPrefix()
{
$this->preferredInternationalPrefix = null;
return $this;
}
public function hasNationalPrefix()
{
return $this->nationalPrefix !== null;
}
public function getNationalPrefix()
{
return $this->nationalPrefix;
}
public function setNationalPrefix($value)
{
$this->nationalPrefix = $value;
return $this;
}
public function clearNationalPrefix()
{
$this->nationalPrefix = '';
return $this;
}
public function hasPreferredExtnPrefix()
{
return $this->preferredExtnPrefix !== null;
}
public function getPreferredExtnPrefix()
{
return $this->preferredExtnPrefix;
}
public function setPreferredExtnPrefix($value)
{
$this->preferredExtnPrefix = $value;
return $this;
}
public function clearPreferredExtnPrefix()
{
$this->preferredExtnPrefix = '';
return $this;
}
public function hasNationalPrefixForParsing()
{
return $this->nationalPrefixForParsing !== null;
}
public function getNationalPrefixForParsing()
{
return $this->nationalPrefixForParsing;
}
public function setNationalPrefixForParsing($value)
{
$this->nationalPrefixForParsing = $value;
return $this;
}
public function hasNationalPrefixTransformRule()
{
return $this->nationalPrefixTransformRule !== null;
}
public function getNationalPrefixTransformRule()
{
return $this->nationalPrefixTransformRule;
}
public function setNationalPrefixTransformRule($value)
{
$this->nationalPrefixTransformRule = $value;
return $this;
}
public function clearNationalPrefixTransformRule()
{
$this->nationalPrefixTransformRule = '';
return $this;
}
public function getSameMobileAndFixedLinePattern()
{
return $this->sameMobileAndFixedLinePattern;
}
public function setSameMobileAndFixedLinePattern($value)
{
$this->sameMobileAndFixedLinePattern = $value;
return $this;
}
public function clearSameMobileAndFixedLinePattern()
{
$this->sameMobileAndFixedLinePattern = false;
return $this;
}
/**
* @return NumberFormat[]
*/
public function numberFormats()
{
return $this->numberFormat;
}
public function intlNumberFormats()
{
return $this->intlNumberFormat;
}
/**
* @return bool
*/
public function hasLeadingDigits()
{
return $this->leadingDigits !== null;
}
public function getLeadingDigits()
{
return $this->leadingDigits;
}
public function setLeadingDigits($value)
{
$this->leadingDigits = $value;
return $this;
}
public function isMobileNumberPortableRegion()
{
return $this->mobileNumberPortableRegion;
}
public function setMobileNumberPortableRegion($value)
{
$this->mobileNumberPortableRegion = $value;
return $this;
}
public function clearMobileNumberPortableRegion()
{
$this->mobileNumberPortableRegion = false;
return $this;
}
/**
* @return PhoneMetadata
*/
public function fromArray(array $input)
{
if (isset($input['generalDesc'])) {
$desc = new PhoneNumberDesc();
$this->setGeneralDesc($desc->fromArray($input['generalDesc']));
}
if (isset($input['fixedLine'])) {
$desc = new PhoneNumberDesc();
$this->setFixedLine($desc->fromArray($input['fixedLine']));
}
if (isset($input['mobile'])) {
$desc = new PhoneNumberDesc();
$this->setMobile($desc->fromArray($input['mobile']));
}
if (isset($input['tollFree'])) {
$desc = new PhoneNumberDesc();
$this->setTollFree($desc->fromArray($input['tollFree']));
}
if (isset($input['premiumRate'])) {
$desc = new PhoneNumberDesc();
$this->setPremiumRate($desc->fromArray($input['premiumRate']));
}
if (isset($input['sharedCost'])) {
$desc = new PhoneNumberDesc();
$this->setSharedCost($desc->fromArray($input['sharedCost']));
}
if (isset($input['personalNumber'])) {
$desc = new PhoneNumberDesc();
$this->setPersonalNumber($desc->fromArray($input['personalNumber']));
}
if (isset($input['voip'])) {
$desc = new PhoneNumberDesc();
$this->setVoip($desc->fromArray($input['voip']));
}
if (isset($input['pager'])) {
$desc = new PhoneNumberDesc();
$this->setPager($desc->fromArray($input['pager']));
}
if (isset($input['uan'])) {
$desc = new PhoneNumberDesc();
$this->setUan($desc->fromArray($input['uan']));
}
if (isset($input['emergency'])) {
$desc = new PhoneNumberDesc();
$this->setEmergency($desc->fromArray($input['emergency']));
}
if (isset($input['voicemail'])) {
$desc = new PhoneNumberDesc();
$this->setVoicemail($desc->fromArray($input['voicemail']));
}
if (isset($input['shortCode'])) {
$desc = new PhoneNumberDesc();
$this->setShortCode($desc->fromArray($input['shortCode']));
}
if (isset($input['standardRate'])) {
$desc = new PhoneNumberDesc();
$this->setStandardRate($desc->fromArray($input['standardRate']));
}
if (isset($input['carrierSpecific'])) {
$desc = new PhoneNumberDesc();
$this->setCarrierSpecific($desc->fromArray($input['carrierSpecific']));
}
if (isset($input['smsServices'])) {
$desc = new PhoneNumberDesc();
$this->setSmsServices($desc->fromArray($input['smsServices']));
}
if (isset($input['noInternationalDialling'])) {
$desc = new PhoneNumberDesc();
$this->setNoInternationalDialling($desc->fromArray($input['noInternationalDialling']));
}
$this->setId($input['id']);
$this->setCountryCode($input['countryCode']);
$this->setInternationalPrefix($input['internationalPrefix']);
if (isset($input['preferredInternationalPrefix'])) {
$this->setPreferredInternationalPrefix($input['preferredInternationalPrefix']);
}
if (isset($input['nationalPrefix'])) {
$this->setNationalPrefix($input['nationalPrefix']);
}
if (isset($input['nationalPrefix'])) {
$this->setNationalPrefix($input['nationalPrefix']);
}
if (isset($input['preferredExtnPrefix'])) {
$this->setPreferredExtnPrefix($input['preferredExtnPrefix']);
}
if (isset($input['nationalPrefixForParsing'])) {
$this->setNationalPrefixForParsing($input['nationalPrefixForParsing']);
}
if (isset($input['nationalPrefixTransformRule'])) {
$this->setNationalPrefixTransformRule($input['nationalPrefixTransformRule']);
}
foreach ($input['numberFormat'] as $numberFormatElt) {
$numberFormat = new NumberFormat();
$numberFormat->fromArray($numberFormatElt);
$this->addNumberFormat($numberFormat);
}
foreach ($input['intlNumberFormat'] as $intlNumberFormatElt) {
$numberFormat = new NumberFormat();
$numberFormat->fromArray($intlNumberFormatElt);
$this->addIntlNumberFormat($numberFormat);
}
$this->setMainCountryForCode($input['mainCountryForCode']);
if (isset($input['leadingDigits'])) {
$this->setLeadingDigits($input['leadingDigits']);
}
if (isset($input['mobileNumberPortableRegion'])) {
$this->setMobileNumberPortableRegion($input['mobileNumberPortableRegion']);
}
return $this;
}
public function addNumberFormat(NumberFormat $value)
{
$this->numberFormat[] = $value;
return $this;
}
public function addIntlNumberFormat(NumberFormat $value)
{
$this->intlNumberFormat[] = $value;
return $this;
}
}

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;
/**
* 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;
/**
* 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;
/**
* 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;
/**
* 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;
/**
* 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;
/**
* 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 $this->countryCode !== null;
}
/**
* 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 $this->nationalNumber !== null;
}
/**
* 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 $this->extension !== null;
}
/**
* 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 $this->italianLeadingZero !== null;
}
/**
* 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 $this->rawInput !== null;
}
/**
* 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 $this->preferredDomesticCarrierCode !== null;
}
/**
* 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)
{
if ($this === $other) {
return true;
}
return $this->countryCode === $other->countryCode
&& $this->nationalNumber === $other->nationalNumber
&& $this->extension === $other->extension
&& $this->italianLeadingZero === $other->italianLeadingZero
&& $this->numberOfLeadingZeros === $other->numberOfLeadingZeros
&& $this->rawInput === $other->rawInput
&& $this->countryCodeSource === $other->countryCodeSource
&& $this->preferredDomesticCarrierCode === $other->preferredDomesticCarrierCode;
}
/**
* 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;
}
/**
*
*/
public function serialize()
{
return serialize($this->__serialize());
}
public function __serialize()
{
return [
$this->countryCode,
$this->nationalNumber,
$this->extension,
$this->italianLeadingZero,
$this->numberOfLeadingZeros,
$this->rawInput,
$this->countryCodeSource,
$this->preferredDomesticCarrierCode,
];
}
/**
*
*/
public function unserialize($serialized)
{
$this->__unserialize(unserialize($serialized));
}
public function __unserialize(array $data)
{
[
$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,235 @@
<?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 = [];
}
/**
* @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 = [];
}
/**
* @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;
}
/**
* @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;
}
/**
* @return boolean
*/
public function exactlySameAs(PhoneNumberDesc $other)
{
return $this->nationalNumberPattern === $other->nationalNumberPattern &&
$this->exampleNumber === $other->exampleNumber;
}
/**
* @return array
*/
public function toArray()
{
$data = [];
if ($this->hasNationalNumberPattern()) {
$data['NationalNumberPattern'] = $this->getNationalNumberPattern();
}
if ($this->hasExampleNumber()) {
$data['ExampleNumber'] = $this->getExampleNumber();
}
$data['PossibleLength'] = $this->getPossibleLength();
$data['PossibleLengthLocalOnly'] = $this->getPossibleLengthLocalOnly();
return $data;
}
/**
* @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
{
public const E164 = 0;
public const INTERNATIONAL = 1;
public const NATIONAL = 2;
public const RFC3966 = 3;
}

View File

@@ -0,0 +1,87 @@
<?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
*/
public function __construct($start, $rawString, PhoneNumber $number)
{
if ($start < 0) {
throw new \InvalidArgumentException('Start index must be >= 0.');
}
if ($rawString === null) {
throw new \InvalidArgumentException('$rawString must be a string');
}
$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,925 @@
<?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 = [];
/**
* 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;
protected static function init()
{
static::$alternateFormatsFilePrefix = __DIR__ . '/data/PhoneNumberAlternateFormats';
static::$innerMatches = [
// 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::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 \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);
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 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 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.
*
* @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));
}
// If a format is provided, 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 string $candidate
* @return bool
*/
public static function checkNumberGroupingIsValid(
PhoneNumber $number,
$candidate,
PhoneNumberUtil $util,
\Closure $checker
) {
$normalizedCandidate = PhoneNumberUtil::normalizeDigits($candidate, true /* keep non-digits */);
$formattedNumberGroups = static::getNationalNumberGroups($util, $number);
if ($checker($util, $number, $normalizedCandidate, $formattedNumberGroups)) {
return true;
}
// If this didn't pass, see if there are any alternative formats that match, and try them instead.
$alternateFormats = static::getAlternateFormatsForCountry($number->getCountryCode());
$nationalSignificantNumber = $util->getNationalSignificantNumber($number);
if ($alternateFormats !== null) {
foreach ($alternateFormats->numberFormats() as $alternateFormat) {
if ($alternateFormat->leadingDigitsPatternSize() > 0) {
// There is only one leading digits pattern for alternate formats.
$pattern = $alternateFormat->getLeadingDigitsPattern(0);
$nationalSignificantNumberMatcher = new Matcher($pattern, $nationalSignificantNumber);
if (!$nationalSignificantNumberMatcher->lookingAt()) {
// Leading digits don't match; try another one.
continue;
}
}
$formattedNumberGroups = static::getNationalNumberGroups($util, $number, $alternateFormat);
if ($checker($util, $number, $normalizedCandidate, $formattedNumberGroups)) {
return true;
}
}
}
return false;
}
/**
* @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 string $candidate
* @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;
}
/**
* @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) && $formatRule->getNationalPrefixFormattingRule() !== '') {
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 = [];
/**
* @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
*/
#[\ReturnTypeWillChange]
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.
*/
#[\ReturnTypeWillChange]
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
*/
#[\ReturnTypeWillChange]
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
*/
#[\ReturnTypeWillChange]
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
*/
#[\ReturnTypeWillChange]
public function rewind()
{
$this->searchIndex = 0;
$this->next();
}
}

View File

@@ -0,0 +1,135 @@
<?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 = [];
/**
* @var PhoneNumberUtil
*/
protected $phoneUtil;
/**
* @var PrefixFileReader
*/
protected $prefixFileReader;
/**
* @param string|null $phonePrefixDataDirectory
*/
protected function __construct($phonePrefixDataDirectory)
{
if ($phonePrefixDataDirectory === null) {
$phonePrefixDataDirectory = __DIR__ . '/carrier/data/';
}
$this->prefixFileReader = new PrefixFileReader($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|null $mappingDir
* @return PhoneNumberToCarrierMapper
*/
public static function getInstance($mappingDir = null)
{
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,143 @@
<?php
/**
* Created by PhpStorm.
* User: giggsey
* Date: 14/10/13
* Time: 16:00
*/
namespace libphonenumber;
use libphonenumber\prefixmapper\PrefixTimeZonesMap;
class PhoneNumberToTimeZonesMapper
{
public const UNKNOWN_TIMEZONE = 'Etc/Unknown';
public const MAPPING_DATA_DIRECTORY = '/timezone/data/';
public const MAPPING_DATA_FILE_NAME = 'map_data.php';
/**
* @var PhoneNumberToTimeZonesMapper
*/
protected static $instance;
protected $unknownTimeZoneList = [];
/**
* @var PhoneNumberUtil
*/
protected $phoneUtil;
protected $prefixTimeZonesMap;
protected function __construct($phonePrefixDataDirectory)
{
$this->prefixTimeZonesMap = static::loadPrefixTimeZonesMapFromFile(
__DIR__ . $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.
*
* @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;
}
if (!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
{
public const FIXED_LINE = 0;
public 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.
public const FIXED_LINE_OR_MOBILE = 2;
// Freephone lines
public const TOLL_FREE = 3;
public 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.
public const SHARED_COST = 5;
// Voice over IP numbers. This includes TSoIP (Telephony Service over IP).
public 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
public const PERSONAL_NUMBER = 7;
public 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.
public const UAN = 9;
// A phone number is of type UNKNOWN when it does not fit any of the known patterns for a
// specific region.
public const UNKNOWN = 10;
// Emergency
public const EMERGENCY = 27;
// Voicemail
public const VOICEMAIL = 28;
// Short Code
public const SHORT_CODE = 29;
// Standard Rate
public const STANDARD_RATE = 30;
public static function values()
{
return [
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,54 @@
<?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 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
* @return bool
*/
private function match($number, $pattern, $allowPrefixMatch)
{
$matcher = new Matcher($pattern, $number);
if (!$matcher->lookingAt()) {
return false;
}
return $matcher->matches() ? true : $allowPrefixMatch;
}
}

View File

@@ -0,0 +1,67 @@
<?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.
* @internal
*/
class RegionCode
{
// Region code for global networks (e.g. +800 numbers).
public const UN001 = '001';
public const AD = 'AD';
public const AE = 'AE';
public const AM = 'AM';
public const AO = 'AO';
public const AQ = 'AQ';
public const AR = 'AR';
public const AU = 'AU';
public const BB = 'BB';
public const BR = 'BR';
public const BS = 'BS';
public const BY = 'BY';
public const CA = 'CA';
public const CH = 'CH';
public const CL = 'CL';
public const CN = 'CN';
public const CO = 'CO';
public const CS = 'CS';
public const CX = 'CX';
public const DE = 'DE';
public const FR = 'FR';
public const GB = 'GB';
public const HU = 'HU';
public const IT = 'IT';
public const JP = 'JP';
public const KR = 'KR';
public const MX = 'MX';
public const NZ = 'NZ';
public const PG = 'PG';
public const PL = 'PL';
public const RE = 'RE';
public const RU = 'RU';
public const SE = 'SE';
public const SG = 'SG';
public const US = 'US';
public const UZ = 'UZ';
public const YT = 'YT';
public const ZW = 'ZW';
// Official code for the unknown region.
public const ZZ = 'ZZ';
}

View File

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

View File

@@ -0,0 +1,654 @@
<?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
{
/**
* @var ShortNumberInfo
*/
protected static $instance;
/**
* @var MatcherAPIInterface
*/
protected $matcherAPI;
protected $currentFilePrefix;
protected $regionToMetadataMap = [];
protected $countryCallingCodeToRegionCodeMap = [];
protected $countryCodeToNonGeographicalMetadataMap = [];
protected static $regionsWhereEmergencyNumbersMustBeExact = [
'BR',
'CL',
'NI',
];
protected function __construct(MatcherAPIInterface $matcherAPI)
{
$this->matcherAPI = $matcherAPI;
// TODO: Create ShortNumberInfo for a given map
$this->countryCallingCodeToRegionCodeMap = CountryCodeToRegionCodeMap::$countryCodeToRegionCodeMap;
$this->currentFilePrefix = __DIR__ . '/data/ShortNumberMetadata';
// 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 the 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) ? [] : $regionCodes;
}
/**
* Helper method to check that the country calling code of the number matches the region it's
* being dialed from.
* @param string $regionDialingFrom
* @return bool
*/
protected function regionDialingFromMatchesNumber(PhoneNumber $number, $regionDialingFrom)
{
if ($regionDialingFrom === null || $regionDialingFrom === '') {
return false;
}
$regionCodes = $this->getRegionCodesForCountryCode($number->getCountryCode());
return in_array(strtoupper($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 '';
}
/**
* @return PhoneMetadata|null
*/
public function getMetadataForRegion($regionCode)
{
$regionCode = strtoupper((string) $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 $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(strtoupper($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.
*
* @return String|null Region Code (or null if none are found)
*/
protected function getRegionCodeForShortNumberFromRegionList(PhoneNumber $number, $regionCodes)
{
if (count($regionCodes) == 0) {
return null;
}
if (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
* @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,260 @@
<?php
/**
* libphonenumber-for-php-lite data file
* This file has been @generated from libphonenumber data
* Do not modify!
* @internal
*/
namespace libphonenumber;
class ShortNumbersRegionCodeSet
{
// A set of all region codes for which data is available.
public static $shortNumbersRegionCodeSet = [
'AC',
'AD',
'AE',
'AF',
'AG',
'AI',
'AL',
'AM',
'AO',
'AR',
'AS',
'AT',
'AU',
'AW',
'AX',
'AZ',
'BA',
'BB',
'BD',
'BE',
'BF',
'BG',
'BH',
'BI',
'BJ',
'BL',
'BM',
'BN',
'BO',
'BQ',
'BR',
'BS',
'BT',
'BW',
'BY',
'BZ',
'CA',
'CC',
'CD',
'CF',
'CG',
'CH',
'CI',
'CK',
'CL',
'CM',
'CN',
'CO',
'CR',
'CU',
'CV',
'CW',
'CX',
'CY',
'CZ',
'DE',
'DJ',
'DK',
'DM',
'DO',
'DZ',
'EC',
'EE',
'EG',
'EH',
'ER',
'ES',
'ET',
'FI',
'FJ',
'FK',
'FM',
'FO',
'FR',
'GA',
'GB',
'GD',
'GE',
'GF',
'GG',
'GH',
'GI',
'GL',
'GM',
'GN',
'GP',
'GR',
'GT',
'GU',
'GW',
'GY',
'HK',
'HN',
'HR',
'HT',
'HU',
'ID',
'IE',
'IL',
'IM',
'IN',
'IQ',
'IR',
'IS',
'IT',
'JE',
'JM',
'JO',
'JP',
'KE',
'KG',
'KH',
'KI',
'KM',
'KN',
'KP',
'KR',
'KW',
'KY',
'KZ',
'LA',
'LB',
'LC',
'LI',
'LK',
'LR',
'LS',
'LT',
'LU',
'LV',
'LY',
'MA',
'MC',
'MD',
'ME',
'MF',
'MG',
'MH',
'MK',
'ML',
'MM',
'MN',
'MO',
'MP',
'MQ',
'MR',
'MS',
'MT',
'MU',
'MV',
'MW',
'MX',
'MY',
'MZ',
'NA',
'NC',
'NE',
'NF',
'NG',
'NI',
'NL',
'NO',
'NP',
'NR',
'NU',
'NZ',
'OM',
'PA',
'PE',
'PF',
'PG',
'PH',
'PK',
'PL',
'PM',
'PR',
'PS',
'PT',
'PW',
'PY',
'QA',
'RE',
'RO',
'RS',
'RU',
'RW',
'SA',
'SB',
'SC',
'SD',
'SE',
'SG',
'SH',
'SI',
'SJ',
'SK',
'SL',
'SM',
'SN',
'SO',
'SR',
'SS',
'ST',
'SV',
'SX',
'SY',
'SZ',
'TC',
'TD',
'TG',
'TH',
'TJ',
'TL',
'TM',
'TN',
'TO',
'TR',
'TT',
'TV',
'TW',
'TZ',
'UA',
'UG',
'US',
'UY',
'UZ',
'VA',
'VC',
'VE',
'VG',
'VI',
'VN',
'VU',
'WF',
'WS',
'XK',
'YE',
'YT',
'ZA',
'ZM',
'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
*/
public const IS_POSSIBLE = 0;
/**
* The number has an invalid country calling code.
*/
public const INVALID_COUNTRY_CODE = 1;
/**
* The number is shorter than all valid numbers for this region.
*/
public const TOO_SHORT = 2;
/**
* The number is longer than all valid numbers for this region.
*/
public 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).
*/
public 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.
*/
public const INVALID_LENGTH = 5;
}

View File

@@ -0,0 +1,261 @@
<?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 [
'ar' =>
[
0 => 965,
],
'be' =>
[
0 => 375,
],
'en' =>
[
0 => 1,
1 => 20,
2 => 211,
3 => 212,
4 => 213,
5 => 216,
6 => 218,
7 => 220,
8 => 221,
9 => 222,
10 => 223,
11 => 224,
12 => 225,
13 => 226,
14 => 227,
15 => 228,
16 => 229,
17 => 230,
18 => 231,
19 => 232,
20 => 233,
21 => 234,
22 => 235,
23 => 236,
24 => 237,
25 => 238,
26 => 239,
27 => 240,
28 => 241,
29 => 242,
30 => 243,
31 => 244,
32 => 245,
33 => 246,
34 => 247,
35 => 248,
36 => 249,
37 => 250,
38 => 251,
39 => 252,
40 => 253,
41 => 254,
42 => 255,
43 => 256,
44 => 257,
45 => 258,
46 => 260,
47 => 261,
48 => 262,
49 => 263,
50 => 264,
51 => 265,
52 => 266,
53 => 267,
54 => 268,
55 => 269,
56 => 27,
57 => 290,
58 => 291,
59 => 297,
60 => 298,
61 => 299,
62 => 30,
63 => 31,
64 => 32,
65 => 33,
66 => 34,
67 => 350,
68 => 351,
69 => 352,
70 => 353,
71 => 354,
72 => 355,
73 => 356,
74 => 357,
75 => 358,
76 => 359,
77 => 36,
78 => 370,
79 => 371,
80 => 372,
81 => 373,
82 => 374,
83 => 375,
84 => 376,
85 => 377,
86 => 378,
87 => 380,
88 => 381,
89 => 382,
90 => 383,
91 => 385,
92 => 386,
93 => 387,
94 => 389,
95 => 39,
96 => 40,
97 => 41,
98 => 420,
99 => 421,
100 => 423,
101 => 43,
102 => 44,
103 => 45,
104 => 46,
105 => 47,
106 => 48,
107 => 49,
108 => 500,
109 => 501,
110 => 502,
111 => 503,
112 => 504,
113 => 505,
114 => 506,
115 => 507,
116 => 508,
117 => 509,
118 => 51,
119 => 53,
120 => 55,
121 => 56,
122 => 57,
123 => 58,
124 => 590,
125 => 591,
126 => 592,
127 => 593,
128 => 594,
129 => 595,
130 => 596,
131 => 597,
132 => 598,
133 => 599,
134 => 60,
135 => 61,
136 => 62,
137 => 63,
138 => 64,
139 => 65,
140 => 66,
141 => 670,
142 => 672,
143 => 673,
144 => 674,
145 => 675,
146 => 676,
147 => 677,
148 => 678,
149 => 679,
150 => 680,
151 => 681,
152 => 682,
153 => 683,
154 => 685,
155 => 686,
156 => 687,
157 => 688,
158 => 689,
159 => 690,
160 => 691,
161 => 692,
162 => 7,
163 => 81,
164 => 82,
165 => 84,
166 => 850,
167 => 852,
168 => 853,
169 => 855,
170 => 856,
171 => 86,
172 => 880,
173 => 881,
174 => 882,
175 => 886,
176 => 90,
177 => 91,
178 => 92,
179 => 93,
180 => 94,
181 => 95,
182 => 960,
183 => 961,
184 => 962,
185 => 963,
186 => 964,
187 => 965,
188 => 966,
189 => 967,
190 => 968,
191 => 970,
192 => 971,
193 => 972,
194 => 973,
195 => 974,
196 => 975,
197 => 976,
198 => 977,
199 => 98,
200 => 992,
201 => 993,
202 => 994,
203 => 995,
204 => 996,
205 => 998,
],
'fa' =>
[
0 => 93,
1 => 98,
],
'ko' =>
[
0 => 82,
],
'ru' =>
[
0 => 374,
1 => 375,
2 => 7,
],
'uk' =>
[
0 => 380,
],
'zh' =>
[
0 => 852,
1 => 86,
],
'zh_Hant' =>
[
0 => 852,
1 => 86,
],
];

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 [
9655 => 'فيفا',
9656 => 'أوريدو',
9659 => 'زين',
];

View File

@@ -0,0 +1,22 @@
<?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 [
37525 => 'БеСТ',
375292 => 'МТС',
375294 => 'БелСел',
375295 => 'МТС',
375297 => 'МТС',
375298 => 'МТС',
37533 => 'МТС',
];

View File

@@ -0,0 +1,695 @@
<?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 [
1242357 => 'BaTelCo',
1242359 => 'BaTelCo',
1242375 => 'BaTelCo',
1242376 => 'BaTelCo',
1242395 => 'BaTelCo',
124242 => 'BaTelCo',
124243 => 'BaTelCo',
124244 => 'BaTelCo',
124245 => 'BaTelCo',
1242462 => 'BaTelCo',
1242463 => 'BaTelCo',
1242464 => 'BaTelCo',
1242465 => 'BaTelCo',
1242466 => 'BaTelCo',
1242467 => 'BaTelCo',
1242468 => 'BaTelCo',
124247 => 'BaTelCo',
124248 => 'BaTelCo',
124252 => 'BaTelCo',
124253 => 'BaTelCo',
124254 => 'BaTelCo',
124255 => 'BaTelCo',
124256 => 'BaTelCo',
124257 => 'BaTelCo',
124263 => 'BaTelCo',
1242646 => 'BaTelCo',
124272 => 'BaTelCo',
124273 => 'aliv',
12428 => 'aliv',
124623 => 'Cable & Wireless',
124624 => 'Cable & Wireless',
124625 => 'Cable & Wireless',
1246256 => 'Digicel',
1246257 => 'Digicel',
1246258 => 'Digicel',
1246259 => 'Digicel',
124626 => 'Digicel',
124628 => 'Cable & Wireless',
124635 => 'Cable & Wireless',
1246360 => 'Cable & Wireless',
1246361 => 'Cable & Wireless',
1246362 => 'Cable & Wireless',
1246363 => 'Cable & Wireless',
1246364 => 'Cable & Wireless',
1246365 => 'Cable & Wireless',
1246366 => 'Cable & Wireless',
1246446 => 'Neptune Communications',
124645 => 'Sunbeach Communications',
12465211 => 'Digicel',
12465214 => 'LIME',
12465217 => 'KW Telecommunications',
1246522 => 'Ozone',
124669 => 'Ozone',
12468 => 'Digicel',
1264469 => 'Cable & Wireless',
126453 => 'Weblinks Limited',
126458 => 'Digicel',
1264729 => 'Cable & Wireless',
126477 => 'Cable & Wireless',
126871 => 'Digicel',
1268720 => 'Digicel',
1268721 => 'Digicel',
1268722 => 'Digicel',
1268724 => 'Digicel',
1268725 => 'Digicel',
1268726 => 'Digicel',
1268727 => 'APUA',
1268729 => 'APUA',
1268730 => 'APUA',
1268732 => 'Digicel',
1268734 => 'Digicel',
1268736 => 'Digicel',
1268773 => 'APUA',
1268774 => 'APUA',
1268775 => 'APUA',
1268780 => 'APUA',
1268781 => 'APUA',
1268783 => 'Digicel',
1268785 => 'Digicel',
1268787 => 'Cable & Wireless',
1268788 => 'Digicel',
128424 => 'Cable & Wireless',
1284300 => 'Digicel',
128434 => 'Digicel',
128436 => 'Digicel',
128439 => 'Digicel',
128444 => 'CCT',
12844689 => 'CCT',
1284496 => 'CCT',
1284499 => 'CCT',
1284546 => 'Cable & Wireless',
128456 => 'Cable & Wireless',
128459 => 'Cable & Wireless',
1340423 => 'Vitelcom Cellular',
134044 => 'GIGSKY Mobile',
1340725 => 'Vitelcom Cellular',
134532 => 'Digicel',
134542 => 'Digicel',
134551 => 'Digicel',
134552 => 'Digicel',
134554 => 'Digicel',
134555 => 'Digicel',
1345649 => 'Digicel',
134582 => 'Logic Communications',
1345919 => 'Cable & Wireless',
1345930 => 'LIME',
1345936 => 'Cable & Wireless',
1345937 => 'Cable & Wireless',
1345938 => 'Cable & Wireless',
1345939 => 'Cable & Wireless',
134599 => 'Cable & Wireless',
14412 => 'Cellular One',
14413 => 'Mobility',
144150 => 'Digicel Bermuda',
144151 => 'Digicel Bermuda',
144152 => 'Digicel Bermuda',
144153 => 'Digicel Bermuda',
144159 => 'Digicel Bermuda',
14417 => 'Cellular One',
14418 => 'Cellular One',
144190 => 'Paradise Mobile',
144192 => 'Deltronics',
1473402 => 'Affordable Island Communications',
147341 => 'Digicel Grenada',
147342 => 'Digicel Grenada',
1473449 => 'C&W',
1473456 => 'C&W',
147352 => 'Affordable Island Communications',
147353 => 'AWS Grenada',
147390 => 'Affordable Island Communications',
164923 => 'C&W',
164924 => 'Cable & Wireless',
16493 => 'Digicel',
164943 => 'Islandcom',
1658295 => 'Cable & Wireless',
1659200 => 'Onvoy',
1659222 => 'Onvoy',
1659300 => 'Onvoy',
1659400 => 'Onvoy',
1659444 => 'Onvoy',
1659500 => 'Onvoy',
1659529 => 'Fractel',
1659600 => 'Onvoy',
1659666 => 'Onvoy',
1659766 => 'Fractel',
1659777 => 'Onvoy',
1659800 => 'Onvoy',
1659888 => 'Fractel',
1659900 => 'Onvoy',
1659999 => 'Onvoy',
166434 => 'Cable & Wireless',
166439 => 'Digicel',
1670284 => 'PTI PACIFICA',
1671480 => 'GTA',
1671482 => 'GTA',
1671483 => 'GTA',
1671485 => 'GTA',
1671486 => 'GTA',
1671487 => 'GTA',
1671488 => 'GTA',
1671489 => 'GTA',
167174 => 'PTI PACIFICA',
167183 => 'i CAN_GSM',
167184 => 'i CAN_GSM',
167185 => 'i CAN_GSM',
1671864 => 'GTA',
1671867 => 'GTA',
1671868 => 'Choice Phone',
167187 => 'Choice Phone',
167188 => 'Choice Phone',
167189 => 'Choice Phone',
168424 => 'ASTCA',
168425 => 'Blue Sky',
168427 => 'Blue Sky',
16847 => 'ASTCA',
175828 => 'Cable & Wireless',
17583 => '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 => 'Digicel',
175852 => 'Digicel',
175858 => 'Cable & Wireless',
175871 => 'Digicel',
175872 => 'Digicel',
175873 => 'Digicel',
17588 => 'Digicel',
176722 => 'Cable & Wireless',
176723 => 'Cable & Wireless',
176724 => 'Cable & Wireless',
1767265 => 'Cable & Wireless',
176727 => 'Cable & Wireless',
176728 => 'Cable & Wireless',
176729 => 'Cable & Wireless',
17673 => 'Digicel',
17676 => 'Digicel',
1767704 => 'Digicel',
1767705 => 'Digicel',
1767706 => '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',
178452 => 'Digicel',
178453 => 'Digicel',
178472 => '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',
18093 => 'Claro',
180930 => 'Viva',
180931 => 'Tricom',
180932 => 'Tricom',
180934 => 'Tricom',
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',
18098 => 'Orange',
180981 => 'Viva',
180982 => 'Claro',
180983 => 'Claro',
180987 => 'Tricom',
180991 => 'Orange',
180992 => 'Tricom',
180993 => 'Tricom',
180994 => 'Tricom',
180995 => 'Claro',
180997 => 'Orange',
180998 => 'Orange',
180999 => 'Tricom',
186825 => 'Digicel',
186826 => 'Digicel',
186827 => 'bmobile',
186828 => 'bmobile',
186829 => 'bmobile',
18683 => 'Digicel',
186843 => 'Digicel',
186846 => 'bmobile',
186847 => 'bmobile',
186848 => 'bmobile',
186849 => 'bmobile',
1868620 => 'bmobile',
1868678 => 'bmobile',
186868 => 'bmobile',
18687 => 'bmobile',
186948 => 'Cable & Wireless',
186955 => 'CariGlobe 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',
187620 => 'Cable & Wireless',
1876210 => 'Cable & Wireless',
187622 => 'Cable & Wireless',
187623 => 'Cable & Wireless',
187624 => 'Digicel',
187625 => 'Digicel',
187626 => 'Digicel',
1876275 => 'Digicel',
1876276 => 'Digicel',
1876277 => 'Digicel',
1876278 => 'Digicel',
1876279 => 'Digicel',
187628 => 'Digicel',
187629 => 'Digicel',
187630 => 'Digicel',
1876310 => 'Cable & Wireless',
1876312 => 'Cable & Wireless',
1876313 => 'Cable & Wireless',
1876314 => 'Cable & Wireless',
1876315 => 'Cable & Wireless',
1876316 => 'Cable & Wireless',
1876317 => 'Cable & Wireless',
1876318 => 'Cable & Wireless',
1876319 => 'Cable & Wireless',
187632 => 'Cable & Wireless',
187633 => 'Cable & Wireless',
187634 => 'Cable & Wireless',
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',
187650 => 'Digicel',
1876501 => 'Cable & Wireless',
1876502 => 'C&W',
187651 => 'C&W',
1876515 => 'Cable & Wireless',
1876517 => 'Cable & Wireless',
1876519 => 'Cable & Wireless',
187652 => 'Digicel',
187653 => 'Cable & Wireless',
187654 => 'Cable & Wireless',
1876550 => 'Digicel',
1876551 => 'Digicel',
1876552 => 'Digicel',
1876553 => 'Digicel',
1876554 => 'Digicel',
1876556 => 'Digicel',
1876557 => 'Digicel',
1876558 => 'Digicel',
1876559 => 'Digicel',
187656 => 'Digicel',
1876563 => 'C&W',
187657 => 'Digicel',
187658 => 'Digicel',
187659 => 'Digicel',
1876648 => 'Digicel',
1876649 => 'Digicel',
1876666 => 'Digicel',
1876667 => 'Digicel',
1876700 => 'Cable & Wireless',
1876707 => 'Cable & Wireless',
187677 => 'Cable & Wireless',
1876781 => 'Cable & Wireless',
1876782 => 'Cable & Wireless',
1876783 => 'Cable & Wireless',
1876784 => 'Cable & Wireless',
1876787 => 'Cable & Wireless',
1876788 => 'Cable & Wireless',
1876789 => 'Cable & Wireless',
1876790 => 'Cable & Wireless',
1876791 => 'Cable & Wireless',
1876792 => 'Cable & Wireless',
1876793 => 'Cable & Wireless',
1876796 => 'Cable & Wireless',
1876797 => 'Cable & Wireless',
1876798 => 'Cable & Wireless',
1876799 => 'Cable & Wireless',
187680 => 'Cable & Wireless',
1876810 => 'Cable & Wireless',
1876812 => 'Cable & Wireless',
1876813 => 'Cable & Wireless',
1876814 => 'Cable & Wireless',
1876815 => 'Cable & Wireless',
1876816 => 'Cable & Wireless',
1876817 => 'Cable & Wireless',
1876818 => 'Cable & Wireless',
1876819 => 'Cable & Wireless',
187682 => 'Cable & Wireless',
187683 => 'Cable & Wireless',
187684 => 'Digicel',
187685 => 'Digicel',
187686 => 'Digicel',
187687 => 'Digicel',
187688 => 'Digicel',
187689 => 'Digicel',
1876909 => 'Cable & Wireless',
1876919 => 'Cable & Wireless',
1876990 => 'Cable & Wireless',
1876995 => 'Cable & Wireless',
1876997 => 'Cable & Wireless',
1876999 => 'Cable & Wireless',
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',
193925 => 'Claro',
1939252 => 'CENTENNIAL',
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,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 [
2010 => 'Vodafone',
2011 => 'Etisalat',
2012 => 'Orange',
2015 => 'TE',
];

View File

@@ -0,0 +1,22 @@
<?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 [
21112 => 'Sudatel Group',
21191 => 'Zain',
21192 => 'MTN',
21195 => 'Network of the World',
21197 => 'Gemtel',
21198 => 'Digitel',
21199 => 'MTN',
];

View File

@@ -0,0 +1,93 @@
<?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 [
21260 => 'Inwi',
21261 => 'Maroc Telecom',
212612 => 'Orange',
212614 => 'Orange',
212617 => 'Orange',
212619 => 'Orange',
212620 => 'Orange',
212621 => 'Orange',
212622 => 'Maroc Telecom',
212623 => 'Maroc Telecom',
212624 => 'Maroc Telecom',
212625 => 'Orange',
212626 => 'Inwi',
212627 => 'Inwi',
212628 => 'Maroc Telecom',
212629 => 'Inwi',
212630 => 'Inwi',
212631 => 'Orange',
212632 => 'Orange',
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 => 'Orange',
212645 => 'Orange',
212646 => 'Inwi',
212647 => 'Inwi',
212648 => 'Maroc Telecom',
212649 => 'Orange',
21265 => 'Maroc Telecom',
212656 => 'Orange',
212657 => 'Orange',
212660 => 'Orange',
212661 => 'Maroc Telecom',
212662 => 'Maroc Telecom',
212663 => 'Orange',
212664 => 'Orange',
212665 => 'Orange',
212666 => 'Maroc Telecom',
212667 => 'Maroc Telecom',
212668 => 'Maroc Telecom',
212669 => 'Orange',
21267 => 'Maroc Telecom',
212674 => 'Orange',
212675 => 'Orange',
212679 => 'Orange',
212680 => 'Inwi',
212681 => 'Inwi',
212682 => 'Maroc Telecom',
212684 => 'Orange',
212687 => 'Inwi',
212688 => 'Orange',
212689 => 'Maroc Telecom',
212690 => 'Inwi',
212691 => 'Orange',
2126921 => 'Al Hourria Telecom',
2126922 => 'Al Hourria Telecom',
212693 => 'Orange',
212694 => 'Orange',
212695 => 'Inwi',
212696 => 'Maroc Telecom',
212697 => 'Maroc Telecom',
212698 => 'Inwi',
212699 => 'Inwi',
21270 => 'Inwi',
21271 => 'Inwi',
21272 => 'Inwi',
21275 => 'Maroc Telecom',
21276 => 'Maroc Telecom',
21277 => 'Orange',
21278 => 'Orange',
];

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 [
2135 => 'Ooredoo',
2136 => 'Mobilis',
2137 => 'Djezzy',
];

View File

@@ -0,0 +1,22 @@
<?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 [
2162 => 'Ooredoo',
2164 => 'Tunisie Telecom',
21645 => 'Watany Ettisalat',
21646 => 'Ooredoo',
21648 => 'Ooredoo',
2165 => 'Orange',
2169 => 'Tunisie Telecom',
];

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 [
21891 => 'Al-Madar',
21892 => 'Libyana',
21893 => 'Al-Madar',
21894 => 'Libyana',
21895 => 'Libya Telecom & Technology',
21896 => 'Libya Telecom & Technology',
];

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 [
2202 => 'Africell',
2203 => 'QCell',
22040 => 'Africell',
22041 => 'Africell',
22045 => 'Africell',
22050 => 'QCell',
22051 => 'QCell',
22052 => 'QCell',
22053 => 'QCell',
22054 => 'QCell',
22058 => 'QCell',
22059 => 'QCell',
2206 => 'Comium',
2207 => 'Africell',
2209 => 'Gamcel',
];

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 [
22170 => 'Expresso',
22171 => 'Orange',
22172 => 'HAYO',
22175 => 'Promobile',
2217536 => 'Orange',
221757 => 'Origines',
2217585 => 'Orange',
22176 => 'Free',
22177 => 'Orange',
22178 => 'Orange',
22179 => 'ADIE',
];

View File

@@ -0,0 +1,42 @@
<?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 [
22220 => 'Chinguitel',
22221 => 'Chinguitel',
22222 => 'Chinguitel',
22223 => 'Chinguitel',
22224 => 'Chinguitel',
22226 => 'Chinguitel',
22227 => 'Chinguitel',
22228 => 'Chinguitel',
22229 => 'Chinguitel',
22230 => 'Mattel',
22231 => 'Mattel',
22232 => 'Mattel',
22233 => 'Mattel',
22234 => 'Mattel',
22236 => 'Mattel',
22237 => 'Mattel',
22238 => 'Mattel',
22239 => 'Mattel',
22240 => 'Mauritel',
22241 => 'Mauritel',
22242 => 'Mauritel',
22243 => 'Mauritel',
22244 => 'Mauritel',
22246 => 'Mauritel',
22247 => 'Mauritel',
22248 => 'Mauritel',
22249 => 'Mauritel',
];

View File

@@ -0,0 +1,36 @@
<?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 [
223200 => 'Orange',
2232079 => 'Sotelma',
223217 => 'Sotelma',
2235 => 'Atel',
2236 => 'Sotelma',
2237 => 'Orange',
22382 => 'Orange',
22383 => 'Orange',
22384 => 'Orange',
22385 => '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,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 [
22460 => 'Sotelgui',
22461 => 'Orange',
22462 => 'Orange',
22463 => 'Intercel',
22465 => 'Cellcom',
22466 => 'Areeba',
];

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 [
22501 => 'Moov',
22505 => 'MTN',
22507 => 'Orange',
];

View File

@@ -0,0 +1,51 @@
<?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 [
22601 => 'Onatel',
22602 => 'Onatel',
22603 => 'Onatel',
22604 => 'Orange',
22605 => 'Orange',
22606 => 'Orange',
22607 => 'Orange',
22650 => 'Onatel',
22651 => 'Onatel',
22652 => 'Onatel',
22653 => 'Onatel',
22654 => 'Orange',
22655 => 'Orange',
22656 => 'Orange',
22657 => 'Orange',
22658 => 'Telecel Faso',
22660 => 'Onatel',
22661 => 'Onatel',
22662 => 'Onatel',
22663 => 'Onatel',
22664 => 'Orange',
22665 => 'Orange',
22666 => 'Orange',
22667 => 'Orange',
22668 => 'Telecel Faso',
22669 => 'Telecel Faso',
22670 => 'Onatel',
22671 => 'Onatel',
22672 => 'Onatel',
22673 => 'Onatel',
22674 => 'Orange',
22675 => 'Orange',
22676 => 'Orange',
22677 => 'Orange',
22678 => 'Telecel Faso',
22679 => 'Telecel Faso',
];

View File

@@ -0,0 +1,39 @@
<?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 [
22723 => 'Orange',
22770 => 'Orange',
22774 => 'Moov',
22777 => 'Airtel',
22780 => 'Orange',
22781 => 'Orange',
22782 => 'Orange',
22783 => 'Niger Telecoms',
22784 => 'Moov',
22785 => 'Moov',
22786 => 'Airtel',
22787 => 'Airtel',
22788 => 'Airtel',
22789 => 'Airtel',
22790 => 'Orange',
22791 => 'Orange',
22792 => 'Orange',
22793 => 'Niger Telecoms',
22794 => 'Moov',
22795 => 'Moov',
22796 => 'Airtel',
22797 => 'Airtel',
22798 => 'Airtel',
22799 => 'Airtel',
];

View File

@@ -0,0 +1,27 @@
<?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 [
22870 => 'Togo Telecom',
22871 => 'Togo Telecom',
22872 => 'Togo Telecom',
22879 => 'Moov',
22890 => 'Togo Telecom',
22891 => 'Togo Telecom',
22892 => 'Togo Telecom',
22893 => 'Togo Telecom',
22896 => 'Moov',
22897 => 'TOGOCEL',
22898 => 'Moov',
22899 => 'Moov',
];

View File

@@ -0,0 +1,64 @@
<?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 [
229014 => 'SBIN',
2290142 => 'MTN',
2290145 => 'Moov',
2290146 => 'MTN',
229015 => 'MTN',
2290155 => 'Moov',
2290158 => 'Moov',
2290160 => 'Moov',
2290161 => 'MTN',
2290162 => 'MTN',
2290163 => 'Moov',
2290164 => 'Moov',
2290165 => 'Moov',
2290166 => 'MTN',
2290167 => 'MTN',
2290168 => 'Moov',
2290169 => 'MTN',
2290190 => 'MTN',
2290191 => 'MTN',
2290194 => 'Moov',
2290195 => 'Moov',
2290196 => 'MTN',
2290197 => 'MTN',
2290198 => 'Moov',
2290199 => 'Moov',
2294 => 'Celtiis',
22942 => 'MTN',
22946 => 'MTN',
2295 => 'MTN',
22955 => 'Moov',
22960 => 'Moov',
22961 => 'MTN',
22962 => 'MTN',
22963 => 'Moov',
22964 => 'Moov',
22965 => 'Moov',
22966 => 'MTN',
22967 => 'MTN',
22968 => 'Moov',
22969 => 'MTN',
22990 => 'MTN',
22991 => 'MTN',
22993 => 'BLK',
22994 => 'Moov',
22995 => 'Moov',
22996 => 'MTN',
22997 => 'MTN',
22998 => 'Moov',
22999 => 'Moov',
];

View File

@@ -0,0 +1,62 @@
<?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 [
230525 => 'Cellplus',
230526 => 'Cellplus',
230527 => 'MTML',
230528 => 'MTML',
230529 => 'MTML',
23054 => 'Emtel',
2305471 => 'Cellplus',
23055 => 'Emtel',
230550 => 'Cellplus',
230552 => 'MTML',
230553 => 'Cellplus',
23057 => 'Cellplus',
230571 => 'Emtel',
230572 => 'Emtel',
230573 => 'Emtel',
230574 => 'Emtel',
230580 => 'Cellplus',
230581 => 'Cellplus',
230582 => 'Cellplus',
230583 => 'Cellplus',
230584 => 'Emtel',
230585 => 'Emtel',
230586 => 'MTML',
2305871 => 'MTML',
2305875 => 'Cellplus',
2305876 => 'Cellplus',
2305877 => 'Cellplus',
2305878 => 'Cellplus',
230588 => 'MTML',
230589 => 'MTML',
230590 => 'Cellplus',
230591 => 'Cellplus',
230592 => 'Cellplus',
230593 => 'Emtel',
230594 => 'Cellplus',
230595 => 'MTML',
230596 => 'MTML',
230597 => 'Emtel',
230598 => 'Emtel',
230700 => 'Cellplus',
230701 => 'Emtel',
230702 => 'MTML',
230703 => 'Emtel',
230704 => 'Emtel',
230730 => 'Emtel',
230731 => 'MTML',
230733 => 'Cellplus',
];

View File

@@ -0,0 +1,22 @@
<?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 [
231220 => 'Liberia Telecom',
231330 => 'West Africa Telecom',
23142 => 'Connect',
231555 => 'Lonestar Cell',
2316 => 'Lonestar Cell',
2317 => 'Orange',
2318 => 'Lonestar Cell',
];

View File

@@ -0,0 +1,27 @@
<?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 [
23225 => 'Sierratel',
23230 => 'Africell',
23231 => 'QCELL',
23232 => 'QCELL',
23233 => 'Africell',
23234 => 'QCELL',
23235 => 'IPTEL',
2326 => 'Onlime',
2327 => 'Orange',
23277 => 'Africell',
2328 => 'Africell',
2329 => 'Africell',
];

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 [
23320 => 'Vodafone',
23323 => 'airteltiGO',
23324 => 'MTN',
23325 => 'MTN',
23326 => 'airteltiGO',
23327 => 'airteltiGO',
23328 => 'Expresso',
23329 => 'National Security',
23350 => 'Vodafone',
23353 => 'MTN',
23354 => 'MTN',
23355 => 'MTN',
23356 => 'airteltiGO',
23357 => 'airteltiGO',
23359 => 'MTN',
];

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 [
234701 => 'Airtel',
2347020 => 'Smile',
2347021 => 'Ntel',
2347022 => 'Ntel',
2347024 => 'Prestel',
2347025 => 'MTN',
2347026 => 'MTN',
2347027 => 'Multilinks',
2347028 => 'Starcomms',
2347029 => 'Starcomms',
234703 => 'MTN',
234704 => 'MTN',
234705 => 'Glo',
234706 => 'MTN',
234707 => 'MTN',
234708 => 'Airtel',
234709 => 'Multilinks',
234801 => 'MAFAB',
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',
234819 => 'Starcomms',
234901 => 'Airtel',
234902 => 'Airtel',
234903 => 'MTN',
234904 => 'Airtel',
234905 => 'Glo',
234906 => 'MTN',
234907 => 'Airtel',
234908 => '9mobile',
234909 => '9mobile',
234911 => 'Airtel',
234912 => 'Airtel',
234913 => 'MTN',
234915 => 'Glo',
234916 => 'MTN',
];

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 [
2356 => 'Airtel',
2357 => 'Sotel',
2358 => 'Airtel',
2359 => 'Tigo',
];

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 [
23670 => 'A-Cell',
23672 => 'Orange',
23674 => 'Orange',
23675 => 'Telecel',
23676 => 'Telecel',
23677 => 'Nationlink',
];

View File

@@ -0,0 +1,40 @@
<?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 [
23762 => 'Camtel',
23764 => 'Orange',
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',
237680 => 'MTN Cameroon',
237681 => 'MTN Cameroon',
237682 => 'MTN Cameroon',
237683 => 'MTN Cameroon',
237684 => 'NEXTTEL',
237685 => 'NEXTTEL',
237686 => 'Orange',
237687 => 'Orange',
237688 => 'Orange',
237689 => 'Orange',
23769 => 'Orange',
];

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 [
23836 => '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,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 [
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 [
2402 => 'GETESA',
2405 => 'Muni',
];

View File

@@ -0,0 +1,33 @@
<?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 [
24104 => 'Airtel',
24105 => 'Moov',
24106 => 'Libertis',
24107 => 'Airtel',
24120 => 'Libertis',
24121 => 'Libertis',
24122 => 'Libertis',
24123 => 'Libertis',
24124 => 'Libertis',
24125 => 'Libertis',
24126 => 'Libertis',
24127 => 'Libertis',
2413 => 'Libertis',
2414 => 'Airtel',
2415 => 'Moov',
2416 => 'Libertis',
24165 => 'Moov',
2417 => 'Airtel',
];

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 [
24201 => 'Equateur Telecom',
24202 => 'Congo telecom',
24204 => 'Warid',
24205 => 'Airtel',
24206 => 'MTN',
];

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 [
24380 => 'Orange',
24381 => 'Vodacom',
24382 => 'Vodacom',
24383 => 'Vodacom',
24384 => 'Orange',
24385 => 'Orange',
24386 => 'Vodacom',
24388 => 'Yozma Timeturns sprl -YTT',
24389 => 'Orange',
24390 => 'Africell',
24391 => 'Africell',
24397 => 'Airtel',
24398 => 'Airtel',
24399 => 'Airtel',
];

View File

@@ -0,0 +1,23 @@
<?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 [
24491 => 'Movicel',
24492 => 'UNITEL',
24493 => 'UNITEL',
24494 => 'UNITEL',
24495 => 'Africell',
24496 => 'Africell',
24497 => 'UNITEL',
24499 => 'Movicel',
];

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 [
24595 => 'Orange',
24596 => 'Spacetel',
24597 => 'Guinetel',
];

View File

@@ -0,0 +1,16 @@
<?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 [
24638 => 'Sure Ltd',
];

View File

@@ -0,0 +1,22 @@
<?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 [
24741 => 'Sure South Atlantic',
24742 => 'Sure South Atlantic',
24743 => 'Sure South Atlantic',
24745 => 'Sure South Atlantic',
24746 => 'Sure South Atlantic',
24747 => 'Sure South Atlantic',
24748 => 'Sure South Atlantic',
];

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 [
24821 => 'Intelvision',
24822 => 'Intelvision',
24825 => 'CWS',
24826 => 'CWS',
24827 => 'Airtel',
24828 => 'Airtel',
];

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 [
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,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 [
25072 => 'TIGO',
25073 => 'Airtel',
25077 => 'KtRN',
25078 => 'MTN',
25079 => '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 [
2517 => 'Safaricom',
2519 => 'Ethio Telecom',
];

View File

@@ -0,0 +1,40 @@
<?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 [
25224 => 'Telesom',
25228 => 'Nationlink',
25235 => 'AirSom',
25239 => 'AirSom',
25248 => 'AirSom',
25249 => 'AirSom',
25260 => 'Golis Telecom',
25261 => 'Hormuud',
25262 => 'Somtel',
25263 => 'Telesom',
25264 => 'Somali Networks',
25265 => 'Somtel',
25266 => 'Somtel',
25267 => 'Nationlink',
25268 => 'SomNet',
25269 => 'Nationlink',
25270 => 'Golis Telecom',
25271 => 'Amtel',
25272 => 'Golis Telecom',
25276 => 'Somtel',
25279 => 'Somtel',
25280 => 'Somali Networks',
25288 => 'Somali Networks',
2529 => 'STG',
25290 => 'Golis Telecom',
];

View File

@@ -0,0 +1,16 @@
<?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 [
2537 => 'Evatis',
];

View File

@@ -0,0 +1,45 @@
<?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 [
25410 => 'Airtel',
25411 => 'Safaricom',
254120 => 'Telkom',
254121 => 'Infura',
254124 => 'Finserve',
25413 => 'NRG Media Limited',
25470 => 'Safaricom',
25471 => 'Safaricom',
25472 => 'Safaricom',
25473 => 'Airtel',
25474 => 'Safaricom',
254744 => 'Homeland Media',
254747 => 'JTL',
25475 => 'Airtel',
254757 => 'Safaricom',
254758 => 'Safaricom',
254759 => 'Safaricom',
254760 => 'Mobile Pay',
254761 => 'Airtel',
254762 => 'Airtel',
254763 => 'Finserve',
254764 => 'Finserve',
254765 => 'Finserve',
254766 => 'Finserve',
254767 => 'Sema Mobile',
254768 => 'Safaricom',
254769 => 'Safaricom',
25477 => 'Telkom',
25478 => 'Airtel',
25479 => 'Safaricom',
];

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 [
25561 => 'Viettel',
25562 => 'Viettel',
25565 => 'tiGO',
25566 => 'SMILE',
25567 => 'tiGO',
25568 => 'Airtel',
25569 => 'Airtel',
25571 => 'tiGO',
25573 => 'Tanzania Telecom',
25574 => 'Vodacom',
25575 => 'Vodacom',
25576 => 'Vodacom',
25577 => 'tiGO',
25578 => 'Airtel',
25579 => 'Vodacom',
];

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 [
25670 => 'Airtel',
25671 => 'UTL',
256720 => 'Smile',
256724 => 'Hamilton Telecom',
256726 => 'Tangerine',
256727 => 'Tangerine',
256728 => 'Talkio',
25673 => 'Hamilton Telecom',
25674 => 'Airtel',
25675 => 'Airtel',
25676 => 'MTN',
25677 => 'MTN',
25678 => 'MTN',
25679 => 'Africell',
];

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 [
25729 => 'Leo',
2576 => 'Viettel',
25771 => 'Leo',
25772 => 'Leo',
25775 => 'Smart Mobile',
25776 => 'Leo',
25777 => 'Onatel',
25778 => 'Smart Mobile',
25779 => 'Leo',
];

View File

@@ -0,0 +1,22 @@
<?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 [
25882 => 'mcel',
25883 => 'mcel',
25884 => 'Vodacom',
25885 => 'Vodacom',
25886 => 'Movitel',
25887 => 'Movitel',
25889 => 'GMPCS',
];

View File

@@ -0,0 +1,22 @@
<?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 [
26075 => 'ZAMTEL',
26076 => 'MTN',
26077 => 'Airtel',
26095 => 'ZAMTEL',
26096 => 'MTN',
26097 => 'Airtel',
26098 => 'Beeline Telecoms',
];

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 [
26132 => 'Orange',
26133 => 'Airtel',
26134 => 'Telma',
26137 => 'Orange',
26138 => 'Telma',
26139 => 'Blueline',
];

View File

@@ -0,0 +1,129 @@
<?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 [
26263900 => 'Orange',
26263901 => 'Orange',
26263902 => 'Orange',
26263903 => 'Telco OI',
26263904 => 'Telco OI',
26263905 => 'Telco OI',
26263906 => 'Telco OI',
26263907 => 'Telco OI',
26263909 => 'SFR',
26263910 => 'SFR',
26263911 => 'SFR',
26263919 => 'Telco OI',
2626392 => 'SFR',
26263926 => 'Telco OI',
26263930 => 'BJT',
26263939 => 'Telco OI',
2626394 => 'SFR',
26263950 => 'BJT',
26263955 => 'Orange',
26263956 => 'Orange',
26263957 => 'Orange',
26263958 => 'Orange',
26263959 => 'Orange',
26263960 => 'Orange',
26263961 => 'Orange',
26263962 => 'Orange',
26263963 => 'Orange',
26263964 => 'Orange',
26263965 => 'SFR',
26263966 => 'SFR',
26263967 => 'SFR',
26263968 => 'SFR',
26263969 => 'SFR',
26263970 => 'BJT',
26263971 => 'Telco OI',
26263972 => 'Telco OI',
26263973 => 'Telco OI',
26263974 => 'Telco OI',
26263975 => 'Telco OI',
26263976 => 'Orange',
26263977 => 'Orange',
26263978 => 'Orange',
26263979 => 'Orange',
26263990 => 'BJT',
26263994 => 'Telco OI',
26263995 => 'Telco OI',
26263996 => 'Telco OI',
26263997 => 'Telco OI',
26263999 => 'Orange',
262692 => 'SFR',
2626920 => 'Orange',
2626922 => 'Orange',
2626923 => 'Orange',
26269240 => 'Orange',
26269241 => 'Orange',
26269242 => 'Orange',
26269243 => 'Orange',
26269244 => 'Orange',
26269292 => 'Telco OI',
26269293 => 'Telco OI',
26269294 => 'Telco OI',
26269300 => 'Orange',
26269301 => 'SFR',
26269302 => 'SFR',
26269303 => 'SFR',
26269304 => 'SFR',
26269305 => 'ZEOP Mobile',
26269306 => 'Orange',
26269310 => 'SFR',
26269311 => 'Orange',
26269313 => 'SFR',
26269320 => 'SFR',
26269321 => 'Orange',
26269322 => 'Orange',
26269330 => 'Telco OI',
26269331 => 'Telco OI',
26269332 => 'Telco OI',
26269333 => 'Orange',
26269339 => 'Orange',
2626934 => 'Telco OI',
26269350 => 'Telco OI',
26269351 => 'Telco OI',
26269352 => 'Telco OI',
26269353 => 'Telco OI',
26269354 => 'Telco OI',
26269355 => 'Orange',
26269360 => 'Telco OI',
26269361 => 'ZEOP Mobile',
26269362 => 'ZEOP Mobile',
26269363 => 'ZEOP Mobile',
26269364 => 'ZEOP Mobile',
26269365 => 'ZEOP Mobile',
26269366 => 'Orange',
26269370 => 'Telco OI',
26269371 => 'Telco OI',
26269372 => 'Telco OI',
26269373 => 'Telco OI',
26269377 => 'Orange',
2626938 => 'Telco OI',
26269388 => 'Orange',
26269390 => 'Orange',
26269391 => 'Orange',
26269392 => 'Orange',
26269393 => 'Orange',
26269394 => 'SFR',
26269397 => 'SFR',
26269399 => 'Orange',
26270920 => 'SFR',
26270921 => 'Orange',
26270922 => 'Telco OI',
26270923 => 'ZEOP Mobile',
26270935 => 'SFR',
26270936 => 'Telco OI',
26270937 => 'Orange',
];

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 [
26371 => 'Net*One',
26372 => 'Net*One',
26373 => 'Telecel',
26377 => 'Econet',
26378 => 'Econet',
];

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 [
26460 => 'Telecom Namibia',
26481 => 'MTC',
26482 => 'Telecom Namibia',
26484 => 'MTN',
26485 => 'TN Mobile',
];

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 [
26511 => 'Malawi Telecom-munications Ltd (MTL)',
2653 => 'TNM',
2657 => 'Globally Advanced Integrated Networks Ltd',
2658 => 'TNM',
2659 => 'Airtel',
];

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 [
2665 => 'Vodacom Lesotho (Pty) Ltd',
2666 => 'Econet Ezi-Cel Lesotho',
];

View File

@@ -0,0 +1,55 @@
<?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 [
26732 => 'Mascom',
26771 => 'Mascom',
26772 => 'Orange',
26773 => 'BTC Mobile',
26774 => 'Mascom',
267743 => 'Orange',
267744 => 'Orange',
267748 => 'Orange',
267749 => 'BTC Mobile',
267750 => 'Orange',
267751 => 'Orange',
267752 => 'Orange',
267753 => 'Orange',
267754 => 'Mascom',
267755 => 'Mascom',
267756 => 'Mascom',
267757 => 'Orange',
267758 => 'BTC Mobile',
267759 => 'Mascom',
267760 => 'Mascom',
267761 => 'Mascom',
267762 => 'Mascom',
267763 => 'Orange',
267764 => 'Orange',
267765 => 'Orange',
267766 => 'Mascom',
267767 => 'Mascom',
267768 => 'BTC Mobile',
267769 => 'Orange',
267770 => 'Mascom',
267771 => 'Mascom',
267772 => 'BTC Mobile',
267773 => 'Orange',
267774 => 'Orange',
267775 => 'Orange',
267776 => 'Mascom',
267777 => 'Mascom',
267778 => 'Mascom',
267779 => 'Orange',
26778 => 'Orange',
];

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 [
26876 => 'Swazi MTN',
26877 => 'SPTC',
26878 => 'Swazi MTN',
26879 => 'Eswatini Mobile',
];

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 [
2693 => 'Comores Telecom',
2694 => 'TELCO',
];

View File

@@ -0,0 +1,148 @@
<?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 [
2710492 => 'Vodacom',
2710493 => 'Vodacom',
2710494 => 'Vodacom',
2712492 => 'Vodacom',
27134920 => 'Vodacom',
27134921 => 'Vodacom',
27134922 => 'Vodacom',
27134925 => 'Vodacom',
27144950 => 'Vodacom',
27144952 => 'Vodacom',
27144953 => 'Vodacom',
27144955 => 'Vodacom',
27154920 => 'Vodacom',
27154950 => 'Vodacom',
27154951 => 'Vodacom',
27164920 => 'Vodacom',
27174920 => 'Vodacom',
27184920 => 'Vodacom',
2719 => 'Telkom Mobile',
2721492 => 'Vodacom',
27224950 => 'Vodacom',
27274950 => 'Vodacom',
27284920 => 'Vodacom',
2731492 => 'Vodacom',
27324920 => 'Vodacom',
27334920 => 'Vodacom',
27344920 => 'Vodacom',
27354920 => 'Vodacom',
27364920 => 'Vodacom',
27394920 => 'Vodacom',
27404920 => 'Vodacom',
2741492 => 'Vodacom',
27424920 => 'Vodacom',
27434920 => 'Vodacom',
27434921 => 'Vodacom',
27444920 => 'Vodacom',
27444921 => 'Vodacom',
27454920 => 'Vodacom',
27464920 => 'Vodacom',
27474950 => 'Vodacom',
27484920 => 'Vodacom',
27494920 => 'Vodacom',
2751492 => 'Vodacom',
27544950 => 'Vodacom',
27564920 => 'Vodacom',
27574920 => 'Vodacom',
27584920 => 'Vodacom',
27601 => 'Telkom Mobile',
27602 => 'Telkom Mobile',
27603 => 'MTN',
27604 => 'MTN',
27605 => 'MTN',
27606 => 'Vodacom',
27607 => 'Vodacom',
27608 => 'Vodacom',
27609 => 'Vodacom',
2761 => 'Cell C',
27614 => 'Telkom Mobile',
2762 => 'Cell C',
2763 => 'MTN',
27636 => 'Vodacom',
27637 => 'Vodacom',
27640 => 'MTN',
27641 => 'Cell C',
27642 => 'Cell C',
27643 => 'Cell C',
27644 => 'Cell C',
27645 => 'Cell C',
27646 => 'Vodacom',
27647 => 'Vodacom',
27648 => 'Vodacom',
27649 => 'Vodacom',
27650 => 'Cell C',
27651 => 'Cell C',
27652 => 'Cell C',
27653 => 'Cell C',
27654 => 'Cell C',
27655 => 'MTN',
27656 => 'MTN',
27657 => 'MTN',
27658 => 'Telkom Mobile',
27659 => 'Telkom Mobile',
27660 => 'Vodacom',
27661 => 'Vodacom',
27662 => 'Vodacom',
27663 => 'Vodacom',
27664 => 'Vodacom',
27665 => 'Vodacom',
2767 => 'Telkom Mobile',
27673 => 'Vodacom',
27674 => 'Vodacom',
27675 => 'Vodacom',
2768 => 'Telkom Mobile',
27686 => 'MTN',
27687 => 'MTN',
27688 => 'MTN',
27689 => 'MTN',
2771 => 'Vodacom',
27710 => 'MTN',
27717 => 'MTN',
27718 => 'MTN',
27719 => 'MTN',
2772 => 'Vodacom',
2773 => 'MTN',
2774 => 'Cell C',
2775 => 'Telkom Mobile',
2776 => 'Vodacom',
2778 => 'MTN',
2779 => 'Vodacom',
27810 => 'MTN',
27811 => 'Telkom Mobile',
27812 => 'Telkom Mobile',
27813 => 'Telkom Mobile',
27814 => 'Telkom Mobile',
27815 => 'Telkom Mobile',
27816 => 'WBS Mobile',
27817 => 'Telkom Mobile',
27818 => 'Vodacom',
278190 => 'TelAfrica (Wirles Connect)',
278191 => 'TelAfrica (Wirles Connect)',
278192 => 'TelAfrica (Wirles Connect)',
2782 => 'Vodacom',
2783 => 'MTN',
2784 => 'Cell C',
2787086 => 'Vodacom',
2787087 => 'Vodacom',
2787158 => 'Vodacom',
2787285 => 'Vodacom',
2787286 => 'Vodacom',
2787287 => 'Vodacom',
2787288 => 'Vodacom',
2787289 => 'Vodacom',
2787310 => 'Vodacom',
];

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 [
29051 => 'Sure South Atlantic Ltd',
29052 => 'Sure South Atlantic Ltd',
29053 => 'Sure South Atlantic Ltd',
29054 => 'Sure South Atlantic Ltd',
29055 => 'Sure South Atlantic Ltd',
29056 => 'Sure South Atlantic Ltd',
29057 => 'Sure South Atlantic Ltd',
29058 => 'Sure South Atlantic Ltd',
29061 => 'Sure South Atlantic Ltd',
29062 => 'Sure South Atlantic Ltd',
29063 => 'Sure South Atlantic Ltd',
29064 => 'Sure South Atlantic Ltd',
29065 => 'Sure South Atlantic Ltd',
29066 => 'Sure South Atlantic Ltd',
29067 => 'Sure South Atlantic Ltd',
29068 => 'Sure South Atlantic Ltd',
];

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 [
29117 => 'EriTel',
2917 => 'EriTel',
];

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 [
29729 => 'Digicel',
29756 => 'SETAR',
29759 => 'SETAR',
29760 => 'SETAR',
29762 => 'MIO Wireless',
29763 => 'MIO Wireless',
29764 => 'Digicel',
29766 => 'SETAR',
297690 => 'SETAR',
297699 => 'SETAR',
29773 => 'Digicel',
29774 => 'Digicel',
29777 => 'SETAR',
297995 => 'SETAR',
];

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 [
29821 => 'Faroese Telecom',
29822 => 'Faroese Telecom',
29823 => 'Faroese Telecom',
29824 => 'Faroese Telecom',
29825 => 'Faroese Telecom',
29826 => 'Faroese Telecom',
29827 => 'Faroese Telecom',
29828 => 'Faroese Telecom',
29829 => 'Faroese Telecom',
2985 => 'Vodafone',
2987 => 'Vodafone',
29878 => 'Faroese Telecom',
29879 => 'Faroese Telecom',
29891 => 'Faroese Telecom',
29896 => 'Faroese Telecom',
];

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 [
2992 => 'TELE Greenland A/S',
2994 => 'TELE Greenland A/S',
2995 => 'TELE Greenland A/S',
];

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