Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Store metadata in objects instead of arrays #678

Merged
merged 18 commits into from
Mar 19, 2025
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Minor code improvements
giggsey committed Mar 19, 2025

Verified

This commit was signed with the committer’s verified signature.
giggsey Joshua Gigg
commit cd23c94656dfb9eb862c745d4956737434f3b77e
12 changes: 3 additions & 9 deletions src/PhoneNumberMatcher.php
Original file line number Diff line number Diff line change
@@ -364,13 +364,7 @@ protected function extractMatch(string $candidate, int $offset): ?PhoneNumberMat

// Try to come up with a valid match given the entire candidate.
$match = $this->parseAndVerify($candidate, $offset);
if ($match !== null) {
return $match;
}

// If that failed, try to find an "inner match" - there might be a phone number within this
// candidate.
return $this->extractInnerMatch($candidate, $offset);
return $match ?? $this->extractInnerMatch($candidate, $offset);
}

/**
@@ -469,7 +463,7 @@ protected function parseAndVerify(string $candidate, int $offset): ?PhoneNumberM
$number->clearPreferredDomesticCarrierCode();
return new PhoneNumberMatch($offset, $candidate, $number);
}
} catch (NumberParseException $e) {
} catch (NumberParseException) {
// ignore and continue
}
return null;
@@ -749,7 +743,7 @@ public static function isNationalPrefixPresentIfRequired(PhoneNumber $number, Ph
$rawInput = $rawInputCopy;
// Check if we found a national prefix and/or carrier code at the start of the raw input, and
// return the result.
$carrierCode = null;
$carrierCode = '';
return $util->maybeStripNationalPrefixAndCarrierCode($rawInput, $metadata, $carrierCode);
}
return true;
8 changes: 0 additions & 8 deletions src/PhoneNumberToTimeZonesMapper.php
Original file line number Diff line number Diff line change
@@ -24,14 +24,6 @@
class PhoneNumberToTimeZonesMapper
{
public const UNKNOWN_TIMEZONE = 'Etc/Unknown';
/**
* @internal
*/
public const MAPPING_DATA_DIRECTORY = '/timezone/data/';
/**
* @internal
*/
public const MAPPING_DATA_FILE_NAME = 'map_data.php';
protected static ?PhoneNumberToTimeZonesMapper $instance;
/**
* @var string[]
38 changes: 15 additions & 23 deletions src/PhoneNumberUtil.php
Original file line number Diff line number Diff line change
@@ -352,7 +352,7 @@
* This class implements a singleton, so the only constructor is protected.
* @param array<int,string[]> $countryCallingCodeToRegionCodeMap
*/
protected function __construct(MetadataSourceInterface $metadataSource, $countryCallingCodeToRegionCodeMap)
protected function __construct(MetadataSourceInterface $metadataSource, array $countryCallingCodeToRegionCodeMap)
{
$this->metadataSource = $metadataSource;
$this->countryCallingCodeToRegionCodeMap = $countryCallingCodeToRegionCodeMap;
@@ -477,9 +477,8 @@
/**
* Helper method for constructing regular expressions for parsing. Creates an expression that
* captures up to maxLength digits.
* @param int $maxLength
*/
protected static function extnDigits($maxLength): string
protected static function extnDigits(int $maxLength): string
{
return '(' . self::DIGITS . '{1,' . $maxLength . '})';
}
@@ -488,10 +487,8 @@
* Helper initialiser method to create the regular-expression pattern to match extensions.
* Note that there are currently six capturing groups for the extension itself. If this number is
* changed, MaybeStripExtension needs to be updated.
*
* @param bool $forParsing
*/
protected static function createExtnPattern($forParsing): string
protected static function createExtnPattern(bool $forParsing): string
{
// We cap the maximum length of an extension based on the ambiguity of the way the extension is
// prefixed. As per ITU, the officially allowed length for extensions is actually 40, but we
@@ -1385,10 +1382,7 @@
static::initMobileTokenMappings();
}

if (isset(static::$MOBILE_TOKEN_MAPPINGS[(string) $countryCallingCode])) {
return static::$MOBILE_TOKEN_MAPPINGS[(string) $countryCallingCode];
}
return '';
return static::$MOBILE_TOKEN_MAPPINGS[(string) $countryCallingCode] ?? '';
}

