有没有办法将自定义代码添加到公共静态函数中?(wooccommerce update_order_review)



我在我的wooccommerce结账页面中添加了一个购物车段。现在我想用ajax更新购物车。(如果有人改变了他的国家…)

到目前为止,我已经尝试在";update_ checkout";但我遇到的问题是,我无法从ajax获取新数据。

唯一有效的方法是,当我编辑核心wooccommercepublic static function update_order_review()时。有没有什么方法可以用我的插件将我的代码添加到这个函数中?我需要添加:

// Get cart fragment. CUSTOM
ob_start();
woocommerce_order_cart();
$woocommerce_order_cart = ob_get_clean();

然后这个片段进入wp_send_json()函数:

wp_send_json(
array(
'result'    => empty( $messages ) ? 'success' : 'failure',
'messages'  => $messages,
'reload'    => $reload_checkout,
'fragments' => apply_filters(
'woocommerce_update_order_review_fragments',
array(
'.woocommerce-cart-form__contents' => $woocommerce_order_cart,/* CUSTOM */
'.woocommerce-checkout-review-order-table' => $woocommerce_order_review,
'.woocommerce-checkout-payment' => $woocommerce_checkout_payment,
)
),
)
);

这就是整个功能:

/**
* AJAX update order review on checkout.
*/
public static function update_order_review() {
check_ajax_referer( 'update-order-review', 'security' );
wc_maybe_define_constant( 'WOOCOMMERCE_CHECKOUT', true );
if ( WC()->cart->is_empty() && ! is_customize_preview() && apply_filters( 'woocommerce_checkout_update_order_review_expired', true ) ) {
self::update_order_review_expired();
}
do_action( 'woocommerce_checkout_update_order_review', isset( $_POST['post_data'] ) ? wp_unslash( $_POST['post_data'] ) : '' ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
$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 ) {
$chosen_shipping_methods[ $i ] = $value;
}
}
WC()->session->set( 'chosen_shipping_methods', $chosen_shipping_methods );
WC()->session->set( 'chosen_payment_method', empty( $_POST['payment_method'] ) ? '' : wc_clean( wp_unslash( $_POST['payment_method'] ) ) );
WC()->customer->set_props(
array(
'billing_country'   => isset( $_POST['country'] ) ? wc_clean( wp_unslash( $_POST['country'] ) ) : null,
'billing_state'     => isset( $_POST['state'] ) ? wc_clean( wp_unslash( $_POST['state'] ) ) : null,
'billing_postcode'  => isset( $_POST['postcode'] ) ? wc_clean( wp_unslash( $_POST['postcode'] ) ) : null,
'billing_city'      => isset( $_POST['city'] ) ? wc_clean( wp_unslash( $_POST['city'] ) ) : null,
'billing_address_1' => isset( $_POST['address'] ) ? wc_clean( wp_unslash( $_POST['address'] ) ) : null,
'billing_address_2' => isset( $_POST['address_2'] ) ? wc_clean( wp_unslash( $_POST['address_2'] ) ) : null,
)
);
if ( wc_ship_to_billing_address_only() ) {
WC()->customer->set_props(
array(
'shipping_country'   => isset( $_POST['country'] ) ? wc_clean( wp_unslash( $_POST['country'] ) ) : null,
'shipping_state'     => isset( $_POST['state'] ) ? wc_clean( wp_unslash( $_POST['state'] ) ) : null,
'shipping_postcode'  => isset( $_POST['postcode'] ) ? wc_clean( wp_unslash( $_POST['postcode'] ) ) : null,
'shipping_city'      => isset( $_POST['city'] ) ? wc_clean( wp_unslash( $_POST['city'] ) ) : null,
'shipping_address_1' => isset( $_POST['address'] ) ? wc_clean( wp_unslash( $_POST['address'] ) ) : null,
'shipping_address_2' => isset( $_POST['address_2'] ) ? wc_clean( wp_unslash( $_POST['address_2'] ) ) : null,
)
);
} else {
WC()->customer->set_props(
array(
'shipping_country'   => isset( $_POST['s_country'] ) ? wc_clean( wp_unslash( $_POST['s_country'] ) ) : null,
'shipping_state'     => isset( $_POST['s_state'] ) ? wc_clean( wp_unslash( $_POST['s_state'] ) ) : null,
'shipping_postcode'  => isset( $_POST['s_postcode'] ) ? wc_clean( wp_unslash( $_POST['s_postcode'] ) ) : null,
'shipping_city'      => isset( $_POST['s_city'] ) ? wc_clean( wp_unslash( $_POST['s_city'] ) ) : null,
'shipping_address_1' => isset( $_POST['s_address'] ) ? wc_clean( wp_unslash( $_POST['s_address'] ) ) : null,
'shipping_address_2' => isset( $_POST['s_address_2'] ) ? wc_clean( wp_unslash( $_POST['s_address_2'] ) ) : null,
)
);
}
if ( isset( $_POST['has_full_address'] ) && wc_string_to_bool( wc_clean( wp_unslash( $_POST['has_full_address'] ) ) ) ) {
WC()->customer->set_calculated_shipping( true );
} else {
WC()->customer->set_calculated_shipping( false );
}
WC()->customer->save();
// Calculate shipping before totals. This will ensure any shipping methods that affect things like taxes are chosen prior to final totals being calculated. Ref: #22708.
WC()->cart->calculate_shipping();
WC()->cart->calculate_totals();
// Get order review fragment.
ob_start();
woocommerce_order_review();
$woocommerce_order_review = ob_get_clean();
// Get cart fragment. CUSTOM
ob_start();
woocommerce_order_cart();
$woocommerce_order_cart = ob_get_clean();
// Get checkout payment fragment.
ob_start();
woocommerce_checkout_payment();
$woocommerce_checkout_payment = ob_get_clean();
// Get messages if reload checkout is not true.
$reload_checkout = isset( WC()->session->reload_checkout );
if ( ! $reload_checkout ) {
$messages = wc_print_notices( true );
} else {
$messages = '';
}
unset( WC()->session->refresh_totals, WC()->session->reload_checkout );
wp_send_json(
array(
'result'    => empty( $messages ) ? 'success' : 'failure',
'messages'  => $messages,
'reload'    => $reload_checkout,
'fragments' => apply_filters(
'woocommerce_update_order_review_fragments',
array(
'.woocommerce-cart-form__contents' => $woocommerce_order_cart,/* CUSTOM */
'.woocommerce-checkout-review-order-table' => $woocommerce_order_review,
'.woocommerce-checkout-payment' => $woocommerce_checkout_payment,
)
),
)
);
}

