Your IP : 3.15.192.89
<?php
/**
* Kkart Core Functions
*
* General core functions available on both the front-end and admin.
*
* @package Kkart\Functions
* @version 3.3.0
*/
use Automattic\Jetpack\Constants;
use Automattic\Kkart\Utilities\NumberUtil;
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
// Include core functions (available in both admin and frontend).
require KKART_ABSPATH . 'includes/kkart-conditional-functions.php';
require KKART_ABSPATH . 'includes/kkart-coupon-functions.php';
require KKART_ABSPATH . 'includes/kkart-user-functions.php';
require KKART_ABSPATH . 'includes/kkart-formatting-functions.php';
require KKART_ABSPATH . 'includes/kkart-order-functions.php';
require KKART_ABSPATH . 'includes/kkart-order-item-functions.php';
require KKART_ABSPATH . 'includes/kkart-page-functions.php';
require KKART_ABSPATH . 'includes/kkart-product-functions.php';
require KKART_ABSPATH . 'includes/kkart-stock-functions.php';
require KKART_ABSPATH . 'includes/kkart-account-functions.php';
require KKART_ABSPATH . 'includes/kkart-term-functions.php';
require KKART_ABSPATH . 'includes/kkart-attribute-functions.php';
require KKART_ABSPATH . 'includes/kkart-rest-functions.php';
require KKART_ABSPATH . 'includes/kkart-widget-functions.php';
require KKART_ABSPATH . 'includes/kkart-webhook-functions.php';
/**
* Filters on data used in admin and frontend.
*/
add_filter( 'kkart_coupon_code', 'html_entity_decode' );
add_filter( 'kkart_coupon_code', 'kkart_sanitize_coupon_code' );
add_filter( 'kkart_coupon_code', 'kkart_strtolower' );
add_filter( 'kkart_stock_amount', 'intval' ); // Stock amounts are integers by default.
add_filter( 'kkart_shipping_rate_label', 'sanitize_text_field' ); // Shipping rate label.
add_filter( 'kkart_attribute_label', 'wp_kses_post', 100 );
/**
* Short Description (excerpt).
*/
if ( function_exists( 'do_blocks' ) ) {
add_filter( 'kkart_short_description', 'do_blocks', 9 );
}
add_filter( 'kkart_short_description', 'wptexturize' );
add_filter( 'kkart_short_description', 'convert_smilies' );
add_filter( 'kkart_short_description', 'convert_chars' );
add_filter( 'kkart_short_description', 'wpautop' );
add_filter( 'kkart_short_description', 'shortcode_unautop' );
add_filter( 'kkart_short_description', 'prepend_attachment' );
add_filter( 'kkart_short_description', 'do_shortcode', 11 ); // After wpautop().
add_filter( 'kkart_short_description', 'kkart_format_product_short_description', 9999999 );
add_filter( 'kkart_short_description', 'kkart_do_oembeds' );
add_filter( 'kkart_short_description', array( $GLOBALS['wp_embed'], 'run_shortcode' ), 8 ); // Before wpautop().
/**
* Define a constant if it is not already defined.
*
* @since 3.0.0
* @param string $name Constant name.
* @param mixed $value Value.
*/
function kkart_maybe_define_constant( $name, $value ) {
if ( ! defined( $name ) ) {
define( $name, $value );
}
}
/**
* Create a new order programmatically.
*
* Returns a new order object on success which can then be used to add additional data.
*
* @param array $args Order arguments.
* @return KKART_Order|WP_Error
*/
function kkart_create_order( $args = array() ) {
$default_args = array(
'status' => null,
'customer_id' => null,
'customer_note' => null,
'parent' => null,
'created_via' => null,
'cart_hash' => null,
'order_id' => 0,
);
try {
$args = wp_parse_args( $args, $default_args );
$order = new KKART_Order( $args['order_id'] );
// Update props that were set (not null).
if ( ! is_null( $args['parent'] ) ) {
$order->set_parent_id( absint( $args['parent'] ) );
}
if ( ! is_null( $args['status'] ) ) {
$order->set_status( $args['status'] );
}
if ( ! is_null( $args['customer_note'] ) ) {
$order->set_customer_note( $args['customer_note'] );
}
if ( ! is_null( $args['customer_id'] ) ) {
$order->set_customer_id( is_numeric( $args['customer_id'] ) ? absint( $args['customer_id'] ) : 0 );
}
if ( ! is_null( $args['created_via'] ) ) {
$order->set_created_via( sanitize_text_field( $args['created_via'] ) );
}
if ( ! is_null( $args['cart_hash'] ) ) {
$order->set_cart_hash( sanitize_text_field( $args['cart_hash'] ) );
}
// Set these fields when creating a new order but not when updating an existing order.
if ( ! $args['order_id'] ) {
$order->set_currency( get_kkart_currency() );
$order->set_prices_include_tax( 'yes' === get_option( 'kkart_prices_include_tax' ) );
$order->set_customer_ip_address( KKART_Geolocation::get_ip_address() );
$order->set_customer_user_agent( kkart_get_user_agent() );
}
// Update other order props set automatically.
$order->save();
} catch ( Exception $e ) {
return new WP_Error( 'error', $e->getMessage() );
}
return $order;
}
/**
* Update an order. Uses kkart_create_order.
*
* @param array $args Order arguments.
* @return KKART_Order|WP_Error
*/
function kkart_update_order( $args ) {
if ( empty( $args['order_id'] ) ) {
return new WP_Error( __( 'Invalid order ID.', 'kkart' ) );
}
return kkart_create_order( $args );
}
/**
* Given a path, this will convert any of the subpaths into their corresponding tokens.
*
* @since 4.3.0
* @param string $path The absolute path to tokenize.
* @param array $path_tokens An array keyed with the token, containing paths that should be replaced.
* @return string The tokenized path.
*/
function kkart_tokenize_path( $path, $path_tokens ) {
// Order most to least specific so that the token can encompass as much of the path as possible.
uasort(
$path_tokens,
function ( $a, $b ) {
$a = strlen( $a );
$b = strlen( $b );
if ( $a > $b ) {
return -1;
}
if ( $b > $a ) {
return 1;
}
return 0;
}
);
foreach ( $path_tokens as $token => $token_path ) {
if ( 0 !== strpos( $path, $token_path ) ) {
continue;
}
$path = str_replace( $token_path, '{{' . $token . '}}', $path );
}
return $path;
}
/**
* Given a tokenized path, this will expand the tokens to their full path.
*
* @since 4.3.0
* @param string $path The absolute path to expand.
* @param array $path_tokens An array keyed with the token, containing paths that should be expanded.
* @return string The absolute path.
*/
function kkart_untokenize_path( $path, $path_tokens ) {
foreach ( $path_tokens as $token => $token_path ) {
$path = str_replace( '{{' . $token . '}}', $token_path, $path );
}
return $path;
}
/**
* Fetches an array containing all of the configurable path constants to be used in tokenization.
*
* @return array The key is the define and the path is the constant.
*/
function kkart_get_path_define_tokens() {
$defines = array(
'ABSPATH',
'WP_CONTENT_DIR',
'KKART_PLUGIN_DIR',
'WPMU_PLUGIN_DIR',
'PLUGINDIR',
'WP_THEME_DIR',
);
$path_tokens = array();
foreach ( $defines as $define ) {
if ( defined( $define ) ) {
$path_tokens[ $define ] = constant( $define );
}
}
return apply_filters( 'kkart_get_path_define_tokens', $path_tokens );
}
/**
* Get template part (for templates like the shop-loop).
*
* KKART_TEMPLATE_DEBUG_MODE will prevent overrides in themes from taking priority.
*
* @param mixed $slug Template slug.
* @param string $name Template name (default: '').
*/
function kkart_get_template_part( $slug, $name = '' ) {
$cache_key = sanitize_key( implode( '-', array( 'template-part', $slug, $name, Constants::get_constant( 'KKART_VERSION' ) ) ) );
$template = (string) wp_cache_get( $cache_key, 'kkart' );
if ( ! $template ) {
if ( $name ) {
$template = KKART_TEMPLATE_DEBUG_MODE ? '' : locate_template(
array(
"{$slug}-{$name}.php",
KKART()->template_path() . "{$slug}-{$name}.php",
)
);
if ( ! $template ) {
$fallback = KKART()->plugin_path() . "/templates/{$slug}-{$name}.php";
$template = file_exists( $fallback ) ? $fallback : '';
}
}
if ( ! $template ) {
// If template file doesn't exist, look in yourtheme/slug.php and yourtheme/kkart/slug.php.
$template = KKART_TEMPLATE_DEBUG_MODE ? '' : locate_template(
array(
"{$slug}.php",
KKART()->template_path() . "{$slug}.php",
)
);
}
// Don't cache the absolute path so that it can be shared between web servers with different paths.
$cache_path = kkart_tokenize_path( $template, kkart_get_path_define_tokens() );
kkart_set_template_cache( $cache_key, $cache_path );
} else {
// Make sure that the absolute path to the template is resolved.
$template = kkart_untokenize_path( $template, kkart_get_path_define_tokens() );
}
// Allow 3rd party plugins to filter template file from their plugin.
$template = apply_filters( 'kkart_get_template_part', $template, $slug, $name );
if ( $template ) {
load_template( $template, false );
}
}
/**
* Get other templates (e.g. product attributes) passing attributes and including the file.
*
* @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: '').
*/
function kkart_get_template( $template_name, $args = array(), $template_path = '', $default_path = '' ) {
$cache_key = sanitize_key( implode( '-', array( 'template', $template_name, $template_path, $default_path, Constants::get_constant( 'KKART_VERSION' ) ) ) );
$template = (string) wp_cache_get( $cache_key, 'kkart' );
if ( ! $template ) {
$template = kkart_locate_template( $template_name, $template_path, $default_path );
// Don't cache the absolute path so that it can be shared between web servers with different paths.
$cache_path = kkart_tokenize_path( $template, kkart_get_path_define_tokens() );
kkart_set_template_cache( $cache_key, $cache_path );
} else {
// Make sure that the absolute path to the template is resolved.
$template = kkart_untokenize_path( $template, kkart_get_path_define_tokens() );
}
// Allow 3rd party plugin filter template file from their plugin.
$filter_template = apply_filters( 'kkart_get_template', $template, $template_name, $args, $template_path, $default_path );
if ( $filter_template !== $template ) {
if ( ! file_exists( $filter_template ) ) {
/* translators: %s template */
kkart_doing_it_wrong( __FUNCTION__, sprintf( __( '%s does not exist.', 'kkart' ), '<code>' . $filter_template . '</code>' ), '2.1' );
return;
}
$template = $filter_template;
}
$action_args = array(
'template_name' => $template_name,
'template_path' => $template_path,
'located' => $template,
'args' => $args,
);
if ( ! empty( $args ) && is_array( $args ) ) {
if ( isset( $args['action_args'] ) ) {
kkart_doing_it_wrong(
__FUNCTION__,
__( 'action_args should not be overwritten when calling kkart_get_template.', 'kkart' ),
'3.6.0'
);
unset( $args['action_args'] );
}
extract( $args ); // @codingStandardsIgnoreLine
}
do_action( 'kkart_before_template_part', $action_args['template_name'], $action_args['template_path'], $action_args['located'], $action_args['args'] );
include $action_args['located'];
do_action( 'kkart_after_template_part', $action_args['template_name'], $action_args['template_path'], $action_args['located'], $action_args['args'] );
}
/**
* Like kkart_get_template, but returns the HTML instead of outputting.
*
* @see kkart_get_template
* @since 2.5.0
* @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: '').
*
* @return string
*/
function kkart_get_template_html( $template_name, $args = array(), $template_path = '', $default_path = '' ) {
ob_start();
kkart_get_template( $template_name, $args, $template_path, $default_path );
return ob_get_clean();
}
/**
* Locate a template and return the path for inclusion.
*
* This is the load order:
*
* yourtheme/$template_path/$template_name
* yourtheme/$template_name
* $default_path/$template_name
*
* @param string $template_name Template name.
* @param string $template_path Template path. (default: '').
* @param string $default_path Default path. (default: '').
* @return string
*/
function kkart_locate_template( $template_name, $template_path = '', $default_path = '' ) {
if ( ! $template_path ) {
$template_path = KKART()->template_path();
}
if ( ! $default_path ) {
$default_path = KKART()->plugin_path() . '/templates/';
}
// Look within passed path within the theme - this is priority.
if ( false !== strpos( $template_name, 'product_cat' ) || false !== strpos( $template_name, 'product_tag' ) ) {
$cs_template = str_replace( '_', '-', $template_name );
$template = locate_template(
array(
trailingslashit( $template_path ) . $cs_template,
$cs_template,
)
);
}
if ( empty( $template ) ) {
$template = locate_template(
array(
trailingslashit( $template_path ) . $template_name,
$template_name,
)
);
}
// Get default template/.
if ( ! $template || KKART_TEMPLATE_DEBUG_MODE ) {
if ( empty( $cs_template ) ) {
$template = $default_path . $template_name;
} else {
$template = $default_path . $cs_template;
}
}
// Return what we found.
return apply_filters( 'kkart_locate_template', $template, $template_name, $template_path );
}
/**
* Add a template to the template cache.
*
* @since 4.3.0
* @param string $cache_key Object cache key.
* @param string $template Located template.
*/
function kkart_set_template_cache( $cache_key, $template ) {
wp_cache_set( $cache_key, $template, 'kkart' );
$cached_templates = wp_cache_get( 'cached_templates', 'kkart' );
if ( is_array( $cached_templates ) ) {
$cached_templates[] = $cache_key;
} else {
$cached_templates = array( $cache_key );
}
wp_cache_set( 'cached_templates', $cached_templates, 'kkart' );
}
/**
* Clear the template cache.
*
* @since 4.3.0
*/
function kkart_clear_template_cache() {
$cached_templates = wp_cache_get( 'cached_templates', 'kkart' );
if ( is_array( $cached_templates ) ) {
foreach ( $cached_templates as $cache_key ) {
wp_cache_delete( $cache_key, 'kkart' );
}
wp_cache_delete( 'cached_templates', 'kkart' );
}
}
/**
* Get Base Currency Code.
*
* @return string
*/
function get_kkart_currency() {
return apply_filters( 'kkart_currency', get_option( 'kkart_currency' ) );
}
/**
* Get full list of currency codes.
*
* Currency symbols and names should follow the Unicode CLDR recommendation (http://cldr.unicode.org/translation/currency-names)
*
* @return array
*/
function get_kkart_currencies() {
static $currencies;
if ( ! isset( $currencies ) ) {
$currencies = array_unique(
apply_filters(
'kkart_currencies',
array(
'AED' => __( 'United Arab Emirates dirham', 'kkart' ),
'AFN' => __( 'Afghan afghani', 'kkart' ),
'ALL' => __( 'Albanian lek', 'kkart' ),
'AMD' => __( 'Armenian dram', 'kkart' ),
'ANG' => __( 'Netherlands Antillean guilder', 'kkart' ),
'AOA' => __( 'Angolan kwanza', 'kkart' ),
'ARS' => __( 'Argentine peso', 'kkart' ),
'AUD' => __( 'Australian dollar', 'kkart' ),
'AWG' => __( 'Aruban florin', 'kkart' ),
'AZN' => __( 'Azerbaijani manat', 'kkart' ),
'BAM' => __( 'Bosnia and Herzegovina convertible mark', 'kkart' ),
'BBD' => __( 'Barbadian dollar', 'kkart' ),
'BDT' => __( 'Bangladeshi taka', 'kkart' ),
'BGN' => __( 'Bulgarian lev', 'kkart' ),
'BHD' => __( 'Bahraini dinar', 'kkart' ),
'BIF' => __( 'Burundian franc', 'kkart' ),
'BMD' => __( 'Bermudian dollar', 'kkart' ),
'BND' => __( 'Brunei dollar', 'kkart' ),
'BOB' => __( 'Bolivian boliviano', 'kkart' ),
'BRL' => __( 'Brazilian real', 'kkart' ),
'BSD' => __( 'Bahamian dollar', 'kkart' ),
'BTC' => __( 'Bitcoin', 'kkart' ),
'BTN' => __( 'Bhutanese ngultrum', 'kkart' ),
'BWP' => __( 'Botswana pula', 'kkart' ),
'BYR' => __( 'Belarusian ruble (old)', 'kkart' ),
'BYN' => __( 'Belarusian ruble', 'kkart' ),
'BZD' => __( 'Belize dollar', 'kkart' ),
'CAD' => __( 'Canadian dollar', 'kkart' ),
'CDF' => __( 'Congolese franc', 'kkart' ),
'CHF' => __( 'Swiss franc', 'kkart' ),
'CLP' => __( 'Chilean peso', 'kkart' ),
'CNY' => __( 'Chinese yuan', 'kkart' ),
'COP' => __( 'Colombian peso', 'kkart' ),
'CRC' => __( 'Costa Rican colón', 'kkart' ),
'CUC' => __( 'Cuban convertible peso', 'kkart' ),
'CUP' => __( 'Cuban peso', 'kkart' ),
'CVE' => __( 'Cape Verdean escudo', 'kkart' ),
'CZK' => __( 'Czech koruna', 'kkart' ),
'DJF' => __( 'Djiboutian franc', 'kkart' ),
'DKK' => __( 'Danish krone', 'kkart' ),
'DOP' => __( 'Dominican peso', 'kkart' ),
'DZD' => __( 'Algerian dinar', 'kkart' ),
'EGP' => __( 'Egyptian pound', 'kkart' ),
'ERN' => __( 'Eritrean nakfa', 'kkart' ),
'ETB' => __( 'Ethiopian birr', 'kkart' ),
'EUR' => __( 'Euro', 'kkart' ),
'FJD' => __( 'Fijian dollar', 'kkart' ),
'FKP' => __( 'Falkland Islands pound', 'kkart' ),
'GBP' => __( 'Pound sterling', 'kkart' ),
'GEL' => __( 'Georgian lari', 'kkart' ),
'GGP' => __( 'Guernsey pound', 'kkart' ),
'GHS' => __( 'Ghana cedi', 'kkart' ),
'GIP' => __( 'Gibraltar pound', 'kkart' ),
'GMD' => __( 'Gambian dalasi', 'kkart' ),
'GNF' => __( 'Guinean franc', 'kkart' ),
'GTQ' => __( 'Guatemalan quetzal', 'kkart' ),
'GYD' => __( 'Guyanese dollar', 'kkart' ),
'HKD' => __( 'Hong Kong dollar', 'kkart' ),
'HNL' => __( 'Honduran lempira', 'kkart' ),
'HRK' => __( 'Croatian kuna', 'kkart' ),
'HTG' => __( 'Haitian gourde', 'kkart' ),
'HUF' => __( 'Hungarian forint', 'kkart' ),
'IDR' => __( 'Indonesian rupiah', 'kkart' ),
'ILS' => __( 'Israeli new shekel', 'kkart' ),
'IMP' => __( 'Manx pound', 'kkart' ),
'INR' => __( 'Indian rupee', 'kkart' ),
'IQD' => __( 'Iraqi dinar', 'kkart' ),
'IRR' => __( 'Iranian rial', 'kkart' ),
'IRT' => __( 'Iranian toman', 'kkart' ),
'ISK' => __( 'Icelandic króna', 'kkart' ),
'JEP' => __( 'Jersey pound', 'kkart' ),
'JMD' => __( 'Jamaican dollar', 'kkart' ),
'JOD' => __( 'Jordanian dinar', 'kkart' ),
'JPY' => __( 'Japanese yen', 'kkart' ),
'KES' => __( 'Kenyan shilling', 'kkart' ),
'KGS' => __( 'Kyrgyzstani som', 'kkart' ),
'KHR' => __( 'Cambodian riel', 'kkart' ),
'KMF' => __( 'Comorian franc', 'kkart' ),
'KPW' => __( 'North Korean won', 'kkart' ),
'KRW' => __( 'South Korean won', 'kkart' ),
'KWD' => __( 'Kuwaiti dinar', 'kkart' ),
'KYD' => __( 'Cayman Islands dollar', 'kkart' ),
'KZT' => __( 'Kazakhstani tenge', 'kkart' ),
'LAK' => __( 'Lao kip', 'kkart' ),
'LBP' => __( 'Lebanese pound', 'kkart' ),
'LKR' => __( 'Sri Lankan rupee', 'kkart' ),
'LRD' => __( 'Liberian dollar', 'kkart' ),
'LSL' => __( 'Lesotho loti', 'kkart' ),
'LYD' => __( 'Libyan dinar', 'kkart' ),
'MAD' => __( 'Moroccan dirham', 'kkart' ),
'MDL' => __( 'Moldovan leu', 'kkart' ),
'MGA' => __( 'Malagasy ariary', 'kkart' ),
'MKD' => __( 'Macedonian denar', 'kkart' ),
'MMK' => __( 'Burmese kyat', 'kkart' ),
'MNT' => __( 'Mongolian tögrög', 'kkart' ),
'MOP' => __( 'Macanese pataca', 'kkart' ),
'MRU' => __( 'Mauritanian ouguiya', 'kkart' ),
'MUR' => __( 'Mauritian rupee', 'kkart' ),
'MVR' => __( 'Maldivian rufiyaa', 'kkart' ),
'MWK' => __( 'Malawian kwacha', 'kkart' ),
'MXN' => __( 'Mexican peso', 'kkart' ),
'MYR' => __( 'Malaysian ringgit', 'kkart' ),
'MZN' => __( 'Mozambican metical', 'kkart' ),
'NAD' => __( 'Namibian dollar', 'kkart' ),
'NGN' => __( 'Nigerian naira', 'kkart' ),
'NIO' => __( 'Nicaraguan córdoba', 'kkart' ),
'NOK' => __( 'Norwegian krone', 'kkart' ),
'NPR' => __( 'Nepalese rupee', 'kkart' ),
'NZD' => __( 'New Zealand dollar', 'kkart' ),
'OMR' => __( 'Omani rial', 'kkart' ),
'PAB' => __( 'Panamanian balboa', 'kkart' ),
'PEN' => __( 'Sol', 'kkart' ),
'PGK' => __( 'Papua New Guinean kina', 'kkart' ),
'PHP' => __( 'Philippine peso', 'kkart' ),
'PKR' => __( 'Pakistani rupee', 'kkart' ),
'PLN' => __( 'Polish złoty', 'kkart' ),
'PRB' => __( 'Transnistrian ruble', 'kkart' ),
'PYG' => __( 'Paraguayan guaraní', 'kkart' ),
'QAR' => __( 'Qatari riyal', 'kkart' ),
'RON' => __( 'Romanian leu', 'kkart' ),
'RSD' => __( 'Serbian dinar', 'kkart' ),
'RUB' => __( 'Russian ruble', 'kkart' ),
'RWF' => __( 'Rwandan franc', 'kkart' ),
'SAR' => __( 'Saudi riyal', 'kkart' ),
'SBD' => __( 'Solomon Islands dollar', 'kkart' ),
'SCR' => __( 'Seychellois rupee', 'kkart' ),
'SDG' => __( 'Sudanese pound', 'kkart' ),
'SEK' => __( 'Swedish krona', 'kkart' ),
'SGD' => __( 'Singapore dollar', 'kkart' ),
'SHP' => __( 'Saint Helena pound', 'kkart' ),
'SLL' => __( 'Sierra Leonean leone', 'kkart' ),
'SOS' => __( 'Somali shilling', 'kkart' ),
'SRD' => __( 'Surinamese dollar', 'kkart' ),
'SSP' => __( 'South Sudanese pound', 'kkart' ),
'STN' => __( 'São Tomé and Príncipe dobra', 'kkart' ),
'SYP' => __( 'Syrian pound', 'kkart' ),
'SZL' => __( 'Swazi lilangeni', 'kkart' ),
'THB' => __( 'Thai baht', 'kkart' ),
'TJS' => __( 'Tajikistani somoni', 'kkart' ),
'TMT' => __( 'Turkmenistan manat', 'kkart' ),
'TND' => __( 'Tunisian dinar', 'kkart' ),
'TOP' => __( 'Tongan paʻanga', 'kkart' ),
'TRY' => __( 'Turkish lira', 'kkart' ),
'TTD' => __( 'Trinidad and Tobago dollar', 'kkart' ),
'TWD' => __( 'New Taiwan dollar', 'kkart' ),
'TZS' => __( 'Tanzanian shilling', 'kkart' ),
'UAH' => __( 'Ukrainian hryvnia', 'kkart' ),
'UGX' => __( 'Ugandan shilling', 'kkart' ),
'USD' => __( 'United States (US) dollar', 'kkart' ),
'UYU' => __( 'Uruguayan peso', 'kkart' ),
'UZS' => __( 'Uzbekistani som', 'kkart' ),
'VEF' => __( 'Venezuelan bolívar', 'kkart' ),
'VES' => __( 'Bolívar soberano', 'kkart' ),
'VND' => __( 'Vietnamese đồng', 'kkart' ),
'VUV' => __( 'Vanuatu vatu', 'kkart' ),
'WST' => __( 'Samoan tālā', 'kkart' ),
'XAF' => __( 'Central African CFA franc', 'kkart' ),
'XCD' => __( 'East Caribbean dollar', 'kkart' ),
'XOF' => __( 'West African CFA franc', 'kkart' ),
'XPF' => __( 'CFP franc', 'kkart' ),
'YER' => __( 'Yemeni rial', 'kkart' ),
'ZAR' => __( 'South African rand', 'kkart' ),
'ZMW' => __( 'Zambian kwacha', 'kkart' ),
)
)
);
}
return $currencies;
}
/**
* Get all available Currency symbols.
*
* Currency symbols and names should follow the Unicode CLDR recommendation (http://cldr.unicode.org/translation/currency-names)
*
* @since 4.1.0
* @return array
*/
function get_kkart_currency_symbols() {
$symbols = apply_filters(
'kkart_currency_symbols',
array(
'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' => '£',
'GEL' => '₾',
'GGP' => '£',
'GHS' => '₵',
'GIP' => '£',
'GMD' => 'D',
'GNF' => 'Fr',
'GTQ' => 'Q',
'GYD' => '$',
'HKD' => '$',
'HNL' => 'L',
'HRK' => 'kn',
'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' => '₸',
'LAK' => '₭',
'LBP' => 'ل.ل',
'LKR' => 'රු',
'LRD' => '$',
'LSL' => 'L',
'LYD' => 'ل.د',
'MAD' => 'د.م.',
'MDL' => 'MDL',
'MGA' => 'Ar',
'MKD' => 'ден',
'MMK' => 'Ks',
'MNT' => '₮',
'MOP' => 'P',
'MRU' => 'UM',
'MUR' => '₨',
'MVR' => '.ރ',
'MWK' => 'MK',
'MXN' => '$',
'MYR' => 'RM',
'MZN' => 'MT',
'NAD' => 'N$',
'NGN' => '₦',
'NIO' => 'C$',
'NOK' => 'kr',
'NPR' => '₨',
'NZD' => '$',
'OMR' => 'ر.ع.',
'PAB' => 'B/.',
'PEN' => 'S/',
'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' => '£',
'STN' => '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',
'VES' => 'Bs.S',
'VND' => '₫',
'VUV' => 'Vt',
'WST' => 'T',
'XAF' => 'CFA',
'XCD' => '$',
'XOF' => 'CFA',
'XPF' => 'Fr',
'YER' => '﷼',
'ZAR' => 'R',
'ZMW' => 'ZK',
)
);
return $symbols;
}
/**
* Get Currency symbol.
*
* Currency symbols and names should follow the Unicode CLDR recommendation (http://cldr.unicode.org/translation/currency-names)
*
* @param string $currency Currency. (default: '').
* @return string
*/
function get_kkart_currency_symbol( $currency = '' ) {
if ( ! $currency ) {
$currency = get_kkart_currency();
}
$symbols = get_kkart_currency_symbols();
$currency_symbol = isset( $symbols[ $currency ] ) ? $symbols[ $currency ] : '';
return apply_filters( 'kkart_currency_symbol', $currency_symbol, $currency );
}
/**
* Send HTML emails from Kkart.
*
* @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: "").
* @return bool
*/
function kkart_mail( $to, $subject, $message, $headers = "Content-Type: text/html\r\n", $attachments = '' ) {
$mailer = KKART()->mailer();
return $mailer->send( $to, $subject, $message, $headers, $attachments );
}
/**
* 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 kkart_get_theme_support( $prop = '', $default = null ) {
$theme_support = get_theme_support( 'kkart' );
$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;
}
/**
* Get an image size by name or defined dimensions.
*
* The returned variable is filtered by kkart_get_image_size_{image_size} filter to
* allow 3rd party customisation.
*
* 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.
* @return array Array of dimensions including width, height, and cropping mode. Cropping mode is 0 for no crop, and 1 for hard crop.
*/
function kkart_get_image_size( $image_size ) {
$cache_key = 'size-' . ( is_array( $image_size ) ? implode( '-', $image_size ) : $image_size );
$size = wp_cache_get( $cache_key, 'kkart' );
if ( $size ) {
return $size;
}
$size = array(
'width' => 600,
'height' => 600,
'crop' => 1,
);
if ( is_array( $image_size ) ) {
$size = array(
'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,
);
$image_size = $size['width'] . '_' . $size['height'];
} else {
$image_size = str_replace( 'kkart_', '', $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';
}
if ( 'single' === $image_size ) {
$size['width'] = absint( kkart_get_theme_support( 'single_image_width', get_option( 'kkart_single_image_width', 600 ) ) );
$size['height'] = '';
$size['crop'] = 0;
} elseif ( 'gallery_thumbnail' === $image_size ) {
$size['width'] = absint( kkart_get_theme_support( 'gallery_thumbnail_image_width', 100 ) );
$size['height'] = $size['width'];
$size['crop'] = 1;
} elseif ( 'thumbnail' === $image_size ) {
$size['width'] = absint( kkart_get_theme_support( 'thumbnail_image_width', get_option( 'kkart_thumbnail_image_width', 300 ) ) );
$cropping = get_option( 'kkart_thumbnail_cropping', '1:1' );
if ( 'uncropped' === $cropping ) {
$size['height'] = '';
$size['crop'] = 0;
} elseif ( 'custom' === $cropping ) {
$width = max( 1, get_option( 'kkart_thumbnail_cropping_custom_width', '4' ) );
$height = max( 1, get_option( 'kkart_thumbnail_cropping_custom_height', '3' ) );
$size['height'] = absint( NumberUtil::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( NumberUtil::round( ( $size['width'] / $width ) * $height ) );
$size['crop'] = 1;
}
}
}
$size = apply_filters( 'kkart_get_image_size_' . $image_size, $size );
wp_cache_set( $cache_key, $size, 'kkart' );
return $size;
}
/**
* Queue some JavaScript code to be output in the footer.
*
* @param string $code Code.
*/
function kkart_enqueue_js( $code ) {
global $kkart_queued_js;
if ( empty( $kkart_queued_js ) ) {
$kkart_queued_js = '';
}
$kkart_queued_js .= "\n" . $code . "\n";
}
/**
* Output any queued javascript code in the footer.
*/
function kkart_print_js() {
global $kkart_queued_js;
if ( ! empty( $kkart_queued_js ) ) {
// Sanitize.
$kkart_queued_js = wp_check_invalid_utf8( $kkart_queued_js );
$kkart_queued_js = preg_replace( '/&#(x)?0*(?(1)27|39);?/i', "'", $kkart_queued_js );
$kkart_queued_js = str_replace( "\r", '', $kkart_queued_js );
$js = "<!-- Kkart JavaScript -->\n<script type=\"text/javascript\">\njQuery(function($) { $kkart_queued_js });\n</script>\n";
/**
* Queued jsfilter.
*
* @since 2.6.0
* @param string $js JavaScript code.
*/
echo apply_filters( 'kkart_queued_js', $js ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
unset( $kkart_queued_js );
}
}
/**
* Set a cookie - wrapper for setcookie using WP constants.
*
* @param string $name Name of the cookie being set.
* @param string $value Value of the cookie.
* @param integer $expire Expiry of the cookie.
* @param bool $secure Whether the cookie should be served only over https.
* @param bool $httponly Whether the cookie is only accessible over HTTP, not scripting languages like JavaScript. @since 3.6.0.
*/
function kkart_setcookie( $name, $value, $expire = 0, $secure = false, $httponly = false ) {
if ( ! headers_sent() ) {
setcookie( $name, $value, $expire, COOKIEPATH ? COOKIEPATH : '/', COOKIE_DOMAIN, $secure, apply_filters( 'kkart_cookie_httponly', $httponly, $name, $value, $expire, $secure ) );
} elseif ( Constants::is_true( 'WP_DEBUG' ) ) {
headers_sent( $file, $line );
trigger_error( "{$name} cookie cannot be set - headers already sent by {$file} on line {$line}", E_USER_NOTICE ); // @codingStandardsIgnoreLine
}
}
/**
* Get the URL to the Kkart REST API.
*
* @since 2.1
* @param string $path an endpoint to include in the URL.
* @return string the URL.
*/
function get_kkart_api_url( $path ) {
if ( Constants::is_defined( 'KKART_API_REQUEST_VERSION' ) ) {
$version = Constants::get_constant( 'KKART_API_REQUEST_VERSION' );
} else {
$version = substr( KKART_API::VERSION, 0, 1 );
}
$url = get_home_url( null, "kkart-api/v{$version}/", is_ssl() ? 'https' : 'http' );
if ( ! empty( $path ) && is_string( $path ) ) {
$url .= ltrim( $path, '/' );
}
return $url;
}
/**
* Get a log file path.
*
* @since 2.2
*
* @param string $handle name.
* @return string the log file path.
*/
function kkart_get_log_file_path( $handle ) {
return KKART_Log_Handler_File::get_log_file_path( $handle );
}
/**
* Get a log file name.
*
* @since 3.3
*
* @param string $handle Name.
* @return string The log file name.
*/
function kkart_get_log_file_name( $handle ) {
return KKART_Log_Handler_File::get_log_file_name( $handle );
}
/**
* Recursively get page children.
*
* @param int $page_id Page ID.
* @return int[]
*/
function kkart_get_page_children( $page_id ) {
$page_ids = get_posts(
array(
'post_parent' => $page_id,
'post_type' => 'page',
'numberposts' => -1, // @codingStandardsIgnoreLine
'post_status' => 'any',
'fields' => 'ids',
)
);
if ( ! empty( $page_ids ) ) {
foreach ( $page_ids as $page_id ) {
$page_ids = array_merge( $page_ids, kkart_get_page_children( $page_id ) );
}
}
return $page_ids;
}
/**
* Flushes rewrite rules when the shop page (or it's children) gets saved.
*/
function flush_rewrite_rules_on_shop_page_save() {
$screen = get_current_screen();
$screen_id = $screen ? $screen->id : '';
// Check if this is the edit page.
if ( 'page' !== $screen_id ) {
return;
}
// Check if page is edited.
if ( empty( $_GET['post'] ) || empty( $_GET['action'] ) || ( isset( $_GET['action'] ) && 'edit' !== $_GET['action'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
return;
}
$post_id = intval( $_GET['post'] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
$shop_page_id = kkart_get_page_id( 'shop' );
if ( $shop_page_id === $post_id || in_array( $post_id, kkart_get_page_children( $shop_page_id ), true ) ) {
do_action( 'kkart_flush_rewrite_rules' );
}
}
add_action( 'admin_footer', 'flush_rewrite_rules_on_shop_page_save' );
/**
* Various rewrite rule fixes.
*
* @since 2.2
* @param array $rules Rules.
* @return array
*/
function kkart_fix_rewrite_rules( $rules ) {
global $wp_rewrite;
$permalinks = kkart_get_permalink_structure();
// Fix the rewrite rules when the product permalink have %product_cat% flag.
if ( preg_match( '`/(.+)(/%product_cat%)`', $permalinks['product_rewrite_slug'], $matches ) ) {
foreach ( $rules as $rule => $rewrite ) {
if ( preg_match( '`^' . preg_quote( $matches[1], '`' ) . '/\(`', $rule ) && preg_match( '/^(index\.php\?product_cat)(?!(.*product))/', $rewrite ) ) {
unset( $rules[ $rule ] );
}
}
}
// If the shop page is used as the base, we need to handle shop page subpages to avoid 404s.
if ( ! $permalinks['use_verbose_page_rules'] ) {
return $rules;
}
$shop_page_id = kkart_get_page_id( 'shop' );
if ( $shop_page_id ) {
$page_rewrite_rules = array();
$subpages = kkart_get_page_children( $shop_page_id );
// Subpage rules.
foreach ( $subpages as $subpage ) {
$uri = get_page_uri( $subpage );
$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 );
}
// Merge with rules.
$rules = array_merge( $page_rewrite_rules, $rules );
}
return $rules;
}
add_filter( 'rewrite_rules_array', 'kkart_fix_rewrite_rules' );
/**
* Prevent product attachment links from breaking when using complex rewrite structures.
*
* @param string $link Link.
* @param int $post_id Post ID.
* @return string
*/
function kkart_fix_product_attachment_link( $link, $post_id ) {
$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 );
}
return $link;
}
add_filter( 'attachment_link', 'kkart_fix_product_attachment_link', 10, 2 );
/**
* Protect downloads from ms-files.php in multisite.
*
* @param string $rewrite rewrite rules.
* @return string
*/
function kkart_ms_protect_download_rewite_rules( $rewrite ) {
if ( ! is_multisite() || 'redirect' === get_option( 'kkart_file_download_method' ) ) {
return $rewrite;
}
$rule = "\n# Kkart Rules - Protect Files from ms-files.php\n\n";
$rule .= "<IfModule mod_rewrite.c>\n";
$rule .= "RewriteEngine On\n";
$rule .= "RewriteCond %{QUERY_STRING} file=kkart_uploads/ [NC]\n";
$rule .= "RewriteRule /ms-files.php$ - [F]\n";
$rule .= "</IfModule>\n\n";
return $rule . $rewrite;
}
add_filter( 'mod_rewrite_rules', 'kkart_ms_protect_download_rewite_rules' );
/**
* Formats a string in the format COUNTRY:STATE into an array.
*
* @since 2.3.0
* @param string $country_string Country string.
* @return array
*/
function kkart_format_country_state_string( $country_string ) {
if ( strstr( $country_string, ':' ) ) {
list( $country, $state ) = explode( ':', $country_string );
} else {
$country = $country_string;
$state = '';
}
return array(
'country' => $country,
'state' => $state,
);
}
/**
* Get the store's base location.
*
* @since 2.3.0
* @return array
*/
function kkart_get_base_location() {
$default = apply_filters( 'kkart_get_base_location', get_option( 'kkart_default_country' ) );
return kkart_format_country_state_string( $default );
}
/**
* Get the customer's default location.
*
* Filtered, and set to base location or left blank. If cache-busting,
* this should only be used when 'location' is set in the querystring.
*
* @since 2.3.0
* @return array
*/
function kkart_get_customer_default_location() {
$set_default_location_to = get_option( 'kkart_default_customer_address', 'base' );
$default_location = '' === $set_default_location_to ? '' : get_option( 'kkart_default_country', '' );
$location = kkart_format_country_state_string( apply_filters( 'kkart_customer_default_location', $default_location ) );
// Geolocation takes priority if used and if geolocation is possible.
if ( 'geolocation' === $set_default_location_to || 'geolocation_ajax' === $set_default_location_to ) {
$ua = kkart_get_user_agent();
// Exclude common bots from geolocation by user agent.
if ( ! stristr( $ua, 'bot' ) && ! stristr( $ua, 'spider' ) && ! stristr( $ua, 'crawl' ) ) {
$geolocation = KKART_Geolocation::geolocate_ip( '', true, false );
if ( ! empty( $geolocation['country'] ) ) {
$location = $geolocation;
}
}
}
// Once we have a location, ensure it's valid, otherwise fallback to a valid location.
$allowed_country_codes = KKART()->countries->get_allowed_countries();
if ( ! empty( $location['country'] ) && ! array_key_exists( $location['country'], $allowed_country_codes ) ) {
$location['country'] = current( array_keys( $allowed_country_codes ) );
$location['state'] = '';
}
return apply_filters( 'kkart_customer_default_location_array', $location );
}
/**
* Get user agent string.
*
* @since 3.0.0
* @return string
*/
function kkart_get_user_agent() {
return isset( $_SERVER['HTTP_USER_AGENT'] ) ? kkart_clean( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ) ) : ''; // @codingStandardsIgnoreLine
}
/**
* Generate a rand hash.
*
* @since 2.4.0
* @return string
*/
function kkart_rand_hash() {
if ( ! function_exists( 'openssl_random_pseudo_bytes' ) ) {
return sha1( wp_rand() );
}
return bin2hex( openssl_random_pseudo_bytes( 20 ) ); // @codingStandardsIgnoreLine
}
/**
* KKART API - Hash.
*
* @since 2.4.0
* @param string $data Message to be hashed.
* @return string
*/
function kkart_api_hash( $data ) {
return hash_hmac( 'sha256', $data, 'kkart-api' );
}
/**
* Find all possible combinations of values from the input array and return in a logical order.
*
* @since 2.5.0
* @param array $input Input.
* @return array
*/
function kkart_array_cartesian( $input ) {
$input = array_filter( $input );
$results = array();
$indexes = array();
$index = 0;
// Generate indexes from keys and values so we have a logical sort order.
foreach ( $input as $key => $values ) {
foreach ( $values as $value ) {
$indexes[ $key ][ $value ] = $index++;
}
}
// Loop over the 2D array of indexes and generate all combinations.
foreach ( $indexes as $key => $values ) {
// When result is empty, fill with the values of the first looped array.
if ( empty( $results ) ) {
foreach ( $values as $value ) {
$results[] = array( $key => $value );
}
} else {
// Second and subsequent input sub-array merging.
foreach ( $results as $result_key => $result ) {
foreach ( $values as $value ) {
// If the key is not set, we can set it.
if ( ! isset( $results[ $result_key ][ $key ] ) ) {
$results[ $result_key ][ $key ] = $value;
} else {
// If the key is set, we can add a new combination to the results array.
$new_combination = $results[ $result_key ];
$new_combination[ $key ] = $value;
$results[] = $new_combination;
}
}
}
}
}
// Sort the indexes.
arsort( $results );
// Convert indexes back to values.
foreach ( $results as $result_key => $result ) {
$converted_values = array();
// Sort the values.
arsort( $results[ $result_key ] );
// Convert the values.
foreach ( $results[ $result_key ] as $key => $value ) {
$converted_values[ $key ] = array_search( $value, $indexes[ $key ], true );
}
$results[ $result_key ] = $converted_values;
}
return $results;
}
/**
* Run a MySQL transaction query, if supported.
*
* @since 2.5.0
* @param string $type Types: start (default), commit, rollback.
* @param bool $force use of transactions.
*/
function kkart_transaction_query( $type = 'start', $force = false ) {
global $wpdb;
$wpdb->hide_errors();
kkart_maybe_define_constant( 'KKART_USE_TRANSACTIONS', true );
if ( Constants::is_true( 'KKART_USE_TRANSACTIONS' ) || $force ) {
switch ( $type ) {
case 'commit':
$wpdb->query( 'COMMIT' );
break;
case 'rollback':
$wpdb->query( 'ROLLBACK' );
break;
default:
$wpdb->query( 'START TRANSACTION' );
break;
}
}
}
/**
* Gets the url to the cart page.
*
* @since 2.5.0
*
* @return string Url to cart page
*/
function kkart_get_cart_url() {
return apply_filters( 'kkart_get_cart_url', kkart_get_page_permalink( 'cart' ) );
}
/**
* Gets the url to the checkout page.
*
* @since 2.5.0
*
* @return string Url to checkout page
*/
function kkart_get_checkout_url() {
$checkout_url = kkart_get_page_permalink( 'checkout' );
if ( $checkout_url ) {
// Force SSL if needed.
if ( is_ssl() || 'yes' === get_option( 'kkart_force_ssl_checkout' ) ) {
$checkout_url = str_replace( 'http:', 'https:', $checkout_url );
}
}
return apply_filters( 'kkart_get_checkout_url', $checkout_url );
}
/**
* Register a shipping method.
*
* @since 1.5.7
* @param string|object $shipping_method class name (string) or a class object.
*/
function kkart_register_shipping_method( $shipping_method ) {
KKART()->shipping()->register_shipping_method( $shipping_method );
}
if ( ! function_exists( 'kkart_get_shipping_zone' ) ) {
/**
* Get the shipping zone matching a given package from the cart.
*
* @since 2.6.0
* @uses KKART_Shipping_Zones::get_zone_matching_package
* @param array $package Shipping package.
* @return KKART_Shipping_Zone
*/
function kkart_get_shipping_zone( $package ) {
return KKART_Shipping_Zones::get_zone_matching_package( $package );
}
}
/**
* Get a nice name for credit card providers.
*
* @since 2.6.0
* @param string $type Provider Slug/Type.
* @return string
*/
function kkart_get_credit_card_type_label( $type ) {
// Normalize.
$type = strtolower( $type );
$type = str_replace( '-', ' ', $type );
$type = str_replace( '_', ' ', $type );
$labels = apply_filters(
'kkart_credit_card_type_labels',
array(
'mastercard' => __( 'MasterCard', 'kkart' ),
'visa' => __( 'Visa', 'kkart' ),
'discover' => __( 'Discover', 'kkart' ),
'american express' => __( 'American Express', 'kkart' ),
'diners' => __( 'Diners', 'kkart' ),
'jcb' => __( 'JCB', 'kkart' ),
)
);
return apply_filters( 'kkart_get_credit_card_type_label', ( array_key_exists( $type, $labels ) ? $labels[ $type ] : ucfirst( $type ) ) );
}
/**
* Outputs a "back" link so admin screens can easily jump back a page.
*
* @param string $label Title of the page to return to.
* @param string $url URL of the page to return to.
*/
function kkart_back_link( $label, $url ) {
echo '<small class="kkart-admin-breadcrumb"><a href="' . esc_url( $url ) . '" aria-label="' . esc_attr( $label ) . '">⤴</a></small>';
}
/**
* Display a Kkart help tip.
*
* @since 2.5.0
*
* @param string $tip Help tip text.
* @param bool $allow_html Allow sanitized HTML if true or escape.
* @return string
*/
function kkart_help_tip( $tip, $allow_html = false ) {
if ( $allow_html ) {
$tip = kkart_sanitize_tooltip( $tip );
} else {
$tip = esc_attr( $tip );
}
return '<span class="kkart-help-tip dashicons dashicons-editor-help" data-tip="' . $tip . '"></span>';
}
/**
* Return a list of potential postcodes for wildcard searching.
*
* @since 2.6.0
* @param string $postcode Postcode.
* @param string $country Country to format postcode for matching.
* @return string[]
*/
function kkart_get_wildcard_postcodes( $postcode, $country = '' ) {
$formatted_postcode = kkart_format_postcode( $postcode, $country );
$length = function_exists( 'mb_strlen' ) ? mb_strlen( $formatted_postcode ) : strlen( $formatted_postcode );
$postcodes = array(
$postcode,
$formatted_postcode,
$formatted_postcode . '*',
);
for ( $i = 0; $i < $length; $i ++ ) {
$postcodes[] = ( function_exists( 'mb_substr' ) ? mb_substr( $formatted_postcode, 0, ( $i + 1 ) * -1 ) : substr( $formatted_postcode, 0, ( $i + 1 ) * -1 ) ) . '*';
}
return $postcodes;
}
/**
* Used by shipping zones and taxes to compare a given $postcode to stored
* postcodes to find matches for numerical ranges, and wildcards.
*
* @since 2.6.0
* @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.
* @param string $object_compare_key DB column name for the value.
* @param string $country Country from which this postcode belongs. Allows for formatting.
* @return array Array of matching object ID and matching values.
*/
function kkart_postcode_location_matcher( $postcode, $objects, $object_id_key, $object_compare_key, $country = '' ) {
$postcode = kkart_normalize_postcode( $postcode );
$wildcard_postcodes = array_map( 'kkart_clean', kkart_get_wildcard_postcodes( $postcode, $country ) );
$matches = array();
foreach ( $objects as $object ) {
$object_id = $object->$object_id_key;
$compare_against = $object->$object_compare_key;
// Handle postcodes containing ranges.
if ( strstr( $compare_against, '...' ) ) {
$range = array_map( 'trim', explode( '...', $compare_against ) );
if ( 2 !== count( $range ) ) {
continue;
}
list( $min, $max ) = $range;
// If the postcode is non-numeric, make it numeric.
if ( ! is_numeric( $min ) || ! is_numeric( $max ) ) {
$compare = kkart_make_numeric_postcode( $postcode );
$min = str_pad( kkart_make_numeric_postcode( $min ), strlen( $compare ), '0' );
$max = str_pad( kkart_make_numeric_postcode( $max ), strlen( $compare ), '0' );
} else {
$compare = $postcode;
}
if ( $compare >= $min && $compare <= $max ) {
$matches[ $object_id ] = isset( $matches[ $object_id ] ) ? $matches[ $object_id ] : array();
$matches[ $object_id ][] = $compare_against;
}
} elseif ( in_array( $compare_against, $wildcard_postcodes, true ) ) {
// Wildcard and standard comparison.
$matches[ $object_id ] = isset( $matches[ $object_id ] ) ? $matches[ $object_id ] : array();
$matches[ $object_id ][] = $compare_against;
}
}
return $matches;
}
/**
* Gets number of shipping methods currently enabled. Used to identify if
* shipping is configured.
*
* @since 2.6.0
* @param bool $include_legacy Count legacy shipping methods too.
* @param bool $enabled_only Whether non-legacy shipping methods should be
* restricted to enabled ones. It doesn't affect
* legacy shipping methods. @since 4.3.0.
* @return int
*/
function kkart_get_shipping_method_count( $include_legacy = false, $enabled_only = false ) {
global $wpdb;
$transient_name = $include_legacy ? 'kkart_shipping_method_count_legacy' : 'kkart_shipping_method_count';
$transient_version = KKART_Cache_Helper::get_transient_version( 'shipping' );
$transient_value = get_transient( $transient_name );
if ( isset( $transient_value['value'], $transient_value['version'] ) && $transient_value['version'] === $transient_version ) {
return absint( $transient_value['value'] );
}
$where_clause = $enabled_only ? 'WHERE is_enabled=1' : '';
$method_count = absint( $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->prefix}kkart_shipping_zone_methods ${where_clause}" ) );
if ( $include_legacy ) {
// Count activated methods that don't support shipping zones.
$methods = KKART()->shipping()->get_shipping_methods();
foreach ( $methods as $method ) {
if ( isset( $method->enabled ) && 'yes' === $method->enabled && ! $method->supports( 'shipping-zones' ) ) {
$method_count++;
}
}
}
$transient_value = array(
'version' => $transient_version,
'value' => $method_count,
);
set_transient( $transient_name, $transient_value, DAY_IN_SECONDS * 30 );
return $method_count;
}
/**
* Wrapper for set_time_limit to see if it is enabled.
*
* @since 2.6.0
* @param int $limit Time limit.
*/
function kkart_set_time_limit( $limit = 0 ) {
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
@set_time_limit( $limit ); // @codingStandardsIgnoreLine
}
}
/**
* Wrapper for nocache_headers which also disables page caching.
*
* @since 3.2.4
*/
function kkart_nocache_headers() {
KKART_Cache_Helper::set_nocache_constants();
nocache_headers();
}
/**
* Used to sort products attributes with uasort.
*
* @since 2.6.0
* @param array $a First attribute to compare.
* @param array $b Second attribute to compare.
* @return int
*/
function kkart_product_attribute_uasort_comparison( $a, $b ) {
$a_position = is_null( $a ) ? null : $a['position'];
$b_position = is_null( $b ) ? null : $b['position'];
return kkart_uasort_comparison( $a_position, $b_position );
}
/**
* Used to sort shipping zone methods with uasort.
*
* @since 3.0.0
* @param array $a First shipping zone method to compare.
* @param array $b Second shipping zone method to compare.
* @return int
*/
function kkart_shipping_zone_method_order_uasort_comparison( $a, $b ) {
return kkart_uasort_comparison( $a->method_order, $b->method_order );
}
/**
* 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 kkart_checkout_fields_uasort_comparison( $a, $b ) {
/*
* We are not guaranteed to get a priority
* setting. So don't compare if they don't
* exist.
*/
if ( ! isset( $a['priority'], $b['priority'] ) ) {
return 0;
}
return kkart_uasort_comparison( $a['priority'], $b['priority'] );
}
/**
* User to sort two values with ausort.
*
* @since 3.5.1
* @param int $a First value to compare.
* @param int $b Second value to compare.
* @return int
*/
function kkart_uasort_comparison( $a, $b ) {
if ( $a === $b ) {
return 0;
}
return ( $a < $b ) ? -1 : 1;
}
/**
* Sort values based on ascii, usefull for special chars in strings.
*
* @param string $a First value.
* @param string $b Second value.
* @return int
*/
function kkart_ascii_uasort_comparison( $a, $b ) {
// phpcs:disable WordPress.PHP.NoSilencedErrors.Discouraged
if ( function_exists( 'iconv' ) && defined( 'ICONV_IMPL' ) && @strcasecmp( ICONV_IMPL, 'unknown' ) !== 0 ) {
$a = @iconv( 'UTF-8', 'ASCII//TRANSLIT//IGNORE', $a );
$b = @iconv( 'UTF-8', 'ASCII//TRANSLIT//IGNORE', $b );
}
// phpcs:enable WordPress.PHP.NoSilencedErrors.Discouraged
return strcmp( $a, $b );
}
/**
* Sort array according to current locale rules and maintaining index association.
* By default tries to use Collator from PHP Internationalization Functions if available.
* If PHP Collator class doesn't exists it fallback to removing accepts from a array
* and by sorting with `uasort( $data, 'strcmp' )` giving support for ASCII values.
*
* @since 4.6.0
* @param array $data List of values to sort.
* @param string $locale Locale.
* @return array
*/
function kkart_asort_by_locale( &$data, $locale = '' ) {
// Use Collator if PHP Internationalization Functions (php-intl) is available.
if ( class_exists( 'Collator' ) ) {
$locale = $locale ? $locale : get_locale();
$collator = new Collator( $locale );
$collator->asort( $data, Collator::SORT_STRING );
return $data;
}
$raw_data = $data;
array_walk(
$data,
function ( &$value ) {
$value = remove_accents( html_entity_decode( $value ) );
}
);
uasort( $data, 'strcmp' );
foreach ( $data as $key => $val ) {
$data[ $key ] = $raw_data[ $key ];
}
return $data;
}
/**
* Get rounding mode for internal tax calculations.
*
* @since 3.2.4
* @return int
*/
function kkart_get_tax_rounding_mode() {
$constant = KKART_TAX_ROUNDING_MODE;
if ( 'auto' === $constant ) {
return 'yes' === get_option( 'kkart_prices_include_tax', 'no' ) ? 2 : 1;
}
return intval( $constant );
}
/**
* Get rounding precision for internal KKART calculations.
* Will increase the precision of kkart_get_price_decimals by 2 decimals, unless KKART_ROUNDING_PRECISION is set to a higher number.
*
* @since 2.6.3
* @return int
*/
function kkart_get_rounding_precision() {
$precision = kkart_get_price_decimals() + 2;
if ( absint( KKART_ROUNDING_PRECISION ) > $precision ) {
$precision = absint( KKART_ROUNDING_PRECISION );
}
return $precision;
}
/**
* Add precision to a number and return a number.
*
* @since 3.2.0
* @param float $value Number to add precision to.
* @param bool $round If should round after adding precision.
* @return int|float
*/
function kkart_add_number_precision( $value, $round = true ) {
$cent_precision = pow( 10, kkart_get_price_decimals() );
$value = $value * $cent_precision;
return $round ? NumberUtil::round( $value, kkart_get_rounding_precision() - kkart_get_price_decimals() ) : $value;
}
/**
* Remove precision from a number and return a float.
*
* @since 3.2.0
* @param float $value Number to add precision to.
* @return float
*/
function kkart_remove_number_precision( $value ) {
$cent_precision = pow( 10, kkart_get_price_decimals() );
return $value / $cent_precision;
}
/**
* 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.
* @param bool $round Should we round after adding precision?.
* @return int|array
*/
function kkart_add_number_precision_deep( $value, $round = true ) {
if ( ! is_array( $value ) ) {
return kkart_add_number_precision( $value, $round );
}
foreach ( $value as $key => $sub_value ) {
$value[ $key ] = kkart_add_number_precision_deep( $sub_value, $round );
}
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.
* @return int|array
*/
function kkart_remove_number_precision_deep( $value ) {
if ( ! is_array( $value ) ) {
return kkart_remove_number_precision( $value );
}
foreach ( $value as $key => $sub_value ) {
$value[ $key ] = kkart_remove_number_precision_deep( $sub_value );
}
return $value;
}
/**
* Get a shared logger instance.
*
* Use the kkart_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 KKART_Logger_Interface.
*
* @see KKART_Logger_Interface
*
* @return KKART_Logger
*/
function kkart_get_logger() {
static $logger = null;
$class = apply_filters( 'kkart_logging_class', 'KKART_Logger' );
if ( null !== $logger && is_string( $class ) && is_a( $logger, $class ) ) {
return $logger;
}
$implements = class_implements( $class );
if ( is_array( $implements ) && in_array( 'KKART_Logger_Interface', $implements, true ) ) {
$logger = is_object( $class ) ? $class : new $class();
} else {
kkart_doing_it_wrong(
__FUNCTION__,
sprintf(
/* translators: 1: class name 2: kkart_logging_class 3: KKART_Logger_Interface */
__( 'The class %1$s provided by %2$s filter must implement %3$s.', 'kkart' ),
'<code>' . esc_html( is_object( $class ) ? get_class( $class ) : $class ) . '</code>',
'<code>kkart_logging_class</code>',
'<code>KKART_Logger_Interface</code>'
),
'3.0'
);
$logger = is_a( $logger, 'KKART_Logger' ) ? $logger : new KKART_Logger();
}
return $logger;
}
/**
* Trigger logging cleanup using the logging class.
*
* @since 3.4.0
*/
function kkart_cleanup_logs() {
$logger = kkart_get_logger();
if ( is_callable( array( $logger, 'clear_expired_logs' ) ) ) {
$logger->clear_expired_logs();
}
}
add_action( 'kkart_cleanup_logs', 'kkart_cleanup_logs' );
/**
* Prints human-readable information about a variable.
*
* Some server environments block some debugging functions. This function provides a safe way to
* turn an expression into a printable, readable form without calling blocked functions.
*
* @since 3.0
*
* @param mixed $expression The expression to be printed.
* @param bool $return Optional. Default false. Set to true to return the human-readable string.
* @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.
*/
function kkart_print_r( $expression, $return = false ) {
$alternatives = array(
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 ),
),
);
$alternatives = apply_filters( 'kkart_print_r_alternatives', $alternatives, $expression );
foreach ( $alternatives as $alternative ) {
if ( function_exists( $alternative['func'] ) ) {
$res = $alternative['func']( ...$alternative['args'] );
if ( $return ) {
return $res; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
echo $res; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
return true;
}
}
return false;
}
/**
* Registers the default log handler.
*
* @since 3.0
* @param array $handlers Handlers.
* @return array
*/
function kkart_register_default_log_handler( $handlers ) {
$handler_class = Constants::get_constant( 'KKART_LOG_HANDLER' );
if ( ! class_exists( $handler_class ) ) {
$handler_class = KKART_Log_Handler_File::class;
}
array_push( $handlers, new $handler_class() );
return $handlers;
}
add_filter( 'kkart_register_log_handlers', 'kkart_register_default_log_handler' );
/**
* Based on wp_list_pluck, this calls a method instead of returning a property.
*
* @since 3.0.0
* @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.
* @return array Array of values.
*/
function kkart_list_pluck( $list, $callback_or_field, $index_key = null ) {
// Use wp_list_pluck if this isn't a callback.
$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 ) {
// 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 ) ) {
$newlist[ $value->$index_key ] = $value->{$callback_or_field}();
} else {
$newlist[] = $value->{$callback_or_field}();
}
}
return $newlist;
}
/**
* 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.
*
* @since 3.0.0
* @return array
*/
function kkart_get_permalink_structure() {
$saved_permalinks = (array) get_option( 'kkart_permalinks', array() );
$permalinks = wp_parse_args(
array_filter( $saved_permalinks ),
array(
'product_base' => _x( 'product', 'slug', 'kkart' ),
'category_base' => _x( 'product-category', 'slug', 'kkart' ),
'tag_base' => _x( 'product-tag', 'slug', 'kkart' ),
'attribute_base' => '',
'use_verbose_page_rules' => false,
)
);
if ( $saved_permalinks !== $permalinks ) {
update_option( 'kkart_permalinks', $permalinks );
}
$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'] );
return $permalinks;
}
/**
* Switch Kkart to site language.
*
* @since 3.1.0
*/
function kkart_switch_to_site_locale() {
if ( function_exists( 'switch_to_locale' ) ) {
switch_to_locale( get_locale() );
// Filter on plugin_locale so load_plugin_textdomain loads the correct locale.
add_filter( 'plugin_locale', 'get_locale' );
// Init KKART locale.
KKART()->load_plugin_textdomain();
}
}
/**
* Switch Kkart language to original.
*
* @since 3.1.0
*/
function kkart_restore_locale() {
if ( function_exists( 'restore_previous_locale' ) ) {
restore_previous_locale();
// Remove filter.
remove_filter( 'plugin_locale', 'get_locale' );
// Init KKART locale.
KKART()->load_plugin_textdomain();
}
}
/**
* Convert plaintext phone number to clickable phone number.
*
* 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
*
* @param string $phone Content to convert phone number.
* @return string Content with converted phone number.
*/
function kkart_make_phone_clickable( $phone ) {
$number = trim( preg_replace( '/[^\d|\+]/', '', $phone ) );
return $number ? '<a href="tel:' . esc_attr( $number ) . '">' . esc_html( $phone ) . '</a>' : '';
}
/**
* Get an item of post data if set, otherwise return a default value.
*
* @since 3.0.9
* @param string $key Meta key.
* @param string $default Default value.
* @return mixed Value sanitized by kkart_clean.
*/
function kkart_get_post_data_by_key( $key, $default = '' ) {
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput, WordPress.Security.NonceVerification.Missing
return kkart_clean( wp_unslash( kkart_get_var( $_POST[ $key ], $default ) ) );
}
/**
* Get data if set, otherwise return a default value or null. Prevents notices when data is not set.
*
* @since 3.2.0
* @param mixed $var Variable.
* @param string $default Default value.
* @return mixed
*/
function kkart_get_var( &$var, $default = null ) {
return isset( $var ) ? $var : $default;
}
/**
* Read in Kkart headers when reading plugin headers.
*
* @since 3.2.0
* @param array $headers Headers.
* @return array
*/
function kkart_enable_kkart_plugin_headers( $headers ) {
if ( ! class_exists( 'KKART_Plugin_Updates' ) ) {
include_once dirname( __FILE__ ) . '/admin/plugin-updates/class-kkart-plugin-updates.php';
}
// KKART requires at least - allows developers to define which version of Kkart the plugin requires to run.
$headers[] = KKART_Plugin_Updates::VERSION_REQUIRED_HEADER;
// KKART tested up to - allows developers to define which version of Kkart they have tested up to.
$headers[] = KKART_Plugin_Updates::VERSION_TESTED_HEADER;
// Woo - This is used in Kkart extensions and is picked up by the helper.
$headers[] = 'Woo';
return $headers;
}
add_filter( 'extra_theme_headers', 'kkart_enable_kkart_plugin_headers' );
add_filter( 'extra_plugin_headers', 'kkart_enable_kkart_plugin_headers' );
/**
* Prevent auto-updating the Kkart plugin on major releases if there are untested extensions active.
*
* @since 3.2.0
* @param bool $should_update If should update.
* @param object $plugin Plugin data.
* @return bool
*/
function kkart_prevent_dangerous_auto_updates( $should_update, $plugin ) {
if ( ! isset( $plugin->plugin, $plugin->new_version ) ) {
return $should_update;
}
if ( 'kkart/kkart.php' !== $plugin->plugin ) {
return $should_update;
}
if ( ! class_exists( 'KKART_Plugin_Updates' ) ) {
include_once dirname( __FILE__ ) . '/admin/plugin-updates/class-kkart-plugin-updates.php';
}
$new_version = kkart_clean( $plugin->new_version );
$plugin_updates = new KKART_Plugin_Updates();
$untested_plugins = $plugin_updates->get_untested_plugins( $new_version, 'major' );
if ( ! empty( $untested_plugins ) ) {
return false;
}
return $should_update;
}
add_filter( 'auto_update_plugin', 'kkart_prevent_dangerous_auto_updates', 99, 2 );
/**
* 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 kkart_delete_expired_transients() {
global $wpdb;
// phpcs:disable WordPress.DB.PreparedSQL.NotPrepared
$sql = "DELETE a, b FROM $wpdb->options a, $wpdb->options b
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";
$rows = $wpdb->query( $wpdb->prepare( $sql, $wpdb->esc_like( '_transient_' ) . '%', $wpdb->esc_like( '_transient_timeout_' ) . '%', time() ) );
$sql = "DELETE a, b FROM $wpdb->options a, $wpdb->options b
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";
$rows2 = $wpdb->query( $wpdb->prepare( $sql, $wpdb->esc_like( '_site_transient_' ) . '%', $wpdb->esc_like( '_site_transient_timeout_' ) . '%', time() ) );
// phpcs:enable WordPress.DB.PreparedSQL.NotPrepared
return absint( $rows + $rows2 );
}
add_action( 'kkart_installed', 'kkart_delete_expired_transients' );
/**
* Make a URL relative, if possible.
*
* @since 3.2.0
* @param string $url URL to make relative.
* @return string
*/
function kkart_get_relative_url( $url ) {
return kkart_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 kkart_is_external_resource( $url ) {
$wp_base = str_replace( array( 'http://', 'https://' ), '//', get_home_url( null, '/', 'http' ) );
return strstr( $url, '://' ) && ! strstr( $url, $wp_base );
}
/**
* 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 kkart_is_active_theme( $theme ) {
return is_array( $theme ) ? in_array( get_template(), $theme, true ) : get_template() === $theme;
}
/**
* Is the site using a default WP theme?
*
* @return boolean
*/
function kkart_is_wp_default_theme_active() {
return kkart_is_active_theme(
array(
'twentytwentyone',
'twentytwenty',
'twentynineteen',
'twentyseventeen',
'twentysixteen',
'twentyfifteen',
'twentyfourteen',
'twentythirteen',
'twentyeleven',
'twentytwelve',
'twentyten',
)
);
}
/**
* Cleans up session data - cron callback.
*
* @since 3.3.0
*/
function kkart_cleanup_session_data() {
$session_class = apply_filters( 'kkart_session_handler', 'KKART_Session_Handler' );
$session = new $session_class();
if ( is_callable( array( $session, 'cleanup_sessions' ) ) ) {
$session->cleanup_sessions();
}
}
add_action( 'kkart_cleanup_sessions', 'kkart_cleanup_session_data' );
/**
* 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 kkart_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 ) {
return array( 0, 1 );
}
$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 );
}
/**
* Round discount.
*
* @param double $value Amount to round.
* @param int $precision DP to round.
* @return float
*/
function kkart_round_discount( $value, $precision ) {
if ( version_compare( PHP_VERSION, '5.3.0', '>=' ) ) {
return NumberUtil::round( $value, $precision, KKART_DISCOUNT_ROUNDING_MODE ); // phpcs:ignore PHPCompatibility.FunctionUse.NewFunctionParameters.round_modeFound
}
if ( 2 === KKART_DISCOUNT_ROUNDING_MODE ) {
return kkart_legacy_round_half_down( $value, $precision );
}
return NumberUtil::round( $value, $precision );
}
/**
* 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 kkart_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 );
}
/**
* Retrieves the MySQL server version. Based on $wpdb.
*
* @since 3.4.1
* @return array Vesion information.
*/
function kkart_get_server_database_version() {
global $wpdb;
if ( empty( $wpdb->is_mysql ) ) {
return array(
'string' => '',
'number' => '',
);
}
// phpcs:disable WordPress.DB.RestrictedFunctions, PHPCompatibility.Extensions.RemovedExtensions.mysql_DeprecatedRemoved
if ( $wpdb->use_mysqli ) {
$server_info = mysqli_get_server_info( $wpdb->dbh );
} else {
$server_info = mysql_get_server_info( $wpdb->dbh );
}
// phpcs:enable WordPress.DB.RestrictedFunctions, PHPCompatibility.Extensions.RemovedExtensions.mysql_DeprecatedRemoved
return array(
'string' => $server_info,
'number' => preg_replace( '/([^\d.]+).*/', '', $server_info ),
);
}
/**
* Initialize and load the cart functionality.
*
* @since 3.6.4
* @return void
*/
function kkart_load_cart() {
if ( ! did_action( 'before_kkart_init' ) || doing_action( 'before_kkart_init' ) ) {
/* translators: 1: kkart_load_cart 2: kkart_init */
kkart_doing_it_wrong( __FUNCTION__, sprintf( __( '%1$s should not be called before the %2$s action.', 'kkart' ), 'kkart_load_cart', 'kkart_init' ), '3.7' );
return;
}
// Ensure dependencies are loaded in all contexts.
include_once KKART_ABSPATH . 'includes/kkart-cart-functions.php';
include_once KKART_ABSPATH . 'includes/kkart-notice-functions.php';
KKART()->initialize_session();
KKART()->initialize_cart();
}
/**
* Test whether the context of execution comes from async action scheduler.
*
* @since 4.0.0
* @return bool
*/
function kkart_is_running_from_async_action_scheduler() {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
return isset( $_REQUEST['action'] ) && 'as_async_request_queue_runner' === $_REQUEST['action'];
}
/**
* Kkart get user addresses
*
* @since 1.0.0
* @return array | false
*/
function kkart_get_user_address($address_id = '') {
$data = array();
if(! is_user_logged_in()){
return $data;
}
$user_id = get_current_user_id();
$addresses = get_user_meta( $user_id, 'kkart_addresses', true);
// Addresses not found?
if(empty($addresses) || (!empty($address_id) && !isset($addresses[$address_id]))){
return $data;
}
// Get single address
if(!empty($address_id)){
return $addresses[$address_id];
}
return $addresses;
}
/**
* Kkart delete user addresses
*
* @since 1.0.0
* @return array | false
*/
function kkart_delete_user_address($address_id){
if(! is_user_logged_in()){
return false;
}
$user_id = get_current_user_id();
$address = kkart_get_user_address();
if(empty($address)){
return true;
}
if(isset($address[$address_id])){
unset($address[$address_id]);
$ret = update_user_meta( $user_id, 'kkart_addresses', $address);
if(empty($ret)){
return false;
}
}
return true;
}
/**
* Kkart update or add user addresses
*
* @since 1.0.0
* @return bool
*/
function kkart_update_user_address($address_id, $array){
if(! is_user_logged_in()){
return false;
}
$user_id = get_current_user_id();
// Get billing fields
$checkout = KKART()->checkout();
$fields = $checkout->get_checkout_fields( 'billing' );
$address = kkart_get_user_address();
if(empty($address)){
$address = array();
}
foreach($fields as $field => $value){
if(isset($array[$field])){
$address[$address_id][$field] = $array[$field];
}
}
$selected_country = $address[$address_id]['billing_country'];
$postal_code = $address[$address_id]['billing_postcode'];
$correct_postal = KKART_Validation::is_postcode( $postal_code, $selected_country);
if (!$correct_postal) {
$postal_error['error'] = __('The postal code is invalid for the selected country.');
return $postal_error;
}
// Update user meta
$ret = update_user_meta( $user_id, 'kkart_addresses', $address);
if(empty($ret) || empty($address[$address_id])){
return false;
}
return $address[$address_id];
}
/////////////////////////////////////////
/// KKART Shortcode related functions
/////////////////////////////////////////
// Get the current query for render the product
function kkart_shortcode_current_query($query_args, $atts, $type){
global $wp_query;
if($type == 'pagelayer_current_query'){
if ( ! is_shop() ) {
$query_args = $wp_query->query_vars;
}
add_action( "kkart_shortcode_before_{$type}_loop", function () {
kkart_set_loop_prop( 'is_shortcode', false );
} );
if(!empty($atts['paginate'])){
$page = get_query_var( 'paged', 1 );
if( 1 < $page ) {
$query_args['paged'] = $page;
}
}
// Always query only IDs
$query_args['fields'] = 'ids';
}
return $query_args;
}