public function testFormatByPattern() { $newNumFormat = new NumberFormat(); $newNumFormat->setPattern("(\\d{3})(\\d{3})(\\d{4})"); $newNumFormat->setFormat("(\$1) \$2-\$3"); $newNumberFormats = array(); $newNumberFormats[] = $newNumFormat; $this->assertEquals("(650) 253-0000", $this->phoneUtil->formatByPattern(self::$usNumber, PhoneNumberFormat::NATIONAL, $newNumberFormats)); $this->assertEquals("+1 (650) 253-0000", $this->phoneUtil->formatByPattern(self::$usNumber, PhoneNumberFormat::INTERNATIONAL, $newNumberFormats)); $this->assertEquals("+1-650-253-0000", $this->phoneUtil->formatByPattern(self::$usNumber, PhoneNumberFormat::RFC3966, $newNumberFormats)); // $NP is set to '1' for the US. Here we check that for other NANPA countries the US rules are // followed. $newNumFormat->setNationalPrefixFormattingRule('$NP ($FG)'); $newNumFormat->setFormat("\$1 \$2-\$3"); $this->assertEquals("1 (242) 365-1234", $this->phoneUtil->formatByPattern(self::$bsNumber, PhoneNumberFormat::NATIONAL, $newNumberFormats)); $this->assertEquals("+1 242 365-1234", $this->phoneUtil->formatByPattern(self::$bsNumber, PhoneNumberFormat::INTERNATIONAL, $newNumberFormats)); $newNumFormat->setPattern("(\\d{2})(\\d{5})(\\d{3})"); $newNumFormat->setFormat("\$1-\$2 \$3"); $newNumberFormats[0] = $newNumFormat; $this->assertEquals("02-36618 300", $this->phoneUtil->formatByPattern(self::$itNumber, PhoneNumberFormat::NATIONAL, $newNumberFormats)); $this->assertEquals("+39 02-36618 300", $this->phoneUtil->formatByPattern(self::$itNumber, PhoneNumberFormat::INTERNATIONAL, $newNumberFormats)); $newNumFormat->setNationalPrefixFormattingRule('$NP$FG'); $newNumFormat->setPattern("(\\d{2})(\\d{4})(\\d{4})"); $newNumFormat->setFormat("\$1 \$2 \$3"); $newNumberFormats[0] = $newNumFormat; $this->assertEquals("020 7031 3000", $this->phoneUtil->formatByPattern(self::$gbNumber, PhoneNumberFormat::NATIONAL, $newNumberFormats)); $newNumFormat->setNationalPrefixFormattingRule('($NP$FG)'); $this->assertEquals("(020) 7031 3000", $this->phoneUtil->formatByPattern(self::$gbNumber, PhoneNumberFormat::NATIONAL, $newNumberFormats)); $newNumFormat->setNationalPrefixFormattingRule(""); $this->assertEquals("20 7031 3000", $this->phoneUtil->formatByPattern(self::$gbNumber, PhoneNumberFormat::NATIONAL, $newNumberFormats)); $this->assertEquals("+44 20 7031 3000", $this->phoneUtil->formatByPattern(self::$gbNumber, PhoneNumberFormat::INTERNATIONAL, $newNumberFormats)); }
/** * 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; }
/** * @todo Implement this method * Extracts the available formats from the provided DOM element. If it does not contain any * nationalPrefixFormattingRule, the one passed-in is retained. * @param PhoneMetadata $metadata * @param type $regionCode * @param DOMElement $element * @param type $nationalPrefix * @param type $nationalPrefixFormattingRule */ private static function loadAvailableFormats(PhoneMetadata $metadata, $regionCode, \DOMElement $element, $nationalPrefix, $nationalPrefixFormattingRule) { $carrierCodeFormattingRule = ""; if ($element->hasAttribute(self::CARRIER_CODE_FORMATTING_RULE)) { $carrierCodeFormattingRule = self::getDomesticCarrierCodeFormattingRuleFromElement($element, $nationalPrefix); } $numberFormatElements = $element->getElementsByTagName(self::NUMBER_FORMAT); $hasExplicitIntlFormatDefined = false; $numOfFormatElements = $numberFormatElements->length; if ($numOfFormatElements > 0) { for ($i = 0; $i < $numOfFormatElements; $i++) { $numberFormatElement = $numberFormatElements->item($i); $format = new NumberFormat(); if ($numberFormatElement->hasAttribute(self::NATIONAL_PREFIX_FORMATTING_RULE)) { $format->setNationalPrefixFormattingRule(self::getNationalPrefixFormattingRuleFromElement($numberFormatElement, $nationalPrefix)); } else { $format->setNationalPrefixFormattingRule($nationalPrefixFormattingRule); } if ($numberFormatElement->hasAttribute(self::CARRIER_CODE_FORMATTING_RULE)) { $format->setDomesticCarrierCodeFormattingRule(self::getDomesticCarrierCodeFormattingRuleFromElement($numberFormatElement, $nationalPrefix)); } else { $format->setDomesticCarrierCodeFormattingRule($carrierCodeFormattingRule); } $nationalFormat = self::loadNationalFormat($metadata, $numberFormatElement, $format); $metadata->addNumberFormat($format); if (self::loadInternationalFormat($metadata, $numberFormatElement, $nationalFormat)) { $hasExplicitIntlFormatDefined = true; } } // Only a small number of regions need to specify the intlFormats in the xml. For the majority // of countries the intlNumberFormat metadata is an exact copy of the national NumberFormat // metadata. To minimize the size of the metadata file, we only keep intlNumberFormats that // actually differ in some way to the national formats. if (!$hasExplicitIntlFormatDefined) { $metadata->clearIntlNumberFormat(); } } }