예제 #1
0
 /**
  * Tries to extract a country calling code from a number. This method will return zero if no
  * country calling code is considered to be present. Country calling codes are extracted in the
  * following ways:
  * <ul>
  *  <li> by stripping the international dialing prefix of the region the person is dialing from,
  *       if this is present in the number, and looking at the next digits
  *  <li> by stripping the '+' sign if present and then looking at the next digits
  *  <li> by comparing the start of the number and the country calling code of the default region.
  *       If the number is not considered possible for the numbering plan of the default region
  *       initially, but starts with the country calling code of this region, validation will be
  *       reattempted after stripping this country calling code. If this number is considered a
  *       possible number, then the first digits will be considered the country calling code and
  *       removed as such.
  * </ul>
  * It will throw a NumberParseException if the number starts with a '+' but the country calling
  * code supplied after this does not match that of any known region.
  *
  * @param string $number non-normalized telephone number that we wish to extract a country calling
  *     code from - may begin with '+'
  * @param PhoneMetadata $defaultRegionMetadata metadata about the region this number may be from
  * @param string $nationalNumber a string buffer to store the national significant number in, in the case
  *     that a country calling code was extracted. The number is appended to any existing contents.
  *     If no country calling code was extracted, this will be left unchanged.
  * @param bool $keepRawInput true if the country_code_source and preferred_carrier_code fields of
  *     phoneNumber should be populated.
  * @param PhoneNumber $phoneNumber the PhoneNumber object where the country_code and country_code_source need
  *     to be populated. Note the country_code is always populated, whereas country_code_source is
  *     only populated when keepCountryCodeSource is true.
  * @return int the country calling code extracted or 0 if none could be extracted
  * @throws NumberParseException
  */
 public function maybeExtractCountryCode($number, PhoneMetadata $defaultRegionMetadata = null, &$nationalNumber, $keepRawInput, PhoneNumber $phoneNumber)
 {
     if (mb_strlen($number) == 0) {
         return 0;
     }
     $fullNumber = $number;
     // Set the default prefix to be something that will never match.
     $possibleCountryIddPrefix = "NonMatch";
     if ($defaultRegionMetadata !== null) {
         $possibleCountryIddPrefix = $defaultRegionMetadata->getInternationalPrefix();
     }
     $countryCodeSource = $this->maybeStripInternationalPrefixAndNormalize($fullNumber, $possibleCountryIddPrefix);
     if ($keepRawInput) {
         $phoneNumber->setCountryCodeSource($countryCodeSource);
     }
     if ($countryCodeSource != CountryCodeSource::FROM_DEFAULT_COUNTRY) {
         if (mb_strlen($fullNumber) <= self::MIN_LENGTH_FOR_NSN) {
             throw new NumberParseException(NumberParseException::TOO_SHORT_AFTER_IDD, "Phone number had an IDD, but after this was not long enough to be a viable phone number.");
         }
         $potentialCountryCode = $this->extractCountryCode($fullNumber, $nationalNumber);
         if ($potentialCountryCode != 0) {
             $phoneNumber->setCountryCode($potentialCountryCode);
             return $potentialCountryCode;
         }
         // If this fails, they must be using a strange country calling code that we don't recognize,
         // or that doesn't exist.
         throw new NumberParseException(NumberParseException::INVALID_COUNTRY_CODE, "Country calling code supplied was not recognised.");
     } else {
         if ($defaultRegionMetadata !== null) {
             // Check to see if the number starts with the country calling code for the default region. If
             // so, we remove the country calling code, and do some checks on the validity of the number
             // before and after.
             $defaultCountryCode = $defaultRegionMetadata->getCountryCode();
             $defaultCountryCodeString = (string) $defaultCountryCode;
             $normalizedNumber = (string) $fullNumber;
             if (strpos($normalizedNumber, $defaultCountryCodeString) === 0) {
                 $potentialNationalNumber = substr($normalizedNumber, mb_strlen($defaultCountryCodeString));
                 $generalDesc = $defaultRegionMetadata->getGeneralDesc();
                 $validNumberPattern = $generalDesc->getNationalNumberPattern();
                 // Don't need the carrier code.
                 $carriercode = null;
                 $this->maybeStripNationalPrefixAndCarrierCode($potentialNationalNumber, $defaultRegionMetadata, $carriercode);
                 $possibleNumberPattern = $generalDesc->getPossibleNumberPattern();
                 // If the number was not valid before but is valid now, or if it was too long before, we
                 // consider the number with the country calling code stripped to be a better result and
                 // keep that instead.
                 if (preg_match('/^(' . $validNumberPattern . ')$/x', $fullNumber) == 0 && preg_match('/^(' . $validNumberPattern . ')$/x', $potentialNationalNumber) > 0 || $this->testNumberLengthAgainstPattern($possibleNumberPattern, (string) $fullNumber) == ValidationResult::TOO_LONG) {
                     $nationalNumber .= $potentialNationalNumber;
                     if ($keepRawInput) {
                         $phoneNumber->setCountryCodeSource(CountryCodeSource::FROM_NUMBER_WITHOUT_PLUS_SIGN);
                     }
                     $phoneNumber->setCountryCode($defaultCountryCode);
                     return $defaultCountryCode;
                 }
             }
         }
     }
     // No country calling code present.
     $phoneNumber->setCountryCode(0);
     return 0;
 }