|
1
|
|
|
<?php |
|
|
|
|
|
|
2
|
|
|
/** |
|
3
|
|
|
* Formatting functions for taking care of proper number formats and such |
|
4
|
|
|
* |
|
5
|
|
|
* @package Give |
|
6
|
|
|
* @subpackage Functions/Formatting |
|
7
|
|
|
* @copyright Copyright (c) 2016, WordImpress |
|
8
|
|
|
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License |
|
9
|
|
|
* @since 1.0 |
|
10
|
|
|
*/ |
|
11
|
|
|
|
|
12
|
|
|
// Exit if accessed directly |
|
13
|
|
|
if ( ! defined( 'ABSPATH' ) ) { |
|
14
|
|
|
exit; |
|
15
|
|
|
} |
|
16
|
|
|
|
|
17
|
|
|
|
|
18
|
|
|
/** |
|
19
|
|
|
* Get decimal count |
|
20
|
|
|
* |
|
21
|
|
|
* @since 1.6 |
|
22
|
|
|
* |
|
23
|
|
|
* @return mixed |
|
24
|
|
|
*/ |
|
25
|
|
|
function give_get_price_decimals() { |
|
26
|
|
|
return apply_filters( 'give_sanitize_amount_decimals', 2 ); |
|
27
|
|
|
} |
|
28
|
|
|
|
|
29
|
52 |
|
/** |
|
30
|
52 |
|
* Get thousand separator |
|
31
|
52 |
|
* |
|
32
|
|
|
* @since 1.6 |
|
33
|
|
|
* |
|
34
|
52 |
|
* @return mixed |
|
35
|
|
|
*/ |
|
36
|
|
|
function give_get_price_thousand_separator() { |
|
37
|
|
|
return give_get_option( 'thousands_separator', ',' ); |
|
38
|
|
|
} |
|
39
|
|
|
|
|
40
|
|
|
/** |
|
41
|
|
|
* Get decimal separator |
|
42
|
52 |
|
* |
|
43
|
|
|
* @since 1.6 |
|
44
|
|
|
* |
|
45
|
|
|
* @return mixed |
|
46
|
52 |
|
*/ |
|
47
|
|
|
function give_get_price_decimal_separator() { |
|
48
|
|
|
return give_get_option( 'decimal_separator', '.' ); |
|
49
|
|
|
} |
|
50
|
52 |
|
|
|
51
|
52 |
|
/** |
|
52
|
52 |
|
* Sanitize Amount |
|
53
|
|
|
* |
|
54
|
52 |
|
* Returns a sanitized amount by stripping out thousands separators. |
|
55
|
|
|
* |
|
56
|
|
|
* @since 1.0 |
|
57
|
|
|
* |
|
58
|
52 |
|
* @param float|string $number Expects either a float or a string with a decimal separator only (no thousands) |
|
59
|
|
|
* @param bool $trim_zeros From end of string |
|
60
|
|
|
* |
|
61
|
|
|
* |
|
62
|
|
|
* @return string $amount Newly sanitized amount |
|
63
|
|
|
*/ |
|
64
|
|
|
function give_sanitize_amount( $number, $trim_zeros = false ) { |
|
65
|
|
|
$thousand_separator = give_get_price_thousand_separator(); |
|
66
|
|
|
|
|
67
|
|
|
$locale = localeconv(); |
|
68
|
|
|
$decimals = array( give_get_price_decimal_separator(), $locale['decimal_point'], $locale['mon_decimal_point'] ); |
|
69
|
|
|
|
|
70
|
|
|
// Remove locale from string |
|
71
|
|
|
if ( ! is_float( $number ) ) { |
|
72
|
|
|
$number = str_replace( $decimals, '.', $number ); |
|
73
|
43 |
|
} |
|
74
|
43 |
|
|
|
75
|
|
|
// Remove thousand amount formatting if amount has. |
|
76
|
|
|
// This condition use to add backward compatibility to version before 1.6, because before version 1.6 we were saving formatted amount to db. |
|
77
|
43 |
|
// Do not replace thousand separator from price if it is same as decimal separator, because it will be already replace by above code. |
|
78
|
|
|
if( ! in_array( $thousand_separator, $decimals ) && ( false !== strpos( $number, $thousand_separator ) ) ) { |
|
79
|
|
|
$number = str_replace( $thousand_separator, '', $number ); |
|
80
|
|
|
} |
|
81
|
|
|
|
|
82
|
|
|
// Remove non numeric entity before decimal separator. |
|
83
|
|
|
$number = preg_replace( '/[^0-9\.]/', '', $number ); |
|
84
|
43 |
|
|
|
85
|
|
|
$decimals = give_get_price_decimals(); |
|
86
|
|
|
$decimals = apply_filters( 'give_sanitize_amount_decimals', $decimals, $number ); |
|
87
|
|
|
|
|
88
|
|
|
$number = number_format( floatval( $number ), $decimals, '.', '' ); |
|
89
|
43 |
|
|
|
90
|
|
|
// Reset negative amount to zero. |
|
91
|
|
|
if ( 0 > $number ) { |
|
92
|
|
|
$number = number_format( 0, 2, '.' ); |
|
93
|
|
|
} |
|
94
|
|
|
|
|
95
|
|
|
// Trim zeros. |
|
96
|
|
|
if ( $trim_zeros && strstr( $number, '.' ) ) { |
|
97
|
|
|
$number = rtrim( rtrim( $number, '0' ), '.' ); |
|
98
|
|
|
} |
|
99
|
43 |
|
|
|
100
|
|
|
return apply_filters( 'give_sanitize_amount', $number ); |
|
101
|
|
|
} |
|
102
|
|
|
|
|
103
|
43 |
|
/** |
|
104
|
2 |
|
* Returns a nicely formatted amount. |
|
105
|
2 |
|
* |
|
106
|
|
|
* @since 1.0 |
|
107
|
43 |
|
* |
|
108
|
|
|
* @param string $amount Price amount to format |
|
109
|
43 |
|
* @param bool|string $decimals Whether or not to use decimals. Useful when set to false for non-currency numbers. |
|
110
|
|
|
* |
|
111
|
43 |
|
* @return string $amount Newly formatted amount or Price Not Available |
|
112
|
|
|
*/ |
|
113
|
|
|
function give_format_amount( $amount, $decimals = true ) { |
|
114
|
|
|
|
|
115
|
|
|
$thousands_sep = give_get_option( 'thousands_separator', ',' ); |
|
116
|
|
|
$decimal_sep = give_get_option( 'decimal_separator', '.' ); |
|
117
|
|
|
|
|
118
|
|
|
// Format the amount |
|
119
|
|
|
if ( $decimal_sep == ',' && false !== ( $sep_found = strpos( $amount, $decimal_sep ) ) ) { |
|
120
|
|
|
$whole = substr( $amount, 0, $sep_found ); |
|
121
|
|
|
$part = substr( $amount, $sep_found + 1, ( strlen( $amount ) - 1 ) ); |
|
122
|
|
|
$amount = $whole . '.' . $part; |
|
123
|
|
|
} |
|
124
|
|
|
|
|
125
|
|
|
// Strip , from the amount (if set as the thousands separator) |
|
126
|
|
|
if ( $thousands_sep == ',' && false !== ( $found = strpos( $amount, $thousands_sep ) ) ) { |
|
127
|
|
|
$amount = str_replace( ',', '', $amount ); |
|
128
|
|
|
} |
|
129
|
|
|
|
|
130
|
|
|
// Strip . from the amount (if set as the thousands separator) AND , set to decimal separator |
|
131
|
|
|
if ( $thousands_sep == '.' && $decimal_sep == ',' && false !== ( $found = strpos( $amount, $thousands_sep ) ) ) { |
|
132
|
|
|
$amount = explode( '.', $amount ); |
|
133
|
|
|
$array_count = count( $amount ); |
|
134
|
|
|
if ( $decimals == true ) { |
|
135
|
|
|
unset( $amount[ $array_count - 1 ] ); |
|
136
|
|
|
} |
|
137
|
|
|
$amount = implode( '', $amount ); |
|
138
|
|
|
} |
|
139
|
|
|
|
|
140
|
|
|
// Strip ' ' from the amount (if set as the thousands separator) |
|
141
|
|
|
if ( $thousands_sep == ' ' && false !== ( $found = strpos( $amount, $thousands_sep ) ) ) { |
|
142
|
|
|
$amount = str_replace( ' ', '', $amount ); |
|
143
|
|
|
} |
|
144
|
|
|
|
|
145
|
|
|
if ( empty( $amount ) ) { |
|
146
|
45 |
|
$amount = 0; |
|
147
|
45 |
|
} |
|
148
|
45 |
|
|
|
149
|
|
|
$decimals = give_get_price_decimals(); |
|
150
|
45 |
|
|
|
151
|
|
|
$formatted = number_format( $amount, $decimals, $decimal_sep, $thousands_sep ); |
|
152
|
45 |
|
|
|
153
|
|
|
return apply_filters( 'give_format_amount', $formatted, $amount, $decimals, $decimal_sep, $thousands_sep ); |
|
154
|
45 |
|
} |
|
155
|
|
|
|
|
156
|
|
|
|
|
157
|
|
|
/** |
|
158
|
45 |
|
* Get human readable amount. |
|
159
|
|
|
* |
|
160
|
45 |
|
* Note: This function only support large number formatting from million to trillion |
|
161
|
|
|
* |
|
162
|
45 |
|
* @since 1.6 |
|
163
|
45 |
|
* |
|
164
|
45 |
|
* @use give_get_price_thousand_separator Get thousand separator. |
|
165
|
45 |
|
* |
|
166
|
45 |
|
* @param string $amount formatted amount number. |
|
167
|
45 |
|
* @return float|string formatted amount number with large number names. |
|
168
|
45 |
|
*/ |
|
169
|
45 |
|
function give_human_format_large_amount( $amount ) { |
|
170
|
45 |
|
|
|
171
|
45 |
|
// Get thousand separator. |
|
172
|
45 |
|
$thousands_sep = give_get_price_thousand_separator(); |
|
173
|
45 |
|
|
|
174
|
45 |
|
// Sanitize amount. |
|
175
|
45 |
|
$sanitize_amount = give_sanitize_amount( $amount ); |
|
176
|
45 |
|
|
|
177
|
45 |
|
// Explode amount to calculate name of large numbers. |
|
178
|
45 |
|
$amount_array = explode( $thousands_sep, $amount ); |
|
179
|
45 |
|
|
|
180
|
45 |
|
// Calculate amount parts count. |
|
181
|
45 |
|
$amount_count_parts = count( $amount_array ); |
|
182
|
45 |
|
|
|
183
|
45 |
|
// Calculate large number formatted amount. |
|
184
|
45 |
|
if ( 4 < $amount_count_parts ){ |
|
185
|
45 |
|
$sanitize_amount = sprintf( esc_html__( '%s trillion', 'give' ), round( ( $sanitize_amount / 1000000000000 ), 2 ) ); |
|
186
|
45 |
|
} elseif ( 3 < $amount_count_parts ){ |
|
187
|
45 |
|
$sanitize_amount = sprintf( esc_html__( '%s billion', 'give' ), round( ( $sanitize_amount / 1000000000 ), 2 )); |
|
188
|
45 |
|
} elseif ( 2 < $amount_count_parts ) { |
|
189
|
45 |
|
$sanitize_amount = sprintf( esc_html__( '%s million', 'give' ), round( ( $sanitize_amount / 1000000), 2 ) ); |
|
190
|
45 |
|
} else{ |
|
191
|
45 |
|
$sanitize_amount = give_format_amount( $amount ); |
|
192
|
|
|
} |
|
193
|
|
|
|
|
194
|
|
|
return apply_filters( 'give_human_format_large_amount', $sanitize_amount, $amount ); |
|
195
|
|
|
} |
|
196
|
|
|
|
|
197
|
|
|
/** |
|
198
|
|
|
* Returns a nicely formatted amount with custom decimal separator. |
|
199
|
45 |
|
* |
|
200
|
45 |
|
* @since 1.0 |
|
201
|
|
|
* |
|
202
|
|
|
* @param string $amount Formatted or sanitized price |
|
203
|
|
|
* |
|
204
|
|
|
* @return string $amount Newly formatted amount or Price Not Available |
|
205
|
|
|
*/ |
|
206
|
|
|
function give_format_decimal( $amount ){ |
|
207
|
|
|
$decimal_separator = give_get_price_decimal_separator(); |
|
208
|
|
|
$formatted_amount = give_sanitize_amount( $amount ); |
|
209
|
|
|
|
|
210
|
|
|
if( false !== strpos( $formatted_amount, '.' ) ) { |
|
211
|
|
|
$formatted_amount = str_replace( '.', $decimal_separator, $formatted_amount ); |
|
212
|
|
|
} |
|
213
|
|
|
|
|
214
|
|
|
return apply_filters( 'give_format_decimal', $formatted_amount, $amount, $decimal_separator ); |
|
215
|
|
|
} |
|
216
|
|
|
|
|
217
|
|
|
|
|
218
|
|
|
/** |
|
219
|
|
|
* Format Multi-level Amount |
|
220
|
|
|
* |
|
221
|
|
|
* Loops through CMB2 repeater field and updates amount field using give_format_amount() |
|
222
|
|
|
* |
|
223
|
|
|
* @param $field_args |
|
224
|
|
|
* @param $field |
|
225
|
|
|
* |
|
226
|
|
|
* @return bool |
|
227
|
|
|
*/ |
|
228
|
|
|
function give_format_admin_multilevel_amount( $field_args, $field ) { |
|
|
|
|
|
|
229
|
|
|
|
|
230
|
|
|
if ( empty( $field->value ) ) { |
|
231
|
|
|
return false; |
|
232
|
|
|
} |
|
233
|
|
|
|
|
234
|
|
|
$field->value = give_format_decimal( $field->value ); |
|
235
|
|
|
} |
|
236
|
|
|
|
|
237
|
|
|
/** |
|
238
|
45 |
|
* Formats the currency display |
|
239
|
|
|
* |
|
240
|
|
|
* @since 1.0 |
|
241
|
|
|
* |
|
242
|
|
|
* @param string $price |
|
243
|
45 |
|
* @param string $currency |
|
244
|
|
|
* |
|
245
|
|
|
* @return mixed|string|void |
|
246
|
|
|
*/ |
|
247
|
|
|
function give_currency_filter( $price = '', $currency = '' ) { |
|
248
|
|
|
|
|
249
|
|
|
if ( empty( $currency ) ) { |
|
250
|
|
|
$currency = give_get_currency(); |
|
251
|
|
|
} |
|
252
|
|
|
|
|
253
|
|
|
$position = give_get_option( 'currency_position', 'before' ); |
|
254
|
|
|
|
|
255
|
|
|
$negative = $price < 0; |
|
256
|
|
|
|
|
257
|
55 |
|
if ( $negative ) { |
|
258
|
|
|
$price = substr( $price, 1 ); // Remove proceeding "-" - |
|
259
|
|
|
} |
|
260
|
55 |
|
|
|
261
|
55 |
|
$symbol = give_currency_symbol( $currency ); |
|
262
|
55 |
|
|
|
263
|
55 |
|
if ( $position == 'before' ): |
|
264
|
|
|
switch ( $currency ): |
|
265
|
|
|
case 'GBP' : |
|
266
|
|
|
case 'BRL' : |
|
267
|
|
|
case 'EUR' : |
|
268
|
|
|
case 'USD' : |
|
269
|
55 |
|
case 'AUD' : |
|
270
|
|
|
case 'CAD' : |
|
271
|
|
|
case 'HKD' : |
|
272
|
|
|
case 'MXN' : |
|
273
|
|
|
case 'NZD' : |
|
274
|
|
|
case 'SGD' : |
|
275
|
|
|
case 'JPY' : |
|
276
|
|
|
case 'THB' : |
|
277
|
|
|
case 'INR' : |
|
278
|
|
|
case 'RIAL' : |
|
279
|
|
|
case 'TRY' : |
|
280
|
|
|
case 'RUB' : |
|
281
|
|
|
case 'SEK' : |
|
282
|
|
|
case 'PLN' : |
|
283
|
|
|
case 'PHP' : |
|
284
|
|
|
case 'TWD' : |
|
285
|
|
|
case 'MYR' : |
|
286
|
|
|
case 'CZK' : |
|
287
|
|
|
case 'DKK' : |
|
288
|
|
|
case 'HUF' : |
|
289
|
|
|
case 'ILS' : |
|
290
|
|
|
case 'MAD' : |
|
291
|
|
|
case 'KRW' : |
|
292
|
|
|
case 'ZAR' : |
|
293
|
|
|
$formatted = $symbol . $price; |
|
294
|
|
|
break; |
|
295
|
|
|
case 'NOK' : |
|
296
|
|
|
$formatted = $symbol . ' ' . $price; |
|
297
|
|
|
break; |
|
298
|
|
|
default : |
|
299
|
|
|
$formatted = $currency . ' ' . $price; |
|
300
|
|
|
break; |
|
301
|
|
|
endswitch; |
|
302
|
|
|
$formatted = apply_filters( 'give_' . strtolower( $currency ) . '_currency_filter_before', $formatted, $currency, $price ); |
|
303
|
|
|
else : |
|
304
|
|
|
switch ( $currency ) : |
|
305
|
|
|
case 'GBP' : |
|
306
|
|
|
case 'BRL' : |
|
307
|
|
|
case 'EUR' : |
|
308
|
|
|
case 'USD' : |
|
309
|
|
|
case 'AUD' : |
|
310
|
|
|
case 'CAD' : |
|
311
|
|
|
case 'HKD' : |
|
312
|
|
|
case 'MXN' : |
|
313
|
|
|
case 'SGD' : |
|
314
|
|
|
case 'JPY' : |
|
315
|
|
|
case 'THB' : |
|
316
|
|
|
case 'INR' : |
|
317
|
|
|
case 'RIAL' : |
|
318
|
|
|
case 'TRY' : |
|
319
|
|
|
case 'RUB' : |
|
320
|
|
|
case 'SEK' : |
|
321
|
|
|
case 'PLN' : |
|
322
|
|
|
case 'PHP' : |
|
323
|
|
|
case 'TWD' : |
|
324
|
|
|
case 'CZK' : |
|
325
|
|
|
case 'DKK' : |
|
326
|
|
|
case 'HUF' : |
|
327
|
|
|
case 'MYR' : |
|
328
|
|
|
case 'ILS' : |
|
329
|
|
|
case 'MAD' : |
|
330
|
|
|
case 'KRW' : |
|
331
|
|
|
case 'ZAR' : |
|
332
|
|
|
$formatted = $price . $symbol; |
|
333
|
|
|
break; |
|
334
|
|
|
default : |
|
335
|
|
|
$formatted = $price . ' ' . $currency; |
|
336
|
|
|
break; |
|
337
|
|
|
endswitch; |
|
338
|
|
|
$formatted = apply_filters( 'give_' . strtolower( $currency ) . '_currency_filter_after', $formatted, $currency, $price ); |
|
339
|
|
|
endif; |
|
340
|
|
|
|
|
341
|
|
|
if ( $negative ) { |
|
342
|
|
|
// Prepend the mins sign before the currency sign |
|
343
|
|
|
$formatted = '-' . $formatted; |
|
344
|
|
|
} |
|
345
|
|
|
|
|
346
|
|
|
return $formatted; |
|
347
|
|
|
} |
|
348
|
|
|
|
|
349
|
|
|
/** |
|
350
|
|
|
* Set the number of decimal places per currency |
|
351
|
|
|
* |
|
352
|
|
|
* @since 1.0 |
|
353
|
|
|
* |
|
354
|
|
|
* @param int $decimals Number of decimal places |
|
355
|
|
|
* |
|
356
|
|
|
* @return int $decimals |
|
357
|
|
|
*/ |
|
358
|
|
|
function give_currency_decimal_filter( $decimals = 2 ) { |
|
359
|
|
|
|
|
360
|
|
|
$currency = give_get_currency(); |
|
361
|
|
|
|
|
362
|
|
|
switch ( $currency ) { |
|
363
|
|
|
case 'RIAL' : |
|
364
|
|
|
case 'JPY' : |
|
365
|
|
|
case 'TWD' : |
|
366
|
|
|
case 'HUF' : |
|
367
|
|
|
|
|
368
|
|
|
$decimals = 0; |
|
369
|
|
|
break; |
|
370
|
|
|
} |
|
371
|
|
|
|
|
372
|
|
|
return apply_filters( 'give_currency_decimal_count', $decimals, $currency ); |
|
373
|
|
|
} |
|
374
|
|
|
|
|
375
|
|
|
add_filter( 'give_sanitize_amount_decimals', 'give_currency_decimal_filter' ); |
|
376
|
|
|
add_filter( 'give_format_amount_decimals', 'give_currency_decimal_filter' ); |
|
377
|
|
|
|
|
378
|
|
|
/** |
|
379
|
|
|
* Sanitize thousand separator |
|
380
|
|
|
* |
|
381
|
|
|
* @since 1.6 |
|
382
|
|
|
* |
|
383
|
|
|
* @param string $value |
|
384
|
|
|
* @param array $field_args |
|
385
|
|
|
* @param object $field |
|
386
|
|
|
* |
|
387
|
|
|
* @return mixed |
|
388
|
|
|
*/ |
|
389
|
|
|
function give_sanitize_thousand_separator( $value, $field_args, $field ){ |
|
|
|
|
|
|
390
|
|
|
return $value; |
|
391
|
|
|
} |
The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.
The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.
To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.