Open Journal Systems  3.3.0
paymethod/paypal/vendor/moneyphp/money/src/Number.php
1 <?php
2 
3 namespace Money;
4 
10 final class Number
11 {
15  private $integerPart;
16 
20  private $fractionalPart;
21 
25  private static $numbers = [0 => 1, 1 => 1, 2 => 1, 3 => 1, 4 => 1, 5 => 1, 6 => 1, 7 => 1, 8 => 1, 9 => 1];
26 
31  public function __construct($integerPart, $fractionalPart = '')
32  {
33  if ('' === $integerPart && '' === $fractionalPart) {
34  throw new \InvalidArgumentException('Empty number is invalid');
35  }
36 
37  $this->integerPart = $this->parseIntegerPart((string) $integerPart);
38  $this->fractionalPart = $this->parseFractionalPart((string) $fractionalPart);
39  }
40 
46  public static function fromString($number)
47  {
48  $decimalSeparatorPosition = strpos($number, '.');
49  if ($decimalSeparatorPosition === false) {
50  return new self($number, '');
51  }
52 
53  return new self(
54  substr($number, 0, $decimalSeparatorPosition),
55  rtrim(substr($number, $decimalSeparatorPosition + 1), '0')
56  );
57  }
58 
64  public static function fromFloat($number)
65  {
66  if (is_float($number) === false) {
67  throw new \InvalidArgumentException('Floating point value expected');
68  }
69 
70  return self::fromString(sprintf('%.14F', $number));
71  }
72 
78  public static function fromNumber($number)
79  {
80  if (is_float($number)) {
81  return self::fromString(sprintf('%.14F', $number));
82  }
83 
84  if (is_int($number)) {
85  return new self($number);
86  }
87 
88  if (is_string($number)) {
89  return self::fromString($number);
90  }
91 
92  throw new \InvalidArgumentException('Valid numeric value expected');
93  }
94 
98  public function isDecimal()
99  {
100  return $this->fractionalPart !== '';
101  }
102 
106  public function isInteger()
107  {
108  return $this->fractionalPart === '';
109  }
110 
114  public function isHalf()
115  {
116  return $this->fractionalPart === '5';
117  }
118 
122  public function isCurrentEven()
123  {
124  $lastIntegerPartNumber = $this->integerPart[strlen($this->integerPart) - 1];
125 
126  return $lastIntegerPartNumber % 2 === 0;
127  }
128 
132  public function isCloserToNext()
133  {
134  if ($this->fractionalPart === '') {
135  return false;
136  }
137 
138  return $this->fractionalPart[0] >= 5;
139  }
140 
144  public function __toString()
145  {
146  if ($this->fractionalPart === '') {
147  return $this->integerPart;
148  }
149 
150  return $this->integerPart.'.'.$this->fractionalPart;
151  }
152 
156  public function isNegative()
157  {
158  return $this->integerPart[0] === '-';
159  }
160 
164  public function getIntegerPart()
165  {
166  return $this->integerPart;
167  }
168 
172  public function getFractionalPart()
173  {
174  return $this->fractionalPart;
175  }
176 
180  public function getIntegerRoundingMultiplier()
181  {
182  if ($this->integerPart[0] === '-') {
183  return '-1';
184  }
185 
186  return '1';
187  }
188 
194  public function base10($number)
195  {
196  if (!is_int($number)) {
197  throw new \InvalidArgumentException('Expecting integer');
198  }
199 
200  if ($this->integerPart === '0' && !$this->fractionalPart) {
201  return $this;
202  }
203 
204  $sign = '';
205  $integerPart = $this->integerPart;
206 
207  if ($integerPart[0] === '-') {
208  $sign = '-';
209  $integerPart = substr($integerPart, 1);
210  }
211 
212  if ($number >= 0) {
213  $integerPart = ltrim($integerPart, '0');
214  $lengthIntegerPart = strlen($integerPart);
215  $integers = $lengthIntegerPart - min($number, $lengthIntegerPart);
216  $zeroPad = $number - min($number, $lengthIntegerPart);
217 
218  return new self(
219  $sign.substr($integerPart, 0, $integers),
220  rtrim(str_pad('', $zeroPad, '0').substr($integerPart, $integers).$this->fractionalPart, '0')
221  );
222  }
223 
224  $number = abs($number);
225  $lengthFractionalPart = strlen($this->fractionalPart);
226  $fractions = $lengthFractionalPart - min($number, $lengthFractionalPart);
227  $zeroPad = $number - min($number, $lengthFractionalPart);
228 
229  return new self(
230  $sign.ltrim($integerPart.substr($this->fractionalPart, 0, $lengthFractionalPart - $fractions).str_pad('', $zeroPad, '0'), '0'),
231  substr($this->fractionalPart, $lengthFractionalPart - $fractions)
232  );
233  }
234 
240  private static function parseIntegerPart($number)
241  {
242  if ('' === $number || '0' === $number) {
243  return '0';
244  }
245 
246  if ('-' === $number) {
247  return '-0';
248  }
249 
250  $nonZero = false;
251 
252  for ($position = 0, $characters = strlen($number); $position < $characters; ++$position) {
253  $digit = $number[$position];
254 
255  if (!isset(static::$numbers[$digit]) && !(0 === $position && '-' === $digit)) {
256  throw new \InvalidArgumentException(
257  sprintf('Invalid integer part %1$s. Invalid digit %2$s found', $number, $digit)
258  );
259  }
260 
261  if (false === $nonZero && '0' === $digit) {
262  throw new \InvalidArgumentException(
263  'Leading zeros are not allowed'
264  );
265  }
266 
267  $nonZero = true;
268  }
269 
270  return $number;
271  }
272 
278  private static function parseFractionalPart($number)
279  {
280  if ('' === $number) {
281  return $number;
282  }
283 
284  for ($position = 0, $characters = strlen($number); $position < $characters; ++$position) {
285  $digit = $number[$position];
286  if (!isset(static::$numbers[$digit])) {
287  throw new \InvalidArgumentException(
288  sprintf('Invalid fractional part %1$s. Invalid digit %2$s found', $number, $digit)
289  );
290  }
291  }
292 
293  return $number;
294  }
295 
303  public static function roundMoneyValue($moneyValue, $targetDigits, $havingDigits)
304  {
305  $valueLength = strlen($moneyValue);
306  $shouldRound = $targetDigits < $havingDigits && $valueLength - $havingDigits + $targetDigits > 0;
307 
308  if ($shouldRound && $moneyValue[$valueLength - $havingDigits + $targetDigits] >= 5) {
309  $position = $valueLength - $havingDigits + $targetDigits;
310  $addend = 1;
311 
312  while ($position > 0) {
313  $newValue = (string) ((int) $moneyValue[$position - 1] + $addend);
314 
315  if ($newValue >= 10) {
316  $moneyValue[$position - 1] = $newValue[1];
317  $addend = $newValue[0];
318  --$position;
319  if ($position === 0) {
320  $moneyValue = $addend.$moneyValue;
321  }
322  } else {
323  if ($moneyValue[$position - 1] === '-') {
324  $moneyValue[$position - 1] = $newValue[0];
325  $moneyValue = '-'.$moneyValue;
326  } else {
327  $moneyValue[$position - 1] = $newValue[0];
328  }
329 
330  break;
331  }
332  }
333  }
334 
335  return $moneyValue;
336  }
337 }
Money\Number\base10
base10($number)
Definition: paymethod/paypal/vendor/moneyphp/money/src/Number.php:200
Money\Number\__construct
__construct($integerPart, $fractionalPart='')
Definition: paymethod/paypal/vendor/moneyphp/money/src/Number.php:37
Money\Number\getIntegerPart
getIntegerPart()
Definition: paymethod/paypal/vendor/moneyphp/money/src/Number.php:170
Money\Number\getIntegerRoundingMultiplier
getIntegerRoundingMultiplier()
Definition: paymethod/paypal/vendor/moneyphp/money/src/Number.php:186
Money
Money\Number\__toString
__toString()
Definition: paymethod/paypal/vendor/moneyphp/money/src/Number.php:150
Money\Number
Definition: paymethod/paypal/vendor/moneyphp/money/src/Number.php:10
Money\Number\getFractionalPart
getFractionalPart()
Definition: paymethod/paypal/vendor/moneyphp/money/src/Number.php:178
Money\Number\fromNumber
static fromNumber($number)
Definition: paymethod/paypal/vendor/moneyphp/money/src/Number.php:84
Money\Number\isDecimal
isDecimal()
Definition: paymethod/paypal/vendor/moneyphp/money/src/Number.php:104
Money\Number\fromString
static fromString($number)
Definition: paymethod/paypal/vendor/moneyphp/money/src/Number.php:52
Money\Number\fromFloat
static fromFloat($number)
Definition: paymethod/paypal/vendor/moneyphp/money/src/Number.php:70
Money\Number\isCloserToNext
isCloserToNext()
Definition: paymethod/paypal/vendor/moneyphp/money/src/Number.php:138
Money\Number\roundMoneyValue
static roundMoneyValue($moneyValue, $targetDigits, $havingDigits)
Definition: paymethod/paypal/vendor/moneyphp/money/src/Number.php:309
Money\Number\isNegative
isNegative()
Definition: paymethod/paypal/vendor/moneyphp/money/src/Number.php:162
Money\Number\isCurrentEven
isCurrentEven()
Definition: paymethod/paypal/vendor/moneyphp/money/src/Number.php:128
Money\Number\isInteger
isInteger()
Definition: paymethod/paypal/vendor/moneyphp/money/src/Number.php:112
Money\Number\isHalf
isHalf()
Definition: paymethod/paypal/vendor/moneyphp/money/src/Number.php:120