Issues (1182)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

includes/wc-formatting-functions.php (10 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

Code
1
<?php
2
/**
3
 * WooCommerce Formatting
4
 *
5
 * Functions for formatting data.
6
 *
7
 * @author 		WooThemes
8
 * @category 	Core
9
 * @package 	WooCommerce/Functions
10
 * @version     2.1.0
11
 */
12
13
if ( ! defined( 'ABSPATH' ) ) {
14
	exit; // Exit if accessed directly
15
}
16
17
/**
18
 * Sanitize taxonomy names. Slug format (no spaces, lowercase).
19
 *
20
 * urldecode is used to reverse munging of UTF8 characters.
21
 *
22
 * @param mixed $taxonomy
23
 * @return string
24
 */
25
function wc_sanitize_taxonomy_name( $taxonomy ) {
26
	return apply_filters( 'sanitize_taxonomy_name', urldecode( sanitize_title( $taxonomy ) ), $taxonomy );
27
}
28
29
/**
30
 * Gets the filename part of a download URL.
31
 *
32
 * @param string $file_url
33
 * @return string
34
 */
35
function wc_get_filename_from_url( $file_url ) {
36
	$parts = parse_url( $file_url );
37
	if ( isset( $parts['path'] ) ) {
38
		return basename( $parts['path'] );
39
	}
40
}
41
42
/**
43
 * Normalise dimensions, unify to cm then convert to wanted unit value.
44
 *
45
 * Usage:
46
 * wc_get_dimension(55, 'in');
47
 * wc_get_dimension(55, 'in', 'm');
48
 *
49
 * @param int|float $dimension
50
 * @param string $to_unit 'in', 'm', 'cm', 'm'
51
 * @param string $from_unit (optional) 'in', 'm', 'cm', 'm'
52
 * @return float
53
 */
54
function wc_get_dimension( $dimension, $to_unit, $from_unit = '' ) {
55
	$to_unit = strtolower( $to_unit );
56
57
	if ( empty( $from_unit ) ) {
58
		$from_unit = strtolower( get_option( 'woocommerce_dimension_unit' ) );
59
	}
60
61
	// Unify all units to cm first.
62
	if ( $from_unit !== $to_unit ) {
63 View Code Duplication
		switch ( $from_unit ) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
64
			case 'in' :
65
				$dimension *= 2.54;
66
				break;
67
			case 'm' :
68
				$dimension *= 100;
69
				break;
70
			case 'mm' :
71
				$dimension *= 0.1;
72
				break;
73
			case 'yd' :
74
				$dimension *= 91.44;
75
				break;
76
		}
77
78
		// Output desired unit.
79 View Code Duplication
		switch ( $to_unit ) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
80
			case 'in' :
81
				$dimension *= 0.3937;
82
				break;
83
			case 'm' :
84
				$dimension *= 0.01;
85
				break;
86
			case 'mm' :
87
				$dimension *= 10;
88
				break;
89
			case 'yd' :
90
				$dimension *= 0.010936133;
91
				break;
92
		}
93
	}
94
95
	return ( $dimension < 0 ) ? 0 : $dimension;
96
}
97
98
/**
99
 * Normalise weights, unify to kg then convert to wanted unit value.
100
 *
101
 * Usage:
102
 * wc_get_weight(55, 'kg');
103
 * wc_get_weight(55, 'kg', 'lbs');
104
 *
105
 * @param int|float $weight
106
 * @param string $to_unit 'g', 'kg', 'lbs', 'oz'
107
 * @param string $from_unit (optional) 'g', 'kg', 'lbs', 'oz'
108
 * @return float
109
 */
