19 const DECIMAL_PATTERN =
'/^(?P<sign>-)?(?P<digits>0|[1-9]\d*)?\.?(?P<fraction>\d+)?$/';
31 $this->currencies = $currencies;
37 public function parse($money, $forceCurrency =
null)
39 if (!is_string($money)) {
43 if (
null === $forceCurrency) {
45 'DecimalMoneyParser cannot parse currency symbols. Use forceCurrency argument'
53 $currency = $forceCurrency;
54 if (!$currency instanceof
Currency) {
55 @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);
59 $decimal = trim($money);
61 if ($decimal ===
'') {
62 return new Money(0, $currency);
65 $subunit = $this->currencies->subunitFor($currency);
67 if (!preg_match(self::DECIMAL_PATTERN, $decimal, $matches) || !isset($matches[
'digits'])) {
68 throw new ParserException(sprintf(
69 'Cannot parse "%s" to Money.',
74 $negative = isset($matches[
'sign']) && $matches[
'sign'] ===
'-';
76 $decimal = $matches[
'digits'];
79 $decimal =
'-'.$decimal;
82 if (isset($matches[
'fraction'])) {
83 $fractionDigits = strlen($matches[
'fraction']);
84 $decimal .= $matches[
'fraction'];
87 if ($fractionDigits > $subunit) {
88 $decimal = substr($decimal, 0, $subunit - $fractionDigits);
89 } elseif ($fractionDigits < $subunit) {
90 $decimal .= str_pad(
'', $subunit - $fractionDigits,
'0');
93 $decimal .= str_pad(
'', $subunit,
'0');
97 $decimal =
'-'.ltrim(substr($decimal, 1),
'0');
99 $decimal = ltrim($decimal,
'0');
102 if ($decimal ===
'' || $decimal ===
'-') {
106 return new Money($decimal, $currency);