好了,我终于可以工作了。

首先,我创建了一个函数来调用我的购物车模板(这与订单审核模板基本相同)

if ( ! function_exists( 'woocommerce_order_cart' ) ) {
/**
* Output the Cart table for the checkout.
*
* @param bool $deprecated Deprecated param.
*/
function bb_order_cart( $deprecated = false ) {
include(plugin_dir_path( __FILE__ ).'assets/templates/woocommerce/cart/bb-cart-summary-ajax.php');
};
};

之后,我将我的购物车片段复制到该文件中。

<?php
/**
* BB Cart Summary
*
*
* @see https://docs.woocommerce.com/document/template-structure/
* @package WooCommerceTemplates
* @version 5.2.0
*/
defined( 'ABSPATH' ) || exit;
?> 
<table class="shop_table shop_table_responsive cart woocommerce-cart-form__contents" cellspacing="0">
<tbody>
<?php do_action( 'woocommerce_before_cart_contents' );
$i = 0;
foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
$_product   = apply_filters( 'woocommerce_cart_item_product', $cart_item['data'], $cart_item, $cart_item_key );
$product_id = apply_filters( 'woocommerce_cart_item_product_id', $cart_item['product_id'], $cart_item, $cart_item_key );
if ( $_product && $_product->exists() && $cart_item['quantity'] > 0 && apply_filters( 'woocommerce_cart_item_visible', true, $cart_item, $cart_item_key ) ) {
$product_permalink = apply_filters( 'woocommerce_cart_item_permalink', $_product->is_visible() ? $_product->get_permalink( $cart_item ) : '', $cart_item, $cart_item_key );
?>
<tr class="woocommerce-cart-form__cart-item <?php echo esc_attr( apply_filters( 'woocommerce_cart_item_class', 'cart_item', $cart_item, $cart_item_key ) ); ?>">
<td class="product-thumbnail">
<?php
$thumbnail = apply_filters( 'woocommerce_cart_item_thumbnail', $_product->get_image(), $cart_item, $cart_item_key );
if ( ! $product_permalink ) {
echo $thumbnail; // PHPCS: XSS ok.
} else {
printf( '<a href="%s">%s</a>', esc_url( $product_permalink ), $thumbnail ); // PHPCS: XSS ok.
};?>
<div class="item_quantity_container">
<?php echo $cart_item['quantity'];?>
</div>
</td>
<td class="product-name" data-title="<?php esc_attr_e( 'Product', 'woocommerce' ); ?>">
<?php
if ( ! $product_permalink ) {
echo wp_kses_post( apply_filters( 'woocommerce_cart_item_name', $_product->get_name(), $cart_item, $cart_item_key ) . '&nbsp;' );
} else {
echo wp_kses_post( apply_filters( 'woocommerce_cart_item_name', sprintf( '<a href="%s">%s</a>', esc_url( $product_permalink ), $_product->get_name() ), $cart_item, $cart_item_key ) );
}
$item_meta_bb = get_field( "wc_bb_prd_cart_input", $product_id );
?> <div class="prd_cart_item_meta"><?php
echo $item_meta_bb;
?></div><?php 
do_action( 'woocommerce_after_cart_item_name', $cart_item, $cart_item_key );
// Meta data.
echo wc_get_formatted_cart_item_data( $cart_item ); // PHPCS: XSS ok.
// Backorder notification.
if ( $_product->backorders_require_notification() && $_product->is_on_backorder( $cart_item['quantity'] ) ) {
echo wp_kses_post( apply_filters( 'woocommerce_cart_item_backorder_notification', '<p class="backorder_notification">' . esc_html__( 'Available on backorder', 'woocommerce' ) . '</p>', $product_id ) );
}
?>
</td>
<!-- 
<td class="product-price" data-title="<?php esc_attr_e( 'Price', 'woocommerce' ); ?>">
<?php
echo apply_filters( 'woocommerce_cart_item_price', WC()->cart->get_product_price( $_product ), $cart_item, $cart_item_key ); // PHPCS: XSS ok.
?>
</td> -->
<td class="product-subtotal" data-title="<?php esc_attr_e( 'Subtotal', 'woocommerce' ); ?>">
<?php
echo apply_filters( 'woocommerce_cart_item_subtotal', WC()->cart->get_product_subtotal( $_product, $cart_item['quantity'] ), $cart_item, $cart_item_key ); // PHPCS: XSS ok.
?>
</td>
</tr>
<?php
}
$i++; 
}
?>
<?php if ($i > '2'){?>
<style type="text/css">.cart_table {width: 102%;}</style><?php };?>

<?php do_action( 'woocommerce_cart_contents' ); ?>
<?php do_action( 'woocommerce_after_cart_contents' ); ?>
</tbody>
</table>

好吧。现在我可以在结账时运行购物车模板了。现在我们将讨论更困难的部分,ajax处理程序。

我创建了一个名为";refresh_cart.js"并对其进行初始化

function changeCart() {
if ( is_checkout() ) {
wp_enqueue_script( 'wc-update-checkout-cart', plugins_url( '/js/refresh_cart.js', __FILE__ ), array('jquery'), '', true);
wp_localize_script( 'wc-update-checkout-cart', 'refresh_cart',
array( 
'ajax_url' => admin_url( 'admin-ajax.php' ), 
) );
}  
}
add_action( 'wp_footer', 'changeCart', 10 );

我已将wc-js中的重要部分复制到该文件中。

/* global wc_checkout_params */
jQuery( function( $ ) {
// wc_checkout_params is required to continue, ensure the object exists
if ( typeof wc_checkout_params === 'undefined' ) {
return false;
}
$.blockUI.defaults.overlayCSS.cursor = 'default';
var wc_checkout_form = {
updateTimer: false,
dirtyInput: false,
selectedPaymentMethod: false,
xhr: false,
$order_review: $( '#order_review' ),
$checkout_form: $( 'form.checkout' ),
init: function() {
$( document.body ).on( 'update_checkout', this.update_checkout );
$( document.body ).on( 'init_checkout', this.init_checkout );

// Update on page load
if ( wc_checkout_params.is_checkout === '1' ) {
$( document.body ).trigger( 'init_checkout' );
}
if ( wc_checkout_params.option_guest_checkout === 'yes' ) {
$( 'input#createaccount' ).on( 'change', this.toggle_create_account ).trigger( 'change' );
}
},
reset_update_checkout_timer: function() {
clearTimeout( wc_checkout_form.updateTimer );
},
update_checkout: function( event, args ) {
// Small timeout to prevent multiple requests when several fields update at the same time
wc_checkout_form.reset_update_checkout_timer();
wc_checkout_form.updateTimer = setTimeout( wc_checkout_form.update_checkout_action, '5', args );
},
update_checkout_action: function( args ) {
if ( wc_checkout_form.xhr ) {
wc_checkout_form.xhr.abort();
}
if ( $( 'form.checkout' ).length === 0 ) {
return;
}
args = typeof args !== 'undefined' ? args : {
update_shipping_method: true
};
var data = {
post_data       : $( 'form.checkout' ).serialize()
};
$( '.woocommerce-checkout-payment, .woocommerce-checkout-review-order-table, .woocommerce-cart-form__contents' ).block({
message: null,
overlayCSS: {
background: '#fff',
opacity: 0.6
}
});

var country      = $( '#billing_country' ).val(),
state      = $( '#billing_state' ).val(),
postcode     = $( ':input#billing_postcode' ).val(),
city       = $( '#billing_city' ).val(),
address      = $( ':input#billing_address_1' ).val(),
address_2    = $( ':input#billing_address_2' ).val(),
s_country    = country,
s_state      = state,
s_postcode     = postcode,
s_city       = city,
s_address    = address,
s_address_2    = address_2,
$required_inputs = $( wc_checkout_form.$checkout_form ).find( '.address-field.validate-required:visible' ),
has_full_address = true;
if ( $required_inputs.length ) {
$required_inputs.each( function() {
if ( $( this ).find( ':input' ).val() === '' ) {
has_full_address = false;
}
});
}
if ( $( '#ship-to-different-address' ).find( 'input' ).is( ':checked' ) ) {
s_country    = $( '#shipping_country' ).val();
s_state      = $( '#shipping_state' ).val();
s_postcode     = $( ':input#shipping_postcode' ).val();
s_city       = $( '#shipping_city' ).val();
s_address    = $( ':input#shipping_address_1' ).val();
s_address_2    = $( ':input#shipping_address_2' ).val();
}
var data = {
action: 'bb_update_order_review',
security: wc_checkout_params.update_order_review_nonce,
country         : country,
state           : state,
postcode        : postcode,
city            : city,
address         : address,
address_2       : address_2,
s_country       : s_country,
s_state         : s_state,
s_postcode      : s_postcode,
s_city          : s_city,
s_address       : s_address,
s_address_2     : s_address_2,
has_full_address: has_full_address,
post_data       : $( 'form.checkout' ).serialize()
};

wc_checkout_form.xhr = $.ajax({
type: "POST",
url: wc_checkout_params.ajax_url,
data: data,
success:  function( data ) {
console.log(data);
// Always update the fragments
if ( data && data.fragments ) {
$.each( data.fragments, function ( key, value ) {
if ( ! wc_checkout_form.fragments || wc_checkout_form.fragments[ key ] !== value ) {
$( key ).replaceWith( value );
}
$( key ).unblock();
} );
wc_checkout_form.fragments = data.fragments;
}
// Fire updated_checkout event.
$( document.body ).trigger( 'updated_checkout', [ data ] );
}
});
},

};
wc_checkout_form.init();
});

现在,我们需要为我们在refresh_cart.js文件中调用的函数添加ajax操作。

add_action( 'wp_ajax_bb_update_order_review', 'bb_update_order_review' );
add_action( 'wp_ajax_nopriv_bb_update_order_review', 'bb_update_order_review' );

现在我们只需要重新创建public static function update_order_review()函数就可以工作了:

function bb_update_order_review() {
WC()->customer->set_props(
array(
'billing_country'   => isset( $_POST['country'] ) ? wc_clean( wp_unslash( $_POST['country'] ) ) : null,
)
);
if ( wc_ship_to_billing_address_only() ) {
WC()->customer->set_props(
array(
'shipping_country'   => isset( $_POST['country'] ) ? wc_clean( wp_unslash( $_POST['country'] ) ) : null,
)
);
} else {
WC()->customer->set_props(
array(
'shipping_country'   => isset( $_POST['s_country'] ) ? wc_clean( wp_unslash( $_POST['s_country'] ) ) : null,
)
);
}
WC()->customer->save();
// Calculate shipping before totals. This will ensure any shipping methods that affect things like taxes are chosen prior to final totals being calculated. Ref: #22708.
WC()->cart->calculate_shipping();
WC()->cart->calculate_totals();
// Get cart fragment. BEERBALLER
ob_start();
bb_order_cart();
$bb_order_cart = ob_get_clean();

/*    $reload_checkout = isset( WC()->session->reload_checkout );
WC()->session->reload_checkout;
unset( WC()->session->refresh_totals, WC()->session->reload_checkout );
*/
wp_send_json(
array(
'result'    => empty( $messages ) ? 'success' : 'failure',
'messages'  => $messages,
'reload'    => $reload_checkout,
'fragments' => apply_filters(
'woocommerce_update_order_review_fragments',
array(
'.woocommerce-cart-form__contents' => $bb_order_cart,/* BEERBALLER */
)
),
)
);
}

就是这样!

最新更新