Merge branch 'master' into pr/14936

This commit is contained in:
Mike Jolley 2017-05-08 18:54:54 +01:00
commit 26bc5ab35b
16 changed files with 132 additions and 104 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -388,6 +388,10 @@ table.variations {
cursor: pointer; cursor: pointer;
} }
li:nth-child(4n+1) {
clear: left;
}
img { img {
opacity: .5; opacity: .5;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -245,6 +245,10 @@ p.demo_store,
} }
} }
} }
li:nth-child(4n+1) {
clear: left;
}
} }
} }

View File

@ -853,7 +853,7 @@ abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order {
if ( $item_id = $item->get_id() ) { if ( $item_id = $item->get_id() ) {
$this->items[ $items_key ][ $item_id ] = $item; $this->items[ $items_key ][ $item_id ] = $item;
} else { } else {
$this->items[ $items_key ][ 'new:' . sizeof( $this->items[ $items_key ] ) ] = $item; $this->items[ $items_key ][ 'new:' . $items_key . sizeof( $this->items[ $items_key ] ) ] = $item;
} }
} }

View File

@ -939,10 +939,15 @@ class WC_API_Orders extends WC_API_Resource {
$line_item->set_variation( $item['variations'] ); $line_item->set_variation( $item['variations'] );
} }
$item_id = $line_item->save(); // Save or add to order.
if ( $creating ) {
$order->add_item( $line_item );
} else {
$item_id = $line_item->save();
if ( ! $item_id ) { if ( ! $item_id ) {
throw new WC_API_Exception( 'woocommerce_cannot_create_line_item', __( 'Cannot create line item, try again.', 'woocommerce' ), 500 ); throw new WC_API_Exception( 'woocommerce_cannot_create_line_item', __( 'Cannot create line item, try again.', 'woocommerce' ), 500 );
}
} }
} }
@ -1023,11 +1028,7 @@ class WC_API_Orders extends WC_API_Resource {
$item = new WC_Order_Item_Shipping(); $item = new WC_Order_Item_Shipping();
$item->set_order_id( $order->get_id() ); $item->set_order_id( $order->get_id() );
$item->set_shipping_rate( $rate ); $item->set_shipping_rate( $rate );
$shipping_id = $item->save(); $order->add_item( $item );
if ( ! $shipping_id ) {
throw new WC_API_Exception( 'woocommerce_cannot_create_shipping', __( 'Cannot create shipping method, try again.', 'woocommerce' ), 500 );
}
} else { } else {
$item = new WC_Order_Item_Shipping( $shipping['id'] ); $item = new WC_Order_Item_Shipping( $shipping['id'] );
@ -1094,11 +1095,7 @@ class WC_API_Orders extends WC_API_Resource {
} }
} }
$fee_id = $item->save(); $order->add_item( $item );
if ( ! $fee_id ) {
throw new WC_API_Exception( 'woocommerce_cannot_create_fee', __( 'Cannot create fee, try again.', 'woocommerce' ), 500 );
}
} else { } else {
$item = new WC_Order_Item_Fee( $fee['id'] ); $item = new WC_Order_Item_Fee( $fee['id'] );
@ -1157,11 +1154,7 @@ class WC_API_Orders extends WC_API_Resource {
'discount_tax' => 0, 'discount_tax' => 0,
'order_id' => $order->get_id(), 'order_id' => $order->get_id(),
) ); ) );
$coupon_id = $item->save(); $order->add_item( $item );
if ( ! $coupon_id ) {
throw new WC_API_Exception( 'woocommerce_cannot_create_order_coupon', __( 'Cannot create coupon, try again.', 'woocommerce' ), 500 );
}
} else { } else {
$item = new WC_Order_Item_Coupon( $coupon['id'] ); $item = new WC_Order_Item_Coupon( $coupon['id'] );

View File

@ -988,10 +988,15 @@ class WC_API_Orders extends WC_API_Resource {
$line_item->set_variation( $item['variations'] ); $line_item->set_variation( $item['variations'] );
} }
$item_id = $line_item->save(); // Save or add to order.
if ( $creating ) {
$order->add_item( $line_item );
} else {
$item_id = $line_item->save();
if ( ! $item_id ) { if ( ! $item_id ) {
throw new WC_API_Exception( 'woocommerce_cannot_create_line_item', __( 'Cannot create line item, try again.', 'woocommerce' ), 500 ); throw new WC_API_Exception( 'woocommerce_cannot_create_line_item', __( 'Cannot create line item, try again.', 'woocommerce' ), 500 );
}
} }
} }
@ -1073,11 +1078,7 @@ class WC_API_Orders extends WC_API_Resource {
$item = new WC_Order_Item_Shipping(); $item = new WC_Order_Item_Shipping();
$item->set_order_id( $order->get_id() ); $item->set_order_id( $order->get_id() );
$item->set_shipping_rate( $rate ); $item->set_shipping_rate( $rate );
$shipping_id = $item->save(); $order->add_item( $item );
if ( ! $shipping_id ) {
throw new WC_API_Exception( 'woocommerce_cannot_create_shipping', __( 'Cannot create shipping method, try again.', 'woocommerce' ), 500 );
}
} else { } else {
$item = new WC_Order_Item_Shipping( $shipping['id'] ); $item = new WC_Order_Item_Shipping( $shipping['id'] );
@ -1144,11 +1145,7 @@ class WC_API_Orders extends WC_API_Resource {
} }
} }
$fee_id = $item->save(); $order->add_item( $item );
if ( ! $fee_id ) {
throw new WC_API_Exception( 'woocommerce_cannot_create_fee', __( 'Cannot create fee, try again.', 'woocommerce' ), 500 );
}
} else { } else {
$item = new WC_Order_Item_Fee( $fee['id'] ); $item = new WC_Order_Item_Fee( $fee['id'] );
@ -1207,11 +1204,7 @@ class WC_API_Orders extends WC_API_Resource {
'discount_tax' => 0, 'discount_tax' => 0,
'order_id' => $order->get_id(), 'order_id' => $order->get_id(),
) ); ) );
$coupon_id = $item->save(); $order->add_item( $item );
if ( ! $coupon_id ) {
throw new WC_API_Exception( 'woocommerce_cannot_create_order_coupon', __( 'Cannot create coupon, try again.', 'woocommerce' ), 500 );
}
} else { } else {
$item = new WC_Order_Item_Coupon( $coupon['id'] ); $item = new WC_Order_Item_Coupon( $coupon['id'] );

View File

@ -200,34 +200,36 @@ class WC_Structured_Data {
return; return;
} }
$markup_offer = array( if ( '' !== $product->get_price() ) {
'@type' => 'Offer', $markup_offer = array(
'priceCurrency' => $currency, '@type' => 'Offer',
'availability' => 'https://schema.org/' . $stock = ( $product->is_in_stock() ? 'InStock' : 'OutOfStock' ),
'sku' => $product->get_sku(),
'image' => wp_get_attachment_url( $product->get_image_id() ),
'description' => $product->get_description(),
'seller' => array(
'@type' => 'Organization',
'name' => $shop_name,
'url' => $shop_url,
),
);
if ( $product->is_type( 'variable' ) ) {
$prices = $product->get_variation_prices();
$markup_offer['priceSpecification'] = array(
'price' => wc_format_decimal( $product->get_price(), wc_get_price_decimals() ),
'minPrice' => wc_format_decimal( current( $prices['price'] ), wc_get_price_decimals() ),
'maxPrice' => wc_format_decimal( end( $prices['price'] ), wc_get_price_decimals() ),
'priceCurrency' => $currency, 'priceCurrency' => $currency,
'availability' => 'https://schema.org/' . $stock = ( $product->is_in_stock() ? 'InStock' : 'OutOfStock' ),
'sku' => $product->get_sku(),
'image' => wp_get_attachment_url( $product->get_image_id() ),
'description' => $product->get_description(),
'seller' => array(
'@type' => 'Organization',
'name' => $shop_name,
'url' => $shop_url,
),
); );
} else {
$markup_offer['price'] = wc_format_decimal( $product->get_price(), wc_get_price_decimals() );
}
$markup['offers'] = array( apply_filters( 'woocommerce_structured_data_product_offer', $markup_offer, $product ) ); if ( $product->is_type( 'variable' ) ) {
$prices = $product->get_variation_prices();
$markup_offer['priceSpecification'] = array(
'price' => wc_format_decimal( $product->get_price(), wc_get_price_decimals() ),
'minPrice' => wc_format_decimal( current( $prices['price'] ), wc_get_price_decimals() ),
'maxPrice' => wc_format_decimal( end( $prices['price'] ), wc_get_price_decimals() ),
'priceCurrency' => $currency,
);
} else {
$markup_offer['price'] = wc_format_decimal( $product->get_price(), wc_get_price_decimals() );
}
$markup['offers'] = array( apply_filters( 'woocommerce_structured_data_product_offer', $markup_offer, $product ) );
}
if ( $product->get_rating_count() ) { if ( $product->get_rating_count() ) {
$markup['aggregateRating'] = array( $markup['aggregateRating'] = array(
@ -398,7 +400,7 @@ class WC_Structured_Data {
$markup = array(); $markup = array();
$markup['@type'] = 'Order'; $markup['@type'] = 'Order';
$markup['url'] = $order_url; $markup['url'] = $order_url;
$markup['orderStatus'] = isset( $order_status[ $order->get_status() ] ) ? $order_status[ $order->get_status() ] : ''; $markup['orderStatus'] = isset( $order_statuses[ $order->get_status() ] ) ? $order_statuses[ $order->get_status() ] : '';
$markup['orderNumber'] = $order->get_order_number(); $markup['orderNumber'] = $order->get_order_number();
$markup['orderDate'] = $order->get_date_created()->format( 'c' ); $markup['orderDate'] = $order->get_date_created()->format( 'c' );
$markup['acceptedOffer'] = $markup_offers; $markup['acceptedOffer'] = $markup_offers;

View File

@ -997,50 +997,46 @@ class WC_Product_Data_Store_CPT extends WC_Data_Store_WP implements WC_Object_Da
public 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; global $wpdb;
// Arrays to string. $include_term_ids = array_merge( $cats_array, $tags_array );
$exclude_ids = implode( ',', array_map( 'absint', $exclude_ids ) ); $exclude_term_ids = array();
$cats_array = implode( ',', array_map( 'absint', $cats_array ) );
$tags_array = implode( ',', array_map( 'absint', $tags_array ) );
$limit = absint( $limit );
$query = array();
$query['fields'] = "SELECT DISTINCT ID FROM {$wpdb->posts} p";
$query['join'] = " INNER JOIN {$wpdb->term_relationships} tr ON (p.ID = tr.object_id)";
$query['join'] .= " INNER JOIN {$wpdb->term_taxonomy} tt ON (tr.term_taxonomy_id = tt.term_taxonomy_id)";
$query['join'] .= " INNER JOIN {$wpdb->terms} t ON (t.term_id = tt.term_id)";
$query['where'] = ' WHERE 1=1';
$query['where'] .= " AND p.post_status = 'publish'";
$query['where'] .= " AND p.post_type = 'product'";
$query['where'] .= " AND p.ID NOT IN ( {$exclude_ids} )";
$product_visibility_term_ids = wc_get_product_visibility_term_ids(); $product_visibility_term_ids = wc_get_product_visibility_term_ids();
if ( $product_visibility_term_ids['exclude-from-catalog'] ) { if ( $product_visibility_term_ids['exclude-from-catalog'] ) {
$query['where'] .= " AND t.term_id !=" . $product_visibility_term_ids['exclude-from-catalog']; $exclude_term_ids[] = $product_visibility_term_ids['exclude-from-catalog'];
} }
if ( 'yes' === get_option( 'woocommerce_hide_out_of_stock_items' ) && $product_visibility_term_ids['outofstock'] ) { if ( 'yes' === get_option( 'woocommerce_hide_out_of_stock_items' ) && $product_visibility_term_ids['outofstock'] ) {
$query['where'] .= " AND t.term_id !=" . $product_visibility_term_ids['outofstock']; $exclude_term_ids[] = $product_visibility_term_ids['outofstock'];
} }
if ( $cats_array || $tags_array ) { $query = array(
$query['where'] .= ' AND ('; 'fields' => "
SELECT DISTINCT ID FROM {$wpdb->posts} p
",
'join' => '',
'where' => "
WHERE 1=1
AND p.post_status = 'publish'
AND p.post_type = 'product'
if ( $cats_array ) { ",
$query['where'] .= " ( tt.taxonomy = 'product_cat' AND t.term_id IN ( {$cats_array} ) ) "; 'limits' => "
if ( $tags_array ) { LIMIT " . absint( $limit ) . "
$query['where'] .= ' OR '; ",
} );
}
if ( $tags_array ) { if ( $exclude_term_ids ) {
$query['where'] .= " ( tt.taxonomy = 'product_tag' AND t.term_id IN ( {$tags_array} ) ) "; $query['join'] .= " LEFT JOIN ( SELECT object_id FROM {$wpdb->term_relationships} WHERE term_taxonomy_id IN ( " . implode( ',', array_map( 'absint', $exclude_term_ids ) ) . " ) ) AS exclude_join ON exclude_join.object_id = p.ID";
} $query['where'] .= " AND exclude_join.object_id IS NULL";
$query['where'] .= ')';
} }
$query['limits'] = " LIMIT {$limit} "; if ( $include_term_ids ) {
$query['join'] .= " INNER JOIN ( SELECT object_id FROM {$wpdb->term_relationships} LEFT JOIN wp_term_taxonomy AS tax using( term_taxonomy_id ) WHERE term_id IN ( " . implode( ',', array_map( 'absint', $include_term_ids ) ) . " ) ) AS include_join ON include_join.object_id = p.ID";
}
if ( $exclude_ids ) {
$query['where'] .= " AND p.ID NOT IN ( " . implode( ',', array_map( 'absint', $exclude_ids ) ) . " )";
}
return $query; return $query;
} }

View File

@ -280,7 +280,7 @@ class WC_Email extends WC_Settings_API {
public function get_headers() { public function get_headers() {
$header = "Content-Type: " . $this->get_content_type() . "\r\n"; $header = "Content-Type: " . $this->get_content_type() . "\r\n";
if ( 'new_order' === $this->id ) { if ( 'new_order' === $this->id && $this->object && $this->object->get_billing_email() && ( $this->object->get_billing_first_name() || $this->object->get_billing_last_name() ) ) {
$header .= 'Reply-to: ' . $this->object->get_billing_first_name() . ' ' . $this->object->get_billing_last_name() . ' <' . $this->object->get_billing_email() . ">\r\n"; $header .= 'Reply-to: ' . $this->object->get_billing_first_name() . ' ' . $this->object->get_billing_last_name() . ' <' . $this->object->get_billing_email() . ">\r\n";
} }

View File

@ -707,7 +707,7 @@ function wc_get_product_attachment_props( $attachment_id = null, $product = fals
$props['alt'] = trim( strip_tags( get_post_meta( $attachment_id, '_wp_attachment_image_alt', true ) ) ); $props['alt'] = trim( strip_tags( get_post_meta( $attachment_id, '_wp_attachment_image_alt', true ) ) );
// Large version. // Large version.
$src = wp_get_attachment_image_src( $attachment_id, 'large' ); $src = wp_get_attachment_image_src( $attachment_id, 'full' );
$props['full_src'] = $src[0]; $props['full_src'] = $src[0];
$props['full_src_w'] = $src[1]; $props['full_src_w'] = $src[1];
$props['full_src_h'] = $src[2]; $props['full_src_h'] = $src[2];

View File

@ -106,6 +106,18 @@ function wc_prevent_adjacent_posts_rel_link_wp_head() {
} }
add_action( 'template_redirect', 'wc_prevent_adjacent_posts_rel_link_wp_head' ); add_action( 'template_redirect', 'wc_prevent_adjacent_posts_rel_link_wp_head' );
/**
* Show the gallery if JS is disabled.
*
* @since 3.0.6
*/
function wc_gallery_noscript() {
?>
<noscript><style>.woocommerce-product-gallery{ opacity: 1 !important; }</style></noscript>
<?php
}
add_action( 'wp_head', 'wc_gallery_noscript' );
/** /**
* When the_post is called, put product data into a global. * When the_post is called, put product data into a global.
* *

View File

@ -13,7 +13,7 @@
* @see https://docs.woocommerce.com/document/template-structure/ * @see https://docs.woocommerce.com/document/template-structure/
* @author WooThemes * @author WooThemes
* @package WooCommerce/Templates * @package WooCommerce/Templates
* @version 3.0.3 * @version 3.0.6
*/ */
if ( ! defined( 'ABSPATH' ) ) { if ( ! defined( 'ABSPATH' ) ) {
exit; exit;
@ -28,12 +28,13 @@ do_action( 'woocommerce_before_add_to_cart_form' ); ?>
<tbody> <tbody>
<?php <?php
$quantites_required = false; $quantites_required = false;
$previous_post = $post;
foreach ( $grouped_products as $grouped_product ) { foreach ( $grouped_products as $grouped_product ) {
$post_object = get_post( $grouped_product->get_id() ); $post_object = get_post( $grouped_product->get_id() );
$quantites_required = $quantites_required || ( $grouped_product->is_purchasable() && ! $grouped_product->has_options() ); $quantites_required = $quantites_required || ( $grouped_product->is_purchasable() && ! $grouped_product->has_options() );
setup_postdata( $GLOBALS['post'] =& $post_object ); setup_postdata( $post =& $post_object );
?> ?>
<tr id="product-<?php the_ID(); ?>" <?php post_class(); ?>> <tr id="product-<?php the_ID(); ?>" <?php post_class(); ?>>
<td> <td>
@ -79,7 +80,7 @@ do_action( 'woocommerce_before_add_to_cart_form' ); ?>
</tr> </tr>
<?php <?php
} }
wp_reset_postdata(); $post = $previous_post;
?> ?>
</tbody> </tbody>
</table> </table>

View File

@ -272,6 +272,29 @@ class WC_Tests_CRUD_Orders extends WC_Unit_Test_Case {
$object->save(); $object->save();
$this->assertCount( 2, $object->get_items() ); $this->assertCount( 2, $object->get_items() );
} }
/**
* Test: get_different_items
*/
function test_get_different_items() {
$object = new WC_Order();
$item_1 = new WC_Order_Item_Product();
$item_1->set_props( array(
'product' => WC_Helper_Product::create_simple_product(),
'quantity' => 4,
) );
$item_2 = new WC_Order_Item_Fee();
$item_2->set_props( array(
'name' => 'Some Fee',
'tax_status' => 'taxable',
'total' => '100',
'tax_class' => '',
) );
$object->add_item( $item_1 );
$object->add_item( $item_2 );
// $object->save();
$this->assertCount( 2, $object->get_items( array( 'line_item', 'fee' ) ) );
}
/** /**
* Test: get_fees * Test: get_fees