Completed
Push — scrutinizer ( f9a285...b1dd77 )
by Ravinder
18:10
created

formatting.php ➔ give_check_variable()   C

Complexity

Conditions 9
Paths 10

Size

Total Lines 23
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 9
eloc 14
nc 10
nop 3
dl 0
loc 23
rs 5.8541
c 0
b 0
f 0
1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 25 and the first side effect is on line 14.

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.

Loading history...
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     https://opensource.org/licenses/gpl-license 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', give_get_option( 'number_decimals', 0 ) );
27
}
28
29
/**
30
 * Get thousand separator
31
 *
32
 * @since 1.6
33
 *
34
 * @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
 *
43
 * @since 1.6
44
 *
45
 * @return mixed
46
 */
47
function give_get_price_decimal_separator() {
48
	return give_get_option( 'decimal_separator', '.' );
49
}
50
51
/**
52
 * Sanitize Amount
53
 *
54
 * Returns a sanitized amount by stripping out thousands separators.
55
 *
56
 * @since      1.0
57
 *
58
 * @param  int|float|string $number     Expects either a float or a string with a decimal separator only (no thousands)
59
 * @param  int|bool         $dp         Number of decimals
60
 * @param  bool             $trim_zeros From end of string
61
 *
62
 * @return string $amount Newly sanitized amount
63
 */
64
function give_sanitize_amount( $number, $dp = false, $trim_zeros = false ) {
65
66
	// Bailout.
67
	if ( empty( $number ) ) {
68
		return $number;
69
	}
70
71
	// Remove slash from amount.
72
	// If thousand or decimal separator is set to ' then in $_POST or $_GET param we will get an escaped number.
73
	// To prevent notices and warning remove slash from amount/number.
74
	$number = wp_unslash( $number );
75
76
	$thousand_separator = give_get_price_thousand_separator();
77
78
	$locale   = localeconv();
79
	$decimals = array( give_get_price_decimal_separator(), $locale['decimal_point'], $locale['mon_decimal_point'] );
80
81
	// Remove locale from string
82
	if ( ! is_float( $number ) ) {
83
		$number = str_replace( $decimals, '.', $number );
84
	}
85
86
	// Remove thousand amount formatting if amount has.
87
	// This condition use to add backward compatibility to version before 1.6, because before version 1.6 we were saving formatted amount to db.
88
	// Do not replace thousand separator from price if it is same as decimal separator, because it will be already replace by above code.
89
	if ( ! in_array( $thousand_separator, $decimals ) && ( false !== strpos( $number, $thousand_separator ) ) ) {
90
		$number = str_replace( $thousand_separator, '', $number );
91
	} elseif ( in_array( $thousand_separator, $decimals ) ) {
92
		$number = preg_replace( '/\.(?=.*\.)/', '', $number );
93
	}
94
95
	// Remove non numeric entity before decimal separator.
96
	$number     = preg_replace( '/[^0-9\.]/', '', $number );
97
	$default_dp = give_get_price_decimals();
98
99
	// Reset negative amount to zero.
100
	if ( 0 > $number ) {
101
		$number = number_format( 0, $default_dp, '.' );
102
	}
103
104
	// If number does not have decimal then add number of decimals to it.
105
	if (
106
		false === strpos( $number, '.' )
107
		|| ( $default_dp > strlen( substr( $number, strpos( $number, '.' ) + 1 ) ) )
108
	) {
109
		$number = number_format( $number, $default_dp, '.', '' );
110
	}
111
112
	// Format number by custom number of decimals.
113
	if ( false !== $dp ) {
114
		$dp     = intval( empty( $dp ) ? $default_dp : $dp );
115
		$dp     = apply_filters( 'give_sanitize_amount_decimals', $dp, $number );
116
		$number = number_format( floatval( $number ), $dp, '.', '' );
117
	}
118
119
	// Trim zeros.
120
	if ( $trim_zeros && strstr( $number, '.' ) ) {
121
		$number = rtrim( rtrim( $number, '0' ), '.' );
122
	}
123
124
	return apply_filters( 'give_sanitize_amount', $number );
125
}
126
127
/**
128
 * Returns a nicely formatted amount.
129
 *
130
 * @since 1.0
131
 *
132
 * @param string $amount   Price amount to format
133
 * @param bool   $decimals Whether or not to use decimals. Useful when set to false for non-currency numbers.
134
 *
135
 * @return string $amount   Newly formatted amount or Price Not Available
136
 */