/**
@@ -1970,7 +1964,7 @@
$potentialNationalNumber = substr($normalizedNumber, mb_strlen($defaultCountryCodeString));
$generalDesc = $defaultRegionMetadata->getGeneralDesc();
// Don't need the carrier code.
$carrierCode = null;
$carrierCode = '';
$this->maybeStripNationalPrefixAndCarrierCode(
$potentialNationalNumber,
$defaultRegionMetadata,
@@ -2150,7 +2144,7 @@
* @param string $carrierCode a place to insert the carrier code if one is extracted
* @return bool true if a national prefix or carrier code (or both) could be extracted.
*/
public function maybeStripNationalPrefixAndCarrierCode(string &$number, PhoneMetadata $metadata, ?string &$carrierCode): bool
public function maybeStripNationalPrefixAndCarrierCode(string &$number, PhoneMetadata $metadata, string &$carrierCode): bool
{
$numberLength = mb_strlen($number);
$possibleNationalPrefix = $metadata->getNationalPrefixForParsing();
@@ -2183,7 +2177,7 @@
)) {
return false;
}
if ($carrierCode !== null && $numOfGroups > 0 && $prefixMatcher->group($numOfGroups) !== null) {

Check failure on line 2180 in src/PhoneNumberUtil.php

GitHub Actions / PHPStan

Strict comparison using !== between string and null will always evaluate to true.
$carrierCode .= $prefixMatcher->group(1);
}

