Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
"firebase/php-jwt": "^7.0",
"fusonic/opengraph": "^3.1.0",
"gapple/structured-fields": "^2.3",
"giggsey/libphonenumber-for-php-lite": "^9.0.9",
"giggsey/libphonenumber-for-php-lite": "^9.0.36",
"guzzlehttp/guzzle": "^7.15.2",
"icewind/searchdav": "^3.2.0",
"icewind/smb": "^3.8.1",
Expand Down
14 changes: 7 additions & 7 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 7 additions & 7 deletions composer/installed.json
Original file line number Diff line number Diff line change
Expand Up @@ -1147,17 +1147,17 @@
},
{
"name": "giggsey/libphonenumber-for-php-lite",
"version": "9.0.9",
"version_normalized": "9.0.9.0",
"version": "9.0.36",
"version_normalized": "9.0.36.0",
"source": {
"type": "git",
"url": "https://github.com/giggsey/libphonenumber-for-php-lite.git",
"reference": "d7ae8dd1186b54ce1451aec437346dd772321492"
"reference": "f21237b7df458b326cd5b1bac44d64cc7b1dcb2f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/giggsey/libphonenumber-for-php-lite/zipball/d7ae8dd1186b54ce1451aec437346dd772321492",
"reference": "d7ae8dd1186b54ce1451aec437346dd772321492",
"url": "https://api.github.com/repos/giggsey/libphonenumber-for-php-lite/zipball/f21237b7df458b326cd5b1bac44d64cc7b1dcb2f",
"reference": "f21237b7df458b326cd5b1bac44d64cc7b1dcb2f",
"shasum": ""
},
"require": {
Expand All @@ -1170,7 +1170,7 @@
"require-dev": {
"ext-dom": "*",
"friendsofphp/php-cs-fixer": "^3.71",
"infection/infection": "^0.28.0",
"infection/infection": "^0.29|^0.31.0",
"nette/php-generator": "^4.1",
"php-coveralls/php-coveralls": "^2.7",
"phpstan/extension-installer": "^1.4.3",
Expand All @@ -1186,7 +1186,7 @@
"suggest": {
"giggsey/libphonenumber-for-php": "Use libphonenumber-for-php for geocoding, carriers, timezones and matching"
},
"time": "2025-07-08T08:38:23+00:00",
"time": "2026-08-03T07:53:53+00:00",
"type": "library",
"extra": {
"branch-alias": {
Expand Down
6 changes: 3 additions & 3 deletions composer/installed.php
Original file line number Diff line number Diff line change
Expand Up @@ -155,9 +155,9 @@
'dev_requirement' => false,
),
'giggsey/libphonenumber-for-php-lite' => array(
'pretty_version' => '9.0.9',
'version' => '9.0.9.0',
'reference' => 'd7ae8dd1186b54ce1451aec437346dd772321492',
'pretty_version' => '9.0.36',
'version' => '9.0.36.0',
'reference' => 'f21237b7df458b326cd5b1bac44d64cc7b1dcb2f',
'type' => 'library',
'install_path' => __DIR__ . '/../giggsey/libphonenumber-for-php-lite',
'aliases' => array(),
Expand Down
2 changes: 1 addition & 1 deletion giggsey/libphonenumber-for-php-lite/METADATA-VERSION.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@
* For more information, look at the phing tasks in build.xml
* @internal
*/
return 'v9.0.9';
return 'v9.0.36';
10 changes: 10 additions & 0 deletions giggsey/libphonenumber-for-php-lite/qodana.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
####################################################################################################################
# WARNING: Do not store sensitive information in this file, as its contents will be included in the Qodana report. #
####################################################################################################################

version: "1.0"
linter: qodana-php
profile:
name: qodana.recommended
include:
- name: CheckDependencyLicenses
2 changes: 1 addition & 1 deletion giggsey/libphonenumber-for-php-lite/src/PhoneNumber.php
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@ public function unserialize($data): void
}

/**
* @param array{int,string,string,bool|null,int,string|null,CountryCodeSource|null,string|null} $data
* @param array{int,string,string,bool|null,int,string|null,CountryCodeSource|int|null,string|null} $data
*/
public function __unserialize(array $data): void
{
Expand Down
80 changes: 60 additions & 20 deletions giggsey/libphonenumber-for-php-lite/src/PhoneNumberUtil.php
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ class PhoneNumberUtil
protected const UNWANTED_END_CHAR_PATTERN = '[^' . self::DIGITS . self::VALID_ALPHA . '#]+$';
protected const DIALLABLE_CHAR_MAPPINGS = self::ASCII_DIGIT_MAPPINGS
+ [self::PLUS_SIGN => self::PLUS_SIGN]
+ ['*' => '*', '#' => '#'];
+ ['*' => '*', '#' => '#'];

protected static ?PhoneNumberUtil $instance;

Expand Down Expand Up @@ -841,6 +841,11 @@ protected function isValidRegionCode(?string $regionCode): bool
public function getRegionCodeForNumber(PhoneNumber $number): ?string
{
$countryCode = $number->getCountryCode();

if ($countryCode === null) {
return null;
}

if (!isset($this->countryCallingCodeToRegionCodeMap[$countryCode])) {
return null;
}
Expand Down Expand Up @@ -890,9 +895,11 @@ protected function getRegionCodeForNumberFromRegionList(PhoneNumber $number, arr
public function getNationalSignificantNumber(PhoneNumber $number): string
{
// If leading zero(s) have been set, we prefix this now. Note this is not a national prefix.
// Defensively cap the number of leading zeros to avoid OOM from malicious input.
$nationalNumber = '';
if ($number->isItalianLeadingZero() && $number->getNumberOfLeadingZeros() > 0) {
$zeros = str_repeat('0', $number->getNumberOfLeadingZeros());
$numberOfLeadingZeros = min($number->getNumberOfLeadingZeros(), 10);
$zeros = str_repeat('0', $numberOfLeadingZeros);
$nationalNumber .= $zeros;
}
$nationalNumber .= $number->getNationalNumber();
Expand Down Expand Up @@ -1112,13 +1119,17 @@ public function getLengthOfNationalDestinationCode(PhoneNumber $number): int
public function format(PhoneNumber $number, PhoneNumberFormat $numberFormat): string
{
if ($number->getNationalNumber() === '0' && $number->hasRawInput()) {
// Unparseable numbers that kept their raw input just use that.
// This is the only case where a number can be formatted as E164 without a
// leading '+' symbol (but the original number wasn't parseable anyway).
// TODO: Consider removing the 'if' above so that unparseable
// strings without raw input format to the empty string instead of "+00"
// Unparseable numbers that kept their raw input just use that, unless default country was
// specified and the format is E164. In that case, we prepend the raw input with the country
// code
$rawInput = $number->getRawInput();
if ($rawInput !== '') {

if ($rawInput !== '' && $number->hasCountryCode() && $number->getCountryCodeSource() === CountryCodeSource::FROM_DEFAULT_COUNTRY && $numberFormat === PhoneNumberFormat::E164) {
$countryCallingCode = $number->getCountryCode();
$formattedNumber = $rawInput;
$this->prefixNumberWithCountryCallingCode($countryCallingCode, $numberFormat, $formattedNumber);
return $formattedNumber;
} elseif ($rawInput !== '' || !$number->hasCountryCode()) {
return $rawInput;
}
}
Expand Down Expand Up @@ -1322,6 +1333,30 @@ public static function getCountryMobileToken(int $countryCallingCode): string
return static::MOBILE_TOKEN_MAPPINGS[$countryCallingCode] ?? '';
}

/**
* Checks whether the supplied string contains at least three ASCII letters.
*/
private function hasAtLeastThreeAlphaChars(string $number): bool
{
$alphaCount = 0;
$length = strlen($number);

for ($i = 0; $i < $length; $i++) {
$character = ord($number[$i]);

if (
($character >= 65 && $character <= 90)
|| ($character >= 97 && $character <= 122)
) {
if (++$alphaCount >= 3) {
return true;
}
}
}

return false;
}

/**
* Checks if the number is a valid vanity (alpha) number such as 800 MICROSOFT. A valid vanity
* number will start with at least 3 digits and will have three or more alpha characters. This
Expand All @@ -1334,12 +1369,18 @@ public static function getCountryMobileToken(int $countryCallingCode): string
*/
public function isAlphaNumber(string $number): bool
{
if (strlen($number) > static::MAX_INPUT_STRING_LENGTH) {
return false;
}

if (!static::isViablePhoneNumber($number)) {
// Number is too short, or doesn't match the basic phone number pattern.
// Number is too short, or doesn't match the basic phone-number pattern.
return false;
}

$this->maybeStripExtension($number);
return preg_match('/' . static::VALID_ALPHA_PHONE_PATTERN . '/' . static::REGEX_FLAGS, $number) === 1;

return $this->hasAtLeastThreeAlphaChars($number);
}

/**
Expand Down Expand Up @@ -2682,7 +2723,9 @@ public function isNANPACountry(string $regionCode): bool
*/
public function formatInOriginalFormat(PhoneNumber $number, string $regionCallingFrom): string
{
if ($number->hasRawInput() && !$this->hasFormattingPatternForNumber($number)) {
$formatRule = $this->getFormattingPatternForNumber($number);

if ($number->hasRawInput() && $formatRule === null) {
// 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();
Expand Down Expand Up @@ -2726,11 +2769,6 @@ public function formatInOriginalFormat(PhoneNumber $number, string $regionCallin
$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).
Expand Down Expand Up @@ -2777,17 +2815,19 @@ public function formatInOriginalFormat(PhoneNumber $number, string $regionCallin
return $formattedNumber;
}

protected function hasFormattingPatternForNumber(PhoneNumber $number): bool
/**
* Called chooseFormattingPatternForNumber in libphonenumber
*/
protected function getFormattingPatternForNumber(PhoneNumber $number): ?NumberFormat
{
$countryCallingCode = $number->getCountryCode();
$phoneNumberRegion = $this->getRegionCodeForCountryCode($countryCallingCode);
$metadata = $this->getMetadataForRegionOrCallingCode($countryCallingCode, $phoneNumberRegion);
if ($metadata === null) {
return false;
return null;
}
$nationalNumber = $this->getNationalSignificantNumber($number);
$formatRule = $this->chooseFormattingPatternForNumber($metadata->numberFormats(), $nationalNumber);
return $formatRule !== null;
return $this->chooseFormattingPatternForNumber($metadata->numberFormats(), $nationalNumber);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public function __construct()
->setNationalNumberPattern('[13]\d{6}(?:\d{2,5})?|[19]\d{7}|(?:[25]\d\d|4)\d{7}(?:\d{2})?')
->setPossibleLength([7, 8, 9, 10, 11, 12]);
$this->mobile = (new PhoneNumberDesc())
->setNationalNumberPattern('342\d{4}|(?:337|49)\d{6}|(?:3(?:2|47|7\d{3})|50\d{3})\d{7}')
->setNationalNumberPattern('342\d{4}|(?:337|49)\d{6}|(?:3(?:2|47|7\d{3})|5(?:0\d{3}|2[0-2]))\d{7}')
->setExampleNumber('3421234')
->setPossibleLength([7, 8, 9, 10, 12]);
$this->premiumRate = PhoneNumberDesc::empty();
Expand Down Expand Up @@ -65,7 +65,7 @@ public function __construct()
(new NumberFormat())
->setPattern('(\d{2})(\d{4})(\d{4})')
->setFormat('$1 $2 $3')
->setLeadingDigitsPattern(['10|23|3(?:[15]|4[57])|4|51'])
->setLeadingDigitsPattern(['10|23|3(?:[15]|4[57])|4|5[12]'])
->setNationalPrefixOptionalWhenFormatting(false),
(new NumberFormat())
->setPattern('(\d{3})(\d{4})(\d{4})')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,15 @@ class PhoneNumberMetadata_AC extends PhoneMetadata
public function __construct()
{
$this->generalDesc = (new PhoneNumberDesc())
->setNationalNumberPattern('(?:[01589]\d|[46])\d{4}')
->setNationalNumberPattern('(?:[01589]\d|[2-467])\d{4}')
->setPossibleLength([5, 6]);
$this->mobile = (new PhoneNumberDesc())
->setNationalNumberPattern('4\d{4}')
->setNationalNumberPattern('[2-47]\d{4}')
->setExampleNumber('40123')
->setPossibleLength([5]);
$this->premiumRate = PhoneNumberDesc::empty();
$this->fixedLine = (new PhoneNumberDesc())
->setNationalNumberPattern('6[2-467]\d{3}')
->setNationalNumberPattern('6\d{4}')
->setExampleNumber('62889')
->setPossibleLength([5]);
$this->tollFree = PhoneNumberDesc::empty();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public function __construct()
->setNationalNumberPattern('(?:[4-7]\d|9[0-689])\d{7}|800\d{2,9}|[2-4679]\d{7}')
->setPossibleLength([5, 6, 7, 8, 9, 10, 11, 12]);
$this->mobile = (new PhoneNumberDesc())
->setNationalNumberPattern('5[024-68]\d{7}')
->setNationalNumberPattern('5[02-68]\d{7}')
->setExampleNumber('501234567')
->setPossibleLength([9]);
$this->premiumRate = (new PhoneNumberDesc())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public function __construct()
->setExampleNumber('8002123456');
$this->sharedCost = PhoneNumberDesc::empty();
$this->personalNumber = (new PhoneNumberDesc())
->setNationalNumberPattern('52(?:3(?:[2-46-9][02-9]\d|5(?:[02-46-9]\d|5[0-46-9]))|4(?:[2-478][02-9]\d|5(?:[034]\d|2[024-9]|5[0-46-9])|6(?:0[1-9]|[2-9]\d)|9(?:[05-9]\d|2[0-5]|49)))\d{4}|52[34][2-9]1[02-9]\d{4}|5(?:00|2[125-9]|33|44|66|77|88)[2-9]\d{6}')
->setNationalNumberPattern('52(?:3(?:[2-46-9][02-9]\d|5(?:[02-46-9]\d|5[0-46-9]))|4(?:[2-478][02-9]\d|5(?:[034]\d|2[024-9]|5[0-46-9])|6(?:0[1-9]|[2-9]\d)|9(?:[05-9]\d|2[0-5]|49)))\d{4}|52[34][2-9]1[02-9]\d{4}|5(?:00|2[125-9]|3[23]|44|66|77|88)[2-9]\d{6}')
->setExampleNumber('5002345678');
$this->voip = (new PhoneNumberDesc())
->setNationalNumberPattern('26848[01]\d{4}')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public function __construct()
->setPossibleLengthLocalOnly([7])
->setPossibleLength([10]);
$this->mobile = (new PhoneNumberDesc())
->setNationalNumberPattern('264(?:235|4(?:69|76)|5(?:3[6-9]|8[1-4])|7(?:29|72))\d{4}')
->setNationalNumberPattern('264(?:235|4(?:69|7[67])|5(?:3[6-9]|8[1-4])|7(?:29|72))\d{4}')
->setExampleNumber('2642351234')
->setPossibleLengthLocalOnly([7]);
$this->premiumRate = (new PhoneNumberDesc())
Expand All @@ -51,7 +51,7 @@ public function __construct()
->setExampleNumber('8002123456');
$this->sharedCost = PhoneNumberDesc::empty();
$this->personalNumber = (new PhoneNumberDesc())
->setNationalNumberPattern('52(?:3(?:[2-46-9][02-9]\d|5(?:[02-46-9]\d|5[0-46-9]))|4(?:[2-478][02-9]\d|5(?:[034]\d|2[024-9]|5[0-46-9])|6(?:0[1-9]|[2-9]\d)|9(?:[05-9]\d|2[0-5]|49)))\d{4}|52[34][2-9]1[02-9]\d{4}|5(?:00|2[125-9]|33|44|66|77|88)[2-9]\d{6}')
->setNationalNumberPattern('52(?:3(?:[2-46-9][02-9]\d|5(?:[02-46-9]\d|5[0-46-9]))|4(?:[2-478][02-9]\d|5(?:[034]\d|2[024-9]|5[0-46-9])|6(?:0[1-9]|[2-9]\d)|9(?:[05-9]\d|2[0-5]|49)))\d{4}|52[34][2-9]1[02-9]\d{4}|5(?:00|2[125-9]|3[23]|44|66|77|88)[2-9]\d{6}')
->setExampleNumber('5002345678');
$this->voip = PhoneNumberDesc::empty();
$this->pager = (new PhoneNumberDesc())
Expand Down
Loading