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 ) { |
|
|
|
|
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 ) { |
|
|
|
|
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 %2$s'; |
339
|
|
|
break; |
340
|
|
|
case 'right_space' : |
341
|
|
|
$format = '%2$s %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' ) ) { |
|
|
|
|
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' ) ) { |
|
|
|
|
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 ) { |
|
|
|
|
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 ) { |
|
|
|
|
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 ) { |
|
|
|
|
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
|
|
|
|
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.