Skip to content

Commit

Permalink
Add MetadataLoader changes from Google r656
Browse files Browse the repository at this point in the history
Note: This does not add the newInstance/setInstance changes from upstream.
  • Loading branch information
giggsey committed May 19, 2014
1 parent c7eb9d0 commit f7224d4
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 71 deletions.
6 changes: 4 additions & 2 deletions Tests/libphonenumber/Tests/core/PhoneNumberUtilTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use libphonenumber\CountryCodeSource;
use libphonenumber\CountryCodeToRegionCodeMapForTesting;
use libphonenumber\DefaultMetadataLoader;
use libphonenumber\MatchType;
use libphonenumber\NumberFormat;
use libphonenumber\NumberParseException;
Expand Down Expand Up @@ -158,7 +159,7 @@ public function testMissingMetadataFileThrowsRuntimeException()
// do is make sure the exception has the file name in it.

try {
$this->phoneUtil->loadMetadataFromFile("no/such/file", "XX", -1);
$this->phoneUtil->loadMetadataFromFile("no/such/file", "XX", -1, new DefaultMetadataLoader());
$this->fail("Expected Exception");
} catch (\RuntimeException $e) {
$this->assertContains('no/such/file_XX', $e->getMessage(), "Unexpected error: " . $e->getMessage());
Expand All @@ -168,7 +169,8 @@ public function testMissingMetadataFileThrowsRuntimeException()
$this->phoneUtil->loadMetadataFromFile(
"no/such/file",
PhoneNumberUtil::REGION_CODE_FOR_NON_GEO_ENTITY,
123
123,
new DefaultMetadataLoader()
);
$this->fail("Expected Exception");
} catch (\RuntimeException $e) {
Expand Down
14 changes: 14 additions & 0 deletions src/libphonenumber/DefaultMetadataLoader.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

namespace libphonenumber;


class DefaultMetadataLoader implements MetadataLoader
{
public function loadMetadata($metadataFileName)
{
return include $metadataFileName;
}
}

/* EOF */
15 changes: 15 additions & 0 deletions src/libphonenumber/MetadataLoader.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

namespace libphonenumber;


interface MetadataLoader
{
/**
* @param string $metadataFileName File name (including path) of metadata to load.
* @return mixed
*/
public function loadMetadata($metadataFileName);
}

/* EOF */
2 changes: 1 addition & 1 deletion src/libphonenumber/PhoneNumber.php
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ public function clear()
return $this;
}

