WC_Product_Data_Store_CPT::update_product_stock()publicWC 3.0.0

Update a product's stock amount directly.

Uses queries rather than update_post_meta so we can do this in one query (to avoid stock issues). Ignores manage stock setting on the product and sets quantities directly in the db: post meta and lookup tables. Uses locking to update the quantity. If the lock is not acquired, change is lost.

Method of the class: WC_Product_Data_Store_CPT{}

Return

Int|float. New stock level.

Usage

$WC_Product_Data_Store_CPT = new WC_Product_Data_Store_CPT();
$WC_Product_Data_Store_CPT->update_product_stock( $product_id_with_stock, $stock_quantity, $operation );
$product_id_with_stock(int) (required)
Product ID.
$stock_quantity(int|float|null)
Stock quantity.
Default: null
$operation(string)
Set, increase and decrease.
Default: 'set'

Changelog

Since 3.0.0 Introduced.
Since 3.0.0 this supports set, increase and decrease.

WC_Product_Data_Store_CPT::update_product_stock() code WC 9.4.2

public function update_product_stock( $product_id_with_stock, $stock_quantity = null, $operation = 'set' ) {
	global $wpdb;

	// Ensures a row exists to update.
	add_post_meta( $product_id_with_stock, '_stock', 0, true );

	if ( 'set' === $operation ) {
		$new_stock = wc_stock_amount( $stock_quantity );

		// Generate SQL.
		$sql = $wpdb->prepare(
			"UPDATE {$wpdb->postmeta} SET meta_value = %f WHERE post_id = %d AND meta_key='_stock'",
			$new_stock,
			$product_id_with_stock
		);
	} else {
		$current_stock = wc_stock_amount(
			$wpdb->get_var(
				$wpdb->prepare(
					"SELECT meta_value FROM {$wpdb->postmeta} WHERE post_id = %d AND meta_key='_stock';",
					$product_id_with_stock
				)
			)
		);

		// Calculate new value for filter below. Set multiplier to subtract or add the meta_value.
		switch ( $operation ) {
			case 'increase':
				$new_stock  = $current_stock + wc_stock_amount( $stock_quantity );
				$multiplier = 1;
				break;
			default:
				$new_stock  = $current_stock - wc_stock_amount( $stock_quantity );
				$multiplier = -1;
				break;
		}

		// Generate SQL.
		$sql = $wpdb->prepare(
			"UPDATE {$wpdb->postmeta} SET meta_value = meta_value %+f WHERE post_id = %d AND meta_key='_stock'",
			wc_stock_amount( $stock_quantity ) * $multiplier, // This will either subtract or add depending on operation.
			$product_id_with_stock
		);
	}

	$sql = apply_filters( 'woocommerce_update_product_stock_query', $sql, $product_id_with_stock, $new_stock, $operation );

	$wpdb->query( $sql ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.PreparedSQL.NotPrepared

	// Cache delete is required (not only) to set correct data for lookup table (which reads from cache).
	// Sometimes I wonder if it shouldn't be part of update_lookup_table.
	wp_cache_delete( $product_id_with_stock, 'post_meta' );

	$this->update_lookup_table( $product_id_with_stock, 'wc_product_meta_lookup' );

	/**
	 * Fire an action for this direct update so it can be detected by other code.
	 *
	 * @since 3.6
	 * @param int $product_id_with_stock Product ID that was updated directly.
	 */
	do_action( 'woocommerce_updated_product_stock', $product_id_with_stock );

	return $new_stock;
}