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

Allow a range of different potential currency codes in the currency matcher regexp #3373

Merged
merged 2 commits into from
Feb 17, 2023
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
16 changes: 12 additions & 4 deletions src/PhpSpreadsheet/Calculation/Engine/FormattedNumber.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ class FormattedNumber

private const STRING_REGEXP_PERCENT = '~^(?:(?: *(?<PrefixedSign>[-+])? *\% *(?<PrefixedSign2>[-+])? *(?<PrefixedValue>[0-9]+\.?[0-9*]*(?:E[-+]?[0-9]*)?) *)|(?: *(?<PostfixedSign>[-+])? *(?<PostfixedValue>[0-9]+\.?[0-9]*(?:E[-+]?[0-9]*)?) *\% *))$~i';

// preg_quoted string for major currency symbols, with a %s for locale currency
private const CURRENCY_CONVERSION_LIST = '\$€£¥%s';

private const STRING_CONVERSION_LIST = [
[self::class, 'convertToNumberIfNumeric'],
[self::class, 'convertToNumberIfFraction'],
Expand Down Expand Up @@ -106,13 +109,11 @@ public static function convertToNumberIfPercent(string &$operand): bool
*/
public static function convertToNumberIfCurrency(string &$operand): bool
{
$quotedCurrencyCode = preg_quote(StringHelper::getCurrencyCode());

$currencyRegexp = self::currencyMatcherRegexp();
$value = preg_replace('/(\d),(\d)/u', '$1$2', $operand);
$regExp = '~^(?:(?: *(?<PrefixedSign>[-+])? *' . $quotedCurrencyCode . ' *(?<PrefixedSign2>[-+])? *(?<PrefixedValue>[0-9]+\.?[0-9*]*(?:E[-+]?[0-9]*)?) *)|(?: *(?<PostfixedSign>[-+])? *(?<PostfixedValue>[0-9]+\.?[0-9]*(?:E[-+]?[0-9]*)?) *' . $quotedCurrencyCode . ' *))$~ui';

$match = [];
if ($value !== null && preg_match($regExp, $value, $match, PREG_UNMATCHED_AS_NULL)) {
if ($value !== null && preg_match($currencyRegexp, $value, $match, PREG_UNMATCHED_AS_NULL)) {
//Determine the sign
$sign = ($match['PrefixedSign'] ?? $match['PrefixedSign2'] ?? $match['PostfixedSign']) ?? '';
//Cast to a float
Expand All @@ -123,4 +124,11 @@ public static function convertToNumberIfCurrency(string &$operand): bool

return false;
}

public static function currencyMatcherRegexp(): string
{
$quotedCurrencyCode = sprintf(self::CURRENCY_CONVERSION_LIST, preg_quote(StringHelper::getCurrencyCode()));

return '~^(?:(?: *(?<PrefixedSign>[-+])? *(?<PrefixedCurrency>[' . $quotedCurrencyCode . ']) *(?<PrefixedSign2>[-+])? *(?<PrefixedValue>[0-9]+\.?[0-9*]*(?:E[-+]?[0-9]*)?) *)|(?: *(?<PostfixedSign>[-+])? *(?<PostfixedValue>[0-9]+\.?[0-9]*(?:E[-+]?[0-9]*)?) *(?<PostCurrency>[' . $quotedCurrencyCode . ']) *))$~ui';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,11 @@ public function providerCurrencies(): array
'basic_postfix_scientific_currency_with_spaces' => ['2000000', "2E6 {$currencyCode}"],

'high_value_currency_with_thousands_separator' => ['2750000', "+{$currencyCode} 2,750,000"],

'explicit dollar' => ['2.75', '$2.75'],
'explicit euro' => ['2.75', '2.75€'],
'explicit pound sterling' => ['2.75', '£2.75'],
'explicit yen' => ['275', '¥275'],
];
}
}