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: *
    *
  1. It only checks the length of phone numbers. In particular, it doesn't check starting * digits of the number. *
  2. 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. *
  3. 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: * *
    *
  1. It only checks the length of phone numbers. In particular, it doesn't check starting * digits of the number. *
  2. 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