110
function wc_get_weight( $weight, $to_unit, $from_unit = '' ) {
111
	$to_unit = strtolower( $to_unit );
112
113
	if ( empty( $from_unit ) ) {
114
		$from_unit = strtolower( get_option( 'woocommerce_weight_unit' ) );
115
	}
116
117
	// Unify all units to kg first.
118
	if ( $from_unit !== $to_unit ) {
119
		switch ( $from_unit ) {
120
			case 'g' :
121
				$weight *= 0.001;
122
				break;
123
			case 'lbs' :
124
				$weight *= 0.453592;
125
				break;
126
			case 'oz' :
127
				$weight *= 0.0283495;
128
				break;
129
		}
130
131
		// Output desired unit.
132
		switch ( $to_unit ) {
133
			case 'g' :
134
				$weight *= 1000;
135
				break;
136
			case 'lbs' :
137
				$weight *= 2.20462;
138
				break;
139
			case 'oz' :
140
				$weight *= 35.274;
141
				break;
142
		}
143
	}
144
145
	return ( $weight < 0 ) ? 0 : $weight;
146
}
147
148
/**
149
 * Trim trailing zeros off prices.
150
 *
151
 * @param mixed $price
152
 * @return string
153
 */
154
function wc_trim_zeros( $price ) {
155
	return preg_replace( '/' . preg_quote( wc_get_price_decimal_separator(), '/' ) . '0++$/', '', $price );
156
}
157
158
/**
159
 * Round a tax amount.
160
 *
161
 * @param mixed $tax
162
 * @return double
163
 */
164
function wc_round_tax_total( $tax ) {
165
	$dp = wc_get_price_decimals();
166
167
	// @codeCoverageIgnoreStart
168
	if ( version_compare( phpversion(), '5.3', '<' ) ) {
169
		$rounded_tax = round( $tax, $dp );
170
	} else {
171
		// @codeCoverageIgnoreEnd
172
		$rounded_tax = round( $tax, $dp, WC_TAX_ROUNDING_MODE );
173
	}
174
	return apply_filters( 'wc_round_tax_total', $rounded_tax, $tax, $dp, WC_TAX_ROUNDING_MODE );
175
}
176
177
/**
178
 * Make a refund total negative.
179
 * @return float
180
 */
181
function wc_format_refund_total( $amount ) {
182
	return $amount * -1;
183
}
184
185
/**
186
 * Format decimal numbers ready for DB storage.
187
 *
188
 * Sanitize, remove locale formatting, and optionally round + trim off zeros.
189
 *
190
 * @param  float|string $number Expects either a float or a string with a decimal separator only (no thousands)
191
 * @param  mixed $dp number of decimal points to use, blank to use woocommerce_price_num_decimals, or false to avoid all rounding.
192
 * @param  bool $trim_zeros from end of string
193
 * @return string
194
 */
195
function wc_format_decimal( $number, $dp = false, $trim_zeros = false ) {
196
	$locale   = localeconv();
197
	$decimals = array( wc_get_price_decimal_separator(), $locale['decimal_point'], $locale['mon_decimal_point'] );
198
199
	// Remove locale from string
200
	if ( ! is_float( $number ) ) {
201
		$number = wc_clean( str_replace( $decimals, '.', $number ) );
202
	}
203
204
	if ( $dp !== false ) {
205
		$dp     = intval( $dp == "" ? wc_get_price_decimals() : $dp );
206
		$number = number_format( floatval( $number ), $dp, '.', '' );
207
208
	// DP is false - don't use number format, just return a string in our format
209
	} elseif ( is_float( $number ) ) {
210
		$number = wc_clean( str_replace( $decimals, '.', strval( $number ) ) );
211
	}
212
213
	if ( $trim_zeros && strstr( $number, '.' ) ) {
214
		$number = rtrim( rtrim( $number, '0' ), '.' );
215
	}
216
217
	return $number;
218
}
219
220
/**
221
 * Convert a float to a string without locale formatting which PHP adds when changing floats to strings.
222
 * @param  float $float
223
 * @return string
224
 */
225
function wc_float_to_string( $float ) {
226
	if ( ! is_float( $float ) ) {
227
		return $float;
228
	}
229
230
	$locale = localeconv();
231
	$string = strval( $float );
232
	$string = str_replace( $locale['decimal_point'], '.', $string );
233
234
	return $string;
235
}
236
237
/**
238
 * Format a price with WC Currency Locale settings.
239
 * @param  string $value
240
 * @return string
241
 */
242
function wc_format_localized_price( $value ) {
243
	return str_replace( '.', wc_get_price_decimal_separator(), strval( $value ) );
244
}
245
246
/**
247
 * Format a decimal with PHP Locale settings.
248
 * @param  string $value
249
 * @return string
250
 */
