예제 #1
0
 /**
  * Formats a phone number in the specified format using client-defined formatting rules. Note that
  * if the phone number has a country calling code of zero or an otherwise invalid country calling
  * code, we cannot work out things like whether there should be a national prefix applied, or how
  * to format extensions, so we return the national significant number with no formatting applied.
  *
  * @param PhoneNumber $number the phone number to be formatted
  * @param int $numberFormat the format the phone number should be formatted into
  * @param array $userDefinedFormats formatting rules specified by clients
  * @return String the formatted phone number
  */
 public function formatByPattern(PhoneNumber $number, $numberFormat, array $userDefinedFormats)
 {
     $countryCallingCode = $number->getCountryCode();
     $nationalSignificantNumber = $this->getNationalSignificantNumber($number);
     if (!$this->hasValidCountryCallingCode($countryCallingCode)) {
         return $nationalSignificantNumber;
     }
     // Note getRegionCodeForCountryCode() is used because formatting information for regions which
     // share a country calling code is contained by only one region for performance reasons. For
     // example, for NANPA regions it will be contained in the metadata for US.
     $regionCode = $this->getRegionCodeForCountryCode($countryCallingCode);
     // Metadata cannot be null because the country calling code is valid
     $metadata = $this->getMetadataForRegionOrCallingCode($countryCallingCode, $regionCode);
     $formattedNumber = "";
     $formattingPattern = $this->chooseFormattingPatternForNumber($userDefinedFormats, $nationalSignificantNumber);
     if ($formattingPattern === null) {
         // If no pattern above is matched, we format the number as a whole.
         $formattedNumber .= $nationalSignificantNumber;
     } else {
         $numFormatCopy = new NumberFormat();
         // Before we do a replacement of the national prefix pattern $NP with the national prefix, we
         // need to copy the rule so that subsequent replacements for different numbers have the
         // appropriate national prefix.
         $numFormatCopy->mergeFrom($formattingPattern);
         $nationalPrefixFormattingRule = $formattingPattern->getNationalPrefixFormattingRule();
         if (mb_strlen($nationalPrefixFormattingRule) > 0) {
             $nationalPrefix = $metadata->getNationalPrefix();
             if (mb_strlen($nationalPrefix) > 0) {
                 // Replace $NP with national prefix and $FG with the first group ($1).
                 $npPatternMatcher = new Matcher(self::NP_PATTERN, $nationalPrefixFormattingRule);
                 $nationalPrefixFormattingRule = $npPatternMatcher->replaceFirst($nationalPrefix);
                 $fgPatternMatcher = new Matcher(self::FG_PATTERN, $nationalPrefixFormattingRule);
                 $nationalPrefixFormattingRule = $fgPatternMatcher->replaceFirst("\\\$1");
                 $numFormatCopy->setNationalPrefixFormattingRule($nationalPrefixFormattingRule);
             } else {
                 // We don't want to have a rule for how to format the national prefix if there isn't one.
                 $numFormatCopy->clearNationalPrefixFormattingRule();
             }
         }
         $formattedNumber .= $this->formatNsnUsingPattern($nationalSignificantNumber, $numFormatCopy, $numberFormat);
     }
     $this->maybeAppendFormattedExtension($number, $metadata, $numberFormat, $formattedNumber);
     $this->prefixNumberWithCountryCallingCode($countryCallingCode, $numberFormat, $formattedNumber);
     return $formattedNumber;
 }
 /**
  * Formats a phone number using the original phone number format that the number is parsed from.
  * The original format is embedded in the country_code_source field of the PhoneNumber object
  * passed in. If such information is missing, the number will be formatted into the NATIONAL
  * format by default. When the number contains a leading zero and this is unexpected for this
  * country, or we don't have a formatting pattern for the number, the method returns the raw input
  * when it is available.
  *
  * Note this method guarantees no digit will be inserted, removed or modified as a result of
  * formatting.
  *
  * @param PhoneNumber $number  the phone number that needs to be formatted in its original number format
  * @param string $regionCallingFrom  the region whose IDD needs to be prefixed if the original number
  *     has one
  * @return string the formatted phone number in its original number format
  */
 public function formatInOriginalFormat(PhoneNumber $number, $regionCallingFrom)
 {
     if ($number->hasRawInput() && ($this->hasUnexpectedItalianLeadingZero($number) || !$this->hasFormattingPatternForNumber($number))) {
         // We check if we have the formatting pattern because without that, we might format the number
         // as a group without national prefix.
         return $number->getRawInput();
     }
     if (!$number->hasCountryCodeSource()) {
         return $this->format($number, PhoneNumberFormat::NATIONAL);
     }
     switch ($number->getCountryCodeSource()) {
         case CountryCodeSource::FROM_NUMBER_WITH_PLUS_SIGN:
             $formattedNumber = $this->format($number, PhoneNumberFormat::INTERNATIONAL);
             break;
         case CountryCodeSource::FROM_NUMBER_WITH_IDD:
             $formattedNumber = $this->formatOutOfCountryCallingNumber($number, $regionCallingFrom);
             break;
         case CountryCodeSource::FROM_NUMBER_WITHOUT_PLUS_SIGN:
             $formattedNumber = substr($this->format($number, PhoneNumberFormat::INTERNATIONAL), 1);
             break;
         case CountryCodeSource::FROM_DEFAULT_COUNTRY:
             // Fall-through to default case.
         // Fall-through to default case.
         default:
             $regionCode = $this->getRegionCodeForCountryCode($number->getCountryCode());
             // We strip non-digits from the NDD here, and from the raw input later, so that we can
             // compare them easily.
             $nationalPrefix = $this->getNddPrefixForRegion($regionCode, true);
             $nationalFormat = $this->format($number, PhoneNumberFormat::NATIONAL);
             if ($nationalPrefix === null || strlen($nationalPrefix) == 0) {
                 // If the region doesn't have a national prefix at all, we can safely return the national
                 // format without worrying about a national prefix being added.
                 $formattedNumber = $nationalFormat;
                 break;
             }
             // Otherwise, we check if the original number was entered with a national prefix.
             if ($this->rawInputContainsNationalPrefix($number->getRawInput(), $nationalPrefix, $regionCode)) {
                 // If so, we can safely return the national format.
                 $formattedNumber = $nationalFormat;
                 break;
             }
             // Metadata cannot be null here because getNddPrefixForRegion() (above) returns null if
             // there is no metadata for the region.
             $metadata = $this->getMetadataForRegion($regionCode);
             $nationalNumber = $this->getNationalSignificantNumber($number);
             $formatRule = $this->chooseFormattingPatternForNumber($metadata->numberFormats(), $nationalNumber);
             // The format rule could still be null here if the national number was 0 and there was no
             // raw input (this should not be possible for numbers generated by the phonenumber library
             // as they would also not have a country calling code and we would have exited earlier).
             if ($formatRule === NULL) {
                 $formattedNumber = $nationalFormat;
                 break;
             }
             // When the format we apply to this number doesn't contain national prefix, we can just
             // return the national format.
             // TODO: Refactor the code below with the code in isNationalPrefixPresentIfRequired.
             $candidateNationalPrefixRule = $formatRule->getNationalPrefixFormattingRule();
             // We assume that the first-group symbol will never be _before_ the national prefix.
             $indexOfFirstGroup = strpos($candidateNationalPrefixRule, '$1');
             if ($indexOfFirstGroup <= 0) {
                 $formattedNumber = $nationalFormat;
                 break;
             }
             $candidateNationalPrefixRule = substr($candidateNationalPrefixRule, 0, $indexOfFirstGroup);
             $candidateNationalPrefixRule = $this->normalizeDigitsOnly($candidateNationalPrefixRule);
             if (strlen($candidateNationalPrefixRule) == 0) {
                 // National prefix not used when formatting this number.
                 $formattedNumber = $nationalFormat;
                 break;
             }
             // Otherwise, we need to remove the national prefix from our output.
             $numFormatCopy = new NumberFormat();
             $numFormatCopy->mergeFrom($formatRule);
             $numFormatCopy->clearNationalPrefixFormattingRule();
             $numberFormats = array();
             $numberFormats[] = $numFormatCopy;
             $formattedNumber = $this->formatByPattern($number, PhoneNumberFormat::NATIONAL, $numberFormats);
             break;
     }
     $rawInput = $number->getRawInput();
     // If no digit is inserted/removed/modified as a result of our formatting, we return the
     // formatted phone number; otherwise we return the raw input the user entered.
     if ($formattedNumber !== NULL && strlen($rawInput) > 0) {
         $normalizedFormattedNumber = $this->normalizeHelper($formattedNumber, self::$DIALLABLE_CHAR_MAPPINGS, TRUE);
         $normalizedRawInput = $this->normalizeHelper($rawInput, self::$DIALLABLE_CHAR_MAPPINGS, TRUE);
         if ($normalizedFormattedNumber != $normalizedRawInput) {
             $formattedNumber = $rawInput;
         }
     }
     return $formattedNumber;
 }