From 90d52eb3fde6da05e8b0c7e38d4bfde79c2d7f2a Mon Sep 17 00:00:00 2001 From: George Mponos Date: Wed, 5 Dec 2018 20:59:01 +0200 Subject: [PATCH 01/13] Made all the parsers use the same code for parsing decimals proving that most probably a trait will be useful --- src/Parser/BitcoinMoneyParser.php | 46 ++++++++++++++++++++++------ src/Parser/IntlMoneyParser.php | 51 +++++++++++++++++++++---------- 2 files changed, 71 insertions(+), 26 deletions(-) diff --git a/src/Parser/BitcoinMoneyParser.php b/src/Parser/BitcoinMoneyParser.php index e6671724..89cedf65 100644 --- a/src/Parser/BitcoinMoneyParser.php +++ b/src/Parser/BitcoinMoneyParser.php @@ -7,6 +7,7 @@ use Money\Exception\ParserException; use Money\Money; use Money\MoneyParser; +use Money\Number; /** * Parses Bitcoin currency to Money. @@ -15,6 +16,8 @@ */ final class BitcoinMoneyParser implements MoneyParser { + const DECIMAL_PATTERN = '/^(?P-)?(?P0|[1-9]\d*)?\.?(?P\d+)?$/'; + /** * @var int */ @@ -33,7 +36,7 @@ public function __construct($fractionDigits) */ public function parse($money, $forceCurrency = null) { - if (is_string($money) === false) { + if (!is_string($money)) { throw new ParserException('Formatted raw money should be string, e.g. $1.00'); } @@ -41,27 +44,50 @@ public function parse($money, $forceCurrency = null) throw new ParserException('Value cannot be parsed as Bitcoin'); } + $currency = new Currency(BitcoinCurrencies::CODE); + $decimal = str_replace(BitcoinCurrencies::SYMBOL, '', $money); - $decimalSeparator = strpos($decimal, '.'); - if (false !== $decimalSeparator) { - $lengthDecimal = strlen($decimal); - $decimal = str_replace('.', '', $decimal); - $decimal .= str_pad('', ($lengthDecimal - $decimalSeparator - $this->fractionDigits - 1) * -1, '0'); + $subunit = $this->fractionDigits; + if (!preg_match(self::DECIMAL_PATTERN, $decimal, $matches) || !isset($matches['digits'])) { + throw new ParserException(sprintf( + 'Cannot parse "%s" to Money.', + $decimal + )); + } + + $negative = isset($matches['sign']) && $matches['sign'] === '-'; + + $decimal = $matches['digits']; + + if ($negative) { + $decimal = '-'.$decimal; + } + + if (isset($matches['fraction'])) { + $fractionDigits = strlen($matches['fraction']); + $decimal .= $matches['fraction']; + $decimal = Number::roundMoneyValue($decimal, $subunit, $fractionDigits); + + if ($fractionDigits > $subunit) { + $decimal = substr($decimal, 0, $subunit - $fractionDigits); + } elseif ($fractionDigits < $subunit) { + $decimal .= str_pad('', $subunit - $fractionDigits, '0'); + } } else { - $decimal .= str_pad('', $this->fractionDigits, '0'); + $decimal .= str_pad('', $subunit, '0'); } - if (substr($decimal, 0, 1) === '-') { + if ($negative) { $decimal = '-'.ltrim(substr($decimal, 1), '0'); } else { $decimal = ltrim($decimal, '0'); } - if ('' === $decimal) { + if ($decimal === '' || $decimal === '-') { $decimal = '0'; } - return new Money($decimal, new Currency(BitcoinCurrencies::CODE)); + return new Money($decimal, $currency); } } diff --git a/src/Parser/IntlMoneyParser.php b/src/Parser/IntlMoneyParser.php index 29339c5c..f159374f 100644 --- a/src/Parser/IntlMoneyParser.php +++ b/src/Parser/IntlMoneyParser.php @@ -16,6 +16,8 @@ */ final class IntlMoneyParser implements MoneyParser { + const DECIMAL_PATTERN = '/^(?P-)?(?P0|[1-9]\d*)?\.?(?P\d+)?$/'; + /** * @var \NumberFormatter */ @@ -56,31 +58,48 @@ public function parse($money, $forceCurrency = null) if (null !== $forceCurrency) { $currency = $forceCurrency; + + /* + * This conversion is only required whilst currency can be either a string or a + * Currency object. + */ + if (!$currency instanceof Currency) { + @trigger_error('Passing a currency as string is deprecated since 3.1 and will be removed in 4.0. Please pass a '.Currency::class.' instance instead.', E_USER_DEPRECATED); + $currency = new Currency($currency); + } } else { $currency = new Currency($currency); } - /* - * This conversion is only required whilst currency can be either a string or a - * Currency object. - */ - if (!$currency instanceof Currency) { - @trigger_error('Passing a currency as string is deprecated since 3.1 and will be removed in 4.0. Please pass a '.Currency::class.' instance instead.', E_USER_DEPRECATED); - $currency = new Currency($currency); + $decimal = trim((string) $decimal); + if ($decimal === '') { + return new Money(0, $currency); } - $decimal = (string) $decimal; $subunit = $this->currencies->subunitFor($currency); - $decimalPosition = strpos($decimal, '.'); - if (false !== $decimalPosition) { - $decimalLength = strlen($decimal); - $fractionDigits = $decimalLength - $decimalPosition - 1; - $decimal = str_replace('.', '', $decimal); + if (!preg_match(self::DECIMAL_PATTERN, $decimal, $matches) || !isset($matches['digits'])) { + throw new ParserException(sprintf( + 'Cannot parse "%s" to Money.', + $decimal + )); + } + + $negative = isset($matches['sign']) && $matches['sign'] === '-'; + + $decimal = $matches['digits']; + + if ($negative) { + $decimal = '-'.$decimal; + } + + if (isset($matches['fraction'])) { + $fractionDigits = strlen($matches['fraction']); + $decimal .= $matches['fraction']; $decimal = Number::roundMoneyValue($decimal, $subunit, $fractionDigits); if ($fractionDigits > $subunit) { - $decimal = substr($decimal, 0, $decimalPosition + $subunit); + $decimal = substr($decimal, 0, $subunit - $fractionDigits); } elseif ($fractionDigits < $subunit) { $decimal .= str_pad('', $subunit - $fractionDigits, '0'); } @@ -88,13 +107,13 @@ public function parse($money, $forceCurrency = null) $decimal .= str_pad('', $subunit, '0'); } - if ('-' === $decimal[0]) { + if ($negative) { $decimal = '-'.ltrim(substr($decimal, 1), '0'); } else { $decimal = ltrim($decimal, '0'); } - if ('' === $decimal) { + if ($decimal === '' || $decimal === '-') { $decimal = '0'; } From 937ee7f614c0f658c4a05d65eaaec1f60d7632b5 Mon Sep 17 00:00:00 2001 From: George Mponos Date: Wed, 5 Dec 2018 21:33:44 +0200 Subject: [PATCH 02/13] Use trait for decimal parser --- src/Parser/DecimalMoneyParser.php | 46 +++---------------------- src/Parser/DecimalParserTrait.php | 56 +++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 42 deletions(-) create mode 100644 src/Parser/DecimalParserTrait.php diff --git a/src/Parser/DecimalMoneyParser.php b/src/Parser/DecimalMoneyParser.php index c6a133c4..19cd2bc3 100644 --- a/src/Parser/DecimalMoneyParser.php +++ b/src/Parser/DecimalMoneyParser.php @@ -7,7 +7,6 @@ use Money\Exception\ParserException; use Money\Money; use Money\MoneyParser; -use Money\Number; /** * Parses a decimal string into a Money object. @@ -16,6 +15,8 @@ */ final class DecimalMoneyParser implements MoneyParser { + use DecimalParserTrait; + const DECIMAL_PATTERN = '/^(?P-)?(?P0|[1-9]\d*)?\.?(?P\d+)?$/'; /** @@ -52,7 +53,7 @@ public function parse($money, $forceCurrency = null) */ $currency = $forceCurrency; if (!$currency instanceof Currency) { - @trigger_error('Passing a currency as string is deprecated since 3.1 and will be removed in 4.0. Please pass a '.Currency::class.' instance instead.', E_USER_DEPRECATED); + @trigger_error('Passing a currency as string is deprecated since 3.1 and will be removed in 4.0. Please pass a ' . Currency::class . ' instance instead.', E_USER_DEPRECATED); $currency = new Currency($currency); } @@ -64,45 +65,6 @@ public function parse($money, $forceCurrency = null) $subunit = $this->currencies->subunitFor($currency); - if (!preg_match(self::DECIMAL_PATTERN, $decimal, $matches) || !isset($matches['digits'])) { - throw new ParserException(sprintf( - 'Cannot parse "%s" to Money.', - $decimal - )); - } - - $negative = isset($matches['sign']) && $matches['sign'] === '-'; - - $decimal = $matches['digits']; - - if ($negative) { - $decimal = '-'.$decimal; - } - - if (isset($matches['fraction'])) { - $fractionDigits = strlen($matches['fraction']); - $decimal .= $matches['fraction']; - $decimal = Number::roundMoneyValue($decimal, $subunit, $fractionDigits); - - if ($fractionDigits > $subunit) { - $decimal = substr($decimal, 0, $subunit - $fractionDigits); - } elseif ($fractionDigits < $subunit) { - $decimal .= str_pad('', $subunit - $fractionDigits, '0'); - } - } else { - $decimal .= str_pad('', $subunit, '0'); - } - - if ($negative) { - $decimal = '-'.ltrim(substr($decimal, 1), '0'); - } else { - $decimal = ltrim($decimal, '0'); - } - - if ($decimal === '' || $decimal === '-') { - $decimal = '0'; - } - - return new Money($decimal, $currency); + return $this->parseDecimal($decimal, $subunit, $currency); } } diff --git a/src/Parser/DecimalParserTrait.php b/src/Parser/DecimalParserTrait.php new file mode 100644 index 00000000..4551d5e2 --- /dev/null +++ b/src/Parser/DecimalParserTrait.php @@ -0,0 +1,56 @@ +-)?(?P0|[1-9]\d*)?\.?(?P\d+)?$/'; + + protected function parseDecimal($decimal, $subunit, $currency) + { + if (!preg_match(self::$decimalPattern, $decimal, $matches) || !isset($matches['digits'])) { + throw new ParserException(sprintf( + 'Cannot parse "%s" to Money.', + $decimal + )); + } + + $negative = isset($matches['sign']) && $matches['sign'] === '-'; + + $decimal = $matches['digits']; + + if ($negative) { + $decimal = '-' . $decimal; + } + + if (isset($matches['fraction'])) { + $fractionDigits = strlen($matches['fraction']); + $decimal .= $matches['fraction']; + $decimal = Number::roundMoneyValue($decimal, $subunit, $fractionDigits); + + if ($fractionDigits > $subunit) { + $decimal = substr($decimal, 0, $subunit - $fractionDigits); + } elseif ($fractionDigits < $subunit) { + $decimal .= str_pad('', $subunit - $fractionDigits, '0'); + } + } else { + $decimal .= str_pad('', $subunit, '0'); + } + + if ($negative) { + $decimal = '-' . ltrim(substr($decimal, 1), '0'); + } else { + $decimal = ltrim($decimal, '0'); + } + + if ($decimal === '' || $decimal === '-') { + $decimal = '0'; + } + + return new Money($decimal, $currency); + } +} From 0da50478be608296c2c9aad0d23b71d3f0a68d9e Mon Sep 17 00:00:00 2001 From: George Mponos Date: Wed, 5 Dec 2018 21:47:21 +0200 Subject: [PATCH 03/13] Use trait for parsing decimals --- src/Parser/BitcoinMoneyParser.php | 45 ++------------------------- src/Parser/DecimalMoneyParser.php | 13 ++------ src/Parser/DecimalParserTrait.php | 12 ++++++-- src/Parser/IntlMoneyParser.php | 51 ++----------------------------- 4 files changed, 16 insertions(+), 105 deletions(-) diff --git a/src/Parser/BitcoinMoneyParser.php b/src/Parser/BitcoinMoneyParser.php index 89cedf65..54290848 100644 --- a/src/Parser/BitcoinMoneyParser.php +++ b/src/Parser/BitcoinMoneyParser.php @@ -5,9 +5,7 @@ use Money\Currencies\BitcoinCurrencies; use Money\Currency; use Money\Exception\ParserException; -use Money\Money; use Money\MoneyParser; -use Money\Number; /** * Parses Bitcoin currency to Money. @@ -16,7 +14,7 @@ */ final class BitcoinMoneyParser implements MoneyParser { - const DECIMAL_PATTERN = '/^(?P-)?(?P0|[1-9]\d*)?\.?(?P\d+)?$/'; + use DecimalParserTrait; /** * @var int @@ -49,45 +47,6 @@ public function parse($money, $forceCurrency = null) $decimal = str_replace(BitcoinCurrencies::SYMBOL, '', $money); $subunit = $this->fractionDigits; - if (!preg_match(self::DECIMAL_PATTERN, $decimal, $matches) || !isset($matches['digits'])) { - throw new ParserException(sprintf( - 'Cannot parse "%s" to Money.', - $decimal - )); - } - - $negative = isset($matches['sign']) && $matches['sign'] === '-'; - - $decimal = $matches['digits']; - - if ($negative) { - $decimal = '-'.$decimal; - } - - if (isset($matches['fraction'])) { - $fractionDigits = strlen($matches['fraction']); - $decimal .= $matches['fraction']; - $decimal = Number::roundMoneyValue($decimal, $subunit, $fractionDigits); - - if ($fractionDigits > $subunit) { - $decimal = substr($decimal, 0, $subunit - $fractionDigits); - } elseif ($fractionDigits < $subunit) { - $decimal .= str_pad('', $subunit - $fractionDigits, '0'); - } - } else { - $decimal .= str_pad('', $subunit, '0'); - } - - if ($negative) { - $decimal = '-'.ltrim(substr($decimal, 1), '0'); - } else { - $decimal = ltrim($decimal, '0'); - } - - if ($decimal === '' || $decimal === '-') { - $decimal = '0'; - } - - return new Money($decimal, $currency); + $this->parseDecimal($decimal, $subunit, $currency); } } diff --git a/src/Parser/DecimalMoneyParser.php b/src/Parser/DecimalMoneyParser.php index 19cd2bc3..4204b2f0 100644 --- a/src/Parser/DecimalMoneyParser.php +++ b/src/Parser/DecimalMoneyParser.php @@ -5,7 +5,6 @@ use Money\Currencies; use Money\Currency; use Money\Exception\ParserException; -use Money\Money; use Money\MoneyParser; /** @@ -17,8 +16,6 @@ final class DecimalMoneyParser implements MoneyParser { use DecimalParserTrait; - const DECIMAL_PATTERN = '/^(?P-)?(?P0|[1-9]\d*)?\.?(?P\d+)?$/'; - /** * @var Currencies */ @@ -53,18 +50,12 @@ public function parse($money, $forceCurrency = null) */ $currency = $forceCurrency; if (!$currency instanceof Currency) { - @trigger_error('Passing a currency as string is deprecated since 3.1 and will be removed in 4.0. Please pass a ' . Currency::class . ' instance instead.', E_USER_DEPRECATED); + @trigger_error('Passing a currency as string is deprecated since 3.1 and will be removed in 4.0. Please pass a '.Currency::class.' instance instead.', E_USER_DEPRECATED); $currency = new Currency($currency); } - $decimal = trim($money); - - if ($decimal === '') { - return new Money(0, $currency); - } - $subunit = $this->currencies->subunitFor($currency); - return $this->parseDecimal($decimal, $subunit, $currency); + return $this->parseDecimal($money, $subunit, $currency); } } diff --git a/src/Parser/DecimalParserTrait.php b/src/Parser/DecimalParserTrait.php index 4551d5e2..58d883ad 100644 --- a/src/Parser/DecimalParserTrait.php +++ b/src/Parser/DecimalParserTrait.php @@ -2,6 +2,7 @@ namespace Money\Parser; +use Money\Currency; use Money\Exception\ParserException; use Money\Money; use Money\Number; @@ -10,8 +11,13 @@ trait DecimalParserTrait { public static $decimalPattern = '/^(?P-)?(?P0|[1-9]\d*)?\.?(?P\d+)?$/'; - protected function parseDecimal($decimal, $subunit, $currency) + protected function parseDecimal($decimal, $subunit, Currency $currency) { + $decimal = trim($decimal); + if ($decimal === '') { + return new Money(0, $currency); + } + if (!preg_match(self::$decimalPattern, $decimal, $matches) || !isset($matches['digits'])) { throw new ParserException(sprintf( 'Cannot parse "%s" to Money.', @@ -24,7 +30,7 @@ protected function parseDecimal($decimal, $subunit, $currency) $decimal = $matches['digits']; if ($negative) { - $decimal = '-' . $decimal; + $decimal = '-'.$decimal; } if (isset($matches['fraction'])) { @@ -42,7 +48,7 @@ protected function parseDecimal($decimal, $subunit, $currency) } if ($negative) { - $decimal = '-' . ltrim(substr($decimal, 1), '0'); + $decimal = '-'.ltrim(substr($decimal, 1), '0'); } else { $decimal = ltrim($decimal, '0'); } diff --git a/src/Parser/IntlMoneyParser.php b/src/Parser/IntlMoneyParser.php index f159374f..8442248c 100644 --- a/src/Parser/IntlMoneyParser.php +++ b/src/Parser/IntlMoneyParser.php @@ -5,9 +5,7 @@ use Money\Currencies; use Money\Currency; use Money\Exception\ParserException; -use Money\Money; use Money\MoneyParser; -use Money\Number; /** * Parses a string into a Money object using intl extension. @@ -16,7 +14,7 @@ */ final class IntlMoneyParser implements MoneyParser { - const DECIMAL_PATTERN = '/^(?P-)?(?P0|[1-9]\d*)?\.?(?P\d+)?$/'; + use DecimalParserTrait; /** * @var \NumberFormatter @@ -71,52 +69,9 @@ public function parse($money, $forceCurrency = null) $currency = new Currency($currency); } - $decimal = trim((string) $decimal); - if ($decimal === '') { - return new Money(0, $currency); - } - + $decimal = (string) $decimal; $subunit = $this->currencies->subunitFor($currency); - if (!preg_match(self::DECIMAL_PATTERN, $decimal, $matches) || !isset($matches['digits'])) { - throw new ParserException(sprintf( - 'Cannot parse "%s" to Money.', - $decimal - )); - } - - $negative = isset($matches['sign']) && $matches['sign'] === '-'; - - $decimal = $matches['digits']; - - if ($negative) { - $decimal = '-'.$decimal; - } - - if (isset($matches['fraction'])) { - $fractionDigits = strlen($matches['fraction']); - $decimal .= $matches['fraction']; - $decimal = Number::roundMoneyValue($decimal, $subunit, $fractionDigits); - - if ($fractionDigits > $subunit) { - $decimal = substr($decimal, 0, $subunit - $fractionDigits); - } elseif ($fractionDigits < $subunit) { - $decimal .= str_pad('', $subunit - $fractionDigits, '0'); - } - } else { - $decimal .= str_pad('', $subunit, '0'); - } - - if ($negative) { - $decimal = '-'.ltrim(substr($decimal, 1), '0'); - } else { - $decimal = ltrim($decimal, '0'); - } - - if ($decimal === '' || $decimal === '-') { - $decimal = '0'; - } - - return new Money($decimal, $currency); + return $this->parseDecimal($decimal, $subunit, $currency); } } From ca90a4f3aa6b210766e7f6d240e51753e1600a8c Mon Sep 17 00:00:00 2001 From: George Mponos Date: Wed, 5 Dec 2018 21:49:03 +0200 Subject: [PATCH 04/13] Add forgotten return --- src/Parser/BitcoinMoneyParser.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Parser/BitcoinMoneyParser.php b/src/Parser/BitcoinMoneyParser.php index 54290848..55c73eb5 100644 --- a/src/Parser/BitcoinMoneyParser.php +++ b/src/Parser/BitcoinMoneyParser.php @@ -47,6 +47,6 @@ public function parse($money, $forceCurrency = null) $decimal = str_replace(BitcoinCurrencies::SYMBOL, '', $money); $subunit = $this->fractionDigits; - $this->parseDecimal($decimal, $subunit, $currency); + return $this->parseDecimal($decimal, $subunit, $currency); } } From 4ff2a640c6ca23911250cf48effcbf902cd8c2b5 Mon Sep 17 00:00:00 2001 From: George Mponos Date: Wed, 5 Dec 2018 22:15:24 +0200 Subject: [PATCH 05/13] Fix style issues --- src/Parser/BitcoinMoneyParser.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Parser/BitcoinMoneyParser.php b/src/Parser/BitcoinMoneyParser.php index 55c73eb5..a15ae12b 100644 --- a/src/Parser/BitcoinMoneyParser.php +++ b/src/Parser/BitcoinMoneyParser.php @@ -47,6 +47,7 @@ public function parse($money, $forceCurrency = null) $decimal = str_replace(BitcoinCurrencies::SYMBOL, '', $money); $subunit = $this->fractionDigits; + return $this->parseDecimal($decimal, $subunit, $currency); } } From 2c9371ba706b006679a81d0972823376381e3174 Mon Sep 17 00:00:00 2001 From: Mponos George Date: Sat, 28 Dec 2019 10:21:28 +0200 Subject: [PATCH 06/13] Merged with master --- src/Parser/BitcoinMoneyParser.php | 15 +++++++++++++-- src/Parser/DecimalMoneyParser.php | 2 +- src/Parser/IntlMoneyParser.php | 18 +++++++++--------- 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/src/Parser/BitcoinMoneyParser.php b/src/Parser/BitcoinMoneyParser.php index 599fcc9d..7ad4f8d1 100644 --- a/src/Parser/BitcoinMoneyParser.php +++ b/src/Parser/BitcoinMoneyParser.php @@ -42,10 +42,21 @@ public function parse($money, $forceCurrency = null) throw new ParserException('Value cannot be parsed as Bitcoin'); } - $currency = new Currency(BitcoinCurrencies::CODE); + if ($forceCurrency === null) { + $forceCurrency = new Currency(BitcoinCurrencies::CODE); + } - $decimal = str_replace(BitcoinCurrencies::SYMBOL, '', $money); + /* + * This conversion is only required whilst currency can be either a string or a + * Currency object. + */ + $currency = $forceCurrency; + if (!$currency instanceof Currency) { + @trigger_error('Passing a currency as string is deprecated since 3.1 and will be removed in 4.0. Please pass a '.Currency::class.' instance instead.', E_USER_DEPRECATED); + $currency = new Currency($currency); + } + $decimal = str_replace(BitcoinCurrencies::SYMBOL, '', $money); return $this->parseDecimal($decimal, $this->fractionDigits, $currency); } } diff --git a/src/Parser/DecimalMoneyParser.php b/src/Parser/DecimalMoneyParser.php index 0c46bbf6..548ddc88 100644 --- a/src/Parser/DecimalMoneyParser.php +++ b/src/Parser/DecimalMoneyParser.php @@ -15,7 +15,7 @@ final class DecimalMoneyParser implements MoneyParser { /** - * @deprecated This stayed here for BC reasons. + * @deprecated This is here for BC reasons. Should not rely on this constant and will be removed on version 4.x */ const DECIMAL_PATTERN = '/^(?P-)?(?P0|[1-9]\d*)?\.?(?P\d+)?$/'; diff --git a/src/Parser/IntlMoneyParser.php b/src/Parser/IntlMoneyParser.php index 8442248c..6d345a0c 100644 --- a/src/Parser/IntlMoneyParser.php +++ b/src/Parser/IntlMoneyParser.php @@ -56,19 +56,19 @@ public function parse($money, $forceCurrency = null) if (null !== $forceCurrency) { $currency = $forceCurrency; - - /* - * This conversion is only required whilst currency can be either a string or a - * Currency object. - */ - if (!$currency instanceof Currency) { - @trigger_error('Passing a currency as string is deprecated since 3.1 and will be removed in 4.0. Please pass a '.Currency::class.' instance instead.', E_USER_DEPRECATED); - $currency = new Currency($currency); - } } else { $currency = new Currency($currency); } + /* + * This conversion is only required whilst currency can be either a string or a + * Currency object. + */ + if (!$currency instanceof Currency) { + @trigger_error('Passing a currency as string is deprecated since 3.1 and will be removed in 4.0. Please pass a '.Currency::class.' instance instead.', E_USER_DEPRECATED); + $currency = new Currency($currency); + } + $decimal = (string) $decimal; $subunit = $this->currencies->subunitFor($currency); From 0f01d7f9a1eb57dd99a77c7d7026713b89333111 Mon Sep 17 00:00:00 2001 From: Mponos George Date: Sat, 28 Dec 2019 10:22:22 +0200 Subject: [PATCH 07/13] Update src/Parser/DecimalParserTrait.php MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Márk Sági-Kazár --- src/Parser/DecimalParserTrait.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Parser/DecimalParserTrait.php b/src/Parser/DecimalParserTrait.php index 58d883ad..6216756b 100644 --- a/src/Parser/DecimalParserTrait.php +++ b/src/Parser/DecimalParserTrait.php @@ -7,7 +7,10 @@ use Money\Money; use Money\Number; -trait DecimalParserTrait +/** + * Common decimal parsing logic extracted from DecimalMoneyParser for reuse. + */ +trait DecimalParser { public static $decimalPattern = '/^(?P-)?(?P0|[1-9]\d*)?\.?(?P\d+)?$/'; From d3009bb7acab7e936c5722e8334d6d5e4862bf6a Mon Sep 17 00:00:00 2001 From: Mponos George Date: Sat, 28 Dec 2019 10:23:38 +0200 Subject: [PATCH 08/13] Update uses of trait --- src/Parser/BitcoinMoneyParser.php | 2 +- src/Parser/DecimalMoneyParser.php | 2 +- src/Parser/{DecimalParserTrait.php => DecimalParser.php} | 2 ++ src/Parser/IntlMoneyParser.php | 2 +- 4 files changed, 5 insertions(+), 3 deletions(-) rename src/Parser/{DecimalParserTrait.php => DecimalParser.php} (99%) diff --git a/src/Parser/BitcoinMoneyParser.php b/src/Parser/BitcoinMoneyParser.php index 7ad4f8d1..a3a9a5e6 100644 --- a/src/Parser/BitcoinMoneyParser.php +++ b/src/Parser/BitcoinMoneyParser.php @@ -14,7 +14,7 @@ */ final class BitcoinMoneyParser implements MoneyParser { - use DecimalParserTrait; + use DecimalParser; /** * @var int diff --git a/src/Parser/DecimalMoneyParser.php b/src/Parser/DecimalMoneyParser.php index 548ddc88..70d0b457 100644 --- a/src/Parser/DecimalMoneyParser.php +++ b/src/Parser/DecimalMoneyParser.php @@ -19,7 +19,7 @@ final class DecimalMoneyParser implements MoneyParser */ const DECIMAL_PATTERN = '/^(?P-)?(?P0|[1-9]\d*)?\.?(?P\d+)?$/'; - use DecimalParserTrait; + use DecimalParser; /** * @var Currencies diff --git a/src/Parser/DecimalParserTrait.php b/src/Parser/DecimalParser.php similarity index 99% rename from src/Parser/DecimalParserTrait.php rename to src/Parser/DecimalParser.php index 6216756b..a8f49a54 100644 --- a/src/Parser/DecimalParserTrait.php +++ b/src/Parser/DecimalParser.php @@ -9,6 +9,8 @@ /** * Common decimal parsing logic extracted from DecimalMoneyParser for reuse. + * + * @internal */ trait DecimalParser { diff --git a/src/Parser/IntlMoneyParser.php b/src/Parser/IntlMoneyParser.php index 6d345a0c..030e92ec 100644 --- a/src/Parser/IntlMoneyParser.php +++ b/src/Parser/IntlMoneyParser.php @@ -14,7 +14,7 @@ */ final class IntlMoneyParser implements MoneyParser { - use DecimalParserTrait; + use DecimalParser; /** * @var \NumberFormatter From 4fdae141674990c5a4ed39ac2ecf28531c111982 Mon Sep 17 00:00:00 2001 From: Mponos George Date: Sat, 28 Dec 2019 10:24:25 +0200 Subject: [PATCH 09/13] Fix phpcs --- src/Parser/BitcoinMoneyParser.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Parser/BitcoinMoneyParser.php b/src/Parser/BitcoinMoneyParser.php index a3a9a5e6..a4fc7a74 100644 --- a/src/Parser/BitcoinMoneyParser.php +++ b/src/Parser/BitcoinMoneyParser.php @@ -57,6 +57,7 @@ public function parse($money, $forceCurrency = null) } $decimal = str_replace(BitcoinCurrencies::SYMBOL, '', $money); + return $this->parseDecimal($decimal, $this->fractionDigits, $currency); } } From 42d35a0c330559b3f96bcd79b1d584c3dabc9184 Mon Sep 17 00:00:00 2001 From: Mponos George Date: Sat, 28 Dec 2019 10:27:00 +0200 Subject: [PATCH 10/13] updated docblocks for phpstan --- src/Parser/DecimalParser.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/Parser/DecimalParser.php b/src/Parser/DecimalParser.php index a8f49a54..0383e4e6 100644 --- a/src/Parser/DecimalParser.php +++ b/src/Parser/DecimalParser.php @@ -14,8 +14,17 @@ */ trait DecimalParser { + /** + * @var string + */ public static $decimalPattern = '/^(?P-)?(?P0|[1-9]\d*)?\.?(?P\d+)?$/'; + /** + * @param string $decimal + * @param int $subunit + * @param Currency $currency + * @return Money + */ protected function parseDecimal($decimal, $subunit, Currency $currency) { $decimal = trim($decimal); From 1068bd155ce279af182055cc3d0f068b9e44ea20 Mon Sep 17 00:00:00 2001 From: Mponos George Date: Sat, 28 Dec 2019 10:29:24 +0200 Subject: [PATCH 11/13] fix codestyle --- src/Parser/DecimalParser.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Parser/DecimalParser.php b/src/Parser/DecimalParser.php index 0383e4e6..f46175de 100644 --- a/src/Parser/DecimalParser.php +++ b/src/Parser/DecimalParser.php @@ -20,8 +20,8 @@ trait DecimalParser public static $decimalPattern = '/^(?P-)?(?P0|[1-9]\d*)?\.?(?P\d+)?$/'; /** - * @param string $decimal - * @param int $subunit + * @param string $decimal + * @param int $subunit * @param Currency $currency * @return Money */ From 0a75907eb30d0c85234d9469215acd2a93c11e74 Mon Sep 17 00:00:00 2001 From: Mponos George Date: Sat, 28 Dec 2019 12:12:47 +0200 Subject: [PATCH 12/13] Convert static attribute to protected --- src/Parser/DecimalParser.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Parser/DecimalParser.php b/src/Parser/DecimalParser.php index f46175de..0e8f0998 100644 --- a/src/Parser/DecimalParser.php +++ b/src/Parser/DecimalParser.php @@ -17,7 +17,7 @@ trait DecimalParser /** * @var string */ - public static $decimalPattern = '/^(?P-)?(?P0|[1-9]\d*)?\.?(?P\d+)?$/'; + protected static $decimalPattern = '/^(?P-)?(?P0|[1-9]\d*)?\.?(?P\d+)?$/'; /** * @param string $decimal From 350523480bb04fea59565220ee7548ced7fb054a Mon Sep 17 00:00:00 2001 From: Mponos George Date: Sat, 28 Dec 2019 12:21:38 +0200 Subject: [PATCH 13/13] make IntlLocalizedDecimalParser use the DecimalParser trait --- src/Parser/IntlLocalizedDecimalParser.php | 32 +++-------------------- 1 file changed, 3 insertions(+), 29 deletions(-) diff --git a/src/Parser/IntlLocalizedDecimalParser.php b/src/Parser/IntlLocalizedDecimalParser.php index b20f1359..6082a8fe 100644 --- a/src/Parser/IntlLocalizedDecimalParser.php +++ b/src/Parser/IntlLocalizedDecimalParser.php @@ -5,9 +5,7 @@ use Money\Currencies; use Money\Currency; use Money\Exception\ParserException; -use Money\Money; use Money\MoneyParser; -use Money\Number; /** * Parses a string into a Money object using intl extension. @@ -16,6 +14,8 @@ */ final class IntlLocalizedDecimalParser implements MoneyParser { + use DecimalParser; + /** * @var \NumberFormatter */ @@ -70,33 +70,7 @@ public function parse($money, $forceCurrency = null) $decimal = (string) $decimal; $subunit = $this->currencies->subunitFor($forceCurrency); - $decimalPosition = strpos($decimal, '.'); - - if (false !== $decimalPosition) { - $decimalLength = strlen($decimal); - $fractionDigits = $decimalLength - $decimalPosition - 1; - $decimal = str_replace('.', '', $decimal); - $decimal = Number::roundMoneyValue($decimal, $subunit, $fractionDigits); - - if ($fractionDigits > $subunit) { - $decimal = substr($decimal, 0, $decimalPosition + $subunit); - } elseif ($fractionDigits < $subunit) { - $decimal .= str_pad('', $subunit - $fractionDigits, '0'); - } - } else { - $decimal .= str_pad('', $subunit, '0'); - } - - if ('-' === $decimal[0]) { - $decimal = '-'.ltrim(substr($decimal, 1), '0'); - } else { - $decimal = ltrim($decimal, '0'); - } - - if ('' === $decimal) { - $decimal = '0'; - } - return new Money($decimal, $forceCurrency); + return $this->parseDecimal($decimal, $subunit, $forceCurrency); } }