@@ -2204,7 +2198,7 @@
&& !$this->matcherAPI->matchNationalNumber($transformedNumber, $generalDesc, false)) {
return false;
}
if ($carrierCode !== null && $numOfGroups > 1) {

Check failure on line 2201 in src/PhoneNumberUtil.php

GitHub Actions / PHPStan

Strict comparison using !== between string and null will always evaluate to true.
$carrierCode .= $prefixMatcher->group(1);
}
$number = substr_replace($number, $transformedNumber, 0, mb_strlen($number));
@@ -2983,7 +2977,7 @@
* undesirable.
*
* @param PhoneNumber $number the phone number that we want to validate
* @param string $regionCode the region that we want to validate the phone number for
* @param string|null $regionCode the region that we want to validate the phone number for
* @return bool that indicates whether the number is of a valid pattern
*/
public function isValidNumberForRegion(PhoneNumber $number, ?string $regionCode): bool
@@ -3107,9 +3101,9 @@
* Gets a valid number for the specified region.
*
* @param $regionCode string the region for which an example number is needed
* @return PhoneNumber a valid fixed-line number for the specified region. Returns null when the metadata
* does not contain such information, or the region 001 is passed in. For 001 (representing
* non-geographical numbers), call {@see getExampleNumberForNonGeoEntity} instead.
* @return PhoneNumber|null a valid fixed-line number for the specified region. Returns null when the metadata
* does not contain such information, or the region 001 is passed in. For 001 (representing
* non-geographical numbers), call {@see getExampleNumberForNonGeoEntity} instead.
*/
public function getExampleNumber(string $regionCode): ?PhoneNumber
{
@@ -3165,7 +3159,7 @@
if (!$this->isValidNumber($possiblyValidNumber)) {
return $possiblyValidNumber;
}
} catch (NumberParseException $e) {
} catch (NumberParseException) {
// Shouldn't happen: we have already checked the length, we know example numbers have
// only valid digits, and we know the region code is fine.
}
@@ -3211,7 +3205,7 @@
if ($desc->getExampleNumber() !== '') {
return $this->parse('+' . $countryCallingCode . $desc->getExampleNumber(), static::UNKNOWN_REGION);
}
} catch (NumberParseException $e) {
} catch (NumberParseException) {
// noop
}
}
@@ -3286,7 +3280,7 @@
if ($desc !== null && $desc->hasExampleNumber()) {
return $this->parse('+' . $countryCallingCode . $desc->getExampleNumber(), self::UNKNOWN_REGION);
}
} catch (NumberParseException $e) {
} catch (NumberParseException) {
// noop
}
}
@@ -3335,7 +3329,7 @@
$this->parseHelper($firstNumberIn, null, false, false, $firstNumberProto);
$this->parseHelper($secondNumberIn, null, false, false, $secondNumberProto);
return $this->isNumberMatch($firstNumberProto, $secondNumberProto);
} catch (NumberParseException $e3) {
} catch (NumberParseException) {
// Fall through and return MatchType::NOT_A_NUMBER
}
}
@@ -3345,8 +3339,6 @@
return MatchType::NOT_A_NUMBER;
}
if ($firstNumberIn instanceof PhoneNumber && is_string($secondNumberIn)) {
// First see if the second number has an implicit country calling code, by attempting to parse
// it.
try {
$secondNumberAsProto = $this->parse($secondNumberIn, static::UNKNOWN_REGION);
return $this->isNumberMatch($firstNumberIn, $secondNumberAsProto);
@@ -3371,7 +3363,7 @@
$secondNumberProto = new PhoneNumber();
$this->parseHelper($secondNumberIn, null, false, false, $secondNumberProto);
return $this->isNumberMatch($firstNumberIn, $secondNumberProto);
} catch (NumberParseException $e2) {
} catch (NumberParseException) {
// Fall-through to return NOT_A_NUMBER.
}
}
8 changes: 0 additions & 8 deletions src/ShortNumberInfo.php
Original file line number Diff line number Diff line change
@@ -23,18 +23,10 @@
class ShortNumberInfo
{
protected static ?ShortNumberInfo $instance;
/**
* @var array<string,PhoneMetadata>
*/
protected array $regionToMetadataMap = [];
/**
* @var array<int,string[]>
*/
protected array $countryCallingCodeToRegionCodeMap = [];
/**
* @var array<int,PhoneMetadata>
*/
protected array $countryCodeToNonGeographicalMetadataMap = [];
/**
* @var string[]
*/
10 changes: 5 additions & 5 deletions tests/core/PhoneNumberUtilTest.php
Original file line number Diff line number Diff line change
@@ -2425,23 +2425,23 @@ public function setNationalPrefixTransformRule(string $value): void
$numberToStrip = '34356778';
$strippedNumber = '356778';

$carrierCode = null;
$carrierCode = '';

self::assertTrue(
$this->phoneUtil->maybeStripNationalPrefixAndCarrierCode($numberToStrip, $metadata, $carrierCode)
);
self::assertEquals($strippedNumber, $numberToStrip, 'Should have had national prefix stripped.');
// Retry stripping - now the number should not start with the national prefix, so no more
// stripping should occur.
$carrierCode = null;
$carrierCode = '';
self::assertFalse(
$this->phoneUtil->maybeStripNationalPrefixAndCarrierCode($numberToStrip, $metadata, $carrierCode)
);
self::assertEquals($strippedNumber, $numberToStrip, 'Should have had no change - no national prefix present.');

// Some countries have no national prefix. Repeat test with none specified.
$metadata->setNationalPrefixForParsing('');
$carrierCode = null;
$carrierCode = '';
self::assertFalse(
$this->phoneUtil->maybeStripNationalPrefixAndCarrierCode($numberToStrip, $metadata, $carrierCode)
);
@@ -2451,7 +2451,7 @@ public function setNationalPrefixTransformRule(string $value): void
$metadata->setNationalPrefixForParsing('3');
$numberToStrip = '3123';
$strippedNumber = '3123';
$carrierCode = null;
$carrierCode = '';
self::assertFalse(
$this->phoneUtil->maybeStripNationalPrefixAndCarrierCode($numberToStrip, $metadata, $carrierCode)
);
@@ -2482,7 +2482,7 @@ public function setNationalPrefixTransformRule(string $value): void
$metadata->setNationalPrefixForParsing('0(\\d{2})');
$numberToStrip = '031123';
$transformedNumber = '5315123';
$carrierCode = null;
$carrierCode = '';
self::assertTrue(
$this->phoneUtil->maybeStripNationalPrefixAndCarrierCode($numberToStrip, $metadata, $carrierCode)
);

Unchanged files with check annotations Beta

. '\$1' . '[' . PhoneNumberUtil::VALID_PUNCTUATION . ']*(\$\\d'
. '[' . PhoneNumberUtil::VALID_PUNCTUATION . ']*)*';
self::$initialised = true;

Check warning on line 149 in src/AsYouTypeFormatter.php

GitHub Actions / Mutation tests (8.4, highest)

Escaped Mutant for Mutator "TrueValue": --- Original +++ New @@ @@ self::$emptyMetadata = new PhoneMetadata(); self::$emptyMetadata->setInternationalPrefix('NA'); self::$eligibleFormatPattern = '[' . PhoneNumberUtil::VALID_PUNCTUATION . ']*' . '\$1' . '[' . PhoneNumberUtil::VALID_PUNCTUATION . ']*(\$\d' . '[' . PhoneNumberUtil::VALID_PUNCTUATION . ']*)*'; - self::$initialised = true; + self::$initialised = false; } } /**
}
}
$this->phoneUtil = PhoneNumberUtil::getInstance();
$this->defaultCountry = strtoupper($regionCode);

Check warning on line 163 in src/AsYouTypeFormatter.php

GitHub Actions / Mutation tests (8.4, highest)

Escaped Mutant for Mutator "UnwrapStrToUpper": --- Original +++ New @@ @@ { self::init(); $this->phoneUtil = PhoneNumberUtil::getInstance(); - $this->defaultCountry = strtoupper($regionCode); + $this->defaultCountry = $regionCode; $this->currentMetadata = $this->getMetadataForRegion($this->defaultCountry); $this->defaultMetadata = $this->currentMetadata; }
$this->currentMetadata = $this->getMetadataForRegion($this->defaultCountry);
$this->defaultMetadata = $this->currentMetadata;
}
unset($this->possibleFormats[$key]);
}
$this->ableToFormat = false;
return false;

Check warning on line 211 in src/AsYouTypeFormatter.php

GitHub Actions / Mutation tests (8.4, highest)

Escaped Mutant for Mutator "FalseValue": --- Original +++ New @@ @@ unset($this->possibleFormats[$key]); } $this->ableToFormat = false; - return false; + return true; } private function getAvailableFormats(string $leadingDigits): void {
}
private function getAvailableFormats(string $leadingDigits): void
&& !$format->getNationalPrefixOptionalWhenFormatting()) {
// This number was entered without a national prefix, and this formatting rule requires one,
// so we discard it.
continue;

Check warning on line 247 in src/AsYouTypeFormatter.php

GitHub Actions / Mutation tests (8.4, highest)

Escaped Mutant for Mutator "Continue_": --- Original +++ New @@ @@ continue; } if ($this->extractedNationalPrefix === '' && !$this->isCompleteNumber && !PhoneNumberUtil::formattingRuleHasFirstGroupOnly($format->getNationalPrefixFormattingRule()) && !$format->getNationalPrefixOptionalWhenFormatting()) { - // This number was entered without a national prefix, and this formatting rule requires one, - // so we discard it. - continue; + break; } $eligibleFormatMatcher = new Matcher(self::$eligibleFormatPattern, $format->getFormat()); if ($eligibleFormatMatcher->matches()) {
}
$eligibleFormatMatcher = new Matcher(self::$eligibleFormatPattern, $format->getFormat());
private function narrowDownPossibleFormats(string $leadingDigits): void
{
$indexOfLeadingDigitsPattern = mb_strlen($leadingDigits) - self::$minLeadingDigitsLength;

Check warning on line 261 in src/AsYouTypeFormatter.php

GitHub Actions / Mutation tests (8.4, highest)

Escaped Mutant for Mutator "MBString": --- Original +++ New @@ @@ } private function narrowDownPossibleFormats(string $leadingDigits): void { - $indexOfLeadingDigitsPattern = mb_strlen($leadingDigits) - self::$minLeadingDigitsLength; + $indexOfLeadingDigitsPattern = strlen($leadingDigits) - self::$minLeadingDigitsLength; foreach ($this->possibleFormats as $key => $format) { if ($format->leadingDigitsPatternSize() === 0) { // Keep everything that isn't restricted by leading digits.
foreach ($this->possibleFormats as $key => $format) {
if ($format->leadingDigitsPatternSize() === 0) {
// Keep everything that isn't restricted by leading digits.
continue;

Check warning on line 266 in src/AsYouTypeFormatter.php

GitHub Actions / Mutation tests (8.4, highest)

Escaped Mutant for Mutator "Continue_": --- Original +++ New @@ @@ $indexOfLeadingDigitsPattern = mb_strlen($leadingDigits) - self::$minLeadingDigitsLength; foreach ($this->possibleFormats as $key => $format) { if ($format->leadingDigitsPatternSize() === 0) { - // Keep everything that isn't restricted by leading digits. - continue; + break; } $lastLeadingDigitsPattern = min($indexOfLeadingDigitsPattern, $format->leadingDigitsPatternSize() - 1); $leadingDigitsPattern = $format->getLeadingDigitsPattern($lastLeadingDigitsPattern);
}
$lastLeadingDigitsPattern = min($indexOfLeadingDigitsPattern, $format->leadingDigitsPatternSize() - 1);
$leadingDigitsPattern = $format->getLeadingDigitsPattern($lastLeadingDigitsPattern);
$this->formattingTemplate = '';
$tempTemplate = $this->getFormattingTemplate($numberPattern, $format->getFormat());
if ($tempTemplate !== '') {
$this->formattingTemplate .= $tempTemplate;

Check warning on line 284 in src/AsYouTypeFormatter.php

GitHub Actions / Mutation tests (8.4, highest)

Escaped Mutant for Mutator "Assignment": --- Original +++ New @@ @@ $this->formattingTemplate = ''; $tempTemplate = $this->getFormattingTemplate($numberPattern, $format->getFormat()); if ($tempTemplate !== '') { - $this->formattingTemplate .= $tempTemplate; + $this->formattingTemplate = $tempTemplate; return true; } return false;
return true;
}
return false;
$aPhoneNumber = $m->group();
// No formatting template can be created if the number of digits entered entered so far
// is longer than the maximum the current formatting rule can accommodate.
if (mb_strlen($aPhoneNumber) < mb_strlen($this->nationalNumber)) {

Check warning on line 304 in src/AsYouTypeFormatter.php

GitHub Actions / Mutation tests (8.4, highest)

Escaped Mutant for Mutator "LessThan": --- Original +++ New @@ @@ $aPhoneNumber = $m->group(); // No formatting template can be created if the number of digits entered entered so far // is longer than the maximum the current formatting rule can accommodate. - if (mb_strlen($aPhoneNumber) < mb_strlen($this->nationalNumber)) { + if (mb_strlen($aPhoneNumber) <= mb_strlen($this->nationalNumber)) { return ''; } // Formats the number according to $numberFormat

Check warning on line 304 in src/AsYouTypeFormatter.php

GitHub Actions / Mutation tests (8.4, highest)

Escaped Mutant for Mutator "MBString": --- Original +++ New @@ @@ $aPhoneNumber = $m->group(); // No formatting template can be created if the number of digits entered entered so far // is longer than the maximum the current formatting rule can accommodate. - if (mb_strlen($aPhoneNumber) < mb_strlen($this->nationalNumber)) { + if (strlen($aPhoneNumber) < mb_strlen($this->nationalNumber)) { return ''; } // Formats the number according to $numberFormat

Check warning on line 304 in src/AsYouTypeFormatter.php

GitHub Actions / Mutation tests (8.4, highest)

Escaped Mutant for Mutator "MBString": --- Original +++ New @@ @@ $aPhoneNumber = $m->group(); // No formatting template can be created if the number of digits entered entered so far // is longer than the maximum the current formatting rule can accommodate. - if (mb_strlen($aPhoneNumber) < mb_strlen($this->nationalNumber)) { + if (mb_strlen($aPhoneNumber) < strlen($this->nationalNumber)) { return ''; } // Formats the number according to $numberFormat
return '';
}
// Formats the number according to $numberFormat