137
function give_format_amount( $amount, $decimals = true ) {
138
	$thousands_sep = give_get_option( 'thousands_separator', ',' );
139
	$decimal_sep   = give_get_option( 'decimal_separator', '.' );
140
141
	if ( empty( $amount ) ) {
142
		$amount = 0;
143
	} else {
144
		// Sanitize amount before formatting.
145
		$amount = give_sanitize_amount( $amount );
146
	}
147
148
	$decimals = $decimals ? give_get_price_decimals() : 0;
149
150
	$formatted = number_format( $amount, $decimals, $decimal_sep, $thousands_sep );
151
152
	return apply_filters( 'give_format_amount', $formatted, $amount, $decimals, $decimal_sep, $thousands_sep );
153
}
154
155
156
/**
157
 * Get human readable amount.
158
 *
159
 * Note: This function only support large number formatting from million to trillion
160
 *
161
 * @since 1.6
162
 *
163
 * @use   give_get_price_thousand_separator Get thousand separator.
164
 *
165
 * @param string $amount formatted amount number.
166
 *
167
 * @return float|string  formatted amount number with large number names.
168
 */
169
function give_human_format_large_amount( $amount ) {
170
171
	// Get thousand separator.
172
	$thousands_sep = give_get_price_thousand_separator();
173
174
	// Sanitize amount.
175
	$sanitize_amount = give_sanitize_amount( $amount );
176
177
	// Explode amount to calculate name of large numbers.
178
	$amount_array = explode( $thousands_sep, $amount );
179
180
	// Calculate amount parts count.
181
	$amount_count_parts = count( $amount_array );
182
183
	// Human format amount (default).
184
	$human_format_amount = $amount;
185
186
	// Calculate large number formatted amount.
187
	if ( 4 < $amount_count_parts ) {
188
		$human_format_amount = sprintf( esc_html__( '%s trillion', 'give' ), round( ( $sanitize_amount / 1000000000000 ), 2 ) );
189
	} elseif ( 3 < $amount_count_parts ) {
190
		$human_format_amount = sprintf( esc_html__( '%s billion', 'give' ), round( ( $sanitize_amount / 1000000000 ), 2 ) );
191
	} elseif ( 2 < $amount_count_parts ) {
192
		$human_format_amount = sprintf( esc_html__( '%s million', 'give' ), round( ( $sanitize_amount / 1000000 ), 2 ) );
193
	}
194
195
	return apply_filters( 'give_human_format_large_amount', $human_format_amount, $amount, $sanitize_amount );
196
}
197
198
/**
199
 * Returns a nicely formatted amount with custom decimal separator.
200
 *
201
 * @since 1.0
202
 *
203
 * @param int|float|string $amount Formatted or sanitized price
204
 * @param int|bool         $dp     number of decimals
205
 *
206
 * @return string $amount Newly formatted amount or Price Not Available
207
 */
208
function give_format_decimal( $amount, $dp = false ) {
209
	$decimal_separator = give_get_price_decimal_separator();
210
	$formatted_amount  = give_sanitize_amount( $amount, $dp );
211
212
	if ( false !== strpos( $formatted_amount, '.' ) ) {
213
		$formatted_amount = str_replace( '.', $decimal_separator, $formatted_amount );
214
	}
215
216
	return apply_filters( 'give_format_decimal', $formatted_amount, $amount, $decimal_separator );
217
}
218
219
220
/**
221
 * Format Multi-level Amount
222
 *
223
 * Loops through CMB2 repeater field and updates amount field using give_format_amount()
224
 *
225
 * @param $field_args
226
 * @param $field
227
 *
228
 * @return bool
229
 */
230
function give_format_admin_multilevel_amount( $field_args, $field ) {
0 ignored issues
show
Unused Code introduced by
The parameter $field_args is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
231
232
	if ( empty( $field->value ) ) {
233
		return false;
234
	}
235
236
	$field->value = give_format_decimal( $field->value );
237
}
238
239
/**
240
 * Formats the currency display
241
 *
242
 * @since 1.0
243
 *
244
 * @param string $price
245
 * @param string $currency
246
 *
247
 * @return mixed|string
248
 */
