Completed
Branch FET-10619-money-entity (c16d10)
by
unknown
56:01 queued 44:44
created
core/domain/values/currency/Money.php 2 patches
Indentation   +329 added lines, -329 removed lines patch added patch discarded remove patch
@@ -22,335 +22,335 @@
 block discarded – undo
22 22
 class Money
23 23
 {
24 24
 
25
-    /**
26
-     * number of decimal places to be added to currencies for internal computations,
27
-     * but removed before any output or formatting is applied.
28
-     * This allows us to avoid rounding errors during calculations.
29
-     */
30
-    const EXTRA_PRECISION = 3;
31
-
32
-    /**
33
-     * @var int $amount
34
-     */
35
-    private $amount;
36
-
37
-    /**
38
-     * @var Currency $currency
39
-     */
40
-    private $currency;
41
-
42
-    /**
43
-     * @var Calculator $calculator
44
-     */
45
-    protected $calculator;
46
-
47
-    /**
48
-     * @var MoneyFormatter[] $formatters
49
-     */
50
-    protected $formatters;
51
-
52
-
53
-
54
-    /**
55
-     * Money constructor.
56
-     *
57
-     * @param float|int|string $amount money amount IN THE STANDARD UNIT FOR THE CURRENCY ie: dollars, Euros, etc
58
-     *                                 example: $12.5 USD would equate to a value amount of 12.50
59
-     * @param Currency         $currency
60
-     * @param Calculator       $calculator
61
-     * @param MoneyFormatter[] $formatters
62
-     * @throws InvalidDataTypeException
63
-     */
64
-    public function __construct($amount, Currency $currency, Calculator $calculator, array $formatters)
65
-    {
66
-        $this->currency   = $currency;
67
-        $this->amount     = (string) $this->parseAmount($amount);
68
-        $this->calculator = $calculator;
69
-        $this->formatters = $formatters;
70
-    }
71
-
72
-
73
-
74
-    /**
75
-     * @return Calculator
76
-     */
77
-    protected function calculator()
78
-    {
79
-        return $this->calculator;
80
-    }
81
-
82
-
83
-
84
-    /**
85
-     * @return MoneyFormatter[]
86
-     */
87
-    protected function formatters()
88
-    {
89
-        return $this->formatters;
90
-    }
91
-
92
-
93
-
94
-    /**
95
-     * @param float|int|string $amount money amount IN THE STANDARD UNIT FOR THE CURRENCY ie: dollars, Euros, etc
96
-     *                                 example: $12.5 USD would equate to a value amount of 12.50
97
-     * @return float|int|number|string
98
-     * @throws InvalidDataTypeException
99
-     */
100
-    private function parseAmount($amount)
101
-    {
102
-        if (! in_array(gettype($amount), array('integer', 'double', 'string'),true)) {
103
-            throw new InvalidDataTypeException(
104
-                '$amount',
105
-                $amount,
106
-                'integer (or float or string)'
107
-            );
108
-        }
109
-        if ($this->currency->decimalMark() !== '.') {
110
-            // remove thousands separator and replace decimal place with standard decimal.
111
-            $amount = str_replace(
112
-                array(
113
-                    $this->currency->thousands(),
114
-                    $this->currency->decimalMark(),
115
-                ),
116
-                array(
117
-                    '',
118
-                    '.',
119
-                ),
120
-                $amount
121
-            );
122
-        }
123
-        // remove any non numeric values but leave the decimal
124
-        $amount = (float) preg_replace('/([^0-9\\.])/', '', $amount);
125
-        // shift the decimal position by the number of decimal places used internally
126
-        // ex: 12.5 for a currency using 2 decimal places, would become 1250
127
-        // then if our extra internal precision was 3, it would become 1250000
128
-        $amount *= pow(10, $this->precision());
129
-        // then round up the remaining value if there is still a fractional amount left
130
-        $amount = round($amount);
131
-        return $amount;
132
-    }
133
-
134
-
135
-
136
-    /**
137
-     * adds or subtracts additional decimal places based on the value of the Money::EXTRA_PRECISION constant
138
-     *
139
-     * @param bool $positive
140
-     * @return int
141
-     */
142
-    private function precision($positive = true)
143
-    {
144
-        $sign = $positive ? 1 : -1;
145
-        return ((int) $this->currency->decimalPlaces() + Money::EXTRA_PRECISION) * $sign;
146
-    }
147
-
148
-
149
-
150
-    /**
151
-     * Returns the money amount as an unformatted string
152
-     * IF YOU REQUIRE A FORMATTED STRING, THEN USE Money::format()
153
-     *
154
-     * @return string
155
-     */
156
-    public function amount()
157
-    {
158
-        // shift the decimal position BACK by the number of decimal places used internally
159
-        // ex: 1250 for a currency using 2 decimal places, would become 12.50
160
-        $amount = (string) $this->amount * pow(10, $this->precision(false));
161
-        // then shave off our extra internal precision using the number of decimal places for the currency
162
-        $amount = round($amount, $this->currency->decimalPlaces());
163
-        return $amount;
164
-    }
165
-
166
-
167
-
168
-    /**
169
-     * Returns the money SUBUNITS amount as an INTEGER
170
-     *
171
-     * @return integer
172
-     */
173
-    public function amountInSubunits()
174
-    {
175
-        // shift the decimal position BACK by the number of decimal places used internally
176
-        // for extra internal precision, but NOT for the number of decimals used by the currency
177
-        // ex: if our extra internal precision was 3, then 1250000 would become 1250
178
-        // and even if the currency used 2 decimal places, we would return 1250 and NOT 12.50
179
-        $amount = (string) $this->amount * pow(10, Money::EXTRA_PRECISION * -1);
180
-        // then shave off anything after the decimal
181
-        $amount = round($amount);
182
-        return $amount;
183
-    }
184
-
185
-
186
-
187
-    /**
188
-     * applies formatting based on the specified formatting level
189
-     * corresponding to one of the constants on \EventEspresso\core\services\currency\MoneyFormatter
190
-     *
191
-     * @param int $formatting_level
192
-     * @return string
193
-     */
194
-    public function format($formatting_level = MoneyFormatter::ADD_THOUSANDS)
195
-    {
196
-        $formatted_amount = $this->amount();
197
-        $formatters       = $this->formatters();
198
-        // if we are applying thousands formatting...
199
-        if ($formatting_level >= MoneyFormatter::ADD_THOUSANDS) {
200
-            // then let's remove decimal formatting since it's included in thousands formatting
201
-            unset($formatters[ MoneyFormatter::DECIMAL_ONLY ]);
202
-        }
203
-        for ($x = 1; $x <= $formatting_level; $x++) {
204
-            if (isset($formatters[ $x ]) && $formatters[ $x ] instanceof MoneyFormatter) {
205
-                $formatted_amount = $formatters[ $x ]->format($formatted_amount, $this->currency);
206
-            }
207
-        }
208
-        return (string) apply_filters(
209
-            'FHEE__EventEspresso_core_domain_values_currency_Money__format__formatted_amount',
210
-            $formatted_amount,
211
-            $this
212
-        );
213
-    }
214
-
215
-
216
-
217
-    /**
218
-     * Returns the Currency object for this money
219
-     *
220
-     * @return Currency
221
-     */
222
-    public function currency()
223
-    {
224
-        return $this->currency;
225
-    }
226
-
227
-
228
-
229
-    /**
230
-     * adds the supplied Money amount to this Money amount
231
-     * and returns a new Money object
232
-     *
233
-     * @param Money $other
234
-     * @return Money
235
-     * @throws InvalidArgumentException
236
-     */
237
-    public function add(Money $other)
238
-    {
239
-        $this->verifySameCurrency($other->currency());
240
-        return new Money(
241
-            $this->calculator()->add(
242
-                $this->amount(),
243
-                $other->amount()
244
-            ),
245
-            $this->currency(),
246
-            $this->calculator(),
247
-            $this->formatters()
248
-        );
249
-    }
250
-
251
-
252
-
253
-    /**
254
-     * subtracts the supplied Money amount from this Money amount
255
-     * and returns a new Money object
256
-     *
257
-     * @param Money $other
258
-     * @return Money
259
-     * @throws InvalidArgumentException
260
-     */
261
-    public function subtract(Money $other)
262
-    {
263
-        $this->verifySameCurrency($other->currency());
264
-        return new Money(
265
-            $this->calculator()->subtract(
266
-                $this->amount(),
267
-                $other->amount()
268
-            ),
269
-            $this->currency(),
270
-            $this->calculator(),
271
-            $this->formatters()
272
-        );
273
-    }
274
-
275
-
276
-
277
-    /**
278
-     * multiplies this Money amount by the supplied $multiplier
279
-     * and returns a new Money object
280
-     *
281
-     * @param float|int|string $multiplier
282
-     * @param int              $rounding_mode
283
-     * @return Money
284
-     * @throws InvalidDataTypeException
285
-     */
286
-    public function multiply($multiplier, $rounding_mode = Calculator::ROUND_HALF_UP)
287
-    {
288
-        return new Money(
289
-            $this->calculator()->multiply(
290
-                $this->amount(),
291
-                $multiplier,
292
-                $this->precision(),
293
-                $rounding_mode
294
-            ),
295
-            $this->currency(),
296
-            $this->calculator(),
297
-            $this->formatters()
298
-        );
299
-    }
300
-
301
-
302
-
303
-    /**
304
-     * divides this Money amount by the supplied $divisor
305
-     * and returns a new Money object
306
-     *
307
-     * @param float|int|string $divisor
308
-     * @param int              $rounding_mode
309
-     * @return Money
310
-     * @throws InvalidDataTypeException
311
-     */
312
-    public function divide($divisor, $rounding_mode = Calculator::ROUND_HALF_UP)
313
-    {
314
-        return new Money(
315
-            $this->calculator()->divide(
316
-                $this->amount(),
317
-                $divisor,
318
-                $this->precision(),
319
-                $rounding_mode
320
-            ),
321
-            $this->currency(),
322
-            $this->calculator(),
323
-            $this->formatters()
324
-        );
325
-    }
326
-
327
-
328
-
329
-    /**
330
-     * @param Currency $other_currency
331
-     * @throws InvalidArgumentException
332
-     */
333
-    public function verifySameCurrency(Currency $other_currency)
334
-    {
335
-        if ($this->currency()->equals($other_currency) !== true) {
336
-            throw new InvalidArgumentException(
337
-                esc_html__(
338
-                    'Currencies must be the same in order to add or subtract their values.',
339
-                    'event_espresso'
340
-                )
341
-            );
342
-        }
343
-    }
344
-
345
-
346
-
347
-    /**
348
-     * @return string
349
-     */
350
-    public function __toString()
351
-    {
352
-        return $this->format(MoneyFormatter::DECIMAL_ONLY);
353
-    }
25
+	/**
26
+	 * number of decimal places to be added to currencies for internal computations,
27
+	 * but removed before any output or formatting is applied.
28
+	 * This allows us to avoid rounding errors during calculations.
29
+	 */
30
+	const EXTRA_PRECISION = 3;
31
+
32
+	/**
33
+	 * @var int $amount
34
+	 */
35
+	private $amount;
36
+
37
+	/**
38
+	 * @var Currency $currency
39
+	 */
40
+	private $currency;
41
+
42
+	/**
43
+	 * @var Calculator $calculator
44
+	 */
45
+	protected $calculator;
46
+
47
+	/**
48
+	 * @var MoneyFormatter[] $formatters
49
+	 */
50
+	protected $formatters;
51
+
52
+
53
+
54
+	/**
55
+	 * Money constructor.
56
+	 *
57
+	 * @param float|int|string $amount money amount IN THE STANDARD UNIT FOR THE CURRENCY ie: dollars, Euros, etc
58
+	 *                                 example: $12.5 USD would equate to a value amount of 12.50
59
+	 * @param Currency         $currency
60
+	 * @param Calculator       $calculator
61
+	 * @param MoneyFormatter[] $formatters
62
+	 * @throws InvalidDataTypeException
63
+	 */
64
+	public function __construct($amount, Currency $currency, Calculator $calculator, array $formatters)
65
+	{
66
+		$this->currency   = $currency;
67
+		$this->amount     = (string) $this->parseAmount($amount);
68
+		$this->calculator = $calculator;
69
+		$this->formatters = $formatters;
70
+	}
71
+
72
+
73
+
74
+	/**
75
+	 * @return Calculator
76
+	 */
77
+	protected function calculator()
78
+	{
79
+		return $this->calculator;
80
+	}
81
+
82
+
83
+
84
+	/**
85
+	 * @return MoneyFormatter[]
86
+	 */
87
+	protected function formatters()
88
+	{
89
+		return $this->formatters;
90
+	}
91
+
92
+
93
+
94
+	/**
95
+	 * @param float|int|string $amount money amount IN THE STANDARD UNIT FOR THE CURRENCY ie: dollars, Euros, etc
96
+	 *                                 example: $12.5 USD would equate to a value amount of 12.50
97
+	 * @return float|int|number|string
98
+	 * @throws InvalidDataTypeException
99
+	 */
100
+	private function parseAmount($amount)
101
+	{
102
+		if (! in_array(gettype($amount), array('integer', 'double', 'string'),true)) {
103
+			throw new InvalidDataTypeException(
104
+				'$amount',
105
+				$amount,
106
+				'integer (or float or string)'
107
+			);
108
+		}
109
+		if ($this->currency->decimalMark() !== '.') {
110
+			// remove thousands separator and replace decimal place with standard decimal.
111
+			$amount = str_replace(
112
+				array(
113
+					$this->currency->thousands(),
114
+					$this->currency->decimalMark(),
115
+				),
116
+				array(
117
+					'',
118
+					'.',
119
+				),
120
+				$amount
121
+			);
122
+		}
123
+		// remove any non numeric values but leave the decimal
124
+		$amount = (float) preg_replace('/([^0-9\\.])/', '', $amount);
125
+		// shift the decimal position by the number of decimal places used internally
126
+		// ex: 12.5 for a currency using 2 decimal places, would become 1250
127
+		// then if our extra internal precision was 3, it would become 1250000
128
+		$amount *= pow(10, $this->precision());
129
+		// then round up the remaining value if there is still a fractional amount left
130
+		$amount = round($amount);
131
+		return $amount;
132
+	}
133
+
134
+
135
+
136
+	/**
137
+	 * adds or subtracts additional decimal places based on the value of the Money::EXTRA_PRECISION constant
138
+	 *
139
+	 * @param bool $positive
140
+	 * @return int
141
+	 */
142
+	private function precision($positive = true)
143
+	{
144
+		$sign = $positive ? 1 : -1;
145
+		return ((int) $this->currency->decimalPlaces() + Money::EXTRA_PRECISION) * $sign;
146
+	}
147
+
148
+
149
+
150
+	/**
151
+	 * Returns the money amount as an unformatted string
152
+	 * IF YOU REQUIRE A FORMATTED STRING, THEN USE Money::format()
153
+	 *
154
+	 * @return string
155
+	 */
156
+	public function amount()
157
+	{
158
+		// shift the decimal position BACK by the number of decimal places used internally
159
+		// ex: 1250 for a currency using 2 decimal places, would become 12.50
160
+		$amount = (string) $this->amount * pow(10, $this->precision(false));
161
+		// then shave off our extra internal precision using the number of decimal places for the currency
162
+		$amount = round($amount, $this->currency->decimalPlaces());
163
+		return $amount;
164
+	}
165
+
166
+
167
+
168
+	/**
169
+	 * Returns the money SUBUNITS amount as an INTEGER
170
+	 *
171
+	 * @return integer
172
+	 */
173
+	public function amountInSubunits()
174
+	{
175
+		// shift the decimal position BACK by the number of decimal places used internally
176
+		// for extra internal precision, but NOT for the number of decimals used by the currency
177
+		// ex: if our extra internal precision was 3, then 1250000 would become 1250
178
+		// and even if the currency used 2 decimal places, we would return 1250 and NOT 12.50
179
+		$amount = (string) $this->amount * pow(10, Money::EXTRA_PRECISION * -1);
180
+		// then shave off anything after the decimal
181
+		$amount = round($amount);
182
+		return $amount;
183
+	}
184
+
185
+
186
+
187
+	/**
188
+	 * applies formatting based on the specified formatting level
189
+	 * corresponding to one of the constants on \EventEspresso\core\services\currency\MoneyFormatter
190
+	 *
191
+	 * @param int $formatting_level
192
+	 * @return string
193
+	 */
194
+	public function format($formatting_level = MoneyFormatter::ADD_THOUSANDS)
195
+	{
196
+		$formatted_amount = $this->amount();
197
+		$formatters       = $this->formatters();
198
+		// if we are applying thousands formatting...
199
+		if ($formatting_level >= MoneyFormatter::ADD_THOUSANDS) {
200
+			// then let's remove decimal formatting since it's included in thousands formatting
201
+			unset($formatters[ MoneyFormatter::DECIMAL_ONLY ]);
202
+		}
203
+		for ($x = 1; $x <= $formatting_level; $x++) {
204
+			if (isset($formatters[ $x ]) && $formatters[ $x ] instanceof MoneyFormatter) {
205
+				$formatted_amount = $formatters[ $x ]->format($formatted_amount, $this->currency);
206
+			}
207
+		}
208
+		return (string) apply_filters(
209
+			'FHEE__EventEspresso_core_domain_values_currency_Money__format__formatted_amount',
210
+			$formatted_amount,
211
+			$this
212
+		);
213
+	}
214
+
215
+
216
+
217
+	/**
218
+	 * Returns the Currency object for this money
219
+	 *
220
+	 * @return Currency
221
+	 */
222
+	public function currency()
223
+	{
224
+		return $this->currency;
225
+	}
226
+
227
+
228
+
229
+	/**
230
+	 * adds the supplied Money amount to this Money amount
231
+	 * and returns a new Money object
232
+	 *
233
+	 * @param Money $other
234
+	 * @return Money
235
+	 * @throws InvalidArgumentException
236
+	 */
237
+	public function add(Money $other)
238
+	{
239
+		$this->verifySameCurrency($other->currency());
240
+		return new Money(
241
+			$this->calculator()->add(
242
+				$this->amount(),
243
+				$other->amount()
244
+			),
245
+			$this->currency(),
246
+			$this->calculator(),
247
+			$this->formatters()
248
+		);
249
+	}
250
+
251
+
252
+
253
+	/**
254
+	 * subtracts the supplied Money amount from this Money amount
255
+	 * and returns a new Money object
256
+	 *
257
+	 * @param Money $other
258
+	 * @return Money
259
+	 * @throws InvalidArgumentException
260
+	 */
261
+	public function subtract(Money $other)
262
+	{
263
+		$this->verifySameCurrency($other->currency());
264
+		return new Money(
265
+			$this->calculator()->subtract(
266
+				$this->amount(),
267
+				$other->amount()
268
+			),
269
+			$this->currency(),
270
+			$this->calculator(),
271
+			$this->formatters()
272
+		);
273
+	}
274
+
275
+
276
+
277
+	/**
278
+	 * multiplies this Money amount by the supplied $multiplier
279
+	 * and returns a new Money object
280
+	 *
281
+	 * @param float|int|string $multiplier
282
+	 * @param int              $rounding_mode
283
+	 * @return Money
284
+	 * @throws InvalidDataTypeException
285
+	 */
286
+	public function multiply($multiplier, $rounding_mode = Calculator::ROUND_HALF_UP)
287
+	{
288
+		return new Money(
289
+			$this->calculator()->multiply(
290
+				$this->amount(),
291
+				$multiplier,
292
+				$this->precision(),
293
+				$rounding_mode
294
+			),
295
+			$this->currency(),
296
+			$this->calculator(),
297
+			$this->formatters()
298
+		);
299
+	}
300
+
301
+
302
+
303
+	/**
304
+	 * divides this Money amount by the supplied $divisor
305
+	 * and returns a new Money object
306
+	 *
307
+	 * @param float|int|string $divisor
308
+	 * @param int              $rounding_mode
309
+	 * @return Money
310
+	 * @throws InvalidDataTypeException
311
+	 */
312
+	public function divide($divisor, $rounding_mode = Calculator::ROUND_HALF_UP)
313
+	{
314
+		return new Money(
315
+			$this->calculator()->divide(
316
+				$this->amount(),
317
+				$divisor,
318
+				$this->precision(),
319
+				$rounding_mode
320
+			),
321
+			$this->currency(),
322
+			$this->calculator(),
323
+			$this->formatters()
324
+		);
325
+	}
326
+
327
+
328
+
329
+	/**
330
+	 * @param Currency $other_currency
331
+	 * @throws InvalidArgumentException
332
+	 */
333
+	public function verifySameCurrency(Currency $other_currency)
334
+	{
335
+		if ($this->currency()->equals($other_currency) !== true) {
336
+			throw new InvalidArgumentException(
337
+				esc_html__(
338
+					'Currencies must be the same in order to add or subtract their values.',
339
+					'event_espresso'
340
+				)
341
+			);
342
+		}
343
+	}
344
+
345
+
346
+
347
+	/**
348
+	 * @return string
349
+	 */
350
+	public function __toString()
351
+	{
352
+		return $this->format(MoneyFormatter::DECIMAL_ONLY);
353
+	}
354 354
 
355 355
 
356 356
 
Please login to merge, or discard this patch.
Spacing   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -99,7 +99,7 @@  discard block
 block discarded – undo
99 99
      */
100 100
     private function parseAmount($amount)
101 101
     {
102
-        if (! in_array(gettype($amount), array('integer', 'double', 'string'),true)) {
102
+        if ( ! in_array(gettype($amount), array('integer', 'double', 'string'), true)) {
103 103
             throw new InvalidDataTypeException(
104 104
                 '$amount',
105 105
                 $amount,
@@ -198,11 +198,11 @@  discard block
 block discarded – undo
198 198
         // if we are applying thousands formatting...
199 199
         if ($formatting_level >= MoneyFormatter::ADD_THOUSANDS) {
200 200
             // then let's remove decimal formatting since it's included in thousands formatting
201
-            unset($formatters[ MoneyFormatter::DECIMAL_ONLY ]);
201
+            unset($formatters[MoneyFormatter::DECIMAL_ONLY]);
202 202
         }
203 203
         for ($x = 1; $x <= $formatting_level; $x++) {
204
-            if (isset($formatters[ $x ]) && $formatters[ $x ] instanceof MoneyFormatter) {
205
-                $formatted_amount = $formatters[ $x ]->format($formatted_amount, $this->currency);
204
+            if (isset($formatters[$x]) && $formatters[$x] instanceof MoneyFormatter) {
205
+                $formatted_amount = $formatters[$x]->format($formatted_amount, $this->currency);
206 206
             }
207 207
         }
208 208
         return (string) apply_filters(
Please login to merge, or discard this patch.