Open Journal Systems  3.3.0
DecimalMoneyParser.php
1 <?php
2 
3 namespace Money\Parser;
4 
8 use Money\Money;
10 use Money\Number;
11 
17 final class DecimalMoneyParser implements MoneyParser
18 {
19  const DECIMAL_PATTERN = '/^(?P<sign>-)?(?P<digits>0|[1-9]\d*)?\.?(?P<fraction>\d+)?$/';
20 
24  private $currencies;
25 
29  public function __construct(Currencies $currencies)
30  {
31  $this->currencies = $currencies;
32  }
33 
37  public function parse($money, $forceCurrency = null)
38  {
39  if (!is_string($money)) {
40  throw new ParserException('Formatted raw money should be string, e.g. 1.00');
41  }
42 
43  if (null === $forceCurrency) {
44  throw new ParserException(
45  'DecimalMoneyParser cannot parse currency symbols. Use forceCurrency argument'
46  );
47  }
48 
49  /*
50  * This conversion is only required whilst currency can be either a string or a
51  * Currency object.
52  */
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);
56  $currency = new Currency($currency);
57  }
58 
59  $decimal = trim($money);
60 
61  if ($decimal === '') {
62  return new Money(0, $currency);
63  }
64 
65  $subunit = $this->currencies->subunitFor($currency);
66 
67  if (!preg_match(self::DECIMAL_PATTERN, $decimal, $matches) || !isset($matches['digits'])) {
68  throw new ParserException(sprintf(
69  'Cannot parse "%s" to Money.',
70  $decimal
71  ));
72  }
73 
74  $negative = isset($matches['sign']) && $matches['sign'] === '-';
75 
76  $decimal = $matches['digits'];
77 
78  if ($negative) {
79  $decimal = '-'.$decimal;
80  }
81 
82  if (isset($matches['fraction'])) {
83  $fractionDigits = strlen($matches['fraction']);
84  $decimal .= $matches['fraction'];
85  $decimal = Number::roundMoneyValue($decimal, $subunit, $fractionDigits);
86 
87  if ($fractionDigits > $subunit) {
88  $decimal = substr($decimal, 0, $subunit - $fractionDigits);
89  } elseif ($fractionDigits < $subunit) {
90  $decimal .= str_pad('', $subunit - $fractionDigits, '0');
91  }
92  } else {
93  $decimal .= str_pad('', $subunit, '0');
94  }
95 
96  if ($negative) {
97  $decimal = '-'.ltrim(substr($decimal, 1), '0');
98  } else {
99  $decimal = ltrim($decimal, '0');
100  }
101 
102  if ($decimal === '' || $decimal === '-') {
103  $decimal = '0';
104  }
105 
106  return new Money($decimal, $currency);
107  }
108 }
Money\Money
Definition: Money.php:16
Money
Money\Currencies
Definition: AggregateCurrencies.php:3
Money\Number
Definition: paymethod/paypal/vendor/moneyphp/money/src/Number.php:10
Money\Parser\DecimalMoneyParser\parse
parse($money, $forceCurrency=null)
Definition: DecimalMoneyParser.php:40
Money\Parser\DecimalMoneyParser\DECIMAL_PATTERN
const DECIMAL_PATTERN
Definition: DecimalMoneyParser.php:19
Money\Currency
Definition: vendor/moneyphp/money/src/Currency.php:14
Money\Exception\ParserException
Definition: ParserException.php:12
Money\Parser
Definition: AggregateMoneyParser.php:3
Money\MoneyParser
Definition: MoneyParser.php:10
Money\Currencies
Definition: Currencies.php:12
Money\Number\roundMoneyValue
static roundMoneyValue($moneyValue, $targetDigits, $havingDigits)
Definition: paymethod/paypal/vendor/moneyphp/money/src/Number.php:309
Money\Parser\DecimalMoneyParser
Definition: DecimalMoneyParser.php:17
Money\Parser\DecimalMoneyParser\__construct
__construct(Currencies $currencies)
Definition: DecimalMoneyParser.php:32