2011-08-09 15:16:18 +00:00
< ? php
2014-09-20 18:58:30 +00:00
2014-06-24 12:05:13 +00:00
if ( ! defined ( 'ABSPATH' ) ) {
2014-09-20 18:58:30 +00:00
exit ; // Exit if accessed directly
2014-06-24 12:05:13 +00:00
}
2013-02-20 17:14:46 +00:00
2011-08-09 15:16:18 +00:00
/**
2015-11-03 13:31:20 +00:00
* Product Variation Class .
2012-08-10 13:21:10 +00:00
*
2011-08-10 17:11:11 +00:00
* The WooCommerce product variation class handles product variation data .
2011-08-09 15:16:18 +00:00
*
2014-09-26 10:45:15 +00:00
* @ class WC_Product_Variation
* @ version 2.2 . 0
* @ package WooCommerce / Classes
* @ category Class
* @ author WooThemes
2011-08-09 15:16:18 +00:00
*/
2012-01-27 16:38:39 +00:00
class WC_Product_Variation extends WC_Product {
2012-08-10 13:21:10 +00:00
2015-07-09 14:56:20 +00:00
/** @public int ID of the variation itself. */
2012-12-20 11:54:38 +00:00
public $variation_id ;
2012-12-19 23:04:25 +00:00
/** @public object Parent Variable product object. */
2012-12-20 11:54:38 +00:00
public $parent ;
2012-12-14 21:54:13 +00:00
/** @public string Stores the shipping class of the variation. */
2014-06-24 12:05:13 +00:00
public $variation_shipping_class = false ;
2014-08-04 18:31:40 +00:00
2012-12-14 21:54:13 +00:00
/** @public int Stores the shipping class ID of the variation. */
2014-06-24 12:05:13 +00:00
public $variation_shipping_class_id = false ;
2014-08-04 18:31:40 +00:00
2014-06-24 12:05:13 +00:00
/** @public unused vars @deprecated in 2.2 */
public $variation_has_sku = true ;
public $variation_has_length = true ;
public $variation_has_width = true ;
public $variation_has_height = true ;
public $variation_has_weight = true ;
public $variation_has_tax_class = true ;
public $variation_has_downloadable_files = true ;
2014-08-28 14:38:51 +00:00
/** @private array Data which is only at variation level - no inheritance plus their default values if left blank. */
2014-08-28 18:21:44 +00:00
protected $variation_level_meta_data = array (
2014-08-28 14:38:51 +00:00
'downloadable' => 'no' ,
'virtual' => 'no' ,
'manage_stock' => 'no' ,
'sale_price_dates_from' => '' ,
'sale_price_dates_to' => '' ,
'price' => '' ,
'regular_price' => '' ,
'sale_price' => '' ,
'stock' => 0 ,
'stock_status' => 'instock' ,
'downloadable_files' => array ()
);
/** @private array Data which can be at variation level, otherwise fallback to parent if not set. */
2014-08-28 18:21:44 +00:00
protected $variation_inherited_meta_data = array (
2014-08-28 14:38:51 +00:00
'tax_class' => '' ,
'backorders' => 'no' ,
'sku' => '' ,
'weight' => '' ,
'length' => '' ,
2014-09-16 12:02:26 +00:00
'width' => '' ,
2014-08-28 14:38:51 +00:00
'height' => ''
2014-06-24 12:05:13 +00:00
);
2013-09-20 16:01:09 +00:00
2011-08-09 15:16:18 +00:00
/**
2014-06-24 12:05:13 +00:00
* Loads required variation data .
2011-08-09 15:16:18 +00:00
*
2014-09-07 23:37:55 +00:00
* @ param int $variation ID of the variation to load
2012-11-22 11:48:16 +00:00
* @ param array $args Array of the arguments containing parent product data
2011-08-09 15:16:18 +00:00
*/
2012-12-14 21:54:13 +00:00
public function __construct ( $variation , $args = array () ) {
2012-11-21 18:07:45 +00:00
if ( is_object ( $variation ) ) {
$this -> variation_id = absint ( $variation -> ID );
} else {
$this -> variation_id = absint ( $variation );
}
2012-08-10 13:21:10 +00:00
2012-11-29 16:48:40 +00:00
/* Get main product data from parent (args) */
2014-06-24 12:05:13 +00:00
$this -> id = ! empty ( $args [ 'parent_id' ] ) ? intval ( $args [ 'parent_id' ] ) : wp_get_post_parent_id ( $this -> variation_id );
2012-11-27 16:16:17 +00:00
2012-11-29 16:48:40 +00:00
// The post doesn't have a parent id, therefore its invalid.
2014-06-24 12:05:13 +00:00
if ( empty ( $this -> id ) ) {
2013-12-02 11:34:27 +00:00
return ;
2014-04-22 01:13:13 +00:00
}
2012-08-10 13:21:10 +00:00
2014-06-24 12:05:13 +00:00
$this -> product_type = 'variation' ;
2014-10-07 09:49:54 +00:00
$this -> parent = ! empty ( $args [ 'parent' ] ) ? $args [ 'parent' ] : wc_get_product ( $this -> id );
2014-06-24 12:05:13 +00:00
$this -> post = ! empty ( $this -> parent -> post ) ? $this -> parent -> post : array ();
}
2012-08-10 13:21:10 +00:00
2014-06-24 12:05:13 +00:00
/**
* __isset function .
*
* @ param mixed $key
* @ return bool
*/
public function __isset ( $key ) {
2014-08-28 14:38:51 +00:00
if ( in_array ( $key , array_keys ( $this -> variation_level_meta_data ) ) ) {
return metadata_exists ( 'post' , $this -> variation_id , '_' . $key );
} elseif ( in_array ( $key , array_keys ( $this -> variation_inherited_meta_data ) ) ) {
2014-06-24 12:05:13 +00:00
return metadata_exists ( 'post' , $this -> variation_id , '_' . $key ) || metadata_exists ( 'post' , $this -> id , '_' . $key );
} else {
return metadata_exists ( 'post' , $this -> id , '_' . $key );
2012-03-21 18:37:57 +00:00
}
2014-06-24 12:05:13 +00:00
}
2012-08-10 13:21:10 +00:00
2014-06-24 12:05:13 +00:00
/**
* Get method returns variation meta data if set , otherwise in most cases the data from the parent .
*
* @ param string $key
* @ return mixed
*/
public function __get ( $key ) {
2014-08-28 14:38:51 +00:00
if ( in_array ( $key , array_keys ( $this -> variation_level_meta_data ) ) ) {
2012-08-10 13:21:10 +00:00
2014-08-28 14:38:51 +00:00
$value = get_post_meta ( $this -> variation_id , '_' . $key , true );
2012-11-27 16:22:47 +00:00
2014-08-28 14:38:51 +00:00
if ( '' === $value ) {
$value = $this -> variation_level_meta_data [ $key ];
}
2012-08-10 13:21:10 +00:00
2014-08-28 14:38:51 +00:00
} elseif ( in_array ( $key , array_keys ( $this -> variation_inherited_meta_data ) ) ) {
2012-08-10 13:21:10 +00:00
2014-08-28 14:38:51 +00:00
$value = metadata_exists ( 'post' , $this -> variation_id , '_' . $key ) ? get_post_meta ( $this -> variation_id , '_' . $key , true ) : get_post_meta ( $this -> id , '_' . $key , true );
2012-11-27 16:22:47 +00:00
2014-08-28 14:38:51 +00:00
// Handle meta data keys which can be empty at variation level to cause inheritance
2014-09-17 09:00:14 +00:00
if ( '' === $value && in_array ( $key , array ( 'sku' , 'weight' , 'length' , 'width' , 'height' ) ) ) {
2014-08-28 14:38:51 +00:00
$value = get_post_meta ( $this -> id , '_' . $key , true );
}
if ( '' === $value ) {
$value = $this -> variation_inherited_meta_data [ $key ];
2014-06-24 12:05:13 +00:00
}
2012-11-27 16:22:47 +00:00
2014-06-24 12:05:13 +00:00
} elseif ( 'variation_data' === $key ) {
2015-07-28 15:20:51 +00:00
return $this -> variation_data = wc_get_product_variation_attributes ( $this -> variation_id );
2012-11-27 16:22:47 +00:00
2014-06-24 12:05:13 +00:00
} elseif ( 'variation_has_stock' === $key ) {
return $this -> managing_stock ();
2012-11-27 16:22:47 +00:00
2014-06-24 12:05:13 +00:00
} else {
2014-09-26 10:45:15 +00:00
$value = metadata_exists ( 'post' , $this -> variation_id , '_' . $key ) ? get_post_meta ( $this -> variation_id , '_' . $key , true ) : parent :: __get ( $key );
2012-10-08 11:51:00 +00:00
}
2012-11-27 16:22:47 +00:00
2014-06-24 12:05:13 +00:00
return $value ;
2011-08-09 15:16:18 +00:00
}
2012-06-29 17:56:42 +00:00
2015-12-04 20:17:25 +00:00
/**
* Return the variation ID
*
* @ since 2.5 . 0
* @ return int variation ( post ) ID
*/
public function get_id () {
return $this -> variation_id ;
}
2013-01-16 12:10:51 +00:00
/**
* Returns whether or not the product post exists .
*
* @ return bool
*/
2013-07-23 10:28:59 +00:00
public function exists () {
2014-06-24 12:05:13 +00:00
return ! empty ( $this -> id );
2013-01-16 12:10:51 +00:00
}
2012-08-14 19:42:38 +00:00
2013-09-23 14:47:47 +00:00
/**
* Wrapper for get_permalink . Adds this variations attributes to the URL .
2014-09-26 10:45:15 +00:00
*
2014-11-27 15:04:24 +00:00
* @ param $cart item array If the cart item is passed , we can get a link containing the exact attributes selected for the variation , rather than the default attributes .
2013-09-23 14:47:47 +00:00
* @ return string
*/
2014-11-27 15:04:24 +00:00
public function get_permalink ( $cart_item = null ) {
2015-07-28 09:37:24 +00:00
return add_query_arg ( array_map ( 'urlencode' , array_filter ( isset ( $cart_item [ 'variation' ] ) ? $cart_item [ 'variation' ] : $this -> variation_data ) ), get_permalink ( $this -> id ) );
2013-09-23 14:47:47 +00:00
}
2013-09-25 11:35:06 +00:00
/**
* Get the add to url used mainly in loops .
*
* @ return string
*/
public function add_to_cart_url () {
2015-08-21 10:32:00 +00:00
$variation_data = array_map ( 'urlencode' , $this -> variation_data );
$url = $this -> is_purchasable () && $this -> is_in_stock () ? remove_query_arg ( 'added-to-cart' , add_query_arg ( array_merge ( array ( 'variation_id' => $this -> variation_id , 'add-to-cart' => $this -> id ), $variation_data ) ) ) : get_permalink ( $this -> id );
2013-09-25 11:35:06 +00:00
return apply_filters ( 'woocommerce_product_add_to_cart_url' , $url , $this );
}
/**
2015-11-03 13:31:20 +00:00
* Get the add to cart button text .
2013-09-25 11:35:06 +00:00
*
* @ return string
*/
public function add_to_cart_text () {
$text = $this -> is_purchasable () && $this -> is_in_stock () ? __ ( 'Add to cart' , 'woocommerce' ) : __ ( 'Read More' , 'woocommerce' );
return apply_filters ( 'woocommerce_product_add_to_cart_text' , $text , $this );
}
2012-08-14 19:42:38 +00:00
/**
2014-09-26 16:22:43 +00:00
* Checks if this particular variation is visible . Invisible variations are enabled and can be selected , but no price / stock info is displayed .
* Instead , a suitable 'unavailable' message is displayed .
* Invisible by default : Disabled variations and variations with an empty price .
2012-08-14 19:42:38 +00:00
*
* @ return bool
*/
2013-06-14 11:21:20 +00:00
public function variation_is_visible () {
2012-06-29 17:56:42 +00:00
$visible = true ;
2012-08-10 13:21:10 +00:00
2013-10-10 15:34:44 +00:00
// Published == enabled checkbox
2014-06-24 12:05:13 +00:00
if ( get_post_status ( $this -> variation_id ) != 'publish' ) {
2013-06-14 11:21:20 +00:00
$visible = false ;
2014-06-24 12:05:13 +00:00
}
2013-06-14 11:21:20 +00:00
2013-01-16 12:10:51 +00:00
// Price not set
2014-06-24 12:05:13 +00:00
elseif ( $this -> get_price () === " " ) {
2013-01-16 12:10:51 +00:00
$visible = false ;
2014-06-24 12:05:13 +00:00
}
2013-01-16 12:10:51 +00:00
2014-11-19 17:46:05 +00:00
return apply_filters ( 'woocommerce_variation_is_visible' , $visible , $this -> variation_id , $this -> id , $this );
2012-06-29 17:56:42 +00:00
}
2012-08-10 13:21:10 +00:00
2014-09-26 16:22:43 +00:00
/**
* Controls whether this particular variation will appear greyed - out ( inactive ) or not ( active ) .
* Used by extensions to make incompatible variations appear greyed - out , etc .
* Other possible uses : prevent out - of - stock variations from being selected .
*
* @ return bool
*/
public function variation_is_active () {
2014-11-19 17:46:05 +00:00
return apply_filters ( 'woocommerce_variation_is_active' , true , $this );
2014-09-26 16:22:43 +00:00
}
2013-10-10 15:34:44 +00:00
/**
* Returns false if the product cannot be bought .
2014-09-26 16:22:43 +00:00
* Override abstract method so that : i ) Disabled variations are not be purchasable by admins . ii ) Enabled variations are not purchasable if the parent product is not purchasable .
2013-10-10 15:34:44 +00:00
*
2014-03-21 21:41:32 +00:00
* @ return bool
2013-10-10 15:34:44 +00:00
*/
public function is_purchasable () {
// Published == enabled checkbox
2014-06-24 12:05:13 +00:00
if ( get_post_status ( $this -> variation_id ) != 'publish' ) {
2013-10-10 15:34:44 +00:00
$purchasable = false ;
2014-06-24 12:05:13 +00:00
} else {
2013-10-10 15:34:44 +00:00
$purchasable = parent :: is_purchasable ();
2014-06-24 12:05:13 +00:00
}
2014-06-23 15:04:03 +00:00
return apply_filters ( 'woocommerce_variation_is_purchasable' , $purchasable , $this );
2013-10-10 15:34:44 +00:00
}
2012-08-14 19:42:38 +00:00
/**
* Returns whether or not the variations parent is visible .
*
* @ return bool
*/
2012-12-14 21:54:13 +00:00
public function parent_is_visible () {
2013-06-14 11:21:20 +00:00
return $this -> is_visible ();
2012-06-29 17:56:42 +00:00
}
2012-08-10 13:21:10 +00:00
2011-08-22 11:57:50 +00:00
/**
2015-11-03 13:31:20 +00:00
* Get variation ID .
2014-09-26 10:45:15 +00:00
*
* @ return int
*/
public function get_variation_id () {
return absint ( $this -> variation_id );
}
2012-08-10 13:21:10 +00:00
2011-08-22 11:57:50 +00:00
/**
2015-11-03 13:31:20 +00:00
* Get variation attribute values .
2014-09-26 10:45:15 +00:00
*
* @ return array of attributes and their values for this variation
*/
public function get_variation_attributes () {
return $this -> variation_data ;
}
2014-10-15 07:11:41 +00:00
/**
2015-11-03 13:31:20 +00:00
* Check if all variation ' s attributes are set .
2014-10-15 07:11:41 +00:00
*
* @ return boolean
*/
2014-10-17 15:24:04 +00:00
public function has_all_attributes_set () {
2014-10-15 07:11:41 +00:00
2014-10-17 15:24:04 +00:00
$set = true ;
2014-11-19 17:46:05 +00:00
2014-10-15 07:11:41 +00:00
// undefined attributes have null strings as array values
foreach ( $this -> get_variation_attributes () as $att ){
if ( ! $att ){
2014-10-17 15:24:04 +00:00
$set = false ;
2014-10-15 07:11:41 +00:00
break ;
}
}
2014-10-17 15:24:04 +00:00
return $set ;
2014-10-15 07:11:41 +00:00
}
2014-11-19 17:46:05 +00:00
2014-09-26 10:45:15 +00:00
/**
* Get variation price HTML . Prices are not inherited from parents .
*
* @ return string containing the formatted price
*/
2013-08-07 14:38:31 +00:00
public function get_price_html ( $price = '' ) {
2014-12-03 09:28:04 +00:00
$display_price = $this -> get_display_price ();
$display_regular_price = $this -> get_display_price ( $this -> get_regular_price () );
$display_sale_price = $this -> get_display_price ( $this -> get_sale_price () );
2013-09-19 15:31:54 +00:00
2013-07-23 10:28:59 +00:00
if ( $this -> get_price () !== '' ) {
if ( $this -> is_on_sale () ) {
2014-06-24 12:05:13 +00:00
$price = apply_filters ( 'woocommerce_variation_sale_price_html' , '<del>' . wc_price ( $display_regular_price ) . '</del> <ins>' . wc_price ( $display_sale_price ) . '</ins>' . $this -> get_price_suffix (), $this );
2013-07-23 10:28:59 +00:00
} elseif ( $this -> get_price () > 0 ) {
2014-06-24 12:05:13 +00:00
$price = apply_filters ( 'woocommerce_variation_price_html' , wc_price ( $display_price ) . $this -> get_price_suffix (), $this );
2013-01-16 12:10:51 +00:00
} else {
2014-06-24 12:05:13 +00:00
$price = apply_filters ( 'woocommerce_variation_free_price_html' , __ ( 'Free!' , 'woocommerce' ), $this );
2013-01-16 12:10:51 +00:00
}
2012-10-08 11:51:00 +00:00
} else {
2013-01-16 12:10:51 +00:00
$price = apply_filters ( 'woocommerce_variation_empty_price_html' , '' , $this );
2012-10-08 11:51:00 +00:00
}
2013-01-16 12:10:51 +00:00
2013-07-26 13:47:23 +00:00
return apply_filters ( 'woocommerce_get_variation_price_html' , $price , $this );
2011-08-09 15:16:18 +00:00
}
2012-08-10 13:21:10 +00:00
2014-09-26 10:45:15 +00:00
/**
* Gets the main product image ID .
*
* @ return int
*/
public function get_image_id () {
if ( $this -> variation_id && has_post_thumbnail ( $this -> variation_id ) ) {
2014-04-08 14:02:11 +00:00
$image_id = get_post_thumbnail_id ( $this -> variation_id );
} elseif ( has_post_thumbnail ( $this -> id ) ) {
$image_id = get_post_thumbnail_id ( $this -> id );
} elseif ( ( $parent_id = wp_get_post_parent_id ( $this -> id ) ) && has_post_thumbnail ( $parent_id ) ) {
$image_id = get_post_thumbnail_id ( $parent_id );
} else {
$image_id = 0 ;
}
return $image_id ;
2014-09-26 10:45:15 +00:00
}
/**
* Gets the main product image .
*
* @ param string $size ( default : 'shop_thumbnail' )
2016-03-21 14:58:14 +00:00
* @ param bool True to return $placeholder if no image is found , or false to return an empty string .
2014-09-26 10:45:15 +00:00
* @ return string
*/
2016-03-21 14:58:14 +00:00
public function get_image ( $size = 'shop_thumbnail' , $attr = array (), $placeholder = true ) {
2014-09-26 10:45:15 +00:00
if ( $this -> variation_id && has_post_thumbnail ( $this -> variation_id ) ) {
2012-11-28 18:02:12 +00:00
$image = get_the_post_thumbnail ( $this -> variation_id , $size , $attr );
2012-08-12 11:41:26 +00:00
} elseif ( has_post_thumbnail ( $this -> id ) ) {
2012-11-28 18:02:12 +00:00
$image = get_the_post_thumbnail ( $this -> id , $size , $attr );
2013-09-04 13:32:16 +00:00
} elseif ( ( $parent_id = wp_get_post_parent_id ( $this -> id ) ) && has_post_thumbnail ( $parent_id ) ) {
2012-11-28 18:02:12 +00:00
$image = get_the_post_thumbnail ( $parent_id , $size , $attr );
2016-03-21 14:58:14 +00:00
} elseif ( $placeholder ) {
2013-11-25 13:56:59 +00:00
$image = wc_placeholder_img ( $size );
2016-03-21 14:58:14 +00:00
} else {
$image = '' ;
2012-08-12 11:41:26 +00:00
}
return $image ;
2014-09-26 10:45:15 +00:00
}
2012-08-10 13:21:10 +00:00
2014-08-04 09:51:50 +00:00
/**
* Returns whether or not the product ( or variation ) is stock managed .
*
* @ return bool | string Bool if managed at variation level , 'parent' if managed by the parent .
*/
public function managing_stock () {
2014-08-04 18:31:40 +00:00
if ( 'yes' === get_option ( 'woocommerce_manage_stock' , 'yes' ) ) {
2014-08-04 09:51:50 +00:00
if ( 'no' === $this -> manage_stock ) {
2015-09-16 15:49:18 +00:00
if ( $this -> parent && $this -> parent -> managing_stock () ) {
2014-08-04 09:51:50 +00:00
return 'parent' ;
}
} else {
return true ;
}
}
return false ;
}
/**
* Returns number of items available for sale from the variation , or parent .
*
* @ return int
*/
public function get_stock_quantity () {
2014-08-04 18:31:40 +00:00
return true === $this -> managing_stock () ? wc_stock_amount ( $this -> stock ) : $this -> parent -> get_stock_quantity ();
2014-08-04 09:51:50 +00:00
}
2015-07-15 18:12:12 +00:00
/**
* Returns the tax status . Always use parent data .
*
* @ return string
*/
public function get_tax_status () {
return $this -> parent -> get_tax_status ();
}
2014-06-24 12:05:13 +00:00
/**
* Returns whether or not the product is in stock .
*
* @ return bool
*/
public function is_in_stock () {
// If we're managing stock at variation level, check stock levels
2014-08-04 09:51:50 +00:00
if ( true === $this -> managing_stock () ) {
2014-06-24 12:05:13 +00:00
if ( $this -> backorders_allowed () ) {
return true ;
2014-08-13 14:03:30 +00:00
} elseif ( $this -> get_stock_quantity () <= get_option ( 'woocommerce_notify_no_stock_amount' ) ) {
2014-06-24 12:05:13 +00:00
return false ;
} else {
return $this -> stock_status === 'instock' ;
}
2014-08-13 14:03:30 +00:00
} else {
2014-06-24 12:05:13 +00:00
return $this -> stock_status === 'instock' ;
}
}
2012-12-28 09:59:20 +00:00
/**
2013-08-13 15:56:09 +00:00
* Set stock level of the product variation .
2014-04-25 14:27:58 +00:00
*
2014-08-04 18:31:40 +00:00
* Uses queries rather than update_post_meta so we can do this in one query ( to avoid stock issues ) .
2014-04-25 14:27:58 +00:00
* We cannot rely on the original loaded value in case another order was made since then .
*
* @ param int $amount
* @ param string $mode can be set , add , or subtract
* @ return int new stock level
2012-12-28 09:59:20 +00:00
*/
2014-06-24 12:05:13 +00:00
public function set_stock ( $amount = null , $mode = 'set' ) {
2014-04-25 14:27:58 +00:00
global $wpdb ;
2012-12-28 09:59:20 +00:00
2014-08-04 09:51:50 +00:00
if ( ! is_null ( $amount ) && true === $this -> managing_stock () ) {
2014-06-24 12:05:13 +00:00
// Ensure key exists
2014-06-24 14:21:39 +00:00
add_post_meta ( $this -> variation_id , '_stock' , 0 , true );
2014-06-24 12:05:13 +00:00
// Update stock in DB directly
switch ( $mode ) {
case 'add' :
2015-05-19 07:59:42 +00:00
$wpdb -> query ( $wpdb -> prepare ( " UPDATE { $wpdb -> postmeta } SET meta_value = meta_value + %f WHERE post_id = %d AND meta_key='_stock' " , $amount , $this -> variation_id ) );
2014-06-24 12:05:13 +00:00
break ;
case 'subtract' :
2015-05-19 07:59:42 +00:00
$wpdb -> query ( $wpdb -> prepare ( " UPDATE { $wpdb -> postmeta } SET meta_value = meta_value - %f WHERE post_id = %d AND meta_key='_stock' " , $amount , $this -> variation_id ) );
2014-06-24 12:05:13 +00:00
break ;
default :
2015-05-19 07:59:42 +00:00
$wpdb -> query ( $wpdb -> prepare ( " UPDATE { $wpdb -> postmeta } SET meta_value = %f WHERE post_id = %d AND meta_key='_stock' " , $amount , $this -> variation_id ) );
2014-06-24 12:05:13 +00:00
break ;
}
2013-08-13 15:56:09 +00:00
2014-06-24 12:05:13 +00:00
// Clear caches
wp_cache_delete ( $this -> variation_id , 'post_meta' );
2014-03-04 14:45:27 +00:00
2014-06-24 12:05:13 +00:00
// Clear total stock transient
2015-06-10 12:41:29 +00:00
delete_transient ( 'wc_product_total_stock_' . $this -> id . WC_Cache_Helper :: get_transient_version ( 'product' ) );
2014-03-04 14:45:27 +00:00
2014-06-24 12:05:13 +00:00
// Stock status
$this -> check_stock_status ();
2014-03-04 14:45:27 +00:00
2014-06-24 12:05:13 +00:00
// Sync the parent
WC_Product_Variable :: sync ( $this -> id );
2013-08-13 15:56:09 +00:00
2014-06-24 12:05:13 +00:00
// Trigger action
do_action ( 'woocommerce_variation_set_stock' , $this );
2013-08-13 15:56:09 +00:00
2014-06-24 12:05:13 +00:00
} elseif ( ! is_null ( $amount ) ) {
return $this -> parent -> set_stock ( $amount , $mode );
}
2014-03-04 14:45:27 +00:00
2014-06-24 12:05:13 +00:00
return $this -> get_stock_quantity ();
}
2013-08-13 15:56:09 +00:00
2014-06-24 12:05:13 +00:00
/**
2016-01-06 15:15:00 +00:00
* Set stock status .
*
* @ param string $status
2014-06-24 12:05:13 +00:00
*/
public function set_stock_status ( $status ) {
$status = 'outofstock' === $status ? 'outofstock' : 'instock' ;
2013-08-13 15:56:09 +00:00
2014-06-24 12:05:13 +00:00
// Sanity check
2014-08-04 09:51:50 +00:00
if ( true === $this -> managing_stock () ) {
2014-06-24 12:05:13 +00:00
if ( ! $this -> backorders_allowed () && $this -> get_stock_quantity () <= get_option ( 'woocommerce_notify_no_stock_amount' ) ) {
$status = 'outofstock' ;
}
2014-08-04 09:51:50 +00:00
} elseif ( 'parent' === $this -> managing_stock () ) {
2014-06-24 12:05:13 +00:00
if ( ! $this -> parent -> backorders_allowed () && $this -> parent -> get_stock_quantity () <= get_option ( 'woocommerce_notify_no_stock_amount' ) ) {
$status = 'outofstock' ;
}
}
2013-08-13 15:56:09 +00:00
2014-06-24 12:05:13 +00:00
if ( update_post_meta ( $this -> variation_id , '_stock_status' , $status ) ) {
do_action ( 'woocommerce_variation_set_stock_status' , $this -> variation_id , $status );
2013-08-13 15:56:09 +00:00
2015-08-24 14:03:44 +00:00
WC_Product_Variable :: sync_stock_status ( $this -> id );
2012-12-28 09:59:20 +00:00
}
}
2011-08-09 15:16:18 +00:00
/**
2012-08-14 19:42:38 +00:00
* Reduce stock level of the product .
2011-08-09 15:16:18 +00:00
*
2014-04-25 14:27:58 +00:00
* @ param int $amount ( default : 1 ) Amount to reduce by
2012-08-14 19:42:38 +00:00
* @ return int stock level
2011-08-09 15:16:18 +00:00
*/
2014-04-25 14:27:58 +00:00
public function reduce_stock ( $amount = 1 ) {
2014-08-04 09:51:50 +00:00
if ( true === $this -> managing_stock () ) {
2014-06-24 12:05:13 +00:00
return $this -> set_stock ( $amount , 'subtract' );
2012-03-21 18:37:57 +00:00
} else {
2014-06-24 12:05:13 +00:00
return $this -> parent -> reduce_stock ( $amount );
2012-03-21 18:37:57 +00:00
}
2011-08-09 15:16:18 +00:00
}
2012-08-10 13:21:10 +00:00
2011-08-09 15:16:18 +00:00
/**
2012-08-14 19:42:38 +00:00
* Increase stock level of the product .
2011-08-09 15:16:18 +00:00
*
2014-04-25 14:27:58 +00:00
* @ param int $amount ( default : 1 ) Amount to increase by
2012-08-14 19:42:38 +00:00
* @ return int stock level
2011-08-09 15:16:18 +00:00
*/
2014-04-25 14:27:58 +00:00
public function increase_stock ( $amount = 1 ) {
2014-08-04 09:51:50 +00:00
if ( true === $this -> managing_stock () ) {
2014-06-24 12:05:13 +00:00
return $this -> set_stock ( $amount , 'add' );
2013-08-13 15:56:09 +00:00
} else {
2014-06-24 12:05:13 +00:00
return $this -> parent -> increase_stock ( $amount );
2013-08-13 15:56:09 +00:00
}
2011-08-09 15:16:18 +00:00
}
2012-08-10 13:21:10 +00:00
2014-06-24 12:05:13 +00:00
/**
* Returns the availability of the product .
*
* @ return string
*/
public function get_availability () {
2014-08-13 14:03:30 +00:00
$availability = $class = '' ;
2014-08-28 14:38:51 +00:00
2014-08-13 14:03:30 +00:00
if ( $this -> managing_stock () ) {
if ( $this -> is_in_stock () && $this -> get_stock_quantity () > get_option ( 'woocommerce_notify_no_stock_amount' ) ) {
switch ( get_option ( 'woocommerce_stock_format' ) ) {
case 'no_amount' :
$availability = __ ( 'In stock' , 'woocommerce' );
break ;
case 'low_amount' :
if ( $this -> get_stock_quantity () <= get_option ( 'woocommerce_notify_low_stock_amount' ) ) {
$availability = sprintf ( __ ( 'Only %s left in stock' , 'woocommerce' ), $this -> get_stock_quantity () );
if ( $this -> backorders_allowed () && $this -> backorders_require_notification () ) {
$availability .= ' ' . __ ( '(can be backordered)' , 'woocommerce' );
}
} else {
$availability = __ ( 'In stock' , 'woocommerce' );
}
break ;
default :
$availability = sprintf ( __ ( '%s in stock' , 'woocommerce' ), $this -> get_stock_quantity () );
if ( $this -> backorders_allowed () && $this -> backorders_require_notification () ) {
$availability .= ' ' . __ ( '(can be backordered)' , 'woocommerce' );
}
break ;
}
$class = 'in-stock' ;
2014-08-15 14:29:10 +00:00
} elseif ( $this -> backorders_allowed () && $this -> backorders_require_notification () ) {
2014-08-13 14:03:30 +00:00
$availability = __ ( 'Available on backorder' , 'woocommerce' );
$class = 'available-on-backorder' ;
2014-08-15 14:29:10 +00:00
} elseif ( $this -> backorders_allowed () ) {
$availability = __ ( 'In stock' , 'woocommerce' );
$class = 'in-stock' ;
2014-08-13 14:03:30 +00:00
} else {
$availability = __ ( 'Out of stock' , 'woocommerce' );
$class = 'out-of-stock' ;
}
} elseif ( ! $this -> is_in_stock () ) {
$availability = __ ( 'Out of stock' , 'woocommerce' );
$class = 'out-of-stock' ;
2013-08-13 15:56:09 +00:00
}
2014-09-26 10:45:15 +00:00
2014-08-13 14:03:30 +00:00
return apply_filters ( 'woocommerce_get_availability' , array ( 'availability' => $availability , 'class' => $class ), $this );
2014-08-28 14:38:51 +00:00
}
2012-08-10 13:21:10 +00:00
2014-06-24 12:05:13 +00:00
/**
* Returns whether or not the product needs to notify the customer on backorder .
*
* @ return bool
*/
public function backorders_require_notification () {
2014-08-04 09:51:50 +00:00
if ( true === $this -> managing_stock () ) {
2014-06-24 12:05:13 +00:00
return parent :: backorders_require_notification ();
} else {
return $this -> parent -> backorders_require_notification ();
}
}
/**
2016-01-06 15:15:00 +00:00
* Is on backorder ?
2014-06-24 12:05:13 +00:00
*
* @ param int $qty_in_cart ( default : 0 )
* @ return bool
*/
public function is_on_backorder ( $qty_in_cart = 0 ) {
2014-08-04 09:51:50 +00:00
if ( true === $this -> managing_stock () ) {
2014-06-24 12:05:13 +00:00
return parent :: is_on_backorder ( $qty_in_cart );
} else {
return $this -> parent -> is_on_backorder ( $qty_in_cart );
2014-08-04 18:31:40 +00:00
}
2014-08-04 09:51:50 +00:00
}
2014-06-24 12:05:13 +00:00
/**
* Returns whether or not the product has enough stock for the order .
*
* @ param mixed $quantity
* @ return bool
*/
public function has_enough_stock ( $quantity ) {
2014-08-04 09:51:50 +00:00
if ( true === $this -> managing_stock () ) {
2014-06-24 12:05:13 +00:00
return parent :: has_enough_stock ( $quantity );
} else {
return $this -> parent -> has_enough_stock ( $quantity );
2014-08-04 18:31:40 +00:00
}
2014-08-04 09:51:50 +00:00
}
2014-06-24 12:05:13 +00:00
2012-02-08 14:39:31 +00:00
/**
2012-08-14 19:42:38 +00:00
* Get the shipping class , and if not set , get the shipping class of the parent .
*
* @ return string
2012-02-08 14:39:31 +00:00
*/
2012-12-14 21:54:13 +00:00
public function get_shipping_class () {
2012-10-18 10:33:47 +00:00
if ( ! $this -> variation_shipping_class ) {
2012-02-10 12:16:21 +00:00
$classes = get_the_terms ( $this -> variation_id , 'product_shipping_class' );
2012-11-27 16:22:47 +00:00
2012-10-18 10:33:47 +00:00
if ( $classes && ! is_wp_error ( $classes ) ) {
2014-06-24 12:05:13 +00:00
$this -> variation_shipping_class = current ( $classes ) -> slug ;
2012-10-18 10:33:47 +00:00
} else {
$this -> variation_shipping_class = parent :: get_shipping_class ();
}
}
2012-02-08 14:39:31 +00:00
return $this -> variation_shipping_class ;
}
2012-08-10 13:21:10 +00:00
2012-08-14 19:42:38 +00:00
/**
* Returns the product shipping class ID .
*
* @ return int
*/
2012-12-14 21:54:13 +00:00
public function get_shipping_class_id () {
2012-06-26 12:17:08 +00:00
if ( ! $this -> variation_shipping_class_id ) {
$classes = get_the_terms ( $this -> variation_id , 'product_shipping_class' );
2012-08-10 13:21:10 +00:00
2014-06-24 12:05:13 +00:00
if ( $classes && ! is_wp_error ( $classes ) ) {
2012-08-10 13:21:10 +00:00
$this -> variation_shipping_class_id = current ( $classes ) -> term_id ;
2014-06-24 12:05:13 +00:00
} else {
2012-06-26 12:17:08 +00:00
$this -> variation_shipping_class_id = parent :: get_shipping_class_id ();
2014-06-24 12:05:13 +00:00
}
2012-06-26 12:17:08 +00:00
}
2012-11-19 14:05:03 +00:00
return absint ( $this -> variation_shipping_class_id );
2012-06-26 12:17:08 +00:00
}
2012-08-10 13:21:10 +00:00
2015-08-13 10:12:24 +00:00
/**
* Get formatted variation data with WC < 2.4 back compat and proper formatting of text - based attribute names .
*
* @ return string
*/
public function get_formatted_variation_attributes ( $flat = false ) {
$variation_data = $this -> get_variation_attributes ();
$attributes = $this -> parent -> get_attributes ();
$description = array ();
$return = '' ;
2015-08-13 10:32:26 +00:00
if ( is_array ( $variation_data ) ) {
2015-08-13 10:12:24 +00:00
2015-08-13 10:32:26 +00:00
if ( ! $flat ) {
$return = '<dl class="variation">' ;
2015-08-13 10:12:24 +00:00
}
2015-08-13 10:32:26 +00:00
foreach ( $attributes as $attribute ) {
// Only deal with attributes that are variations
if ( ! $attribute [ 'is_variation' ] ) {
continue ;
}
$variation_selected_value = isset ( $variation_data [ 'attribute_' . sanitize_title ( $attribute [ 'name' ] ) ] ) ? $variation_data [ 'attribute_' . sanitize_title ( $attribute [ 'name' ] ) ] : '' ;
$description_name = esc_html ( wc_attribute_label ( $attribute [ 'name' ] ) );
$description_value = __ ( 'Any' , 'woocommerce' );
2015-08-13 10:12:24 +00:00
2015-08-13 10:32:26 +00:00
// Get terms for attribute taxonomy or value if its a custom attribute
if ( $attribute [ 'is_taxonomy' ] ) {
2015-08-13 10:12:24 +00:00
2015-08-13 10:32:26 +00:00
$post_terms = wp_get_post_terms ( $this -> id , $attribute [ 'name' ] );
2015-08-13 10:12:24 +00:00
2015-08-13 10:32:26 +00:00
foreach ( $post_terms as $term ) {
if ( $variation_selected_value === $term -> slug ) {
2015-10-18 16:42:44 +00:00
$description_value = esc_html ( apply_filters ( 'woocommerce_variation_option_name' , $term -> name ) );
2015-08-13 10:32:26 +00:00
}
2015-08-13 10:12:24 +00:00
}
2015-08-13 10:32:26 +00:00
} else {
2015-08-13 10:12:24 +00:00
2015-08-13 10:32:26 +00:00
$options = wc_get_text_attributes ( $attribute [ 'value' ] );
2015-08-13 10:12:24 +00:00
2015-08-13 10:32:26 +00:00
foreach ( $options as $option ) {
2015-08-13 10:12:24 +00:00
2015-08-13 10:32:26 +00:00
if ( sanitize_title ( $variation_selected_value ) === $variation_selected_value ) {
if ( $variation_selected_value !== sanitize_title ( $option ) ) {
continue ;
}
} else {
if ( $variation_selected_value !== $option ) {
continue ;
}
2015-08-13 10:12:24 +00:00
}
2015-08-13 10:32:26 +00:00
$description_value = esc_html ( apply_filters ( 'woocommerce_variation_option_name' , $option ) );
2015-08-13 10:12:24 +00:00
}
2015-08-13 10:32:26 +00:00
}
2015-08-13 10:12:24 +00:00
2015-08-13 10:32:26 +00:00
if ( $flat ) {
$description [] = $description_name . ': ' . rawurldecode ( $description_value );
} else {
$description [] = '<dt>' . $description_name . ':</dt><dd>' . rawurldecode ( $description_value ) . '</dd>' ;
2015-08-13 10:12:24 +00:00
}
}
if ( $flat ) {
2015-08-13 10:32:26 +00:00
$return .= implode ( ', ' , $description );
2015-08-13 10:12:24 +00:00
} else {
2015-08-13 10:32:26 +00:00
$return .= implode ( '' , $description );
2015-08-13 10:12:24 +00:00
}
2015-08-13 10:32:26 +00:00
if ( ! $flat ) {
$return .= '</dl>' ;
}
2015-08-13 10:12:24 +00:00
}
return $return ;
}
2013-03-27 07:57:52 +00:00
/**
2013-03-27 08:06:59 +00:00
* Get product name with extra details such as SKU , price and attributes . Used within admin .
2013-03-27 07:57:52 +00:00
*
2013-03-27 08:06:59 +00:00
* @ return string Formatted product name , including attributes and price
2013-03-27 07:57:52 +00:00
*/
2013-03-27 08:06:59 +00:00
public function get_formatted_name () {
2014-06-24 12:05:13 +00:00
if ( $this -> get_sku () ) {
2013-03-27 07:57:52 +00:00
$identifier = $this -> get_sku ();
2014-06-24 12:05:13 +00:00
} else {
2013-03-27 07:57:52 +00:00
$identifier = '#' . $this -> variation_id ;
2014-06-24 12:05:13 +00:00
}
2013-03-27 07:57:52 +00:00
2015-08-13 10:12:24 +00:00
$formatted_attributes = $this -> get_formatted_variation_attributes ( true );
$extra_data = ' – ' . $formatted_attributes . ' – ' . wc_price ( $this -> get_price () );
2013-03-27 07:57:52 +00:00
return sprintf ( __ ( '%s – %s%s' , 'woocommerce' ), $identifier , $this -> get_title (), $extra_data );
}
2015-05-14 17:56:26 +00:00
/**
2015-11-03 13:31:20 +00:00
* Get product variation description .
2015-05-14 17:56:26 +00:00
*
* @ return string
*/
public function get_variation_description () {
2015-09-21 23:34:06 +00:00
return wpautop ( do_shortcode ( wp_kses_post ( get_post_meta ( $this -> variation_id , '_variation_description' , true ) ) ) );
2015-05-14 17:56:26 +00:00
}
2013-08-07 14:38:31 +00:00
}