251
function wc_format_localized_decimal( $value ) {
252
	$locale = localeconv();
253
	return str_replace( '.', $locale['decimal_point'], strval( $value ) );
254
}
255
256
/**
257
 * Clean variables using sanitize_text_field. Arrays are cleaned recursively.
258
 * Non-scalar values are ignored.
259
 * @param string|array $var
260
 * @return string|array
261
 */
262
function wc_clean( $var ) {
263
	if ( is_array( $var ) ) {
264
		return array_map( 'wc_clean', $var );
265
	} else {
266
		return is_scalar( $var ) ? sanitize_text_field( $var ) : $var;
267
	}
268
}
269
270
/**
271
 * Sanitize a string destined to be a tooltip.
272
 *
273
 * @since 2.3.10 Tooltips are encoded with htmlspecialchars to prevent XSS. Should not be used in conjunction with esc_attr()
274
 * @param string $var
275
 * @return string
276
 */
277
function wc_sanitize_tooltip( $var ) {
278
	return htmlspecialchars( wp_kses( html_entity_decode( $var ), array(
279
		'br'     => array(),
280
		'em'     => array(),
281
		'strong' => array(),
282
		'small'  => array(),
283
		'span'   => array(),
284
		'ul'     => array(),
285
		'li'     => array(),
286
		'ol'     => array(),
287
		'p'      => array(),
288
    ) ) );
289
}
290
291
/**
292
 * Merge two arrays.
293
 *
294
 * @param array $a1
295
 * @param array $a2
296
 * @return array
297
 */
298
function wc_array_overlay( $a1, $a2 ) {
299
	foreach ( $a1 as $k => $v ) {
300
		if ( ! array_key_exists( $k, $a2 ) ) {
301
			continue;
302
		}
303
		if ( is_array( $v ) && is_array( $a2[ $k ] ) ) {
304
			$a1[ $k ] = wc_array_overlay( $v, $a2[ $k ] );
305
		} else {
306
			$a1[ $k ] = $a2[ $k ];
307
		}
308
	}
309
	return $a1;
310
}
311
312
/**
313
 * Formats a stock amount by running it through a filter.
314
 * @param  int|float $amount
315
 * @return int|float
316
 */
317
function wc_stock_amount( $amount ) {
318
	return apply_filters( 'woocommerce_stock_amount', $amount );
319
}
320
321
/**
322
 * Get the price format depending on the currency position.
323
 *
324
 * @return string
325
 */
326
function get_woocommerce_price_format() {
327
	$currency_pos = get_option( 'woocommerce_currency_pos' );
328
	$format = '%1$s%2$s';
329
330
	switch ( $currency_pos ) {
331
		case 'left' :
332
			$format = '%1$s%2$s';
333
		break;
334
		case 'right' :
335
			$format = '%2$s%1$s';
336
		break;
337
		case 'left_space' :
338
			$format = '%1$s&nbsp;%2$s';
339
		break;
340
		case 'right_space' :
341
			$format = '%2$s&nbsp;%1$s';
342
		break;
343
	}
344
345
	return apply_filters( 'woocommerce_price_format', $format, $currency_pos );
346
}
347
348
/**
349
 * Return the thousand separator for prices.
350
 * @since  2.3
351
 * @return string
352
 */
353
function wc_get_price_thousand_separator() {
354
	$separator = stripslashes( get_option( 'woocommerce_price_thousand_sep' ) );
355
	return $separator;
356
}
357
358
/**
359
 * Return the decimal separator for prices.
360
 * @since  2.3
361
 * @return string
362
 */
363
function wc_get_price_decimal_separator() {
364
	$separator = stripslashes( get_option( 'woocommerce_price_decimal_sep' ) );
365
	return $separator ? $separator : '.';
366
}
367
368
/**
369
 * Return the number of decimals after the decimal point.
370
 * @since  2.3
371
 * @return int
372
 */
373
function wc_get_price_decimals() {
374
	return absint( get_option( 'woocommerce_price_num_decimals', 2 ) );
375
}
376
377
/**
378
 * Format the price with a currency symbol.
379
 *
380
 * @param float $price
381
 * @param array $args (default: array())
382
 * @return string
383
 */
