Revise the stock + stock status saving logic (#11858)
* use set_stock to reset stock meta when not managing stock Ensures that the 'woocommerce_{ variation | product }_set_stock' hooks fire to refllect the fact that stock becomes infinite. * track state of Manage Stock? option * quick/bulk edit fixes * reapply quick and bulk edit fixes * improve conditional reset logic that prevents actions from *_set_stock actions from firing with every save
This commit is contained in:
parent
a426004975
commit
4658245625
|
@ -257,9 +257,9 @@ class WC_Product {
|
||||||
* Uses queries rather than update_post_meta so we can do this in one query (to avoid stock issues).
|
* Uses queries rather than update_post_meta so we can do this in one query (to avoid stock issues).
|
||||||
* We cannot rely on the original loaded value in case another order was made since then.
|
* We cannot rely on the original loaded value in case another order was made since then.
|
||||||
*
|
*
|
||||||
* @param int $amount (default: null)
|
* @param int $amount (default: null)
|
||||||
* @param string $mode can be set, add, or subtract
|
* @param string $mode can be set, add, or subtract
|
||||||
* @return int new stock level
|
* @return int new stock level
|
||||||
*/
|
*/
|
||||||
public function set_stock( $amount = null, $mode = 'set' ) {
|
public function set_stock( $amount = null, $mode = 'set' ) {
|
||||||
global $wpdb;
|
global $wpdb;
|
||||||
|
@ -291,6 +291,14 @@ class WC_Product {
|
||||||
// Stock status
|
// Stock status
|
||||||
$this->check_stock_status();
|
$this->check_stock_status();
|
||||||
|
|
||||||
|
// Trigger action
|
||||||
|
do_action( 'woocommerce_product_set_stock', $this );
|
||||||
|
|
||||||
|
// If not managing stock and clearing the stock meta, trigger action to indicate that stock has changed (infinite stock)
|
||||||
|
} elseif ( '' === $amount && '' !== get_post_meta( $this->id, '_stock', true ) ) {
|
||||||
|
|
||||||
|
update_post_meta( $this->id, '_stock', '' );
|
||||||
|
|
||||||
// Trigger action
|
// Trigger action
|
||||||
do_action( 'woocommerce_product_set_stock', $this );
|
do_action( 'woocommerce_product_set_stock', $this );
|
||||||
}
|
}
|
||||||
|
|
|
@ -1148,11 +1148,20 @@ class WC_Admin_Post_Types {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle stock status
|
// Handle Stock Data
|
||||||
if ( isset( $_REQUEST['_stock_status'] ) ) {
|
$manage_stock = ! empty( $_REQUEST['_manage_stock'] ) && 'grouped' !== $product->product_type ? 'yes' : 'no';
|
||||||
$stock_status = wc_clean( $_REQUEST['_stock_status'] );
|
$backorders = ! empty( $_REQUEST['_backorders'] ) ? wc_clean( $_REQUEST['_backorders'] ) : 'no';
|
||||||
|
$stock_status = ! empty( $_REQUEST['_stock_status'] ) ? wc_clean( $_REQUEST['_stock_status'] ) : 'instock';
|
||||||
|
$stock_amount = 'yes' === $manage_stock ? wc_stock_amount( $_REQUEST['_stock'] ) : '';
|
||||||
|
|
||||||
if ( $product->is_type( 'variable' ) ) {
|
if ( 'yes' === get_option( 'woocommerce_manage_stock' ) ) {
|
||||||
|
|
||||||
|
// Apply product type constraints to stock status
|
||||||
|
if ( 'external' === $product->product_type ) {
|
||||||
|
// External always in stock
|
||||||
|
$stock_status = 'instock';
|
||||||
|
} elseif ( 'variable' === $product->product_type ) {
|
||||||
|
// Stock status is always determined by children
|
||||||
foreach ( $product->get_children() as $child_id ) {
|
foreach ( $product->get_children() as $child_id ) {
|
||||||
if ( 'yes' !== get_post_meta( $child_id, '_manage_stock', true ) ) {
|
if ( 'yes' !== get_post_meta( $child_id, '_manage_stock', true ) ) {
|
||||||
wc_update_product_stock_status( $child_id, $stock_status );
|
wc_update_product_stock_status( $child_id, $stock_status );
|
||||||
|
@ -1160,24 +1169,19 @@ class WC_Admin_Post_Types {
|
||||||
}
|
}
|
||||||
|
|
||||||
WC_Product_Variable::sync_stock_status( $post_id );
|
WC_Product_Variable::sync_stock_status( $post_id );
|
||||||
} else {
|
}
|
||||||
|
|
||||||
|
update_post_meta( $post_id, '_manage_stock', $manage_stock );
|
||||||
|
update_post_meta( $post_id, '_backorders', $backorders );
|
||||||
|
|
||||||
|
if ( 'variable' !== $product->product_type ) {
|
||||||
wc_update_product_stock_status( $post_id, $stock_status );
|
wc_update_product_stock_status( $post_id, $stock_status );
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Handle stock
|
wc_update_product_stock( $post_id, $stock_amount );
|
||||||
if ( ! $product->is_type( 'grouped' ) ) {
|
|
||||||
if ( isset( $_REQUEST['_manage_stock'] ) ) {
|
|
||||||
update_post_meta( $post_id, '_manage_stock', 'yes' );
|
|
||||||
wc_update_product_stock( $post_id, wc_stock_amount( $_REQUEST['_stock'] ) );
|
|
||||||
} else {
|
|
||||||
update_post_meta( $post_id, '_manage_stock', 'no' );
|
|
||||||
wc_update_product_stock( $post_id, 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( ! empty( $_REQUEST['_backorders'] ) ) {
|
} else {
|
||||||
update_post_meta( $post_id, '_backorders', wc_clean( $_REQUEST['_backorders'] ) );
|
wc_update_product_stock_status( $post_id, $stock_status );
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
do_action( 'woocommerce_product_quick_edit_save', $product );
|
do_action( 'woocommerce_product_quick_edit_save', $product );
|
||||||
|
@ -1222,22 +1226,6 @@ class WC_Admin_Post_Types {
|
||||||
update_post_meta( $post_id, '_tax_class', $tax_class );
|
update_post_meta( $post_id, '_tax_class', $tax_class );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ! empty( $_REQUEST['_stock_status'] ) ) {
|
|
||||||
$stock_status = wc_clean( $_REQUEST['_stock_status'] );
|
|
||||||
|
|
||||||
if ( $product->is_type( 'variable' ) ) {
|
|
||||||
foreach ( $product->get_children() as $child_id ) {
|
|
||||||
if ( 'yes' !== get_post_meta( $child_id, '_manage_stock', true ) ) {
|
|
||||||
wc_update_product_stock_status( $child_id, $stock_status );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
WC_Product_Variable::sync_stock_status( $post_id );
|
|
||||||
} else {
|
|
||||||
wc_update_product_stock_status( $post_id, $stock_status );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( ! empty( $_REQUEST['_shipping_class'] ) ) {
|
if ( ! empty( $_REQUEST['_shipping_class'] ) ) {
|
||||||
$shipping_class = '_no_shipping_class' == $_REQUEST['_shipping_class'] ? '' : wc_clean( $_REQUEST['_shipping_class'] );
|
$shipping_class = '_no_shipping_class' == $_REQUEST['_shipping_class'] ? '' : wc_clean( $_REQUEST['_shipping_class'] );
|
||||||
|
|
||||||
|
@ -1380,27 +1368,50 @@ class WC_Admin_Post_Types {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle stock
|
// Handle Stock Data
|
||||||
if ( ! $product->is_type( 'grouped' ) ) {
|
$was_managing_stock = get_post_meta( $post_id, '_manage_stock', true );
|
||||||
|
$stock_status = get_post_meta( $post_id, '_stock_status', true );
|
||||||
|
$backorders = get_post_meta( $post_id, '_stock_status', true );
|
||||||
|
|
||||||
if ( ! empty( $_REQUEST['change_stock'] ) ) {
|
$backorders = ! empty( $_REQUEST['_backorders'] ) ? wc_clean( $_REQUEST['_backorders'] ) : $backorders;
|
||||||
update_post_meta( $post_id, '_manage_stock', 'yes' );
|
$stock_status = ! empty( $_REQUEST['_stock_status'] ) ? wc_clean( $_REQUEST['_stock_status'] ) : $stock_status;
|
||||||
wc_update_product_stock( $post_id, wc_stock_amount( $_REQUEST['_stock'] ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( ! empty( $_REQUEST['_manage_stock'] ) ) {
|
if ( ! empty( $_REQUEST['_manage_stock'] ) ) {
|
||||||
|
$manage_stock = 'yes' === wc_clean( $_REQUEST['_manage_stock'] ) && 'grouped' !== $product->product_type ? 'yes' : 'no';
|
||||||
|
} else {
|
||||||
|
$manage_stock = $was_managing_stock;
|
||||||
|
}
|
||||||
|
|
||||||
if ( 'yes' === $_REQUEST['_manage_stock'] ) {
|
$stock_amount = 'yes' === $manage_stock && isset( $_REQUEST['_change_stock'] ) ? wc_stock_amount( $_REQUEST['_change_stock'] ) : '';
|
||||||
update_post_meta( $post_id, '_manage_stock', 'yes' );
|
|
||||||
} else {
|
if ( 'yes' === get_option( 'woocommerce_manage_stock' ) ) {
|
||||||
update_post_meta( $post_id, '_manage_stock', 'no' );
|
|
||||||
wc_update_product_stock( $post_id, 0 );
|
// Apply product type constraints to stock status
|
||||||
|
if ( 'external' === $product->product_type ) {
|
||||||
|
// External always in stock
|
||||||
|
$stock_status = 'instock';
|
||||||
|
} elseif ( 'variable' === $product->product_type ) {
|
||||||
|
// Stock status is always determined by children
|
||||||
|
foreach ( $product->get_children() as $child_id ) {
|
||||||
|
if ( 'yes' !== get_post_meta( $child_id, '_manage_stock', true ) ) {
|
||||||
|
wc_update_product_stock_status( $child_id, $stock_status );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WC_Product_Variable::sync_stock_status( $post_id );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ! empty( $_REQUEST['_backorders'] ) ) {
|
update_post_meta( $post_id, '_manage_stock', $manage_stock );
|
||||||
update_post_meta( $post_id, '_backorders', wc_clean( $_REQUEST['_backorders'] ) );
|
update_post_meta( $post_id, '_backorders', $backorders );
|
||||||
|
|
||||||
|
if ( 'variable' !== $product->product_type ) {
|
||||||
|
wc_update_product_stock_status( $post_id, $stock_status );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wc_update_product_stock( $post_id, $stock_amount );
|
||||||
|
|
||||||
|
} else {
|
||||||
|
wc_update_product_stock_status( $post_id, $stock_status );
|
||||||
}
|
}
|
||||||
|
|
||||||
do_action( 'woocommerce_product_bulk_edit_save', $product );
|
do_action( 'woocommerce_product_bulk_edit_save', $product );
|
||||||
|
|
|
@ -1103,28 +1103,20 @@ class WC_Meta_Box_Product_Data {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stock Data
|
// Stock Data
|
||||||
|
$manage_stock = ! empty( $_POST['_manage_stock'] ) && 'grouped' !== $product_type ? 'yes' : 'no';
|
||||||
|
$backorders = ! empty( $_POST['_backorders'] ) && 'yes' === $manage_stock ? wc_clean( $_POST['_backorders'] ) : 'no';
|
||||||
|
$stock_status = ! empty( $_POST['_stock_status'] ) ? wc_clean( $_POST['_stock_status'] ) : 'instock';
|
||||||
|
$stock_amount = 'yes' === $manage_stock ? wc_stock_amount( $_POST['_stock'] ) : '';
|
||||||
|
|
||||||
if ( 'yes' === get_option( 'woocommerce_manage_stock' ) ) {
|
if ( 'yes' === get_option( 'woocommerce_manage_stock' ) ) {
|
||||||
|
|
||||||
$manage_stock = 'no';
|
// Apply product type constraints to stock status
|
||||||
$backorders = 'no';
|
|
||||||
$stock_status = wc_clean( $_POST['_stock_status'] );
|
|
||||||
|
|
||||||
if ( 'external' === $product_type ) {
|
if ( 'external' === $product_type ) {
|
||||||
|
// External always in stock
|
||||||
$stock_status = 'instock';
|
$stock_status = 'instock';
|
||||||
|
|
||||||
} elseif ( 'variable' === $product_type ) {
|
} elseif ( 'variable' === $product_type ) {
|
||||||
|
|
||||||
// Stock status is always determined by children so sync later
|
// Stock status is always determined by children so sync later
|
||||||
$stock_status = '';
|
$stock_status = '';
|
||||||
|
|
||||||
if ( ! empty( $_POST['_manage_stock'] ) ) {
|
|
||||||
$manage_stock = 'yes';
|
|
||||||
$backorders = wc_clean( $_POST['_backorders'] );
|
|
||||||
}
|
|
||||||
} elseif ( 'grouped' !== $product_type && ! empty( $_POST['_manage_stock'] ) ) {
|
|
||||||
$manage_stock = 'yes';
|
|
||||||
$backorders = wc_clean( $_POST['_backorders'] );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
update_post_meta( $post_id, '_manage_stock', $manage_stock );
|
update_post_meta( $post_id, '_manage_stock', $manage_stock );
|
||||||
|
@ -1134,13 +1126,10 @@ class WC_Meta_Box_Product_Data {
|
||||||
wc_update_product_stock_status( $post_id, $stock_status );
|
wc_update_product_stock_status( $post_id, $stock_status );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ! empty( $_POST['_manage_stock'] ) ) {
|
wc_update_product_stock( $post_id, $stock_amount );
|
||||||
wc_update_product_stock( $post_id, wc_stock_amount( $_POST['_stock'] ) );
|
|
||||||
} else {
|
} else {
|
||||||
update_post_meta( $post_id, '_stock', '' );
|
wc_update_product_stock_status( $post_id, $stock_status );
|
||||||
}
|
|
||||||
} elseif ( 'variable' !== $product_type ) {
|
|
||||||
wc_update_product_stock_status( $post_id, wc_clean( $_POST['_stock_status'] ) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cross sells and upsells
|
// Cross sells and upsells
|
||||||
|
@ -1411,7 +1400,7 @@ class WC_Meta_Box_Product_Data {
|
||||||
wc_update_product_stock( $variation_id, wc_stock_amount( $variable_stock[ $i ] ) );
|
wc_update_product_stock( $variation_id, wc_stock_amount( $variable_stock[ $i ] ) );
|
||||||
} else {
|
} else {
|
||||||
delete_post_meta( $variation_id, '_backorders' );
|
delete_post_meta( $variation_id, '_backorders' );
|
||||||
delete_post_meta( $variation_id, '_stock' );
|
wc_update_product_stock( $variation_id, '' );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only update stock status to user setting if changed by the user, but do so before looking at stock levels at variation level
|
// Only update stock status to user setting if changed by the user, but do so before looking at stock levels at variation level
|
||||||
|
|
|
@ -1208,8 +1208,8 @@ class WC_REST_Products_Controller extends WC_REST_Posts_Controller {
|
||||||
// Don't manage stock.
|
// Don't manage stock.
|
||||||
update_post_meta( $product->id, '_manage_stock', 'no' );
|
update_post_meta( $product->id, '_manage_stock', 'no' );
|
||||||
update_post_meta( $product->id, '_backorders', $backorders );
|
update_post_meta( $product->id, '_backorders', $backorders );
|
||||||
update_post_meta( $product->id, '_stock', '' );
|
|
||||||
|
|
||||||
|
wc_update_product_stock( $product->id, '' );
|
||||||
wc_update_product_stock_status( $product->id, $stock_status );
|
wc_update_product_stock_status( $product->id, $stock_status );
|
||||||
}
|
}
|
||||||
} elseif ( 'variable' !== $product_type ) {
|
} elseif ( 'variable' !== $product_type ) {
|
||||||
|
@ -1482,7 +1482,7 @@ class WC_REST_Products_Controller extends WC_REST_Posts_Controller {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
delete_post_meta( $variation_id, '_backorders' );
|
delete_post_meta( $variation_id, '_backorders' );
|
||||||
delete_post_meta( $variation_id, '_stock' );
|
wc_update_product_stock( $variation_id, '' );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Regular Price.
|
// Regular Price.
|
||||||
|
|
|
@ -437,9 +437,9 @@ class WC_Product_Variation extends WC_Product {
|
||||||
* Uses queries rather than update_post_meta so we can do this in one query (to avoid stock issues).
|
* Uses queries rather than update_post_meta so we can do this in one query (to avoid stock issues).
|
||||||
* We cannot rely on the original loaded value in case another order was made since then.
|
* We cannot rely on the original loaded value in case another order was made since then.
|
||||||
*
|
*
|
||||||
* @param int $amount
|
* @param int $amount
|
||||||
* @param string $mode can be set, add, or subtract
|
* @param string $mode can be set, add, or subtract
|
||||||
* @return int new stock level
|
* @return int new stock level
|
||||||
*/
|
*/
|
||||||
public function set_stock( $amount = null, $mode = 'set' ) {
|
public function set_stock( $amount = null, $mode = 'set' ) {
|
||||||
global $wpdb;
|
global $wpdb;
|
||||||
|
@ -477,6 +477,17 @@ class WC_Product_Variation extends WC_Product {
|
||||||
// Trigger action
|
// Trigger action
|
||||||
do_action( 'woocommerce_variation_set_stock', $this );
|
do_action( 'woocommerce_variation_set_stock', $this );
|
||||||
|
|
||||||
|
// If not managing stock and clearing the stock meta, trigger action to indicate that stock has changed (infinite stock)
|
||||||
|
} elseif ( '' === $amount ) {
|
||||||
|
|
||||||
|
if ( false !== get_post_meta( $this->variation_id, '_stock' ) ) {
|
||||||
|
|
||||||
|
delete_post_meta( $this->variation_id, '_stock' );
|
||||||
|
// Trigger action
|
||||||
|
do_action( 'woocommerce_variation_set_stock', $this );
|
||||||
|
}
|
||||||
|
|
||||||
|
// If not managing stock and setting stock, apply changes to the parent
|
||||||
} elseif ( ! is_null( $amount ) ) {
|
} elseif ( ! is_null( $amount ) ) {
|
||||||
return $this->parent->set_stock( $amount, $mode );
|
return $this->parent->set_stock( $amount, $mode );
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue