diff --git a/src/Parser/BitcoinMoneyParser.php b/src/Parser/BitcoinMoneyParser.php index 320456d4..a4fc7a74 100644 --- a/src/Parser/BitcoinMoneyParser.php +++ b/src/Parser/BitcoinMoneyParser.php @@ -5,7 +5,6 @@ use Money\Currencies\BitcoinCurrencies; use Money\Currency; use Money\Exception\ParserException; -use Money\Money; use Money\MoneyParser; /** @@ -15,6 +14,8 @@ */ final class BitcoinMoneyParser implements MoneyParser { + use DecimalParser; + /** * @var int */ @@ -56,27 +57,7 @@ public function parse($money, $forceCurrency = null) } $decimal = str_replace(BitcoinCurrencies::SYMBOL, '', $money); - $decimalSeparator = strpos($decimal, '.'); - - if (false !== $decimalSeparator) { - $decimal = rtrim($decimal, '0'); - $lengthDecimal = strlen($decimal); - $decimal = str_replace('.', '', $decimal); - $decimal .= str_pad('', ($lengthDecimal - $decimalSeparator - $this->fractionDigits - 1) * -1, '0'); - } else { - $decimal .= str_pad('', $this->fractionDigits, '0'); - } - - if (substr($decimal, 0, 1) === '-') { - $decimal = '-'.ltrim(substr($decimal, 1), '0'); - } else { - $decimal = ltrim($decimal, '0'); - } - - if ('' === $decimal) { - $decimal = '0'; - } - return new Money($decimal, $currency); + return $this->parseDecimal($decimal, $this->fractionDigits, $currency); } } diff --git a/src/Parser/DecimalMoneyParser.php b/src/Parser/DecimalMoneyParser.php index c6a133c4..70d0b457 100644 --- a/src/Parser/DecimalMoneyParser.php +++ b/src/Parser/DecimalMoneyParser.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 decimal string into a Money object. @@ -16,8 +14,13 @@ */ final class DecimalMoneyParser implements MoneyParser { + /** + * @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+)?$/'; + use DecimalParser; + /** * @var Currencies */ @@ -56,53 +59,8 @@ public function parse($money, $forceCurrency = null) $currency = new Currency($currency); } - $decimal = trim($money); - - if ($decimal === '') { - return new Money(0, $currency); - } - $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($money, $subunit, $currency); } } diff --git a/src/Parser/DecimalParser.php b/src/Parser/DecimalParser.php new file mode 100644 index 00000000..0e8f0998 --- /dev/null +++ b/src/Parser/DecimalParser.php @@ -0,0 +1,76 @@ +-)?(?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); + 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.', + $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); + } +} 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); } } diff --git a/src/Parser/IntlMoneyParser.php b/src/Parser/IntlMoneyParser.php index 29339c5c..030e92ec 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,6 +14,8 @@ */ final class IntlMoneyParser implements MoneyParser { + use DecimalParser; + /** * @var \NumberFormatter */ @@ -71,33 +71,7 @@ public function parse($money, $forceCurrency = null) $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); - $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, $currency); + return $this->parseDecimal($decimal, $subunit, $currency); } }