Product CRUD improvements (#12359)
* args is not used any more - remove todo * Added test for attributes * wc_get_price_excluding_tax usage * parent usage * Fix rating counts * Test fixes * Cleanup after tests * Make sure status transition code runs even during API calls, not just in admin. * Default visibility * Fix attribute setting in API * Use get name instead of get title * variation id usage * Improved cross sell templates * variation_data * Grouped product sync * Notices * Sync is not needed in API * Delete * Rename interfaces * Update counts in data store
This commit is contained in:
parent
d8fcfcefb8
commit
599a2ad296
|
@ -101,6 +101,16 @@ abstract class WC_Data {
|
|||
$this->default_data = $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the data store.
|
||||
*
|
||||
* @since 2.7.0
|
||||
* @return object
|
||||
*/
|
||||
public function get_data_store() {
|
||||
return $this->data_store;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the unique ID for this object.
|
||||
* @return int
|
||||
|
|
|
@ -153,8 +153,8 @@ abstract class WC_Abstract_Legacy_Order extends WC_Data {
|
|||
if ( $product->backorders_require_notification() && $product->is_on_backorder( $args['qty'] ) ) {
|
||||
$item->add_meta_data( apply_filters( 'woocommerce_backordered_item_meta_name', __( 'Backordered', 'woocommerce' ) ), $args['qty'] - max( 0, $product->get_stock_quantity() ), true );
|
||||
}
|
||||
$args['subtotal'] = $args['subtotal'] ? $args['subtotal'] : $product->get_price_excluding_tax( $args['qty'] );
|
||||
$args['total'] = $args['total'] ? $args['total'] : $product->get_price_excluding_tax( $args['qty'] );
|
||||
$args['subtotal'] = $args['subtotal'] ? $args['subtotal'] : wc_get_price_excluding_tax( $product, array( 'qty' => $args['qty'] ) );
|
||||
$args['total'] = $args['total'] ? $args['total'] : wc_get_price_excluding_tax( $product, array( 'qty' => $args['qty'] ) );
|
||||
}
|
||||
|
||||
$item->set_order_id( $this->get_id() );
|
||||
|
|
|
@ -481,7 +481,7 @@ abstract class WC_Abstract_Legacy_Product extends WC_Data {
|
|||
*/
|
||||
public function get_upsells() {
|
||||
_deprecated_function( 'WC_Product::get_upsells', '2.7', 'WC_Product::get_upsell_ids' );
|
||||
return apply_filters( 'woocommerce_product_upsell_ids', (array) maybe_unserialize( $this->upsell_ids ), $this );
|
||||
return apply_filters( 'woocommerce_product_upsell_ids', $this->get_upsell_ids(), $this );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -492,7 +492,7 @@ abstract class WC_Abstract_Legacy_Product extends WC_Data {
|
|||
*/
|
||||
public function get_cross_sells() {
|
||||
_deprecated_function( 'WC_Product::get_cross_sells', '2.7', 'WC_Product::get_cross_sell_ids' );
|
||||
return apply_filters( 'woocommerce_product_crosssell_ids', (array) maybe_unserialize( $this->crosssell_ids ), $this );
|
||||
return apply_filters( 'woocommerce_product_crosssell_ids', $this->get_cross_sell_ids(), $this );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -725,4 +725,11 @@ abstract class WC_Abstract_Legacy_Product extends WC_Data {
|
|||
wc_soft_deprecated_function( 'WC_Product::get_files', '2.7', '2.8', 'WC_Product::get_downloads' );
|
||||
return $this->get_downloads();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprected 2.7.0 Sync is taken care of during save - no need to call this directly.
|
||||
*/
|
||||
public function grouped_product_sync() {
|
||||
_deprecated_function( 'WC_Product::grouped_product_sync', '2.7' );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -978,7 +978,7 @@ abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order {
|
|||
public function add_product( $product, $qty = 1, $args = array() ) {
|
||||
if ( $product ) {
|
||||
$default_args = array(
|
||||
'name' => $product->get_title(),
|
||||
'name' => $product->get_name(),
|
||||
'tax_class' => $product->get_tax_class(),
|
||||
'product_id' => $product->is_type( 'variation' ) ? $product->get_parent_id() : $product->get_id(),
|
||||
'variation_id' => $product->is_type( 'variation' ) ? $product->get_id() : 0,
|
||||
|
|
|
@ -118,6 +118,9 @@ class WC_Product extends WC_Abstract_Legacy_Product {
|
|||
'_downloadable',
|
||||
'_featured',
|
||||
'_downloadable_files',
|
||||
'_wc_rating_count',
|
||||
'_wc_average_rating',
|
||||
'_wc_review_count',
|
||||
);
|
||||
|
||||
/**
|
||||
|
@ -1346,6 +1349,9 @@ class WC_Product extends WC_Abstract_Legacy_Product {
|
|||
} else {
|
||||
$this->data_store->create( $this );
|
||||
}
|
||||
if ( $this->get_parent_id() ) {
|
||||
wp_schedule_single_event( time(), 'woocommerce_deferred_product_sync', array( 'product_id' => $this->get_parent_id() ) );
|
||||
}
|
||||
return $this->get_id();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -274,7 +274,7 @@ abstract class WC_Shipping_Method extends WC_Settings_API {
|
|||
$items_in_package = array();
|
||||
foreach ( $args['package']['contents'] as $item ) {
|
||||
$product = $item['data'];
|
||||
$items_in_package[] = $product->get_title() . ' × ' . $item['quantity'];
|
||||
$items_in_package[] = $product->get_name() . ' × ' . $item['quantity'];
|
||||
}
|
||||
$rate->add_meta_data( __( 'Items', 'woocommerce' ), implode( ', ', $items_in_package ) );
|
||||
}
|
||||
|
|
|
@ -71,13 +71,6 @@ class WC_Admin_Post_Types {
|
|||
add_filter( 'parse_query', array( $this, 'product_filters_query' ) );
|
||||
add_filter( 'posts_search', array( $this, 'product_search' ) );
|
||||
|
||||
// Status transitions
|
||||
add_action( 'delete_post', array( $this, 'delete_post' ) );
|
||||
add_action( 'wp_trash_post', array( $this, 'trash_post' ) );
|
||||
add_action( 'untrash_post', array( $this, 'untrash_post' ) );
|
||||
add_action( 'before_delete_post', array( $this, 'delete_order_items' ) );
|
||||
add_action( 'before_delete_post', array( $this, 'delete_order_downloadable_permissions' ) );
|
||||
|
||||
// Edit post screens
|
||||
add_filter( 'enter_title_here', array( $this, 'enter_title_here' ), 1, 2 );
|
||||
add_action( 'edit_form_after_title', array( $this, 'edit_form_after_title' ) );
|
||||
|
@ -1922,180 +1915,6 @@ class WC_Admin_Post_Types {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes variations etc belonging to a deleted post, and clears transients.
|
||||
*
|
||||
* @param mixed $id ID of post being deleted
|
||||
*/
|
||||
public function delete_post( $id ) {
|
||||
global $woocommerce, $wpdb;
|
||||
|
||||
if ( ! current_user_can( 'delete_posts' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( $id > 0 ) {
|
||||
|
||||
$post_type = get_post_type( $id );
|
||||
|
||||
switch ( $post_type ) {
|
||||
case 'product' :
|
||||
|
||||
$child_product_variations = get_children( 'post_parent=' . $id . '&post_type=product_variation' );
|
||||
|
||||
if ( ! empty( $child_product_variations ) ) {
|
||||
foreach ( $child_product_variations as $child ) {
|
||||
wp_delete_post( $child->ID, true );
|
||||
}
|
||||
}
|
||||
|
||||
$child_products = get_children( 'post_parent=' . $id . '&post_type=product' );
|
||||
|
||||
if ( ! empty( $child_products ) ) {
|
||||
foreach ( $child_products as $child ) {
|
||||
$child_post = array();
|
||||
$child_post['ID'] = $child->ID;
|
||||
$child_post['post_parent'] = 0;
|
||||
wp_update_post( $child_post );
|
||||
}
|
||||
}
|
||||
|
||||
if ( $parent_id = wp_get_post_parent_id( $id ) ) {
|
||||
wc_delete_product_transients( $parent_id );
|
||||
}
|
||||
|
||||
break;
|
||||
case 'product_variation' :
|
||||
wc_delete_product_transients( wp_get_post_parent_id( $id ) );
|
||||
break;
|
||||
case 'shop_order' :
|
||||
$refunds = $wpdb->get_results( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_type = 'shop_order_refund' AND post_parent = %d", $id ) );
|
||||
|
||||
if ( ! is_null( $refunds ) ) {
|
||||
foreach ( $refunds as $refund ) {
|
||||
wp_delete_post( $refund->ID, true );
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* woocommerce_trash_post function.
|
||||
*
|
||||
* @param mixed $id
|
||||
*/
|
||||
public function trash_post( $id ) {
|
||||
global $wpdb;
|
||||
|
||||
if ( $id > 0 ) {
|
||||
|
||||
$post_type = get_post_type( $id );
|
||||
|
||||
if ( in_array( $post_type, wc_get_order_types( 'order-count' ) ) ) {
|
||||
|
||||
// Delete count - meta doesn't work on trashed posts
|
||||
$user_id = get_post_meta( $id, '_customer_user', true );
|
||||
|
||||
if ( $user_id > 0 ) {
|
||||
delete_user_meta( $user_id, '_money_spent' );
|
||||
delete_user_meta( $user_id, '_order_count' );
|
||||
}
|
||||
|
||||
$refunds = $wpdb->get_results( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_type = 'shop_order_refund' AND post_parent = %d", $id ) );
|
||||
|
||||
foreach ( $refunds as $refund ) {
|
||||
$wpdb->update( $wpdb->posts, array( 'post_status' => 'trash' ), array( 'ID' => $refund->ID ) );
|
||||
}
|
||||
|
||||
delete_transient( 'woocommerce_processing_order_count' );
|
||||
wc_delete_shop_order_transients( $id );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* woocommerce_untrash_post function.
|
||||
*
|
||||
* @param mixed $id
|
||||
*/
|
||||
public function untrash_post( $id ) {
|
||||
global $wpdb;
|
||||
|
||||
if ( $id > 0 ) {
|
||||
|
||||
$post_type = get_post_type( $id );
|
||||
|
||||
if ( in_array( $post_type, wc_get_order_types( 'order-count' ) ) ) {
|
||||
|
||||
// Delete count - meta doesn't work on trashed posts
|
||||
$user_id = get_post_meta( $id, '_customer_user', true );
|
||||
|
||||
if ( $user_id > 0 ) {
|
||||
delete_user_meta( $user_id, '_money_spent' );
|
||||
delete_user_meta( $user_id, '_order_count' );
|
||||
}
|
||||
|
||||
$refunds = $wpdb->get_results( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_type = 'shop_order_refund' AND post_parent = %d", $id ) );
|
||||
|
||||
foreach ( $refunds as $refund ) {
|
||||
$wpdb->update( $wpdb->posts, array( 'post_status' => 'wc-completed' ), array( 'ID' => $refund->ID ) );
|
||||
}
|
||||
|
||||
delete_transient( 'woocommerce_processing_order_count' );
|
||||
wc_delete_shop_order_transients( $id );
|
||||
} elseif ( 'product' === $post_type ) {
|
||||
// Check if SKU is valid before untrash the product.
|
||||
$sku = get_post_meta( $id, '_sku', true );
|
||||
|
||||
if ( ! empty( $sku ) ) {
|
||||
if ( ! wc_product_has_unique_sku( $id, $sku ) ) {
|
||||
update_post_meta( $id, '_sku', '' );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove item meta on permanent deletion.
|
||||
*/
|
||||
public function delete_order_items( $postid ) {
|
||||
global $wpdb;
|
||||
|
||||
if ( in_array( get_post_type( $postid ), wc_get_order_types() ) ) {
|
||||
do_action( 'woocommerce_delete_order_items', $postid );
|
||||
|
||||
$wpdb->query( "
|
||||
DELETE {$wpdb->prefix}woocommerce_order_items, {$wpdb->prefix}woocommerce_order_itemmeta
|
||||
FROM {$wpdb->prefix}woocommerce_order_items
|
||||
JOIN {$wpdb->prefix}woocommerce_order_itemmeta ON {$wpdb->prefix}woocommerce_order_items.order_item_id = {$wpdb->prefix}woocommerce_order_itemmeta.order_item_id
|
||||
WHERE {$wpdb->prefix}woocommerce_order_items.order_id = '{$postid}';
|
||||
" );
|
||||
|
||||
do_action( 'woocommerce_deleted_order_items', $postid );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove downloadable permissions on permanent order deletion.
|
||||
*/
|
||||
public function delete_order_downloadable_permissions( $postid ) {
|
||||
global $wpdb;
|
||||
|
||||
if ( in_array( get_post_type( $postid ), wc_get_order_types() ) ) {
|
||||
do_action( 'woocommerce_delete_order_downloadable_permissions', $postid );
|
||||
|
||||
$wpdb->query( $wpdb->prepare( "
|
||||
DELETE FROM {$wpdb->prefix}woocommerce_downloadable_product_permissions
|
||||
WHERE order_id = %d
|
||||
", $postid ) );
|
||||
|
||||
do_action( 'woocommerce_deleted_order_downloadable_permissions', $postid );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Change title boxes in admin.
|
||||
* @param string $text
|
||||
|
|
|
@ -10,7 +10,7 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|||
<button type="button" data-permission_id="<?php echo absint( $download->permission_id ); ?>" rel="<?php echo absint( $download->product_id ) . ',' . esc_attr( $download->download_id ); ?>" class="revoke_access button"><?php _e( 'Revoke access', 'woocommerce' ); ?></button>
|
||||
<div class="handlediv" aria-label="<?php esc_attr_e( 'Click to toggle', 'woocommerce' ); ?>"></div>
|
||||
<strong>
|
||||
<?php echo '#' . absint( $product->get_id() ) . ' — ' . apply_filters( 'woocommerce_admin_download_permissions_title', $product->get_title(), $download->product_id, $download->order_id, $download->order_key, $download->download_id ) . ' — ' . esc_html( $file_count ) . ': ' . wc_get_filename_from_url( $product->get_file_download_path( $download->download_id ) ) . ' — ' . sprintf( _n( 'Downloaded %s time', 'Downloaded %s times', absint( $download->download_count ), 'woocommerce' ), absint( $download->download_count ) ); ?>
|
||||
<?php echo '#' . absint( $product->get_id() ) . ' — ' . apply_filters( 'woocommerce_admin_download_permissions_title', $product->get_name(), $download->product_id, $download->order_id, $download->order_key, $download->download_id ) . ' — ' . esc_html( $file_count ) . ': ' . wc_get_filename_from_url( $product->get_file_download_path( $download->download_id ) ) . ' — ' . sprintf( _n( 'Downloaded %s time', 'Downloaded %s times', absint( $download->download_count ), 'woocommerce' ), absint( $download->download_count ) ); ?>
|
||||
</strong>
|
||||
</h3>
|
||||
<table cellpadding="0" cellspacing="0" class="wc-metabox-content">
|
||||
|
|
|
@ -87,7 +87,7 @@ class WC_Report_Stock extends WP_List_Table {
|
|||
echo $sku . ' - ';
|
||||
}
|
||||
|
||||
echo $product->get_title();
|
||||
echo $product->get_name();
|
||||
|
||||
// Get variation data
|
||||
if ( $product->is_type( 'variation' ) ) {
|
||||
|
|
|
@ -380,7 +380,7 @@ class WC_REST_Product_Variations_Controller extends WC_REST_Products_Controller
|
|||
'visible' => array(
|
||||
'description' => __( "Define if the attribute is visible on the \"Additional information\" tab in the product's page.", 'woocommerce' ),
|
||||
'type' => 'boolean',
|
||||
'default' => false,
|
||||
'default' => true,
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
'purchasable' => array(
|
||||
|
|
|
@ -1154,8 +1154,6 @@ class WC_REST_Products_Controller extends WC_REST_Posts_Controller {
|
|||
$product->set_date_on_sale_from( '' );
|
||||
$product->set_price( '' );
|
||||
} else {
|
||||
$date_from = $date_to = '';
|
||||
|
||||
// Regular Price.
|
||||
if ( isset( $request['regular_price'] ) ) {
|
||||
$product->set_regular_price( $request['regular_price'] );
|
||||
|
@ -1180,46 +1178,6 @@ class WC_REST_Products_Controller extends WC_REST_Posts_Controller {
|
|||
$product->set_parent_id( $request['parent_id'] );
|
||||
}
|
||||
|
||||
// Update parent if grouped so price sorting works and stays in sync with the cheapest child.
|
||||
if ( $product->get_parent_id() > 0 || $product->is_type( 'grouped' ) ) {
|
||||
|
||||
$clear_parent_ids = array();
|
||||
|
||||
if ( $product->get_parent_id() > 0 ) {
|
||||
$clear_parent_ids[] = $product->get_parent_id();
|
||||
$parent = wc_get_product( $product->get_parent_id() );
|
||||
$children = $parent->get_children();
|
||||
$parent->set_children( array_filter( array_merge( $children, array( $product->get_id() ) ) ) );
|
||||
$parent->save();
|
||||
}
|
||||
|
||||
if ( $product->is_type( 'grouped' ) ) {
|
||||
$clear_parent_ids[] = $product->get_id();
|
||||
}
|
||||
|
||||
if ( ! empty( $clear_parent_ids ) ) {
|
||||
foreach ( $clear_parent_ids as $clear_id ) {
|
||||
$clear_product = wc_get_product( $clear_id );
|
||||
$children_by_price = get_posts( array(
|
||||
'post_parent' => $clear_id,
|
||||
'orderby' => 'meta_value_num',
|
||||
'order' => 'asc',
|
||||
'meta_key' => '_price',
|
||||
'posts_per_page' => 1,
|
||||
'post_type' => 'product',
|
||||
'fields' => 'ids',
|
||||
) );
|
||||
|
||||
if ( $children_by_price ) {
|
||||
foreach ( $children_by_price as $child ) {
|
||||
$child_product = wc_get_product( $child );
|
||||
$clear_product->set_price( $child_product->get_price() );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sold individually.
|
||||
if ( isset( $request['sold_individually'] ) ) {
|
||||
$product->set_sold_individually( $request['sold_individually'] );
|
||||
|
@ -1380,7 +1338,6 @@ class WC_REST_Products_Controller extends WC_REST_Posts_Controller {
|
|||
} else {
|
||||
$variations = $request['variations'];
|
||||
}
|
||||
$attributes = $product->get_variation_attributes();
|
||||
|
||||
foreach ( $variations as $menu_order => $data ) {
|
||||
$variation_id = isset( $data['id'] ) ? absint( $data['id'] ) : 0;
|
||||
|
@ -1506,7 +1463,8 @@ class WC_REST_Products_Controller extends WC_REST_Posts_Controller {
|
|||
|
||||
// Update taxonomies.
|
||||
if ( isset( $data['attributes'] ) ) {
|
||||
$_attributes = array();
|
||||
$attributes = array();
|
||||
$parent_attributes = $product->get_attributes();
|
||||
|
||||
foreach ( $data['attributes'] as $attribute ) {
|
||||
$attribute_id = 0;
|
||||
|
@ -1524,30 +1482,28 @@ class WC_REST_Products_Controller extends WC_REST_Posts_Controller {
|
|||
continue;
|
||||
}
|
||||
|
||||
if ( isset( $attributes[ $attribute_name ] ) ) {
|
||||
$_attribute = $attributes[ $attribute_name ];
|
||||
if ( ! isset( $parent_attributes[ $attribute_name ] ) || ! $parent_attributes[ $attribute_name ]->get_variation() ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( isset( $_attribute['is_variation'] ) && $_attribute['is_variation'] ) {
|
||||
$_attribute_key = sanitize_title( $_attribute['name'] );
|
||||
$attribute_value = isset( $attribute['option'] ) ? wc_clean( stripslashes( $attribute['option'] ) ) : '';
|
||||
$attribute_key = sanitize_title( $parent_attributes[ $attribute_name ]->get_name() );
|
||||
$attribute_value = isset( $attribute['option'] ) ? wc_clean( stripslashes( $attribute['option'] ) ) : '';
|
||||
|
||||
if ( ! empty( $_attribute['is_taxonomy'] ) ) {
|
||||
// If dealing with a taxonomy, we need to get the slug from the name posted to the API.
|
||||
$term = get_term_by( 'name', $attribute_value, $attribute_name );
|
||||
if ( $parent_attributes[ $attribute_name ]->is_taxonomy() ) {
|
||||
// If dealing with a taxonomy, we need to get the slug from the name posted to the API.
|
||||
$term = get_term_by( 'name', $attribute_value, $attribute_name );
|
||||
|
||||
if ( $term && ! is_wp_error( $term ) ) {
|
||||
$attribute_value = $term->slug;
|
||||
} else {
|
||||
$attribute_value = sanitize_title( $attribute_value );
|
||||
}
|
||||
if ( $term && ! is_wp_error( $term ) ) {
|
||||
$attribute_value = $term->slug;
|
||||
} else {
|
||||
$attribute_value = sanitize_title( $attribute_value );
|
||||
}
|
||||
|
||||
$_attributes[ $_attribute_key ] = $attribute_value;
|
||||
}
|
||||
|
||||
$attributes[ $attribute_key ] = $attribute_value;
|
||||
}
|
||||
|
||||
$variation->set_attributes( $_attributes );
|
||||
$variation->set_attributes( $attributes );
|
||||
}
|
||||
|
||||
$variation->save();
|
||||
|
|
|
@ -80,7 +80,7 @@ class WC_REST_Report_Top_Sellers_Controller extends WC_REST_Report_Sales_Control
|
|||
|
||||
if ( $product ) {
|
||||
$top_sellers[] = array(
|
||||
'name' => $product->get_title(),
|
||||
'name' => $product->get_name(),
|
||||
'product_id' => (int) $item->product_id,
|
||||
'quantity' => wc_stock_amount( $item->order_item_qty ),
|
||||
);
|
||||
|
|
|
@ -315,7 +315,7 @@ class WC_API_Products extends WC_API_Resource {
|
|||
'categories' => wp_get_post_terms( $product->get_id(), 'product_cat', array( 'fields' => 'names' ) ),
|
||||
'tags' => wp_get_post_terms( $product->get_id(), 'product_tag', array( 'fields' => 'names' ) ),
|
||||
'images' => $this->get_images( $product ),
|
||||
'featured_src' => wp_get_attachment_url( get_post_thumbnail_id( $product->is_type( 'variation' ) ? $product->variation_id : $product->get_id() ) ),
|
||||
'featured_src' => wp_get_attachment_url( get_post_thumbnail_id( $product->get_id() ) ),
|
||||
'attributes' => $this->get_attributes( $product ),
|
||||
'downloads' => $this->get_downloads( $product ),
|
||||
'download_limit' => $product->get_download_limit(),
|
||||
|
|
|
@ -399,7 +399,7 @@ class WC_API_Reports extends WC_API_Resource {
|
|||
$product = wc_get_product( $top_seller->product_id );
|
||||
|
||||
$top_sellers_data[] = array(
|
||||
'title' => $product->get_title(),
|
||||
'title' => $product->get_name(),
|
||||
'product_id' => $top_seller->product_id,
|
||||
'quantity' => $top_seller->order_item_qty,
|
||||
);
|
||||
|
|
|
@ -735,7 +735,7 @@ class WC_API_Products extends WC_API_Resource {
|
|||
'categories' => wp_get_post_terms( $product->get_id(), 'product_cat', array( 'fields' => 'names' ) ),
|
||||
'tags' => wp_get_post_terms( $product->get_id(), 'product_tag', array( 'fields' => 'names' ) ),
|
||||
'images' => $this->get_images( $product ),
|
||||
'featured_src' => wp_get_attachment_url( get_post_thumbnail_id( $product->is_type( 'variation' ) ? $product->variation_id : $product->get_id() ) ),
|
||||
'featured_src' => wp_get_attachment_url( get_post_thumbnail_id( $product->get_id() ) ),
|
||||
'attributes' => $this->get_attributes( $product ),
|
||||
'downloads' => $this->get_downloads( $product ),
|
||||
'download_limit' => $product->get_download_limit(),
|
||||
|
@ -1072,16 +1072,6 @@ class WC_API_Products extends WC_API_Resource {
|
|||
$product->set_parent_id( absint( $data['parent_id'] ) );
|
||||
}
|
||||
|
||||
// Update parent if grouped so price sorting works and stays in sync with the cheapest child
|
||||
if ( $product->get_parent_id() > 0 || $product->is_type( 'grouped' ) ) {
|
||||
if ( $product->get_parent_id() > 0 ) {
|
||||
$parent = wc_get_product( $product->get_parent_id() );
|
||||
$children = $parent->get_children();
|
||||
$parent->set_children( array_filter( array_merge( $children, array( $product->get_id() ) ) ) );
|
||||
$parent->save();
|
||||
}
|
||||
}
|
||||
|
||||
// Sold Individually
|
||||
if ( isset( $data['sold_individually'] ) ) {
|
||||
$product->set_sold_individually( true === $data['sold_individually'] ? 'yes' : '' );
|
||||
|
|
|
@ -247,7 +247,7 @@ class WC_API_Reports extends WC_API_Resource {
|
|||
|
||||
if ( $product ) {
|
||||
$top_sellers_data[] = array(
|
||||
'title' => $product->get_title(),
|
||||
'title' => $product->get_name(),
|
||||
'product_id' => $top_seller->product_id,
|
||||
'quantity' => $top_seller->order_item_qty,
|
||||
);
|
||||
|
|
|
@ -1180,7 +1180,7 @@ class WC_API_Products extends WC_API_Resource {
|
|||
'categories' => wp_get_post_terms( $product->get_id(), 'product_cat', array( 'fields' => 'names' ) ),
|
||||
'tags' => wp_get_post_terms( $product->get_id(), 'product_tag', array( 'fields' => 'names' ) ),
|
||||
'images' => $this->get_images( $product ),
|
||||
'featured_src' => wp_get_attachment_url( get_post_thumbnail_id( $product->is_type( 'variation' ) ? $product->variation_id : $product->get_id() ) ),
|
||||
'featured_src' => wp_get_attachment_url( get_post_thumbnail_id( $product->get_id() ) ),
|
||||
'attributes' => $this->get_attributes( $product ),
|
||||
'downloads' => $this->get_downloads( $product ),
|
||||
'download_limit' => $product->get_download_limit(),
|
||||
|
@ -1557,16 +1557,6 @@ class WC_API_Products extends WC_API_Resource {
|
|||
$product->set_parent_id( absint( $data['parent_id'] ) );
|
||||
}
|
||||
|
||||
// Update parent if grouped so price sorting works and stays in sync with the cheapest child.
|
||||
if ( $product->get_parent_id() > 0 || $product->is_type( 'grouped' ) ) {
|
||||
if ( $product->get_parent_id() > 0 ) {
|
||||
$parent = wc_get_product( $product->get_parent_id() );
|
||||
$children = $parent->get_children();
|
||||
$parent->set_children( array_filter( array_merge( $children, array( $product->get_id() ) ) ) );
|
||||
$parent->save();
|
||||
}
|
||||
}
|
||||
|
||||
// Sold Individually.
|
||||
if ( isset( $data['sold_individually'] ) ) {
|
||||
$product->set_sold_individually( true === $data['sold_individually'] ? 'yes' : '' );
|
||||
|
|
|
@ -247,7 +247,7 @@ class WC_API_Reports extends WC_API_Resource {
|
|||
|
||||
if ( $product ) {
|
||||
$top_sellers_data[] = array(
|
||||
'title' => $product->get_title(),
|
||||
'title' => $product->get_name(),
|
||||
'product_id' => $top_seller->product_id,
|
||||
'quantity' => $top_seller->order_item_qty,
|
||||
);
|
||||
|
|
|
@ -1061,13 +1061,7 @@ class WC_AJAX {
|
|||
$stock_change = apply_filters( 'woocommerce_reduce_order_stock_quantity', $order_item_qty[ $item_id ], $item_id );
|
||||
$new_stock = $_product->reduce_stock( $stock_change );
|
||||
$item_name = $_product->get_sku() ? $_product->get_sku() : $_product->get_id();
|
||||
|
||||
if ( ! empty( $_product->variation_id ) ) {
|
||||
$note = sprintf( __( 'Item %1$s variation #%2$s stock reduced from %3$s to %4$s.', 'woocommerce' ), $item_name, $_product->variation_id, $new_stock + $stock_change, $new_stock );
|
||||
} else {
|
||||
$note = sprintf( __( 'Item %1$s stock reduced from %2$s to %3$s.', 'woocommerce' ), $item_name, $new_stock + $stock_change, $new_stock );
|
||||
}
|
||||
|
||||
$note = sprintf( __( 'Item %1$s stock reduced from %2$s to %3$s.', 'woocommerce' ), $item_name, $new_stock + $stock_change, $new_stock );
|
||||
$return[] = $note;
|
||||
$order->add_order_note( $note );
|
||||
}
|
||||
|
@ -1107,13 +1101,7 @@ class WC_AJAX {
|
|||
$stock_change = apply_filters( 'woocommerce_restore_order_stock_quantity', $order_item_qty[ $item_id ], $item_id );
|
||||
$new_quantity = $_product->increase_stock( $stock_change );
|
||||
$item_name = $_product->get_sku() ? $_product->get_sku() : $_product->get_id();
|
||||
|
||||
if ( ! empty( $_product->variation_id ) ) {
|
||||
$note = sprintf( __( 'Item %1$s variation #%2$s stock increased from %3$s to %4$s.', 'woocommerce' ), $item_name, $_product->variation_id, $old_stock, $new_quantity );
|
||||
} else {
|
||||
$note = sprintf( __( 'Item %1$s stock increased from %2$s to %3$s.', 'woocommerce' ), $item_name, $old_stock, $new_quantity );
|
||||
}
|
||||
|
||||
$note = sprintf( __( 'Item %1$s stock increased from %2$s to %3$s.', 'woocommerce' ), $item_name, $old_stock, $new_quantity );
|
||||
$return[] = $note;
|
||||
$order->add_order_note( $note );
|
||||
}
|
||||
|
|
|
@ -236,7 +236,7 @@ class WC_Cart {
|
|||
// Flag to indicate the stored cart should be update
|
||||
$update_cart_session = true;
|
||||
/* translators: %s: product name */
|
||||
wc_add_notice( sprintf( __( '%s has been removed from your cart because it can no longer be purchased. Please contact us if you need assistance.', 'woocommerce' ), $product->get_title() ), 'error' );
|
||||
wc_add_notice( sprintf( __( '%s has been removed from your cart because it can no longer be purchased. Please contact us if you need assistance.', 'woocommerce' ), $product->get_name() ), 'error' );
|
||||
do_action( 'woocommerce_remove_cart_item_from_session', $key, $values );
|
||||
|
||||
} else {
|
||||
|
@ -476,7 +476,7 @@ class WC_Cart {
|
|||
*/
|
||||
if ( ! $product->is_in_stock() ) {
|
||||
/* translators: %s: product name */
|
||||
$error->add( 'out-of-stock', sprintf( __( 'Sorry, "%s" is not in stock. Please edit your cart and try again. We apologise for any inconvenience caused.', 'woocommerce' ), $product->get_title() ) );
|
||||
$error->add( 'out-of-stock', sprintf( __( 'Sorry, "%s" is not in stock. Please edit your cart and try again. We apologise for any inconvenience caused.', 'woocommerce' ), $product->get_name() ) );
|
||||
return $error;
|
||||
}
|
||||
|
||||
|
@ -489,7 +489,7 @@ class WC_Cart {
|
|||
*/
|
||||
if ( ! $product->has_enough_stock( $product_qty_in_cart[ $product->get_stock_managed_by_id() ] ) ) {
|
||||
/* translators: 1: product name 2: quantity in stock */
|
||||
$error->add( 'out-of-stock', sprintf( __( 'Sorry, we do not have enough "%1$s" in stock to fulfill your order (%2$s in stock). Please edit your cart and try again. We apologise for any inconvenience caused.', 'woocommerce' ), $product->get_title(), $product->get_stock_quantity() ) );
|
||||
$error->add( 'out-of-stock', sprintf( __( 'Sorry, we do not have enough "%1$s" in stock to fulfill your order (%2$s in stock). Please edit your cart and try again. We apologise for any inconvenience caused.', 'woocommerce' ), $product->get_name(), $product->get_stock_quantity() ) );
|
||||
return $error;
|
||||
}
|
||||
|
||||
|
@ -518,7 +518,7 @@ class WC_Cart {
|
|||
|
||||
if ( $product->get_stock_quantity() < ( $held_stock + $product_qty_in_cart[ $product->get_stock_managed_by_id() ] ) ) {
|
||||
/* translators: 1: product name 2: minutes */
|
||||
$error->add( 'out-of-stock', sprintf( __( 'Sorry, we do not have enough "%1$s" in stock to fulfill your order right now. Please try again in %2$d minutes or edit your cart and try again. We apologise for any inconvenience caused.', 'woocommerce' ), $product->get_title(), get_option( 'woocommerce_hold_stock_minutes' ) ) );
|
||||
$error->add( 'out-of-stock', sprintf( __( 'Sorry, we do not have enough "%1$s" in stock to fulfill your order right now. Please try again in %2$d minutes or edit your cart and try again. We apologise for any inconvenience caused.', 'woocommerce' ), $product->get_name(), get_option( 'woocommerce_hold_stock_minutes' ) ) );
|
||||
return $error;
|
||||
}
|
||||
}
|
||||
|
@ -538,12 +538,13 @@ class WC_Cart {
|
|||
$item_data = array();
|
||||
|
||||
// Variation data
|
||||
if ( ! empty( $cart_item['data']->variation_id ) && is_array( $cart_item['variation'] ) ) {
|
||||
if ( $cart_item['data']->is_type( 'variation' ) && is_array( $cart_item['variation'] ) ) {
|
||||
|
||||
foreach ( $cart_item['variation'] as $name => $value ) {
|
||||
|
||||
if ( '' === $value )
|
||||
if ( '' === $value ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$taxonomy = wc_attribute_taxonomy_name( str_replace( 'attribute_pa_', '', urldecode( $name ) ) );
|
||||
|
||||
|
@ -616,7 +617,7 @@ class WC_Cart {
|
|||
if ( ! $this->is_empty() ) {
|
||||
foreach ( $this->get_cart() as $cart_item_key => $values ) {
|
||||
if ( $values['quantity'] > 0 ) {
|
||||
$cross_sells = array_merge( $values['data']->get_cross_sells(), $cross_sells );
|
||||
$cross_sells = array_merge( $values['data']->get_cross_sell_ids(), $cross_sells );
|
||||
$in_cart[] = $values['product_id'];
|
||||
}
|
||||
}
|
||||
|
@ -892,7 +893,7 @@ class WC_Cart {
|
|||
$product_data = wc_get_product( $variation_id ? $variation_id : $product_id );
|
||||
|
||||
// Sanity check
|
||||
if ( $quantity <= 0 || ! $product_data || 'trash' === $product_data->post->post_status ) {
|
||||
if ( $quantity <= 0 || ! $product_data || 'trash' === $product_data->get_status() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -912,7 +913,7 @@ class WC_Cart {
|
|||
|
||||
if ( $in_cart_quantity > 0 ) {
|
||||
/* translators: %s: product name */
|
||||
throw new Exception( sprintf( '<a href="%s" class="button wc-forward">%s</a> %s', wc_get_cart_url(), __( 'View cart', 'woocommerce' ), sprintf( __( 'You cannot add another "%s" to your cart.', 'woocommerce' ), $product_data->get_title() ) ) );
|
||||
throw new Exception( sprintf( '<a href="%s" class="button wc-forward">%s</a> %s', wc_get_cart_url(), __( 'View cart', 'woocommerce' ), sprintf( __( 'You cannot add another "%s" to your cart.', 'woocommerce' ), $product_data->get_name() ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -923,12 +924,12 @@ class WC_Cart {
|
|||
|
||||
// Stock check - only check if we're managing stock and backorders are not allowed
|
||||
if ( ! $product_data->is_in_stock() ) {
|
||||
throw new Exception( sprintf( __( 'You cannot add "%s" to the cart because the product is out of stock.', 'woocommerce' ), $product_data->get_title() ) );
|
||||
throw new Exception( sprintf( __( 'You cannot add "%s" to the cart because the product is out of stock.', 'woocommerce' ), $product_data->get_name() ) );
|
||||
}
|
||||
|
||||
if ( ! $product_data->has_enough_stock( $quantity ) ) {
|
||||
/* translators: 1: product name 2: quantity in stock */
|
||||
throw new Exception( sprintf( __( 'You cannot add that amount of "%1$s" to the cart because there is not enough stock (%2$s remaining).', 'woocommerce' ), $product_data->get_title(), $product_data->get_stock_quantity() ) );
|
||||
throw new Exception( sprintf( __( 'You cannot add that amount of "%1$s" to the cart because there is not enough stock (%2$s remaining).', 'woocommerce' ), $product_data->get_name(), $product_data->get_stock_quantity() ) );
|
||||
}
|
||||
|
||||
// Stock check - this time accounting for whats already in-cart
|
||||
|
@ -2127,7 +2128,7 @@ class WC_Cart {
|
|||
|
||||
if ( 'excl' === $this->tax_display_cart ) {
|
||||
|
||||
$row_price = $product->get_price_excluding_tax( $quantity );
|
||||
$row_price = wc_get_price_excluding_tax( $product, array( 'qty' => $quantity ) );
|
||||
$product_subtotal = wc_price( $row_price );
|
||||
|
||||
if ( $this->prices_include_tax && $this->tax_total > 0 ) {
|
||||
|
@ -2135,7 +2136,7 @@ class WC_Cart {
|
|||
}
|
||||
} else {
|
||||
|
||||
$row_price = $product->get_price_including_tax( $quantity );
|
||||
$row_price = wc_get_price_including_tax( $product, array( 'qty' => $quantity ) );
|
||||
$product_subtotal = wc_price( $row_price );
|
||||
|
||||
if ( ! $this->prices_include_tax && $this->tax_total > 0 ) {
|
||||
|
|
|
@ -232,10 +232,10 @@ class WC_Checkout {
|
|||
$product = $values['data'];
|
||||
$item = new WC_Order_Item_Product( array(
|
||||
'quantity' => $values['quantity'],
|
||||
'name' => $product ? $product->get_title() : '',
|
||||
'name' => $product ? $product->get_name() : '',
|
||||
'tax_class' => $product ? $product->get_tax_class() : '',
|
||||
'product_id' => $product && isset( $product->id ) ? $product->id : 0,
|
||||
'variation_id' => $product && isset( $product->variation_id ) ? $product->variation_id : 0,
|
||||
'product_id' => $product ? ( $product->is_type( 'variation' ) ? $product->get_parent_id() : $product->get_id() ) : 0,
|
||||
'variation_id' => $product && $product->is_type( 'variation' ) ? $product->get_id() : 0,
|
||||
'variation' => $values['variation'],
|
||||
'subtotal' => $values['line_subtotal'],
|
||||
'total' => $values['line_total'],
|
||||
|
|
|
@ -239,9 +239,9 @@ class WC_Comments {
|
|||
|
||||
if ( 'product' === get_post_type( $post_id ) ) {
|
||||
$product = wc_get_product( $post_id );
|
||||
update_post_meta( $post_id, '_wc_rating_count', self::get_rating_counts_for_product( $product ) );
|
||||
update_post_meta( $post_id, '_wc_average_rating', self::get_average_rating_for_product( $product ) );
|
||||
update_post_meta( $post_id, '_wc_review_count', self::get_review_count_for_product( $product ) );
|
||||
self::get_rating_counts_for_product( $product );
|
||||
self::get_average_rating_for_product( $product );
|
||||
self::get_review_count_for_product( $product );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -336,7 +336,7 @@ class WC_Comments {
|
|||
* @param WC_Product $product
|
||||
* @return float
|
||||
*/
|
||||
public static function get_average_rating_for_product( $product ) {
|
||||
public static function get_average_rating_for_product( &$product ) {
|
||||
global $wpdb;
|
||||
|
||||
$count = $product->get_rating_count();
|
||||
|
@ -355,7 +355,10 @@ class WC_Comments {
|
|||
$average = 0;
|
||||
}
|
||||
|
||||
update_post_meta( $product->get_id(), '_wc_average_rating', true );
|
||||
$product->set_average_rating( $average );
|
||||
|
||||
$data_store = $product->get_data_store();
|
||||
$data_store->update_average_rating( $product );
|
||||
|
||||
return $average;
|
||||
}
|
||||
|
@ -367,7 +370,7 @@ class WC_Comments {
|
|||
* @param WC_Product $product
|
||||
* @return int
|
||||
*/
|
||||
public static function get_review_count_for_product( $product ) {
|
||||
public static function get_review_count_for_product( &$product ) {
|
||||
global $wpdb;
|
||||
|
||||
$count = $wpdb->get_var( $wpdb->prepare("
|
||||
|
@ -377,7 +380,10 @@ class WC_Comments {
|
|||
AND comment_approved = '1'
|
||||
", $product->get_id() ) );
|
||||
|
||||
update_post_meta( $product->get_id(), '_wc_review_count', true );
|
||||
$product->set_review_count( $count );
|
||||
|
||||
$data_store = $product->get_data_store();
|
||||
$data_store->update_review_count( $product );
|
||||
|
||||
return $count;
|
||||
}
|
||||
|
@ -389,7 +395,7 @@ class WC_Comments {
|
|||
* @param WC_Product $product
|
||||
* @return array of integers
|
||||
*/
|
||||
public static function get_rating_counts_for_product( $product ) {
|
||||
public static function get_rating_counts_for_product( &$product ) {
|
||||
global $wpdb;
|
||||
|
||||
$counts = array();
|
||||
|
@ -407,7 +413,10 @@ class WC_Comments {
|
|||
$counts[ $count->meta_value ] = absint( $count->meta_value_count );
|
||||
}
|
||||
|
||||
update_post_meta( $product->get_id(), '_wc_rating_count', true );
|
||||
$product->set_rating_counts( $counts );
|
||||
|
||||
$data_store = $product->get_data_store();
|
||||
$data_store->update_rating_counts( $product );
|
||||
|
||||
return $counts;
|
||||
}
|
||||
|
|
|
@ -391,9 +391,9 @@ class WC_Coupon extends WC_Legacy_Coupon {
|
|||
* Uses price inc tax if prices include tax to work around https://github.com/woocommerce/woocommerce/issues/7669 and https://github.com/woocommerce/woocommerce/issues/8074.
|
||||
*/
|
||||
if ( wc_prices_include_tax() ) {
|
||||
$discount_percent = ( $cart_item['data']->get_price_including_tax() * $cart_item_qty ) / WC()->cart->subtotal;
|
||||
$discount_percent = ( wc_get_price_including_tax( $cart_item['data'] ) * $cart_item_qty ) / WC()->cart->subtotal;
|
||||
} else {
|
||||
$discount_percent = ( $cart_item['data']->get_price_excluding_tax() * $cart_item_qty ) / WC()->cart->subtotal_ex_tax;
|
||||
$discount_percent = ( wc_get_price_excluding_tax( $cart_item['data'] ) * $cart_item_qty ) / WC()->cart->subtotal_ex_tax;
|
||||
}
|
||||
$discount = ( $this->get_amount() * $discount_percent ) / $cart_item_qty;
|
||||
|
||||
|
@ -845,7 +845,7 @@ class WC_Coupon extends WC_Legacy_Coupon {
|
|||
$valid_for_cart = false;
|
||||
if ( ! WC()->cart->is_empty() ) {
|
||||
foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
|
||||
if ( in_array( $cart_item['product_id'], $this->get_product_ids() ) || in_array( $cart_item['variation_id'], $this->get_product_ids() ) || in_array( $cart_item['data']->get_parent(), $this->get_product_ids() ) ) {
|
||||
if ( in_array( $cart_item['product_id'], $this->get_product_ids() ) || in_array( $cart_item['variation_id'], $this->get_product_ids() ) || in_array( $cart_item['data']->get_parent_id(), $this->get_product_ids() ) ) {
|
||||
$valid_for_cart = true;
|
||||
}
|
||||
}
|
||||
|
@ -949,7 +949,7 @@ class WC_Coupon extends WC_Legacy_Coupon {
|
|||
$valid_for_cart = true;
|
||||
if ( ! WC()->cart->is_empty() ) {
|
||||
foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
|
||||
if ( in_array( $cart_item['product_id'], $this->get_excluded_product_ids() ) || in_array( $cart_item['variation_id'], $this->get_excluded_product_ids() ) || in_array( $cart_item['data']->get_parent(), $this->get_excluded_product_ids() ) ) {
|
||||
if ( in_array( $cart_item['product_id'], $this->get_excluded_product_ids() ) || in_array( $cart_item['variation_id'], $this->get_excluded_product_ids() ) || in_array( $cart_item['data']->get_parent_id(), $this->get_excluded_product_ids() ) ) {
|
||||
$valid_for_cart = false;
|
||||
}
|
||||
}
|
||||
|
@ -1061,7 +1061,7 @@ class WC_Coupon extends WC_Legacy_Coupon {
|
|||
|
||||
$valid = false;
|
||||
$product_cats = wc_get_product_cat_ids( $product->get_id() );
|
||||
$product_ids = array( $product->get_id(), ( isset( $product->variation_id ) ? $product->variation_id : 0 ), $product->get_parent() );
|
||||
$product_ids = array( $product->get_id(), $product->get_parent_id() );
|
||||
|
||||
// Specific products get the discount
|
||||
if ( sizeof( $this->get_product_ids() ) && sizeof( array_intersect( $product_ids, $this->get_product_ids() ) ) ) {
|
||||
|
@ -1092,11 +1092,7 @@ class WC_Coupon extends WC_Legacy_Coupon {
|
|||
if ( $this->get_exclude_sale_items() ) {
|
||||
$product_ids_on_sale = wc_get_product_ids_on_sale();
|
||||
|
||||
if ( isset( $product->variation_id ) ) {
|
||||
if ( in_array( $product->variation_id, $product_ids_on_sale, true ) ) {
|
||||
$valid = false;
|
||||
}
|
||||
} elseif ( in_array( $product->get_id(), $product_ids_on_sale, true ) ) {
|
||||
if ( in_array( $product->get_id(), $product_ids_on_sale, true ) ) {
|
||||
$valid = false;
|
||||
}
|
||||
}
|
||||
|
@ -1197,7 +1193,7 @@ class WC_Coupon extends WC_Legacy_Coupon {
|
|||
$products = array();
|
||||
if ( ! WC()->cart->is_empty() ) {
|
||||
foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
|
||||
if ( in_array( $cart_item['product_id'], $this->get_excluded_product_ids() ) || in_array( $cart_item['variation_id'], $this->get_excluded_product_ids() ) || in_array( $cart_item['data']->get_parent(), $this->get_excluded_product_ids() ) ) {
|
||||
if ( in_array( $cart_item['product_id'], $this->get_excluded_product_ids() ) || in_array( $cart_item['variation_id'], $this->get_excluded_product_ids() ) || in_array( $cart_item['data']->get_parent_id(), $this->get_excluded_product_ids() ) ) {
|
||||
$products[] = $cart_item['data']->get_title();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -485,7 +485,7 @@ class WC_Form_Handler {
|
|||
|
||||
$product = wc_get_product( $cart_item['product_id'] );
|
||||
|
||||
$item_removed_title = apply_filters( 'woocommerce_cart_item_removed_title', $product ? sprintf( _x( '“%s”', 'Item name in quotes', 'woocommerce' ), $product->get_title() ) : __( 'Item', 'woocommerce' ), $cart_item );
|
||||
$item_removed_title = apply_filters( 'woocommerce_cart_item_removed_title', $product ? sprintf( _x( '“%s”', 'Item name in quotes', 'woocommerce' ), $product->get_name() ) : __( 'Item', 'woocommerce' ), $cart_item );
|
||||
|
||||
// Don't show undo link if removed item is out of stock.
|
||||
if ( $product->is_in_stock() && $product->has_enough_stock( $cart_item['quantity'] ) ) {
|
||||
|
@ -542,7 +542,7 @@ class WC_Form_Handler {
|
|||
|
||||
// is_sold_individually
|
||||
if ( $_product->is_sold_individually() && $quantity > 1 ) {
|
||||
wc_add_notice( sprintf( __( 'You can only have 1 %s in your cart.', 'woocommerce' ), $_product->get_title() ), 'error' );
|
||||
wc_add_notice( sprintf( __( 'You can only have 1 %s in your cart.', 'woocommerce' ), $_product->get_name() ), 'error' );
|
||||
$passed_validation = false;
|
||||
}
|
||||
|
||||
|
@ -805,13 +805,14 @@ class WC_Form_Handler {
|
|||
$variation_id = $data_store->find_matching_product_variation( $adding_to_cart, wp_unslash( $_POST ) );
|
||||
}
|
||||
|
||||
$variation = wc_get_product( $variation_id );
|
||||
|
||||
// Validate the attributes.
|
||||
try {
|
||||
if ( empty( $variation_id ) ) {
|
||||
throw new Exception( __( 'Please choose product options…', 'woocommerce' ) );
|
||||
}
|
||||
|
||||
$variation_data = wc_get_product_variation_attributes( $variation_id );
|
||||
|
||||
foreach ( $attributes as $attribute ) {
|
||||
if ( ! $attribute['is_variation'] ) {
|
||||
continue;
|
||||
|
@ -829,7 +830,7 @@ class WC_Form_Handler {
|
|||
}
|
||||
|
||||
// Get valid value from variation
|
||||
$valid_value = isset( $variation->variation_data[ $taxonomy ] ) ? $variation->variation_data[ $taxonomy ] : '';
|
||||
$valid_value = isset( $variation_data[ $taxonomy ] ) ? $variation_data[ $taxonomy ] : '';
|
||||
|
||||
// Allow if valid or show error.
|
||||
if ( '' === $valid_value || $valid_value === $value ) {
|
||||
|
|
|
@ -371,7 +371,7 @@ class WC_Order_Item_Product extends WC_Order_Item {
|
|||
} else {
|
||||
$this->set_product_id( $product->get_id() );
|
||||
}
|
||||
$this->set_name( $product->get_title() );
|
||||
$this->set_name( $product->get_name() );
|
||||
$this->set_tax_class( $product->get_tax_class() );
|
||||
}
|
||||
|
||||
|
|
|
@ -40,6 +40,13 @@ class WC_Post_Data {
|
|||
add_filter( 'update_order_item_metadata', array( __CLASS__, 'update_order_item_metadata' ), 10, 5 );
|
||||
add_filter( 'update_post_metadata', array( __CLASS__, 'update_post_metadata' ), 10, 5 );
|
||||
add_filter( 'wp_insert_post_data', array( __CLASS__, 'wp_insert_post_data' ) );
|
||||
|
||||
// Status transitions
|
||||
add_action( 'delete_post', array( __CLASS__, 'delete_post' ) );
|
||||
add_action( 'wp_trash_post', array( __CLASS__, 'trash_post' ) );
|
||||
add_action( 'untrash_post', array( __CLASS__, 'untrash_post' ) );
|
||||
add_action( 'before_delete_post', array( __CLASS__, 'delete_order_items' ) );
|
||||
add_action( 'before_delete_post', array( __CLASS__, 'delete_order_downloadable_permissions' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -213,6 +220,180 @@ class WC_Post_Data {
|
|||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes variations etc belonging to a deleted post, and clears transients.
|
||||
*
|
||||
* @param mixed $id ID of post being deleted
|
||||
*/
|
||||
public static function delete_post( $id ) {
|
||||
global $woocommerce, $wpdb;
|
||||
|
||||
if ( ! current_user_can( 'delete_posts' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( $id > 0 ) {
|
||||
|
||||
$post_type = get_post_type( $id );
|
||||
|
||||
switch ( $post_type ) {
|
||||
case 'product' :
|
||||
|
||||
$child_product_variations = get_children( 'post_parent=' . $id . '&post_type=product_variation' );
|
||||
|
||||
if ( ! empty( $child_product_variations ) ) {
|
||||
foreach ( $child_product_variations as $child ) {
|
||||
wp_delete_post( $child->ID, true );
|
||||
}
|
||||
}
|
||||
|
||||
$child_products = get_children( 'post_parent=' . $id . '&post_type=product' );
|
||||
|
||||
if ( ! empty( $child_products ) ) {
|
||||
foreach ( $child_products as $child ) {
|
||||
$child_post = array();
|
||||
$child_post['ID'] = $child->ID;
|
||||
$child_post['post_parent'] = 0;
|
||||
wp_update_post( $child_post );
|
||||
}
|
||||
}
|
||||
|
||||
if ( $parent_id = wp_get_post_parent_id( $id ) ) {
|
||||
wc_delete_product_transients( $parent_id );
|
||||
}
|
||||
|
||||
break;
|
||||
case 'product_variation' :
|
||||
wc_delete_product_transients( wp_get_post_parent_id( $id ) );
|
||||
break;
|
||||
case 'shop_order' :
|
||||
$refunds = $wpdb->get_results( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_type = 'shop_order_refund' AND post_parent = %d", $id ) );
|
||||
|
||||
if ( ! is_null( $refunds ) ) {
|
||||
foreach ( $refunds as $refund ) {
|
||||
wp_delete_post( $refund->ID, true );
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* woocommerce_trash_post function.
|
||||
*
|
||||
* @param mixed $id
|
||||
*/
|
||||
public static function trash_post( $id ) {
|
||||
global $wpdb;
|
||||
|
||||
if ( $id > 0 ) {
|
||||
|
||||
$post_type = get_post_type( $id );
|
||||
|
||||
if ( in_array( $post_type, wc_get_order_types( 'order-count' ) ) ) {
|
||||
|
||||
// Delete count - meta doesn't work on trashed posts
|
||||
$user_id = get_post_meta( $id, '_customer_user', true );
|
||||
|
||||
if ( $user_id > 0 ) {
|
||||
delete_user_meta( $user_id, '_money_spent' );
|
||||
delete_user_meta( $user_id, '_order_count' );
|
||||
}
|
||||
|
||||
$refunds = $wpdb->get_results( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_type = 'shop_order_refund' AND post_parent = %d", $id ) );
|
||||
|
||||
foreach ( $refunds as $refund ) {
|
||||
$wpdb->update( $wpdb->posts, array( 'post_status' => 'trash' ), array( 'ID' => $refund->ID ) );
|
||||
}
|
||||
|
||||
delete_transient( 'woocommerce_processing_order_count' );
|
||||
wc_delete_shop_order_transients( $id );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* woocommerce_untrash_post function.
|
||||
*
|
||||
* @param mixed $id
|
||||
*/
|
||||
public static function untrash_post( $id ) {
|
||||
global $wpdb;
|
||||
|
||||
if ( $id > 0 ) {
|
||||
|
||||
$post_type = get_post_type( $id );
|
||||
|
||||
if ( in_array( $post_type, wc_get_order_types( 'order-count' ) ) ) {
|
||||
|
||||
// Delete count - meta doesn't work on trashed posts
|
||||
$user_id = get_post_meta( $id, '_customer_user', true );
|
||||
|
||||
if ( $user_id > 0 ) {
|
||||
delete_user_meta( $user_id, '_money_spent' );
|
||||
delete_user_meta( $user_id, '_order_count' );
|
||||
}
|
||||
|
||||
$refunds = $wpdb->get_results( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_type = 'shop_order_refund' AND post_parent = %d", $id ) );
|
||||
|
||||
foreach ( $refunds as $refund ) {
|
||||
$wpdb->update( $wpdb->posts, array( 'post_status' => 'wc-completed' ), array( 'ID' => $refund->ID ) );
|
||||
}
|
||||
|
||||
delete_transient( 'woocommerce_processing_order_count' );
|
||||
wc_delete_shop_order_transients( $id );
|
||||
} elseif ( 'product' === $post_type ) {
|
||||
// Check if SKU is valid before untrash the product.
|
||||
$sku = get_post_meta( $id, '_sku', true );
|
||||
|
||||
if ( ! empty( $sku ) ) {
|
||||
if ( ! wc_product_has_unique_sku( $id, $sku ) ) {
|
||||
update_post_meta( $id, '_sku', '' );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove item meta on permanent deletion.
|
||||
*/
|
||||
public static function delete_order_items( $postid ) {
|
||||
global $wpdb;
|
||||
|
||||
if ( in_array( get_post_type( $postid ), wc_get_order_types() ) ) {
|
||||
do_action( 'woocommerce_delete_order_items', $postid );
|
||||
|
||||
$wpdb->query( "
|
||||
DELETE {$wpdb->prefix}woocommerce_order_items, {$wpdb->prefix}woocommerce_order_itemmeta
|
||||
FROM {$wpdb->prefix}woocommerce_order_items
|
||||
JOIN {$wpdb->prefix}woocommerce_order_itemmeta ON {$wpdb->prefix}woocommerce_order_items.order_item_id = {$wpdb->prefix}woocommerce_order_itemmeta.order_item_id
|
||||
WHERE {$wpdb->prefix}woocommerce_order_items.order_id = '{$postid}';
|
||||
" );
|
||||
|
||||
do_action( 'woocommerce_deleted_order_items', $postid );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove downloadable permissions on permanent order deletion.
|
||||
*/
|
||||
public static function delete_order_downloadable_permissions( $postid ) {
|
||||
global $wpdb;
|
||||
|
||||
if ( in_array( get_post_type( $postid ), wc_get_order_types() ) ) {
|
||||
do_action( 'woocommerce_delete_order_downloadable_permissions', $postid );
|
||||
|
||||
$wpdb->query( $wpdb->prepare( "
|
||||
DELETE FROM {$wpdb->prefix}woocommerce_downloadable_product_permissions
|
||||
WHERE order_id = %d
|
||||
", $postid ) );
|
||||
|
||||
do_action( 'woocommerce_deleted_order_downloadable_permissions', $postid );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WC_Post_Data::init();
|
||||
|
|
|
@ -86,7 +86,7 @@ class WC_Product_Grouped extends WC_Product {
|
|||
foreach ( $this->get_children() as $child_id ) {
|
||||
$child = wc_get_product( $child_id );
|
||||
if ( '' !== $child->get_price() ) {
|
||||
$child_prices[] = 'incl' === $tax_display_mode ? $child->get_price_including_tax() : $child->get_price_excluding_tax();
|
||||
$child_prices[] = 'incl' === $tax_display_mode ? wc_get_price_including_tax( $child ) : wc_get_price_excluding_tax( $child );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -105,7 +105,7 @@ class WC_Product_Grouped extends WC_Product {
|
|||
if ( $is_free ) {
|
||||
$price = apply_filters( 'woocommerce_grouped_free_price_html', __( 'Free!', 'woocommerce' ), $this );
|
||||
} else {
|
||||
$price = apply_filters( 'woocommerce_grouped_price_html', $price . $this->get_price_suffix(), $this, $child_prices );
|
||||
$price = apply_filters( 'woocommerce_grouped_price_html', $price . wc_get_price_suffix( $this ), $this, $child_prices );
|
||||
}
|
||||
} else {
|
||||
$price = apply_filters( 'woocommerce_grouped_empty_price_html', '', $this );
|
||||
|
@ -148,4 +148,32 @@ class WC_Product_Grouped extends WC_Product {
|
|||
public function set_children( $children ) {
|
||||
$this->set_prop( 'children', array_filter( wp_parse_id_list( (array) $children ) ) );
|
||||
}
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Sync with children.
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* Sync a grouped product with it's children. These sync functions sync
|
||||
* upwards (from child to parent) when the variation is saved.
|
||||
*
|
||||
* @param WC_Product|int $product Product object or ID for which you wish to sync.
|
||||
* @param bool $save If true, the prouduct object will be saved to the DB before returning it.
|
||||
* @return WC_Product Synced product object.
|
||||
*/
|
||||
public static function sync( $product, $save = true ) {
|
||||
if ( ! is_a( $product, 'WC_Product' ) ) {
|
||||
$product = wc_get_product( $product );
|
||||
}
|
||||
if ( is_a( $product, 'WC_Product_Grouped' ) ) {
|
||||
$data_store = WC_Data_Store::load( 'product_' . $product->get_type() );
|
||||
$data_store->sync_price( $product );
|
||||
if ( $save ) {
|
||||
$product->save();
|
||||
}
|
||||
}
|
||||
return $product;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,48 +55,4 @@ class WC_Product_Simple extends WC_Product {
|
|||
|
||||
return apply_filters( 'woocommerce_product_add_to_cart_text', $text, $this );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the title of the post. @todo should this be deprecated or not? It's in deprecated class and needs review.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_title() {
|
||||
$post = get_post( $this->get_id() );
|
||||
$title = $post->post_title;
|
||||
|
||||
if ( $this->get_parent_id() > 0 ) {
|
||||
/* translators: 1: parent product title 2: product title */
|
||||
$title = sprintf( __( '%1$s → %2$s' , 'woocommerce' ), get_the_title( $this->get_parent_id() ), $title );
|
||||
}
|
||||
|
||||
return apply_filters( 'woocommerce_product_title', $title, $this );
|
||||
}
|
||||
|
||||
/**
|
||||
* Sync grouped products with the children lowest price (so they can be sorted by price accurately). @todo should this be here?
|
||||
*/
|
||||
public function grouped_product_sync() {
|
||||
if ( ! $this->get_parent_id() ) return;
|
||||
|
||||
$children_by_price = get_posts( array(
|
||||
'post_parent' => $this->get_parent_id(),
|
||||
'orderby' => 'meta_value_num',
|
||||
'order' => 'asc',
|
||||
'meta_key' => '_price',
|
||||
'posts_per_page' => 1,
|
||||
'post_type' => 'product',
|
||||
'fields' => 'ids',
|
||||
));
|
||||
if ( $children_by_price ) {
|
||||
foreach ( $children_by_price as $child ) {
|
||||
$child_price = get_post_meta( $child, '_price', true );
|
||||
update_post_meta( $this->get_parent_id(), '_price', $child_price );
|
||||
}
|
||||
}
|
||||
|
||||
delete_transient( 'wc_products_onsale' );
|
||||
|
||||
do_action( 'woocommerce_grouped_product_sync', $this->id, $children_by_price );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -485,26 +485,6 @@ class WC_Product_Variation extends WC_Product_Simple {
|
|||
parent::update_post_meta();
|
||||
}
|
||||
|
||||
/**
|
||||
* Save data (either create or update depending on if we are working on an existing product).
|
||||
*
|
||||
* @since 2.7.0
|
||||
*/
|
||||
public function save() {
|
||||
$this->validate_props();
|
||||
|
||||
if ( $this->data_store ) {
|
||||
if ( $this->get_id() ) {
|
||||
$this->data_store->update( $this );
|
||||
} else {
|
||||
$this->data_store->create( $this );
|
||||
}
|
||||
|
||||
wp_schedule_single_event( time(), 'woocommerce_deferred_product_sync', array( 'product_id' => $this->get_parent_id() ) );
|
||||
return $this->get_id();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Conditionals
|
||||
|
|
|
@ -173,7 +173,7 @@ class WC_Structured_Data {
|
|||
$markup['@type'] = 'Product';
|
||||
$markup['@id'] = get_permalink( $product->get_id() );
|
||||
$markup['url'] = $markup['@id'];
|
||||
$markup['name'] = $product->get_title();
|
||||
$markup['name'] = $product->get_name();
|
||||
|
||||
if ( apply_filters( 'woocommerce_structured_data_product_limit', is_product_taxonomy() || is_shop() ) ) {
|
||||
$this->set_data( apply_filters( 'woocommerce_structured_data_product_limited', $markup, $product ) );
|
||||
|
|
|
@ -771,7 +771,7 @@ class WC_CLI_Product extends WC_CLI_Command {
|
|||
|
||||
// Add data that applies to every product type.
|
||||
$product_data = array(
|
||||
'title' => $product->get_title(),
|
||||
'title' => $product->get_name(),
|
||||
'id' => (int) $product->is_type( 'variation' ) ? $product->get_variation_id() : $product->get_id(),
|
||||
'created_at' => $this->format_datetime( $product->get_post_data()->post_date_gmt ),
|
||||
'updated_at' => $this->format_datetime( $product->get_post_data()->post_modified_gmt ),
|
||||
|
@ -1292,43 +1292,6 @@ class WC_CLI_Product extends WC_CLI_Command {
|
|||
wp_update_post( array( 'ID' => $product_id, 'post_parent' => absint( $data['parent_id'] ) ) );
|
||||
}
|
||||
|
||||
// Update parent if grouped so price sorting works and stays in sync with the cheapest child
|
||||
$_product = wc_get_product( $product_id );
|
||||
if ( $_product && $_product->post->post_parent > 0 || 'grouped' === $product_type ) {
|
||||
|
||||
$clear_parent_ids = array();
|
||||
|
||||
if ( $_product->post->post_parent > 0 ) {
|
||||
$clear_parent_ids[] = $_product->post->post_parent;
|
||||
}
|
||||
|
||||
if ( 'grouped' === $product_type ) {
|
||||
$clear_parent_ids[] = $product_id;
|
||||
}
|
||||
|
||||
if ( ! empty( $clear_parent_ids ) ) {
|
||||
foreach ( $clear_parent_ids as $clear_id ) {
|
||||
|
||||
$children_by_price = get_posts( array(
|
||||
'post_parent' => $clear_id,
|
||||
'orderby' => 'meta_value_num',
|
||||
'order' => 'asc',
|
||||
'meta_key' => '_price',
|
||||
'posts_per_page' => 1,
|
||||
'post_type' => 'product',
|
||||
'fields' => 'ids',
|
||||
) );
|
||||
|
||||
if ( $children_by_price ) {
|
||||
foreach ( $children_by_price as $child ) {
|
||||
$child_price = get_post_meta( $child, '_price', true );
|
||||
update_post_meta( $clear_id, '_price', $child_price );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sold Individually
|
||||
if ( isset( $data['sold_individually'] ) ) {
|
||||
update_post_meta( $product_id, '_sold_individually', ( $this->is_true( $data['sold_individually'] ) ) ? 'yes' : '' );
|
||||
|
|
|
@ -10,7 +10,7 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|||
* @category Class
|
||||
* @author WooThemes
|
||||
*/
|
||||
class WC_Product_Data_Store_CPT extends WC_Data_Store_CPT implements WC_Object_Data_Store, WC_Product_Data_Store {
|
||||
class WC_Product_Data_Store_CPT extends WC_Data_Store_CPT implements WC_Object_Data_Store, WC_Product_Data_Store_Interface {
|
||||
|
||||
/**
|
||||
* If we have already saved our extra data, don't do automatic / default handling.
|
||||
|
@ -129,12 +129,17 @@ class WC_Product_Data_Store_CPT extends WC_Data_Store_CPT implements WC_Object_D
|
|||
/**
|
||||
* Method to delete a product from the database.
|
||||
* @param WC_Product
|
||||
* @param array $args Array of args to pass to the delete method.
|
||||
*/
|
||||
public function delete( &$product, $force_delete = false ) {
|
||||
$id = $product->get_id();
|
||||
public function delete( &$product, $args = array() ) {
|
||||
$id = $product->get_id();
|
||||
$post_type = $product->is_type( 'variation' ) ? 'product_variation' : 'product';
|
||||
|
||||
if ( $force_delete ) {
|
||||
$args = wp_parse_args( $args, array(
|
||||
'force_delete' => false,
|
||||
) );
|
||||
|
||||
if ( $args['force_delete'] ) {
|
||||
wp_delete_post( $product->get_id() );
|
||||
$product->set_id( 0 );
|
||||
} else {
|
||||
|
@ -157,26 +162,26 @@ class WC_Product_Data_Store_CPT extends WC_Data_Store_CPT implements WC_Object_D
|
|||
* @since 2.7.0
|
||||
*/
|
||||
protected function read_product_data( &$product ) {
|
||||
$id = $product->get_id();
|
||||
$review_count = get_post_meta( $id, '_wc_review_count', true );
|
||||
$rating_counts = get_post_meta( $id, '_wc_rating_count', true );
|
||||
$average_rating = get_post_meta( $id, '_wc_average_rating', true );
|
||||
$id = $product->get_id();
|
||||
|
||||
if ( '' === $review_count ) {
|
||||
$review_count = WC_Comments::get_review_count_for_product( $product );
|
||||
if ( '' === ( $review_count = get_post_meta( $id, '_wc_review_count', true ) ) ) {
|
||||
WC_Comments::get_review_count_for_product( $product );
|
||||
} else {
|
||||
$product->set_review_count( $review_count );
|
||||
}
|
||||
|
||||
if ( '' === $rating_counts ) {
|
||||
$rating_counts = WC_Comments::get_rating_counts_for_product( $product );
|
||||
if ( '' === ( $rating_counts = get_post_meta( $id, '_wc_rating_count', true ) ) ) {
|
||||
WC_Comments::get_rating_counts_for_product( $product );
|
||||
} else {
|
||||
$product->set_rating_counts( $rating_counts );
|
||||
}
|
||||
|
||||
if ( '' === $average_rating ) {
|
||||
$average_rating = WC_Comments::get_average_rating_for_product( $product );
|
||||
if ( '' === ( $average_rating = get_post_meta( $id, '_wc_average_rating', true ) ) ) {
|
||||
WC_Comments::get_average_rating_for_product( $product );
|
||||
} else {
|
||||
$product->set_average_rating( $average_rating );
|
||||
}
|
||||
|
||||
$product->set_average_rating( $average_rating );
|
||||
$product->set_rating_counts( $rating_counts );
|
||||
$product->set_review_count( $review_count );
|
||||
$product->set_props( array(
|
||||
'featured' => get_post_meta( $id, '_featured', true ),
|
||||
'catalog_visibility' => get_post_meta( $id, '_visibility', true ),
|
||||
|
@ -750,7 +755,7 @@ class WC_Product_Data_Store_CPT extends WC_Data_Store_CPT implements WC_Object_D
|
|||
* @param int $limit Limit of results.
|
||||
* @return string
|
||||
*/
|
||||
function get_related_products_query( $cats_array, $tags_array, $exclude_ids, $limit ) {
|
||||
public function get_related_products_query( $cats_array, $tags_array, $exclude_ids, $limit ) {
|
||||
global $wpdb;
|
||||
|
||||
// Arrays to string.
|
||||
|
@ -812,7 +817,7 @@ class WC_Product_Data_Store_CPT extends WC_Data_Store_CPT implements WC_Object_D
|
|||
* @param int|null $stock_quantity
|
||||
* @param string $operation set, increase and decrease.
|
||||
*/
|
||||
function update_product_stock( $product_id_with_stock, $stock_quantity = null, $operation = 'set' ) {
|
||||
public function update_product_stock( $product_id_with_stock, $stock_quantity = null, $operation = 'set' ) {
|
||||
global $wpdb;
|
||||
add_post_meta( $product_id_with_stock, '_stock', 0, true );
|
||||
|
||||
|
@ -832,4 +837,34 @@ class WC_Product_Data_Store_CPT extends WC_Data_Store_CPT implements WC_Object_D
|
|||
wp_cache_delete( $product_id_with_stock, 'post_meta' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a products average rating meta.
|
||||
*
|
||||
* @since 2.7.0
|
||||
* @param WC_Product $product
|
||||
*/
|
||||
public function update_average_rating( $product ) {
|
||||
update_post_meta( $product->get_id(), '_wc_average_rating', $product->get_average_rating( 'edit' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a products review count meta.
|
||||
*
|
||||
* @since 2.7.0
|
||||
* @param WC_Product $product
|
||||
*/
|
||||
public function update_review_count( $product ) {
|
||||
update_post_meta( $product->get_id(), '_wc_review_count', $product->get_review_count( 'edit' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a products rating counts.
|
||||
*
|
||||
* @since 2.7.0
|
||||
* @param WC_Product $product
|
||||
*/
|
||||
public function update_rating_counts( $product ) {
|
||||
update_post_meta( $product->get_id(), '_wc_rating_count', $product->get_rating_counts( 'edit' ) );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -41,4 +41,31 @@ class WC_Product_Grouped_Data_Store_CPT extends WC_Product_Data_Store_CPT implem
|
|||
parent::update_post_meta( $product );
|
||||
}
|
||||
|
||||
/**
|
||||
* Sync grouped product prices with children.
|
||||
*
|
||||
* @since 2.7.0
|
||||
* @param WC_Product|int $product
|
||||
*/
|
||||
public function sync_price( &$product ) {
|
||||
global $wpdb;
|
||||
|
||||
$children_ids = get_posts( array(
|
||||
'post_parent' => $product->get_id(),
|
||||
'post_type' => 'product',
|
||||
'fields' => 'ids',
|
||||
) );
|
||||
$prices = $children_ids ? array_unique( $wpdb->get_col( "SELECT meta_value FROM $wpdb->postmeta WHERE meta_key = '_price' AND post_id IN ( " . implode( ',', array_map( 'absint', $children_ids ) ) . " )" ) ) : array();
|
||||
|
||||
delete_post_meta( $product->get_id(), '_price' );
|
||||
delete_transient( 'wc_var_prices_' . $product->get_id() );
|
||||
|
||||
if ( $prices ) {
|
||||
sort( $prices );
|
||||
// To allow sorting and filtering by multiple values, we have no choice but to store child prices in this manner.
|
||||
foreach ( $prices as $price ) {
|
||||
add_post_meta( $product->get_id(), '_price', $price, false );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|||
* @category Class
|
||||
* @author WooThemes
|
||||
*/
|
||||
class WC_Product_Variable_Data_Store_CPT extends WC_Product_Data_Store_CPT implements WC_Object_Data_Store, WC_Product_Variable_Data_Store {
|
||||
class WC_Product_Variable_Data_Store_CPT extends WC_Product_Data_Store_CPT implements WC_Object_Data_Store, WC_Product_Variable_Data_Store_Interface {
|
||||
|
||||
/**
|
||||
* Cached & hashed prices array for child variations.
|
||||
|
@ -196,7 +196,7 @@ class WC_Product_Variable_Data_Store_CPT extends WC_Product_Data_Store_CPT imple
|
|||
$sale_prices = array();
|
||||
$variation_ids = $product->get_visible_children();
|
||||
foreach ( $variation_ids as $variation_id ) {
|
||||
if ( $variation = wc_get_product( $variation_id ) ) { // @todo loop from missing args? remember?
|
||||
if ( $variation = wc_get_product( $variation_id ) ) {
|
||||
$price = apply_filters( 'woocommerce_variation_prices_price', $variation->get_price(), $variation, $product );
|
||||
$regular_price = apply_filters( 'woocommerce_variation_prices_regular_price', $variation->get_regular_price(), $variation, $product );
|
||||
$sale_price = apply_filters( 'woocommerce_variation_prices_sale_price', $variation->get_sale_price(), $variation, $product );
|
||||
|
|
|
@ -12,7 +12,7 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|||
* @category Interface
|
||||
* @author WooThemes
|
||||
*/
|
||||
interface WC_Product_Data_Store {
|
||||
interface WC_Product_Data_Store_Interface {
|
||||
|
||||
/**
|
||||
* Returns an array of on sale products, as an array of objects with an
|
|
@ -12,7 +12,7 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|||
* @category Interface
|
||||
* @author WooThemes
|
||||
*/
|
||||
interface WC_Product_Variable_Data_Store {
|
||||
interface WC_Product_Variable_Data_Store_Interface {
|
||||
/**
|
||||
* Does a child have a weight set?
|
||||
*
|
|
@ -205,7 +205,7 @@ function wc_cart_totals_shipping_html() {
|
|||
|
||||
if ( sizeof( $packages ) > 1 ) {
|
||||
foreach ( $package['contents'] as $item_id => $values ) {
|
||||
$product_names[] = $values['data']->get_title() . ' ×' . $values['quantity'];
|
||||
$product_names[] = $values['data']->get_name() . ' ×' . $values['quantity'];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -481,18 +481,6 @@ function wc_scheduled_sales() {
|
|||
}
|
||||
|
||||
$product->save();
|
||||
|
||||
$parent = $product->get_parent_id();
|
||||
// Sync parent
|
||||
if ( $parent ) {
|
||||
// Clear prices transient for variable products.
|
||||
delete_transient( 'wc_var_prices_' . $parent );
|
||||
|
||||
// Grouped products need syncing via a function
|
||||
if ( $product->is_type( 'simple' ) ) {
|
||||
$product->grouped_product_sync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete_transient( 'wc_products_onsale' );
|
||||
|
@ -509,19 +497,6 @@ function wc_scheduled_sales() {
|
|||
$product->set_date_on_sale_to( '' );
|
||||
$product->set_date_on_sale_from( '' );
|
||||
$product->save();
|
||||
|
||||
$parent = $product->get_parent_id();
|
||||
|
||||
// Sync parent
|
||||
if ( $parent ) {
|
||||
// Clear prices transient for variable products.
|
||||
delete_transient( 'wc_var_prices_' . $parent );
|
||||
|
||||
// Grouped products need syncing via a function
|
||||
if ( $product->is_type( 'simple' ) ) {
|
||||
$product->grouped_product_sync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WC_Cache_Helper::get_transient_version( 'product', true );
|
||||
|
|
|
@ -975,7 +975,7 @@ if ( ! function_exists( 'woocommerce_grouped_add_to_cart' ) ) {
|
|||
|
||||
wc_get_template( 'single-product/add-to-cart/grouped.php', array(
|
||||
'grouped_product' => $product,
|
||||
'grouped_products' => $product->get_children(),
|
||||
'grouped_products' => array_filter( array_map( 'wc_get_product', $product->get_children() ), 'wc_products_array_filter_visible' ),
|
||||
'quantites_required' => false,
|
||||
) );
|
||||
}
|
||||
|
@ -1369,18 +1369,31 @@ if ( ! function_exists( 'woocommerce_cross_sell_display' ) ) {
|
|||
/**
|
||||
* Output the cart cross-sells.
|
||||
*
|
||||
* @param int $posts_per_page (default: 2)
|
||||
* @param int $limit (default: 2)
|
||||
* @param int $columns (default: 2)
|
||||
* @param string $orderby (default: 'rand')
|
||||
* @param string $order (default: 'desc')
|
||||
*/
|
||||
function woocommerce_cross_sell_display( $posts_per_page = 2, $columns = 2, $orderby = 'rand' ) {
|
||||
function woocommerce_cross_sell_display( $limit = 2, $columns = 2, $orderby = 'rand', $order = 'desc' ) {
|
||||
if ( is_checkout() ) {
|
||||
return;
|
||||
}
|
||||
// Get visble cross sells then sort them at random.
|
||||
$cross_sells = array_filter( array_map( 'wc_get_product', WC()->cart->get_cross_sells() ), 'wc_products_array_filter_visible' );
|
||||
|
||||
// Handle orderby and limit results.
|
||||
$orderby = apply_filters( 'woocommerce_cross_sells_orderby', $orderby );
|
||||
$cross_sells = wc_products_array_orderby( $cross_sells, $orderby, $order );
|
||||
$limit = apply_filters( 'woocommerce_cross_sells_total', $limit );
|
||||
$cross_sells = $limit > 0 ? array_slice( $cross_sells, 0, $limit ) : $cross_sells;
|
||||
|
||||
wc_get_template( 'cart/cross-sells.php', array(
|
||||
'posts_per_page' => $posts_per_page,
|
||||
'orderby' => $orderby,
|
||||
'columns' => $columns,
|
||||
'cross_sells' => $cross_sells,
|
||||
|
||||
// Not used now, but used in previous version of up-sells.php.
|
||||
'posts_per_page' => $limit,
|
||||
'orderby' => $orderby,
|
||||
'columns' => $columns,
|
||||
) );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -437,7 +437,7 @@ function wc_get_customer_available_downloads( $customer_id ) {
|
|||
// Download name will be 'Product Name' for products with a single downloadable file, and 'Product Name - File X' for products with multiple files
|
||||
$download_name = apply_filters(
|
||||
'woocommerce_downloadable_product_name',
|
||||
$_product->get_title() . ' – ' . $download_file['name'],
|
||||
$_product->get_name() . ' – ' . $download_file['name'],
|
||||
$_product,
|
||||
$result->download_id,
|
||||
$file_number
|
||||
|
@ -455,7 +455,7 @@ function wc_get_customer_available_downloads( $customer_id ) {
|
|||
),
|
||||
'download_id' => $result->download_id,
|
||||
'product_id' => $_product->get_id(),
|
||||
'product_name' => $_product->get_title(),
|
||||
'product_name' => $_product->get_name(),
|
||||
'download_name' => $download_name,
|
||||
'order_id' => $order->get_id(),
|
||||
'order_key' => $order->get_order_key(),
|
||||
|
|
|
@ -79,7 +79,7 @@ class WC_Widget_Recent_Reviews extends WC_Widget {
|
|||
|
||||
echo $_product->get_image();
|
||||
|
||||
echo $_product->get_title() . '</a>';
|
||||
echo $_product->get_name() . '</a>';
|
||||
|
||||
echo $rating_html;
|
||||
|
||||
|
|
|
@ -78,9 +78,9 @@ do_action( 'woocommerce_before_cart' ); ?>
|
|||
<td class="product-name" data-title="<?php _e( 'Product', 'woocommerce' ); ?>">
|
||||
<?php
|
||||
if ( ! $product_permalink ) {
|
||||
echo apply_filters( 'woocommerce_cart_item_name', $_product->get_title(), $cart_item, $cart_item_key ) . ' ';
|
||||
echo apply_filters( 'woocommerce_cart_item_name', $_product->get_name(), $cart_item, $cart_item_key ) . ' ';
|
||||
} else {
|
||||
echo apply_filters( 'woocommerce_cart_item_name', sprintf( '<a href="%s">%s</a>', esc_url( $product_permalink ), $_product->get_title() ), $cart_item, $cart_item_key );
|
||||
echo apply_filters( 'woocommerce_cart_item_name', sprintf( '<a href="%s">%s</a>', esc_url( $product_permalink ), $_product->get_name() ), $cart_item, $cart_item_key );
|
||||
}
|
||||
|
||||
// Meta data
|
||||
|
|
|
@ -13,34 +13,14 @@
|
|||
* @see https://docs.woocommerce.com/document/template-structure/
|
||||
* @author WooThemes
|
||||
* @package WooCommerce/Templates
|
||||
* @version 1.6.4
|
||||
* @version 2.7.0
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
global $product, $woocommerce_loop;
|
||||
|
||||
if ( ! $crosssells = WC()->cart->get_cross_sells() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$args = array(
|
||||
'post_type' => 'product',
|
||||
'ignore_sticky_posts' => 1,
|
||||
'no_found_rows' => 1,
|
||||
'posts_per_page' => apply_filters( 'woocommerce_cross_sells_total', $posts_per_page ),
|
||||
'orderby' => $orderby,
|
||||
'post__in' => $crosssells,
|
||||
'meta_query' => WC()->query->get_meta_query(),
|
||||
);
|
||||
|
||||
$products = new WP_Query( $args );
|
||||
$woocommerce_loop['name'] = 'cross-sells';
|
||||
$woocommerce_loop['columns'] = apply_filters( 'woocommerce_cross_sells_columns', $columns );
|
||||
|
||||
if ( $products->have_posts() ) : ?>
|
||||
if ( $cross_sells ) : ?>
|
||||
|
||||
<div class="cross-sells">
|
||||
|
||||
|
@ -48,11 +28,16 @@ if ( $products->have_posts() ) : ?>
|
|||
|
||||
<?php woocommerce_product_loop_start(); ?>
|
||||
|
||||
<?php while ( $products->have_posts() ) : $products->the_post(); ?>
|
||||
<?php foreach ( $cross_sells as $cross_sell ) : ?>
|
||||
|
||||
<?php wc_get_template_part( 'content', 'product' ); ?>
|
||||
<?php
|
||||
$post_object = get_post( $cross_sell->get_id() );
|
||||
|
||||
<?php endwhile; // end of the loop. ?>
|
||||
setup_postdata( $GLOBALS['post'] =& $post_object );
|
||||
|
||||
wc_get_template_part( 'content', 'product' ); ?>
|
||||
|
||||
<?php endforeach; ?>
|
||||
|
||||
<?php woocommerce_product_loop_end(); ?>
|
||||
|
||||
|
@ -60,4 +45,4 @@ if ( $products->have_posts() ) : ?>
|
|||
|
||||
<?php endif;
|
||||
|
||||
wp_reset_query();
|
||||
wp_reset_postdata();
|
||||
|
|
|
@ -38,7 +38,7 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|||
$product_id = apply_filters( 'woocommerce_cart_item_product_id', $cart_item['product_id'], $cart_item, $cart_item_key );
|
||||
|
||||
if ( $_product && $_product->exists() && $cart_item['quantity'] > 0 && apply_filters( 'woocommerce_widget_cart_item_visible', true, $cart_item, $cart_item_key ) ) {
|
||||
$product_name = apply_filters( 'woocommerce_cart_item_name', $_product->get_title(), $cart_item, $cart_item_key );
|
||||
$product_name = apply_filters( 'woocommerce_cart_item_name', $_product->get_name(), $cart_item, $cart_item_key );
|
||||
$thumbnail = apply_filters( 'woocommerce_cart_item_thumbnail', $_product->get_image(), $cart_item, $cart_item_key );
|
||||
$product_price = apply_filters( 'woocommerce_cart_item_price', WC()->cart->get_product_price( $_product ), $cart_item, $cart_item_key );
|
||||
$product_permalink = apply_filters( 'woocommerce_cart_item_permalink', $_product->is_visible() ? $_product->get_permalink( $cart_item ) : '', $cart_item, $cart_item_key );
|
||||
|
|
|
@ -38,7 +38,7 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|||
?>
|
||||
<tr class="<?php echo esc_attr( apply_filters( 'woocommerce_cart_item_class', 'cart_item', $cart_item, $cart_item_key ) ); ?>">
|
||||
<td class="product-name">
|
||||
<?php echo apply_filters( 'woocommerce_cart_item_name', $_product->get_title(), $cart_item, $cart_item_key ) . ' '; ?>
|
||||
<?php echo apply_filters( 'woocommerce_cart_item_name', $_product->get_name(), $cart_item, $cart_item_key ) . ' '; ?>
|
||||
<?php echo apply_filters( 'woocommerce_checkout_cart_item_quantity', ' <strong class="product-quantity">' . sprintf( '× %s', $cart_item['quantity'] ) . '</strong>', $cart_item, $cart_item_key ); ?>
|
||||
<?php echo WC()->cart->get_item_data( $cart_item ); ?>
|
||||
</td>
|
||||
|
|
|
@ -26,7 +26,7 @@ global $product; ?>
|
|||
<li>
|
||||
<a href="<?php echo esc_url( $product->get_permalink() ); ?>">
|
||||
<?php echo $product->get_image(); ?>
|
||||
<span class="product-title"><?php echo $product->get_title(); ?></span>
|
||||
<span class="product-title"><?php echo $product->get_name(); ?></span>
|
||||
</a>
|
||||
<?php if ( ! empty( $show_rating ) ) : ?>
|
||||
<?php echo wc_get_rating_html( $product->get_average_rating() ); ?>
|
||||
|
|
|
@ -13,74 +13,58 @@
|
|||
* @see https://docs.woocommerce.com/document/template-structure/
|
||||
* @author WooThemes
|
||||
* @package WooCommerce/Templates
|
||||
* @version 2.1.7
|
||||
* @version 2.7.0
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
exit;
|
||||
}
|
||||
|
||||
global $product, $post;
|
||||
|
||||
$parent_product_post = $post;
|
||||
|
||||
do_action( 'woocommerce_before_add_to_cart_form' ); ?>
|
||||
|
||||
<form class="cart" method="post" enctype='multipart/form-data'>
|
||||
<table cellspacing="0" class="group_table">
|
||||
<tbody>
|
||||
<?php
|
||||
foreach ( $grouped_products as $product_id ) :
|
||||
if ( ! $product = wc_get_product( $product_id ) ) {
|
||||
continue;
|
||||
}
|
||||
foreach ( $grouped_products as $grouped_product ) {
|
||||
$post_object = get_post( $grouped_product->get_id() );
|
||||
|
||||
if ( 'yes' === get_option( 'woocommerce_hide_out_of_stock_items' ) && ! $product->is_in_stock() ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$post = $product->post;
|
||||
setup_postdata( $post );
|
||||
setup_postdata( $GLOBALS['post'] =& $post_object );
|
||||
?>
|
||||
<tr>
|
||||
<td>
|
||||
<?php if ( $product->is_sold_individually() || ! $product->is_purchasable() ) : ?>
|
||||
<?php if ( $grouped_product->is_sold_individually() || ! $grouped_product->is_purchasable() ) : ?>
|
||||
<?php woocommerce_template_loop_add_to_cart(); ?>
|
||||
<?php else : ?>
|
||||
<?php
|
||||
$quantites_required = true;
|
||||
woocommerce_quantity_input( array(
|
||||
'input_name' => 'quantity[' . $product_id . ']',
|
||||
'input_value' => ( isset( $_POST['quantity'][ $product_id ] ) ? wc_stock_amount( $_POST['quantity'][ $product_id ] ) : 0 ),
|
||||
'min_value' => apply_filters( 'woocommerce_quantity_input_min', 0, $product ),
|
||||
'max_value' => apply_filters( 'woocommerce_quantity_input_max', $product->backorders_allowed() ? '' : $product->get_stock_quantity(), $product ),
|
||||
'input_name' => 'quantity[' . $grouped_product->get_id() . ']',
|
||||
'input_value' => ( isset( $_POST['quantity'][ $grouped_product->get_id() ] ) ? wc_stock_amount( $_POST['quantity'][ $grouped_product->get_id() ] ) : 0 ),
|
||||
'min_value' => apply_filters( 'woocommerce_quantity_input_min', 0, $grouped_product ),
|
||||
'max_value' => apply_filters( 'woocommerce_quantity_input_max', $grouped_product->backorders_allowed() || ! $grouped_product->get_manage_stock() ? '' : $grouped_product->get_stock_quantity(), $grouped_product ),
|
||||
) );
|
||||
?>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
|
||||
<td class="label">
|
||||
<label for="product-<?php echo $product_id; ?>">
|
||||
<?php echo $product->is_visible() ? '<a href="' . esc_url( apply_filters( 'woocommerce_grouped_product_list_link', get_permalink(), $product_id ) ) . '">' . get_the_title() . '</a>' : get_the_title(); ?>
|
||||
<label for="product-<?php echo $grouped_product->get_id(); ?>">
|
||||
<?php echo $product->is_visible() ? '<a href="' . esc_url( apply_filters( 'woocommerce_grouped_product_list_link', get_permalink(), $grouped_product->get_id() ) ) . '">' . get_the_title() . '</a>' : get_the_title(); ?>
|
||||
</label>
|
||||
</td>
|
||||
|
||||
<?php do_action( 'woocommerce_grouped_product_list_before_price', $product ); ?>
|
||||
|
||||
<?php do_action( 'woocommerce_grouped_product_list_before_price', $grouped_product ); ?>
|
||||
<td class="price">
|
||||
<?php
|
||||
echo $product->get_price_html();
|
||||
echo wc_get_stock_html( $product );
|
||||
echo $grouped_product->get_price_html();
|
||||
echo wc_get_stock_html( $grouped_product );
|
||||
?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php
|
||||
endforeach;
|
||||
|
||||
// Reset to parent grouped product
|
||||
$post = $parent_product_post;
|
||||
$product = wc_get_product( $parent_product_post->ID );
|
||||
setup_postdata( $parent_product_post );
|
||||
}
|
||||
wp_reset_postdata();
|
||||
?>
|
||||
</tbody>
|
||||
</table>
|
||||
|
|
|
@ -200,7 +200,7 @@ class WC_Helper_Product {
|
|||
update_post_meta( $variation_id, '_regular_price', '15' );
|
||||
|
||||
// General meta
|
||||
update_post_meta( $variation_id, '_sku', 'DUMMY SKU VARIABLE SMALL' );
|
||||
update_post_meta( $variation_id, '_sku', 'DUMMY SKU VARIABLE LARGE' );
|
||||
update_post_meta( $variation_id, '_manage_stock', 'no' );
|
||||
update_post_meta( $variation_id, '_downloadable', 'no' );
|
||||
update_post_meta( $variation_id, '_virtual', 'no' );
|
||||
|
|
|
@ -41,11 +41,11 @@ class Product_Variations_API extends WC_REST_Unit_Test_Case {
|
|||
$product = WC_Helper_Product::create_variation_product();
|
||||
$response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v1/products/' . $product->get_id() . '/variations' ) );
|
||||
$variations = $response->get_data();
|
||||
|
||||
$this->assertEquals( 200, $response->get_status() );
|
||||
$this->assertEquals( 2, count( $variations ) );
|
||||
$this->assertEquals( 'DUMMY SKU VARIABLE SMALL', $variations[0]['sku'] );
|
||||
$this->assertEquals( 'size', $variations[0]['attributes'][0]['name'] );
|
||||
$product->delete( true );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -58,6 +58,7 @@ class Product_Variations_API extends WC_REST_Unit_Test_Case {
|
|||
$product = WC_Helper_Product::create_variation_product();
|
||||
$response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v1/products/' . $product->get_id() . '/variations' ) );
|
||||
$this->assertEquals( 401, $response->get_status() );
|
||||
$product->delete( true );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -77,6 +78,7 @@ class Product_Variations_API extends WC_REST_Unit_Test_Case {
|
|||
$this->assertEquals( 200, $response->get_status() );
|
||||
$this->assertEquals( $variation_id, $variation['id'] );
|
||||
$this->assertEquals( 'size', $variation['attributes'][0]['name'] );
|
||||
$product->delete( true );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -91,6 +93,7 @@ class Product_Variations_API extends WC_REST_Unit_Test_Case {
|
|||
$variation_id = $children[0];
|
||||
$response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v1/products/' . $product->get_id() . '/variations/' . $variation_id ) );
|
||||
$this->assertEquals( 401, $response->get_status() );
|
||||
$product->delete( true );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -112,6 +115,7 @@ class Product_Variations_API extends WC_REST_Unit_Test_Case {
|
|||
$response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v1/products/' . $product->get_id() . '/variations' ) );
|
||||
$variations = $response->get_data();
|
||||
$this->assertEquals( 1, count( $variations ) );
|
||||
$product->delete( true );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -129,6 +133,7 @@ class Product_Variations_API extends WC_REST_Unit_Test_Case {
|
|||
$request->set_param( 'force', true );
|
||||
$response = $this->server->dispatch( $request );
|
||||
$this->assertEquals( 401, $response->get_status() );
|
||||
$product->delete( true );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -143,6 +148,7 @@ class Product_Variations_API extends WC_REST_Unit_Test_Case {
|
|||
$request->set_param( 'force', true );
|
||||
$response = $this->server->dispatch( $request );
|
||||
$this->assertEquals( 404, $response->get_status() );
|
||||
$product->delete( true );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -184,6 +190,7 @@ class Product_Variations_API extends WC_REST_Unit_Test_Case {
|
|||
|
||||
$this->assertContains( 'Dr1Bczxq4q', $variation['image'][0]['src'] );
|
||||
$this->assertContains( 'test upload image', $variation['image'][0]['alt'] );
|
||||
$product->delete( true );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -203,6 +210,7 @@ class Product_Variations_API extends WC_REST_Unit_Test_Case {
|
|||
) );
|
||||
$response = $this->server->dispatch( $request );
|
||||
$this->assertEquals( 401, $response->get_status() );
|
||||
$product->delete( true );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -219,6 +227,7 @@ class Product_Variations_API extends WC_REST_Unit_Test_Case {
|
|||
) );
|
||||
$response = $this->server->dispatch( $request );
|
||||
$this->assertEquals( 400, $response->get_status() );
|
||||
$product->delete( true );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -254,6 +263,7 @@ class Product_Variations_API extends WC_REST_Unit_Test_Case {
|
|||
$response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v1/products/' . $product->get_id() . '/variations' ) );
|
||||
$variations = $response->get_data();
|
||||
$this->assertEquals( 3, count( $variations ) );
|
||||
$product->delete( true );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -274,6 +284,7 @@ class Product_Variations_API extends WC_REST_Unit_Test_Case {
|
|||
) );
|
||||
$response = $this->server->dispatch( $request );
|
||||
$this->assertEquals( 401, $response->get_status() );
|
||||
$product->delete( true );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -319,6 +330,7 @@ class Product_Variations_API extends WC_REST_Unit_Test_Case {
|
|||
$data = $response->get_data();
|
||||
|
||||
$this->assertEquals( 2, count( $data ) );
|
||||
$product->delete( true );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -368,6 +380,7 @@ class Product_Variations_API extends WC_REST_Unit_Test_Case {
|
|||
$this->assertArrayHasKey( 'shipping_class_id', $properties );
|
||||
$this->assertArrayHasKey( 'image', $properties );
|
||||
$this->assertArrayHasKey( 'attributes', $properties );
|
||||
$product->delete( true );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -198,6 +198,7 @@ class Products_API extends WC_REST_Unit_Test_Case {
|
|||
|
||||
$this->assertEquals( array( 'small' ), $data['attributes'][0]['options'] );
|
||||
$this->assertEquals( array( 'red', 'yellow' ), $data['attributes'][1]['options'] );
|
||||
$product->delete( true );
|
||||
|
||||
// test external product
|
||||
$product = WC_Helper_Product::create_external_product();
|
||||
|
@ -217,6 +218,7 @@ class Products_API extends WC_REST_Unit_Test_Case {
|
|||
|
||||
$this->assertEquals( 'Test API Update', $data['button_text'] );
|
||||
$this->assertEquals( 'http://automattic.com', $data['external_url'] );
|
||||
$product->delete( true );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -233,6 +235,7 @@ class Products_API extends WC_REST_Unit_Test_Case {
|
|||
) );
|
||||
$response = $this->server->dispatch( $request );
|
||||
$this->assertEquals( 401, $response->get_status() );
|
||||
$product->delete( true );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -249,6 +252,7 @@ class Products_API extends WC_REST_Unit_Test_Case {
|
|||
) );
|
||||
$response = $this->server->dispatch( $request );
|
||||
$this->assertEquals( 400, $response->get_status() );
|
||||
$product->delete( true );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -408,6 +412,8 @@ class Products_API extends WC_REST_Unit_Test_Case {
|
|||
$data = $response->get_data();
|
||||
|
||||
$this->assertEquals( 3, count( $data ) );
|
||||
$product->delete( true );
|
||||
$product_2->delete( true );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -506,6 +512,7 @@ class Products_API extends WC_REST_Unit_Test_Case {
|
|||
$data = $response->get_data();
|
||||
$properties = $data['schema']['properties'];
|
||||
$this->assertEquals( 61, count( $properties ) );
|
||||
$product->delete( true );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -232,6 +232,7 @@ class WC_Tests_Cart extends WC_Unit_Test_Case {
|
|||
|
||||
// Clean up the cart
|
||||
WC()->cart->empty_cart();
|
||||
$product->delete( true );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -125,7 +125,7 @@ class WC_Tests_Cart_Functions extends WC_Unit_Test_Case {
|
|||
|
||||
WC()->cart->add_to_cart( $product->get_id(), 1 );
|
||||
|
||||
$this->expectOutputString( wc_price( $product->price ), wc_cart_totals_subtotal_html() );
|
||||
$this->expectOutputString( wc_price( $product->get_price( 'edit' ) ), wc_cart_totals_subtotal_html() );
|
||||
|
||||
WC_Helper_Product::delete_product( $product->get_id() );
|
||||
}
|
||||
|
@ -161,21 +161,21 @@ class WC_Tests_Cart_Functions extends WC_Unit_Test_Case {
|
|||
$product = WC_Helper_Product::create_simple_product();
|
||||
|
||||
$message = wc_add_to_cart_message( array( $product->get_id() => 1 ), false, true );
|
||||
$this->assertEquals( '<a href="http://example.org" class="button wc-forward">View Cart</a> “Dummy Product” has been added to your cart.', $message );
|
||||
$this->assertEquals( '<a href="http://example.org" class="button wc-forward">View cart</a> “Dummy Product” has been added to your cart.', $message );
|
||||
|
||||
$message = wc_add_to_cart_message( array( $product->get_id() => 3 ), false, true );
|
||||
$this->assertEquals( '<a href="http://example.org" class="button wc-forward">View Cart</a> “Dummy Product” has been added to your cart.', $message );
|
||||
$this->assertEquals( '<a href="http://example.org" class="button wc-forward">View cart</a> “Dummy Product” has been added to your cart.', $message );
|
||||
|
||||
$message = wc_add_to_cart_message( array( $product->get_id() => 1 ), true, true );
|
||||
$this->assertEquals( '<a href="http://example.org" class="button wc-forward">View Cart</a> “Dummy Product” has been added to your cart.', $message );
|
||||
$this->assertEquals( '<a href="http://example.org" class="button wc-forward">View cart</a> “Dummy Product” has been added to your cart.', $message );
|
||||
|
||||
$message = wc_add_to_cart_message( array( $product->get_id() => 3 ), true, true );
|
||||
$this->assertEquals( '<a href="http://example.org" class="button wc-forward">View Cart</a> 3 × “Dummy Product” have been added to your cart.', $message );
|
||||
$this->assertEquals( '<a href="http://example.org" class="button wc-forward">View cart</a> 3 × “Dummy Product” have been added to your cart.', $message );
|
||||
|
||||
$message = wc_add_to_cart_message( $product->get_id(), false, true );
|
||||
$this->assertEquals( '<a href="http://example.org" class="button wc-forward">View Cart</a> “Dummy Product” has been added to your cart.', $message );
|
||||
$this->assertEquals( '<a href="http://example.org" class="button wc-forward">View cart</a> “Dummy Product” has been added to your cart.', $message );
|
||||
|
||||
$message = wc_add_to_cart_message( $product->get_id(), true, true );
|
||||
$this->assertEquals( '<a href="http://example.org" class="button wc-forward">View Cart</a> “Dummy Product” has been added to your cart.', $message );
|
||||
$this->assertEquals( '<a href="http://example.org" class="button wc-forward">View cart</a> “Dummy Product” has been added to your cart.', $message );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -222,6 +222,7 @@ class WC_Tests_Product_Data_Store extends WC_Unit_Test_Case {
|
|||
|
||||
$expected_attributes = array( 'pa_size' => array( 'small', 'large' ) );
|
||||
$this->assertEquals( $expected_attributes, $product->get_variation_attributes() );
|
||||
$product->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -260,6 +261,7 @@ class WC_Tests_Product_Data_Store extends WC_Unit_Test_Case {
|
|||
$this->assertEquals( 'Variation #1 of Dummy Variable CRUD Product', $variation->get_name() );
|
||||
$this->assertEquals( 'CRUD DUMMY SKU VARIABLE GREEN', $variation->get_sku() );
|
||||
$this->assertEquals( 10, $variation->get_price() );
|
||||
$product->delete();
|
||||
|
||||
$product = new WC_Product_Variable( $product->get_id() );
|
||||
$children = $product->get_children();
|
||||
|
@ -283,6 +285,7 @@ class WC_Tests_Product_Data_Store extends WC_Unit_Test_Case {
|
|||
$this->assertEquals( 'Variation #2 of Dummy Variable CRUD Product', $variation_2->get_name() );
|
||||
$this->assertEquals( 'CRUD DUMMY SKU VARIABLE RED', $variation_2->get_sku() );
|
||||
$this->assertEquals( 10, $variation_2->get_price() );
|
||||
$product->delete();
|
||||
|
||||
$product = new WC_Product_Variable( $product->get_id() );
|
||||
$children = $product->get_children();
|
||||
|
@ -297,6 +300,7 @@ class WC_Tests_Product_Data_Store extends WC_Unit_Test_Case {
|
|||
$variation_2->set_sale_price( 9.99 );
|
||||
$variation_2->set_date_on_sale_to( '32532537600' );
|
||||
$variation_2->save();
|
||||
$product->delete();
|
||||
|
||||
$product = new WC_Product_Variable( $product->get_id() );
|
||||
$expected_prices['price'][ $children[0] ] = 10.00;
|
||||
|
@ -312,6 +316,7 @@ class WC_Tests_Product_Data_Store extends WC_Unit_Test_Case {
|
|||
$product->set_name( 'Renamed Variable Product' );
|
||||
$product->save();
|
||||
$this->assertEquals( 'Renamed Variable Product', $product->get_name() );
|
||||
$product->delete();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -8,11 +8,21 @@ class WC_Tests_Product_Data extends WC_Unit_Test_Case {
|
|||
|
||||
/**
|
||||
* Test product setters and getters
|
||||
* @todo needs tests for attributes
|
||||
* @since 2.7.0
|
||||
*/
|
||||
public function test_product_getters_and_setters() {
|
||||
global $wpdb;
|
||||
|
||||
$attributes = array();
|
||||
$attribute = new WC_Product_Attribute();
|
||||
$attribute->set_id( 0 );
|
||||
$attribute->set_name( 'Test Attribute' );
|
||||
$attribute->set_options( array( 'Fish', 'Fingers' ) );
|
||||
$attribute->set_position( 0 );
|
||||
$attribute->set_visible( true );
|
||||
$attribute->set_variation( false );
|
||||
$attributes['test-attribute'] = $attribute;
|
||||
|
||||
$getters_and_setters = array(
|
||||
'name' => 'Test',
|
||||
'slug' => 'test',
|
||||
|
@ -48,6 +58,7 @@ class WC_Tests_Product_Data extends WC_Unit_Test_Case {
|
|||
'gallery_image_ids' => array(),
|
||||
'download_expiry' => -1,
|
||||
'download_limit' => 5,
|
||||
'attributes' => $attributes,
|
||||
);
|
||||
$product = new WC_Product();
|
||||
foreach ( $getters_and_setters as $function => $value ) {
|
||||
|
|
|
@ -24,6 +24,11 @@ class WC_Tests_Product_Factory extends WC_Unit_Test_Case {
|
|||
$this->assertEquals( 'grouped', WC()->product_factory->get_product_type( $grouped->get_id() ) );
|
||||
$this->assertEquals( 'variable', WC()->product_factory->get_product_type( $variable->get_id() ) );
|
||||
$this->assertEquals( 'variation', WC()->product_factory->get_product_type( $child_id ) );
|
||||
|
||||
$simple->delete( true );
|
||||
$external->delete( true );
|
||||
$grouped->delete( true );
|
||||
$variable->delete( true );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -47,7 +52,7 @@ class WC_Tests_Product_Factory extends WC_Unit_Test_Case {
|
|||
function test_get_product() {
|
||||
$test_product = WC_Helper_Product::create_simple_product();
|
||||
$get_product = WC()->product_factory->get_product( $test_product->get_id() );
|
||||
$this->assertEquals( $test_product, $get_product );
|
||||
$this->assertEquals( $test_product->get_data(), $get_product->get_data() );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -104,6 +104,8 @@ class WC_Tests_Product_Functions extends WC_Unit_Test_Case {
|
|||
// test exclude
|
||||
$products = wc_get_products( array( 'return' => 'ids', 'limit' => 200, 'exclude' => array( $product->get_id() ) ) );
|
||||
$this->assertNotContains( $product->get_id(), $products );
|
||||
|
||||
$variation->delete( true );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -51,7 +51,7 @@ class WC_Tests_Product_Simple extends WC_Unit_Test_Case {
|
|||
// Create product
|
||||
$product = WC_Helper_Product::create_simple_product();
|
||||
|
||||
$this->assertEquals( 'Dummy Product', $product->get_title() );
|
||||
$this->assertEquals( 'Dummy Product', $product->get_name() );
|
||||
|
||||
// Delete product
|
||||
WC_Helper_Product::delete_product( $product->get_id() );
|
||||
|
|
|
@ -287,8 +287,8 @@ final class WooCommerce {
|
|||
include_once( WC_ABSPATH . 'includes/class-wc-data-store.php' ); // WC_Data_Store for CRUD
|
||||
include_once( WC_ABSPATH . 'includes/data-stores/interfaces/interface-wc-object-data-store.php' );
|
||||
include_once( WC_ABSPATH . 'includes/data-stores/interfaces/interface-wc-coupon-data-store.php' );
|
||||
include_once( WC_ABSPATH . 'includes/data-stores/interfaces/interface-wc-product-data-store.php' );
|
||||
include_once( WC_ABSPATH . 'includes/data-stores/interfaces/interface-wc-product-variable-data-store.php' );
|
||||
include_once( WC_ABSPATH . 'includes/data-stores/interfaces/wc-product-data-store-interface.php' );
|
||||
include_once( WC_ABSPATH . 'includes/data-stores/interfaces/wc-product-variable-data-store-interface.php' );
|
||||
include_once( WC_ABSPATH . 'includes/data-stores/interfaces/class-wc-payment-token-data-store-interface.php' );
|
||||
include_once( WC_ABSPATH . 'includes/data-stores/class-wc-data-store-cpt.php' );
|
||||
include_once( WC_ABSPATH . 'includes/data-stores/class-wc-coupon-data-store-cpt.php' );
|
||||
|
|
Loading…
Reference in New Issue