public function mergeFrom(PhoneNumber $other)
public function mergeFrom(PhoneNumber $other)
{
if ($other->hasCountryCode()) {
$this->setCountryCode($other->getCountryCode());
Expand Down
151 changes: 83 additions & 68 deletions src/libphonenumber/PhoneNumberUtil.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*
* @author Shaopeng Jia
* @author Lara Rennie
* @see https://code.google.com/p/libphonenumber/
*/
class PhoneNumberUtil
{
Expand Down Expand Up @@ -206,6 +207,13 @@ class PhoneNumberUtil
*/
private static $VALID_PHONE_NUMBER;
private static $numericCharacters = array();

/**
* The metadata loader used to inject alternative metadata sources.
* @var MetadataLoader
*/
private $metadataLoader;

/**
* A mapping from a region code to the PhoneMetadata for that region.
* @var array
Expand Down Expand Up @@ -251,9 +259,62 @@ class PhoneNumberUtil
/**
* This class implements a singleton, so the only constructor is private.
*/
private function __construct()
{

private function __construct($filePrefix, MetadataLoader $metadataLoader, $countryCallingCodeToRegionCodeMap)
{
$this->metadataLoader = $metadataLoader;
$this->countryCallingCodeToRegionCodeMap = $countryCallingCodeToRegionCodeMap;
$this->init($filePrefix);
self::initCapturingExtnDigits();
self::initExtnPatterns();
self::initAsciiDigitMappings();
self::initExtnPattern();
self::$PLUS_CHARS_PATTERN = "[" . self::PLUS_CHARS . "]+";
self::$SEPARATOR_PATTERN = "[" . self::VALID_PUNCTUATION . "]+";
self::$CAPTURING_DIGIT_PATTERN = "(" . self::DIGITS . ")";
self::$VALID_START_CHAR_PATTERN = "[" . self::PLUS_CHARS . self::DIGITS . "]";

self::$ALPHA_PHONE_MAPPINGS = self::$ALPHA_MAPPINGS + self::$asciiDigitMappings;

self::$DIALLABLE_CHAR_MAPPINGS = self::$asciiDigitMappings;
self::$DIALLABLE_CHAR_MAPPINGS[self::PLUS_SIGN] = self::PLUS_SIGN;
self::$DIALLABLE_CHAR_MAPPINGS['*'] = '*';

self::$ALL_PLUS_NUMBER_GROUPING_SYMBOLS = array();
// Put (lower letter -> upper letter) and (upper letter -> upper letter) mappings.
foreach (self::$ALPHA_MAPPINGS as $c => $value) {
self::$ALL_PLUS_NUMBER_GROUPING_SYMBOLS[strtolower($c)] = $c;
self::$ALL_PLUS_NUMBER_GROUPING_SYMBOLS[$c] = $c;
}
self::$ALL_PLUS_NUMBER_GROUPING_SYMBOLS += self::$asciiDigitMappings;
self::$ALL_PLUS_NUMBER_GROUPING_SYMBOLS["-"] = '-';
self::$ALL_PLUS_NUMBER_GROUPING_SYMBOLS["\xEF\xBC\x8D"] = '-';
self::$ALL_PLUS_NUMBER_GROUPING_SYMBOLS["\xE2\x80\x90"] = '-';
self::$ALL_PLUS_NUMBER_GROUPING_SYMBOLS["\xE2\x80\x91"] = '-';
self::$ALL_PLUS_NUMBER_GROUPING_SYMBOLS["\xE2\x80\x92"] = '-';
self::$ALL_PLUS_NUMBER_GROUPING_SYMBOLS["\xE2\x80\x93"] = '-';
self::$ALL_PLUS_NUMBER_GROUPING_SYMBOLS["\xE2\x80\x94"] = '-';
self::$ALL_PLUS_NUMBER_GROUPING_SYMBOLS["\xE2\x80\x95"] = '-';
self::$ALL_PLUS_NUMBER_GROUPING_SYMBOLS["\xE2\x88\x92"] = '-';
self::$ALL_PLUS_NUMBER_GROUPING_SYMBOLS["/"] = "/";
self::$ALL_PLUS_NUMBER_GROUPING_SYMBOLS["\xEF\xBC\x8F"] = "/";
self::$ALL_PLUS_NUMBER_GROUPING_SYMBOLS[" "] = " ";
self::$ALL_PLUS_NUMBER_GROUPING_SYMBOLS["\xE3\x80\x80"] = " ";
self::$ALL_PLUS_NUMBER_GROUPING_SYMBOLS["\xE2\x81\xA0"] = " ";
self::$ALL_PLUS_NUMBER_GROUPING_SYMBOLS["."] = ".";
self::$ALL_PLUS_NUMBER_GROUPING_SYMBOLS["\xEF\xBC\x8E"] = ".";


self::$MIN_LENGTH_PHONE_NUMBER_PATTERN = "[" . self::DIGITS . "]{" . self::MIN_LENGTH_FOR_NSN . "}";
self::$VALID_PHONE_NUMBER = "[" . self::PLUS_CHARS . "]*(?:[" . self::VALID_PUNCTUATION . self::STAR_SIGN . "]*[" . self::DIGITS . "]){3,}[" . self::VALID_PUNCTUATION . self::STAR_SIGN . self::VALID_ALPHA . self::DIGITS . "]*";
self::$VALID_PHONE_NUMBER_PATTERN = "%^" . self::$MIN_LENGTH_PHONE_NUMBER_PATTERN . "$|^" . self::$VALID_PHONE_NUMBER . "(?:" . self::$EXTN_PATTERNS_FOR_PARSING . ")?%" . self::REGEX_FLAGS;

self::$UNWANTED_END_CHAR_PATTERN = "[^" . self::DIGITS . self::VALID_ALPHA . "#]+$";

self::$MOBILE_TOKEN_MAPPINGS = array();
self::$MOBILE_TOKEN_MAPPINGS['52'] = "1";
self::$MOBILE_TOKEN_MAPPINGS['54'] = "9";

self::loadNumericCharacters();
}

/**
Expand All @@ -266,68 +327,21 @@ private function __construct()
*
* @param string $baseFileLocation
* @param array|null $countryCallingCodeToRegionCodeMap
* @param MetadataLoader $metadataLoader
* @return PhoneNumberUtil instance
*/
public static function getInstance($baseFileLocation = self::META_DATA_FILE_PREFIX, array $countryCallingCodeToRegionCodeMap = null)
public static function getInstance($baseFileLocation = self::META_DATA_FILE_PREFIX, array $countryCallingCodeToRegionCodeMap = null, MetadataLoader $metadataLoader = null)
{
if ($countryCallingCodeToRegionCodeMap === null) {
$countryCallingCodeToRegionCodeMap = CountryCodeToRegionCodeMap::$countryCodeToRegionCodeMap;
}
if (self::$instance === null) {
self::$instance = new PhoneNumberUtil();
self::$instance->countryCallingCodeToRegionCodeMap = $countryCallingCodeToRegionCodeMap;
self::$instance->init($baseFileLocation);
self::initCapturingExtnDigits();
self::initExtnPatterns();
self::initAsciiDigitMappings();
self::initExtnPattern();
self::$PLUS_CHARS_PATTERN = "[" . self::PLUS_CHARS . "]+";
self::$SEPARATOR_PATTERN = "[" . self::VALID_PUNCTUATION . "]+";
self::$CAPTURING_DIGIT_PATTERN = "(" . self::DIGITS . ")";
self::$VALID_START_CHAR_PATTERN = "[" . self::PLUS_CHARS . self::DIGITS . "]";

self::$ALPHA_PHONE_MAPPINGS = self::$ALPHA_MAPPINGS + self::$asciiDigitMappings;

self::$DIALLABLE_CHAR_MAPPINGS = self::$asciiDigitMappings;
self::$DIALLABLE_CHAR_MAPPINGS[self::PLUS_SIGN] = self::PLUS_SIGN;
self::$DIALLABLE_CHAR_MAPPINGS['*'] = '*';

self::$ALL_PLUS_NUMBER_GROUPING_SYMBOLS = array();
// Put (lower letter -> upper letter) and (upper letter -> upper letter) mappings.
foreach (self::$ALPHA_MAPPINGS as $c => $value) {
self::$ALL_PLUS_NUMBER_GROUPING_SYMBOLS[strtolower($c)] = $c;
self::$ALL_PLUS_NUMBER_GROUPING_SYMBOLS[$c] = $c;
if ($countryCallingCodeToRegionCodeMap === null) {
$countryCallingCodeToRegionCodeMap = CountryCodeToRegionCodeMap::$countryCodeToRegionCodeMap;
}

if ($metadataLoader === null) {
$metadataLoader = new DefaultMetadataLoader();
}
self::$ALL_PLUS_NUMBER_GROUPING_SYMBOLS += self::$asciiDigitMappings;
self::$ALL_PLUS_NUMBER_GROUPING_SYMBOLS["-"] = '-';
self::$ALL_PLUS_NUMBER_GROUPING_SYMBOLS["\xEF\xBC\x8D"] = '-';
self::$ALL_PLUS_NUMBER_GROUPING_SYMBOLS["\xE2\x80\x90"] = '-';
self::$ALL_PLUS_NUMBER_GROUPING_SYMBOLS["\xE2\x80\x91"] = '-';
self::$ALL_PLUS_NUMBER_GROUPING_SYMBOLS["\xE2\x80\x92"] = '-';
self::$ALL_PLUS_NUMBER_GROUPING_SYMBOLS["\xE2\x80\x93"] = '-';
self::$ALL_PLUS_NUMBER_GROUPING_SYMBOLS["\xE2\x80\x94"] = '-';
self::$ALL_PLUS_NUMBER_GROUPING_SYMBOLS["\xE2\x80\x95"] = '-';
self::$ALL_PLUS_NUMBER_GROUPING_SYMBOLS["\xE2\x88\x92"] = '-';
self::$ALL_PLUS_NUMBER_GROUPING_SYMBOLS["/"] = "/";
self::$ALL_PLUS_NUMBER_GROUPING_SYMBOLS["\xEF\xBC\x8F"] = "/";
self::$ALL_PLUS_NUMBER_GROUPING_SYMBOLS[" "] = " ";
self::$ALL_PLUS_NUMBER_GROUPING_SYMBOLS["\xE3\x80\x80"] = " ";
self::$ALL_PLUS_NUMBER_GROUPING_SYMBOLS["\xE2\x81\xA0"] = " ";
self::$ALL_PLUS_NUMBER_GROUPING_SYMBOLS["."] = ".";
self::$ALL_PLUS_NUMBER_GROUPING_SYMBOLS["\xEF\xBC\x8E"] = ".";


self::$MIN_LENGTH_PHONE_NUMBER_PATTERN = "[" . self::DIGITS . "]{" . self::MIN_LENGTH_FOR_NSN . "}";
self::$VALID_PHONE_NUMBER = "[" . self::PLUS_CHARS . "]*(?:[" . self::VALID_PUNCTUATION . self::STAR_SIGN . "]*[" . self::DIGITS . "]){3,}[" . self::VALID_PUNCTUATION . self::STAR_SIGN . self::VALID_ALPHA . self::DIGITS . "]*";
self::$VALID_PHONE_NUMBER_PATTERN = "%^" . self::$MIN_LENGTH_PHONE_NUMBER_PATTERN . "$|^" . self::$VALID_PHONE_NUMBER . "(?:" . self::$EXTN_PATTERNS_FOR_PARSING . ")?%" . self::REGEX_FLAGS;

self::$UNWANTED_END_CHAR_PATTERN = "[^" . self::DIGITS . self::VALID_ALPHA . "#]+$";

self::$MOBILE_TOKEN_MAPPINGS = array();
self::$MOBILE_TOKEN_MAPPINGS['52'] = "1";
self::$MOBILE_TOKEN_MAPPINGS['54'] = "9";

self::loadNumericCharacters();

self::$instance = new PhoneNumberUtil($baseFileLocation, $metadataLoader, $countryCallingCodeToRegionCodeMap);
}
return self::$instance;
}
Expand Down Expand Up @@ -625,7 +639,7 @@ public function getMetadataForRegion($regionCode)
if (!isset($this->regionToMetadataMap[$regionCode])) {
// The regionCode here will be valid and won't be '001', so we don't need to worry about
// what to pass in for the country calling code.
$this->loadMetadataFromFile($this->currentFilePrefix, $regionCode, 0);
$this->loadMetadataFromFile($this->currentFilePrefix, $regionCode, 0, $this->metadataLoader);
}
return isset($this->regionToMetadataMap[$regionCode]) ? $this->regionToMetadataMap[$regionCode] : null;
}
Expand All @@ -644,16 +658,17 @@ private function isValidRegionCode($regionCode)
* @param string $filePrefix
* @param string $regionCode
* @param int $countryCallingCode
* @param MetadataLoader $metadataLoader
* @throws \RuntimeException
*/
public function loadMetadataFromFile($filePrefix, $regionCode, $countryCallingCode)
public function loadMetadataFromFile($filePrefix, $regionCode, $countryCallingCode, MetadataLoader $metadataLoader)
{
$isNonGeoRegion = self::REGION_CODE_FOR_NON_GEO_ENTITY === $regionCode;
$fileName = $filePrefix . '_' . ($isNonGeoRegion ? $countryCallingCode : $regionCode) . '.php';
if (!is_readable($fileName)) {
throw new \RuntimeException('missing metadata: ' . $fileName);
} else {
$data = include $fileName;
$data = $metadataLoader->loadMetadata($fileName);
$metadata = new PhoneMetadata();
$metadata->fromArray($data);
if ($isNonGeoRegion) {
Expand Down Expand Up @@ -836,10 +851,10 @@ public function isNumberPossibleForDesc($nationalNumber, PhoneNumberDesc $number
* Tests whether a phone number has a geographical association. It checks if the number is
* associated to a certain region in the country where it belongs to. Note that this doesn't
* verify if the number is actually in use.
* @param string $phoneNumber
* @param PhoneNumber $phoneNumber
* @return bool
*/
public function isNumberGeographical($phoneNumber)
public function isNumberGeographical(PhoneNumber $phoneNumber)
{
$numberType = $this->getNumberType($phoneNumber);
// TODO: Include mobile phone numbers from countries like Indonesia, which has some
Expand Down Expand Up @@ -887,7 +902,8 @@ public function getMetadataForNonGeographicalRegion($countryCallingCode)
$this->loadMetadataFromFile(
$this->currentFilePrefix,
self::REGION_CODE_FOR_NON_GEO_ENTITY,
$countryCallingCode
$countryCallingCode,
$this->metadataLoader
);
}
return $this->countryCodeToNonGeographicalMetadataMap[$countryCallingCode];
Expand Down Expand Up @@ -1399,7 +1415,6 @@ private function parseHelper($numberToParse, $defaultRegion, $keepRawInput, $che
// Check to see if the number is given in international format so we know whether this number is
// from the default region or not.
$normalizedNationalNumber = "";
$countryCode = 0;
try {
// TODO: This method should really just take in the string buffer that has already
// been created, and just remove the prefix, rather than taking in a string and then
Expand Down Expand Up @@ -3185,4 +3200,4 @@ public function truncateTooLongNumber(PhoneNumber $number)
}
}

/* EOF */
/* EOF */

0 comments on commit f7224d4

Please sign in to comment.