Rather than have hooks *everywhere* use a single set stock function in admin and on the frontend Closes #3593

This commit is contained in:
Mike Jolley 2013-08-13 16:56:09 +01:00
parent 8db53a8d9d
commit d021980c10
6 changed files with 120 additions and 208 deletions

View File

@ -151,26 +151,33 @@ class WC_Product {
/** /**
* Set stock level of the product. * Set stock level of the product.
* *
* @access public
* @param mixed $amount (default: null) * @param mixed $amount (default: null)
* @return int Stock * @return int Stock
*/ */
public function set_stock( $amount = null ) { public function set_stock( $amount = null ) {
global $woocommerce; if ( is_null( $amount ) )
return;
if ( $this->managing_stock() && ! is_null( $amount ) ) { if ( $this->managing_stock() ) {
// Update stock amount
$this->stock = intval( $amount ); $this->stock = intval( $amount );
// Update meta
update_post_meta( $this->id, '_stock', $this->stock ); update_post_meta( $this->id, '_stock', $this->stock );
do_action( 'woocommerce_product_set_stock', $this ); // Update stock status
// Out of stock attribute
if ( ! $this->backorders_allowed() && $this->get_total_stock() <= 0 ) if ( ! $this->backorders_allowed() && $this->get_total_stock() <= 0 )
$this->set_stock_status( 'outofstock' ); $this->set_stock_status( 'outofstock' );
elseif ( $this->backorders_allowed() || $this->get_total_stock() > 0 ) elseif ( $this->backorders_allowed() || $this->get_total_stock() > 0 )
$this->set_stock_status( 'instock' ); $this->set_stock_status( 'instock' );
wc_delete_product_transients( $this->id ); // Clear transient // Clear total stock transient
delete_transient( 'wc_product_total_stock_' . $this->id );
// Trigger action
do_action( 'woocommerce_product_set_stock', $this );
return $this->get_stock_quantity(); return $this->get_stock_quantity();
} }
@ -179,53 +186,21 @@ class WC_Product {
/** /**
* Reduce stock level of the product. * Reduce stock level of the product.
* *
* @access public
* @param int $by (default: 1) Amount to reduce by. * @param int $by (default: 1) Amount to reduce by.
* @return int Stock * @return int Stock
*/ */
public function reduce_stock( $by = 1 ) { public function reduce_stock( $by = 1 ) {
global $woocommerce; return $this->set_stock( $this->stock - $by );
if ( $this->managing_stock() ) {
$this->stock = $this->stock - $by;
update_post_meta( $this->id, '_stock', $this->stock );
do_action( 'woocommerce_product_reduce_stock', $this, $by );
// Out of stock attribute
if ( ! $this->backorders_allowed() && $this->get_total_stock() <= 0 )
$this->set_stock_status( 'outofstock' );
wc_delete_product_transients( $this->id ); // Clear transient
return $this->get_stock_quantity();
}
} }
/** /**
* Increase stock level of the product. * Increase stock level of the product.
* *
* @access public
* @param int $by (default: 1) Amount to increase by * @param int $by (default: 1) Amount to increase by
* @return int Stock * @return int Stock
*/ */
public function increase_stock( $by = 1 ) { public function increase_stock( $by = 1 ) {
global $woocommerce; return $this->set_stock( $this->stock + $by );
if ( $this->managing_stock() ) {
$this->stock = $this->stock + $by;
update_post_meta( $this->id, '_stock', $this->stock );
do_action( 'woocommerce_product_increase_stock', $this, $by );
// Out of stock attribute
if ( $this->backorders_allowed() || $this->get_total_stock() > 0 )
$this->set_stock_status( 'instock' );
wc_delete_product_transients( $this->id ); // Clear transient
return $this->get_stock_quantity();
}
} }
/** /**

View File

@ -151,7 +151,7 @@ class WC_Admin_CPT_Product extends WC_Admin_CPT {
if ( isset( $_POST['_visibility'] ) ) if ( isset( $_POST['_visibility'] ) )
update_post_meta( $post_id, '_visibility', stripslashes( $_POST['_visibility'] ) ); update_post_meta( $post_id, '_visibility', stripslashes( $_POST['_visibility'] ) );
if ( isset( $_POST['_stock_status'] ) ) if ( isset( $_POST['_stock_status'] ) )
update_post_meta( $post_id, '_stock_status', stripslashes( $_POST['_stock_status'] ) ); wc_update_product_stock_status( $post_id, woocommerce_clean( $_POST['_stock_status'] ) );
} }
/** /**
@ -683,7 +683,6 @@ class WC_Admin_CPT_Product extends WC_Admin_CPT {
if ( isset( $_REQUEST['_length'] ) ) update_post_meta( $post_id, '_length', woocommerce_clean( $_REQUEST['_length'] ) ); if ( isset( $_REQUEST['_length'] ) ) update_post_meta( $post_id, '_length', woocommerce_clean( $_REQUEST['_length'] ) );
if ( isset( $_REQUEST['_width'] ) ) update_post_meta( $post_id, '_width', woocommerce_clean( $_REQUEST['_width'] ) ); if ( isset( $_REQUEST['_width'] ) ) update_post_meta( $post_id, '_width', woocommerce_clean( $_REQUEST['_width'] ) );
if ( isset( $_REQUEST['_height'] ) ) update_post_meta( $post_id, '_height', woocommerce_clean( $_REQUEST['_height'] ) ); if ( isset( $_REQUEST['_height'] ) ) update_post_meta( $post_id, '_height', woocommerce_clean( $_REQUEST['_height'] ) );
if ( isset( $_REQUEST['_stock_status'] ) ) update_post_meta( $post_id, '_stock_status', woocommerce_clean( $_REQUEST['_stock_status'] ) );
if ( isset( $_REQUEST['_visibility'] ) ) update_post_meta( $post_id, '_visibility', woocommerce_clean( $_REQUEST['_visibility'] ) ); if ( isset( $_REQUEST['_visibility'] ) ) update_post_meta( $post_id, '_visibility', woocommerce_clean( $_REQUEST['_visibility'] ) );
if ( isset( $_REQUEST['_featured'] ) ) update_post_meta( $post_id, '_featured', 'yes' ); else update_post_meta( $post_id, '_featured', 'no' ); if ( isset( $_REQUEST['_featured'] ) ) update_post_meta( $post_id, '_featured', 'yes' ); else update_post_meta( $post_id, '_featured', 'no' );
@ -716,14 +715,18 @@ class WC_Admin_CPT_Product extends WC_Admin_CPT {
} }
} }
// Handle stock status
if ( isset( $_REQUEST['_stock_status'] ) )
wc_update_product_stock_status( $post_id, woocommerce_clean( $_REQUEST['_stock_status'] ) );
// Handle stock // Handle stock
if ( ! $product->is_type('grouped') ) { if ( ! $product->is_type('grouped') ) {
if ( isset( $_REQUEST['_manage_stock'] ) ) { if ( isset( $_REQUEST['_manage_stock'] ) ) {
update_post_meta( $post_id, '_manage_stock', 'yes' ); update_post_meta( $post_id, '_manage_stock', 'yes' );
update_post_meta( $post_id, '_stock', (int) $_REQUEST['_stock'] ); wc_update_product_stock( $post_id, intval( $_REQUEST['_stock'] ) );
} else { } else {
update_post_meta( $post_id, '_manage_stock', 'no' ); update_post_meta( $post_id, '_manage_stock', 'no' );
update_post_meta( $post_id, '_stock', '0' ); wc_update_product_stock( $post_id, 0 );
} }
} }
@ -762,7 +765,7 @@ class WC_Admin_CPT_Product extends WC_Admin_CPT {
} }
if ( ! empty( $_REQUEST['_stock_status'] ) ) if ( ! empty( $_REQUEST['_stock_status'] ) )
update_post_meta( $post_id, '_stock_status', stripslashes( $_REQUEST['_stock_status'] ) ); wc_update_product_stock_status( $post_id, woocommerce_clean( $_REQUEST['_stock_status'] ) );
if ( ! empty( $_REQUEST['_visibility'] ) ) if ( ! empty( $_REQUEST['_visibility'] ) )
update_post_meta( $post_id, '_visibility', stripslashes( $_REQUEST['_visibility'] ) ); update_post_meta( $post_id, '_visibility', stripslashes( $_REQUEST['_visibility'] ) );
@ -872,8 +875,8 @@ class WC_Admin_CPT_Product extends WC_Admin_CPT {
if ( ! $product->is_type( 'grouped' ) ) { if ( ! $product->is_type( 'grouped' ) ) {
if ( ! empty( $_REQUEST['change_stock'] ) ) { if ( ! empty( $_REQUEST['change_stock'] ) ) {
update_post_meta( $post_id, '_stock', (int) $_REQUEST['_stock'] );
update_post_meta( $post_id, '_manage_stock', 'yes' ); update_post_meta( $post_id, '_manage_stock', 'yes' );
wc_update_product_stock( $post_id, intval( $_REQUEST['_stock'] ) );
} }
if ( ! empty( $_REQUEST['_manage_stock'] ) ) { if ( ! empty( $_REQUEST['_manage_stock'] ) ) {
@ -882,7 +885,7 @@ class WC_Admin_CPT_Product extends WC_Admin_CPT {
update_post_meta( $post_id, '_manage_stock', 'yes' ); update_post_meta( $post_id, '_manage_stock', 'yes' );
} else { } else {
update_post_meta( $post_id, '_manage_stock', 'no' ); update_post_meta( $post_id, '_manage_stock', 'no' );
update_post_meta( $post_id, '_stock', '0' ); wc_update_product_stock( $post_id, 0 );
} }
} }

View File

@ -1148,44 +1148,40 @@ class WC_Meta_Box_Product_Data {
if ( $product_type == 'grouped' ) { if ( $product_type == 'grouped' ) {
update_post_meta( $post_id, '_stock_status', stripslashes( $_POST['_stock_status'] ) );
update_post_meta( $post_id, '_stock', '' );
update_post_meta( $post_id, '_manage_stock', 'no' ); update_post_meta( $post_id, '_manage_stock', 'no' );
update_post_meta( $post_id, '_backorders', 'no' ); update_post_meta( $post_id, '_backorders', 'no' );
update_post_meta( $post_id, '_stock', '' );
wc_update_product_stock_status( $post_id, woocommerce_clean( $_POST['_stock_status'] ) );
} elseif ( $product_type == 'external' ) { } elseif ( $product_type == 'external' ) {
update_post_meta( $post_id, '_stock_status', 'instock' );
update_post_meta( $post_id, '_stock', '' );
update_post_meta( $post_id, '_manage_stock', 'no' ); update_post_meta( $post_id, '_manage_stock', 'no' );
update_post_meta( $post_id, '_backorders', 'no' ); update_post_meta( $post_id, '_backorders', 'no' );
update_post_meta( $post_id, '_stock', '' );
wc_update_product_stock_status( $post_id, 'instock' );
} elseif ( ! empty( $_POST['_manage_stock'] ) ) { } elseif ( ! empty( $_POST['_manage_stock'] ) ) {
// Manage stock
update_post_meta( $post_id, '_stock', (int) $_POST['_stock'] );
update_post_meta( $post_id, '_stock_status', stripslashes( $_POST['_stock_status'] ) );
update_post_meta( $post_id, '_backorders', stripslashes( $_POST['_backorders'] ) );
update_post_meta( $post_id, '_manage_stock', 'yes' ); update_post_meta( $post_id, '_manage_stock', 'yes' );
update_post_meta( $post_id, '_backorders', woocommerce_clean( $_POST['_backorders'] ) );
// Check stock level wc_update_product_stock_status( $post_id, woocommerce_clean( $_POST['_stock_status'] ) );
if ( $product_type !== 'variable' && $_POST['_backorders'] == 'no' && (int) $_POST['_stock'] < 1 ) wc_update_product_stock( $post_id, intval( $_POST['_stock'] ) );
update_post_meta( $post_id, '_stock_status', 'outofstock' );
} else { } else {
// Don't manage stock // Don't manage stock
update_post_meta( $post_id, '_stock', '' );
update_post_meta( $post_id, '_stock_status', stripslashes( $_POST['_stock_status'] ) );
update_post_meta( $post_id, '_backorders', stripslashes( $_POST['_backorders'] ) );
update_post_meta( $post_id, '_manage_stock', 'no' ); update_post_meta( $post_id, '_manage_stock', 'no' );
update_post_meta( $post_id, '_backorders', woocommerce_clean( $_POST['_backorders'] ) );
update_post_meta( $post_id, '_stock', '' );
wc_update_product_stock_status( $post_id, woocommerce_clean( $_POST['_stock_status'] ) );
} }
} else { } else {
wc_update_product_stock_status( $post_id, woocommerce_clean( $_POST['_stock_status'] ) );
update_post_meta( $post_id, '_stock_status', stripslashes( $_POST['_stock_status'] ) );
} }
// Upsells // Upsells
@ -1274,6 +1270,8 @@ class WC_Meta_Box_Product_Data {
public static function save_variations( $post_id, $post ) { public static function save_variations( $post_id, $post ) {
global $woocommerce, $wpdb; global $woocommerce, $wpdb;
$attributes = (array) maybe_unserialize( get_post_meta( $post_id, '_product_attributes', true ) );
if ( isset( $_POST['variable_sku'] ) ) { if ( isset( $_POST['variable_sku'] ) ) {
$variable_post_id = $_POST['variable_post_id']; $variable_post_id = $_POST['variable_post_id'];
@ -1299,8 +1297,6 @@ class WC_Meta_Box_Product_Data {
$variable_is_virtual = isset( $_POST['variable_is_virtual'] ) ? $_POST['variable_is_virtual'] : array(); $variable_is_virtual = isset( $_POST['variable_is_virtual'] ) ? $_POST['variable_is_virtual'] : array();
$variable_is_downloadable = isset( $_POST['variable_is_downloadable'] ) ? $_POST['variable_is_downloadable'] : array(); $variable_is_downloadable = isset( $_POST['variable_is_downloadable'] ) ? $_POST['variable_is_downloadable'] : array();
$attributes = (array) maybe_unserialize( get_post_meta( $post_id, '_product_attributes', true ) );
$max_loop = max( array_keys( $_POST['variable_post_id'] ) ); $max_loop = max( array_keys( $_POST['variable_post_id'] ) );
for ( $i = 0; $i <= $max_loop; $i ++ ) { for ( $i = 0; $i <= $max_loop; $i ++ ) {
@ -1348,17 +1344,16 @@ class WC_Meta_Box_Product_Data {
// Update post meta // Update post meta
update_post_meta( $variation_id, '_sku', woocommerce_clean( $variable_sku[ $i ] ) ); update_post_meta( $variation_id, '_sku', woocommerce_clean( $variable_sku[ $i ] ) );
update_post_meta( $variation_id, '_weight', woocommerce_clean( $variable_weight[ $i ] ) ); update_post_meta( $variation_id, '_weight', woocommerce_clean( $variable_weight[ $i ] ) );
update_post_meta( $variation_id, '_length', woocommerce_clean( $variable_length[ $i ] ) ); update_post_meta( $variation_id, '_length', woocommerce_clean( $variable_length[ $i ] ) );
update_post_meta( $variation_id, '_width', woocommerce_clean( $variable_width[ $i ] ) ); update_post_meta( $variation_id, '_width', woocommerce_clean( $variable_width[ $i ] ) );
update_post_meta( $variation_id, '_height', woocommerce_clean( $variable_height[ $i ] ) ); update_post_meta( $variation_id, '_height', woocommerce_clean( $variable_height[ $i ] ) );
update_post_meta( $variation_id, '_stock', woocommerce_clean( $variable_stock[ $i ] ) );
update_post_meta( $variation_id, '_thumbnail_id', absint( $upload_image_id[ $i ] ) ); update_post_meta( $variation_id, '_thumbnail_id', absint( $upload_image_id[ $i ] ) );
update_post_meta( $variation_id, '_virtual', woocommerce_clean( $is_virtual ) ); update_post_meta( $variation_id, '_virtual', woocommerce_clean( $is_virtual ) );
update_post_meta( $variation_id, '_downloadable', woocommerce_clean( $is_downloadable ) ); update_post_meta( $variation_id, '_downloadable', woocommerce_clean( $is_downloadable ) );
// Stock handling
wc_update_product_stock( $variation_id, woocommerce_clean( $variable_stock[ $i ] ) );
// Price handling // Price handling
$regular_price = woocommerce_clean( $variable_regular_price[ $i ] ); $regular_price = woocommerce_clean( $variable_regular_price[ $i ] );
$sale_price = woocommerce_clean( $variable_sale_price[ $i ] ); $sale_price = woocommerce_clean( $variable_sale_price[ $i ] );

View File

@ -68,82 +68,16 @@ class WC_Product_Variable extends WC_Product {
/** /**
* Set stock level of the product. * Set stock level of the product.
* *
* @access public
* @param mixed $amount (default: null) * @param mixed $amount (default: null)
* @return int Stock * @return int Stock
*/ */
function set_stock( $amount = null ) { function set_stock( $amount = null ) {
global $woocommerce; // Empty total stock so its refreshed
$this->total_stock = '';
if ( $this->managing_stock() && ! is_null( $amount ) ) { // Call parent set_stock
return parent::set_stock( $amount );
$this->stock = intval( $amount );
$this->total_stock = intval( $amount );
update_post_meta( $this->id, '_stock', $this->stock );
// Check parents out of stock attribute
if ( ! $this->backorders_allowed() && $this->get_total_stock() <= 0 )
$this->set_stock_status( 'outofstock' );
elseif ( $this->backorders_allowed() || $this->get_total_stock() > 0 )
$this->set_stock_status( 'instock' );
wc_delete_product_transients( $this->id ); // Clear transient
return apply_filters( 'woocommerce_stock_amount', $this->stock );
} }
}
/**
* Reduce stock level of the product.
*
* @access public
* @param int $by (default: 1) Amount to reduce by.
* @return int Stock
*/
public function reduce_stock( $by = 1 ) {
global $woocommerce;
if ( $this->managing_stock() ) {
$this->stock = $this->stock - $by;
$this->total_stock = $this->get_total_stock() - $by;
update_post_meta($this->id, '_stock', $this->stock);
// Out of stock attribute
if ( ! $this->backorders_allowed() && $this->get_total_stock() <= 0 )
$this->set_stock_status( 'outofstock' );
wc_delete_product_transients( $this->id ); // Clear transient
return apply_filters( 'woocommerce_stock_amount', $this->stock );
}
}
/**
* Increase stock level of the product.
*
* @access public
* @param int $by (default: 1) Amount to increase by
* @return int Stock
*/
public function increase_stock( $by = 1 ) {
global $woocommerce;
if ($this->managing_stock()) :
$this->stock = $this->stock + $by;
$this->total_stock = $this->get_total_stock() + $by;
update_post_meta($this->id, '_stock', $this->stock);
// Out of stock attribute
if ( $this->backorders_allowed() || $this->get_total_stock() > 0 )
$this->set_stock_status( 'instock' );
wc_delete_product_transients( $this->id ); // Clear transient
return apply_filters( 'woocommerce_stock_amount', $this->stock );
endif;
}
/** /**
* Return the products children posts. * Return the products children posts.

View File

@ -281,22 +281,35 @@ class WC_Product_Variation extends WC_Product {
} }
/** /**
* Set stock level of the product. * Set stock level of the product variation.
* *
* @access public * @param int $amount
* @param mixed $amount (default: null) * @param boolean $force_variation_stock If true, the variation's stock will be updated and not the parents.
* @return int Stock
*/ */
function set_stock( $amount = null ) { function set_stock( $amount = null, $force_variation_stock = false ) {
global $woocommerce; if ( is_null( $amount ) )
return;
if ( $this->variation_has_stock ) { if ( $amount === '' && $force_variation_stock ) {
if ( $this->managing_stock() && ! is_null( $amount ) ) {
// If amount is an empty string, stock management is being turned off at variation level
$this->variation_has_stock = false;
$this->stock = '';
unset( $this->manage_stock );
// Update meta
update_post_meta( $this->variation_id, '_stock', '' );
} elseif ( $this->variation_has_stock || $force_variation_stock ) {
// Update stock amount
$this->stock = intval( $amount ); $this->stock = intval( $amount );
$this->total_stock = intval( $amount );
// Update meta
update_post_meta( $this->variation_id, '_stock', $this->stock ); update_post_meta( $this->variation_id, '_stock', $this->stock );
wc_delete_product_transients( $this->id ); // Clear transient
// Clear total stock transient
delete_transient( 'wc_product_total_stock_' . $this->id );
// Check parents out of stock attribute // Check parents out of stock attribute
if ( ! $this->is_in_stock() ) { if ( ! $this->is_in_stock() ) {
@ -312,45 +325,27 @@ class WC_Product_Variation extends WC_Product {
$this->set_stock_status( 'instock' ); $this->set_stock_status( 'instock' );
} }
return apply_filters( 'woocommerce_stock_amount', $this->stock ); // Trigger action
} do_action( 'woocommerce_product_set_stock', $this );
return $this->get_stock_quantity();
} else { } else {
return parent::set_stock( $amount ); return parent::set_stock( $amount );
} }
} }
/** /**
* Reduce stock level of the product. * Reduce stock level of the product.
* *
* @access public
* @param int $by (default: 1) Amount to reduce by * @param int $by (default: 1) Amount to reduce by
* @return int stock level * @return int stock level
*/ */
public function reduce_stock( $by = 1 ) { public function reduce_stock( $by = 1 ) {
global $woocommerce;
if ( $this->variation_has_stock ) { if ( $this->variation_has_stock ) {
if ( $this->managing_stock() ) { return $this->set_stock( $this->stock - $by );
$this->stock = $this->stock - $by;
$this->total_stock = $this->total_stock - $by;
update_post_meta( $this->variation_id, '_stock', $this->stock );
wc_delete_product_transients( $this->id ); // Clear transient
// Check parents out of stock attribute
if ( ! $this->is_in_stock() ) {
// Check parent
$parent_product = get_product( $this->id );
// Only continue if the parent has backorders off
if ( ! $parent_product->backorders_allowed() && $parent_product->get_total_stock() <= 0 )
$this->set_stock_status( 'outofstock' );
}
return apply_filters( 'woocommerce_stock_amount', $this->stock );
}
} else { } else {
return parent::reduce_stock( $by ); return parent::reduce_stock( $by );
} }
@ -359,30 +354,15 @@ class WC_Product_Variation extends WC_Product {
/** /**
* Increase stock level of the product. * Increase stock level of the product.
* *
* @access public
* @param int $by (default: 1) Amount to increase by * @param int $by (default: 1) Amount to increase by
* @return int stock level * @return int stock level
*/ */
public function increase_stock( $by = 1 ) { public function increase_stock( $by = 1 ) {
global $woocommerce; if ( $this->variation_has_stock ) {
return $this->set_stock( $this->stock + $by );
if ($this->variation_has_stock) : } else {
if ($this->managing_stock()) :
$this->stock = $this->stock + $by;
$this->total_stock = $this->total_stock + $by;
update_post_meta( $this->variation_id, '_stock', $this->stock );
wc_delete_product_transients( $this->id ); // Clear transient
// Parents out of stock attribute
if ( $this->is_in_stock() )
$this->set_stock_status( 'instock' );
return apply_filters( 'woocommerce_stock_amount', $this->stock );
endif;
else :
return parent::increase_stock( $by ); return parent::increase_stock( $by );
endif; }
} }
/** /**

View File

@ -13,7 +13,6 @@
/** /**
* Main function for returning products, uses the WC_Product_Factory class. * Main function for returning products, uses the WC_Product_Factory class.
* *
* @access public
* @param mixed $the_product Post object or post ID of the product. * @param mixed $the_product Post object or post ID of the product.
* @param array $args (default: array()) Contains all arguments to be used to get this product. * @param array $args (default: array()) Contains all arguments to be used to get this product.
* @return WC_Product * @return WC_Product
@ -23,6 +22,32 @@ function get_product( $the_product = false, $args = array() ) {
return $woocommerce->product_factory->get_product( $the_product, $args ); return $woocommerce->product_factory->get_product( $the_product, $args );
} }
/**
* Update a product's stock amount
*
* @param int $product_id
* @param int $new_stock_level
*/
function wc_update_product_stock( $product_id, $new_stock_level ) {
$product = get_product( $product_id );
if ( $product->is_type( 'variation' ) )
$product->set_stock( $new_stock_level, true );
else
$product->set_stock( $new_stock_level );
}
/**
* Update a product's stock status
*
* @param int $product_id
* @param int $status
*/
function wc_update_product_stock_status( $product_id, $status ) {
$product = get_product( $product_id );
$product-> set_stock_status( $status );
}
/** /**
* Clear all transients cache for product data. * Clear all transients cache for product data.
* *