If stock changes between page load and editing, reject stock changes

Fixes #15818
This commit is contained in:
Mike Jolley 2017-06-27 21:22:46 +01:00
parent be0fc10bfe
commit 1265633286
3 changed files with 30 additions and 4 deletions

View File

@ -310,6 +310,17 @@ class WC_Meta_Box_Product_Data {
$classname = WC_Product_Factory::get_product_classname( $post_id, $product_type ? $product_type : 'simple' ); $classname = WC_Product_Factory::get_product_classname( $post_id, $product_type ? $product_type : 'simple' );
$product = new $classname( $post_id ); $product = new $classname( $post_id );
$attributes = self::prepare_attributes(); $attributes = self::prepare_attributes();
$stock = null;
// Handle stock changes.
if ( isset( $_POST['_stock'] ) ) {
if ( isset( $_POST['_original_stock'] ) && wc_stock_amount( $product->get_stock_quantity( 'edit' ) ) !== wc_stock_amount( $_POST['_original_stock'] ) ) {
WC_Admin_Meta_Boxes::add_error( sprintf( __( 'The stock has not been updated because the value has changed since editing. Product %d has %d units in stock.', 'woocommerce' ), $product->get_id(), $product->get_stock_quantity( 'edit' ) ) );
} else {
$stock = wc_stock_amount( $_POST['_stock'] );
}
}
$errors = $product->set_props( array( $errors = $product->set_props( array(
'sku' => isset( $_POST['_sku'] ) ? wc_clean( $_POST['_sku'] ) : null, 'sku' => isset( $_POST['_sku'] ) ? wc_clean( $_POST['_sku'] ) : null,
'purchase_note' => wp_kses_post( stripslashes( $_POST['_purchase_note'] ) ), 'purchase_note' => wp_kses_post( stripslashes( $_POST['_purchase_note'] ) ),
@ -334,7 +345,7 @@ class WC_Meta_Box_Product_Data {
'manage_stock' => ! empty( $_POST['_manage_stock'] ), 'manage_stock' => ! empty( $_POST['_manage_stock'] ),
'backorders' => isset( $_POST['_backorders'] ) ? wc_clean( $_POST['_backorders'] ) : null, 'backorders' => isset( $_POST['_backorders'] ) ? wc_clean( $_POST['_backorders'] ) : null,
'stock_status' => wc_clean( $_POST['_stock_status'] ), 'stock_status' => wc_clean( $_POST['_stock_status'] ),
'stock_quantity' => isset( $_POST['_stock'] ) ? wc_stock_amount( $_POST['_stock'] ) : null, 'stock_quantity' => $stock,
'download_limit' => '' === $_POST['_download_limit'] ? '' : absint( $_POST['_download_limit'] ), 'download_limit' => '' === $_POST['_download_limit'] ? '' : absint( $_POST['_download_limit'] ),
'download_expiry' => '' === $_POST['_download_expiry'] ? '' : absint( $_POST['_download_expiry'] ), 'download_expiry' => '' === $_POST['_download_expiry'] ? '' : absint( $_POST['_download_expiry'] ),
'downloads' => self::prepare_downloads( 'downloads' => self::prepare_downloads(
@ -391,6 +402,17 @@ class WC_Meta_Box_Product_Data {
} }
$variation_id = absint( $_POST['variable_post_id'][ $i ] ); $variation_id = absint( $_POST['variable_post_id'][ $i ] );
$variation = new WC_Product_Variation( $variation_id ); $variation = new WC_Product_Variation( $variation_id );
$stock = null;
// Handle stock changes.
if ( isset( $_POST['variable_stock'], $_POST['variable_stock'][ $i ] ) ) {
if ( isset( $_POST['variable_original_stock'], $_POST['variable_original_stock'][ $i ] ) && wc_stock_amount( $variation->get_stock_quantity( 'edit' ) ) !== wc_stock_amount( $_POST['variable_original_stock'][ $i ] ) ) {
WC_Admin_Meta_Boxes::add_error( sprintf( __( 'The stock has not been updated because the value has changed since editing. Product %d has %d units in stock.', 'woocommerce' ), $variation->get_id(), $variation->get_stock_quantity( 'edit' ) ) );
} else {
$stock = wc_stock_amount( $_POST['variable_stock'][ $i ] );
}
}
$errors = $variation->set_props( array( $errors = $variation->set_props( array(
'status' => isset( $_POST['variable_enabled'][ $i ] ) ? 'publish' : 'private', 'status' => isset( $_POST['variable_enabled'][ $i ] ) ? 'publish' : 'private',
'menu_order' => wc_clean( $_POST['variation_menu_order'][ $i ] ), 'menu_order' => wc_clean( $_POST['variation_menu_order'][ $i ] ),
@ -409,7 +431,7 @@ class WC_Meta_Box_Product_Data {
isset( $_POST['_wc_variation_file_hashes'][ $variation_id ] ) ? $_POST['_wc_variation_file_hashes'][ $variation_id ] : array() isset( $_POST['_wc_variation_file_hashes'][ $variation_id ] ) ? $_POST['_wc_variation_file_hashes'][ $variation_id ] : array()
), ),
'manage_stock' => isset( $_POST['variable_manage_stock'][ $i ] ), 'manage_stock' => isset( $_POST['variable_manage_stock'][ $i ] ),
'stock_quantity' => isset( $_POST['variable_stock'], $_POST['variable_stock'][ $i ] ) ? wc_clean( $_POST['variable_stock'][ $i ] ) : null, 'stock_quantity' => $stock,
'backorders' => isset( $_POST['variable_backorders'], $_POST['variable_backorders'][ $i ] ) ? wc_clean( $_POST['variable_backorders'][ $i ] ) : null, 'backorders' => isset( $_POST['variable_backorders'], $_POST['variable_backorders'][ $i ] ) ? wc_clean( $_POST['variable_backorders'][ $i ] ) : null,
'stock_status' => wc_clean( $_POST['variable_stock_status'][ $i ] ), 'stock_status' => wc_clean( $_POST['variable_stock_status'][ $i ] ),
'image_id' => wc_clean( $_POST['upload_image_id'][ $i ] ), 'image_id' => wc_clean( $_POST['upload_image_id'][ $i ] ),

View File

@ -35,7 +35,7 @@ if ( ! defined( 'ABSPATH' ) ) {
woocommerce_wp_text_input( array( woocommerce_wp_text_input( array(
'id' => '_stock', 'id' => '_stock',
'value' => $product_object->get_stock_quantity( 'edit' ), 'value' => wc_stock_amount( $product_object->get_stock_quantity( 'edit' ) ),
'label' => __( 'Stock quantity', 'woocommerce' ), 'label' => __( 'Stock quantity', 'woocommerce' ),
'desc_tip' => true, 'desc_tip' => true,
'description' => __( 'Stock quantity. If this is a variable product this value will be used to control stock for all variations, unless you define stock at variation level.', 'woocommerce' ), 'description' => __( 'Stock quantity. If this is a variable product this value will be used to control stock for all variations, unless you define stock at variation level.', 'woocommerce' ),
@ -46,6 +46,8 @@ if ( ! defined( 'ABSPATH' ) ) {
'data_type' => 'stock', 'data_type' => 'stock',
) ); ) );
echo '<input type="hidden" name="_original_stock" value="' . esc_attr( wc_stock_amount( $product_object->get_stock_quantity( 'edit' ) ) ) . '" />';
woocommerce_wp_select( array( woocommerce_wp_select( array(
'id' => '_backorders', 'id' => '_backorders',
'value' => $product_object->get_backorders( 'edit' ), 'value' => $product_object->get_backorders( 'edit' ),

View File

@ -158,7 +158,7 @@ if ( ! defined( 'ABSPATH' ) ) {
woocommerce_wp_text_input( array( woocommerce_wp_text_input( array(
'id' => "variable_stock{$loop}", 'id' => "variable_stock{$loop}",
'name' => "variable_stock[{$loop}]", 'name' => "variable_stock[{$loop}]",
'value' => $variation_object->get_stock_quantity( 'edit' ), 'value' => wc_stock_amount( $variation_object->get_stock_quantity( 'edit' ) ),
'label' => __( 'Stock quantity', 'woocommerce' ), 'label' => __( 'Stock quantity', 'woocommerce' ),
'desc_tip' => true, 'desc_tip' => true,
'description' => __( "Enter a quantity to enable stock management at variation level, or leave blank to use the parent product's options.", 'woocommerce' ), 'description' => __( "Enter a quantity to enable stock management at variation level, or leave blank to use the parent product's options.", 'woocommerce' ),
@ -170,6 +170,8 @@ if ( ! defined( 'ABSPATH' ) ) {
'wrapper_class' => 'form-row form-row-first', 'wrapper_class' => 'form-row form-row-first',
) ); ) );
echo '<input type="hidden" name="variable_original_stock[' . $loop . ']" value="' . esc_attr( wc_stock_amount( $variation_object->get_stock_quantity( 'edit' ) ) ) . '" />';
woocommerce_wp_select( array( woocommerce_wp_select( array(
'id' => "variable_backorders{$loop}", 'id' => "variable_backorders{$loop}",
'name' => "variable_backorders[{$loop}]", 'name' => "variable_backorders[{$loop}]",