Last active
December 10, 2021 14:03
-
-
Save damiencarbery/5be43650ec558a9fa9fab48ddcda667e to your computer and use it in GitHub Desktop.
Edit stock levels in WooCommerce - Add editing capability to the List stock levels in WooCommerce plugin - https://www.damiencarbery.com/2019/10/edit-stock-levels-in-woocommerce
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
table.wp-list-table tr.updated { animation: highlight 3s ease 2; } | |
@keyframes highlight { | |
0% { background-color: inherit; } | |
50% { background-color: #d1fa88; } | |
100% { background-color: inherit; } | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
$stock_level_form = sprintf( '<form method="post" action="">'. | |
'<label for="new-stock-count"><input type="number" name="new_stock_count" value="%d" /></label>'. | |
'<input type="hidden" name="old_stock_count" value="%d" />'. | |
'<input type="hidden" name="product_id" value="%d" />'. | |
'<input type="submit" value="Update" data-product-id="%d" />%s</form>', | |
$stock_level, $stock_level, $product->get_id(), $product->get_id(), $nonce_field ); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// $Id: woocommerce-stock-info.js 4872 2019-10-27 18:14:20Z damien $ | |
jQuery(document).ready( function( $ ){ | |
jQuery( 'input[type=submit]' ).on( 'click', function(e) { // Click on a Submit button. | |
e.preventDefault(); | |
product_id = $(this).data( 'product-id' ); | |
jQuery.ajax({ | |
url : ajax_js_stock_level.ajax_url, | |
type : 'post', | |
data : { | |
action : 'dcwd_ajax_stock_level', // Note that this is part of the add_action() call. | |
wc_stock_info_name : ajax_js_stock_level.the_nonce, | |
product_id : product_id, | |
new_stock_count : $( '#product-' + product_id + ' input[name=new_stock_count]' ).val(), | |
old_stock_count : $( '#product-' + product_id + ' input[name=old_stock_count]' ).val(), | |
}, | |
success : function( response ) { | |
alert( response.data.message ); | |
$( '#product-' + response.data.product_id ).addClass( 'updated' ); | |
}, | |
error : function( response ) { | |
alert('Error updating stock level: ' + response.status + ' ' + response.statusText); | |
console.log( response ); | |
} | |
}); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/* | |
Plugin Name: WooCommerce Stock Info | |
Plugin URI: https://www.damiencarbery.com/2019/10/list-stock-levels-in-woocommerce/ | |
Description: List the stock level for each product and variation. The level can be changed for items with "Manage Stock" enabled. | |
Author: Damien Carbery | |
Author URI: https://www.damiencarbery.com | |
Version: $Revision: 4877 $ | |
Tested up to: 5.2.4 | |
Requires PHP: 5.6 | |
WC requires at least: 3.0.0 | |
WC tested up to: 3.7.1 | |
$Id: woocommerce-stock-info.php 4877 2019-11-01 13:11:37Z damien $ | |
*/ | |
if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly | |
// Load ajax script and add the nonce. | |
add_action( 'admin_enqueue_scripts', 'dcwd_ajax_enqueue_script' ); | |
function dcwd_ajax_enqueue_script() { | |
$current_screen = get_current_screen(); | |
if ( 'woocommerce_page_dcwd-woocommerce-stock-info' == $current_screen->id ) { | |
wp_enqueue_script( 'dcwd_stock_info', plugin_dir_url( __FILE__ ). 'woocommerce-stock-info.js', array('jquery') ); | |
wp_localize_script( 'dcwd_stock_info', 'ajax_js_stock_level', array( | |
'ajax_url' => admin_url( 'admin-ajax.php' ), | |
'the_nonce' => wp_create_nonce('ajax_stock_info_name') | |
)); | |
} | |
} | |
// Exclude the nopriv version as this code should only be run by logged in users. | |
// The add_submenu_page() call requires 'manage_options' and the function below | |
// checks that the user can 'manage_options' too. | |
add_action( 'wp_ajax_dcwd_ajax_stock_level', 'update_wc_stock_level' ); // For logged in users. | |
// Update stock level if a form or ajax request was submitted. | |
// wp_doing_ajax() is used to distinguish between an ajax and form submission. | |
function update_wc_stock_level() { | |
if ( wp_doing_ajax() ) { | |
// This function will die if submitted_nonce is not correct. | |
check_ajax_referer( 'ajax_stock_info_name', 'wc_stock_info_name' ); | |
if ( ! current_user_can( 'manage_options' ) ) { | |
wp_send_json_error(); | |
wp_die(); | |
} | |
} | |
else { | |
if ( !isset( $_POST['wc_stock_info_name'] ) || !wp_verify_nonce( $_POST['wc_stock_info_name'], 'wc_stock_info_update' ) ) { | |
return null; | |
} | |
if ( ! current_user_can( 'manage_options' ) ) { | |
return null; | |
} | |
} | |
// Verify that 'product_id' is an int. | |
if ( isset( $_POST[ 'product_id' ] ) && (int) $_POST[ 'product_id' ] ) { | |
// wc_get_product() will ensure that 'product_id' corresponds to a valid product or variation. | |
$product_to_update = wc_get_product( (int) $_POST[ 'product_id' ] ); | |
if ( ( 'simple' == $product_to_update->get_type() ) || ( 'variable' == $product_to_update->get_type() ) ) { | |
// Ensure 'new_stock_count' is a positive int. | |
if ( isset( $_POST[ 'new_stock_count' ] ) && (int) $_POST[ 'new_stock_count' ] && 0 < (int) $_POST[ 'new_stock_count' ] ) { | |
$product_to_update->set_stock_quantity( wc_stock_amount( (int) $_POST[ 'new_stock_count' ] ) ); | |
$product_to_update->save(); | |
$product_updated = $product_to_update->get_id(); | |
if ( wp_doing_ajax() ) { | |
$response = array( 'message' => 'Stock level for ' . $product_to_update->get_name() . ' increased to ' . $_POST[ 'new_stock_count' ] . '.', 'product_id' => $product_to_update->get_id() ); | |
wp_send_json_success( $response ); | |
wp_die(); | |
} | |
else { | |
return $product_updated; | |
} | |
} | |
} | |
} | |
if ( wp_doing_ajax() ) { | |
wp_send_json_error(); | |
wp_die(); | |
} | |
else { | |
return null; | |
} | |
} | |
add_action( 'admin_enqueue_scripts', 'wsi_include_wc_admin_css', 20 ); | |
function wsi_include_wc_admin_css() { | |
wp_enqueue_style( 'woocommerce_admin_styles' ); | |
} | |
add_action('admin_menu', 'wsi_add_menu_page', 100 ); | |
function wsi_add_menu_page() { | |
add_submenu_page( 'woocommerce', 'WooCommerce Stock Info', 'Stock Info', 'manage_options', 'dcwd-woocommerce-stock-info', 'wsi_stock_info_page' ); | |
} | |
function wsi_stock_info_page() { | |
?> | |
<div class="wrap"> | |
<h1>Stock Information</h1> | |
<style> | |
table.wp-list-table mark.instock input, table.wp-list-table mark.onbackorder input, table.wp-list-table mark.outofstock input { font-weight: initial; } | |
table.wp-list-table input[type="number"] { width: 5em; } | |
/*table.wp-list-table tr { transition-property: background-color; transition-duration: 1s; }*/ | |
table.wp-list-table tr.updated { animation: highlight 3s ease 2; } | |
@keyframes highlight { | |
0% { background-color: inherit; } | |
50% { background-color: #d1fa88; } | |
100% { background-color: inherit; } | |
} | |
</style> | |
<?php | |
$product_updated = update_wc_stock_level(); | |
$args = array( 'limit' => -1, 'orderby' => 'name', 'order' => 'ASC', 'status' => 'publish' ); | |
$all_products = wc_get_products( $args ); | |
$nonce_field = wp_nonce_field( 'wc_stock_info_update', 'wc_stock_info_name', true, false ); | |
echo '<table class="wp-list-table widefat fixed striped posts">'; | |
echo '<thead><tr><td class="manage-column">Product name</td><td class="manage-column">Variation name</td><td class="manage-column">Stock level</td><td class="manage-column">In stock?</td></tr></thead>'; | |
foreach ( $all_products as $product ) { | |
if ( 'variable' == $product->get_type() ) { | |
echo '<tr><td colspan="4"><strong>', $product->get_name(), ' (Variable product)</strong></td></tr>'; | |
$variations = $product->get_available_variations(); | |
foreach ( $variations as $variation_obj ) { | |
$variation = wc_get_product( $variation_obj['variation_id'] ); | |
$stock_level = wsi_stock_level_message( $variation, $nonce_field ); | |
echo wsi_stock_level_table_row( $variation->get_attribute_summary(), $variation->get_id(), $stock_level, $variation->get_stock_status(), $product_updated ); | |
} | |
} | |
elseif ( 'simple' == $product->get_type() ) { | |
echo '<tr><td colspan="4"><strong>', $product->get_name(), ' (Simple product)</strong></td></tr>'; | |
$stock_level = wsi_stock_level_message( $product, $nonce_field ); | |
echo wsi_stock_level_table_row( $product->get_name(), $product->get_id(), $stock_level, $product->get_stock_status(), $product_updated ); | |
} | |
else { | |
// Skip over products that are not variable or simple. | |
} | |
} | |
echo '</table>'; | |
?> | |
</div> | |
<?php | |
} | |
// Generate the stock level message. | |
function wsi_stock_level_message( $product, $nonce_field ) { | |
$stock_level = '<span style="color: red">Stock not managed</span>'; // Warning that stock not managed. | |
if ( $product->get_manage_stock() ) { | |
$stock_level = wc_stock_amount( $product->get_stock_quantity() ); | |
$stock_level_form = sprintf( '<form method="post" action="">'. | |
'<label for="new-stock-count"><input type="number" name="new_stock_count" value="%d" /></label>'. | |
'<input type="hidden" name="old_stock_count" value="%d" />'. | |
'<input type="hidden" name="product_id" value="%d" />'. | |
'<input type="submit" value="Update" data-product-id="%d" />%s</form>', | |
$stock_level, $stock_level, $product->get_id(), $product->get_id(), $nonce_field ); | |
$low_stock_amount = wc_get_low_stock_amount( $product ); | |
if ( $stock_level <= $low_stock_amount ) { | |
$stock_level = '<mark class="outofstock">' . $stock_level_form . ' (low stock)</mark>'; | |
} | |
else { | |
$stock_level = '<mark class="instock">' . $stock_level_form . '</mark>'; | |
} | |
} | |
return $stock_level; | |
} | |
// Generate the table row with product name, stock level and stock status. | |
function wsi_stock_level_table_row( $product_name, $product_id, $stock_level, $stock_status, $product_updated_id ) { | |
$stock_status_text = array( 'instock' => 'In stock', 'outofstock' => '<mark class="outofstock">Out of stock</mark>', 'onbackorder' => 'On backorder' ); | |
return sprintf( '<tr id="product-%d" class="%s"><td></td><td>%s</td><td>%s</td><td>%s</td></tr>', | |
$product_id, ( $product_updated_id == $product_id ) ? 'updated' : '', $product_name, $stock_level, $stock_status_text[ $stock_status ] ); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment