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
|
|
|
/**
|
|
|
|
* 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
|
|
|
|
2012-12-14 21:54:13 +00:00
|
|
|
/** @public int ID of the variable product. */
|
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 ) {
|
|
|
|
$all_meta = get_post_meta( $this->variation_id );
|
2012-11-27 16:22:47 +00:00
|
|
|
|
2014-09-16 11:21:09 +00:00
|
|
|
// The variation data array
|
|
|
|
$this->variation_data = array();
|
|
|
|
|
2014-06-24 12:05:13 +00:00
|
|
|
// Get the variation attributes from meta
|
|
|
|
foreach ( $all_meta as $name => $value ) {
|
|
|
|
if ( ! strstr( $name, 'attribute_' ) ) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
$this->variation_data[ $name ] = sanitize_title( $value[0] );
|
|
|
|
}
|
|
|
|
return $this->variation_data;
|
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
|
|
|
|
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 ) {
|
|
|
|
return add_query_arg( 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() {
|
|
|
|
$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 ), $this->variation_data ) ) ) : get_permalink( $this->id );
|
|
|
|
|
|
|
|
return apply_filters( 'woocommerce_product_add_to_cart_url', $url, $this );
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the add to cart button text
|
|
|
|
*
|
|
|
|
* @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
|
|
|
/**
|
2014-09-26 10:45:15 +00:00
|
|
|
* Get variation ID
|
|
|
|
*
|
|
|
|
* @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
|
|
|
/**
|
2014-09-26 10:45:15 +00:00
|
|
|
* Get variation attribute values
|
|
|
|
*
|
|
|
|
* @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
|
|
|
/**
|
2014-10-17 15:24:04 +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 = '' ) {
|
2013-09-19 15:31:54 +00:00
|
|
|
$tax_display_mode = get_option( 'woocommerce_tax_display_shop' );
|
|
|
|
$display_price = $tax_display_mode == 'incl' ? $this->get_price_including_tax() : $this->get_price_excluding_tax();
|
|
|
|
$display_regular_price = $tax_display_mode == 'incl' ? $this->get_price_including_tax( 1, $this->get_regular_price() ) : $this->get_price_excluding_tax( 1, $this->get_regular_price() );
|
|
|
|
$display_sale_price = $tax_display_mode == 'incl' ? $this->get_price_including_tax( 1, $this->get_sale_price() ) : $this->get_price_excluding_tax( 1, $this->get_sale_price() );
|
|
|
|
|
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')
|
|
|
|
* @return string
|
|
|
|
*/
|
|
|
|
public function get_image( $size = 'shop_thumbnail', $attr = array() ) {
|
|
|
|
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);
|
2012-08-12 11:41:26 +00:00
|
|
|
} else {
|
2013-11-25 13:56:59 +00:00
|
|
|
$image = wc_placeholder_img( $size );
|
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 ) {
|
|
|
|
if ( $this->parent->managing_stock() ) {
|
|
|
|
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
|
|
|
}
|
|
|
|
|
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' :
|
|
|
|
$wpdb->query( "UPDATE {$wpdb->postmeta} SET meta_value = meta_value + {$amount} WHERE post_id = {$this->variation_id} AND meta_key='_stock'" );
|
|
|
|
break;
|
|
|
|
case 'subtract' :
|
|
|
|
$wpdb->query( "UPDATE {$wpdb->postmeta} SET meta_value = meta_value - {$amount} WHERE post_id = {$this->variation_id} AND meta_key='_stock'" );
|
|
|
|
break;
|
|
|
|
default :
|
|
|
|
$wpdb->query( "UPDATE {$wpdb->postmeta} SET meta_value = {$amount} WHERE post_id = {$this->variation_id} AND meta_key='_stock'" );
|
|
|
|
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
|
|
|
|
delete_transient( 'wc_product_total_stock_' . $this->id );
|
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
|
|
|
/**
|
|
|
|
* set_stock_status function.
|
|
|
|
*/
|
|
|
|
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
|
|
|
|
2014-08-04 09:51:50 +00:00
|
|
|
if ( true === $this->managing_stock() ) {
|
2014-06-24 12:05:13 +00:00
|
|
|
WC_Product_Variable::sync_stock_status( $this->id );
|
2014-04-25 14:27:58 +00:00
|
|
|
}
|
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();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* is_on_backorder function.
|
|
|
|
*
|
|
|
|
* @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
|
|
|
|
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
|
|
|
|
|
|
|
$attributes = $this->get_variation_attributes();
|
2013-11-25 13:34:21 +00:00
|
|
|
$extra_data = ' – ' . implode( ', ', $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 );
|
|
|
|
}
|
2013-08-07 14:38:31 +00:00
|
|
|
}
|