' . $mini_cart . '
',
)
),
'cart_hash' => WC()->cart->get_cart_hash(),
);
wp_send_json( $data );
}
/**
* AJAX apply coupon on checkout page.
*/
public static function apply_coupon() {
check_ajax_referer( 'apply-coupon', 'security' );
$coupon_code = ArrayUtil::get_value_or_default( $_POST, 'coupon_code' );
$billing_email = ArrayUtil::get_value_or_default( $_POST, 'billing_email' );
if ( is_string( $billing_email ) && is_email( $billing_email ) ) {
wc()->customer->set_billing_email( $billing_email );
}
if ( ! StringUtil::is_null_or_whitespace( $coupon_code ) ) {
WC()->cart->add_discount( wc_format_coupon_code( wp_unslash( $coupon_code ) ) ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
} else {
wc_add_notice( WC_Coupon::get_generic_coupon_error( WC_Coupon::E_WC_COUPON_PLEASE_ENTER ), 'error' );
}
wc_print_notices();
wp_die();
}
/**
* AJAX remove coupon on cart and checkout page.
*/
public static function remove_coupon() {
check_ajax_referer( 'remove-coupon', 'security' );
$coupon = isset( $_POST['coupon'] ) ? wc_format_coupon_code( wp_unslash( $_POST['coupon'] ) ) : false; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
if ( StringUtil::is_null_or_whitespace( $coupon ) ) {
wc_add_notice( __( 'Sorry there was a problem removing this coupon.', 'woocommerce' ), 'error' );
} else {
WC()->cart->remove_coupon( $coupon );
wc_add_notice( __( 'Coupon has been removed.', 'woocommerce' ) );
}
wc_print_notices();
wp_die();
}
/**
* AJAX update shipping method on cart page.
*/
public static function update_shipping_method() {
check_ajax_referer( 'update-shipping-method', 'security' );
wc_maybe_define_constant( 'WOOCOMMERCE_CART', true );
$chosen_shipping_methods = WC()->session->get( 'chosen_shipping_methods' );
$posted_shipping_methods = isset( $_POST['shipping_method'] ) ? wc_clean( wp_unslash( $_POST['shipping_method'] ) ) : array();
if ( is_array( $posted_shipping_methods ) ) {
foreach ( $posted_shipping_methods as $i => $value ) {
if ( ! is_string( $value ) ) {
continue;
}
$chosen_shipping_methods[ $i ] = $value;
}
}
WC()->session->set( 'chosen_shipping_methods', $chosen_shipping_methods );
self::get_cart_totals();
}
/**
* AJAX receive updated cart_totals div.
*/
public static function get_cart_totals() {
wc_maybe_define_constant( 'WOOCOMMERCE_CART', true );
WC()->cart->calculate_totals();
woocommerce_cart_totals();
wp_die();
}
/**
* Session has expired.
*/
private static function update_order_review_expired() {
wp_send_json(
array(
'fragments' => apply_filters(
'woocommerce_update_order_review_fragments',
array(
'form.woocommerce-checkout' => wc_print_notice(
esc_html__( 'Sorry, your session has expired.', 'woocommerce' ) . ' ';
foreach ( $errors as $error ) {
echo '
' . wp_kses_post( $error ) . '
';
}
echo '
';
echo '
';
delete_option( WC_Admin_Meta_Boxes::ERROR_STORE );
}
wp_die();
}
/**
* Bulk action - Toggle Enabled.
*
* @param array $variations List of variations.
* @param array $data Data to set.
*
* @used-by bulk_edit_variations
*/
private static function variation_bulk_action_toggle_enabled( $variations, $data ) {
foreach ( $variations as $variation_id ) {
$variation = wc_get_product( $variation_id );
$variation->set_status( 'private' === $variation->get_status( 'edit' ) ? 'publish' : 'private' );
$variation->save();
}
}
/**
* Bulk action - Toggle Downloadable Checkbox.
*
* @param array $variations List of variations.
* @param array $data Data to set.
*
* @used-by bulk_edit_variations
*/
private static function variation_bulk_action_toggle_downloadable( $variations, $data ) {
self::variation_bulk_toggle( $variations, 'downloadable' );
}
/**
* Bulk action - Toggle Virtual Checkbox.
*
* @param array $variations List of variations.
* @param array $data Data to set.
*
* @used-by bulk_edit_variations
*/
private static function variation_bulk_action_toggle_virtual( $variations, $data ) {
self::variation_bulk_toggle( $variations, 'virtual' );
}
/**
* Bulk action - Toggle Manage Stock Checkbox.
*
* @param array $variations List of variations.
* @param array $data Data to set.
*
* @used-by bulk_edit_variations
*/
private static function variation_bulk_action_toggle_manage_stock( $variations, $data ) {
self::variation_bulk_toggle( $variations, 'manage_stock' );
}
/**
* Bulk action - Set Regular Prices.
*
* @param array $variations List of variations.
* @param array $data Data to set.
*
* @used-by bulk_edit_variations
*/
private static function variation_bulk_action_variable_regular_price( $variations, $data ) {
self::variation_bulk_set( $variations, 'regular_price', $data['value'] );
}
/**
* Bulk action - Set Sale Prices.
*
* @param array $variations List of variations.
* @param array $data Data to set.
*
* @used-by bulk_edit_variations
*/
private static function variation_bulk_action_variable_sale_price( $variations, $data ) {
self::variation_bulk_set( $variations, 'sale_price', $data['value'] );
}
/**
* Bulk action - Set Stock Status as In Stock.
*
* @param array $variations List of variations.
* @param array $data Data to set.
*
* @used-by bulk_edit_variations
*/
private static function variation_bulk_action_variable_stock_status_instock( $variations, $data ) {
self::variation_bulk_set( $variations, 'stock_status', 'instock' );
}
/**
* Bulk action - Set Stock Status as Out of Stock.
*
* @param array $variations List of variations.
* @param array $data Data to set.
*
* @used-by bulk_edit_variations
*/
private static function variation_bulk_action_variable_stock_status_outofstock( $variations, $data ) {
self::variation_bulk_set( $variations, 'stock_status', 'outofstock' );
}
/**
* Bulk action - Set Stock Status as On Backorder.
*
* @param array $variations List of variations.
* @param array $data Data to set.
*
* @used-by bulk_edit_variations
*/
private static function variation_bulk_action_variable_stock_status_onbackorder( $variations, $data ) {
self::variation_bulk_set( $variations, 'stock_status', 'onbackorder' );
}
/**
* Bulk action - Set Stock.
*
* @param array $variations List of variations.
* @param array $data Data to set.
*
* @used-by bulk_edit_variations
*/
private static function variation_bulk_action_variable_stock( $variations, $data ) {
if ( ! isset( $data['value'] ) ) {
return;
}
$quantity = wc_stock_amount( wc_clean( $data['value'] ) );
foreach ( $variations as $variation_id ) {
$variation = wc_get_product( $variation_id );
if ( $variation->managing_stock() ) {
$variation->set_stock_quantity( $quantity );
} else {
$variation->set_stock_quantity( null );
}
$variation->save();
}
}
/**
* Bulk action - Set Low Stock Amount.
*
* @param array $variations List of variations.
* @param array $data Data to set.
*
* @used-by bulk_edit_variations
*/
private static function variation_bulk_action_variable_low_stock_amount( $variations, $data ) {
if ( ! isset( $data['value'] ) ) {
return;
}
$low_stock_amount = wc_stock_amount( wc_clean( $data['value'] ) );
foreach ( $variations as $variation_id ) {
$variation = wc_get_product( $variation_id );
if ( $variation->managing_stock() ) {
$variation->set_low_stock_amount( $low_stock_amount );
} else {
$variation->set_low_stock_amount( '' );
}
$variation->save();
}
}
/**
* Bulk action - Set Weight.
*
* @param array $variations List of variations.
* @param array $data Data to set.
*
* @used-by bulk_edit_variations
*/
private static function variation_bulk_action_variable_weight( $variations, $data ) {
self::variation_bulk_set( $variations, 'weight', $data['value'] );
}
/**
* Bulk action - Set Length.
*
* @param array $variations List of variations.
* @param array $data Data to set.
*
* @used-by bulk_edit_variations
*/
private static function variation_bulk_action_variable_length( $variations, $data ) {
self::variation_bulk_set( $variations, 'length', $data['value'] );
}
/**
* Bulk action - Set Width.
*
* @param array $variations List of variations.
* @param array $data Data to set.
*
* @used-by bulk_edit_variations
*/
private static function variation_bulk_action_variable_width( $variations, $data ) {
self::variation_bulk_set( $variations, 'width', $data['value'] );
}
/**
* Bulk action - Set Height.
*
* @param array $variations List of variations.
* @param array $data Data to set.
*
* @used-by bulk_edit_variations
*/
private static function variation_bulk_action_variable_height( $variations, $data ) {
self::variation_bulk_set( $variations, 'height', $data['value'] );
}
/**
* Bulk action - Set Download Limit.
*
* @param array $variations List of variations.
* @param array $data Data to set.
*
* @used-by bulk_edit_variations
*/
private static function variation_bulk_action_variable_download_limit( $variations, $data ) {
self::variation_bulk_set( $variations, 'download_limit', $data['value'] );
}
/**
* Bulk action - Set Download Expiry.
*
* @param array $variations List of variations.
* @param array $data Data to set.
*
* @used-by bulk_edit_variations
*/
private static function variation_bulk_action_variable_download_expiry( $variations, $data ) {
self::variation_bulk_set( $variations, 'download_expiry', $data['value'] );
}
/**
* Bulk action - Delete all.
*
* @param array $variations List of variations.
* @param array $data Data to set.
*
* @used-by bulk_edit_variations
*/
private static function variation_bulk_action_delete_all( $variations, $data ) {
if ( isset( $data['allowed'] ) && 'true' === $data['allowed'] ) {
foreach ( $variations as $variation_id ) {
$variation = wc_get_product( $variation_id );
$variation->delete( true );
}
}
}
/**
* Bulk action - Sale Schedule.
*
* @param array $variations List of variations.
* @param array $data Data to set.
*
* @used-by bulk_edit_variations
*/
private static function variation_bulk_action_variable_sale_schedule( $variations, $data ) {
if ( ! isset( $data['date_from'] ) && ! isset( $data['date_to'] ) ) {
return;
}
foreach ( $variations as $variation_id ) {
$variation = wc_get_product( $variation_id );
if ( 'false' !== $data['date_from'] ) {
$date_on_sale_from = date( 'Y-m-d 00:00:00', strtotime( wc_clean( $data['date_from'] ) ) ); // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date
$variation->set_date_on_sale_from( $date_on_sale_from );
}
if ( 'false' !== $data['date_to'] ) {
$date_on_sale_to = date( 'Y-m-d 23:59:59', strtotime( wc_clean( $data['date_to'] ) ) ); // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date
$variation->set_date_on_sale_to( $date_on_sale_to );
}
$variation->save();
}
}
/**
* Bulk action - Increase Regular Prices.
*
* @param array $variations List of variations.
* @param array $data Data to set.
*
* @used-by bulk_edit_variations
*/
private static function variation_bulk_action_variable_regular_price_increase( $variations, $data ) {
self::variation_bulk_adjust_price( $variations, 'regular_price', '+', wc_clean( $data['value'] ) );
}
/**
* Bulk action - Decrease Regular Prices.
*
* @param array $variations List of variations.
* @param array $data Data to set.
*
* @used-by bulk_edit_variations
*/
private static function variation_bulk_action_variable_regular_price_decrease( $variations, $data ) {
self::variation_bulk_adjust_price( $variations, 'regular_price', '-', wc_clean( $data['value'] ) );
}
/**
* Bulk action - Increase Sale Prices.
*
* @param array $variations List of variations.
* @param array $data Data to set.
*
* @used-by bulk_edit_variations
*/
private static function variation_bulk_action_variable_sale_price_increase( $variations, $data ) {
self::variation_bulk_adjust_price( $variations, 'sale_price', '+', wc_clean( $data['value'] ) );
}
/**
* Bulk action - Decrease Sale Prices.
*
* @param array $variations List of variations.
* @param array $data Data to set.
*
* @used-by bulk_edit_variations
*/
private static function variation_bulk_action_variable_sale_price_decrease( $variations, $data ) {
self::variation_bulk_adjust_price( $variations, 'sale_price', '-', wc_clean( $data['value'] ) );
}
/**
* Bulk action - Set Price.
*
* @param array $variations List of variations.
* @param string $field price being adjusted _regular_price or _sale_price.
* @param string $operator + or -.
* @param string $value Price or Percent.
*
* @used-by bulk_edit_variations
*/
private static function variation_bulk_adjust_price( $variations, $field, $operator, $value ) {
foreach ( $variations as $variation_id ) {
$variation = wc_get_product( $variation_id );
$field_value = $variation->{"get_$field"}( 'edit' );
if ( '%' === substr( $value, -1 ) ) {
$percent = wc_format_decimal( substr( $value, 0, -1 ) );
$field_value += NumberUtil::round( ( $field_value / 100 ) * $percent, wc_get_price_decimals() ) * "{$operator}1";
} else {
$field_value += $value * "{$operator}1";
}
$variation->{"set_$field"}( $field_value );
$variation->save();
}
}
/**
* Bulk set convenience function.
*
* @param array $variations List of variations.
* @param string $field Field to set.
* @param string $value to set.
*/
private static function variation_bulk_set( $variations, $field, $value ) {
foreach ( $variations as $variation_id ) {
$variation = wc_get_product( $variation_id );
$variation->{ "set_$field" }( wc_clean( $value ) );
$variation->save();
}
}
/**
* Bulk toggle convenience function.
*
* @param array $variations List of variations.
* @param string $field Field to toggle.
*/
private static function variation_bulk_toggle( $variations, $field ) {
foreach ( $variations as $variation_id ) {
$variation = wc_get_product( $variation_id );
$prev_value = $variation->{ "get_$field" }( 'edit' );
$variation->{ "set_$field" }( ! $prev_value );
$variation->save();
}
}
/**
* Bulk edit variations via AJAX.
*
* @uses WC_AJAX::variation_bulk_set()
* @uses WC_AJAX::variation_bulk_adjust_price()
* @uses WC_AJAX::variation_bulk_action_variable_sale_price_decrease()
* @uses WC_AJAX::variation_bulk_action_variable_sale_price_increase()
* @uses WC_AJAX::variation_bulk_action_variable_regular_price_decrease()
* @uses WC_AJAX::variation_bulk_action_variable_regular_price_increase()
* @uses WC_AJAX::variation_bulk_action_variable_sale_schedule()
* @uses WC_AJAX::variation_bulk_action_delete_all()
* @uses WC_AJAX::variation_bulk_action_variable_download_expiry()
* @uses WC_AJAX::variation_bulk_action_variable_download_limit()
* @uses WC_AJAX::variation_bulk_action_variable_height()
* @uses WC_AJAX::variation_bulk_action_variable_width()
* @uses WC_AJAX::variation_bulk_action_variable_length()
* @uses WC_AJAX::variation_bulk_action_variable_weight()
* @uses WC_AJAX::variation_bulk_action_variable_stock()
* @uses WC_AJAX::variation_bulk_action_variable_sale_price()
* @uses WC_AJAX::variation_bulk_action_variable_regular_price()
* @uses WC_AJAX::variation_bulk_action_toggle_manage_stock()
* @uses WC_AJAX::variation_bulk_action_toggle_virtual()
* @uses WC_AJAX::variation_bulk_action_toggle_downloadable()
* @uses WC_AJAX::variation_bulk_action_toggle_enabled
* @uses WC_AJAX::variation_bulk_action_variable_low_stock_amount()
*/
public static function bulk_edit_variations() {
ob_start();
check_ajax_referer( 'bulk-edit-variations', 'security' );
// Check permissions again and make sure we have what we need.
if ( ! current_user_can( 'edit_products' ) || empty( $_POST['product_id'] ) || empty( $_POST['bulk_action'] ) ) {
wp_die( -1 );
}
$product_id = absint( $_POST['product_id'] );
$bulk_action = wc_clean( wp_unslash( $_POST['bulk_action'] ) );
$data = ! empty( $_POST['data'] ) ? wc_clean( wp_unslash( $_POST['data'] ) ) : array();
$variations = array();
if ( apply_filters( 'woocommerce_bulk_edit_variations_need_children', true ) ) {
$variations = get_posts(
array(
'post_parent' => $product_id,
'posts_per_page' => -1,
'post_type' => 'product_variation',
'fields' => 'ids',
'post_status' => array( 'publish', 'private' ),
)
);
}
if ( method_exists( __CLASS__, "variation_bulk_action_$bulk_action" ) ) {
call_user_func( array( __CLASS__, "variation_bulk_action_$bulk_action" ), $variations, $data );
} else {
do_action( 'woocommerce_bulk_edit_variations_default', $bulk_action, $data, $product_id, $variations );
}
do_action( 'woocommerce_bulk_edit_variations', $bulk_action, $data, $product_id, $variations );
WC_Product_Variable::sync( $product_id );
wc_delete_product_transients( $product_id );
wp_die();
}
/**
* Handle submissions from assets/js/settings-views-html-settings-tax.js Backbone model.
*/
public static function tax_rates_save_changes() {
// phpcs:disable WordPress.Security.NonceVerification.Missing
if ( ! isset( $_POST['wc_tax_nonce'], $_POST['changes'] ) ) {
wp_send_json_error( 'missing_fields' );
wp_die();
}
$current_class = ! empty( $_POST['current_class'] ) ? wp_unslash( $_POST['current_class'] ) : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
if ( ! wp_verify_nonce( wp_unslash( $_POST['wc_tax_nonce'] ), 'wc_tax_nonce-class:' . $current_class ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
wp_send_json_error( 'bad_nonce' );
wp_die();
}
$current_class = WC_Tax::format_tax_rate_class( $current_class );
// Check User Caps.
if ( ! current_user_can( 'manage_woocommerce' ) ) {
wp_send_json_error( 'missing_capabilities' );
wp_die();
}
$changes = wp_unslash( $_POST['changes'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
foreach ( $changes as $tax_rate_id => $data ) {
if ( isset( $data['deleted'] ) ) {
if ( isset( $data['newRow'] ) ) {
// So the user added and deleted a new row.
// That's fine, it's not in the database anyways. NEXT!
continue;
}
WC_Tax::_delete_tax_rate( $tax_rate_id );
}
$tax_rate = array_intersect_key(
$data,
array(
'tax_rate_country' => 1,
'tax_rate_state' => 1,
'tax_rate' => 1,
'tax_rate_name' => 1,
'tax_rate_priority' => 1,
'tax_rate_compound' => 1,
'tax_rate_shipping' => 1,
'tax_rate_order' => 1,
)
);
if ( isset( $tax_rate['tax_rate'] ) ) {
$tax_rate['tax_rate'] = wc_format_decimal( $tax_rate['tax_rate'] );
}
if ( isset( $data['newRow'] ) ) {
$tax_rate['tax_rate_class'] = $current_class;
$tax_rate_id = WC_Tax::_insert_tax_rate( $tax_rate );
} elseif ( ! empty( $tax_rate ) ) {
WC_Tax::_update_tax_rate( $tax_rate_id, $tax_rate );
}
if ( isset( $data['postcode'] ) ) {
$postcode = array_map( 'wc_clean', $data['postcode'] );
$postcode = array_map( 'wc_normalize_postcode', $postcode );
WC_Tax::_update_tax_rate_postcodes( $tax_rate_id, $postcode );
}
if ( isset( $data['city'] ) ) {
WC_Tax::_update_tax_rate_cities( $tax_rate_id, array_map( 'wc_clean', array_map( 'wp_unslash', $data['city'] ) ) );
}
}
WC_Cache_Helper::invalidate_cache_group( 'taxes' );
WC_Cache_Helper::get_transient_version( 'shipping', true );
wp_send_json_success(
array(
'rates' => WC_Tax::get_rates_for_tax_class( $current_class ),
)
);
// phpcs:enable
}
/**
* Handle submissions from assets/js/wc-shipping-zones.js Backbone model.
*/
public static function shipping_zones_save_changes() {
if ( ! isset( $_POST['wc_shipping_zones_nonce'], $_POST['changes'] ) ) {
wp_send_json_error( 'missing_fields' );
wp_die();
}
if ( ! wp_verify_nonce( wp_unslash( $_POST['wc_shipping_zones_nonce'] ), 'wc_shipping_zones_nonce' ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
wp_send_json_error( 'bad_nonce' );
wp_die();
}
// Check User Caps.
if ( ! current_user_can( 'manage_woocommerce' ) ) {
wp_send_json_error( 'missing_capabilities' );
wp_die();
}
$changes = wp_unslash( $_POST['changes'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
foreach ( $changes as $zone_id => $data ) {
if ( isset( $data['deleted'] ) ) {
if ( isset( $data['newRow'] ) ) {
// So the user added and deleted a new row.
// That's fine, it's not in the database anyways. NEXT!
continue;
}
/**
* Notify that a non-option setting has been deleted.
*
* @since 7.8.0
*/
do_action(
'woocommerce_update_non_option_setting',
array(
'id' => 'shipping_zone',
'action' => 'delete',
)
);
WC_Shipping_Zones::delete_zone( $zone_id );
continue;
}
$zone_data = array_intersect_key(
$data,
array(
'zone_id' => 1,
'zone_order' => 1,
)
);
if ( isset( $zone_data['zone_id'] ) ) {
$zone = new WC_Shipping_Zone( $zone_data['zone_id'] );
if ( isset( $zone_data['zone_order'] ) ) {
/**
* Notify that a non-option setting has been updated.
*
* @since 7.8.0
*/
do_action(
'woocommerce_update_non_option_setting',
array(
'id' => 'zone_order',
)
);
$zone->set_zone_order( $zone_data['zone_order'] );
}
$zone->save();
}
}
global $current_tab;
$current_tab = 'shipping';
/**
* Completes the saving process for options.
*
* @since 7.8.0
*/
do_action( 'woocommerce_update_options' );
wp_send_json_success(
array(
'zones' => WC_Shipping_Zones::get_zones( 'json' ),
)
);
}
/**
* Handle submissions from assets/js/wc-shipping-zone-methods.js Backbone model.
*/
public static function shipping_zone_add_method() {
if ( ! isset( $_POST['wc_shipping_zones_nonce'], $_POST['zone_id'], $_POST['method_id'] ) ) {
wp_send_json_error( 'missing_fields' );
wp_die();
}
if ( ! wp_verify_nonce( wp_unslash( $_POST['wc_shipping_zones_nonce'] ), 'wc_shipping_zones_nonce' ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
wp_send_json_error( 'bad_nonce' );
wp_die();
}
// Check User Caps.
if ( ! current_user_can( 'manage_woocommerce' ) ) {
wp_send_json_error( 'missing_capabilities' );
wp_die();
}
$zone_id = wc_clean( wp_unslash( $_POST['zone_id'] ) );
$zone = new WC_Shipping_Zone( $zone_id );
// A shipping zone can be created here if the user is adding a method without first saving the shipping zone.
if ( '' === $zone_id ) {
/**
* Notified that a non-option setting has been added.
*
* @since 7.8.0
*/
do_action(
'woocommerce_update_non_option_setting',
array(
'id' => 'shipping_zone',
'action' => 'add',
)
);
}
/**
* Notify that a non-option setting has been added.
*
* @since 7.8.0
*/
do_action(
'woocommerce_update_non_option_setting',
array(
'id' => 'zone_method',
'action' => 'add',
)
);
$instance_id = $zone->add_shipping_method( wc_clean( wp_unslash( $_POST['method_id'] ) ) );
global $current_tab;
$current_tab = 'shipping';
/**
* Completes the saving process for options.
*
* @since 7.8.0
*/
do_action( 'woocommerce_update_options' );
wp_send_json_success(
array(
'instance_id' => $instance_id,
'zone_id' => $zone->get_id(),
'zone_name' => $zone->get_zone_name(),
'methods' => $zone->get_shipping_methods( false, 'json' ),
)
);
}
/**
* Handle submissions from assets/js/wc-shipping-zone-methods.js Backbone model.
*/
public static function shipping_zone_remove_method() {
if ( ! isset( $_POST['wc_shipping_zones_nonce'], $_POST['instance_id'], $_POST['zone_id'] ) ) {
wp_send_json_error( 'missing_fields' );
wp_die();
}
if ( ! wp_verify_nonce( wp_unslash( $_POST['wc_shipping_zones_nonce'] ), 'wc_shipping_zones_nonce' ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
wp_send_json_error( 'bad_nonce' );
wp_die();
}
// Check User Caps.
if ( ! current_user_can( 'manage_woocommerce' ) ) {
wp_send_json_error( 'missing_capabilities' );
wp_die();
}
$zone_id = wc_clean( wp_unslash( $_POST['zone_id'] ) );
$zone = new WC_Shipping_Zone( $zone_id );
$instance_id = wc_clean( wp_unslash( $_POST['instance_id'] ) );
/**
* Notify that a non-option setting has been updated.
*
* @since 7.8.0
*/
do_action(
'woocommerce_update_non_option_setting',
array(
'id' => $instance_id,
)
);
if ( ! $zone->delete_shipping_method( $instance_id ) ) {
wp_send_json_error( 'missing_shipping_method_instance_id' );
wp_die();
}
global $current_tab;
$current_tab = 'shipping';
/**
* Completes the saving process for options.
*
* @since 7.8.0
*/
do_action( 'woocommerce_update_options' );
wp_send_json_success(
array(
'instance_id' => $instance_id,
'methods' => $zone->get_shipping_methods( false, 'json' ),
)
);
}
/**
* Handle submissions from assets/js/wc-shipping-zone-methods.js Backbone model.
*/
public static function shipping_zone_methods_save_changes() {
if ( ! isset( $_POST['wc_shipping_zones_nonce'], $_POST['zone_id'], $_POST['changes'] ) ) {
wp_send_json_error( 'missing_fields' );
wp_die();
}
if ( ! wp_verify_nonce( wp_unslash( $_POST['wc_shipping_zones_nonce'] ), 'wc_shipping_zones_nonce' ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
wp_send_json_error( 'bad_nonce' );
wp_die();
}
if ( ! current_user_can( 'manage_woocommerce' ) ) {
wp_send_json_error( 'missing_capabilities' );
wp_die();
}
global $wpdb;
$zone_id = wc_clean( wp_unslash( $_POST['zone_id'] ) );
$zone = new WC_Shipping_Zone( $zone_id );
// A shipping zone can be created here if the user is adding a method without first saving the shipping zone.
if ( '' === $zone_id ) {
/**
* Notifies that a non-option setting has been added.
*
* @since 7.8.0
*/
do_action(
'woocommerce_update_non_option_setting',
array(
'id' => 'shipping_zone',
'action' => 'add',
)
);
}
$changes = wp_unslash( $_POST['changes'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
if ( isset( $changes['zone_name'] ) ) {
/**
* Notifies that a non-option setting has been updated.
*
* @since 7.8.0
*/
do_action( 'woocommerce_update_non_option_setting', array( 'id' => 'zone_name' ) );
$zone->set_zone_name( wc_clean( $changes['zone_name'] ) );
}
if ( isset( $changes['zone_locations'] ) ) {
/**
* Notifies that a non-option setting has been updated.
*
* @since 7.8.0
*/
do_action( 'woocommerce_update_non_option_setting', array( 'id' => 'zone_locations' ) );
$zone->clear_locations( array( 'state', 'country', 'continent' ) );
$locations = array_filter( array_map( 'wc_clean', (array) $changes['zone_locations'] ) );
foreach ( $locations as $location ) {
// Each posted location will be in the format type:code.
$location_parts = explode( ':', $location );
switch ( $location_parts[0] ) {
case 'state':
$zone->add_location( $location_parts[1] . ':' . $location_parts[2], 'state' );
break;
case 'country':
$zone->add_location( $location_parts[1], 'country' );
break;
case 'continent':
$zone->add_location( $location_parts[1], 'continent' );
break;
}
}
}
if ( isset( $changes['zone_postcodes'] ) ) {
/**
* Notifies that a non-option setting has been updated.
*
* @since 7.8.0
*/
do_action( 'woocommerce_update_non_option_setting', array( 'id' => 'zone_postcodes' ) );
$zone->clear_locations( 'postcode' );
$postcodes = array_filter( array_map( 'strtoupper', array_map( 'wc_clean', explode( "\n", $changes['zone_postcodes'] ) ) ) );
foreach ( $postcodes as $postcode ) {
$zone->add_location( $postcode, 'postcode' );
}
}
if ( isset( $changes['methods'] ) ) {
foreach ( $changes['methods'] as $instance_id => $data ) {
$method_id = $wpdb->get_var( $wpdb->prepare( "SELECT method_id FROM {$wpdb->prefix}woocommerce_shipping_zone_methods WHERE instance_id = %d", $instance_id ) );
if ( isset( $data['deleted'] ) ) {
$shipping_method = WC_Shipping_Zones::get_shipping_method( $instance_id );
$option_key = $shipping_method->get_instance_option_key();
if ( $wpdb->delete( "{$wpdb->prefix}woocommerce_shipping_zone_methods", array( 'instance_id' => $instance_id ) ) ) {
delete_option( $option_key );
/**
* Notifies that a non-option setting has been deleted.
*
* @since 7.8.0
*/
do_action(
'woocommerce_update_non_option_setting',
array(
'id' => 'zone_method',
'action' => 'delete',
)
);
do_action( 'woocommerce_shipping_zone_method_deleted', $instance_id, $method_id, $zone_id );
}
continue;
}
$method_data = array_intersect_key(
$data,
array(
'method_order' => 1,
'enabled' => 1,
)
);
if ( isset( $method_data['method_order'] ) ) {
/**
* Notifies that a non-option setting has been updated.
*
* @since 7.8.0
*/
do_action( 'woocommerce_update_non_option_setting', array( 'id' => 'zone_methods_order' ) );
$wpdb->update( "{$wpdb->prefix}woocommerce_shipping_zone_methods", array( 'method_order' => absint( $method_data['method_order'] ) ), array( 'instance_id' => absint( $instance_id ) ) );
}
if ( isset( $method_data['enabled'] ) ) {
/**
* Notifies that a non-option setting has been updated.
*
* @since 7.8.0
*/
do_action( 'woocommerce_update_non_option_setting', array( 'id' => 'zone_methods_enabled' ) );
$is_enabled = absint( 'yes' === $method_data['enabled'] );
if ( $wpdb->update( "{$wpdb->prefix}woocommerce_shipping_zone_methods", array( 'is_enabled' => $is_enabled ), array( 'instance_id' => absint( $instance_id ) ) ) ) {
do_action( 'woocommerce_shipping_zone_method_status_toggled', $instance_id, $method_id, $zone_id, $is_enabled );
}
}
}
}
$zone->save();
global $current_tab;
$current_tab = 'shipping';
/**
* Completes the saving process for options.
*
* @since 7.8.0
*/
do_action( 'woocommerce_update_options' );
wp_send_json_success(
array(
'zone_id' => $zone->get_id(),
'zone_name' => $zone->get_zone_name(),
'methods' => $zone->get_shipping_methods( false, 'json' ),
)
);
}
/**
* Save method settings
*/
public static function shipping_zone_methods_save_settings() {
if ( ! isset( $_POST['wc_shipping_zones_nonce'], $_POST['instance_id'], $_POST['data'] ) ) {
wp_send_json_error( 'missing_fields' );
wp_die();
}
if ( ! wp_verify_nonce( wp_unslash( $_POST['wc_shipping_zones_nonce'] ), 'wc_shipping_zones_nonce' ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
wp_send_json_error( 'bad_nonce' );
wp_die();
}
if ( ! current_user_can( 'manage_woocommerce' ) ) {
wp_send_json_error( 'missing_capabilities' );
wp_die();
}
$instance_id = absint( $_POST['instance_id'] );
$zone = WC_Shipping_Zones::get_zone_by( 'instance_id', $instance_id );
$shipping_method = WC_Shipping_Zones::get_shipping_method( $instance_id );
/**
* Notify that a non-option setting has been updated.
*
* @since 7.8.0
*/
do_action( 'woocommerce_update_non_option_setting', array( 'id' => 'zone_method_settings' ) );
$shipping_method->set_post_data( wp_unslash( $_POST['data'] ) ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
global $current_tab;
$current_tab = 'shipping';
/**
* Completes the saving process for options.
*
* @since 7.8.0
*/
do_action( 'woocommerce_update_options' );
$shipping_method->process_admin_options();
WC_Cache_Helper::get_transient_version( 'shipping', true );
wp_send_json_success(
array(
'zone_id' => $zone->get_id(),
'zone_name' => $zone->get_zone_name(),
'methods' => $zone->get_shipping_methods( false, 'json' ),
'errors' => $shipping_method->get_errors(),
)
);
}
/**
* Handle submissions from assets/js/wc-shipping-classes.js Backbone model.
*/
public static function shipping_classes_save_changes() {
if ( ! isset( $_POST['wc_shipping_classes_nonce'], $_POST['changes'] ) ) {
wp_send_json_error( 'missing_fields' );
wp_die();
}
if ( ! wp_verify_nonce( wp_unslash( $_POST['wc_shipping_classes_nonce'] ), 'wc_shipping_classes_nonce' ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
wp_send_json_error( 'bad_nonce' );
wp_die();
}
if ( ! current_user_can( 'manage_woocommerce' ) ) {
wp_send_json_error( 'missing_capabilities' );
wp_die();
}
$changes = wp_unslash( $_POST['changes'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
foreach ( $changes as $term_id => $data ) {
$term_id = absint( $term_id );
if ( isset( $data['deleted'] ) ) {
if ( isset( $data['newRow'] ) ) {
// So the user added and deleted a new row.
// That's fine, it's not in the database anyways. NEXT!
continue;
}
/**
* Notifies that a non-option setting has been deleted.
*
* @since 7.8.0
*/
do_action(
'woocommerce_update_non_option_setting',
array(
'id' => 'shipping_class',
'action' => 'delete',
)
);
wp_delete_term( $term_id, 'product_shipping_class' );
continue;
}
$update_args = array();
if ( isset( $data['name'] ) ) {
/**
* Notify that a non-option setting has been updated.
*
* @since 7.8.0
*/
do_action( 'woocommerce_update_non_option_setting', array( 'id' => 'shipping_class_name' ) );
$update_args['name'] = wc_clean( $data['name'] );
}
if ( isset( $data['slug'] ) ) {
/**
* Notify that a non-option setting has been updated.
*
* @since 7.8.0
*/
do_action( 'woocommerce_update_non_option_setting', array( 'id' => 'shipping_class_slug' ) );
$update_args['slug'] = wc_clean( $data['slug'] );
}
if ( isset( $data['description'] ) ) {
/**
* Notify that a non-option setting has been updated.
*
* @since 7.8.0
*/
do_action( 'woocommerce_update_non_option_setting', array( 'id' => 'shipping_class_description' ) );
$update_args['description'] = wc_clean( $data['description'] );
}
if ( isset( $data['newRow'] ) ) {
$update_args = array_filter( $update_args );
if ( empty( $update_args['name'] ) ) {
continue;
}
/**
* Notifies that a non-option setting has been added.
*
* @since 7.8.0
*/
do_action(
'woocommerce_update_non_option_setting',
array(
'id' => 'shipping_class',
'action' => 'add',
)
);
$inserted_term = wp_insert_term( $update_args['name'], 'product_shipping_class', $update_args );
$term_id = is_wp_error( $inserted_term ) ? 0 : $inserted_term['term_id'];
} else {
/**
* Notifies that a non-option setting has been updated.
*
* @since 7.8.0
*/
do_action( 'woocommerce_update_non_option_setting', array( 'id' => 'shipping_class' ) );
wp_update_term( $term_id, 'product_shipping_class', $update_args );
}
do_action( 'woocommerce_shipping_classes_save_class', $term_id, $data );
}
global $current_tab, $current_section;
$current_tab = 'shipping';
$current_section = 'classes';
/**
* Completes the saving process for options.
*
* @since 7.8.0
*/
do_action( 'woocommerce_update_options' );
$wc_shipping = WC_Shipping::instance();
wp_send_json_success(
array(
'shipping_classes' => $wc_shipping->get_shipping_classes(),
)
);
}
/**
* Toggle payment gateway on or off via AJAX.
*
* @since 3.4.0
*/
public static function toggle_gateway_enabled() {
if ( current_user_can( 'manage_woocommerce' ) && check_ajax_referer( 'woocommerce-toggle-payment-gateway-enabled', 'security' ) && isset( $_POST['gateway_id'] ) ) {
// Set current tab.
$referer = wp_get_referer();
if ( $referer ) {
global $current_tab;
parse_str( wp_parse_url( $referer, PHP_URL_QUERY ), $queries );
$current_tab = $queries['tab'] ?? '';
}
// Load gateways.
$payment_gateways = WC()->payment_gateways->payment_gateways();
// Get posted gateway.
$gateway_id = wc_clean( wp_unslash( $_POST['gateway_id'] ) );
foreach ( $payment_gateways as $gateway ) {
if ( ! in_array( $gateway_id, array( $gateway->id, sanitize_title( get_class( $gateway ) ) ), true ) ) {
continue;
}
$enabled = $gateway->get_option( 'enabled', 'no' );
$option = array(
'id' => $gateway->get_option_key(),
);
if ( ! wc_string_to_bool( $enabled ) ) {
if ( $gateway->needs_setup() ) {
wp_send_json_error( 'needs_setup' );
wp_die();
} else {
do_action( 'woocommerce_update_option', $option );
$gateway->update_option( 'enabled', 'yes' );
}
} else {
do_action( 'woocommerce_update_option', $option );
// Disable the gateway.
$gateway->update_option( 'enabled', 'no' );
}
do_action( 'woocommerce_update_options' );
wp_send_json_success( ! wc_string_to_bool( $enabled ) );
wp_die();
}
}
wp_send_json_error( 'invalid_gateway_id' );
wp_die();
}
/**
* Reimplementation of WP core's `wp_ajax_add_meta` method to support order custom meta updates with custom tables.
*/
private static function order_add_meta() {
wc_get_container()->get( CustomMetaBox::class )->add_meta_ajax();
}
/**
* Reimplementation of WP core's `wp_ajax_delete_meta` method to support order custom meta updates with custom tables.
*
* @return void
*/
private static function order_delete_meta() : void {
wc_get_container()->get( CustomMetaBox::class )->delete_meta_ajax();
}
/**
* Hooked to 'heartbeat_received' on the edit order page to refresh the lock on an order being edited by the current user.
*
* @param array $response The heartbeat response to be sent.
* @param array $data Data sent through the heartbeat.
* @return array Response to be sent.
*/
private static function order_refresh_lock( $response, $data ) {
return wc_get_container()->get( Automattic\WooCommerce\Internal\Admin\Orders\EditLock::class )->refresh_lock_ajax( $response, $data );
}
/**
* Hooked to 'heartbeat_received' on the orders screen to refresh the locked status of orders in the list table.
*
* @since 7.8.0
*
* @param array $response The heartbeat response to be sent.
* @param array $data Data sent through the heartbeat.
* @return array Response to be sent.
*/
private static function check_locked_orders( $response, $data ) {
return wc_get_container()->get( Automattic\WooCommerce\Internal\Admin\Orders\EditLock::class )->check_locked_orders_ajax( $response, $data );
}
}
WC_AJAX::init();