384
function wc_price( $price, $args = array() ) {
385
	extract( apply_filters( 'wc_price_args', wp_parse_args( $args, array(
386
		'ex_tax_label'       => false,
387
		'currency'           => '',
388
		'decimal_separator'  => wc_get_price_decimal_separator(),
389
		'thousand_separator' => wc_get_price_thousand_separator(),
390
		'decimals'           => wc_get_price_decimals(),
391
		'price_format'       => get_woocommerce_price_format()
392
	) ) ) );
393
394
	$negative        = $price < 0;
395
	$price           = apply_filters( 'raw_woocommerce_price', floatval( $negative ? $price * -1 : $price ) );
396
	$price           = apply_filters( 'formatted_woocommerce_price', number_format( $price, $decimals, $decimal_separator, $thousand_separator ), $price, $decimals, $decimal_separator, $thousand_separator );
397
398
	if ( apply_filters( 'woocommerce_price_trim_zeros', false ) && $decimals > 0 ) {
399
		$price = wc_trim_zeros( $price );
400
	}
401
402
	$formatted_price = ( $negative ? '-' : '' ) . sprintf( $price_format, '<span class="woocommerce-Price-currencySymbol">' . get_woocommerce_currency_symbol( $currency ) . '</span>', $price );
403
	$return          = '<span class="woocommerce-Price-amount amount">' . $formatted_price . '</span>';
404
405
	if ( $ex_tax_label && wc_tax_enabled() ) {
406
		$return .= ' <small class="woocommerce-Price-taxLabel tax_label">' . WC()->countries->ex_tax_or_vat() . '</small>';
407
	}
408
409
	return apply_filters( 'wc_price', $return, $price, $args );
410
}
411
412
/**
413
 * let_to_num function.
414
 *
415
 * This function transforms the php.ini notation for numbers (like '2M') to an integer.
416
 *
417
 * @param $size
418
 * @return int
419
 */
420
function wc_let_to_num( $size ) {
421
	$l   = substr( $size, -1 );
422
	$ret = substr( $size, 0, -1 );
423
	switch ( strtoupper( $l ) ) {
424
		case 'P':
425
			$ret *= 1024;
426
		case 'T':
427
			$ret *= 1024;
428
		case 'G':
429
			$ret *= 1024;
430
		case 'M':
431
			$ret *= 1024;
432
		case 'K':
433
			$ret *= 1024;
434
	}
435
	return $ret;
436
}
437
438
/**
439
 * WooCommerce Date Format - Allows to change date format for everything WooCommerce.
440
 *
441
 * @return string
442
 */
443
function wc_date_format() {
444
	return apply_filters( 'woocommerce_date_format', get_option( 'date_format' ) );
445
}
446
447
/**
448
 * WooCommerce Time Format - Allows to change time format for everything WooCommerce.
449
 *
450
 * @return string
451
 */
452
function wc_time_format() {
453
	return apply_filters( 'woocommerce_time_format', get_option( 'time_format' ) );
454
}
455
456
/**
457
 * WooCommerce Timezone - helper to retrieve the timezone string for a site until.
458
 * a WP core method exists (see https://core.trac.wordpress.org/ticket/24730).
459
 *
460
 * Adapted from https://secure.php.net/manual/en/function.timezone-name-from-abbr.php#89155.
461
 *
462
 * @since 2.1
463
 * @return string a valid PHP timezone string for the site
464
 */
465
function wc_timezone_string() {
466
467
	// if site timezone string exists, return it
468
	if ( $timezone = get_option( 'timezone_string' ) ) {
469
		return $timezone;
470
	}
471
472
	// get UTC offset, if it isn't set then return UTC
473
	if ( 0 === ( $utc_offset = get_option( 'gmt_offset', 0 ) ) ) {
474
		return 'UTC';
475
	}
476
477
	// adjust UTC offset from hours to seconds
478
	$utc_offset *= 3600;
479
480
	// attempt to guess the timezone string from the UTC offset
481
	$timezone = timezone_name_from_abbr( '', $utc_offset, 0 );
482
483
	// last try, guess timezone string manually
484
	if ( false === $timezone ) {
485
		$is_dst = date( 'I' );
486
487
		foreach ( timezone_abbreviations_list() as $abbr ) {
488
			foreach ( $abbr as $city ) {
489
				if ( $city['dst'] == $is_dst && $city['offset'] == $utc_offset ) {
490
					return $city['timezone_id'];
491
				}
492
			}
493
		}
494
495
		// fallback to UTC
496
		return 'UTC';
497
	}
498
499
	return $timezone;
500
}
501
502
if ( ! function_exists( 'wc_rgb_from_hex' ) ) {
503
504
	/**
505
	 * Hex darker/lighter/contrast functions for colours.
506
	 *
507
	 * @param mixed $color
508
	 * @return string
509
	 */
510
	function wc_rgb_from_hex( $color ) {
511
		$color = str_replace( '#', '', $color );
512
		// Convert shorthand colors to full format, e.g. "FFF" -> "FFFFFF"
513
		$color = preg_replace( '~^(.)(.)(.)$~', '$1$1$2$2$3$3', $color );
514
515
		$rgb      = array();
516
		$rgb['R'] = hexdec( $color{0}.$color{1} );
517
		$rgb['G'] = hexdec( $color{2}.$color{3} );
518
		$rgb['B'] = hexdec( $color{4}.$color{5} );
519
520
		return $rgb;
521
	}
522
}
523
524 View Code Duplication
if ( ! function_exists( 'wc_hex_darker' ) ) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
525
526
	/**
527
	 * Hex darker/lighter/contrast functions for colours.
528
	 *
529
	 * @param mixed $color
530
	 * @param int $factor (default: 30)
531
	 * @return string
532
	 */
533
	function wc_hex_darker( $color, $factor = 30 ) {
534
		$base  = wc_rgb_from_hex( $color );
535
		$color = '#';
536
537
		foreach ( $base as $k => $v ) {
538
			$amount      = $v / 100;
539
			$amount      = round( $amount * $factor );
540
			$new_decimal = $v - $amount;
541
542
			$new_hex_component = dechex( $new_decimal );
543
			if ( strlen( $new_hex_component ) < 2 ) {
544
				$new_hex_component = "0" . $new_hex_component;
545
			}
546
			$color .= $new_hex_component;
547
		}
548
549
		return $color;
550
	}
551
}
552
553 View Code Duplication
if ( ! function_exists( 'wc_hex_lighter' ) ) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
554
555
	/**
556
	 * Hex darker/lighter/contrast functions for colours.
557
	 *
558
	 * @param mixed $color
559
	 * @param int $factor (default: 30)
560
	 * @return string
561
	 */
562
	function wc_hex_lighter( $color, $factor = 30 ) {
563
		$base  = wc_rgb_from_hex( $color );
564
		$color = '#';
565
566
		foreach ( $base as $k => $v ) {
567
			$amount      = 255 - $v;
568
			$amount      = $amount / 100;
569
			$amount      = round( $amount * $factor );
570
			$new_decimal = $v + $amount;
571
572
			$new_hex_component = dechex( $new_decimal );
573
			if ( strlen( $new_hex_component ) < 2 ) {
574
				$new_hex_component = "0" . $new_hex_component;
575
			}
576
			$color .= $new_hex_component;
577
		}
578
579
		return $color;
580
	}
581
}
582
583
if ( ! function_exists( 'wc_light_or_dark' ) ) {
584
585
	/**
586
	 * Detect if we should use a light or dark colour on a background colour.
587
	 *
588
	 * @param mixed $color
589
	 * @param string $dark (default: '#000000')
590
	 * @param string $light (default: '#FFFFFF')
591
	 * @return string
592
	 */
593
	function wc_light_or_dark( $color, $dark = '#000000', $light = '#FFFFFF' ) {
594
595
		$hex = str_replace( '#', '', $color );
596
597
		$c_r = hexdec( substr( $hex, 0, 2 ) );
598
		$c_g = hexdec( substr( $hex, 2, 2 ) );
599
		$c_b = hexdec( substr( $hex, 4, 2 ) );
600
601
		$brightness = ( ( $c_r * 299 ) + ( $c_g * 587 ) + ( $c_b * 114 ) ) / 1000;
602
603
		return $brightness > 155 ? $dark : $light;
604
	}
605
}
606
607
if ( ! function_exists( 'wc_format_hex' ) ) {
608
609
	/**
610
	 * Format string as hex.
611
	 *
612
	 * @param string $hex
613
	 * @return string
614
	 */
615
	function wc_format_hex( $hex ) {
616
617
		$hex = trim( str_replace( '#', '', $hex ) );
618
619
		if ( strlen( $hex ) == 3 ) {
620
			$hex = $hex[0] . $hex[0] . $hex[1] . $hex[1] . $hex[2] . $hex[2];
621
		}
622
623
		return $hex ? '#' . $hex : null;
624
	}
625
}
626
627
/**
628
 * Format the postcode according to the country and length of the postcode.
629
 *
630
 * @param string $postcode
631
 * @param string $country
632
 * @return string Formatted postcode.
633
 */
