2013-08-09 16:11:15 +00:00
< ? php
/**
2015-11-03 13:53:50 +00:00
* WooCommerce Core Functions
2013-08-09 16:11:15 +00:00
*
2013-09-03 12:03:05 +00:00
* General core functions available on both the front - end and admin .
2013-08-09 16:11:15 +00:00
*
2018-03-07 21:37:32 +00:00
* @ package WooCommerce\Functions
* @ version 3.3 . 0
2013-08-09 16:11:15 +00:00
*/
2014-09-20 19:07:11 +00:00
if ( ! defined ( 'ABSPATH' ) ) {
2014-11-20 20:56:24 +00:00
exit ;
2014-09-20 19:07:11 +00:00
}
2013-08-09 16:11:15 +00:00
2015-10-31 19:10:45 +00:00
// Include core functions (available in both admin and frontend).
2018-03-07 21:37:32 +00:00
require WC_ABSPATH . 'includes/wc-conditional-functions.php' ;
require WC_ABSPATH . 'includes/wc-coupon-functions.php' ;
require WC_ABSPATH . 'includes/wc-user-functions.php' ;
require WC_ABSPATH . 'includes/wc-deprecated-functions.php' ;
require WC_ABSPATH . 'includes/wc-formatting-functions.php' ;
require WC_ABSPATH . 'includes/wc-order-functions.php' ;
require WC_ABSPATH . 'includes/wc-order-item-functions.php' ;
require WC_ABSPATH . 'includes/wc-page-functions.php' ;
require WC_ABSPATH . 'includes/wc-product-functions.php' ;
require WC_ABSPATH . 'includes/wc-stock-functions.php' ;
require WC_ABSPATH . 'includes/wc-account-functions.php' ;
require WC_ABSPATH . 'includes/wc-term-functions.php' ;
require WC_ABSPATH . 'includes/wc-attribute-functions.php' ;
require WC_ABSPATH . 'includes/wc-rest-functions.php' ;
require WC_ABSPATH . 'includes/wc-widget-functions.php' ;
require WC_ABSPATH . 'includes/wc-webhook-functions.php' ;
2013-08-09 16:11:15 +00:00
/**
2015-10-31 19:10:45 +00:00
* Filters on data used in admin and frontend .
2013-08-09 16:11:15 +00:00
*/
2015-02-12 22:50:22 +00:00
add_filter ( 'woocommerce_coupon_code' , 'html_entity_decode' );
2019-03-06 11:42:07 +00:00
add_filter ( 'woocommerce_coupon_code' , 'wc_sanitize_coupon_code' );
2017-08-18 17:11:33 +00:00
add_filter ( 'woocommerce_coupon_code' , 'wc_strtolower' );
2017-12-01 17:13:27 +00:00
add_filter ( 'woocommerce_stock_amount' , 'intval' ); // Stock amounts are integers by default.
add_filter ( 'woocommerce_shipping_rate_label' , 'sanitize_text_field' ); // Shipping rate label.
2018-05-24 18:32:32 +00:00
add_filter ( 'woocommerce_attribute_label' , 'wp_kses_post' , 100 );
2013-08-09 16:11:15 +00:00
/**
2015-10-31 19:10:45 +00:00
* Short Description ( excerpt ) .
2013-08-09 16:11:15 +00:00
*/
2019-01-17 20:14:53 +00:00
if ( function_exists ( 'do_blocks' ) ) {
2019-01-16 16:49:25 +00:00
add_filter ( 'woocommerce_short_description' , 'do_blocks' , 9 );
}
2013-08-09 16:11:15 +00:00
add_filter ( 'woocommerce_short_description' , 'wptexturize' );
add_filter ( 'woocommerce_short_description' , 'convert_smilies' );
add_filter ( 'woocommerce_short_description' , 'convert_chars' );
add_filter ( 'woocommerce_short_description' , 'wpautop' );
add_filter ( 'woocommerce_short_description' , 'shortcode_unautop' );
add_filter ( 'woocommerce_short_description' , 'prepend_attachment' );
2017-12-01 17:13:27 +00:00
add_filter ( 'woocommerce_short_description' , 'do_shortcode' , 11 ); // After wpautop().
2017-04-10 22:21:22 +00:00
add_filter ( 'woocommerce_short_description' , 'wc_format_product_short_description' , 9999999 );
2017-03-17 18:39:17 +00:00
add_filter ( 'woocommerce_short_description' , 'wc_do_oembeds' );
2017-12-21 18:19:15 +00:00
add_filter ( 'woocommerce_short_description' , array ( $GLOBALS [ 'wp_embed' ], 'run_shortcode' ), 8 ); // Before wpautop().
2013-08-09 16:11:15 +00:00
2016-11-24 14:20:58 +00:00
/**
* Define a constant if it is not already defined .
*
2017-09-06 17:47:35 +00:00
* @ since 3.0 . 0
* @ param string $name Constant name .
2018-05-26 03:16:44 +00:00
* @ param mixed $value Value .
2016-11-24 14:20:58 +00:00
*/
function wc_maybe_define_constant ( $name , $value ) {
if ( ! defined ( $name ) ) {
define ( $name , $value );
}
}
2014-06-06 14:51:09 +00:00
/**
2015-10-31 19:10:45 +00:00
* Create a new order programmatically .
2014-06-06 14:51:09 +00:00
*
2014-07-13 01:43:27 +00:00
* Returns a new order object on success which can then be used to add additional data .
2014-06-24 18:56:53 +00:00
*
2017-12-01 17:13:27 +00:00
* @ param array $args Order arguments .
2016-08-24 15:02:19 +00:00
* @ return WC_Order | WP_Error
2014-06-06 14:51:09 +00:00
*/
2014-06-13 15:11:15 +00:00
function wc_create_order ( $args = array () ) {
2014-06-06 14:51:09 +00:00
$default_args = array (
2016-08-09 13:02:40 +00:00
'status' => null ,
2014-06-11 14:10:03 +00:00
'customer_id' => null ,
'customer_note' => null ,
2016-08-09 13:02:40 +00:00
'parent' => null ,
'created_via' => null ,
'cart_hash' => null ,
2015-04-01 13:21:07 +00:00
'order_id' => 0 ,
2014-06-06 14:51:09 +00:00
);
2016-08-24 14:26:35 +00:00
try {
2016-08-24 15:02:19 +00:00
$args = wp_parse_args ( $args , $default_args );
2016-08-24 14:26:35 +00:00
$order = new WC_Order ( $args [ 'order_id' ] );
2014-06-06 14:51:09 +00:00
2017-12-01 17:13:27 +00:00
// Update props that were set (not null).
2016-08-24 14:26:35 +00:00
if ( ! is_null ( $args [ 'parent' ] ) ) {
$order -> set_parent_id ( absint ( $args [ 'parent' ] ) );
}
2014-06-11 14:10:03 +00:00
2016-08-24 14:26:35 +00:00
if ( ! is_null ( $args [ 'status' ] ) ) {
$order -> set_status ( $args [ 'status' ] );
}
2014-06-06 14:51:09 +00:00
2016-08-24 14:26:35 +00:00
if ( ! is_null ( $args [ 'customer_note' ] ) ) {
$order -> set_customer_note ( $args [ 'customer_note' ] );
}
2014-06-06 14:51:09 +00:00
2016-08-24 14:26:35 +00:00
if ( ! is_null ( $args [ 'customer_id' ] ) ) {
$order -> set_customer_id ( is_numeric ( $args [ 'customer_id' ] ) ? absint ( $args [ 'customer_id' ] ) : 0 );
}
2014-06-11 14:10:03 +00:00
2016-08-24 14:26:35 +00:00
if ( ! is_null ( $args [ 'created_via' ] ) ) {
$order -> set_created_via ( sanitize_text_field ( $args [ 'created_via' ] ) );
}
2014-06-06 14:51:09 +00:00
2016-08-24 14:26:35 +00:00
if ( ! is_null ( $args [ 'cart_hash' ] ) ) {
$order -> set_cart_hash ( sanitize_text_field ( $args [ 'cart_hash' ] ) );
}
2014-06-24 18:56:53 +00:00
2017-09-07 20:50:47 +00:00
// Set these fields when creating a new order but not when updating an existing order.
if ( ! $args [ 'order_id' ] ) {
$order -> set_currency ( get_woocommerce_currency () );
$order -> set_prices_include_tax ( 'yes' === get_option ( 'woocommerce_prices_include_tax' ) );
$order -> set_customer_ip_address ( WC_Geolocation :: get_ip_address () );
$order -> set_customer_user_agent ( wc_get_user_agent () );
}
2017-12-01 17:13:27 +00:00
// Update other order props set automatically.
2016-08-24 14:26:35 +00:00
$order -> save ();
2016-08-24 15:02:19 +00:00
} catch ( Exception $e ) {
return new WP_Error ( 'error' , $e -> getMessage () );
2016-08-24 14:26:35 +00:00
}
2016-08-24 15:02:19 +00:00
2016-08-09 13:02:40 +00:00
return $order ;
2014-06-11 14:10:03 +00:00
}
/**
* Update an order . Uses wc_create_order .
2015-11-03 13:31:20 +00:00
*
2017-12-01 17:13:27 +00:00
* @ param array $args Order arguments .
* @ return WC_Order | WP_Error
2014-06-11 14:10:03 +00:00
*/
function wc_update_order ( $args ) {
2017-09-07 20:50:47 +00:00
if ( empty ( $args [ 'order_id' ] ) ) {
2016-10-11 01:39:13 +00:00
return new WP_Error ( __ ( 'Invalid order ID.' , 'woocommerce' ) );
2014-06-06 14:51:09 +00:00
}
2014-06-11 14:10:03 +00:00
return wc_create_order ( $args );
2014-06-06 14:51:09 +00:00
}
2013-09-12 13:42:57 +00:00
/**
* Get template part ( for templates like the shop - loop ) .
*
2015-12-16 11:28:34 +00:00
* WC_TEMPLATE_DEBUG_MODE will prevent overrides in themes from taking priority .
*
2017-12-01 17:13:27 +00:00
* @ param mixed $slug Template slug .
* @ param string $name Template name ( default : '' ) .
2013-09-12 13:42:57 +00:00
*/
2013-11-25 12:45:04 +00:00
function wc_get_template_part ( $slug , $name = '' ) {
2019-01-30 12:55:59 +00:00
$cache_key = sanitize_key ( implode ( '-' , array ( 'template-part' , $slug , $name ) ) );
$template = ( string ) wp_cache_get ( $cache_key , 'woocommerce' );
2013-09-12 13:42:57 +00:00
2019-01-30 12:55:59 +00:00
if ( ! $template ) {
if ( $name ) {
$template = WC_TEMPLATE_DEBUG_MODE ? '' : locate_template (
array (
" { $slug } - { $name } .php " ,
WC () -> template_path () . " { $slug } - { $name } .php " ,
)
);
2013-09-12 13:42:57 +00:00
2019-01-30 12:55:59 +00:00
if ( ! $template ) {
$fallback = WC () -> plugin_path () . " /templates/ { $slug } - { $name } .php " ;
$template = file_exists ( $fallback ) ? $fallback : '' ;
}
}
2013-09-12 13:42:57 +00:00
2019-01-30 10:53:48 +00:00
if ( ! $template ) {
2019-01-30 12:55:59 +00:00
// If template file doesn't exist, look in yourtheme/slug.php and yourtheme/woocommerce/slug.php.
$template = WC_TEMPLATE_DEBUG_MODE ? '' : locate_template (
array (
" { $slug } .php " ,
WC () -> template_path () . " { $slug } .php " ,
)
);
2019-01-30 10:53:48 +00:00
}
2013-09-12 13:42:57 +00:00
2019-01-30 12:55:59 +00:00
wp_cache_set ( $cache_key , $template , 'woocommerce' );
2014-02-01 14:58:56 +00:00
}
2013-09-12 13:42:57 +00:00
2015-12-16 11:28:34 +00:00
// Allow 3rd party plugins to filter template file from their plugin.
$template = apply_filters ( 'wc_get_template_part' , $template , $slug , $name );
2014-01-27 03:37:03 +00:00
2014-02-01 14:58:56 +00:00
if ( $template ) {
2013-09-12 13:42:57 +00:00
load_template ( $template , false );
2014-02-01 14:58:56 +00:00
}
2013-09-12 13:42:57 +00:00
}
/**
* Get other templates ( e . g . product attributes ) passing attributes and including the file .
*
2017-12-01 17:13:27 +00:00
* @ param string $template_name Template name .
* @ param array $args Arguments . ( default : array ) .
* @ param string $template_path Template path . ( default : '' ) .
* @ param string $default_path Default path . ( default : '' ) .
2013-09-12 13:42:57 +00:00
*/
2013-11-25 12:45:04 +00:00
function wc_get_template ( $template_name , $args = array (), $template_path = '' , $default_path = '' ) {
2019-01-30 12:55:59 +00:00
$cache_key = sanitize_key ( implode ( '-' , array ( 'template' , $template_name , $template_path , $default_path ) ) );
$template = ( string ) wp_cache_get ( $cache_key , 'woocommerce' );
if ( ! $template ) {
$template = wc_locate_template ( $template_name , $template_path , $default_path );
wp_cache_set ( $cache_key , $template , 'woocommerce' );
2014-02-01 14:58:56 +00:00
}
2013-09-12 13:42:57 +00:00
2018-10-31 09:48:29 +00:00
// Allow 3rd party plugin filter template file from their plugin.
2019-01-30 12:55:59 +00:00
$filter_template = apply_filters ( 'wc_get_template' , $template , $template_name , $args , $template_path , $default_path );
2013-09-12 13:42:57 +00:00
2019-01-30 12:55:59 +00:00
if ( $filter_template !== $template ) {
if ( ! file_exists ( $filter_template ) ) {
2019-01-30 10:54:02 +00:00
/* translators: %s template */
2019-01-30 12:55:59 +00:00
wc_doing_it_wrong ( __FUNCTION__ , sprintf ( __ ( '%s does not exist.' , 'woocommerce' ), '<code>' . $template . '</code>' ), '2.1' );
2019-01-30 10:54:02 +00:00
return ;
}
2019-01-30 12:55:59 +00:00
$template = $filter_template ;
2014-02-11 14:48:28 +00:00
}
2018-10-28 14:36:13 +00:00
$action_args = array (
'template_name' => $template_name ,
'template_path' => $template_path ,
2019-01-30 12:55:59 +00:00
'located' => $template ,
2018-10-28 14:36:13 +00:00
'args' => $args ,
);
2014-07-22 01:05:25 +00:00
2018-10-28 14:36:13 +00:00
if ( ! empty ( $args ) && is_array ( $args ) ) {
extract ( $args ); // @codingStandardsIgnoreLine
}
2013-09-12 13:42:57 +00:00
2018-10-28 14:36:13 +00:00
do_action ( 'woocommerce_before_template_part' , $action_args [ 'template_name' ], $action_args [ 'template_path' ], $action_args [ 'located' ], $action_args [ 'args' ] );
2013-09-12 13:42:57 +00:00
2019-01-30 12:55:59 +00:00
include $template ;
2013-09-12 13:42:57 +00:00
2018-10-28 14:36:13 +00:00
do_action ( 'woocommerce_after_template_part' , $action_args [ 'template_name' ], $action_args [ 'template_path' ], $action_args [ 'located' ], $action_args [ 'args' ] );
2013-09-12 13:42:57 +00:00
}
2017-05-15 11:50:52 +00:00
2015-12-04 13:26:24 +00:00
/**
* Like wc_get_template , but returns the HTML instead of outputting .
2017-05-23 18:00:24 +00:00
*
2015-12-04 13:26:24 +00:00
* @ see wc_get_template
* @ since 2.5 . 0
2017-12-01 17:13:27 +00:00
* @ param string $template_name Template name .
* @ param array $args Arguments . ( default : array ) .
* @ param string $template_path Template path . ( default : '' ) .
* @ param string $default_path Default path . ( default : '' ) .
2017-05-15 11:50:52 +00:00
*
* @ return string
2015-12-04 13:26:24 +00:00
*/
function wc_get_template_html ( $template_name , $args = array (), $template_path = '' , $default_path = '' ) {
ob_start ();
wc_get_template ( $template_name , $args , $template_path , $default_path );
return ob_get_clean ();
}
2013-09-12 13:42:57 +00:00
/**
* Locate a template and return the path for inclusion .
*
* This is the load order :
*
2017-12-01 17:13:27 +00:00
* yourtheme / $template_path / $template_name
* yourtheme / $template_name
* $default_path / $template_name
2013-09-12 13:42:57 +00:00
*
2017-12-01 17:13:27 +00:00
* @ param string $template_name Template name .
* @ param string $template_path Template path . ( default : '' ) .
* @ param string $default_path Default path . ( default : '' ) .
2013-09-12 13:42:57 +00:00
* @ return string
*/
2013-11-25 12:45:04 +00:00
function wc_locate_template ( $template_name , $template_path = '' , $default_path = '' ) {
2014-02-01 14:58:56 +00:00
if ( ! $template_path ) {
$template_path = WC () -> template_path ();
}
if ( ! $default_path ) {
$default_path = WC () -> plugin_path () . '/templates/' ;
}
2013-09-12 13:42:57 +00:00
2015-10-31 19:10:45 +00:00
// Look within passed path within the theme - this is priority.
2013-09-12 13:42:57 +00:00
$template = locate_template (
array (
trailingslashit ( $template_path ) . $template_name ,
2016-08-27 02:08:49 +00:00
$template_name ,
2013-09-12 13:42:57 +00:00
)
);
2017-12-01 17:13:27 +00:00
// Get default template/.
2014-10-03 09:52:11 +00:00
if ( ! $template || WC_TEMPLATE_DEBUG_MODE ) {
2013-09-12 13:42:57 +00:00
$template = $default_path . $template_name ;
2014-02-01 14:58:56 +00:00
}
2013-09-12 13:42:57 +00:00
2015-10-31 19:10:45 +00:00
// Return what we found.
2014-10-03 09:52:11 +00:00
return apply_filters ( 'woocommerce_locate_template' , $template , $template_name , $template_path );
2013-09-12 13:42:57 +00:00
}
2013-08-09 16:11:15 +00:00
/**
* Get Base Currency Code .
2015-11-03 13:31:20 +00:00
*
2013-08-09 16:11:15 +00:00
* @ return string
*/
function get_woocommerce_currency () {
2016-09-02 01:51:31 +00:00
return apply_filters ( 'woocommerce_currency' , get_option ( 'woocommerce_currency' ) );
2013-08-09 16:11:15 +00:00
}
/**
* Get full list of currency codes .
2015-11-03 13:31:20 +00:00
*
2013-08-09 16:11:15 +00:00
* @ return array
*/
function get_woocommerce_currencies () {
2017-09-01 16:30:08 +00:00
static $currencies ;
if ( ! isset ( $currencies ) ) {
$currencies = array_unique (
2018-03-07 21:37:32 +00:00
apply_filters (
'woocommerce_currencies' ,
2017-09-01 16:30:08 +00:00
array (
'AED' => __ ( 'United Arab Emirates dirham' , 'woocommerce' ),
'AFN' => __ ( 'Afghan afghani' , 'woocommerce' ),
'ALL' => __ ( 'Albanian lek' , 'woocommerce' ),
'AMD' => __ ( 'Armenian dram' , 'woocommerce' ),
'ANG' => __ ( 'Netherlands Antillean guilder' , 'woocommerce' ),
'AOA' => __ ( 'Angolan kwanza' , 'woocommerce' ),
'ARS' => __ ( 'Argentine peso' , 'woocommerce' ),
'AUD' => __ ( 'Australian dollar' , 'woocommerce' ),
'AWG' => __ ( 'Aruban florin' , 'woocommerce' ),
'AZN' => __ ( 'Azerbaijani manat' , 'woocommerce' ),
'BAM' => __ ( 'Bosnia and Herzegovina convertible mark' , 'woocommerce' ),
'BBD' => __ ( 'Barbadian dollar' , 'woocommerce' ),
'BDT' => __ ( 'Bangladeshi taka' , 'woocommerce' ),
'BGN' => __ ( 'Bulgarian lev' , 'woocommerce' ),
'BHD' => __ ( 'Bahraini dinar' , 'woocommerce' ),
'BIF' => __ ( 'Burundian franc' , 'woocommerce' ),
'BMD' => __ ( 'Bermudian dollar' , 'woocommerce' ),
'BND' => __ ( 'Brunei dollar' , 'woocommerce' ),
'BOB' => __ ( 'Bolivian boliviano' , 'woocommerce' ),
'BRL' => __ ( 'Brazilian real' , 'woocommerce' ),
'BSD' => __ ( 'Bahamian dollar' , 'woocommerce' ),
'BTC' => __ ( 'Bitcoin' , 'woocommerce' ),
'BTN' => __ ( 'Bhutanese ngultrum' , 'woocommerce' ),
'BWP' => __ ( 'Botswana pula' , 'woocommerce' ),
2017-11-07 02:24:01 +00:00
'BYR' => __ ( 'Belarusian ruble (old)' , 'woocommerce' ),
'BYN' => __ ( 'Belarusian ruble' , 'woocommerce' ),
2017-09-01 16:30:08 +00:00
'BZD' => __ ( 'Belize dollar' , 'woocommerce' ),
'CAD' => __ ( 'Canadian dollar' , 'woocommerce' ),
'CDF' => __ ( 'Congolese franc' , 'woocommerce' ),
'CHF' => __ ( 'Swiss franc' , 'woocommerce' ),
'CLP' => __ ( 'Chilean peso' , 'woocommerce' ),
'CNY' => __ ( 'Chinese yuan' , 'woocommerce' ),
'COP' => __ ( 'Colombian peso' , 'woocommerce' ),
'CRC' => __ ( 'Costa Rican colón' , 'woocommerce' ),
'CUC' => __ ( 'Cuban convertible peso' , 'woocommerce' ),
'CUP' => __ ( 'Cuban peso' , 'woocommerce' ),
'CVE' => __ ( 'Cape Verdean escudo' , 'woocommerce' ),
'CZK' => __ ( 'Czech koruna' , 'woocommerce' ),
'DJF' => __ ( 'Djiboutian franc' , 'woocommerce' ),
'DKK' => __ ( 'Danish krone' , 'woocommerce' ),
'DOP' => __ ( 'Dominican peso' , 'woocommerce' ),
'DZD' => __ ( 'Algerian dinar' , 'woocommerce' ),
'EGP' => __ ( 'Egyptian pound' , 'woocommerce' ),
'ERN' => __ ( 'Eritrean nakfa' , 'woocommerce' ),
'ETB' => __ ( 'Ethiopian birr' , 'woocommerce' ),
'EUR' => __ ( 'Euro' , 'woocommerce' ),
'FJD' => __ ( 'Fijian dollar' , 'woocommerce' ),
'FKP' => __ ( 'Falkland Islands pound' , 'woocommerce' ),
'GBP' => __ ( 'Pound sterling' , 'woocommerce' ),
'GEL' => __ ( 'Georgian lari' , 'woocommerce' ),
'GGP' => __ ( 'Guernsey pound' , 'woocommerce' ),
'GHS' => __ ( 'Ghana cedi' , 'woocommerce' ),
'GIP' => __ ( 'Gibraltar pound' , 'woocommerce' ),
'GMD' => __ ( 'Gambian dalasi' , 'woocommerce' ),
'GNF' => __ ( 'Guinean franc' , 'woocommerce' ),
'GTQ' => __ ( 'Guatemalan quetzal' , 'woocommerce' ),
'GYD' => __ ( 'Guyanese dollar' , 'woocommerce' ),
'HKD' => __ ( 'Hong Kong dollar' , 'woocommerce' ),
'HNL' => __ ( 'Honduran lempira' , 'woocommerce' ),
'HRK' => __ ( 'Croatian kuna' , 'woocommerce' ),
'HTG' => __ ( 'Haitian gourde' , 'woocommerce' ),
'HUF' => __ ( 'Hungarian forint' , 'woocommerce' ),
'IDR' => __ ( 'Indonesian rupiah' , 'woocommerce' ),
'ILS' => __ ( 'Israeli new shekel' , 'woocommerce' ),
'IMP' => __ ( 'Manx pound' , 'woocommerce' ),
'INR' => __ ( 'Indian rupee' , 'woocommerce' ),
'IQD' => __ ( 'Iraqi dinar' , 'woocommerce' ),
'IRR' => __ ( 'Iranian rial' , 'woocommerce' ),
'IRT' => __ ( 'Iranian toman' , 'woocommerce' ),
'ISK' => __ ( 'Icelandic króna' , 'woocommerce' ),
'JEP' => __ ( 'Jersey pound' , 'woocommerce' ),
'JMD' => __ ( 'Jamaican dollar' , 'woocommerce' ),
'JOD' => __ ( 'Jordanian dinar' , 'woocommerce' ),
'JPY' => __ ( 'Japanese yen' , 'woocommerce' ),
'KES' => __ ( 'Kenyan shilling' , 'woocommerce' ),
'KGS' => __ ( 'Kyrgyzstani som' , 'woocommerce' ),
'KHR' => __ ( 'Cambodian riel' , 'woocommerce' ),
'KMF' => __ ( 'Comorian franc' , 'woocommerce' ),
'KPW' => __ ( 'North Korean won' , 'woocommerce' ),
'KRW' => __ ( 'South Korean won' , 'woocommerce' ),
'KWD' => __ ( 'Kuwaiti dinar' , 'woocommerce' ),
'KYD' => __ ( 'Cayman Islands dollar' , 'woocommerce' ),
'KZT' => __ ( 'Kazakhstani tenge' , 'woocommerce' ),
'LAK' => __ ( 'Lao kip' , 'woocommerce' ),
'LBP' => __ ( 'Lebanese pound' , 'woocommerce' ),
'LKR' => __ ( 'Sri Lankan rupee' , 'woocommerce' ),
'LRD' => __ ( 'Liberian dollar' , 'woocommerce' ),
'LSL' => __ ( 'Lesotho loti' , 'woocommerce' ),
'LYD' => __ ( 'Libyan dinar' , 'woocommerce' ),
'MAD' => __ ( 'Moroccan dirham' , 'woocommerce' ),
'MDL' => __ ( 'Moldovan leu' , 'woocommerce' ),
'MGA' => __ ( 'Malagasy ariary' , 'woocommerce' ),
'MKD' => __ ( 'Macedonian denar' , 'woocommerce' ),
'MMK' => __ ( 'Burmese kyat' , 'woocommerce' ),
'MNT' => __ ( 'Mongolian tögrög' , 'woocommerce' ),
'MOP' => __ ( 'Macanese pataca' , 'woocommerce' ),
'MRO' => __ ( 'Mauritanian ouguiya' , 'woocommerce' ),
'MUR' => __ ( 'Mauritian rupee' , 'woocommerce' ),
'MVR' => __ ( 'Maldivian rufiyaa' , 'woocommerce' ),
'MWK' => __ ( 'Malawian kwacha' , 'woocommerce' ),
'MXN' => __ ( 'Mexican peso' , 'woocommerce' ),
'MYR' => __ ( 'Malaysian ringgit' , 'woocommerce' ),
'MZN' => __ ( 'Mozambican metical' , 'woocommerce' ),
'NAD' => __ ( 'Namibian dollar' , 'woocommerce' ),
'NGN' => __ ( 'Nigerian naira' , 'woocommerce' ),
'NIO' => __ ( 'Nicaraguan córdoba' , 'woocommerce' ),
'NOK' => __ ( 'Norwegian krone' , 'woocommerce' ),
'NPR' => __ ( 'Nepalese rupee' , 'woocommerce' ),
'NZD' => __ ( 'New Zealand dollar' , 'woocommerce' ),
'OMR' => __ ( 'Omani rial' , 'woocommerce' ),
'PAB' => __ ( 'Panamanian balboa' , 'woocommerce' ),
2019-01-30 01:01:04 +00:00
'PEN' => __ ( 'Sol' , 'woocommerce' ),
2017-09-01 16:30:08 +00:00
'PGK' => __ ( 'Papua New Guinean kina' , 'woocommerce' ),
'PHP' => __ ( 'Philippine peso' , 'woocommerce' ),
'PKR' => __ ( 'Pakistani rupee' , 'woocommerce' ),
'PLN' => __ ( 'Polish złoty' , 'woocommerce' ),
'PRB' => __ ( 'Transnistrian ruble' , 'woocommerce' ),
'PYG' => __ ( 'Paraguayan guaraní' , 'woocommerce' ),
'QAR' => __ ( 'Qatari riyal' , 'woocommerce' ),
'RON' => __ ( 'Romanian leu' , 'woocommerce' ),
'RSD' => __ ( 'Serbian dinar' , 'woocommerce' ),
'RUB' => __ ( 'Russian ruble' , 'woocommerce' ),
'RWF' => __ ( 'Rwandan franc' , 'woocommerce' ),
'SAR' => __ ( 'Saudi riyal' , 'woocommerce' ),
'SBD' => __ ( 'Solomon Islands dollar' , 'woocommerce' ),
'SCR' => __ ( 'Seychellois rupee' , 'woocommerce' ),
'SDG' => __ ( 'Sudanese pound' , 'woocommerce' ),
'SEK' => __ ( 'Swedish krona' , 'woocommerce' ),
'SGD' => __ ( 'Singapore dollar' , 'woocommerce' ),
'SHP' => __ ( 'Saint Helena pound' , 'woocommerce' ),
'SLL' => __ ( 'Sierra Leonean leone' , 'woocommerce' ),
'SOS' => __ ( 'Somali shilling' , 'woocommerce' ),
'SRD' => __ ( 'Surinamese dollar' , 'woocommerce' ),
'SSP' => __ ( 'South Sudanese pound' , 'woocommerce' ),
'STD' => __ ( 'São Tomé and Príncipe dobra' , 'woocommerce' ),
'SYP' => __ ( 'Syrian pound' , 'woocommerce' ),
'SZL' => __ ( 'Swazi lilangeni' , 'woocommerce' ),
'THB' => __ ( 'Thai baht' , 'woocommerce' ),
'TJS' => __ ( 'Tajikistani somoni' , 'woocommerce' ),
'TMT' => __ ( 'Turkmenistan manat' , 'woocommerce' ),
'TND' => __ ( 'Tunisian dinar' , 'woocommerce' ),
'TOP' => __ ( 'Tongan paʻanga' , 'woocommerce' ),
'TRY' => __ ( 'Turkish lira' , 'woocommerce' ),
'TTD' => __ ( 'Trinidad and Tobago dollar' , 'woocommerce' ),
'TWD' => __ ( 'New Taiwan dollar' , 'woocommerce' ),
'TZS' => __ ( 'Tanzanian shilling' , 'woocommerce' ),
'UAH' => __ ( 'Ukrainian hryvnia' , 'woocommerce' ),
'UGX' => __ ( 'Ugandan shilling' , 'woocommerce' ),
2018-03-27 17:35:15 +00:00
'USD' => __ ( 'United States (US) dollar' , 'woocommerce' ),
2017-09-01 16:30:08 +00:00
'UYU' => __ ( 'Uruguayan peso' , 'woocommerce' ),
'UZS' => __ ( 'Uzbekistani som' , 'woocommerce' ),
'VEF' => __ ( 'Venezuelan bolívar' , 'woocommerce' ),
2019-01-16 20:51:07 +00:00
'VES' => __ ( 'Bolívar soberano' , 'woocommerce' ),
2017-09-01 16:30:08 +00:00
'VND' => __ ( 'Vietnamese đồng' , 'woocommerce' ),
'VUV' => __ ( 'Vanuatu vatu' , 'woocommerce' ),
'WST' => __ ( 'Samoan tālā' , 'woocommerce' ),
'XAF' => __ ( 'Central African CFA franc' , 'woocommerce' ),
'XCD' => __ ( 'East Caribbean dollar' , 'woocommerce' ),
'XOF' => __ ( 'West African CFA franc' , 'woocommerce' ),
'XPF' => __ ( 'CFP franc' , 'woocommerce' ),
'YER' => __ ( 'Yemeni rial' , 'woocommerce' ),
'ZAR' => __ ( 'South African rand' , 'woocommerce' ),
'ZMW' => __ ( 'Zambian kwacha' , 'woocommerce' ),
)
2013-08-09 16:11:15 +00:00
)
2017-09-01 16:30:08 +00:00
);
}
return $currencies ;
2013-08-09 16:11:15 +00:00
}
2017-09-01 16:30:08 +00:00
2013-08-09 16:11:15 +00:00
/**
* Get Currency symbol .
2015-11-03 13:31:20 +00:00
*
2017-12-01 17:13:27 +00:00
* @ param string $currency Currency . ( default : '' ) .
2013-08-09 16:11:15 +00:00
* @ return string
*/
function get_woocommerce_currency_symbol ( $currency = '' ) {
2014-02-01 14:58:56 +00:00
if ( ! $currency ) {
2013-08-09 16:11:15 +00:00
$currency = get_woocommerce_currency ();
2014-02-01 14:58:56 +00:00
}
2013-08-09 16:11:15 +00:00
2018-03-07 21:37:32 +00:00
$symbols = apply_filters (
2018-11-21 13:01:37 +00:00
'woocommerce_currency_symbols' ,
array (
2018-03-07 21:37:32 +00:00
'AED' => 'د.إ' ,
'AFN' => '؋' ,
'ALL' => 'L' ,
'AMD' => 'AMD' ,
'ANG' => 'ƒ' ,
'AOA' => 'Kz' ,
'ARS' => '$' ,
'AUD' => '$' ,
'AWG' => 'Afl.' ,
'AZN' => 'AZN' ,
'BAM' => 'KM' ,
'BBD' => '$' ,
'BDT' => '৳ ' ,
'BGN' => 'лв.' ,
'BHD' => '.د.ب' ,
'BIF' => 'Fr' ,
'BMD' => '$' ,
'BND' => '$' ,
'BOB' => 'Bs.' ,
'BRL' => 'R$' ,
'BSD' => '$' ,
'BTC' => '฿' ,
'BTN' => 'Nu.' ,
'BWP' => 'P' ,
'BYR' => 'Br' ,
'BYN' => 'Br' ,
'BZD' => '$' ,
'CAD' => '$' ,
'CDF' => 'Fr' ,
'CHF' => 'CHF' ,
'CLP' => '$' ,
'CNY' => '¥' ,
'COP' => '$' ,
'CRC' => '₡' ,
'CUC' => '$' ,
'CUP' => '$' ,
'CVE' => '$' ,
'CZK' => 'Kč' ,
'DJF' => 'Fr' ,
'DKK' => 'DKK' ,
'DOP' => 'RD$' ,
'DZD' => 'د.ج' ,
'EGP' => 'EGP' ,
'ERN' => 'Nfk' ,
'ETB' => 'Br' ,
'EUR' => '€' ,
'FJD' => '$' ,
'FKP' => '£' ,
'GBP' => '£' ,
2018-04-04 09:11:05 +00:00
'GEL' => '₾' ,
2018-03-07 21:37:32 +00:00
'GGP' => '£' ,
'GHS' => '₵' ,
'GIP' => '£' ,
'GMD' => 'D' ,
'GNF' => 'Fr' ,
'GTQ' => 'Q' ,
'GYD' => '$' ,
'HKD' => '$' ,
'HNL' => 'L' ,
2018-11-15 17:36:36 +00:00
'HRK' => 'kn' ,
2018-03-07 21:37:32 +00:00
'HTG' => 'G' ,
'HUF' => 'Ft' ,
'IDR' => 'Rp' ,
'ILS' => '₪' ,
'IMP' => '£' ,
'INR' => '₹' ,
'IQD' => 'ع.د' ,
'IRR' => '﷼' ,
'IRT' => 'تومان' ,
'ISK' => 'kr.' ,
'JEP' => '£' ,
'JMD' => '$' ,
'JOD' => 'د.ا' ,
'JPY' => '¥' ,
'KES' => 'KSh' ,
'KGS' => 'сом' ,
'KHR' => '៛' ,
'KMF' => 'Fr' ,
'KPW' => '₩' ,
'KRW' => '₩' ,
'KWD' => 'د.ك' ,
'KYD' => '$' ,
'KZT' => 'KZT' ,
'LAK' => '₭' ,
'LBP' => 'ل.ل' ,
'LKR' => 'රු' ,
'LRD' => '$' ,
'LSL' => 'L' ,
'LYD' => 'ل.د' ,
'MAD' => 'د.م.' ,
'MDL' => 'MDL' ,
'MGA' => 'Ar' ,
'MKD' => 'ден' ,
'MMK' => 'Ks' ,
'MNT' => '₮' ,
'MOP' => 'P' ,
'MRO' => 'UM' ,
'MUR' => '₨' ,
'MVR' => '.ރ' ,
'MWK' => 'MK' ,
'MXN' => '$' ,
'MYR' => 'RM' ,
'MZN' => 'MT' ,
'NAD' => '$' ,
'NGN' => '₦' ,
'NIO' => 'C$' ,
'NOK' => 'kr' ,
'NPR' => '₨' ,
'NZD' => '$' ,
'OMR' => 'ر.ع.' ,
'PAB' => 'B/.' ,
2019-01-30 01:01:04 +00:00
'PEN' => 'S/' ,
2018-03-07 21:37:32 +00:00
'PGK' => 'K' ,
'PHP' => '₱' ,
'PKR' => '₨' ,
'PLN' => 'zł' ,
'PRB' => 'р.' ,
'PYG' => '₲' ,
'QAR' => 'ر.ق' ,
'RMB' => '¥' ,
'RON' => 'lei' ,
'RSD' => 'дин.' ,
'RUB' => '₽' ,
'RWF' => 'Fr' ,
'SAR' => 'ر.س' ,
'SBD' => '$' ,
'SCR' => '₨' ,
'SDG' => 'ج.س.' ,
'SEK' => 'kr' ,
'SGD' => '$' ,
'SHP' => '£' ,
'SLL' => 'Le' ,
'SOS' => 'Sh' ,
'SRD' => '$' ,
'SSP' => '£' ,
'STD' => 'Db' ,
'SYP' => 'ل.س' ,
'SZL' => 'L' ,
'THB' => '฿' ,
'TJS' => 'ЅМ' ,
'TMT' => 'm' ,
'TND' => 'د.ت' ,
'TOP' => 'T$' ,
'TRY' => '₺' ,
'TTD' => '$' ,
'TWD' => 'NT$' ,
'TZS' => 'Sh' ,
'UAH' => '₴' ,
'UGX' => 'UGX' ,
'USD' => '$' ,
'UYU' => '$' ,
'UZS' => 'UZS' ,
'VEF' => 'Bs F' ,
2019-01-16 12:49:17 +00:00
'VES' => 'Bs.S' ,
2018-03-07 21:37:32 +00:00
'VND' => '₫' ,
'VUV' => 'Vt' ,
'WST' => 'T' ,
'XAF' => 'CFA' ,
'XCD' => '$' ,
'XOF' => 'CFA' ,
'XPF' => 'Fr' ,
'YER' => '﷼' ,
'ZAR' => 'R' ,
'ZMW' => 'ZK' ,
)
);
2015-12-16 15:23:44 +00:00
$currency_symbol = isset ( $symbols [ $currency ] ) ? $symbols [ $currency ] : '' ;
2013-08-09 16:11:15 +00:00
return apply_filters ( 'woocommerce_currency_symbol' , $currency_symbol , $currency );
}
/**
2015-10-31 19:10:45 +00:00
* Send HTML emails from WooCommerce .
2013-08-09 16:11:15 +00:00
*
2017-12-01 17:13:27 +00:00
* @ param mixed $to Receiver .
* @ param mixed $subject Subject .
* @ param mixed $message Message .
* @ param string $headers Headers . ( default : " Content-Type: text/html \r \n " ) .
* @ param string $attachments Attachments . ( default : " " ) .
2013-08-09 16:11:15 +00:00
*/
2017-12-01 17:13:27 +00:00
function wc_mail ( $to , $subject , $message , $headers = " Content-Type: text/html \r \n " , $attachments = '' ) {
2013-11-25 14:01:32 +00:00
$mailer = WC () -> mailer ();
2013-08-09 16:11:15 +00:00
$mailer -> send ( $to , $subject , $message , $headers , $attachments );
2013-08-21 07:29:44 +00:00
}
2013-09-12 13:41:02 +00:00
2018-01-08 18:48:57 +00:00
/**
* Return " theme support " values from the current theme , if set .
*
* @ since 3.3 . 0
* @ param string $prop Name of prop ( or key :: subkey for arrays of props ) if you want a specific value . Leave blank to get all props as an array .
* @ param mixed $default Optional value to return if the theme does not declare support for a prop .
* @ return mixed Value of prop ( s ) .
*/
function wc_get_theme_support ( $prop = '' , $default = null ) {
$theme_support = get_theme_support ( 'woocommerce' );
$theme_support = is_array ( $theme_support ) ? $theme_support [ 0 ] : false ;
if ( ! $theme_support ) {
return $default ;
}
if ( $prop ) {
$prop_stack = explode ( '::' , $prop );
$prop_key = array_shift ( $prop_stack );
if ( isset ( $theme_support [ $prop_key ] ) ) {
$value = $theme_support [ $prop_key ];
if ( count ( $prop_stack ) ) {
foreach ( $prop_stack as $prop_key ) {
if ( is_array ( $value ) && isset ( $value [ $prop_key ] ) ) {
$value = $value [ $prop_key ];
} else {
$value = $default ;
break ;
}
}
}
} else {
$value = $default ;
}
return $value ;
}
return $theme_support ;
}
2013-09-12 13:41:02 +00:00
/**
2017-11-07 11:04:06 +00:00
* Get an image size by name or defined dimensions .
2013-09-12 13:41:02 +00:00
*
2017-11-07 11:04:06 +00:00
* The returned variable is filtered by woocommerce_get_image_size_ { image_size } filter to
* allow 3 rd party customisation .
2013-09-12 13:41:02 +00:00
*
2017-11-07 11:04:06 +00:00
* Sizes defined by the theme take priority over settings . Settings are hidden when a theme
* defines sizes .
*
* @ param array | string $image_size Name of the image size to get , or an array of dimensions .
2017-11-07 18:32:43 +00:00
* @ return array Array of dimensions including width , height , and cropping mode . Cropping mode is 0 for no crop , and 1 for hard crop .
2013-09-12 13:41:02 +00:00
*/
function wc_get_image_size ( $image_size ) {
2019-03-01 10:22:27 +00:00
$cache_key = 'size-' . ( is_array ( $image_size ) ? implode ( '-' , $image_size ) : $image_size );
$size = wp_cache_get ( $cache_key , 'woocommerce' );
2019-02-21 17:35:41 +00:00
if ( $size ) {
return $size ;
}
2018-01-08 18:48:57 +00:00
$size = array (
2017-11-07 18:32:43 +00:00
'width' => 600 ,
'height' => 600 ,
2017-11-07 11:04:06 +00:00
'crop' => 1 ,
);
2015-03-06 14:39:46 +00:00
2017-11-07 11:04:06 +00:00
if ( is_array ( $image_size ) ) {
2018-03-07 21:37:32 +00:00
$size = array (
2018-02-01 16:58:57 +00:00
'width' => isset ( $image_size [ 0 ] ) ? absint ( $image_size [ 0 ] ) : 600 ,
'height' => isset ( $image_size [ 1 ] ) ? absint ( $image_size [ 1 ] ) : 600 ,
'crop' => isset ( $image_size [ 2 ] ) ? absint ( $image_size [ 2 ] ) : 1 ,
2015-02-14 01:18:07 +00:00
);
2017-11-07 11:04:06 +00:00
$image_size = $size [ 'width' ] . '_' . $size [ 'height' ];
2018-02-13 12:51:55 +00:00
} else {
$image_size = str_replace ( 'woocommerce_' , '' , $image_size );
// Legacy size mapping.
if ( 'shop_single' === $image_size ) {
$image_size = 'single' ;
} elseif ( 'shop_catalog' === $image_size ) {
$image_size = 'thumbnail' ;
} elseif ( 'shop_thumbnail' === $image_size ) {
$image_size = 'gallery_thumbnail' ;
}
2018-02-12 17:47:22 +00:00
2018-02-13 12:51:55 +00:00
if ( 'single' === $image_size ) {
$size [ 'width' ] = absint ( wc_get_theme_support ( 'single_image_width' , get_option ( 'woocommerce_single_image_width' , 600 ) ) );
2018-02-01 16:58:57 +00:00
$size [ 'height' ] = '' ;
2017-11-07 18:32:43 +00:00
$size [ 'crop' ] = 0 ;
2018-02-13 12:51:55 +00:00
} elseif ( 'gallery_thumbnail' === $image_size ) {
$size [ 'width' ] = absint ( wc_get_theme_support ( 'gallery_thumbnail_image_width' , 100 ) );
$size [ 'height' ] = $size [ 'width' ];
2017-11-07 18:32:43 +00:00
$size [ 'crop' ] = 1 ;
2018-02-13 12:51:55 +00:00
} elseif ( 'thumbnail' === $image_size ) {
$size [ 'width' ] = absint ( wc_get_theme_support ( 'thumbnail_image_width' , get_option ( 'woocommerce_thumbnail_image_width' , 300 ) ) );
$cropping = get_option ( 'woocommerce_thumbnail_cropping' , '1:1' );
if ( 'uncropped' === $cropping ) {
$size [ 'height' ] = '' ;
$size [ 'crop' ] = 0 ;
} elseif ( 'custom' === $cropping ) {
$width = max ( 1 , get_option ( 'woocommerce_thumbnail_cropping_custom_width' , '4' ) );
$height = max ( 1 , get_option ( 'woocommerce_thumbnail_cropping_custom_height' , '3' ) );
$size [ 'height' ] = absint ( round ( ( $size [ 'width' ] / $width ) * $height ) );
$size [ 'crop' ] = 1 ;
} else {
$cropping_split = explode ( ':' , $cropping );
$width = max ( 1 , current ( $cropping_split ) );
$height = max ( 1 , end ( $cropping_split ) );
$size [ 'height' ] = absint ( round ( ( $size [ 'width' ] / $width ) * $height ) );
$size [ 'crop' ] = 1 ;
}
2017-11-07 18:32:43 +00:00
}
2013-09-12 13:41:02 +00:00
}
2014-02-01 14:58:56 +00:00
2019-02-21 17:35:41 +00:00
$size = apply_filters ( 'woocommerce_get_image_size_' . $image_size , $size );
2019-03-01 10:22:27 +00:00
wp_cache_set ( $cache_key , $size , 'woocommerce' );
2019-02-21 17:35:41 +00:00
return $size ;
2013-09-12 13:41:02 +00:00
}
/**
* Queue some JavaScript code to be output in the footer .
*
2017-12-01 17:13:27 +00:00
* @ param string $code Code .
2013-09-12 13:41:02 +00:00
*/
function wc_enqueue_js ( $code ) {
global $wc_queued_js ;
2014-02-01 14:58:56 +00:00
if ( empty ( $wc_queued_js ) ) {
$wc_queued_js = '' ;
}
2013-09-12 13:41:02 +00:00
$wc_queued_js .= " \n " . $code . " \n " ;
}
/**
* Output any queued javascript code in the footer .
*/
function wc_print_js () {
global $wc_queued_js ;
if ( ! empty ( $wc_queued_js ) ) {
2016-03-14 13:47:25 +00:00
// Sanitize.
2013-09-12 13:41:02 +00:00
$wc_queued_js = wp_check_invalid_utf8 ( $wc_queued_js );
$wc_queued_js = preg_replace ( '/&#(x)?0*(?(1)27|39);?/i' , " ' " , $wc_queued_js );
$wc_queued_js = str_replace ( " \r " , '' , $wc_queued_js );
2016-03-14 13:47:25 +00:00
$js = " <!-- WooCommerce JavaScript --> \n <script type= \" text/javascript \" > \n jQuery(function( $ ) { $wc_queued_js }); \n </script> \n " ;
/**
2017-12-01 17:13:27 +00:00
* Queued jsfilter .
2016-03-14 13:47:25 +00:00
*
* @ since 2.6 . 0
* @ param string $js JavaScript code .
*/
2017-12-01 17:13:27 +00:00
echo apply_filters ( 'woocommerce_queued_js' , $js ); // WPCS: XSS ok.
2013-09-12 13:41:02 +00:00
unset ( $wc_queued_js );
}
2013-10-17 14:29:39 +00:00
}
/**
2015-10-31 19:10:45 +00:00
* Set a cookie - wrapper for setcookie using WP constants .
2013-11-03 23:54:56 +00:00
*
2015-10-31 19:10:45 +00:00
* @ param string $name Name of the cookie being set .
* @ param string $value Value of the cookie .
* @ param integer $expire Expiry of the cookie .
2017-05-15 11:50:52 +00:00
* @ param bool $secure Whether the cookie should be served only over https .
2019-03-14 17:14:57 +00:00
* @ param bool $httponly Whether the cookie is only accessible over HTTP , not scripting languages like JavaScript . @ since 3.6 . 0
2013-10-17 14:29:39 +00:00
*/
2019-03-14 17:14:57 +00:00
function wc_setcookie ( $name , $value , $expire = 0 , $secure = false , $httponly = false ) {
2013-10-17 14:29:39 +00:00
if ( ! headers_sent () ) {
2019-03-14 17:14:57 +00:00
setcookie ( $name , $value , $expire , COOKIEPATH ? COOKIEPATH : '/' , COOKIE_DOMAIN , $secure , apply_filters ( 'woocommerce_cookie_httponly' , $httponly , $name , $value , $expire , $secure ) );
2013-10-17 14:29:39 +00:00
} elseif ( defined ( 'WP_DEBUG' ) && WP_DEBUG ) {
2014-09-17 10:40:51 +00:00
headers_sent ( $file , $line );
2018-03-07 21:37:32 +00:00
trigger_error ( " { $name } cookie cannot be set - headers already sent by { $file } on line { $line } " , E_USER_NOTICE ); // @codingStandardsIgnoreLine
2013-10-17 14:29:39 +00:00
}
2013-11-03 23:54:56 +00:00
}
/**
2015-10-31 19:10:45 +00:00
* Get the URL to the WooCommerce REST API .
2013-11-03 23:54:56 +00:00
*
2013-11-06 06:23:19 +00:00
* @ since 2.1
2015-10-31 19:10:45 +00:00
* @ param string $path an endpoint to include in the URL .
* @ return string the URL .
2013-11-03 23:54:56 +00:00
*/
2013-11-06 06:23:19 +00:00
function get_woocommerce_api_url ( $path ) {
2018-03-07 21:37:32 +00:00
$version = defined ( 'WC_API_REQUEST_VERSION' ) ? WC_API_REQUEST_VERSION : substr ( WC_API :: VERSION , 0 , 1 );
2014-07-12 21:51:29 +00:00
$url = get_home_url ( null , " wc-api/v { $version } / " , is_ssl () ? 'https' : 'http' );
2013-11-03 23:54:56 +00:00
2014-02-01 14:58:56 +00:00
if ( ! empty ( $path ) && is_string ( $path ) ) {
2013-11-06 06:23:19 +00:00
$url .= ltrim ( $path , '/' );
2014-02-01 14:58:56 +00:00
}
2013-11-03 23:54:56 +00:00
2013-11-06 06:23:19 +00:00
return $url ;
2013-11-03 23:54:56 +00:00
}
2014-05-28 14:08:33 +00:00
2017-01-12 19:39:39 +00:00
/**
* Get a log file path .
*
* @ since 2.2
*
* @ param string $handle name .
* @ return string the log file path .
*/
function wc_get_log_file_path ( $handle ) {
return WC_Log_Handler_File :: get_log_file_path ( $handle );
}
2017-11-10 10:20:59 +00:00
/**
* Get a log file name .
*
* @ since 3.3
*
* @ param string $handle Name .
* @ return string The log file name .
*/
function wc_get_log_file_name ( $handle ) {
return WC_Log_Handler_File :: get_log_file_name ( $handle );
}
2014-06-02 20:00:44 +00:00
/**
2016-07-26 12:39:31 +00:00
* Recursively get page children .
2017-12-01 17:13:27 +00:00
*
* @ param int $page_id Page ID .
2016-07-26 12:39:31 +00:00
* @ return int []
2014-06-04 06:46:21 +00:00
*/
2016-07-26 12:39:31 +00:00
function wc_get_page_children ( $page_id ) {
2018-03-07 21:37:32 +00:00
$page_ids = get_posts (
array (
'post_parent' => $page_id ,
'post_type' => 'page' ,
'numberposts' => - 1 , // @codingStandardsIgnoreLine
'post_status' => 'any' ,
'fields' => 'ids' ,
)
);
2016-07-26 12:39:31 +00:00
if ( ! empty ( $page_ids ) ) {
foreach ( $page_ids as $page_id ) {
$page_ids = array_merge ( $page_ids , wc_get_page_children ( $page_id ) );
}
}
return $page_ids ;
}
2014-06-04 06:46:21 +00:00
2016-07-26 12:39:31 +00:00
/**
* Flushes rewrite rules when the shop page ( or it ' s children ) gets saved .
*/
2017-04-27 00:51:30 +00:00
function flush_rewrite_rules_on_shop_page_save () {
2017-04-27 15:42:16 +00:00
$screen = get_current_screen ();
$screen_id = $screen ? $screen -> id : '' ;
// Check if this is the edit page.
if ( 'page' !== $screen_id ) {
2017-04-27 00:51:30 +00:00
return ;
}
// Check if page is edited.
2018-03-07 21:37:32 +00:00
if ( empty ( $_GET [ 'post' ] ) || empty ( $_GET [ 'action' ] ) || ( isset ( $_GET [ 'action' ] ) && 'edit' !== $_GET [ 'action' ] ) ) { // WPCS: input var ok, CSRF ok.
2017-04-27 00:51:30 +00:00
return ;
}
2018-03-07 21:37:32 +00:00
$post_id = intval ( $_GET [ 'post' ] ); // WPCS: input var ok, CSRF ok.
2016-07-26 12:39:31 +00:00
$shop_page_id = wc_get_page_id ( 'shop' );
2017-04-27 00:51:30 +00:00
2018-03-07 21:37:32 +00:00
if ( $shop_page_id === $post_id || in_array ( $post_id , wc_get_page_children ( $shop_page_id ), true ) ) {
2016-10-21 14:29:50 +00:00
do_action ( 'woocommerce_flush_rewrite_rules' );
2014-06-04 06:46:21 +00:00
}
}
2017-04-27 00:51:30 +00:00
add_action ( 'admin_footer' , 'flush_rewrite_rules_on_shop_page_save' );
2014-06-04 06:46:21 +00:00
/**
2015-10-31 19:10:45 +00:00
* Various rewrite rule fixes .
2014-06-02 20:00:44 +00:00
*
* @ since 2.2
2017-12-01 17:13:27 +00:00
* @ param array $rules Rules .
2014-06-02 20:00:44 +00:00
* @ return array
*/
function wc_fix_rewrite_rules ( $rules ) {
2014-06-04 06:46:21 +00:00
global $wp_rewrite ;
2017-02-07 16:16:45 +00:00
$permalinks = wc_get_permalink_structure ();
2014-06-02 20:00:44 +00:00
2015-10-31 19:10:45 +00:00
// Fix the rewrite rules when the product permalink have %product_cat% flag.
2017-12-01 17:13:27 +00:00
if ( preg_match ( '`/(.+)(/%product_cat%)`' , $permalinks [ 'product_rewrite_slug' ], $matches ) ) {
2014-06-02 20:00:44 +00:00
foreach ( $rules as $rule => $rewrite ) {
2014-10-21 13:20:19 +00:00
if ( preg_match ( '`^' . preg_quote ( $matches [ 1 ], '`' ) . '/\(`' , $rule ) && preg_match ( '/^(index\.php\?product_cat)(?!(.*product))/' , $rewrite ) ) {
2014-06-02 20:00:44 +00:00
unset ( $rules [ $rule ] );
}
}
}
2016-07-26 12:39:31 +00:00
// If the shop page is used as the base, we need to handle shop page subpages to avoid 404s.
2017-12-01 17:13:27 +00:00
if ( ! $permalinks [ 'use_verbose_page_rules' ] ) {
return $rules ;
}
$shop_page_id = wc_get_page_id ( 'shop' );
if ( $shop_page_id ) {
2016-07-26 12:39:31 +00:00
$page_rewrite_rules = array ();
$subpages = wc_get_page_children ( $shop_page_id );
2017-12-01 17:13:27 +00:00
// Subpage rules.
2016-07-26 12:39:31 +00:00
foreach ( $subpages as $subpage ) {
2017-12-01 17:13:27 +00:00
$uri = get_page_uri ( $subpage );
2016-07-26 12:39:31 +00:00
$page_rewrite_rules [ $uri . '/?$' ] = 'index.php?pagename=' . $uri ;
$wp_generated_rewrite_rules = $wp_rewrite -> generate_rewrite_rules ( $uri , EP_PAGES , true , true , false , false );
foreach ( $wp_generated_rewrite_rules as $key => $value ) {
$wp_generated_rewrite_rules [ $key ] = $value . '&pagename=' . $uri ;
}
$page_rewrite_rules = array_merge ( $page_rewrite_rules , $wp_generated_rewrite_rules );
}
2017-12-01 17:13:27 +00:00
// Merge with rules.
2016-07-26 12:39:31 +00:00
$rules = array_merge ( $page_rewrite_rules , $rules );
2014-06-04 06:46:21 +00:00
}
2014-06-02 20:00:44 +00:00
return $rules ;
}
add_filter ( 'rewrite_rules_array' , 'wc_fix_rewrite_rules' );
2014-06-04 10:16:19 +00:00
2014-08-06 10:50:03 +00:00
/**
* Prevent product attachment links from breaking when using complex rewrite structures .
2014-08-12 15:13:29 +00:00
*
2017-12-01 17:13:27 +00:00
* @ param string $link Link .
* @ param int $post_id Post ID .
2014-08-06 10:50:03 +00:00
* @ return string
*/
function wc_fix_product_attachment_link ( $link , $post_id ) {
2017-10-24 15:29:04 +00:00
$parent_type = get_post_type ( wp_get_post_parent_id ( $post_id ) );
if ( 'product' === $parent_type || 'product_variation' === $parent_type ) {
$link = home_url ( '/?attachment_id=' . $post_id );
2014-08-06 10:50:03 +00:00
}
return $link ;
}
add_filter ( 'attachment_link' , 'wc_fix_product_attachment_link' , 10 , 2 );
2014-06-04 10:16:19 +00:00
/**
2015-10-31 19:10:45 +00:00
* Protect downloads from ms - files . php in multisite .
2014-06-04 10:16:19 +00:00
*
2017-11-07 12:11:37 +00:00
* @ param string $rewrite rewrite rules .
2014-06-04 10:16:19 +00:00
* @ return string
*/
function wc_ms_protect_download_rewite_rules ( $rewrite ) {
2017-11-07 12:11:37 +00:00
if ( ! is_multisite () || 'redirect' === get_option ( 'woocommerce_file_download_method' ) ) {
2014-06-04 10:16:19 +00:00
return $rewrite ;
}
$rule = " \n # WooCommerce Rules - Protect Files from ms-files.php \n \n " ;
$rule .= " <IfModule mod_rewrite.c> \n " ;
$rule .= " RewriteEngine On \n " ;
$rule .= " RewriteCond % { QUERY_STRING} file=woocommerce_uploads/ [NC] \n " ;
$rule .= " RewriteRule /ms-files.php $ - [F] \n " ;
$rule .= " </IfModule> \n \n " ;
return $rule . $rewrite ;
}
2014-06-24 18:56:53 +00:00
add_filter ( 'mod_rewrite_rules' , 'wc_ms_protect_download_rewite_rules' );
2014-11-18 14:56:13 +00:00
/**
2014-12-23 17:33:51 +00:00
* Formats a string in the format COUNTRY : STATE into an array .
2015-11-03 13:31:20 +00:00
*
2014-11-18 14:56:13 +00:00
* @ since 2.3 . 0
2017-12-01 17:13:27 +00:00
* @ param string $country_string Country string .
2014-11-18 14:56:13 +00:00
* @ return array
*/
2014-12-23 17:33:51 +00:00
function wc_format_country_state_string ( $country_string ) {
if ( strstr ( $country_string , ':' ) ) {
list ( $country , $state ) = explode ( ':' , $country_string );
2014-11-18 14:56:13 +00:00
} else {
2014-12-23 17:33:51 +00:00
$country = $country_string ;
2014-11-18 14:56:13 +00:00
$state = '' ;
}
return array (
'country' => $country ,
2016-08-27 01:46:45 +00:00
'state' => $state ,
2014-11-18 14:56:13 +00:00
);
}
2014-12-23 17:33:51 +00:00
/**
* Get the store ' s base location .
2015-11-03 13:31:20 +00:00
*
2014-12-23 17:33:51 +00:00
* @ since 2.3 . 0
* @ return array
*/
function wc_get_base_location () {
$default = apply_filters ( 'woocommerce_get_base_location' , get_option ( 'woocommerce_default_country' ) );
return wc_format_country_state_string ( $default );
}
/**
2016-01-07 11:25:24 +00:00
* Get the customer ' s default location .
2015-06-17 11:12:49 +00:00
*
2015-10-31 19:10:45 +00:00
* Filtered , and set to base location or left blank . If cache - busting ,
* this should only be used when 'location' is set in the querystring .
2015-06-17 11:12:49 +00:00
*
2014-12-23 17:33:51 +00:00
* @ since 2.3 . 0
* @ return array
*/
function wc_get_customer_default_location () {
2019-01-07 15:01:46 +00:00
$set_default_location_to = get_option ( 'woocommerce_default_customer_address' , 'geolocation' );
$default_location = '' === $set_default_location_to ? '' : get_option ( 'woocommerce_default_country' , '' );
$location = wc_format_country_state_string ( apply_filters ( 'woocommerce_customer_default_location' , $default_location ) );
2016-04-01 10:14:24 +00:00
2019-01-07 15:01:46 +00:00
// Geolocation takes priority if used and if geolocation is possible.
if ( 'geolocation' === $set_default_location_to || 'geolocation_ajax' === $set_default_location_to ) {
$ua = wc_get_user_agent ();
2014-12-23 18:50:05 +00:00
2019-01-07 15:01:46 +00:00
// Exclude common bots from geolocation by user agent.
if ( ! stristr ( $ua , 'bot' ) && ! stristr ( $ua , 'spider' ) && ! stristr ( $ua , 'crawl' ) ) {
$geolocation = WC_Geolocation :: geolocate_ip ( '' , true , false );
2016-04-18 13:51:39 +00:00
2019-01-07 15:01:46 +00:00
if ( ! empty ( $geolocation [ 'country' ] ) ) {
$location = $geolocation ;
2018-12-04 19:47:04 +00:00
}
2019-01-07 15:01:46 +00:00
}
}
2018-12-04 19:47:04 +00:00
2019-01-07 15:01:46 +00:00
// Once we have a location, ensure it's valid, otherwise fallback to a valid location.
$allowed_country_codes = WC () -> countries -> get_allowed_countries ();
if ( ! empty ( $location [ 'country' ] ) && ! array_key_exists ( $location [ 'country' ], $allowed_country_codes ) ) {
$location [ 'country' ] = current ( $allowed_country_codes );
$location [ 'state' ] = '' ;
2014-12-23 17:33:51 +00:00
}
2016-01-07 11:25:24 +00:00
return apply_filters ( 'woocommerce_customer_default_location_array' , $location );
2014-12-23 17:33:51 +00:00
}
2015-01-19 05:11:41 +00:00
2016-08-09 13:02:40 +00:00
/**
* Get user agent string .
2017-12-01 17:13:27 +00:00
*
2017-03-15 16:36:53 +00:00
* @ since 3.0 . 0
2016-08-09 13:02:40 +00:00
* @ return string
*/
function wc_get_user_agent () {
2018-07-11 11:54:14 +00:00
return isset ( $_SERVER [ 'HTTP_USER_AGENT' ] ) ? wc_clean ( wp_unslash ( $_SERVER [ 'HTTP_USER_AGENT' ] ) ) : '' ; // @codingStandardsIgnoreLine
2016-08-09 13:02:40 +00:00
}
2015-10-31 19:10:45 +00:00
// This function can be removed when WP 3.9.2 or greater is required.
2015-01-19 05:11:41 +00:00
if ( ! function_exists ( 'hash_equals' ) ) :
/**
* Compare two strings in constant time .
*
* This function was added in PHP 5.6 .
* It can leak the length of a string .
*
* @ since 3.9 . 2
*
* @ param string $a Expected string .
* @ param string $b Actual string .
* @ return bool Whether strings are equal .
*/
function hash_equals ( $a , $b ) {
$a_length = strlen ( $a );
2016-09-07 22:32:24 +00:00
if ( strlen ( $b ) !== $a_length ) {
2015-01-19 05:11:41 +00:00
return false ;
}
$result = 0 ;
// Do not attempt to "optimize" this.
for ( $i = 0 ; $i < $a_length ; $i ++ ) {
$result |= ord ( $a [ $i ] ) ^ ord ( $b [ $i ] );
}
2016-09-07 22:32:24 +00:00
return 0 === $result ;
2015-01-19 05:11:41 +00:00
}
endif ;
2015-06-08 15:01:54 +00:00
/**
2015-10-31 19:10:45 +00:00
* Generate a rand hash .
2015-06-08 15:01:54 +00:00
*
* @ since 2.4 . 0
* @ return string
*/
function wc_rand_hash () {
2018-05-24 16:42:56 +00:00
if ( ! function_exists ( 'openssl_random_pseudo_bytes' ) ) {
2015-06-08 15:01:54 +00:00
return sha1 ( wp_rand () );
}
2018-05-24 16:42:56 +00:00
return bin2hex ( openssl_random_pseudo_bytes ( 20 ) ); // @codingStandardsIgnoreLine
2015-06-08 15:01:54 +00:00
}
2015-06-08 15:57:19 +00:00
/**
2015-10-31 19:10:45 +00:00
* WC API - Hash .
2015-06-08 15:57:19 +00:00
*
* @ since 2.4 . 0
2017-12-01 17:13:27 +00:00
* @ param string $data Message to be hashed .
2015-06-08 15:57:19 +00:00
* @ return string
*/
function wc_api_hash ( $data ) {
return hash_hmac ( 'sha256' , $data , 'wc-api' );
}
2015-11-04 12:14:48 +00:00
/**
* Find all possible combinations of values from the input array and return in a logical order .
2017-12-01 17:13:27 +00:00
*
2015-11-04 12:14:48 +00:00
* @ since 2.5 . 0
2017-12-01 17:13:27 +00:00
* @ param array $input Input .
2015-11-04 12:14:48 +00:00
* @ return array
*/
function wc_array_cartesian ( $input ) {
$input = array_filter ( $input );
$results = array ();
$indexes = array ();
$index = 0 ;
2017-12-01 17:13:27 +00:00
// Generate indexes from keys and values so we have a logical sort order.
2015-11-04 12:14:48 +00:00
foreach ( $input as $key => $values ) {
foreach ( $values as $value ) {
2016-03-04 10:53:48 +00:00
$indexes [ $key ][ $value ] = $index ++ ;
2015-11-04 12:14:48 +00:00
}
}
2017-12-01 17:13:27 +00:00
// Loop over the 2D array of indexes and generate all combinations.
2015-11-04 12:14:48 +00:00
foreach ( $indexes as $key => $values ) {
2017-12-01 17:13:27 +00:00
// When result is empty, fill with the values of the first looped array.
2015-11-04 12:14:48 +00:00
if ( empty ( $results ) ) {
foreach ( $values as $value ) {
$results [] = array ( $key => $value );
}
} else {
2017-12-01 17:13:27 +00:00
// Second and subsequent input sub-array merging.
2015-11-04 12:14:48 +00:00
foreach ( $results as $result_key => $result ) {
foreach ( $values as $value ) {
2017-12-01 17:13:27 +00:00
// If the key is not set, we can set it.
2015-11-04 12:14:48 +00:00
if ( ! isset ( $results [ $result_key ][ $key ] ) ) {
$results [ $result_key ][ $key ] = $value ;
} else {
2017-12-01 17:13:27 +00:00
// If the key is set, we can add a new combination to the results array.
2015-11-04 12:14:48 +00:00
$new_combination = $results [ $result_key ];
$new_combination [ $key ] = $value ;
$results [] = $new_combination ;
}
}
}
}
}
2017-12-01 17:13:27 +00:00
// Sort the indexes.
2015-11-04 12:14:48 +00:00
arsort ( $results );
2017-12-01 17:13:27 +00:00
// Convert indexes back to values.
2015-11-04 12:14:48 +00:00
foreach ( $results as $result_key => $result ) {
$converted_values = array ();
2017-12-01 17:13:27 +00:00
// Sort the values.
2015-11-04 12:14:48 +00:00
arsort ( $results [ $result_key ] );
2017-12-01 17:13:27 +00:00
// Convert the values.
2015-11-04 12:14:48 +00:00
foreach ( $results [ $result_key ] as $key => $value ) {
2017-12-01 17:13:27 +00:00
$converted_values [ $key ] = array_search ( $value , $indexes [ $key ], true );
2015-11-04 12:14:48 +00:00
}
2015-11-04 14:11:40 +00:00
2015-11-04 12:14:48 +00:00
$results [ $result_key ] = $converted_values ;
}
return $results ;
}
2015-11-04 14:11:40 +00:00
/**
* Run a MySQL transaction query , if supported .
2017-12-01 17:13:27 +00:00
*
2015-11-04 14:11:40 +00:00
* @ since 2.5 . 0
2017-12-01 17:13:27 +00:00
* @ param string $type Types : start ( default ), commit , rollback .
2018-01-03 16:13:08 +00:00
* @ param bool $force use of transactions .
2015-11-04 14:11:40 +00:00
*/
2018-01-03 16:13:08 +00:00
function wc_transaction_query ( $type = 'start' , $force = false ) {
2015-11-04 14:11:40 +00:00
global $wpdb ;
2016-01-15 11:43:06 +00:00
$wpdb -> hide_errors ();
2015-11-04 14:11:40 +00:00
2017-09-05 19:51:09 +00:00
wc_maybe_define_constant ( 'WC_USE_TRANSACTIONS' , true );
2015-11-04 14:11:40 +00:00
2018-01-03 16:13:08 +00:00
if ( WC_USE_TRANSACTIONS || $force ) {
2015-11-04 14:11:40 +00:00
switch ( $type ) {
2017-12-01 17:13:27 +00:00
case 'commit' :
2015-11-04 14:11:40 +00:00
$wpdb -> query ( 'COMMIT' );
break ;
2017-12-01 17:13:27 +00:00
case 'rollback' :
2015-11-04 14:11:40 +00:00
$wpdb -> query ( 'ROLLBACK' );
break ;
2017-12-01 17:13:27 +00:00
default :
2015-11-04 14:11:40 +00:00
$wpdb -> query ( 'START TRANSACTION' );
2017-12-01 17:13:27 +00:00
break ;
2015-11-04 14:11:40 +00:00
}
}
}
2015-12-18 17:10:58 +00:00
2016-02-10 14:40:46 +00:00
/**
* Gets the url to the cart page .
*
* @ since 2.5 . 0
*
* @ return string Url to cart page
*/
function wc_get_cart_url () {
return apply_filters ( 'woocommerce_get_cart_url' , wc_get_page_permalink ( 'cart' ) );
}
/**
* Gets the url to the checkout page .
*
* @ since 2.5 . 0
*
* @ return string Url to checkout page
*/
function wc_get_checkout_url () {
$checkout_url = wc_get_page_permalink ( 'checkout' );
if ( $checkout_url ) {
2017-12-01 17:13:27 +00:00
// Force SSL if needed.
2016-02-10 14:40:46 +00:00
if ( is_ssl () || 'yes' === get_option ( 'woocommerce_force_ssl_checkout' ) ) {
$checkout_url = str_replace ( 'http:' , 'https:' , $checkout_url );
}
}
return apply_filters ( 'woocommerce_get_checkout_url' , $checkout_url );
}
2015-12-18 17:10:58 +00:00
/**
* Register a shipping method .
*
* @ since 1.5 . 7
* @ param string | object $shipping_method class name ( string ) or a class object .
*/
function woocommerce_register_shipping_method ( $shipping_method ) {
2018-10-02 15:03:17 +00:00
WC () -> shipping () -> register_shipping_method ( $shipping_method );
2015-12-18 17:10:58 +00:00
}
2016-05-03 14:16:20 +00:00
if ( ! function_exists ( 'wc_get_shipping_zone' ) ) {
/**
* Get the shipping zone matching a given package from the cart .
*
* @ since 2.6 . 0
* @ uses WC_Shipping_Zones :: get_zone_matching_package
2017-12-01 17:13:27 +00:00
* @ param array $package Shipping package .
2016-05-03 14:16:20 +00:00
* @ return WC_Shipping_Zone
*/
function wc_get_shipping_zone ( $package ) {
return WC_Shipping_Zones :: get_zone_matching_package ( $package );
}
2015-12-18 17:10:58 +00:00
}
2016-02-17 16:02:22 +00:00
2016-03-01 18:07:27 +00:00
/**
* Get a nice name for credit card providers .
*
* @ since 2.6 . 0
2017-12-01 17:13:27 +00:00
* @ param string $type Provider Slug / Type .
2016-03-01 18:07:27 +00:00
* @ return string
*/
function wc_get_credit_card_type_label ( $type ) {
2017-12-01 17:13:27 +00:00
// Normalize.
2016-03-01 18:07:27 +00:00
$type = strtolower ( $type );
$type = str_replace ( '-' , ' ' , $type );
$type = str_replace ( '_' , ' ' , $type );
2018-03-07 21:37:32 +00:00
$labels = apply_filters (
2018-11-21 13:01:37 +00:00
'woocommerce_credit_card_type_labels' ,
array (
2018-03-07 21:37:32 +00:00
'mastercard' => __ ( 'MasterCard' , 'woocommerce' ),
'visa' => __ ( 'Visa' , 'woocommerce' ),
'discover' => __ ( 'Discover' , 'woocommerce' ),
'american express' => __ ( 'American Express' , 'woocommerce' ),
'diners' => __ ( 'Diners' , 'woocommerce' ),
'jcb' => __ ( 'JCB' , 'woocommerce' ),
)
);
2016-03-01 18:07:27 +00:00
return apply_filters ( 'woocommerce_get_credit_card_type_label' , ( array_key_exists ( $type , $labels ) ? $labels [ $type ] : ucfirst ( $type ) ) );
}
2016-02-17 16:02:22 +00:00
/**
* Outputs a " back " link so admin screens can easily jump back a page .
2016-02-21 04:25:33 +00:00
*
* @ param string $label Title of the page to return to .
* @ param string $url URL of the page to return to .
2016-02-17 16:02:22 +00:00
*/
function wc_back_link ( $label , $url ) {
2016-11-04 15:41:51 +00:00
echo '<small class="wc-admin-breadcrumb"><a href="' . esc_url ( $url ) . '" aria-label="' . esc_attr ( $label ) . '">⤴</a></small>' ;
2016-02-17 16:02:22 +00:00
}
2016-03-31 14:30:42 +00:00
/**
* Display a WooCommerce help tip .
*
* @ since 2.5 . 0
*
2017-12-01 17:13:27 +00:00
* @ param string $tip Help tip text .
* @ param bool $allow_html Allow sanitized HTML if true or escape .
2016-03-31 14:30:42 +00:00
* @ return string
*/
function wc_help_tip ( $tip , $allow_html = false ) {
if ( $allow_html ) {
$tip = wc_sanitize_tooltip ( $tip );
} else {
$tip = esc_attr ( $tip );
}
return '<span class="woocommerce-help-tip" data-tip="' . $tip . '"></span>' ;
}
2016-04-22 13:02:36 +00:00
/**
* Return a list of potential postcodes for wildcard searching .
2017-12-01 17:13:27 +00:00
*
2016-04-22 15:47:54 +00:00
* @ since 2.6 . 0
2017-12-01 17:13:27 +00:00
* @ param string $postcode Postcode .
* @ param string $country Country to format postcode for matching .
2016-06-06 16:50:18 +00:00
* @ return string []
2016-04-22 13:02:36 +00:00
*/
2016-06-16 10:28:53 +00:00
function wc_get_wildcard_postcodes ( $postcode , $country = '' ) {
2016-10-12 10:52:39 +00:00
$formatted_postcode = wc_format_postcode ( $postcode , $country );
2017-01-22 01:24:20 +00:00
$length = function_exists ( 'mb_strlen' ) ? mb_strlen ( $formatted_postcode ) : strlen ( $formatted_postcode );
2016-10-12 10:52:39 +00:00
$postcodes = array (
$postcode ,
$formatted_postcode ,
$formatted_postcode . '*' ,
);
2016-04-22 13:02:36 +00:00
2016-10-12 10:52:39 +00:00
for ( $i = 0 ; $i < $length ; $i ++ ) {
2017-01-22 01:24:20 +00:00
$postcodes [] = ( function_exists ( 'mb_substr' ) ? mb_substr ( $formatted_postcode , 0 , ( $i + 1 ) * - 1 ) : substr ( $formatted_postcode , 0 , ( $i + 1 ) * - 1 ) ) . '*' ;
2016-04-22 13:02:36 +00:00
}
2016-06-16 10:28:53 +00:00
2016-04-22 13:02:36 +00:00
return $postcodes ;
}
/**
* Used by shipping zones and taxes to compare a given $postcode to stored
* postcodes to find matches for numerical ranges , and wildcards .
2017-12-01 17:13:27 +00:00
*
2016-04-22 15:47:54 +00:00
* @ since 2.6 . 0
2017-12-01 17:13:27 +00:00
* @ param string $postcode Postcode you want to match against stored postcodes .
* @ param array $objects Array of postcode objects from Database .
* @ param string $object_id_key DB column name for the ID .
2016-04-22 13:02:36 +00:00
* @ param string $object_compare_key DB column name for the value .
2017-12-01 17:13:27 +00:00
* @ param string $country Country from which this postcode belongs . Allows for formatting .
2016-06-10 23:26:07 +00:00
* @ return array Array of matching object ID and matching values .
2016-04-22 13:02:36 +00:00
*/
2016-06-16 10:28:53 +00:00
function wc_postcode_location_matcher ( $postcode , $objects , $object_id_key , $object_compare_key , $country = '' ) {
2016-04-28 16:51:43 +00:00
$postcode = wc_normalize_postcode ( $postcode );
2016-06-16 10:28:53 +00:00
$wildcard_postcodes = array_map ( 'wc_clean' , wc_get_wildcard_postcodes ( $postcode , $country ) );
2016-04-27 23:43:48 +00:00
$matches = array ();
2016-04-22 13:02:36 +00:00
2016-06-10 23:26:07 +00:00
foreach ( $objects as $object ) {
$object_id = $object -> $object_id_key ;
$compare_against = $object -> $object_compare_key ;
2016-04-22 13:02:36 +00:00
2016-04-27 23:43:48 +00:00
// Handle postcodes containing ranges.
2016-05-23 16:30:37 +00:00
if ( strstr ( $compare_against , '...' ) ) {
$range = array_map ( 'trim' , explode ( '...' , $compare_against ) );
2016-04-22 13:02:36 +00:00
2017-12-01 17:13:27 +00:00
if ( 2 !== count ( $range ) ) {
2016-04-22 13:02:36 +00:00
continue ;
}
list ( $min , $max ) = $range ;
2016-04-27 23:43:48 +00:00
// If the postcode is non-numeric, make it numeric.
2016-04-22 13:02:36 +00:00
if ( ! is_numeric ( $min ) || ! is_numeric ( $max ) ) {
2016-06-10 23:26:07 +00:00
$compare = wc_make_numeric_postcode ( $postcode );
2016-05-26 14:09:03 +00:00
$min = str_pad ( wc_make_numeric_postcode ( $min ), strlen ( $compare ), '0' );
$max = str_pad ( wc_make_numeric_postcode ( $max ), strlen ( $compare ), '0' );
2016-06-10 23:26:07 +00:00
} else {
$compare = $postcode ;
2016-04-22 13:02:36 +00:00
}
if ( $compare >= $min && $compare <= $max ) {
2017-12-01 17:13:27 +00:00
$matches [ $object_id ] = isset ( $matches [ $object_id ] ) ? $matches [ $object_id ] : array ();
2016-06-10 23:26:07 +00:00
$matches [ $object_id ][] = $compare_against ;
2016-04-22 13:02:36 +00:00
}
2017-12-01 17:13:27 +00:00
} elseif ( in_array ( $compare_against , $wildcard_postcodes , true ) ) {
// Wildcard and standard comparison.
$matches [ $object_id ] = isset ( $matches [ $object_id ] ) ? $matches [ $object_id ] : array ();
2016-06-10 23:26:07 +00:00
$matches [ $object_id ][] = $compare_against ;
2016-04-22 13:02:36 +00:00
}
}
return $matches ;
}
2016-05-25 11:04:42 +00:00
/**
* Gets number of shipping methods currently enabled . Used to identify if
* shipping is configured .
2016-05-25 19:06:06 +00:00
*
2016-05-25 11:04:42 +00:00
* @ since 2.6 . 0
* @ param bool $include_legacy Count legacy shipping methods too .
* @ return int
*/
function wc_get_shipping_method_count ( $include_legacy = false ) {
global $wpdb ;
2019-01-21 12:05:58 +00:00
$transient_name = $include_legacy ? 'wc_shipping_method_count_legacy' : 'wc_shipping_method_count' ;
$transient_version = WC_Cache_Helper :: get_transient_version ( 'shipping' );
$transient_value = get_transient ( $transient_name );
2016-05-25 11:04:42 +00:00
2019-01-21 12:05:58 +00:00
if ( isset ( $transient_value [ 'value' ], $transient_value [ 'version' ] ) && $transient_value [ 'version' ] === $transient_version ) {
return absint ( $transient_value [ 'value' ] );
}
2016-05-25 11:04:42 +00:00
2019-01-21 12:05:58 +00:00
$method_count = absint ( $wpdb -> get_var ( " SELECT COUNT(*) FROM { $wpdb -> prefix } woocommerce_shipping_zone_methods " ) );
2016-05-26 11:54:14 +00:00
2019-01-21 12:05:58 +00:00
if ( $include_legacy ) {
// Count activated methods that don't support shipping zones.
$methods = WC () -> shipping () -> get_shipping_methods ();
foreach ( $methods as $method ) {
if ( isset ( $method -> enabled ) && 'yes' === $method -> enabled && ! $method -> supports ( 'shipping-zones' ) ) {
$method_count ++ ;
2016-05-25 11:04:42 +00:00
}
}
}
2019-01-21 12:05:58 +00:00
$transient_value = array (
'version' => $transient_version ,
'value' => $method_count ,
);
set_transient ( $transient_name , $transient_value , DAY_IN_SECONDS * 30 );
return $method_count ;
2016-05-25 11:04:42 +00:00
}
2016-06-06 15:55:27 +00:00
/**
* Wrapper for set_time_limit to see if it is enabled .
2017-05-15 11:50:52 +00:00
*
2017-11-08 15:07:00 +00:00
* @ since 2.6 . 0
2017-12-01 17:13:27 +00:00
* @ param int $limit Time limit .
2016-06-06 15:55:27 +00:00
*/
function wc_set_time_limit ( $limit = 0 ) {
2018-11-21 13:08:26 +00:00
if ( function_exists ( 'set_time_limit' ) && false === strpos ( ini_get ( 'disable_functions' ), 'set_time_limit' ) && ! ini_get ( 'safe_mode' ) ) { // phpcs:ignore PHPCompatibility.IniDirectives.RemovedIniDirectives.safe_modeDeprecatedRemoved
2017-12-01 17:13:27 +00:00
@ set_time_limit ( $limit ); // @codingStandardsIgnoreLine
2016-06-06 15:55:27 +00:00
}
}
2016-06-06 16:24:31 +00:00
2017-11-08 15:07:00 +00:00
/**
* Wrapper for nocache_headers which also disables page caching .
*
* @ since 3.2 . 4
*/
function wc_nocache_headers () {
WC_Cache_Helper :: set_nocache_constants ();
nocache_headers ();
}
2016-06-06 16:24:31 +00:00
/**
* Used to sort products attributes with uasort .
2017-05-15 11:50:52 +00:00
*
2017-12-01 17:13:27 +00:00
* @ since 2.6 . 0
* @ param array $a First attribute to compare .
* @ param array $b Second attribute to compare .
2017-05-15 11:50:52 +00:00
* @ return int
2016-06-06 16:24:31 +00:00
*/
function wc_product_attribute_uasort_comparison ( $a , $b ) {
2018-10-31 05:41:01 +00:00
return wc_uasort_comparison ( $a [ 'position' ], $b [ 'position' ] );
2016-06-06 16:24:31 +00:00
}
2016-07-11 15:26:54 +00:00
2016-07-21 13:30:05 +00:00
/**
2016-07-21 14:30:07 +00:00
* Used to sort shipping zone methods with uasort .
2017-05-15 11:50:52 +00:00
*
2017-12-01 17:13:27 +00:00
* @ since 3.0 . 0
* @ param array $a First shipping zone method to compare .
* @ param array $b Second shipping zone method to compare .
2017-05-15 11:50:52 +00:00
* @ return int
2016-07-21 13:30:05 +00:00
*/
function wc_shipping_zone_method_order_uasort_comparison ( $a , $b ) {
2018-10-31 05:40:08 +00:00
return wc_uasort_comparison ( $a -> method_order , $b -> method_order );
2016-07-21 13:30:05 +00:00
}
2018-10-31 06:14:50 +00:00
/**
* User to sort checkout fields based on priority with uasort .
*
* @ since 3.5 . 1
* @ param array $a First field to compare .
* @ param array $b Second field to compare .
* @ return int
*/
function wc_checkout_fields_uasort_comparison ( $a , $b ) {
2018-11-03 15:13:14 +00:00
/*
2018-11-06 20:53:11 +00:00
* We are not guaranteed to get a priority
2018-11-03 15:13:14 +00:00
* setting . So don 't compare if they don' t
* exist .
*/
if ( ! isset ( $a [ 'priority' ], $b [ 'priority' ] ) ) {
return 0 ;
}
2018-10-31 06:14:50 +00:00
return wc_uasort_comparison ( $a [ 'priority' ], $b [ 'priority' ] );
}
2018-10-31 05:38:38 +00:00
/**
* User to sort two values with ausort .
*
2018-10-31 05:40:08 +00:00
* @ since 3.5 . 1
2018-10-31 05:38:38 +00:00
* @ param int $a First value to compare .
* @ param int $b Second value to compare .
* @ return int
*/
function wc_uasort_comparison ( $a , $b ) {
if ( $a === $b ) {
return 0 ;
}
return ( $a < $b ) ? - 1 : 1 ;
}
2019-01-11 11:18:59 +00:00
/**
* Sort values based on ascii , usefull for special chars in strings .
*
* @ param string $a First value .
* @ param string $b Second value .
* @ return int
*/
function wc_ascii_uasort_comparison ( $a , $b ) {
2019-01-22 13:26:40 +00:00
if ( function_exists ( 'iconv' ) ) {
$a = iconv ( 'UTF-8' , 'ASCII//TRANSLIT' , $a );
$b = iconv ( 'UTF-8' , 'ASCII//TRANSLIT' , $b );
}
2019-01-22 13:39:17 +00:00
return strcmp ( $a , $b );
2019-01-11 11:18:59 +00:00
}
2017-11-06 21:25:02 +00:00
/**
* Get rounding mode for internal tax calculations .
*
* @ since 3.2 . 4
* @ return int
*/
function wc_get_tax_rounding_mode () {
$constant = WC_TAX_ROUNDING_MODE ;
if ( 'auto' === $constant ) {
return 'yes' === get_option ( 'woocommerce_prices_include_tax' , 'no' ) ? 2 : 1 ;
}
return intval ( $constant );
}
2016-07-21 13:30:05 +00:00
2016-07-11 15:26:54 +00:00
/**
2016-07-21 09:14:12 +00:00
* Get rounding precision for internal WC calculations .
* Will increase the precision of wc_get_price_decimals by 2 decimals , unless WC_ROUNDING_PRECISION is set to a higher number .
2016-07-11 15:26:54 +00:00
*
* @ since 2.6 . 3
* @ return int
*/
function wc_get_rounding_precision () {
2016-07-21 09:14:12 +00:00
$precision = wc_get_price_decimals () + 2 ;
if ( absint ( WC_ROUNDING_PRECISION ) > $precision ) {
$precision = absint ( WC_ROUNDING_PRECISION );
2016-07-11 15:26:54 +00:00
}
2016-07-21 09:14:12 +00:00
return $precision ;
2016-07-11 15:26:54 +00:00
}
2016-08-08 12:59:23 +00:00
2017-07-27 09:49:47 +00:00
/**
2017-12-04 20:32:51 +00:00
* Add precision to a number and return a number .
2017-07-27 09:49:47 +00:00
*
* @ since 3.2 . 0
* @ param float $value Number to add precision to .
2017-12-07 20:21:52 +00:00
* @ param bool $round If should round after adding precision .
2017-11-20 16:30:04 +00:00
* @ return int | float
2017-07-27 09:49:47 +00:00
*/
2017-11-20 16:37:44 +00:00
function wc_add_number_precision ( $value , $round = true ) {
2017-12-04 20:32:51 +00:00
$cent_precision = pow ( 10 , wc_get_price_decimals () );
$value = $value * $cent_precision ;
return $round ? round ( $value , wc_get_rounding_precision () - wc_get_price_decimals () ) : $value ;
2017-07-27 09:49:47 +00:00
}
/**
* Remove precision from a number and return a float .
*
* @ since 3.2 . 0
* @ param float $value Number to add precision to .
* @ return float
*/
function wc_remove_number_precision ( $value ) {
2017-12-04 20:32:51 +00:00
$cent_precision = pow ( 10 , wc_get_price_decimals () );
return $value / $cent_precision ;
2017-07-27 09:49:47 +00:00
}
/**
* Add precision to an array of number and return an array of int .
*
* @ since 3.2 . 0
* @ param array $value Number to add precision to .
2017-12-01 17:13:27 +00:00
* @ param bool $round Should we round after adding precision ? .
2018-05-25 10:18:49 +00:00
* @ return int | array
2017-07-27 09:49:47 +00:00
*/
2017-11-20 16:37:44 +00:00
function wc_add_number_precision_deep ( $value , $round = true ) {
2018-05-25 10:18:49 +00:00
if ( ! is_array ( $value ) ) {
return wc_add_number_precision ( $value , $round );
2017-07-27 09:49:47 +00:00
}
2018-05-25 10:18:49 +00:00
foreach ( $value as $key => $sub_value ) {
$value [ $key ] = wc_add_number_precision_deep ( $sub_value , $round );
}
2017-07-27 09:49:47 +00:00
return $value ;
}
/**
* Remove precision from an array of number and return an array of int .
*
* @ since 3.2 . 0
* @ param array $value Number to add precision to .
2018-05-24 16:55:00 +00:00
* @ return int | array
2017-07-27 09:49:47 +00:00
*/
function wc_remove_number_precision_deep ( $value ) {
2018-05-24 16:55:00 +00:00
if ( ! is_array ( $value ) ) {
2018-05-24 17:02:07 +00:00
return wc_remove_number_precision ( $value );
2017-07-27 09:49:47 +00:00
}
2018-05-24 16:55:00 +00:00
foreach ( $value as $key => $sub_value ) {
$value [ $key ] = wc_remove_number_precision_deep ( $sub_value );
2017-07-27 09:49:47 +00:00
}
2018-05-24 16:55:00 +00:00
2017-07-27 09:49:47 +00:00
return $value ;
}
2016-08-08 12:59:23 +00:00
/**
2017-01-14 17:06:10 +00:00
* Get a shared logger instance .
*
2017-01-15 12:29:10 +00:00
* Use the woocommerce_logging_class filter to change the logging class . You may provide one of the following :
* - a class name which will be instantiated as `new $class` with no arguments
* - an instance which will be used directly as the logger
* In either case , the class or instance * must * implement WC_Logger_Interface .
2017-01-14 17:06:10 +00:00
*
* @ see WC_Logger_Interface
*
2016-08-08 12:59:23 +00:00
* @ return WC_Logger
*/
function wc_get_logger () {
2016-12-15 19:52:24 +00:00
static $logger = null ;
2018-03-01 16:24:53 +00:00
$class = apply_filters ( 'woocommerce_logging_class' , 'WC_Logger' );
2018-09-26 10:41:28 +00:00
if ( null !== $logger && is_string ( $class ) && is_a ( $logger , $class ) ) {
2018-06-07 07:46:06 +00:00
return $logger ;
}
2018-03-01 16:24:53 +00:00
2018-06-07 07:46:06 +00:00
$implements = class_implements ( $class );
if ( is_array ( $implements ) && in_array ( 'WC_Logger_Interface' , $implements , true ) ) {
$logger = is_object ( $class ) ? $class : new $class ();
} else {
wc_doing_it_wrong (
__FUNCTION__ ,
sprintf (
/* translators: 1: class name 2: woocommerce_logging_class 3: WC_Logger_Interface */
__ ( 'The class %1$s provided by %2$s filter must implement %3$s.' , 'woocommerce' ),
'<code>' . esc_html ( is_object ( $class ) ? get_class ( $class ) : $class ) . '</code>' ,
'<code>woocommerce_logging_class</code>' ,
'<code>WC_Logger_Interface</code>'
),
'3.0'
);
$logger = is_a ( $logger , 'WC_Logger' ) ? $logger : new WC_Logger ();
2016-08-08 12:59:23 +00:00
}
2018-06-07 07:46:06 +00:00
2016-12-15 19:52:24 +00:00
return $logger ;
2016-08-08 12:59:23 +00:00
}
2016-08-15 10:02:49 +00:00
2018-05-01 15:37:14 +00:00
/**
* Trigger logging cleanup using the logging class .
*
* @ since 3.4 . 0
*/
function wc_cleanup_logs () {
$logger = wc_get_logger ();
if ( is_callable ( array ( $logger , 'clear_expired_logs' ) ) ) {
$logger -> clear_expired_logs ();
}
}
add_action ( 'woocommerce_cleanup_logs' , 'wc_cleanup_logs' );
2016-11-20 21:10:04 +00:00
/**
2016-12-16 21:51:20 +00:00
* Prints human - readable information about a variable .
2016-11-20 21:10:04 +00:00
*
* Some server environments blacklist some debugging functions . This function provides a safe way to
2016-12-16 21:51:20 +00:00
* turn an expression into a printable , readable form without calling blacklisted functions .
2016-11-20 21:10:04 +00:00
*
2017-03-15 16:36:53 +00:00
* @ since 3.0
2016-12-16 21:51:20 +00:00
*
2016-11-20 21:10:04 +00:00
* @ param mixed $expression The expression to be printed .
2017-12-01 17:13:27 +00:00
* @ param bool $return Optional . Default false . Set to true to return the human - readable string .
2016-12-16 21:51:20 +00:00
* @ return string | bool False if expression could not be printed . True if the expression was printed .
* If $return is true , a string representation will be returned .
2016-11-20 21:10:04 +00:00
*/
2016-12-16 21:51:20 +00:00
function wc_print_r ( $expression , $return = false ) {
2016-11-20 21:10:04 +00:00
$alternatives = array (
2017-12-01 17:13:27 +00:00
array (
'func' => 'print_r' ,
'args' => array ( $expression , true ),
),
array (
'func' => 'var_export' ,
'args' => array ( $expression , true ),
),
array (
'func' => 'json_encode' ,
'args' => array ( $expression ),
),
array (
'func' => 'serialize' ,
'args' => array ( $expression ),
),
2016-11-20 21:10:04 +00:00
);
2016-12-16 21:51:20 +00:00
$alternatives = apply_filters ( 'woocommerce_print_r_alternatives' , $alternatives , $expression );
2016-11-20 21:10:04 +00:00
foreach ( $alternatives as $alternative ) {
if ( function_exists ( $alternative [ 'func' ] ) ) {
2016-12-16 21:51:20 +00:00
$res = call_user_func_array ( $alternative [ 'func' ], $alternative [ 'args' ] );
if ( $return ) {
return $res ;
}
2018-05-14 18:01:15 +00:00
echo $res ; // WPCS: XSS ok.
return true ;
2016-11-20 21:10:04 +00:00
}
}
return false ;
}
2016-11-12 18:42:32 +00:00
/**
2016-12-03 17:23:52 +00:00
* Registers the default log handler .
2016-11-12 18:42:32 +00:00
*
2017-03-15 16:36:53 +00:00
* @ since 3.0
2017-12-01 17:13:27 +00:00
* @ param array $handlers Handlers .
2016-11-12 18:42:32 +00:00
* @ return array
*/
2016-12-03 17:23:52 +00:00
function wc_register_default_log_handler ( $handlers ) {
2016-12-22 21:29:47 +00:00
if ( defined ( 'WC_LOG_HANDLER' ) && class_exists ( WC_LOG_HANDLER ) ) {
2018-03-07 21:37:32 +00:00
$handler_class = WC_LOG_HANDLER ;
2016-12-22 21:29:47 +00:00
$default_handler = new $handler_class ();
2016-12-03 17:23:52 +00:00
} else {
2016-12-22 21:29:47 +00:00
$default_handler = new WC_Log_Handler_File ();
2016-11-12 18:42:32 +00:00
}
2016-12-22 21:29:47 +00:00
array_push ( $handlers , $default_handler );
2016-11-12 18:42:32 +00:00
return $handlers ;
}
2016-12-22 21:29:47 +00:00
add_filter ( 'woocommerce_register_log_handlers' , 'wc_register_default_log_handler' );
2016-11-12 18:42:32 +00:00
2016-10-27 13:08:16 +00:00
/**
* Based on wp_list_pluck , this calls a method instead of returning a property .
*
2017-03-15 16:36:53 +00:00
* @ since 3.0 . 0
2017-12-01 17:13:27 +00:00
* @ param array $list List of objects or arrays .
* @ param int | string $callback_or_field Callback method from the object to place instead of the entire object .
* @ param int | string $index_key Optional . Field from the object to use as keys for the new array .
* Default null .
2016-10-27 13:08:16 +00:00
* @ return array Array of values .
*/
function wc_list_pluck ( $list , $callback_or_field , $index_key = null ) {
2017-12-01 17:13:27 +00:00
// Use wp_list_pluck if this isn't a callback.
2016-10-27 13:08:16 +00:00
$first_el = current ( $list );
if ( ! is_object ( $first_el ) || ! is_callable ( array ( $first_el , $callback_or_field ) ) ) {
return wp_list_pluck ( $list , $callback_or_field , $index_key );
}
if ( ! $index_key ) {
/*
* This is simple . Could at some point wrap array_column ()
* if we knew we had an array of arrays .
*/
foreach ( $list as $key => $value ) {
$list [ $key ] = $value -> { $callback_or_field }();
}
return $list ;
}
/*
* When index_key is not set for a particular item , push the value
* to the end of the stack . This is how array_column () behaves .
*/
$newlist = array ();
foreach ( $list as $value ) {
2017-08-11 12:52:28 +00:00
// Get index. @since 3.2.0 this supports a callback.
if ( is_callable ( array ( $value , $index_key ) ) ) {
$newlist [ $value -> { $index_key }() ] = $value -> { $callback_or_field }();
} elseif ( isset ( $value -> $index_key ) ) {
2016-10-27 13:08:16 +00:00
$newlist [ $value -> $index_key ] = $value -> { $callback_or_field }();
} else {
$newlist [] = $value -> { $callback_or_field }();
}
}
return $newlist ;
}
2017-02-07 16:16:45 +00:00
/**
2017-10-24 15:29:04 +00:00
* Get permalink settings for things like products and taxonomies .
*
* As of 3.3 . 0 , the permalink settings are stored to the option instead of
* being blank and inheritting from the locale . This speeds up page loading
* times by negating the need to switch locales on each page load .
*
* This is more inline with WP core behavior which does not localize slugs .
2017-02-07 16:16:45 +00:00
*
2017-03-15 16:36:53 +00:00
* @ since 3.0 . 0
2017-02-07 16:16:45 +00:00
* @ return array
*/
function wc_get_permalink_structure () {
2017-10-24 15:29:04 +00:00
$saved_permalinks = ( array ) get_option ( 'woocommerce_permalinks' , array () );
2018-03-07 21:37:32 +00:00
$permalinks = wp_parse_args (
2018-11-21 13:01:37 +00:00
array_filter ( $saved_permalinks ),
array (
2018-03-07 21:37:32 +00:00
'product_base' => _x ( 'product' , 'slug' , 'woocommerce' ),
'category_base' => _x ( 'product-category' , 'slug' , 'woocommerce' ),
'tag_base' => _x ( 'product-tag' , 'slug' , 'woocommerce' ),
'attribute_base' => '' ,
'use_verbose_page_rules' => false ,
)
);
2017-02-07 16:16:45 +00:00
2017-10-24 15:29:04 +00:00
if ( $saved_permalinks !== $permalinks ) {
update_option ( 'woocommerce_permalinks' , $permalinks );
2017-02-07 16:16:45 +00:00
}
2017-10-24 15:29:04 +00:00
$permalinks [ 'product_rewrite_slug' ] = untrailingslashit ( $permalinks [ 'product_base' ] );
$permalinks [ 'category_rewrite_slug' ] = untrailingslashit ( $permalinks [ 'category_base' ] );
$permalinks [ 'tag_rewrite_slug' ] = untrailingslashit ( $permalinks [ 'tag_base' ] );
$permalinks [ 'attribute_rewrite_slug' ] = untrailingslashit ( $permalinks [ 'attribute_base' ] );
2017-02-07 16:16:45 +00:00
return $permalinks ;
}
2017-06-05 13:18:39 +00:00
/**
* Switch WooCommerce to site language .
*
* @ since 3.1 . 0
*/
function wc_switch_to_site_locale () {
if ( function_exists ( 'switch_to_locale' ) ) {
2017-06-07 13:31:09 +00:00
switch_to_locale ( get_locale () );
2017-06-05 13:18:39 +00:00
// Filter on plugin_locale so load_plugin_textdomain loads the correct locale.
add_filter ( 'plugin_locale' , 'get_locale' );
// Init WC locale.
WC () -> load_plugin_textdomain ();
}
}
/**
* Switch WooCommerce language to original .
*
* @ since 3.1 . 0
*/
function wc_restore_locale () {
2017-06-06 11:54:49 +00:00
if ( function_exists ( 'restore_previous_locale' ) ) {
restore_previous_locale ();
2017-06-05 13:18:39 +00:00
2017-06-06 11:54:49 +00:00
// Remove filter.
remove_filter ( 'plugin_locale' , 'get_locale' );
2017-06-05 13:18:39 +00:00
2017-06-06 11:54:49 +00:00
// Init WC locale.
WC () -> load_plugin_textdomain ();
}
2017-06-05 13:18:39 +00:00
}
2017-06-06 11:55:50 +00:00
2017-04-26 12:18:56 +00:00
/**
* Convert plaintext phone number to clickable phone number .
*
2017-06-05 19:15:04 +00:00
* Remove formatting and allow " + " .
* Example and specs : https :// developer . mozilla . org / en / docs / Web / HTML / Element / a #Creating_a_phone_link
*
* @ since 3.1 . 0
2017-04-26 12:18:56 +00:00
*
2017-06-05 19:15:04 +00:00
* @ param string $phone Content to convert phone number .
2017-04-26 12:18:56 +00:00
* @ return string Content with converted phone number .
*/
2017-06-05 19:15:04 +00:00
function wc_make_phone_clickable ( $phone ) {
$number = trim ( preg_replace ( '/[^\d|\+]/' , '' , $phone ) );
2018-03-16 13:53:18 +00:00
return $number ? '<a href="tel:' . esc_attr ( $number ) . '">' . esc_html ( $phone ) . '</a>' : '' ;
2017-06-05 19:15:04 +00:00
}
2017-06-16 10:45:53 +00:00
/**
* Get an item of post data if set , otherwise return a default value .
*
* @ since 3.0 . 9
2017-12-01 17:13:27 +00:00
* @ param string $key Meta key .
* @ param string $default Default value .
* @ return mixed Value sanitized by wc_clean .
2017-06-16 10:45:53 +00:00
*/
function wc_get_post_data_by_key ( $key , $default = '' ) {
2017-12-13 17:56:01 +00:00
return wc_clean ( wp_unslash ( wc_get_var ( $_POST [ $key ], $default ) ) ); // @codingStandardsIgnoreLine
2017-08-07 10:02:19 +00:00
}
/**
* Get data if set , otherwise return a default value or null . Prevents notices when data is not set .
*
* @ since 3.2 . 0
2017-12-01 17:13:27 +00:00
* @ param mixed $var Variable .
* @ param string $default Default value .
* @ return mixed
2017-08-07 10:02:19 +00:00
*/
function wc_get_var ( & $var , $default = null ) {
return isset ( $var ) ? $var : $default ;
2017-06-16 10:45:53 +00:00
}
2017-08-03 18:42:19 +00:00
/**
* Read in WooCommerce headers when reading plugin headers .
*
* @ since 3.2 . 0
2017-12-01 17:13:27 +00:00
* @ param array $headers Headers .
* @ return array
2017-08-03 18:42:19 +00:00
*/
function wc_enable_wc_plugin_headers ( $headers ) {
if ( ! class_exists ( 'WC_Plugin_Updates' ) ) {
2018-03-07 21:37:32 +00:00
include_once dirname ( __FILE__ ) . '/admin/plugin-updates/class-wc-plugin-updates.php' ;
2017-08-03 18:42:19 +00:00
}
2019-03-08 12:44:33 +00:00
// WC requires at least - allows developers to define which version of WooCommerce the plugin requires to run.
$headers [] = WC_Plugin_Updates :: VERSION_REQUIRED_HEADER ;
// WC tested up to - allows developers to define which version of WooCommerce they have tested up to.
$headers [] = WC_Plugin_Updates :: VERSION_TESTED_HEADER ;
// Woo - This is used in WooCommerce extensions and is picked up by the helper.
$headers [] = 'Woo' ;
2017-08-03 18:42:19 +00:00
return $headers ;
}
2019-03-08 12:44:33 +00:00
add_filter ( 'extra_theme_headers' , 'wc_enable_wc_plugin_headers' );
2017-08-03 18:42:19 +00:00
add_filter ( 'extra_plugin_headers' , 'wc_enable_wc_plugin_headers' );
/**
* Prevent auto - updating the WooCommerce plugin on major releases if there are untested extensions active .
*
* @ since 3.2 . 0
2017-12-01 17:13:27 +00:00
* @ param bool $should_update If should update .
* @ param object $plugin Plugin data .
2017-08-03 18:42:19 +00:00
* @ return bool
*/
function wc_prevent_dangerous_auto_updates ( $should_update , $plugin ) {
2018-05-25 11:07:12 +00:00
if ( ! isset ( $plugin -> plugin , $plugin -> new_version ) ) {
return $should_update ;
}
2017-08-03 18:42:19 +00:00
if ( 'woocommerce/woocommerce.php' !== $plugin -> plugin ) {
return $should_update ;
}
if ( ! class_exists ( 'WC_Plugin_Updates' ) ) {
2017-12-01 17:13:27 +00:00
include_once dirname ( __FILE__ ) . '/admin/plugin-updates/class-wc-plugin-updates.php' ;
2017-08-03 18:42:19 +00:00
}
2017-12-01 17:13:27 +00:00
$new_version = wc_clean ( $plugin -> new_version );
$plugin_updates = new WC_Plugin_Updates ();
2017-08-03 18:42:19 +00:00
$untested_plugins = $plugin_updates -> get_untested_plugins ( $new_version , 'major' );
if ( ! empty ( $untested_plugins ) ) {
return false ;
}
return $should_update ;
}
add_filter ( 'auto_update_plugin' , 'wc_prevent_dangerous_auto_updates' , 99 , 2 );
2017-09-05 10:54:04 +00:00
/**
* Delete expired transients .
*
* Deletes all expired transients . The multi - table delete syntax is used .
* to delete the transient record from table a , and the corresponding .
* transient_timeout record from table b .
*
* Based on code inside core ' s upgrade_network () function .
*
* @ since 3.2 . 0
* @ return int Number of transients that were cleared .
*/
function wc_delete_expired_transients () {
global $wpdb ;
2018-03-07 21:37:32 +00:00
$sql = " DELETE a, b FROM $wpdb->options a, $wpdb->options b
2017-09-05 10:54:04 +00:00
WHERE a . option_name LIKE % s
AND a . option_name NOT LIKE % s
AND b . option_name = CONCAT ( '_transient_timeout_' , SUBSTRING ( a . option_name , 12 ) )
AND b . option_value < % d " ;
2017-12-01 17:13:27 +00:00
$rows = $wpdb -> query ( $wpdb -> prepare ( $sql , $wpdb -> esc_like ( '_transient_' ) . '%' , $wpdb -> esc_like ( '_transient_timeout_' ) . '%' , time () ) ); // WPCS: unprepared SQL ok.
2017-09-05 10:54:04 +00:00
2018-03-07 21:37:32 +00:00
$sql = " DELETE a, b FROM $wpdb->options a, $wpdb->options b
2017-09-05 10:54:04 +00:00
WHERE a . option_name LIKE % s
AND a . option_name NOT LIKE % s
AND b . option_name = CONCAT ( '_site_transient_timeout_' , SUBSTRING ( a . option_name , 17 ) )
AND b . option_value < % d " ;
2017-12-01 17:13:27 +00:00
$rows2 = $wpdb -> query ( $wpdb -> prepare ( $sql , $wpdb -> esc_like ( '_site_transient_' ) . '%' , $wpdb -> esc_like ( '_site_transient_timeout_' ) . '%' , time () ) ); // WPCS: unprepared SQL ok.
2017-09-05 10:54:04 +00:00
return absint ( $rows + $rows2 );
}
add_action ( 'woocommerce_installed' , 'wc_delete_expired_transients' );
2017-09-08 11:20:03 +00:00
/**
* Make a URL relative , if possible .
*
* @ since 3.2 . 0
* @ param string $url URL to make relative .
* @ return string
*/
function wc_get_relative_url ( $url ) {
return wc_is_external_resource ( $url ) ? $url : str_replace ( array ( 'http://' , 'https://' ), '//' , $url );
}
/**
* See if a resource is remote .
*
* @ since 3.2 . 0
* @ param string $url URL to check .
* @ return bool
*/
function wc_is_external_resource ( $url ) {
$wp_base = str_replace ( array ( 'http://' , 'https://' ), '//' , get_home_url ( null , '/' , 'http' ) );
2018-02-19 13:06:04 +00:00
return strstr ( $url , '://' ) && ! strstr ( $url , $wp_base );
2017-09-08 11:20:03 +00:00
}
2017-12-15 12:32:54 +00:00
/**
* See if theme / s is activate or not .
*
* @ since 3.3 . 0
* @ param string | array $theme Theme name or array of theme names to check .
* @ return boolean
*/
function wc_is_active_theme ( $theme ) {
return is_array ( $theme ) ? in_array ( get_template (), $theme , true ) : get_template () === $theme ;
}
2017-12-15 14:46:02 +00:00
/**
* Cleans up session data - cron callback .
*
* @ since 3.3 . 0
*/
function wc_cleanup_session_data () {
$session_class = apply_filters ( 'woocommerce_session_handler' , 'WC_Session_Handler' );
$session = new $session_class ();
if ( is_callable ( array ( $session , 'cleanup_sessions' ) ) ) {
$session -> cleanup_sessions ();
}
}
add_action ( 'woocommerce_cleanup_sessions' , 'wc_cleanup_session_data' );
2018-01-25 12:34:28 +00:00
/**
* Convert a decimal ( e . g . 3.5 ) to a fraction ( e . g . 7 / 2 ) .
* From : https :// www . designedbyaturtle . co . uk / 2015 / converting - a - decimal - to - a - fraction - in - php /
*
* @ param float $decimal the decimal number .
* @ return array | bool a 1 / 2 would be [ 1 , 2 ] array ( this can be imploded with '/' to form a string ) .
*/
function wc_decimal_to_fraction ( $decimal ) {
if ( 0 > $decimal || ! is_numeric ( $decimal ) ) {
// Negative digits need to be passed in as positive numbers and prefixed as negative once the response is imploded.
return false ;
}
if ( 0 === $decimal ) {
2018-01-25 15:14:02 +00:00
return array ( 0 , 1 );
2018-01-25 12:34:28 +00:00
}
$tolerance = 1.e-4 ;
$numerator = 1 ;
$h2 = 0 ;
$denominator = 0 ;
$k2 = 1 ;
$b = 1 / $decimal ;
do {
$b = 1 / $b ;
$a = floor ( $b );
$aux = $numerator ;
$numerator = $a * $numerator + $h2 ;
$h2 = $aux ;
$aux = $denominator ;
$denominator = $a * $denominator + $k2 ;
$k2 = $aux ;
$b = $b - $a ;
} while ( abs ( $decimal - $numerator / $denominator ) > $decimal * $tolerance );
return array ( $numerator , $denominator );
}
2018-03-07 13:14:59 +00:00
/**
* Round discount .
*
* @ param double $value Amount to round .
* @ param int $precision DP to round .
* @ return float
*/
function wc_round_discount ( $value , $precision ) {
if ( version_compare ( PHP_VERSION , '5.3.0' , '>=' ) ) {
2018-11-21 13:08:26 +00:00
return round ( $value , $precision , WC_DISCOUNT_ROUNDING_MODE ); // phpcs:ignore PHPCompatibility.FunctionUse.NewFunctionParameters.round_modeFound
2018-05-14 18:07:29 +00:00
}
if ( 2 === WC_DISCOUNT_ROUNDING_MODE ) {
2018-03-07 13:14:59 +00:00
return wc_legacy_round_half_down ( $value , $precision );
}
2018-05-14 18:07:29 +00:00
return round ( $value , $precision );
2018-03-07 13:14:59 +00:00
}
2018-04-18 13:54:57 +00:00
/**
* Return the html selected attribute if stringified $value is found in array of stringified $options
* or if stringified $value is the same as scalar stringified $options .
*
* @ param string | int $value Value to find within options .
* @ param string | int | array $options Options to go through when looking for value .
* @ return string
*/
function wc_selected ( $value , $options ) {
if ( is_array ( $options ) ) {
$options = array_map ( 'strval' , $options );
return selected ( in_array ( ( string ) $value , $options , true ), true , false );
}
return selected ( $value , $options , false );
}
2018-05-25 10:15:30 +00:00
/**
* Retrieves the MySQL server version . Based on $wpdb .
*
* @ since 3.4 . 1
* @ return array Vesion information .
*/
function wc_get_server_database_version () {
global $wpdb ;
if ( empty ( $wpdb -> is_mysql ) ) {
return array (
'string' => '' ,
'number' => '' ,
);
}
if ( $wpdb -> use_mysqli ) {
$server_info = mysqli_get_server_info ( $wpdb -> dbh ); // @codingStandardsIgnoreLine.
} else {
$server_info = mysql_get_server_info ( $wpdb -> dbh ); // @codingStandardsIgnoreLine.
}
return array (
'string' => $server_info ,
'number' => preg_replace ( '/([^\d.]+).*/' , '' , $server_info ),
);
}