Update v1.0.6
This commit is contained in:
@@ -1,7 +0,0 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
require __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
$app = new \libphonenumber\buildtools\BuildApplication();
|
||||
$app->run();
|
@@ -1,13 +0,0 @@
|
||||
diff --git a/resources/PhoneNumberMetadata.xml b/resources/PhoneNumberMetadata.xml
|
||||
index a53b48d..820598c 100644
|
||||
--- a/resources/PhoneNumberMetadata.xml
|
||||
+++ b/resources/PhoneNumberMetadata.xml
|
||||
@@ -19031,7 +19031,7 @@
|
||||
<generalDesc>
|
||||
<nationalNumberPattern>
|
||||
[12]\d{6,8}|
|
||||
- [3-57-9]\d{8}|
|
||||
+ (?:[3-5]|[7-9])\d{8}|
|
||||
6\d{5,8}
|
||||
</nationalNumberPattern>
|
||||
<possibleNumberPattern>\d{6,9}</possibleNumberPattern>
|
@@ -1,26 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace libphonenumber\buildtools;
|
||||
|
||||
use libphonenumber\buildtools\Commands\BuildMetadataPHPFromXMLCommand;
|
||||
use libphonenumber\buildtools\Commands\GeneratePhonePrefixDataCommand;
|
||||
use libphonenumber\buildtools\Commands\GenerateTimeZonesMapDataCommand;
|
||||
use Symfony\Component\Console\Application;
|
||||
|
||||
class BuildApplication extends Application
|
||||
{
|
||||
const VERSION = '5';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct('libphonenumber Data Builder', self::VERSION);
|
||||
|
||||
$this->addCommands(
|
||||
array(
|
||||
new BuildMetadataPHPFromXMLCommand(),
|
||||
new GeneratePhonePrefixDataCommand(),
|
||||
new GenerateTimeZonesMapDataCommand(),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
@@ -1,463 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace libphonenumber\buildtools;
|
||||
|
||||
use libphonenumber\NumberFormat;
|
||||
use libphonenumber\PhoneMetadata;
|
||||
use libphonenumber\PhoneNumberDesc;
|
||||
|
||||
/**
|
||||
* Library to build phone number metadata from the XML format.
|
||||
*
|
||||
* @author Davide Mendolia
|
||||
*/
|
||||
class BuildMetadataFromXml
|
||||
{
|
||||
// String constants used to fetch the XML nodes and attributes.
|
||||
const CARRIER_CODE_FORMATTING_RULE = "carrierCodeFormattingRule";
|
||||
const COUNTRY_CODE = "countryCode";
|
||||
const EMERGENCY = "emergency";
|
||||
const EXAMPLE_NUMBER = "exampleNumber";
|
||||
const FIXED_LINE = "fixedLine";
|
||||
const FORMAT = "format";
|
||||
const GENERAL_DESC = "generalDesc";
|
||||
const INTERNATIONAL_PREFIX = "internationalPrefix";
|
||||
const INTL_FORMAT = "intlFormat";
|
||||
const LEADING_DIGITS = "leadingDigits";
|
||||
const LEADING_ZERO_POSSIBLE = "leadingZeroPossible";
|
||||
const MOBILE_NUMBER_PORTABLE_REGION = "mobileNumberPortableRegion";
|
||||
const MAIN_COUNTRY_FOR_CODE = "mainCountryForCode";
|
||||
const MOBILE = "mobile";
|
||||
const NATIONAL_NUMBER_PATTERN = "nationalNumberPattern";
|
||||
const NATIONAL_PREFIX = "nationalPrefix";
|
||||
const NATIONAL_PREFIX_FORMATTING_RULE = "nationalPrefixFormattingRule";
|
||||
const NATIONAL_PREFIX_OPTIONAL_WHEN_FORMATTING = "nationalPrefixOptionalWhenFormatting";
|
||||
const NATIONAL_PREFIX_FOR_PARSING = "nationalPrefixForParsing";
|
||||
const NATIONAL_PREFIX_TRANSFORM_RULE = "nationalPrefixTransformRule";
|
||||
const NO_INTERNATIONAL_DIALLING = "noInternationalDialling";
|
||||
const NUMBER_FORMAT = "numberFormat";
|
||||
const PAGER = "pager";
|
||||
const CARRIER_SPECIFIC = 'carrierSpecific';
|
||||
const PATTERN = "pattern";
|
||||
const PERSONAL_NUMBER = "personalNumber";
|
||||
const POSSIBLE_NUMBER_PATTERN = "possibleNumberPattern";
|
||||
const PREFERRED_EXTN_PREFIX = "preferredExtnPrefix";
|
||||
const PREFERRED_INTERNATIONAL_PREFIX = "preferredInternationalPrefix";
|
||||
const PREMIUM_RATE = "premiumRate";
|
||||
const SHARED_COST = "sharedCost";
|
||||
const SHORT_CODE = "shortCode";
|
||||
const STANDARD_RATE = "standardRate";
|
||||
const TOLL_FREE = "tollFree";
|
||||
const UAN = "uan";
|
||||
const VOICEMAIL = "voicemail";
|
||||
const VOIP = "voip";
|
||||
/**
|
||||
* @var boolean
|
||||
*/
|
||||
private static $liteBuild;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $inputXmlFile
|
||||
* @param boolean $liteBuild
|
||||
* @return PhoneMetadata[]
|
||||
*/
|
||||
public static function buildPhoneMetadataCollection($inputXmlFile, $liteBuild)
|
||||
{
|
||||
self::$liteBuild = $liteBuild;
|
||||
$document = new \DOMDocument();
|
||||
$document->load($inputXmlFile);
|
||||
$territories = $document->getElementsByTagName("territory");
|
||||
$metadataCollection = array();
|
||||
foreach ($territories as $territory) {
|
||||
if ($territory->hasAttribute("id")) {
|
||||
$regionCode = $territory->getAttribute("id");
|
||||
} else {
|
||||
$regionCode = "";
|
||||
}
|
||||
$metadata = self::loadCountryMetadata($regionCode, $territory);
|
||||
$metadataCollection[] = $metadata;
|
||||
}
|
||||
return $metadataCollection;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $regionCode
|
||||
* @param \DOMElement $element
|
||||
* @return PhoneMetadata
|
||||
*/
|
||||
public static function loadCountryMetadata($regionCode, \DOMElement $element)
|
||||
{
|
||||
$nationalPrefix = self::getNationalPrefix($element);
|
||||
$nationalPrefixFormattingRule = self::getNationalPrefixFormattingRuleFromElement($element, $nationalPrefix);
|
||||
$metadata = self::loadTerritoryTagMetadata(
|
||||
$regionCode,
|
||||
$element,
|
||||
$nationalPrefix,
|
||||
$nationalPrefixFormattingRule
|
||||
);
|
||||
|
||||
self::loadAvailableFormats($metadata, $regionCode, $element, $nationalPrefix, $nationalPrefixFormattingRule);
|
||||
self::loadGeneralDesc($metadata, $element);
|
||||
return $metadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the national prefix of the provided country element.
|
||||
* @param \DOMElement $element
|
||||
* @return string
|
||||
*/
|
||||
private static function getNationalPrefix(\DOMElement $element)
|
||||
{
|
||||
return $element->hasAttribute(self::NATIONAL_PREFIX) ? $element->getAttribute(self::NATIONAL_PREFIX) : "";
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param \DOMElement $element
|
||||
* @param string $nationalPrefix
|
||||
* @return string
|
||||
*/
|
||||
private static function getNationalPrefixFormattingRuleFromElement(\DOMElement $element, $nationalPrefix)
|
||||
{
|
||||
$nationalPrefixFormattingRule = $element->getAttribute(self::NATIONAL_PREFIX_FORMATTING_RULE);
|
||||
// Replace $NP with national prefix and $FG with the first group ($1).
|
||||
$nationalPrefixFormattingRule = str_replace('$NP', $nationalPrefix, $nationalPrefixFormattingRule);
|
||||
$nationalPrefixFormattingRule = str_replace('$FG', '$1', $nationalPrefixFormattingRule);
|
||||
return $nationalPrefixFormattingRule;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $regionCode
|
||||
* @param \DOMElement $element
|
||||
* @param string $nationalPrefix
|
||||
* @param string $nationalPrefixFormattingRule
|
||||
* @return PhoneMetadata
|
||||
*/
|
||||
private static function loadTerritoryTagMetadata(
|
||||
$regionCode,
|
||||
\DOMElement $element,
|
||||
$nationalPrefix,
|
||||
$nationalPrefixFormattingRule
|
||||
) {
|
||||
$metadata = new PhoneMetadata();
|
||||
$metadata->setId($regionCode);
|
||||
$metadata->setCountryCode((int)$element->getAttribute(self::COUNTRY_CODE));
|
||||
if ($element->hasAttribute(self::LEADING_DIGITS)) {
|
||||
$metadata->setLeadingDigits($element->getAttribute(self::LEADING_DIGITS));
|
||||
}
|
||||
$metadata->setInternationalPrefix($element->getAttribute(self::INTERNATIONAL_PREFIX));
|
||||
if ($element->hasAttribute(self::PREFERRED_INTERNATIONAL_PREFIX)) {
|
||||
$preferredInternationalPrefix = $element->getAttribute(self::PREFERRED_INTERNATIONAL_PREFIX);
|
||||
$metadata->setPreferredInternationalPrefix($preferredInternationalPrefix);
|
||||
}
|
||||
if ($element->hasAttribute(self::NATIONAL_PREFIX_FOR_PARSING)) {
|
||||
$metadata->setNationalPrefixForParsing(
|
||||
$element->getAttribute(self::NATIONAL_PREFIX_FOR_PARSING)
|
||||
);
|
||||
if ($element->hasAttribute(self::NATIONAL_PREFIX_TRANSFORM_RULE)) {
|
||||
$metadata->setNationalPrefixTransformRule($element->getAttribute(self::NATIONAL_PREFIX_TRANSFORM_RULE));
|
||||
}
|
||||
}
|
||||
if ($nationalPrefix != '') {
|
||||
$metadata->setNationalPrefix($nationalPrefix);
|
||||
if (!$metadata->hasNationalPrefixForParsing()) {
|
||||
$metadata->setNationalPrefixForParsing($nationalPrefix);
|
||||
}
|
||||
}
|
||||
if ($element->hasAttribute(self::PREFERRED_EXTN_PREFIX)) {
|
||||
$metadata->setPreferredExtnPrefix($element->getAttribute(self::PREFERRED_EXTN_PREFIX));
|
||||
}
|
||||
if ($element->hasAttribute(self::MAIN_COUNTRY_FOR_CODE)) {
|
||||
$metadata->setMainCountryForCode(true);
|
||||
}
|
||||
if ($element->hasAttribute(self::LEADING_ZERO_POSSIBLE)) {
|
||||
$metadata->setLeadingZeroPossible(true);
|
||||
}
|
||||
if ($element->hasAttribute(self::MOBILE_NUMBER_PORTABLE_REGION)) {
|
||||
$metadata->setMobileNumberPortableRegion(true);
|
||||
}
|
||||
return $metadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 string $regionCode
|
||||
* @param \DOMElement $element
|
||||
* @param string $nationalPrefix
|
||||
* @param string $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);
|
||||
}
|
||||
self::loadNationalFormat($metadata, $numberFormatElement, $format);
|
||||
$metadata->addNumberFormat($format);
|
||||
|
||||
if (self::loadInternationalFormat($metadata, $numberFormatElement, $format)) {
|
||||
$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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static function getDomesticCarrierCodeFormattingRuleFromElement(\DOMElement $element, $nationalPrefix)
|
||||
{
|
||||
$carrierCodeFormattingRule = $element->getAttribute(self::CARRIER_CODE_FORMATTING_RULE);
|
||||
// Replace $FG with the first group ($1) and $NP with the national prefix.
|
||||
$carrierCodeFormattingRule = str_replace('$NP', $nationalPrefix, $carrierCodeFormattingRule);
|
||||
$carrierCodeFormattingRule = str_replace('$FG', '$1', $carrierCodeFormattingRule);
|
||||
return $carrierCodeFormattingRule;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the pattern for the national format.
|
||||
*
|
||||
* @param PhoneMetadata $metadata
|
||||
* @param \DOMElement $numberFormatElement
|
||||
* @param NumberFormat $format
|
||||
* @throws \RuntimeException if multiple or no formats have been encountered.
|
||||
*/
|
||||
private static function loadNationalFormat(
|
||||
PhoneMetadata $metadata,
|
||||
\DOMElement $numberFormatElement,
|
||||
NumberFormat $format
|
||||
) {
|
||||
self::setLeadingDigitsPatterns($numberFormatElement, $format);
|
||||
$format->setPattern($numberFormatElement->getAttribute(self::PATTERN));
|
||||
|
||||
$formatPattern = $numberFormatElement->getElementsByTagName(self::FORMAT);
|
||||
if ($formatPattern->length != 1) {
|
||||
$countryId = strlen($metadata->getId()) > 0 ? $metadata->getId() : $metadata->getCountryCode();
|
||||
throw new \RuntimeException("Invalid number of format patterns for country: " . $countryId);
|
||||
}
|
||||
$nationalFormat = $formatPattern->item(0)->firstChild->nodeValue;
|
||||
$format->setFormat($nationalFormat);
|
||||
}
|
||||
|
||||
public static function setLeadingDigitsPatterns(\DOMElement $numberFormatElement, NumberFormat $format)
|
||||
{
|
||||
$leadingDigitsPatternNodes = $numberFormatElement->getElementsByTagName(self::LEADING_DIGITS);
|
||||
$numOfLeadingDigitsPatterns = $leadingDigitsPatternNodes->length;
|
||||
if ($numOfLeadingDigitsPatterns > 0) {
|
||||
for ($i = 0; $i < $numOfLeadingDigitsPatterns; $i++) {
|
||||
$elt = $leadingDigitsPatternNodes->item($i);
|
||||
$format->addLeadingDigitsPattern(
|
||||
$elt->firstChild->nodeValue,
|
||||
true
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the pattern for international format. If there is no intlFormat, default to using the
|
||||
* national format. If the intlFormat is set to "NA" the intlFormat should be ignored.
|
||||
*
|
||||
* @param PhoneMetadata $metadata
|
||||
* @param \DOMElement $numberFormatElement
|
||||
* @param NumberFormat $nationalFormat
|
||||
* @throws \RuntimeException if multiple intlFormats have been encountered.
|
||||
* @return bool whether an international number format is defined.
|
||||
*/
|
||||
private static function loadInternationalFormat(
|
||||
PhoneMetadata $metadata,
|
||||
\DOMElement $numberFormatElement,
|
||||
NumberFormat $nationalFormat
|
||||
) {
|
||||
$intlFormat = new NumberFormat();
|
||||
$intlFormatPattern = $numberFormatElement->getElementsByTagName(self::INTL_FORMAT);
|
||||
$hasExplicitIntlFormatDefined = false;
|
||||
|
||||
if ($intlFormatPattern->length > 1) {
|
||||
$countryId = strlen($metadata->getId()) > 0 ? $metadata->getId() : $metadata->getCountryCode();
|
||||
throw new \RuntimeException("Invalid number of intlFormat patterns for country: " . $countryId);
|
||||
} elseif ($intlFormatPattern->length == 0) {
|
||||
// Default to use the same as the national pattern if none is defined.
|
||||
$intlFormat->mergeFrom($nationalFormat);
|
||||
} else {
|
||||
$intlFormat->setPattern($numberFormatElement->getAttribute(self::PATTERN));
|
||||
self::setLeadingDigitsPatterns($numberFormatElement, $intlFormat);
|
||||
$intlFormatPatternValue = $intlFormatPattern->item(0)->firstChild->nodeValue;
|
||||
if ($intlFormatPatternValue !== "NA") {
|
||||
$intlFormat->setFormat($intlFormatPatternValue);
|
||||
}
|
||||
$hasExplicitIntlFormatDefined = true;
|
||||
}
|
||||
|
||||
if ($intlFormat->hasFormat()) {
|
||||
$metadata->addIntlNumberFormat($intlFormat);
|
||||
}
|
||||
return $hasExplicitIntlFormatDefined;
|
||||
}
|
||||
|
||||
private static function loadGeneralDesc(PhoneMetadata $metadata, \DOMElement $element)
|
||||
{
|
||||
$generalDesc = new PhoneNumberDesc();
|
||||
$generalDesc = self::processPhoneNumberDescElement($generalDesc, $element, self::GENERAL_DESC);
|
||||
$metadata->setGeneralDesc($generalDesc);
|
||||
$metadata->setFixedLine(self::processPhoneNumberDescElement($generalDesc, $element, self::FIXED_LINE));
|
||||
$metadata->setMobile(self::processPhoneNumberDescElement($generalDesc, $element, self::MOBILE));
|
||||
$metadata->setStandardRate(self::processPhoneNumberDescElement($generalDesc, $element, self::STANDARD_RATE));
|
||||
$metadata->setPremiumRate(self::processPhoneNumberDescElement($generalDesc, $element, self::PREMIUM_RATE));
|
||||
$metadata->setShortCode(self::processPhoneNumberDescElement($generalDesc, $element, self::SHORT_CODE));
|
||||
$metadata->setTollFree(self::processPhoneNumberDescElement($generalDesc, $element, self::TOLL_FREE));
|
||||
$metadata->setSharedCost(self::processPhoneNumberDescElement($generalDesc, $element, self::SHARED_COST));
|
||||
|
||||
|
||||
$metadata->setVoip(self::processPhoneNumberDescElement($generalDesc, $element, self::VOIP));
|
||||
$metadata->setPersonalNumber(
|
||||
self::processPhoneNumberDescElement($generalDesc, $element, self::PERSONAL_NUMBER)
|
||||
);
|
||||
$metadata->setPager(self::processPhoneNumberDescElement($generalDesc, $element, self::PAGER));
|
||||
$metadata->setUan(self::processPhoneNumberDescElement($generalDesc, $element, self::UAN));
|
||||
$metadata->setEmergency(self::processPhoneNumberDescElement($generalDesc, $element, self::EMERGENCY));
|
||||
$metadata->setVoicemail(self::processPhoneNumberDescElement($generalDesc, $element, self::VOICEMAIL));
|
||||
$metadata->setCarrierSpecific(
|
||||
self::processPhoneNumberDescElement($generalDesc, $element, self::CARRIER_SPECIFIC)
|
||||
);
|
||||
|
||||
|
||||
$metadata->setNoInternationalDialling(
|
||||
self::processPhoneNumberDescElement($generalDesc, $element, self::NO_INTERNATIONAL_DIALLING)
|
||||
);
|
||||
$metadata->setSameMobileAndFixedLinePattern(
|
||||
$metadata->getMobile()->getNationalNumberPattern() === $metadata->getFixedLine()->getNationalNumberPattern()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes a phone number description element from the XML file and returns it as a
|
||||
* PhoneNumberDesc. If the description element is a fixed line or mobile number, the general
|
||||
* description will be used to fill in the whole element if necessary, or any components that are
|
||||
* missing. For all other types, the general description will only be used to fill in missing
|
||||
* components if the type has a partial definition. For example, if no "tollFree" element exists,
|
||||
* we assume there are no toll free numbers for that locale, and return a phone number description
|
||||
* with "NA" for both the national and possible number patterns.
|
||||
*
|
||||
* @param PhoneNumberDesc $generalDesc generic phone number description that will be used to fill in missing
|
||||
* parts of the description
|
||||
* @param \DOMElement $countryElement XML element representing all the country information
|
||||
* @param string $numberType name of the number type, corresponding to the appropriate tag in the XML
|
||||
* file with information about that type
|
||||
* @return PhoneNumberDesc complete description of that phone number type
|
||||
*/
|
||||
private static function processPhoneNumberDescElement(
|
||||
PhoneNumberDesc $generalDesc,
|
||||
\DOMElement $countryElement,
|
||||
$numberType
|
||||
) {
|
||||
$phoneNumberDescList = $countryElement->getElementsByTagName($numberType);
|
||||
$numberDesc = new PhoneNumberDesc();
|
||||
if ($phoneNumberDescList->length == 0 && !self::isValidNumberType($numberType)) {
|
||||
$numberDesc->setNationalNumberPattern("NA");
|
||||
$numberDesc->setPossibleNumberPattern("NA");
|
||||
return $numberDesc;
|
||||
}
|
||||
$numberDesc->mergeFrom($generalDesc);
|
||||
if ($phoneNumberDescList->length > 0) {
|
||||
$element = $phoneNumberDescList->item(0);
|
||||
$possiblePattern = $element->getElementsByTagName(self::POSSIBLE_NUMBER_PATTERN);
|
||||
if ($possiblePattern->length > 0) {
|
||||
$numberDesc->setPossibleNumberPattern($possiblePattern->item(0)->firstChild->nodeValue);
|
||||
}
|
||||
|
||||
$validPattern = $element->getElementsByTagName(self::NATIONAL_NUMBER_PATTERN);
|
||||
if ($validPattern->length > 0) {
|
||||
$numberDesc->setNationalNumberPattern($validPattern->item(0)->firstChild->nodeValue);
|
||||
}
|
||||
|
||||
if (!self::$liteBuild) {
|
||||
$exampleNumber = $element->getElementsByTagName(self::EXAMPLE_NUMBER);
|
||||
if ($exampleNumber->length > 0) {
|
||||
$numberDesc->setExampleNumber($exampleNumber->item(0)->firstChild->nodeValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $numberDesc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $numberType
|
||||
* @return bool
|
||||
*/
|
||||
private static function isValidNumberType($numberType)
|
||||
{
|
||||
return $numberType == self::FIXED_LINE || $numberType == self::MOBILE || $numberType == self::GENERAL_DESC;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $metadataCollection PhoneMetadata[]
|
||||
* @return array
|
||||
*/
|
||||
public static function buildCountryCodeToRegionCodeMap($metadataCollection)
|
||||
{
|
||||
$countryCodeToRegionCodeMap = array();
|
||||
|
||||
foreach ($metadataCollection as $metadata) {
|
||||
$regionCode = $metadata->getId();
|
||||
$countryCode = $metadata->getCountryCode();
|
||||
if (array_key_exists($countryCode, $countryCodeToRegionCodeMap)) {
|
||||
if ($metadata->getMainCountryForCode()) {
|
||||
array_unshift($countryCodeToRegionCodeMap[$countryCode], $regionCode);
|
||||
} else {
|
||||
$countryCodeToRegionCodeMap[$countryCode][] = $regionCode;
|
||||
}
|
||||
} else {
|
||||
// For most countries, there will be only one region code for the country calling code.
|
||||
$listWithRegionCode = array();
|
||||
if ($regionCode != '') { // For alternate formats, there are no region codes at all.
|
||||
$listWithRegionCode[] = $regionCode;
|
||||
}
|
||||
$countryCodeToRegionCodeMap[$countryCode] = $listWithRegionCode;
|
||||
}
|
||||
}
|
||||
|
||||
return $countryCodeToRegionCodeMap;
|
||||
}
|
||||
|
||||
}
|
@@ -1,124 +0,0 @@
|
||||
<?php
|
||||
namespace libphonenumber\buildtools;
|
||||
|
||||
use libphonenumber\PhoneMetadata;
|
||||
|
||||
/**
|
||||
* Tool to convert phone number metadata from the XML format to protocol buffer format.
|
||||
*
|
||||
* @author Davide Mendolia
|
||||
*/
|
||||
class BuildMetadataPHPFromXml
|
||||
{
|
||||
const GENERATION_COMMENT = <<<'EOT'
|
||||
/**
|
||||
* This file is automatically @generated by {@link BuildMetadataPHPFromXml}.
|
||||
* Please don't modify it directly.
|
||||
*/
|
||||
|
||||
|
||||
EOT;
|
||||
const MAP_COMMENT = <<<'EOT'
|
||||
// A mapping from a country code to the region codes which denote the
|
||||
// country/region represented by that country code. In the case of multiple
|
||||
// countries sharing a calling code, such as the NANPA countries, the one
|
||||
// indicated with "isMainCountryForCode" in the metadata should be first.
|
||||
|
||||
EOT;
|
||||
const COUNTRY_CODE_SET_COMMENT =
|
||||
" // A set of all country codes for which data is available.\n";
|
||||
const REGION_CODE_SET_COMMENT =
|
||||
" // A set of all region codes for which data is available.\n";
|
||||
|
||||
public function start($inputFile, $outputDir, $filePrefix, $mappingClass, $mappingClassLocation, $liteBuild)
|
||||
{
|
||||
$savePath = $outputDir . $filePrefix;
|
||||
|
||||
$metadataCollection = BuildMetadataFromXml::buildPhoneMetadataCollection($inputFile, $liteBuild);
|
||||
|
||||
$this->writeMetadataToFile($metadataCollection, $savePath);
|
||||
|
||||
|
||||
$countryCodeToRegionCodeMap = BuildMetadataFromXml::buildCountryCodeToRegionCodeMap($metadataCollection);
|
||||
|
||||
// Sort $countryCodeToRegionCodeMap just to have the regions in order
|
||||
|
||||
ksort($countryCodeToRegionCodeMap);
|
||||
|
||||
$this->writeCountryCallingCodeMappingToFile($countryCodeToRegionCodeMap, $mappingClassLocation, $mappingClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $metadataCollection PhoneMetadata[]
|
||||
* @param $filePrefix
|
||||
*/
|
||||
private function writeMetadataToFile($metadataCollection, $filePrefix)
|
||||
{
|
||||
foreach ($metadataCollection as $metadata) {
|
||||
/** @var $phoneMetadata PhoneMetadata */
|
||||
$regionCode = $metadata->getId();
|
||||
// For non-geographical country calling codes (e.g. +800), use the country calling codes
|
||||
// instead of the region code to form the file name.
|
||||
if ($regionCode === '001' || $regionCode == '') {
|
||||
$regionCode = $metadata->getCountryCode();
|
||||
}
|
||||
|
||||
$data = '<?php' . PHP_EOL . self::GENERATION_COMMENT . PHP_EOL . 'return ' . var_export(
|
||||
$metadata->toArray(),
|
||||
true
|
||||
) . ';' . PHP_EOL;
|
||||
|
||||
file_put_contents($filePrefix . "_" . $regionCode . '.php', $data);
|
||||
}
|
||||
}
|
||||
|
||||
private function writeCountryCallingCodeMappingToFile($countryCodeToRegionCodeMap, $outputDir, $mappingClass)
|
||||
{
|
||||
// Find out whether the countryCodeToRegionCodeMap has any region codes or country
|
||||
// calling codes listed in it.
|
||||
$hasRegionCodes = false;
|
||||
foreach ($countryCodeToRegionCodeMap as $key => $listWithRegionCode) {
|
||||
if (count($listWithRegionCode) > 0) {
|
||||
$hasRegionCodes = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$hasCountryCodes = (count($countryCodeToRegionCodeMap) > 1);
|
||||
|
||||
$variableName = lcfirst($mappingClass);
|
||||
|
||||
$data = '<?php' . PHP_EOL .
|
||||
self::GENERATION_COMMENT . PHP_EOL .
|
||||
"namespace libphonenumber;" . PHP_EOL .
|
||||
"class {$mappingClass} {" . PHP_EOL .
|
||||
PHP_EOL;
|
||||
|
||||
if ($hasRegionCodes && $hasCountryCodes) {
|
||||
$data .= self::MAP_COMMENT . PHP_EOL;
|
||||
$data .= " public static \${$variableName} = " . var_export(
|
||||
$countryCodeToRegionCodeMap,
|
||||
true
|
||||
) . ";" . PHP_EOL;
|
||||
} elseif ($hasCountryCodes) {
|
||||
$data .= self::COUNTRY_CODE_SET_COMMENT . PHP_EOL;
|
||||
$data .= " public static \${$variableName} = " . var_export(
|
||||
array_keys($countryCodeToRegionCodeMap),
|
||||
true
|
||||
) . ";" . PHP_EOL;
|
||||
} else {
|
||||
$data .= self::REGION_CODE_SET_COMMENT . PHP_EOL;
|
||||
$data .= " public static \${$variableName} = " . var_export(
|
||||
$countryCodeToRegionCodeMap[0],
|
||||
true
|
||||
) . ";" . PHP_EOL;
|
||||
}
|
||||
|
||||
$data .= PHP_EOL .
|
||||
"}" . PHP_EOL;
|
||||
|
||||
file_put_contents($outputDir . $mappingClass . '.php', $data);
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -1,42 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace libphonenumber\buildtools\Commands;
|
||||
|
||||
|
||||
use libphonenumber\buildtools\BuildMetadataPHPFromXml;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
class BuildMetadataPHPFromXMLCommand extends Command
|
||||
{
|
||||
protected function configure()
|
||||
{
|
||||
$this->setName('BuildMetadataPHPFromXML');
|
||||
$this->setDescription('Generate phone metadata data files');
|
||||
$this->setDefinition(
|
||||
array(
|
||||
new InputArgument('InputFile', InputArgument::REQUIRED, 'The input file containing phone number metadata in XML format.'),
|
||||
new InputArgument('OutputDirectory', InputArgument::REQUIRED, 'The output source directory to store phone number metadata (one file per region) and the country code to region code mapping file'),
|
||||
new InputArgument('DataPrefix', InputArgument::REQUIRED, 'The start of the filename to store the files (e.g. dataPrefix_GB.php'),
|
||||
new InputArgument('MappingClass', InputArgument::REQUIRED, 'The name of the mapping class generated'),
|
||||
new InputArgument('MappingClassLocation', InputArgument::REQUIRED, 'The directory where the mapping class is stored'),
|
||||
new InputArgument('LiteBuild', InputArgument::OPTIONAL, 'Whether to generate the lite-version of the metadata. When set to true, certain metadata will be omitted. AT this moment, example numbers information is omitted', false),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$build = new BuildMetadataPHPFromXml();
|
||||
$build->start(
|
||||
$input->getArgument('InputFile'),
|
||||
$input->getArgument('OutputDirectory'),
|
||||
$input->getArgument('DataPrefix'),
|
||||
$input->getArgument('MappingClass'),
|
||||
$input->getArgument('MappingClassLocation'),
|
||||
($input->getArgument('LiteBuild') == 'true') ? true : false
|
||||
);
|
||||
}
|
||||
}
|
@@ -1,35 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace libphonenumber\buildtools\Commands;
|
||||
|
||||
|
||||
use libphonenumber\buildtools\GeneratePhonePrefixData;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
class GeneratePhonePrefixDataCommand extends Command
|
||||
{
|
||||
protected function configure()
|
||||
{
|
||||
$this->setName('GeneratePhonePrefixData');
|
||||
$this->setDescription('Generate phone prefix data files');
|
||||
$this->setDefinition(
|
||||
array(
|
||||
new InputArgument('InputDirectory', InputArgument::REQUIRED, 'The input directory containing the locale/region.txt files'),
|
||||
new InputArgument('OutputDirectory', InputArgument::REQUIRED, 'The output source directory'),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$generatePhonePrefixData = new GeneratePhonePrefixData();
|
||||
$generatePhonePrefixData->start(
|
||||
$input->getArgument('InputDirectory'),
|
||||
$input->getArgument('OutputDirectory'),
|
||||
$output
|
||||
);
|
||||
}
|
||||
}
|
@@ -1,30 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace libphonenumber\buildtools\Commands;
|
||||
|
||||
|
||||
use libphonenumber\buildtools\GenerateTimeZonesMapData;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
class GenerateTimeZonesMapDataCommand extends Command
|
||||
{
|
||||
protected function configure()
|
||||
{
|
||||
$this->setName('GenerateTimeZonesMapData');
|
||||
$this->setDescription('Generate time zone data files');
|
||||
$this->setDefinition(
|
||||
array(
|
||||
new InputArgument('InputFile', InputArgument::REQUIRED, 'The input file containing the timezone map data'),
|
||||
new InputArgument('OutputDirectory', InputArgument::REQUIRED, 'The output directory to save the file'),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
new GenerateTimeZonesMapData($input->getArgument('InputFile'), $input->getArgument('OutputDirectory'));
|
||||
}
|
||||
}
|
@@ -1,404 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace libphonenumber\buildtools;
|
||||
|
||||
use Symfony\Component\Console\Helper\ProgressBar;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
class GeneratePhonePrefixData
|
||||
{
|
||||
const NANPA_COUNTRY_CODE = 1;
|
||||
const DATA_FILE_EXTENSION = '.txt';
|
||||
const GENERATION_COMMENT = <<<'EOT'
|
||||
/**
|
||||
* This file is automatically @generated by {@link GeneratePhonePrefixData}.
|
||||
* Please don't modify it directly.
|
||||
*/
|
||||
|
||||
|
||||
EOT;
|
||||
|
||||
public $inputDir;
|
||||
private $filesToIgnore = array('.', '..', '.svn', '.git');
|
||||
private $outputDir;
|
||||
private $englishMaps = array();
|
||||
|
||||
|
||||
public function start($inputDir, $outputDir, OutputInterface $consoleOutput)
|
||||
{
|
||||
$this->inputDir = $inputDir;
|
||||
$this->outputDir = $outputDir;
|
||||
|
||||
$inputOutputMappings = $this->createInputOutputMappings();
|
||||
$availableDataFiles = array();
|
||||
|
||||
$progress = new ProgressBar($consoleOutput, count($inputOutputMappings));
|
||||
|
||||
$progress->start();
|
||||
foreach ($inputOutputMappings as $textFile => $outputFiles) {
|
||||
$mappings = $this->readMappingsFromFile($textFile);
|
||||
|
||||
$language = $this->getLanguageFromTextFile($textFile);
|
||||
|
||||
$this->removeEmptyEnglishMappings($mappings, $language);
|
||||
$this->makeDataFallbackToEnglish($textFile, $mappings);
|
||||
$mappingForFiles = $this->splitMap($mappings, $outputFiles);
|
||||
|
||||
foreach ($mappingForFiles as $outputFile => $value) {
|
||||
$this->writeMappingFile($language, $outputFile, $value);
|
||||
$this->addConfigurationMapping($availableDataFiles, $language, $outputFile);
|
||||
}
|
||||
$progress->advance();
|
||||
}
|
||||
|
||||
$this->writeConfigMap($availableDataFiles);
|
||||
$progress->finish();
|
||||
}
|
||||
|
||||
private function createInputOutputMappings()
|
||||
{
|
||||
$topLevel = scandir($this->inputDir);
|
||||
|
||||
$mappings = array();
|
||||
|
||||
foreach ($topLevel as $languageDirectory) {
|
||||
if (in_array($languageDirectory, $this->filesToIgnore)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$fileLocation = $this->inputDir . DIRECTORY_SEPARATOR . $languageDirectory;
|
||||
|
||||
if (is_dir($fileLocation)) {
|
||||
// Will contain files
|
||||
|
||||
$countryCodeFiles = scandir($fileLocation);
|
||||
|
||||
foreach ($countryCodeFiles as $countryCodeFileName) {
|
||||
if (in_array($countryCodeFileName, $this->filesToIgnore)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
$outputFiles = $this->createOutputFileNames(
|
||||
$countryCodeFileName,
|
||||
$this->getCountryCodeFromTextFileName($countryCodeFileName),
|
||||
$languageDirectory
|
||||
);
|
||||
|
||||
$mappings[$languageDirectory . DIRECTORY_SEPARATOR . $countryCodeFileName] = $outputFiles;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $mappings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used by {@code #createInputOutputMappings()} to generate the list of output binary files
|
||||
* from the provided input text file. For the data files expected to be large (currently only
|
||||
* NANPA is supported), this method generates a list containing one output file for each area
|
||||
* code. Otherwise, a single file is added to the list.
|
||||
*/
|
||||
|
||||
private function createOutputFileNames($file, $countryCode, $language)
|
||||
{
|
||||
$outputFiles = array();
|
||||
|
||||
if ($countryCode == self::NANPA_COUNTRY_CODE) {
|
||||
// Fetch the 4-digit prefixes stored in the file.
|
||||
$phonePrefixes = array();
|
||||
|
||||
$this->parseTextFile(
|
||||
$this->getFilePathFromLanguageAndCountryCode($language, $countryCode),
|
||||
function ($prefix, $location) use (&$phonePrefixes) {
|
||||
$shortPrefix = substr($prefix, 0, 4);
|
||||
if (!in_array($shortPrefix, $phonePrefixes)) {
|
||||
$phonePrefixes[] = $shortPrefix;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
foreach ($phonePrefixes as $prefix) {
|
||||
$outputFiles[] = $this->generateFilename($prefix, $language);
|
||||
}
|
||||
} elseif ($countryCode == 86) {
|
||||
|
||||
/*
|
||||
* Reduce memory usage for China numbers
|
||||
* @see https://github.com/giggsey/libphonenumber-for-php/issues/44
|
||||
*/
|
||||
|
||||
// Fetch the 5-digit prefixes stored in the file.
|
||||
$phonePrefixes = array();
|
||||
|
||||
$this->parseTextFile(
|
||||
$this->getFilePathFromLanguageAndCountryCode($language, $countryCode),
|
||||
function ($prefix, $location) use (&$phonePrefixes) {
|
||||
$shortPrefix = substr($prefix, 0, 5);
|
||||
if (!in_array($shortPrefix, $phonePrefixes)) {
|
||||
$phonePrefixes[] = $shortPrefix;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
foreach ($phonePrefixes as $prefix) {
|
||||
$outputFiles[] = $this->generateFilename($prefix, $language);
|
||||
}
|
||||
} else {
|
||||
$outputFiles[] = $this->generateFilename($countryCode, $language);
|
||||
}
|
||||
|
||||
return $outputFiles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads phone prefix data from the provides file path and invokes the given handler for each
|
||||
* mapping read.
|
||||
*
|
||||
* @param $filePath
|
||||
* @param $handler
|
||||
* @return array
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
private function parseTextFile($filePath, \Closure $handler)
|
||||
{
|
||||
|
||||
if (!file_exists($filePath) || !is_readable($filePath)) {
|
||||
throw new \InvalidArgumentException("File '{$filePath}' does not exist");
|
||||
}
|
||||
|
||||
$data = file($filePath);
|
||||
|
||||
$countryData = array();
|
||||
|
||||
foreach ($data as $line) {
|
||||
// Remove \n
|
||||
$line = str_replace("\n", "", $line);
|
||||
$line = str_replace("\r", "", $line);
|
||||
$line = trim($line);
|
||||
|
||||
if (strlen($line) == 0 || substr($line, 0, 1) == '#') {
|
||||
continue;
|
||||
}
|
||||
if (strpos($line, '|')) {
|
||||
// Valid line
|
||||
$parts = explode('|', $line);
|
||||
|
||||
|
||||
$prefix = $parts[0];
|
||||
$location = $parts[1];
|
||||
|
||||
$handler($prefix, $location);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return $countryData;
|
||||
|
||||
}
|
||||
|
||||
private function getFilePathFromLanguageAndCountryCode($language, $code)
|
||||
{
|
||||
return $this->getFilePath($language . DIRECTORY_SEPARATOR . $code . self::DATA_FILE_EXTENSION);
|
||||
}
|
||||
|
||||
private function getFilePath($fileName)
|
||||
{
|
||||
$path = $this->inputDir . $fileName;
|
||||
|
||||
return $path;
|
||||
}
|
||||
|
||||
private function generateFilename($prefix, $language)
|
||||
{
|
||||
return $language . DIRECTORY_SEPARATOR . $prefix . self::DATA_FILE_EXTENSION;
|
||||
}
|
||||
|
||||
private function getCountryCodeFromTextFileName($countryCodeFileName)
|
||||
{
|
||||
return str_replace(self::DATA_FILE_EXTENSION, '', $countryCodeFileName);
|
||||
}
|
||||
|
||||
private function readMappingsFromFile($inputFile)
|
||||
{
|
||||
$areaCodeMap = array();
|
||||
|
||||
$this->parseTextFile(
|
||||
$this->inputDir . $inputFile,
|
||||
function ($prefix, $location) use (&$areaCodeMap) {
|
||||
$areaCodeMap[$prefix] = $location;
|
||||
}
|
||||
);
|
||||
|
||||
return $areaCodeMap;
|
||||
}
|
||||
|
||||
private function getLanguageFromTextFile($textFile)
|
||||
{
|
||||
$parts = explode(DIRECTORY_SEPARATOR, $textFile);
|
||||
|
||||
return $parts[0];
|
||||
}
|
||||
|
||||
private function removeEmptyEnglishMappings(&$mappings, $language)
|
||||
{
|
||||
if ($language != "en") {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($mappings as $k => $v) {
|
||||
if ($v == "") {
|
||||
unset($mappings[$k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compress the provided mappings according to the English data file if any.
|
||||
* @param string $textFile
|
||||
* @param array $mappings
|
||||
*/
|
||||
private function makeDataFallbackToEnglish($textFile, &$mappings)
|
||||
{
|
||||
$englishPath = $this->getEnglishDataPath($textFile);
|
||||
|
||||
if ($textFile == $englishPath || !file_exists($this->getFilePath($englishPath))) {
|
||||
return;
|
||||
}
|
||||
|
||||
$countryCode = substr($textFile, 3, 2);
|
||||
|
||||
if (!array_key_exists($countryCode, $this->englishMaps)) {
|
||||
$englishMap = $this->readMappingsFromFile($englishPath);
|
||||
|
||||
$this->englishMaps[$countryCode] = $englishMap;
|
||||
}
|
||||
|
||||
$this->compressAccordingToEnglishData($this->englishMaps[$countryCode], $mappings);
|
||||
}
|
||||
|
||||
private function getEnglishDataPath($textFile)
|
||||
{
|
||||
return "en" . DIRECTORY_SEPARATOR . substr($textFile, 3, 2) . self::DATA_FILE_EXTENSION;
|
||||
}
|
||||
|
||||
private function compressAccordingToEnglishData($englishMap, &$nonEnglishMap)
|
||||
{
|
||||
foreach ($nonEnglishMap as $prefix => $value) {
|
||||
|
||||
if (array_key_exists($prefix, $englishMap)) {
|
||||
$englishDescription = $englishMap[$prefix];
|
||||
if ($englishDescription == $value) {
|
||||
if (!$this->hasOverlappingPrefix($prefix, $nonEnglishMap)) {
|
||||
unset($nonEnglishMap[$prefix]);
|
||||
} else {
|
||||
$nonEnglishMap[$prefix] = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function hasOverlappingPrefix($number, $mappings)
|
||||
{
|
||||
while (strlen($number) > 0) {
|
||||
$number = substr($number, 0, -1);
|
||||
|
||||
if (array_key_exists($number, $mappings)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private function splitMap($mappings, $outputFiles)
|
||||
{
|
||||
$mappingForFiles = array();
|
||||
|
||||
foreach ($mappings as $prefix => $location) {
|
||||
$targetFile = null;
|
||||
|
||||
foreach ($outputFiles as $k => $outputFile) {
|
||||
$outputFilePrefix = $this->getPhonePrefixLanguagePairFromFilename($outputFile)->prefix;
|
||||
if (self::startsWith($prefix, $outputFilePrefix)) {
|
||||
$targetFile = $outputFilePrefix;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!array_key_exists($targetFile, $mappingForFiles)) {
|
||||
$mappingForFiles[$targetFile] = array();
|
||||
}
|
||||
$mappingForFiles[$targetFile][$prefix] = $location;
|
||||
}
|
||||
|
||||
return $mappingForFiles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the phone prefix and the language code contained in the provided file name.
|
||||
*/
|
||||
private function getPhonePrefixLanguagePairFromFilename($outputFile)
|
||||
{
|
||||
$parts = explode(DIRECTORY_SEPARATOR, $outputFile);
|
||||
|
||||
$returnObj = new \stdClass();
|
||||
$returnObj->language = $parts[0];
|
||||
|
||||
$returnObj->prefix = $this->getCountryCodeFromTextFileName($parts[1]);
|
||||
|
||||
return $returnObj;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @link http://stackoverflow.com/a/834355/403165
|
||||
* @param $haystack
|
||||
* @param $needle
|
||||
* @return bool
|
||||
*/
|
||||
private static function startsWith($haystack, $needle)
|
||||
{
|
||||
return !strncmp($haystack, $needle, strlen($needle));
|
||||
}
|
||||
|
||||
private function writeMappingFile($language, $outputFile, $data)
|
||||
{
|
||||
|
||||
if (!file_exists($this->outputDir . $language)) {
|
||||
mkdir($this->outputDir . $language);
|
||||
}
|
||||
|
||||
$phpSource = '<?php' . PHP_EOL
|
||||
. self::GENERATION_COMMENT
|
||||
. 'return ' . var_export($data, true) . ';'
|
||||
. PHP_EOL;
|
||||
|
||||
$outputPath = $this->outputDir . $language . DIRECTORY_SEPARATOR . $outputFile . '.php';
|
||||
|
||||
file_put_contents($outputPath, $phpSource);
|
||||
}
|
||||
|
||||
public function addConfigurationMapping(&$availableDataFiles, $language, $prefix)
|
||||
{
|
||||
if (!array_key_exists($language, $availableDataFiles)) {
|
||||
$availableDataFiles[$language] = array();
|
||||
}
|
||||
|
||||
$availableDataFiles[$language][] = $prefix;
|
||||
}
|
||||
|
||||
private function writeConfigMap($availableDataFiles)
|
||||
{
|
||||
$phpSource = '<?php' . PHP_EOL
|
||||
. self::GENERATION_COMMENT
|
||||
. 'return ' . var_export($availableDataFiles, true) . ';'
|
||||
. PHP_EOL;
|
||||
|
||||
$outputPath = $this->outputDir . 'Map.php';
|
||||
|
||||
file_put_contents($outputPath, $phpSource);
|
||||
}
|
||||
}
|
@@ -1,77 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace libphonenumber\buildtools;
|
||||
|
||||
|
||||
use libphonenumber\PhoneNumberToTimeZonesMapper;
|
||||
|
||||
class GenerateTimeZonesMapData
|
||||
{
|
||||
const GENERATION_COMMENT = <<<'EOT'
|
||||
/**
|
||||
* This file is automatically @generated by {@link GeneratePhonePrefixData}.
|
||||
* Please don't modify it directly.
|
||||
*/
|
||||
|
||||
|
||||
EOT;
|
||||
private $inputTextFile;
|
||||
|
||||
public function __construct($inputFile, $outputDir)
|
||||
{
|
||||
$this->inputTextFile = $inputFile;
|
||||
|
||||
if (!is_readable($this->inputTextFile)) {
|
||||
throw new \RuntimeException("The provided input text file does not exist.");
|
||||
}
|
||||
|
||||
$data = $this->parseTextFile();
|
||||
$this->writeMappingFile($outputDir, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads phone prefix data from the provided input stream and returns a SortedMap with the
|
||||
* prefix to time zones mappings.
|
||||
*/
|
||||
private function parseTextFile()
|
||||
{
|
||||
$data = file($this->inputTextFile);
|
||||
|
||||
$timeZoneMap = array();
|
||||
|
||||
foreach ($data as $line) {
|
||||
// Remove \n
|
||||
$line = str_replace("\n", "", $line);
|
||||
$line = str_replace("\r", "", $line);
|
||||
$line = trim($line);
|
||||
|
||||
if (strlen($line) == 0 || substr($line, 0, 1) == '#') {
|
||||
continue;
|
||||
}
|
||||
if (strpos($line, '|')) {
|
||||
// Valid line
|
||||
$parts = explode('|', $line);
|
||||
|
||||
|
||||
$prefix = $parts[0];
|
||||
$timezone = $parts[1];
|
||||
|
||||
$timeZoneMap[$prefix] = $timezone;
|
||||
}
|
||||
}
|
||||
|
||||
return $timeZoneMap;
|
||||
}
|
||||
|
||||
private function writeMappingFile($outputFile, $data)
|
||||
{
|
||||
$phpSource = '<?php' . PHP_EOL
|
||||
. self::GENERATION_COMMENT
|
||||
. 'return ' . var_export($data, true) . ';'
|
||||
. PHP_EOL;
|
||||
|
||||
$outputPath = $outputFile . DIRECTORY_SEPARATOR . PhoneNumberToTimeZonesMapper::MAPPING_DATA_FILE_NAME;
|
||||
|
||||
file_put_contents($outputPath, $phpSource);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user