634
function wc_format_postcode( $postcode, $country ) {
635
	$postcode = wc_normalize_postcode( $postcode );
636
637
	switch ( $country ) {
638
		case 'CA' :
639
		case 'GB' :
640
			$postcode = trim( substr_replace( $postcode, ' ', -3, 0 ) );
641
			break;
642
		case 'BR' :
643
			$postcode = trim( substr_replace( $postcode, '-', -3, 0 ) );
644
			break;
645
	}
646
647
	return apply_filters( 'woocommerce_format_postcode', $postcode, $country );
648
}
649
650
/**
651
 * Normalize postcodes.
652
 *
653
 * Remove spaces and convert characters to uppercase.
654
 *
655
 * @since 2.6.0
656
 * @param string $postcode
657
 * @return string Sanitized postcode.
658
 */
659
function wc_normalize_postcode( $postcode ) {
660
	return trim( preg_replace( '/[\s\-]/', '', strtoupper( $postcode ) ) );
661
}
662
663
/**
664
 * format_phone function.
665
 *
666
 * @param mixed $tel
667
 * @return string
668
 */
669
function wc_format_phone_number( $tel ) {
670
	return str_replace( '.', '-', $tel );
671
}
672
673
/**
674
 * Make a string lowercase.
675
 * Try to use mb_strtolower() when available.
676
 *
677
 * @since  2.3
678
 * @param  string $string
679
 * @return string
680
 */
681
function wc_strtolower( $string ) {
682
	return function_exists( 'mb_strtolower' ) ? mb_strtolower( $string ) : strtolower( $string );
683
}
684
685
/**
686
 * Trim a string and append a suffix.
687
 * @param  string  $string
688
 * @param  integer $chars
689
 * @param  string  $suffix
690
 * @return string
691
 */
692
function wc_trim_string( $string, $chars = 200, $suffix = '...' ) {
693
	if ( strlen( $string ) > $chars ) {
694
		if ( function_exists( 'mb_substr' ) ) {
695
			$string = mb_substr( $string, 0, ( $chars - mb_strlen( $suffix ) ) ) . $suffix;
696
		} else {
697
			$string = substr( $string, 0, ( $chars - strlen( $suffix ) ) ) . $suffix;
698
		}
699
	}
700
	return $string;
701
}
702
703
/**
704
 * Format content to display shortcodes.
705
 *
706
 * @since  2.3.0
707
 * @param  string $raw_string
708
 * @return string
709
 */
710
function wc_format_content( $raw_string ) {
711
	return apply_filters( 'woocommerce_format_content', do_shortcode( shortcode_unautop( wpautop( $raw_string ) ) ), $raw_string );
712
}
713
714
/**
715
 * Format product short description.
716
 * Adds support for Jetpack Markdown.
717
 *
718
 * @since  2.4.0
719
 * @param  string $content
720
 * @return string
721
 */
722
function wc_format_product_short_description( $content ) {
723
	// Add support for Jetpack Markdown
724
	if ( class_exists( 'WPCom_Markdown' ) ) {
725
		$markdown = WPCom_Markdown::get_instance();
726
727
		return wpautop( $markdown->transform( $content, array( 'unslash' => false ) ) );
728
	}
729
730
	return $content;
731
}
732
733
add_filter( 'woocommerce_short_description', 'wc_format_product_short_description', 9999999 );
734
735
/**
736
 * Formats curency symbols when saved in settings.
737
 * @param  string $value
738
 * @param  array $option
739
 * @param  string $raw_value
740
 * @return string
741
 */
