[EDIT: it actually works when adding the code in functions.php and omitting the changes in code WC files. Important: it only works when ONE attribute exists. However when there are 2 attributes (size & color for instance) then it doesn't work because it's not about out-of-stock variations anymore but about variation combinations, and indeed WooCommerce is completely clueless in this common scenario. Note that there seems to be no available plugin currently to address this very obvious problem either. Great.]
Since 2.0 WooCommerce either hides out-of-stock product variations (an obvious problem since clients have then no way to know about their existence) or displays them just as in-stock variations (also a problem because clients are then systematically disappointed to find out the variation is out-of-stock after clicking purchase).
This thread includes a solution to grey out the out-of-stock product variations:
Presumably to be added to functions.php
:
add_filter( 'woocommerce_variation_is_active', 'grey_out_variations_when_out_of_stock', 10, 3 );
function grey_out_variations_when_out_of_stock( $grey_out, $variation_id, $id ) {
$variation = get_product( $variation_id );
if ( ! $variation->is_in_stock() )
return false;
return true;
}
To be done in plugins/woocommerce/includes/class-wc-product-variation.php
:
Change:
return apply_filters( 'woocommerce_variation_is_active', true, $this->variation_id, $this->id );
to:
return apply_filters( 'woocommerce_variation_is_active', true, $this );
Also change:
return apply_filters( 'woocommerce_variation_is_visible', $visible, $this->variation_id, $this->id );
to:
return apply_filters( 'woocommerce_variation_is_visible', $visible, $this->variation_id, $this->id, $this );
Yet although it reportedly works, in my case the out-of-stock variations are displayed the same as the others and I also have a warning:
Warning: Missing argument 3 for grey_out_variations_when_out_of_stock() in ...\functions.php on line 600
What am I doing wrong?
Don't change anything in core.
That error tells you that you are trying to call 3 variables as parameters for your function, but the action hook is only passing 2, hence the third one is missing. This is because you have modified core to remove the 3rd argument.
Also note that
// Hide out of stock variations if 'Hide out of stock items from the catalog' is checked
if ( empty( $variation->variation_id ) || ( 'yes' === get_option( 'woocommerce_hide_out_of_stock_items' ) && ! $variation->is_in_stock() ) ) {
continue;
}
can be found in the variable product class. If the woocommerce_hide_out_of_stock_items
option is set in the WooCommerce settings that should handle this automatically.
UPDATE
I read through the github issue that you reference. The commits made by franticpsyx have since been modified slightly, so the function that franticpsyx posted isn't working as he originally posted it there and why you are running into the variable number error. In the WooCommerce source the woocommerce_variation_is_active
now only has 2 variables passed to it.
public function variation_is_active() {
return apply_filters( 'woocommerce_variation_is_active', true, $this );
}
So we need to modify the code to use the variables that are being passed:
add_filter( 'woocommerce_variation_is_active', 'grey_out_variations_when_out_of_stock', 10, 2 );
function grey_out_variations_when_out_of_stock( $grey_out, $variation ) {
if ( ! $variation->is_in_stock() )
return false;
return true;
}
This worked for me. I'm pretty sure that on the front-end the items are greyed out via Javascript, because to do so on the back-end would require a lot of mods to core.
Just adding my answer as I hunted a long time for it and none of these were working for me. no matter what $variation->is_in_stock() would ALWAYS return true.
My solution was to modify the function by changing $variation->is_in_stock() to $variation->get_stock_quantity().
$variation->get_stock_quantity() actually returns a number that you can use which is the remaining stock. so rewrite the function based on the parameters you like, say when there are 5 left you want it marked out of stock (or 0 if you want 0 to be out of stock) the function would look like so:
add_filter( 'woocommerce_variation_is_active', 'my_jazzy_function', 10, 2 );
function my_jazzy_function( $active, $variation ) {
$var_stock_count = $variation->get_stock_quantity();
// if there are 5 or less, disable the variant, could always just set to 0.
if( $var_stock_count <= 6 ) {
return false;
}
else {
return true;
}
}