249
function give_currency_filter( $price = '', $currency = '' ) {
250
251
	if ( empty( $currency ) ) {
252
		$currency = give_get_currency();
253
	}
254
255
	$position = give_get_option( 'currency_position', 'before' );
256
257
	$negative = $price < 0;
258
259
	if ( $negative ) {
260
		// Remove proceeding "-".
261
		$price = substr( $price, 1 );
262
	}
263
264
	$symbol = give_currency_symbol( $currency );
265
266
	switch ( $currency ) :
267
		case 'GBP' :
268
		case 'BRL' :
269
		case 'EUR' :
270
		case 'USD' :
271
		case 'AUD' :
272
		case 'CAD' :
273
		case 'HKD' :
274
		case 'MXN' :
275
		case 'NZD' :
276
		case 'SGD' :
277
		case 'JPY' :
278
		case 'THB' :
279
		case 'INR' :
280
		case 'RIAL' :
281
		case 'TRY' :
282
		case 'RUB' :
283
		case 'SEK' :
284
		case 'PLN' :
285
		case 'PHP' :
286
		case 'TWD' :
287
		case 'MYR' :
288
		case 'CZK' :
289
		case 'DKK' :
290
		case 'HUF' :
291
		case 'ILS' :
292
		case 'MAD' :
293
		case 'KRW' :
294
		case 'ZAR' :
295
			$formatted = ( 'before' === $position ? $symbol . $price : $price . $symbol );
296
			break;
297
		case 'NOK' :
298
			$formatted = ( 'before' === $position ? $symbol . ' ' . $price : $price . ' ' . $symbol );
299
			break;
300
		default :
301
			$formatted = ( 'before' === $position ? $currency . ' ' . $price : $price . ' ' . $currency );
302
			break;
303
	endswitch;
304
305
	/**
306
	 * Filter formatted amount with currency
307
	 *
308
	 * Filter name depends upon current value of currency and currency position.
309
	 * For example :
310
	 *           if currency is USD and currency position is before then
311
	 *           filter name will be give_usd_currency_filter_before
312
	 *
313
	 *           and if currency is USD and currency position is after then
314
	 *           filter name will be give_usd_currency_filter_after
315
	 */
316
	$formatted = apply_filters( 'give_' . strtolower( $currency ) . "_currency_filter_{$position}", $formatted, $currency, $price );
317
318
	if ( $negative ) {
319
		// Prepend the minus sign before the currency sign.
320
		$formatted = '-' . $formatted;
321
	}
322
323
	return $formatted;
324
}
325
326
/**
327
 * Set the number of decimal places per currency
328
 *
329
 * @since 1.0
330
 * @since 1.6 $decimals parameter removed from function params
331
 * *
332
 * @return int $decimals
333
 */
334
function give_currency_decimal_filter() {
335
336
	remove_filter( 'give_sanitize_amount_decimals', 'give_currency_decimal_filter' );
337
338
	// Set default number of decimals.
339
	$decimals = give_get_price_decimals();
340
341
	add_filter( 'give_sanitize_amount_decimals', 'give_currency_decimal_filter' );
342
343
	// Get number of decimals with backward compatibility ( version < 1.6 )
344
	if ( 1 <= func_num_args() ) {
345
		$decimals = ( false === func_get_arg( 0 ) ? $decimals : absint( func_get_arg( 0 ) ) );
346
	}
347
348
	$currency = give_get_currency();
349
350
	switch ( $currency ) {
351
		case 'RIAL' :
352
		case 'JPY' :
353
		case 'TWD' :
354
		case 'HUF' :
355
356
			$decimals = 0;
357
			break;
358
	}
359
360
	return apply_filters( 'give_currency_decimal_count', $decimals, $currency );
361
}
362
363
add_filter( 'give_sanitize_amount_decimals', 'give_currency_decimal_filter' );
364
add_filter( 'give_format_amount_decimals', 'give_currency_decimal_filter' );
365
366
367
/**
368
 * Get date format string on basis of given context.
369
 *
370
 * @since 1.7
371
 *
372
 * @param  string $date_context Date format context name.
373
 *
374
 * @return string                  Date format string
375
 */
376
function give_date_format( $date_context = '' ) {
377
	/**
378
	 * Filter the date context
379
	 *
380
	 * You can add your own date context or use already exist context.
381
	 * For example:
382
	 *    add_filter( 'give_date_format_contexts', 'add_new_date_contexts' );
383
	 *    function add_new_date_contexts( $date_format_contexts ) {
384
	 *        // You can add single context like this $date_format_contexts['checkout'] = 'F j, Y';
385
	 *        // Instead add multiple date context at once.
386
	 *        $new_date_format_contexts = array(
387
	 *            'checkout' => 'F j, Y',
388
	 *            'report'   => 'Y-m-d',
389
	 *            'email'    => 'm/d/Y',
390
	 *        );
391
	 *
392
	 *       // Merge date contexts array only if you are adding multiple date contexts at once otherwise return  $date_format_contexts.
393
	 *       return array_merge( $new_date_format_contexts, $date_format_contexts );
394
	 *
395
	 *    }
396
	 */
397
	$date_format_contexts = apply_filters( 'give_date_format_contexts', array() );
398
399
	// Set date format to default date format.
400
	$date_format = get_option( 'date_format' );
401
402
	// Update date format if we have non empty date format context array and non empty date format string for that context.
403
	if ( $date_context && ! empty( $date_format_contexts ) && array_key_exists( $date_context, $date_format_contexts ) ) {
404
		$date_format = ! empty( $date_format_contexts[ $date_context ] )
405
			? $date_format_contexts[ $date_context ]
406
			: $date_format;
407
	}
408
409
	return apply_filters( 'give_date_format', $date_format );
410
}
411
412
/**
413
 * Get cache key.
414
 *
415
 * @since  1.7
416
 *
417
 * @param  string $action     Cache key prefix.
418
 * @param array  $query_args Query array.
419
 *
420
 * @return string
421
 */
422
function give_get_cache_key( $action, $query_args ) {
423
	// Bailout.
424
	if ( ! is_array( $query_args ) || empty( $query_args ) ) {
425
		return '';
426
	}
427
428
	return "give_cache_{$action}_" . substr( md5( serialize( $query_args ) ), 0, 15 );
429
}
430
431
/**
432
 * Clean variables using sanitize_text_field. Arrays are cleaned recursively.
433
 * Non-scalar values are ignored.
434
 *
435
 * @since  1.8
436
 *
437
 * @param  string|array $var
438
 *
439
 * @return string|array
440
 */
441
function give_clean( $var ) {
442
	if ( is_array( $var ) ) {
443
		return array_map( 'give_clean', $var );
444
	} else {
445
		return is_scalar( $var ) ? sanitize_text_field( $var ) : $var;
446
	}
447
}
448
449
/**
450
 * Transforms php.ini notation for numbers (like '2M') to an integer.
451
 *
452
 * @since 1.8
453
 *
454
 * @param $size
455
 *
456
 * @return int
457
 */
458
function give_let_to_num( $size ) {
459
	$l   = substr( $size, - 1 );
460
	$ret = substr( $size, 0, - 1 );
461
	switch ( strtoupper( $l ) ) {
462
		case 'P':
463
			$ret *= 1024;
464
		case 'T':
465
			$ret *= 1024;
466
		case 'G':
467
			$ret *= 1024;
468
		case 'M':
469
			$ret *= 1024;
470
		case 'K':
471
			$ret *= 1024;
472
	}
473
474
	return $ret;
475
}
476
477
/**
478
 * Verify nonce.
479
 *
480
 * @since 1.8
481
 *
482
 * @param        $nonce
483
 * @param int   $action
484
 * @param array $wp_die_args
485
 */
486
function give_validate_nonce( $nonce, $action = - 1, $wp_die_args = array() ) {
487
488
	$default_wp_die_args = array(
489
		'message' => esc_html__( 'Nonce verification has failed.', 'give' ),
490
		'title'   => esc_html__( 'Error', 'give' ),
491
		'args'    => array( 'response' => 403 ),
492
	);
493
494
	$wp_die_args = wp_parse_args( $wp_die_args, $default_wp_die_args );
495
496
	if ( ! wp_verify_nonce( $nonce, $action ) ) {
497
		wp_die(
498
			$wp_die_args['message'],
499
			$wp_die_args['title'],
500
			$wp_die_args['args']
501
		);
502
	}
503
}
504
505
/**
506
 * Check variable and get default or valid value.
507
 *
508
 * Helper function to check if a variable is set, empty, etc.
509
 *
510
 * @since 1.8
511
 *
512
 * @param                   $variable
513
 * @param string (optional) $conditional , default value: isset
514
 * @param bool (optional)   $default     , default value: false
515
 *
516
 * @return mixed
517
 */
518
function give_check_variable( $variable, $conditional = '', $default = false ) {
519
520
	switch ( $conditional ) {
521
		case 'isset_empty':
522
			$variable = isset( $variable ) && empty( $variable ) ? $variable : $default;
523
			break;
524
525
		case 'empty':
526
			$variable = empty( $variable ) ? $variable : $default;
527
			break;
528
529
		case 'null':
530
			$variable = is_null( $variable ) ? $variable : $default;
531
			break;
532
533
		default:
534
			$variable = isset( $variable ) ? $variable : $default;
535
536
	}
537
538
	return $variable;
539
540
}
541