742
function wc_format_option_price_separators( $value, $option, $raw_value ) {
0 ignored issues
show
The parameter $value 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...
The parameter $option 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...
743
	return wp_kses_post( $raw_value );
744
}
745
add_filter( 'woocommerce_admin_settings_sanitize_option_woocommerce_price_decimal_sep', 'wc_format_option_price_separators', 10, 3 );
746
add_filter( 'woocommerce_admin_settings_sanitize_option_woocommerce_price_thousand_sep', 'wc_format_option_price_separators', 10, 3 );
747
748
/**
749
 * Formats decimals when saved in settings.
750
 * @param  string $value
751
 * @param  array $option
752
 * @param  string $raw_value
753
 * @return string
754
 */
755
function wc_format_option_price_num_decimals( $value, $option, $raw_value ) {
0 ignored issues
show
The parameter $value 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...
The parameter $option 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...
756
	return is_null( $raw_value ) ? 2 : absint( $raw_value );
757
}
758
add_filter( 'woocommerce_admin_settings_sanitize_option_woocommerce_price_num_decimals', 'wc_format_option_price_num_decimals', 10, 3 );
759
760
/**
761
 * Formats hold stock option and sets cron event up.
762
 * @param  string $value
763
 * @param  array $option
764
 * @param  string $raw_value
765
 * @return string
766
 */
767
function wc_format_option_hold_stock_minutes( $value, $option, $raw_value ) {
0 ignored issues
show
The parameter $value 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...
The parameter $option 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...
768
	$value = ! empty( $raw_value ) ? absint( $raw_value ) : ''; // Allow > 0 or set to ''
769
770
	wp_clear_scheduled_hook( 'woocommerce_cancel_unpaid_orders' );
771
772
	if ( '' !== $value ) {
773
		wp_schedule_single_event( time() + ( absint( $value ) * 60 ), 'woocommerce_cancel_unpaid_orders' );
774
	}
775
776
	return $value;
777
}
778
add_filter( 'woocommerce_admin_settings_sanitize_option_woocommerce_hold_stock_minutes', 'wc_format_option_hold_stock_minutes', 10, 3 );
779
780
/**
781
 * Sanitize terms from an attribute text based.
782
 *
783
 * @since  2.4.5
784
 * @param  string $term
785
 * @return string
786
 */
787
function wc_sanitize_term_text_based( $term ) {
788
	return trim( wp_unslash( strip_tags( $term ) ) );
789
}
790
791
if ( ! function_exists( 'wc_make_numeric_postcode' ) ) {
792
	/**
793
	 * Make numeric postcode.
794
	 *
795
	 * Converts letters to numbers so we can do a simple range check on postcodes.
796
	 * E.g. PE30 becomes 16050300 (P = 16, E = 05, 3 = 03, 0 = 00)
797
	 *
798
	 * @since 2.6.0
799
	 * @param string $postcode Regular postcode
800
	 * @return string
801
	 */
802
	function wc_make_numeric_postcode( $postcode ) {
803
		$postcode_length    = strlen( $postcode );
804
		$letters_to_numbers = array_merge( array( 0 ), range( 'A', 'Z' ) );
805
		$letters_to_numbers = array_flip( $letters_to_numbers );
806
		$numeric_postcode   = '';
807
808
		for ( $i = 0; $i < $postcode_length; $i ++ ) {
809
			if ( is_numeric( $postcode[ $i ] ) ) {
810
				$numeric_postcode .= str_pad( $postcode[ $i ], 2, '0', STR_PAD_LEFT );
811
			} elseif ( isset( $letters_to_numbers[ $postcode[ $i ] ] ) ) {
812
				$numeric_postcode .= str_pad( $letters_to_numbers[ $postcode[ $i ] ], 2, '0', STR_PAD_LEFT );
813
			} else {
814
				$numeric_postcode .= '00';
815
			}
816
		}
817
818
		return $numeric_postcode;
819
	}
820
}
821