NSN_MATCH;
}
if ($this->isNationalNumberSuffixOfTheOther($firstNumber, $secondNumber)) {
return MatchType::SHORT_NSN_MATCH;
}
return MatchType::NO_MATCH;
}
return MatchType::NOT_A_NUMBER;
}
/**
* Returns true when one national number is the suffix of the other or both are the same.
* @param PhoneNumber $firstNumber
* @param PhoneNumber $secondNumber
* @return bool
*/
protected function isNationalNumberSuffixOfTheOther(PhoneNumber $firstNumber, PhoneNumber $secondNumber)
{
$firstNumberNationalNumber = trim((string)$firstNumber->getNationalNumber());
$secondNumberNationalNumber = trim((string)$secondNumber->getNationalNumber());
return $this->stringEndsWithString($firstNumberNationalNumber, $secondNumberNationalNumber) ||
$this->stringEndsWithString($secondNumberNationalNumber, $firstNumberNationalNumber);
}
/**
* Returns true if a string ends with a given substring, false otherwise.
*
* @param string $hayStack
* @param string $needle
* @return bool
*/
protected function stringEndsWithString($hayStack, $needle)
{
$revNeedle = strrev($needle);
$revHayStack = strrev($hayStack);
return strpos($revHayStack, $revNeedle) === 0;
}
/**
* Returns true if the supplied region supports mobile number portability. Returns false for
* invalid, unknown or regions that don't support mobile number portability.
*
* @param string $regionCode the region for which we want to know whether it supports mobile number
* portability or not.
* @return bool
*/
public function isMobileNumberPortableRegion($regionCode)
{
$metadata = $this->getMetadataForRegion($regionCode);
if ($metadata === null) {
return false;
}
return $metadata->isMobileNumberPortableRegion();
}
/**
* Check whether a phone number is a possible number given a number in the form of a string, and
* the region where the number could be dialed from. It provides a more lenient check than
* {@link #isValidNumber}. See {@link #isPossibleNumber(PhoneNumber)} for details.
*
* Convenience wrapper around {@link #isPossibleNumberWithReason}. Instead of returning the reason
* for failure, this method returns a boolean value.
* For failure, this method returns true if the number is either a possible fully-qualified number
* (containing the area code and country code), or if the number could be a possible local number
* (with a country code, but missing an area code). Local numbers are considered possible if they
* could be possibly dialled in this format: if the area code is needed for a call to connect, the
* number is not considered possible without it.
*
* Note: There are two ways to call this method.
*
* isPossibleNumber(PhoneNumber $numberObject)
* isPossibleNumber(string '+441174960126', string 'GB')
*
* @param PhoneNumber|string $number the number that needs to be checked, in the form of a string
* @param string|null $regionDialingFrom the region that we are expecting the number to be dialed from.
* Note this is different from the region where the number belongs. For example, the number
* +1 650 253 0000 is a number that belongs to US. When written in this form, it can be
* dialed from any region. When it is written as 00 1 650 253 0000, it can be dialed from any
* region which uses an international dialling prefix of 00. When it is written as
* 650 253 0000, it can only be dialed from within the US, and when written as 253 0000, it
* can only be dialed from within a smaller area in the US (Mountain View, CA, to be more
* specific).
* @return boolean true if the number is possible
*/
public function isPossibleNumber($number, $regionDialingFrom = null)
{
if (is_string($number)) {
try {
return $this->isPossibleNumber($this->parse($number, $regionDialingFrom));
} catch (NumberParseException $e) {
return false;
}
} else {
$result = $this->isPossibleNumberWithReason($number);
return $result === ValidationResult::IS_POSSIBLE
|| $result === ValidationResult::IS_POSSIBLE_LOCAL_ONLY;
}
}
/**
* Check whether a phone number is a possible number. It provides a more lenient check than
* {@link #isValidNumber} in the following sense:
*
* - It only checks the length of phone numbers. In particular, it doesn't check starting
* digits of the number.
*
- It doesn't attempt to figure out the type of the number, but uses general rules which
* applies to all types of phone numbers in a region. Therefore, it is much faster than
* isValidNumber.
*
- For some numbers (particularly fixed-line), many regions have the concept of area code,
* which together with subscriber number constitute the national significant number. It is
* sometimes okay to dial only the subscriber number when dialing in the same area. This
* function will return IS_POSSIBLE_LOCAL_ONLY if the subscriber-number-only version is
* passed in. On the other hand, because isValidNumber validates using information on both
* starting digits (for fixed line numbers, that would most likely be area codes) and
* length (obviously includes the length of area codes for fixed line numbers), it will
* return false for the subscriber-number-only version.
*
* @param PhoneNumber $number the number that needs to be checked
* @return int a ValidationResult object which indicates whether the number is possible
*/
public function isPossibleNumberWithReason(PhoneNumber $number)
{
return $this->isPossibleNumberForTypeWithReason($number, PhoneNumberType::UNKNOWN);
}
/**
* Check whether a phone number is a possible number of a particular type. For types that don't
* exist in a particular region, this will return a result that isn't so useful; it is recommended
* that you use {@link #getSupportedTypesForRegion} or {@link #getSupportedTypesForNonGeoEntity}
* respectively before calling this method to determine whether you should call it for this number
* at all.
*
* This provides a more lenient check than {@link #isValidNumber} in the following sense:
*
*
* - It only checks the length of phone numbers. In particular, it doesn't check starting
* digits of the number.
*
- For some numbers (particularly fixed-line), many regions have the concept of area code,
* which together with subscriber number constitute the national significant number. It is
* sometimes okay to dial only the subscriber number when dialing in the same area. This
* function will return IS_POSSIBLE_LOCAL_ONLY if the subscriber-number-only version is
* passed in. On the other hand, because isValidNumber validates using information on both
* starting digits (for fixed line numbers, that would most likely be area codes) and
* length (obviously includes the length of area codes for fixed line numbers), it will
* return false for the subscriber-number-only version.
*
*
* @param PhoneNumber $number the number that needs to be checked
* @param int $type the PhoneNumberType we are interested in
* @return int a ValidationResult object which indicates whether the number is possible
*/
public function isPossibleNumberForTypeWithReason(PhoneNumber $number, $type)
{
$nationalNumber = $this->getNationalSignificantNumber($number);
$countryCode = $number->getCountryCode();
// Note: For regions that share a country calling code, like NANPA numbers, we just use the
// rules from the default region (US in this case) since the getRegionCodeForNumber will not
// work if the number is possible but not valid. There is in fact one country calling code (290)
// where the possible number pattern differs between various regions (Saint Helena and Tristan
// da Cuñha), but this is handled by putting all possible lengths for any country with this
// country calling code in the metadata for the default region in this case.
if (!$this->hasValidCountryCallingCode($countryCode)) {
return ValidationResult::INVALID_COUNTRY_CODE;
}
$regionCode = $this->getRegionCodeForCountryCode($countryCode);
// Metadata cannot be null because the country calling code is valid.
$metadata = $this->getMetadataForRegionOrCallingCode($countryCode, $regionCode);
return $this->testNumberLength($nationalNumber, $metadata, $type);
}
/**
* Attempts to extract a valid number from a phone number that is too long to be valid, and resets
* the PhoneNumber object passed in to that valid version. If no valid number could be extracted,
* the PhoneNumber object passed in will not be modified.
*
* @param PhoneNumber $number a PhoneNumber object which contains a number that is too long to be valid.
* @return boolean true if a valid phone number can be successfully extracted.
*/
public function truncateTooLongNumber(PhoneNumber $number)
{
if ($this->isValidNumber($number)) {
return true;
}
$numberCopy = new PhoneNumber();
$numberCopy->mergeFrom($number);
$nationalNumber = $number->getNationalNumber();
do {
$nationalN