Merge branch 'master' into feature/webhook-crud
This commit is contained in:
commit
13978e496b
|
@ -199,6 +199,7 @@ module.exports = function( grunt ) {
|
|||
potFilename: 'woocommerce.pot',
|
||||
exclude: [
|
||||
'apigen/.*',
|
||||
'vendor/.*',
|
||||
'tests/.*',
|
||||
'tmp/.*'
|
||||
]
|
||||
|
|
|
@ -472,13 +472,13 @@ jQuery( function ( $ ) {
|
|||
if ( value != null ) {
|
||||
wc_meta_boxes_order_items.block();
|
||||
|
||||
var data = {
|
||||
var data = $.extend( {}, wc_meta_boxes_order_items.get_taxable_address(), {
|
||||
action : 'woocommerce_add_order_fee',
|
||||
dataType: 'json',
|
||||
order_id: woocommerce_admin_meta_boxes.post_id,
|
||||
security: woocommerce_admin_meta_boxes.order_item_nonce,
|
||||
amount : value
|
||||
};
|
||||
} );
|
||||
|
||||
$.post( woocommerce_admin_meta_boxes.ajax_url, data, function( response ) {
|
||||
if ( response.success ) {
|
||||
|
@ -543,12 +543,13 @@ jQuery( function ( $ ) {
|
|||
|
||||
wc_meta_boxes_order_items.block();
|
||||
|
||||
var data = {
|
||||
var data = $.extend( {}, wc_meta_boxes_order_items.get_taxable_address(), {
|
||||
order_id : woocommerce_admin_meta_boxes.post_id,
|
||||
order_item_ids: order_item_id,
|
||||
action : 'woocommerce_remove_order_item',
|
||||
security : woocommerce_admin_meta_boxes.order_item_nonce
|
||||
};
|
||||
} );
|
||||
|
||||
// Check if items have changed, if so pass them through so we can save them before deleting.
|
||||
if ( 'true' === $( 'button.cancel-action' ).attr( 'data-reload' ) ) {
|
||||
data.items = $( 'table.woocommerce_order_items :input[name], .wc-order-totals-items :input[name]' ).serialize();
|
||||
|
@ -607,39 +608,44 @@ jQuery( function ( $ ) {
|
|||
return false;
|
||||
},
|
||||
|
||||
get_taxable_address: function() {
|
||||
var country = '';
|
||||
var state = '';
|
||||
var postcode = '';
|
||||
var city = '';
|
||||
|
||||
if ( 'shipping' === woocommerce_admin_meta_boxes.tax_based_on ) {
|
||||
country = $( '#_shipping_country' ).val();
|
||||
state = $( '#_shipping_state' ).val();
|
||||
postcode = $( '#_shipping_postcode' ).val();
|
||||
city = $( '#_shipping_city' ).val();
|
||||
}
|
||||
|
||||
if ( 'billing' === woocommerce_admin_meta_boxes.tax_based_on || ! country ) {
|
||||
country = $( '#_billing_country' ).val();
|
||||
state = $( '#_billing_state' ).val();
|
||||
postcode = $( '#_billing_postcode' ).val();
|
||||
city = $( '#_billing_city' ).val();
|
||||
}
|
||||
|
||||
return {
|
||||
country: country,
|
||||
state: state,
|
||||
postcode: postcode,
|
||||
city: city
|
||||
};
|
||||
},
|
||||
|
||||
recalculate: function() {
|
||||
if ( window.confirm( woocommerce_admin_meta_boxes.calc_totals ) ) {
|
||||
wc_meta_boxes_order_items.block();
|
||||
|
||||
var country = '';
|
||||
var state = '';
|
||||
var postcode = '';
|
||||
var city = '';
|
||||
|
||||
if ( 'shipping' === woocommerce_admin_meta_boxes.tax_based_on ) {
|
||||
country = $( '#_shipping_country' ).val();
|
||||
state = $( '#_shipping_state' ).val();
|
||||
postcode = $( '#_shipping_postcode' ).val();
|
||||
city = $( '#_shipping_city' ).val();
|
||||
}
|
||||
|
||||
if ( 'billing' === woocommerce_admin_meta_boxes.tax_based_on || ! country ) {
|
||||
country = $( '#_billing_country' ).val();
|
||||
state = $( '#_billing_state' ).val();
|
||||
postcode = $( '#_billing_postcode' ).val();
|
||||
city = $( '#_billing_city' ).val();
|
||||
}
|
||||
|
||||
var data = {
|
||||
var data = $.extend( {}, wc_meta_boxes_order_items.get_taxable_address(), {
|
||||
action: 'woocommerce_calc_line_taxes',
|
||||
order_id: woocommerce_admin_meta_boxes.post_id,
|
||||
items: $( 'table.woocommerce_order_items :input[name], .wc-order-totals-items :input[name]' ).serialize(),
|
||||
country: country,
|
||||
state: state,
|
||||
postcode: postcode,
|
||||
city: city,
|
||||
security: woocommerce_admin_meta_boxes.calc_totals_nonce
|
||||
};
|
||||
} );
|
||||
|
||||
$.ajax({
|
||||
url: woocommerce_admin_meta_boxes.ajax_url,
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -99,9 +99,9 @@ jQuery( function( $ ) {
|
|||
}
|
||||
|
||||
if ( $( this ).data( 'order_button_text' ) ) {
|
||||
$( '#place_order' ).val( $( this ).data( 'order_button_text' ) );
|
||||
$( '#place_order' ).text( $( this ).data( 'order_button_text' ) );
|
||||
} else {
|
||||
$( '#place_order' ).val( $( '#place_order' ).data( 'value' ) );
|
||||
$( '#place_order' ).text( $( '#place_order' ).data( 'value' ) );
|
||||
}
|
||||
|
||||
var selectedPaymentMethod = $( '.woocommerce-checkout input[name="payment_method"]:checked' ).attr( 'id' );
|
||||
|
|
|
@ -1762,6 +1762,17 @@ class WC_Product extends WC_Abstract_Legacy_Product {
|
|||
return apply_filters( 'woocommerce_product_add_to_cart_text', __( 'Read more', 'woocommerce' ), $this );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the add to cart button text description - used in aria tags.
|
||||
*
|
||||
* @since 3.3.0
|
||||
* @return string
|
||||
*/
|
||||
public function add_to_cart_description() {
|
||||
/* translators: %s: Product title */
|
||||
return apply_filters( 'woocommerce_product_add_to_cart_description', sprintf( __( 'Read more about “%s”', 'woocommerce' ), $this->get_name() ), $this );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the main product image.
|
||||
*
|
||||
|
|
|
@ -744,7 +744,7 @@ class WC_Admin_Post_Types {
|
|||
echo '<input type="radio" name="_visibility" id="_visibility_' . esc_attr( $name ) . '" value="' . esc_attr( $name ) . '" ' . checked( $current_visibility, $name, false ) . ' data-label="' . esc_attr( $label ) . '" /> <label for="_visibility_' . esc_attr( $name ) . '" class="selectit">' . esc_html( $label ) . '</label><br />';
|
||||
}
|
||||
|
||||
echo '<br /><input type="checkbox" name="_featured" id="_featured" ' . checked( $current_featured, 'yes', false ) . ' /> <label for="_featured">' . esc_html_e( 'This is a featured product', 'woocommerce' ) . '</label><br />';
|
||||
echo '<br /><input type="checkbox" name="_featured" id="_featured" ' . checked( $current_featured, 'yes', false ) . ' /> <label for="_featured">' . esc_html__( 'This is a featured product', 'woocommerce' ) . '</label><br />';
|
||||
?>
|
||||
<p>
|
||||
<a href="#catalog-visibility" class="save-post-visibility hide-if-no-js button"><?php esc_html_e( 'OK', 'woocommerce' ); ?></a>
|
||||
|
@ -769,11 +769,11 @@ class WC_Admin_Post_Types {
|
|||
$pathdata['url'] = $pathdata['url'] . '/woocommerce_uploads';
|
||||
$pathdata['subdir'] = '/woocommerce_uploads';
|
||||
} else {
|
||||
$new_subdir = '/woocommerce_uploads' . $uploads['subdir'];
|
||||
$new_subdir = '/woocommerce_uploads' . $pathdata['subdir'];
|
||||
|
||||
$uploads['path'] = str_replace( $uploads['subdir'], $new_subdir, $uploads['path'] );
|
||||
$uploads['url'] = str_replace( $uploads['subdir'], $new_subdir, $uploads['url'] );
|
||||
$uploads['subdir'] = str_replace( $uploads['subdir'], $new_subdir, $uploads['subdir'] );
|
||||
$pathdata['path'] = str_replace( $pathdata['subdir'], $new_subdir, $pathdata['path'] );
|
||||
$pathdata['url'] = str_replace( $pathdata['subdir'], $new_subdir, $pathdata['url'] );
|
||||
$pathdata['subdir'] = str_replace( $pathdata['subdir'], $new_subdir, $pathdata['subdir'] );
|
||||
}
|
||||
}
|
||||
return $pathdata;
|
||||
|
@ -827,7 +827,7 @@ class WC_Admin_Post_Types {
|
|||
|
||||
if ( $post && absint( $shop_page_id ) === absint( $post->ID ) ) {
|
||||
echo '<div class="notice notice-info">';
|
||||
echo '<p>' . sprintf( wp_kses_post( __( 'This is the WooCommerce shop page. The shop page is a special archive that lists your products. <a href="%s">You can read more about this here</a>.', 'woocommerce' ), 'https://docs.woocommerce.com/document/woocommerce-pages/#section-4' ) ) . '</p>';
|
||||
echo '<p>' . sprintf( wp_kses_post( __( 'This is the WooCommerce shop page. The shop page is a special archive that lists your products. <a href="%s">You can read more about this here</a>.', 'woocommerce' ) ), 'https://docs.woocommerce.com/document/woocommerce-pages/#section-4' ) . '</p>';
|
||||
echo '</div>';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -179,7 +179,7 @@ class WC_Admin_Profile {
|
|||
<?php elseif ( ! empty( $field['type'] ) && 'checkbox' === $field['type'] ) : ?>
|
||||
<input type="checkbox" name="<?php echo esc_attr( $key ); ?>" id="<?php echo esc_attr( $key ); ?>" value="1" class="<?php echo esc_attr( $field['class'] ); ?>" <?php checked( (int) get_user_meta( $user->ID, $key, true ), 1, true ); ?> />
|
||||
<?php elseif ( ! empty( $field['type'] ) && 'button' === $field['type'] ) : ?>
|
||||
<button id="<?php echo esc_attr( $key ); ?>" class="button <?php echo esc_attr( $field['class'] ); ?>"><?php echo esc_html( $field['text'] ); ?></button>
|
||||
<button type="button" id="<?php echo esc_attr( $key ); ?>" class="button <?php echo esc_attr( $field['class'] ); ?>"><?php echo esc_html( $field['text'] ); ?></button>
|
||||
<?php else : ?>
|
||||
<input type="text" name="<?php echo esc_attr( $key ); ?>" id="<?php echo esc_attr( $key ); ?>" value="<?php echo esc_attr( $this->get_user_meta( $user->ID, $key ) ); ?>" class="<?php echo ( ! empty( $field['class'] ) ? esc_attr( $field['class'] ) : 'regular-text' ); ?>" />
|
||||
<?php endif; ?>
|
||||
|
|
|
@ -1265,8 +1265,14 @@ class WC_Admin_Setup_Wizard {
|
|||
<form method="post" class="wc-wizard-payment-gateway-form">
|
||||
<p>
|
||||
<?php printf(
|
||||
esc_html__(
|
||||
'WooCommerce can accept both online and offline payments. <a href="%1$s" target="_blank">Additional payment methods</a> can be installed later.', 'woocommerce'
|
||||
wp_kses(
|
||||
__( 'WooCommerce can accept both online and offline payments. <a href="%1$s" target="_blank">Additional payment methods</a> can be installed later.', 'woocommerce' ),
|
||||
array(
|
||||
'a' => array(
|
||||
'href' => array(),
|
||||
'target' => array(),
|
||||
),
|
||||
)
|
||||
),
|
||||
esc_url( admin_url( 'admin.php?page=wc-addons&view=payment-gateways' ) )
|
||||
); ?>
|
||||
|
|
|
@ -326,6 +326,8 @@ class WC_Admin_List_Table_Orders extends WC_Admin_List_Table {
|
|||
</button>
|
||||
</header>
|
||||
<article>
|
||||
<?php do_action( 'woocommerce_admin_order_preview_start' ); ?>
|
||||
|
||||
{{{ data.item_html }}}
|
||||
|
||||
<div class="wc-order-preview-addresses">
|
||||
|
@ -369,6 +371,7 @@ class WC_Admin_List_Table_Orders extends WC_Admin_List_Table {
|
|||
</div>
|
||||
<# } #>
|
||||
</div>
|
||||
<?php do_action( 'woocommerce_admin_order_preview_end' ); ?>
|
||||
</article>
|
||||
<footer>
|
||||
<div class="inner">
|
||||
|
|
|
@ -45,9 +45,12 @@ class WC_Meta_Box_Order_Items {
|
|||
* Save meta box data.
|
||||
*
|
||||
* @param int $post_id
|
||||
* @param WP_Post $post
|
||||
*/
|
||||
public static function save( $post_id, $post ) {
|
||||
public static function save( $post_id ) {
|
||||
/**
|
||||
* This $_POST variable's data has been validated and escaped
|
||||
* inside `wc_save_order_items()` function.
|
||||
*/
|
||||
wc_save_order_items( $post_id, $_POST );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ $thumbnail = $product ? apply_filters( 'woocommerce_admin_order_item_thumbnai
|
|||
</td>
|
||||
<td class="name" data-sort-value="<?php echo esc_attr( $item->get_name() ); ?>">
|
||||
<?php
|
||||
echo $product_link ? '<a href="' . esc_url( $product_link ) . '" class="wc-order-item-name">' . esc_html( $item->get_name() ) . '</a>' : '<div class=""wc-order-item-name">' . esc_html( $item->get_name() ) . '</div>';
|
||||
echo $product_link ? '<a href="' . esc_url( $product_link ) . '" class="wc-order-item-name">' . esc_html( $item->get_name() ) . '</a>' : '<div class="wc-order-item-name">' . esc_html( $item->get_name() ) . '</div>';
|
||||
|
||||
if ( $product && $product->get_sku() ) {
|
||||
echo '<div class="wc-order-item-sku"><strong>' . __( 'SKU:', 'woocommerce' ) . '</strong> ' . esc_html( $product->get_sku() ) . '</div>';
|
||||
|
|
|
@ -1159,7 +1159,7 @@ class WC_REST_Orders_Controller extends WC_REST_Legacy_Orders_Controller {
|
|||
),
|
||||
'tax_class' => array(
|
||||
'description' => __( 'Tax class of product.', 'woocommerce' ),
|
||||
'type' => 'integer',
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
'subtotal' => array(
|
||||
|
@ -1244,7 +1244,7 @@ class WC_REST_Orders_Controller extends WC_REST_Legacy_Orders_Controller {
|
|||
),
|
||||
'price' => array(
|
||||
'description' => __( 'Product price.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'type' => 'number',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
|
|
|
@ -1917,6 +1917,9 @@ class WC_REST_Products_Controller extends WC_REST_Legacy_Products_Controller {
|
|||
'description' => __( 'List of available term names of the attribute.', 'woocommerce' ),
|
||||
'type' => 'array',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'items' => array(
|
||||
'type' => 'string',
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
@ -1238,7 +1238,7 @@ class WC_REST_Orders_V1_Controller extends WC_REST_Posts_Controller {
|
|||
),
|
||||
'tax_class' => array(
|
||||
'description' => __( 'Tax class of product.', 'woocommerce' ),
|
||||
'type' => 'integer',
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
|
|
|
@ -548,7 +548,7 @@ class WC_AJAX {
|
|||
<?php
|
||||
$item_html = ob_get_clean();
|
||||
|
||||
wp_send_json_success( array(
|
||||
wp_send_json_success( apply_filters( 'woocommerce_ajax_get_order_details', array(
|
||||
'data' => $order->get_data(),
|
||||
'order_number' => $order->get_order_number(),
|
||||
'item_html' => $item_html,
|
||||
|
@ -559,7 +559,7 @@ class WC_AJAX {
|
|||
'shipping_address_map_url' => $order->get_shipping_address_map_url(),
|
||||
'payment_via' => $order->get_payment_method_title() . ( $order->get_transaction_id() ? ' (' . $order->get_transaction_id() . ')' : '' ),
|
||||
'shipping_via' => $order->get_shipping_method(),
|
||||
) );
|
||||
), $order ) );
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
@ -686,7 +686,7 @@ class WC_AJAX {
|
|||
$product_object = wc_get_product( $product_id );
|
||||
$variation_object = new WC_Product_Variation();
|
||||
$variation_object->set_parent_id( $product_id );
|
||||
$variation_object->set_attributes( array_fill_keys( array_keys( $product_object->get_variation_attributes() ), '' ) );
|
||||
$variation_object->set_attributes( array_fill_keys( array_map( 'sanitize_title', array_keys( $product_object->get_variation_attributes() ) ), '' ) );
|
||||
$variation_id = $variation_object->save();
|
||||
$variation = get_post( $variation_id );
|
||||
$variation_data = array_merge( array_map( 'maybe_unserialize', get_post_custom( $variation_id ) ), wc_get_product_variation_attributes( $variation_id ) ); // kept for BW compatibility.
|
||||
|
@ -913,9 +913,15 @@ class WC_AJAX {
|
|||
}
|
||||
|
||||
try {
|
||||
$order_id = absint( $_POST['order_id'] );
|
||||
$amount = wc_clean( $_POST['amount'] );
|
||||
$order = wc_get_order( $order_id );
|
||||
$order_id = absint( $_POST['order_id'] );
|
||||
$amount = wc_clean( $_POST['amount'] );
|
||||
$order = wc_get_order( $order_id );
|
||||
$calculate_tax_args = array(
|
||||
'country' => strtoupper( wc_clean( $_POST['country'] ) ),
|
||||
'state' => strtoupper( wc_clean( $_POST['state'] ) ),
|
||||
'postcode' => strtoupper( wc_clean( $_POST['postcode'] ) ),
|
||||
'city' => strtoupper( wc_clean( $_POST['city'] ) ),
|
||||
);
|
||||
|
||||
if ( ! $order ) {
|
||||
throw new exception( __( 'Invalid order', 'woocommerce' ) );
|
||||
|
@ -936,7 +942,8 @@ class WC_AJAX {
|
|||
$fee->set_name( sprintf( __( '%s fee', 'woocommerce' ), $formatted_amount ) );
|
||||
|
||||
$order->add_item( $fee );
|
||||
$order->calculate_totals( true );
|
||||
$order->calculate_taxes( $calculate_tax_args );
|
||||
$order->calculate_totals( false );
|
||||
$order->save();
|
||||
|
||||
ob_start();
|
||||
|
@ -1084,9 +1091,15 @@ class WC_AJAX {
|
|||
}
|
||||
|
||||
try {
|
||||
$order_id = absint( $_POST['order_id'] );
|
||||
$order_item_ids = $_POST['order_item_ids'];
|
||||
$items = ( ! empty( $_POST['items'] ) ) ? $_POST['items'] : '';
|
||||
$order_id = absint( $_POST['order_id'] );
|
||||
$order_item_ids = $_POST['order_item_ids'];
|
||||
$items = ( ! empty( $_POST['items'] ) ) ? $_POST['items']: '';
|
||||
$calculate_tax_args = array(
|
||||
'country' => strtoupper( wc_clean( $_POST['country'] ) ),
|
||||
'state' => strtoupper( wc_clean( $_POST['state'] ) ),
|
||||
'postcode' => strtoupper( wc_clean( $_POST['postcode'] ) ),
|
||||
'city' => strtoupper( wc_clean( $_POST['city'] ) ),
|
||||
);
|
||||
|
||||
if ( ! is_array( $order_item_ids ) && is_numeric( $order_item_ids ) ) {
|
||||
$order_item_ids = array( $order_item_ids );
|
||||
|
@ -1107,7 +1120,8 @@ class WC_AJAX {
|
|||
}
|
||||
|
||||
$order = wc_get_order( $order_id );
|
||||
$order->calculate_totals( true );
|
||||
$order->calculate_taxes( $calculate_tax_args );
|
||||
$order->calculate_totals( false );
|
||||
|
||||
ob_start();
|
||||
include( 'admin/meta-boxes/views/html-order-items.php' );
|
||||
|
@ -1325,15 +1339,30 @@ class WC_AJAX {
|
|||
if ( $post_id > 0 ) {
|
||||
$order = wc_get_order( $post_id );
|
||||
$comment_id = $order->add_order_note( $note, $is_customer_note, true );
|
||||
$note = wc_get_order_note( $comment_id );
|
||||
|
||||
echo '<li rel="' . esc_attr( $comment_id ) . '" class="note ';
|
||||
if ( $is_customer_note ) {
|
||||
echo 'customer-note';
|
||||
}
|
||||
echo '"><div class="note_content">';
|
||||
echo wpautop( wptexturize( $note ) );
|
||||
echo '</div><p class="meta"><a href="#" class="delete_note">' . __( 'Delete note', 'woocommerce' ) . '</a></p>';
|
||||
echo '</li>';
|
||||
$note_classes = array( 'note' );
|
||||
$note_classes[] = $is_customer_note ? 'customer-note' : '';
|
||||
$note_classes = apply_filters( 'woocommerce_order_note_class', array_filter( $note_classes ), $note );
|
||||
?>
|
||||
<li rel="<?php echo absint( $note->id ); ?>" class="<?php echo esc_attr( implode( ' ', $note_classes ) ); ?>">
|
||||
<div class="note_content">
|
||||
<?php echo wpautop( wptexturize( wp_kses_post( $note->content ) ) ); ?>
|
||||
</div>
|
||||
<p class="meta">
|
||||
<abbr class="exact-date" title="<?php echo $note->date_created->date( 'y-m-d h:i:s' ); ?>">
|
||||
<?php printf( __( 'added on %1$s at %2$s', 'woocommerce' ), $note->date_created->date_i18n( wc_date_format() ), $note->date_created->date_i18n( wc_time_format() ) ); ?>
|
||||
</abbr>
|
||||
<?php
|
||||
if ( 'system' !== $note->added_by ) :
|
||||
/* translators: %s: note author */
|
||||
printf( ' ' . __( 'by %s', 'woocommerce' ), $note->added_by );
|
||||
endif;
|
||||
?>
|
||||
<a href="#" class="delete_note" role="button"><?php _e( 'Delete note', 'woocommerce' ); ?></a>
|
||||
</p>
|
||||
</li>
|
||||
<?php
|
||||
}
|
||||
wp_die();
|
||||
}
|
||||
|
|
|
@ -89,7 +89,7 @@ class WC_API extends WC_Legacy_API {
|
|||
wc_nocache_headers();
|
||||
|
||||
// Clean the API request.
|
||||
$api_request = $wp->query_vars['wc-api'];
|
||||
$api_request = strtolower( wc_clean( $wp->query_vars['wc-api'] ) );
|
||||
|
||||
// Trigger generic action before request hook.
|
||||
do_action( 'woocommerce_api_request', $api_request );
|
||||
|
|
|
@ -192,7 +192,7 @@ class WC_Auth {
|
|||
$callback_url = $this->get_formatted_url( $_REQUEST['callback_url'] );
|
||||
|
||||
if ( 0 !== stripos( $callback_url, 'https://' ) ) {
|
||||
throw new Exception( __( 'The callback_url need to be over SSL', 'woocommerce' ) );
|
||||
throw new Exception( __( 'The callback_url needs to be over SSL', 'woocommerce' ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -558,15 +558,19 @@ class WC_Emails {
|
|||
'order_id' => '',
|
||||
) );
|
||||
|
||||
extract( $args );
|
||||
|
||||
if ( ! $product || ! $quantity || ! ( $order = wc_get_order( $order_id ) ) ) {
|
||||
$order = wc_get_order( $args['order_id'] );
|
||||
if (
|
||||
! $args['product'] ||
|
||||
! is_object( $args['product'] ) ||
|
||||
! $args['quantity'] ||
|
||||
! $order
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
$subject = sprintf( '[%s] %s', $this->get_blogname(), __( 'Product backorder', 'woocommerce' ) );
|
||||
$message = sprintf( __( '%1$s units of %2$s have been backordered in order #%3$s.', 'woocommerce' ), $quantity, html_entity_decode( strip_tags( $product->get_formatted_name() ), ENT_QUOTES, get_bloginfo( 'charset' ) ), $order->get_order_number() );
|
||||
|
||||
$message = sprintf( __( '%1$s units of %2$s have been backordered in order #%3$s.', 'woocommerce' ), $args['quantity'], html_entity_decode( strip_tags( $args['product']->get_formatted_name() ), ENT_QUOTES, get_bloginfo( 'charset' ) ), $order->get_order_number() );
|
||||
|
||||
wp_mail(
|
||||
apply_filters( 'woocommerce_email_recipient_backorder', get_option( 'woocommerce_stock_email_recipient' ), $args ),
|
||||
apply_filters( 'woocommerce_email_subject_backorder', $subject, $args ),
|
||||
|
|
|
@ -87,16 +87,18 @@ class WC_Order_Item_Fee extends WC_Order_Item {
|
|||
if ( 'non-taxable' === $tax_class ) {
|
||||
continue;
|
||||
}
|
||||
$proportion = $tax_class_cost / $total_costs;
|
||||
$cart_discount_proportion = $this->get_total() * $proportion;
|
||||
$discount_taxes = wc_array_merge_recursive_numeric( $discount_taxes, WC_Tax::calc_tax( $cart_discount_proportion, WC_Tax::get_rates( $tax_class ) ) );
|
||||
$proportion = $tax_class_cost / $total_costs;
|
||||
$cart_discount_proportion = $this->get_total() * $proportion;
|
||||
$calculate_tax_for['tax_class'] = $tax_class;
|
||||
$tax_rates = WC_Tax::find_rates( $calculate_tax_for );
|
||||
$discount_taxes = wc_array_merge_recursive_numeric( $discount_taxes, WC_Tax::calc_tax( $cart_discount_proportion, $tax_rates ) );
|
||||
}
|
||||
}
|
||||
$this->set_taxes( array( 'total' => $discount_taxes ) );
|
||||
} else {
|
||||
$this->set_taxes( false );
|
||||
}
|
||||
|
||||
|
||||
do_action( 'woocommerce_order_item_fee_after_calculate_taxes', $this, $calculate_tax_for );
|
||||
|
||||
return true;
|
||||
|
|
|
@ -108,6 +108,9 @@ class WC_Post_Data {
|
|||
foreach ( array_merge( $tt_ids, $old_tt_ids ) as $id ) {
|
||||
delete_transient( 'wc_ln_count_' . md5( sanitize_key( $taxonomy ) . sanitize_key( $id ) ) );
|
||||
}
|
||||
if ( in_array( get_post_type( $object_id ), array( 'product', 'product_variation' ) ) ) {
|
||||
self::delete_product_query_transients();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -180,4 +180,15 @@ class WC_Product_External extends WC_Product {
|
|||
public function add_to_cart_text() {
|
||||
return apply_filters( 'woocommerce_product_add_to_cart_text', $this->get_button_text() ? $this->get_button_text() : _x( 'Buy product', 'placeholder', 'woocommerce' ), $this );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the add to cart button text description - used in aria tags.
|
||||
*
|
||||
* @since 3.3.0
|
||||
* @return string
|
||||
*/
|
||||
public function add_to_cart_description() {
|
||||
/* translators: %s: Product title */
|
||||
return apply_filters( 'woocommerce_product_add_to_cart_description', $this->get_button_text() ? $this->get_button_text() : sprintf( __( 'Buy “%s”', 'woocommerce' ), $this->get_name() ), $this );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,6 +43,17 @@ class WC_Product_Grouped extends WC_Product {
|
|||
return apply_filters( 'woocommerce_product_add_to_cart_text', __( 'View products', 'woocommerce' ), $this );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the add to cart button text description - used in aria tags.
|
||||
*
|
||||
* @since 3.3.0
|
||||
* @return string
|
||||
*/
|
||||
public function add_to_cart_description() {
|
||||
/* translators: %s: Product title */
|
||||
return apply_filters( 'woocommerce_product_add_to_cart_description', sprintf( __( 'View products in the “%s” group', 'woocommerce' ), $this->get_name() ), $this );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not the product is on sale.
|
||||
*
|
||||
|
|
|
@ -55,4 +55,17 @@ class WC_Product_Simple extends WC_Product {
|
|||
|
||||
return apply_filters( 'woocommerce_product_add_to_cart_text', $text, $this );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the add to cart button text description - used in aria tags.
|
||||
*
|
||||
* @since 3.3.0
|
||||
* @return string
|
||||
*/
|
||||
public function add_to_cart_description() {
|
||||
/* translators: %s: Product title */
|
||||
$text = $this->is_purchasable() && $this->is_in_stock() ? __( 'Add “%s” to your cart', 'woocommerce' ) : __( 'Read more about “%s”', 'woocommerce' );
|
||||
|
||||
return apply_filters( 'woocommerce_product_add_to_cart_description', sprintf( $text, $this->get_name() ), $this );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,6 +60,17 @@ class WC_Product_Variable extends WC_Product {
|
|||
return apply_filters( 'woocommerce_product_add_to_cart_text', $this->is_purchasable() ? __( 'Select options', 'woocommerce' ) : __( 'Read more', 'woocommerce' ), $this );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the add to cart button text description - used in aria tags.
|
||||
*
|
||||
* @since 3.3.0
|
||||
* @return string
|
||||
*/
|
||||
public function add_to_cart_description() {
|
||||
/* translators: %s: Product title */
|
||||
return apply_filters( 'woocommerce_product_add_to_cart_description', sprintf( __( 'Select options for “%s”', 'woocommerce' ), $this->get_name() ), $this );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of all sale and regular prices from all variations. This is used for example when displaying the price range at variable product level or seeing if the variable product is on sale.
|
||||
*
|
||||
|
|
|
@ -50,6 +50,16 @@ class WC_Product_Variation extends WC_Product_Simple {
|
|||
'purchase_note' => '',
|
||||
);
|
||||
|
||||
/**
|
||||
* Override the default constructor to set custom defaults.
|
||||
*
|
||||
* @param int|WC_Product|object $product Product to init.
|
||||
*/
|
||||
public function __construct( $product = 0 ) {
|
||||
$this->data['tax_class'] = 'parent';
|
||||
parent::__construct( $product );
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefix for action and filter hooks on data.
|
||||
*
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
<?php
|
||||
/**
|
||||
* All functionality to regenerate images in the background when settings change.
|
||||
*
|
||||
* @category Images
|
||||
* @package WooCommerce/Classes
|
||||
* @author Automattic
|
||||
* @version 3.3.0
|
||||
* @since 3.3.0
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
/**
|
||||
* Class that extends WP_Background_Process to process image regeneration in the background
|
||||
*/
|
||||
class WC_Regenerate_Images_Request extends WP_Background_Process {
|
||||
|
||||
/**
|
||||
* Action to hook onto
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $action = 'woocommerce_regenerate_images';
|
||||
|
||||
/**
|
||||
* Fires when the job should start
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function dispatch() {
|
||||
$log = wc_get_logger();
|
||||
$log->info( __( 'Starting product image regeneration job.', 'woocommerce' ),
|
||||
array(
|
||||
'source' => 'wc-image-regeneration',
|
||||
)
|
||||
);
|
||||
parent::dispatch();
|
||||
}
|
||||
|
||||
/**
|
||||
* Code to execute for each item in the queue
|
||||
*
|
||||
* @param mixed $item Queue item to iterate over.
|
||||
* @return bool
|
||||
*/
|
||||
protected function task( $item ) {
|
||||
if ( ! is_array( $item ) && ! isset( $item['attachment_id'] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'wp_crop_image' ) ) {
|
||||
include( ABSPATH . 'wp-admin/includes/image.php' );
|
||||
}
|
||||
|
||||
$attachment_id = absint( $item['attachment_id'] );
|
||||
|
||||
$attachment = get_post( $attachment_id );
|
||||
if ( ! $attachment || 'attachment' !== $attachment->post_type || 'image/' !== substr( $attachment->post_mime_type, 0, 6 ) ) {
|
||||
return false;
|
||||
}
|
||||
$log = wc_get_logger();
|
||||
// translators: %s: ID of the attachment.
|
||||
$log->info( sprintf( __( 'Regenerating images for attachment ID: %s', 'woocommerce' ), absint( $attachment->ID ) ),
|
||||
array(
|
||||
'source' => 'wc-image-regeneration',
|
||||
)
|
||||
);
|
||||
|
||||
$fullsizepath = get_attached_file( $attachment->ID );
|
||||
|
||||
// Check if the file exists, if not just remove item from queue.
|
||||
if ( false === $fullsizepath || ! file_exists( $fullsizepath ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// This function will generate the new image sizes.
|
||||
$metadata = wp_generate_attachment_metadata( $attachment->ID, $fullsizepath );
|
||||
|
||||
// If something went wrong lets just remove the item from the queue.
|
||||
if ( is_wp_error( $metadata ) || empty( $metadata ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Update the meta data with the new size values.
|
||||
wp_update_attachment_metadata( $attachment->ID, $metadata );
|
||||
|
||||
// We made it till the end, now lets remove the item from the queue.
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This runs once the job has completed all items on the queue.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function complete() {
|
||||
parent::complete();
|
||||
$log = wc_get_logger();
|
||||
$log->info( __( 'Completed product image regeneration job.', 'woocommerce' ),
|
||||
array(
|
||||
'source' => 'wc-image-regeneration',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,210 @@
|
|||
<?php
|
||||
/**
|
||||
* Regenerate Images Functionality
|
||||
*
|
||||
* All functionality pertaining to regenerating product images in realtime.
|
||||
*
|
||||
* @category Images
|
||||
* @package WooCommerce/Classes
|
||||
* @author Automattic
|
||||
* @version 3.3.0
|
||||
* @since 3.3.0
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
/**
|
||||
* Regenerate Images Class
|
||||
*/
|
||||
class WC_Regenerate_Images {
|
||||
|
||||
/**
|
||||
* Background process to regenerate all images
|
||||
*
|
||||
* @var WC_Regenerate_Images_Request
|
||||
*/
|
||||
protected static $background_process;
|
||||
|
||||
/**
|
||||
* Init function
|
||||
*/
|
||||
public static function init() {
|
||||
include_once( WC_ABSPATH . 'includes/class-wc-regenerate-images-request.php' );
|
||||
self::$background_process = new WC_Regenerate_Images_Request();
|
||||
|
||||
if ( apply_filters( 'woocommerce_resize_images', true ) && ! is_admin() ) {
|
||||
// Action to handle on-the-fly image resizing.
|
||||
add_action( 'wp_get_attachment_image_src', array( __CLASS__, 'maybe_resize_image' ), 10, 4 );
|
||||
}
|
||||
|
||||
if ( apply_filters( 'woocommerce_background_image_regeneration', true ) ) {
|
||||
// Actions to handle image generation when settings change.
|
||||
add_action( 'update_option_woocommerce_thumbnail_cropping', array( __CLASS__, 'maybe_regenerate_images_option_update' ), 10, 3 );
|
||||
add_action( 'update_option_woocommerce_thumbnail_image_width', array( __CLASS__, 'maybe_regenerate_images_option_update' ), 10, 3 );
|
||||
add_action( 'update_option_woocommerce_single_image_width', array( __CLASS__, 'maybe_regenerate_images_option_update' ), 10, 3 );
|
||||
add_action( 'after_switch_theme', array( __CLASS__, 'maybe_regenerate_image_theme_switch' ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if we should maybe generate a new image size if not already there.
|
||||
*
|
||||
* @param array $image Properties of the image.
|
||||
* @param int $attachment_id Attachment ID.
|
||||
* @param string|array $size Image size.
|
||||
* @param bool $icon If icon or not.
|
||||
* @return array
|
||||
*/
|
||||
public static function maybe_resize_image( $image, $attachment_id, $size, $icon ) {
|
||||
$imagemeta = wp_get_attachment_metadata( $attachment_id );
|
||||
|
||||
if ( false === $imagemeta || empty( $imagemeta ) ) {
|
||||
return $image;
|
||||
}
|
||||
|
||||
$size_settings = wc_get_image_size( $size );
|
||||
|
||||
if ( isset( $imagemeta['sizes'], $imagemeta['sizes'][ $size ] ) ) {
|
||||
if ( $imagemeta['sizes'][ $size ]['width'] !== $size_settings['width'] || $imagemeta['sizes'][ $size ]['height'] !== $size_settings['height'] ) {
|
||||
$image = self::resize_and_return_image( $attachment_id, $image, $size, $icon );
|
||||
}
|
||||
} else {
|
||||
$image = self::resize_and_return_image( $attachment_id, $image, $size, $icon );
|
||||
}
|
||||
return $image;
|
||||
}
|
||||
|
||||
/**
|
||||
* Regenerate the image according to the required size
|
||||
*
|
||||
* @param int $attachment_id Attachment ID.
|
||||
* @param array $image Original Image.
|
||||
* @param string $size Size to return for new URL.
|
||||
* @param bool $icon If icon or not.
|
||||
* @return string
|
||||
*/
|
||||
private static function resize_and_return_image( $attachment_id, $image, $size, $icon ) {
|
||||
$attachment = get_post( $attachment_id );
|
||||
if ( ! $attachment || 'attachment' !== $attachment->post_type || 'image/' !== substr( $attachment->post_mime_type, 0, 6 ) ) {
|
||||
return $image;
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'wp_crop_image' ) ) {
|
||||
include( ABSPATH . 'wp-admin/includes/image.php' );
|
||||
}
|
||||
|
||||
$wp_uploads = wp_upload_dir( null, false );
|
||||
$wp_uploads_dir = $wp_uploads['basedir'];
|
||||
$wp_uploads_url = $wp_uploads['baseurl'];
|
||||
|
||||
$original_image_file_path = get_attached_file( $attachment->ID );
|
||||
|
||||
if ( ! file_exists( $original_image_file_path ) || ! getimagesize( $original_image_file_path ) ) {
|
||||
return $image;
|
||||
}
|
||||
|
||||
$info = pathinfo( $original_image_file_path );
|
||||
$ext = $info['extension'];
|
||||
list( $orig_w, $orig_h ) = getimagesize( $original_image_file_path );
|
||||
// Get image size after cropping.
|
||||
$image_size = wc_get_image_size( $size );
|
||||
$dimensions = image_resize_dimensions( $orig_w, $orig_h, $image_size['width'], $image_size['height'], $image_size['crop'] );
|
||||
if ( ! $dimensions || ! is_array( $dimensions ) ) {
|
||||
return $image;
|
||||
}
|
||||
|
||||
$dst_w = $dimensions[4];
|
||||
$dst_h = $dimensions[5];
|
||||
$suffix = "{$dst_w}x{$dst_h}";
|
||||
$dst_rel_path = str_replace( '.' . $ext, '', $original_image_file_path );
|
||||
$destfilename = "{$dst_rel_path}-{$suffix}.{$ext}";
|
||||
|
||||
// If the file is already there perhaps just load it.
|
||||
if ( file_exists( $destfilename ) ) {
|
||||
return array(
|
||||
0 => str_replace( $wp_uploads_dir, $wp_uploads_url, $destfilename ),
|
||||
1 => $image_size['width'],
|
||||
2 => $image_size['height'],
|
||||
);
|
||||
}
|
||||
|
||||
// Lets resize the image if it does not exist yet.
|
||||
$editor = wp_get_image_editor( $original_image_file_path );
|
||||
if ( is_wp_error( $editor ) || is_wp_error( $editor->resize( $image_size['width'], $image_size['height'], $image_size['crop'] ) ) ) {
|
||||
return $image;
|
||||
}
|
||||
$resized_file = $editor->save();
|
||||
if ( ! is_wp_error( $resized_file ) ) {
|
||||
$img_url = str_replace( $wp_uploads_dir, $wp_uploads_url, $resized_file['path'] );
|
||||
return array(
|
||||
0 => $img_url,
|
||||
1 => $image_size['width'],
|
||||
2 => $image_size['height'],
|
||||
);
|
||||
}
|
||||
|
||||
// Lets just add this here as a fallback.
|
||||
return $image;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if we should regenerate the product images when options change.
|
||||
*
|
||||
* @param mixed $old_value Old option value.
|
||||
* @param mixed $new_value New option value.
|
||||
* @param string $option Option name.
|
||||
*/
|
||||
public static function maybe_regenerate_images_option_update( $old_value, $new_value, $option ) {
|
||||
if ( $new_value === $old_value ) {
|
||||
return;
|
||||
}
|
||||
|
||||
self::queue_image_regeneration();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if we should generate images when new themes declares custom sizes
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function maybe_regenerate_image_theme_switch() {
|
||||
$theme_support = get_theme_support( 'woocommerce' );
|
||||
$theme_support = is_array( $theme_support ) ? $theme_support[0] : false;
|
||||
|
||||
// Only queue image generation if the theme declares custom sizes via theme_support.
|
||||
if ( is_array( $theme_support ) && ( isset( $theme_support['single_image_width'] ) || isset( $theme_support['thumbnail_image_width'] ) ) ) {
|
||||
self::queue_image_regeneration();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of images and queue them for regeneration
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private static function queue_image_regeneration() {
|
||||
global $wpdb;
|
||||
// First lets cancel existing running queue to avoid running it more than once.
|
||||
self::$background_process->cancel_process();
|
||||
|
||||
// Now lets find all product image attachments IDs and pop them onto the queue.
|
||||
$images = $wpdb->get_results( // @codingStandardsIgnoreLine
|
||||
"SELECT ID
|
||||
FROM $wpdb->posts
|
||||
WHERE post_type = 'attachment'
|
||||
AND post_mime_type LIKE 'image/%'
|
||||
ORDER BY ID DESC"
|
||||
);
|
||||
foreach ( $images as $image ) {
|
||||
self::$background_process->push_to_queue( array(
|
||||
'attachment_id' => $image->ID,
|
||||
) );
|
||||
}
|
||||
|
||||
// Lets dispatch the queue to start processing.
|
||||
self::$background_process->save()->dispatch();
|
||||
}
|
||||
}
|
||||
WC_Regenerate_Images::init();
|
|
@ -16,7 +16,6 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|||
* Main WooCommerce Class.
|
||||
*
|
||||
* @class WooCommerce
|
||||
* @version 3.3.0
|
||||
*/
|
||||
final class WooCommerce {
|
||||
|
||||
|
@ -237,13 +236,13 @@ final class WooCommerce {
|
|||
*/
|
||||
private function is_request( $type ) {
|
||||
switch ( $type ) {
|
||||
case 'admin' :
|
||||
case 'admin':
|
||||
return is_admin();
|
||||
case 'ajax' :
|
||||
case 'ajax':
|
||||
return defined( 'DOING_AJAX' );
|
||||
case 'cron' :
|
||||
case 'cron':
|
||||
return defined( 'DOING_CRON' );
|
||||
case 'frontend' :
|
||||
case 'frontend':
|
||||
return ( ! is_admin() || defined( 'DOING_AJAX' ) ) && ! defined( 'DOING_CRON' );
|
||||
}
|
||||
}
|
||||
|
@ -321,11 +320,11 @@ final class WooCommerce {
|
|||
include_once( WC_ABSPATH . 'includes/class-wc-emails.php' );
|
||||
include_once( WC_ABSPATH . 'includes/class-wc-data-exception.php' );
|
||||
include_once( WC_ABSPATH . 'includes/class-wc-query.php' );
|
||||
include_once( WC_ABSPATH . 'includes/class-wc-meta-data.php' ); // Meta data internal object
|
||||
include_once( WC_ABSPATH . 'includes/class-wc-meta-data.php' ); // Meta data internal object.
|
||||
include_once( WC_ABSPATH . 'includes/class-wc-order-factory.php' ); // Order factory.
|
||||
include_once( WC_ABSPATH . 'includes/class-wc-order-query.php' ); // Order query.
|
||||
include_once( WC_ABSPATH . 'includes/class-wc-product-factory.php' ); // Product factory.
|
||||
include_once( WC_ABSPATH . 'includes/class-wc-product-query.php' ); // Product query
|
||||
include_once( WC_ABSPATH . 'includes/class-wc-product-query.php' ); // Product query.
|
||||
include_once( WC_ABSPATH . 'includes/class-wc-payment-tokens.php' ); // Payment tokens controller.
|
||||
include_once( WC_ABSPATH . 'includes/class-wc-shipping-zone.php' );
|
||||
include_once( WC_ABSPATH . 'includes/gateways/class-wc-payment-gateway-cc.php' ); // CC Payment Gateway.
|
||||
|
@ -339,6 +338,7 @@ final class WooCommerce {
|
|||
include_once( WC_ABSPATH . 'includes/class-wc-background-emailer.php' );
|
||||
include_once( WC_ABSPATH . 'includes/class-wc-discounts.php' );
|
||||
include_once( WC_ABSPATH . 'includes/class-wc-cart-totals.php' );
|
||||
include_once( WC_ABSPATH . 'includes/class-wc-regenerate-images.php' ); // Image regeneration class.
|
||||
|
||||
/**
|
||||
* Data stores - used to store and retrieve CRUD object data from the database.
|
||||
|
@ -411,28 +411,28 @@ final class WooCommerce {
|
|||
|
||||
if ( $this->is_active_theme( array( 'twentyseventeen', 'twentysixteen', 'twentyfifteen', 'twentyfourteen', 'twentythirteen', 'twentyeleven', 'twentytwelve', 'twentyten' ) ) ) {
|
||||
switch ( get_template() ) {
|
||||
case 'twentyten' :
|
||||
case 'twentyten':
|
||||
include_once( WC_ABSPATH . 'includes/theme-support/class-wc-twenty-ten.php' );
|
||||
break;
|
||||
case 'twentyeleven' :
|
||||
case 'twentyeleven':
|
||||
include_once( WC_ABSPATH . 'includes/theme-support/class-wc-twenty-eleven.php' );
|
||||
break;
|
||||
case 'twentytwelve' :
|
||||
case 'twentytwelve':
|
||||
include_once( WC_ABSPATH . 'includes/theme-support/class-wc-twenty-twelve.php' );
|
||||
break;
|
||||
case 'twentythirteen' :
|
||||
case 'twentythirteen':
|
||||
include_once( WC_ABSPATH . 'includes/theme-support/class-wc-twenty-thirteen.php' );
|
||||
break;
|
||||
case 'twentyfourteen' :
|
||||
case 'twentyfourteen':
|
||||
include_once( WC_ABSPATH . 'includes/theme-support/class-wc-twenty-fourteen.php' );
|
||||
break;
|
||||
case 'twentyfifteen' :
|
||||
case 'twentyfifteen':
|
||||
include_once( WC_ABSPATH . 'includes/theme-support/class-wc-twenty-fifteen.php' );
|
||||
break;
|
||||
case 'twentysixteen' :
|
||||
case 'twentysixteen':
|
||||
include_once( WC_ABSPATH . 'includes/theme-support/class-wc-twenty-sixteen.php' );
|
||||
break;
|
||||
case 'twentyseventeen' :
|
||||
case 'twentyseventeen':
|
||||
include_once( WC_ABSPATH . 'includes/theme-support/class-wc-twenty-seventeen.php' );
|
||||
break;
|
||||
}
|
||||
|
@ -560,7 +560,7 @@ final class WooCommerce {
|
|||
*/
|
||||
private function add_image_sizes() {
|
||||
$thumbnail = wc_get_image_size( 'thumbnail' );
|
||||
$single = wc_get_image_size( 'single' );
|
||||
$single = wc_get_image_size( 'single' );
|
||||
|
||||
add_image_size( 'woocommerce_thumbnail', $thumbnail['width'], $thumbnail['height'], $thumbnail['crop'] );
|
||||
add_image_size( 'woocommerce_single', $single['width'], $single['height'], $single['crop'] );
|
||||
|
|
|
@ -57,6 +57,7 @@ class WC_Customer_Data_Store extends WC_Data_Store_WP implements WC_Customer_Dat
|
|||
'shipping_company',
|
||||
'wptests_capabilities',
|
||||
'wptests_user_level',
|
||||
'syntax_highlighting',
|
||||
'_order_count',
|
||||
'_money_spent',
|
||||
);
|
||||
|
|
|
@ -374,16 +374,14 @@ class WC_Product_Data_Store_CPT extends WC_Data_Store_WP implements WC_Object_Da
|
|||
/**
|
||||
* Read attributes from post meta.
|
||||
*
|
||||
* @param WC_Product
|
||||
* @since 3.0.0
|
||||
* @param WC_Product $product Product object.
|
||||
*/
|
||||
protected function read_attributes( &$product ) {
|
||||
$meta_values = get_post_meta( $product->get_id(), '_product_attributes', true );
|
||||
$meta_attributes = get_post_meta( $product->get_id(), '_product_attributes', true );
|
||||
|
||||
if ( ! empty( $meta_values ) && is_array( $meta_values ) ) {
|
||||
if ( ! empty( $meta_attributes ) && is_array( $meta_attributes ) ) {
|
||||
$attributes = array();
|
||||
foreach ( $meta_values as $meta_value ) {
|
||||
$id = 0;
|
||||
foreach ( $meta_attributes as $meta_attribute_key => $meta_attribute_value ) {
|
||||
$meta_value = array_merge( array(
|
||||
'name' => '',
|
||||
'value' => '',
|
||||
|
@ -391,7 +389,7 @@ class WC_Product_Data_Store_CPT extends WC_Data_Store_WP implements WC_Object_Da
|
|||
'is_visible' => 0,
|
||||
'is_variation' => 0,
|
||||
'is_taxonomy' => 0,
|
||||
), (array) $meta_value );
|
||||
), (array) $meta_attribute_value );
|
||||
|
||||
// Check if is a taxonomy attribute.
|
||||
if ( ! empty( $meta_value['is_taxonomy'] ) ) {
|
||||
|
@ -401,11 +399,11 @@ class WC_Product_Data_Store_CPT extends WC_Data_Store_WP implements WC_Object_Da
|
|||
$id = wc_attribute_taxonomy_id_by_name( $meta_value['name'] );
|
||||
$options = wc_get_object_terms( $product->get_id(), $meta_value['name'], 'term_id' );
|
||||
} else {
|
||||
$id = 0;
|
||||
$options = wc_get_text_attributes( $meta_value['value'] );
|
||||
}
|
||||
|
||||
$attribute = new WC_Product_Attribute();
|
||||
|
||||
$attribute->set_id( $id );
|
||||
$attribute->set_name( $meta_value['name'] );
|
||||
$attribute->set_options( $options );
|
||||
|
|
|
@ -25,6 +25,73 @@ class WC_Product_Variable_Data_Store_CPT extends WC_Product_Data_Store_CPT imple
|
|||
*/
|
||||
protected $prices_array = array();
|
||||
|
||||
/**
|
||||
* Read attributes from post meta.
|
||||
*
|
||||
* @param WC_Product $product Product object.
|
||||
*/
|
||||
protected function read_attributes( &$product ) {
|
||||
$meta_attributes = get_post_meta( $product->get_id(), '_product_attributes', true );
|
||||
|
||||
if ( ! empty( $meta_attributes ) && is_array( $meta_attributes ) ) {
|
||||
$attributes = array();
|
||||
$force_update = false;
|
||||
foreach ( $meta_attributes as $meta_attribute_key => $meta_attribute_value ) {
|
||||
$meta_value = array_merge( array(
|
||||
'name' => '',
|
||||
'value' => '',
|
||||
'position' => 0,
|
||||
'is_visible' => 0,
|
||||
'is_variation' => 0,
|
||||
'is_taxonomy' => 0,
|
||||
), (array) $meta_attribute_value );
|
||||
|
||||
// Maintain data integrity. 4.9 changed sanitization functions - update the values here so variations function correctly.
|
||||
if ( $meta_value['is_variation'] && strstr( $meta_value['name'], '/' ) && sanitize_title( $meta_value['name'] ) !== $meta_attribute_key ) {
|
||||
global $wpdb;
|
||||
|
||||
$old_slug = 'attribute_' . $meta_attribute_key;
|
||||
$new_slug = 'attribute_' . sanitize_title( $meta_value['name'] );
|
||||
$old_meta_rows = $wpdb->get_results( $wpdb->prepare( "SELECT post_id, meta_value FROM {$wpdb->postmeta} WHERE meta_key = %s;", $old_slug ) ); // WPCS: db call ok, cache ok.
|
||||
|
||||
if ( $old_meta_rows ) {
|
||||
foreach ( $old_meta_rows as $old_meta_row ) {
|
||||
update_post_meta( $old_meta_row->post_id, $new_slug, $old_meta_row->meta_value );
|
||||
}
|
||||
}
|
||||
|
||||
$force_update = true;
|
||||
}
|
||||
|
||||
// Check if is a taxonomy attribute.
|
||||
if ( ! empty( $meta_value['is_taxonomy'] ) ) {
|
||||
if ( ! taxonomy_exists( $meta_value['name'] ) ) {
|
||||
continue;
|
||||
}
|
||||
$id = wc_attribute_taxonomy_id_by_name( $meta_value['name'] );
|
||||
$options = wc_get_object_terms( $product->get_id(), $meta_value['name'], 'term_id' );
|
||||
} else {
|
||||
$id = 0;
|
||||
$options = wc_get_text_attributes( $meta_value['value'] );
|
||||
}
|
||||
|
||||
$attribute = new WC_Product_Attribute();
|
||||
$attribute->set_id( $id );
|
||||
$attribute->set_name( $meta_value['name'] );
|
||||
$attribute->set_options( $options );
|
||||
$attribute->set_position( $meta_value['position'] );
|
||||
$attribute->set_visible( $meta_value['is_visible'] );
|
||||
$attribute->set_variation( $meta_value['is_variation'] );
|
||||
$attributes[] = $attribute;
|
||||
}
|
||||
$product->set_attributes( $attributes );
|
||||
|
||||
if ( $force_update ) {
|
||||
$this->update_attributes( $product, true );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read product data.
|
||||
*
|
||||
|
@ -63,9 +130,12 @@ class WC_Product_Variable_Data_Store_CPT extends WC_Product_Data_Store_CPT imple
|
|||
'post_type' => 'product_variation',
|
||||
'orderby' => array( 'menu_order' => 'ASC', 'ID' => 'ASC' ),
|
||||
'fields' => 'ids',
|
||||
'post_status' => 'publish',
|
||||
'post_status' => array( 'publish', 'private' ),
|
||||
'numberposts' => -1,
|
||||
);
|
||||
|
||||
$visible_only_args['post_status'] = 'publish';
|
||||
|
||||
if ( 'yes' === get_option( 'woocommerce_hide_out_of_stock_items' ) ) {
|
||||
$visible_only_args['tax_query'][] = array(
|
||||
'taxonomy' => 'product_visibility',
|
||||
|
|
|
@ -125,6 +125,15 @@ abstract class WC_Product_Importer implements WC_Importer_Interface {
|
|||
return apply_filters( 'woocommerce_product_importer_parsed_data', $this->parsed_data, $this->get_raw_data() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get importer parameters.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_params() {
|
||||
return $this->params;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get file pointer position from the last read.
|
||||
*
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* @author Automattic
|
||||
* @category Shortcodes
|
||||
* @package WooCommerce/Shortcodes
|
||||
* @version 3.2.0
|
||||
* @version 3.2.4
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
|
@ -195,7 +195,12 @@ class WC_Shortcode_Products {
|
|||
// Categories.
|
||||
$this->set_categories_query_args( $query_args );
|
||||
|
||||
return apply_filters( 'woocommerce_shortcode_products_query', $query_args, $this->attributes, $this->type );
|
||||
$query_args = apply_filters( 'woocommerce_shortcode_products_query', $query_args, $this->attributes, $this->type );
|
||||
|
||||
// Always query only IDs.
|
||||
$query_args['fields'] = 'ids';
|
||||
|
||||
return $query_args;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -450,16 +455,16 @@ class WC_Shortcode_Products {
|
|||
}
|
||||
|
||||
/**
|
||||
* Get products.
|
||||
* Get products IDs.
|
||||
*
|
||||
* @since 3.2.0
|
||||
* @return WP_Query
|
||||
* @since 3.2.4
|
||||
* @return array
|
||||
*/
|
||||
protected function get_products() {
|
||||
protected function get_products_ids() {
|
||||
$transient_name = $this->get_transient_name();
|
||||
$products = get_transient( $transient_name );
|
||||
$ids = get_transient( $transient_name );
|
||||
|
||||
if ( false === $products || ! is_a( $products, 'WP_Query' ) ) {
|
||||
if ( false === $ids ) {
|
||||
if ( 'top_rated_products' === $this->type ) {
|
||||
add_filter( 'posts_clauses', array( __CLASS__, 'order_by_rating_post_clauses' ) );
|
||||
$products = new WP_Query( $this->query_args );
|
||||
|
@ -468,7 +473,9 @@ class WC_Shortcode_Products {
|
|||
$products = new WP_Query( $this->query_args );
|
||||
}
|
||||
|
||||
set_transient( $transient_name, $products, DAY_IN_SECONDS * 30 );
|
||||
$ids = wp_parse_id_list( $products->posts );
|
||||
|
||||
set_transient( $transient_name, $ids, DAY_IN_SECONDS * 30 );
|
||||
}
|
||||
|
||||
// Remove ordering query arguments.
|
||||
|
@ -476,7 +483,7 @@ class WC_Shortcode_Products {
|
|||
WC()->query->remove_ordering_args();
|
||||
}
|
||||
|
||||
return $products;
|
||||
return $ids;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -492,20 +499,25 @@ class WC_Shortcode_Products {
|
|||
$classes = $this->get_wrapper_classes( $columns );
|
||||
$woocommerce_loop['columns'] = $columns;
|
||||
$woocommerce_loop['name'] = $this->type;
|
||||
$products = $this->get_products();
|
||||
$products_ids = $this->get_products_ids();
|
||||
|
||||
ob_start();
|
||||
|
||||
if ( $products->have_posts() ) {
|
||||
// Prime caches before grabbing objects.
|
||||
update_post_caches( $products->posts, array( 'product', 'product_variation' ) );
|
||||
if ( $products_ids ) {
|
||||
// Prime meta cache to reduce future queries.
|
||||
update_meta_cache( 'post', $products_ids );
|
||||
update_object_term_cache( $products_ids, 'product' );
|
||||
|
||||
$original_post = $GLOBALS['post'];
|
||||
|
||||
do_action( "woocommerce_shortcode_before_{$this->type}_loop", $this->attributes );
|
||||
|
||||
woocommerce_product_loop_start();
|
||||
|
||||
while ( $products->have_posts() ) {
|
||||
$products->the_post();
|
||||
foreach ( $products_ids as $product_id ) {
|
||||
$post_object = get_post( $product_id );
|
||||
$GLOBALS['post'] =& $post_object; // WPCS: override ok.
|
||||
setup_postdata( $post_object );
|
||||
|
||||
// Set custom product visibility when quering hidden products.
|
||||
add_action( 'woocommerce_product_is_visible', array( $this, 'set_product_as_visible' ) );
|
||||
|
@ -517,15 +529,17 @@ class WC_Shortcode_Products {
|
|||
remove_action( 'woocommerce_product_is_visible', array( $this, 'set_product_as_visible' ) );
|
||||
}
|
||||
|
||||
$GLOBALS['post'] = $original_post; // WPCS: override ok.
|
||||
woocommerce_product_loop_end();
|
||||
|
||||
do_action( "woocommerce_shortcode_after_{$this->type}_loop", $this->attributes );
|
||||
|
||||
wp_reset_postdata();
|
||||
} else {
|
||||
do_action( "woocommerce_shortcode_{$this->type}_loop_no_results", $this->attributes );
|
||||
}
|
||||
|
||||
woocommerce_reset_loop();
|
||||
wp_reset_postdata();
|
||||
|
||||
return '<div class="' . esc_attr( implode( ' ', $classes ) ) . '">' . ob_get_clean() . '</div>';
|
||||
}
|
||||
|
|
|
@ -686,7 +686,7 @@ function wc_get_image_size( $image_size ) {
|
|||
'crop' => isset( $image_size[2] ) ? $image_size[2] : 1,
|
||||
);
|
||||
$image_size = $size['width'] . '_' . $size['height'];
|
||||
} elseif ( in_array( $image_size, array( 'single', 'shop_single' ), true ) ) {
|
||||
} elseif ( in_array( $image_size, array( 'single', 'shop_single', 'woocommerce_single' ), true ) ) {
|
||||
// If the theme supports woocommerce, take image sizes from that definition.
|
||||
if ( isset( $theme_support[ 'single_image_width' ] ) ) {
|
||||
$size['width'] = $theme_support[ 'single_image_width' ];
|
||||
|
@ -696,7 +696,7 @@ function wc_get_image_size( $image_size ) {
|
|||
$size['height'] = 9999999999;
|
||||
$size['crop'] = 0;
|
||||
$image_size = 'single';
|
||||
} elseif ( in_array( $image_size, array( 'thumbnail', 'shop_thumbnail', 'shop_catalog' ), true ) ) {
|
||||
} elseif ( in_array( $image_size, array( 'thumbnail', 'shop_thumbnail', 'shop_catalog', 'woocommerce_thumbnail' ), true ) ) {
|
||||
// If the theme supports woocommerce, take image sizes from that definition.
|
||||
if ( isset( $theme_support[ 'thumbnail_image_width' ] ) ) {
|
||||
$size['width'] = $theme_support[ 'thumbnail_image_width' ];
|
||||
|
|
|
@ -412,7 +412,7 @@ function wc_query_string_form_fields( $values = null, $exclude = array(), $curre
|
|||
if ( is_array( $value ) ) {
|
||||
$html .= wc_query_string_form_fields( $value, $exclude, $key, true );
|
||||
} else {
|
||||
$html .= '<input type="hidden" name="' . esc_attr( $key ) . '" value="' . esc_attr( $value ) . '" />';
|
||||
$html .= '<input type="hidden" name="' . esc_attr( $key ) . '" value="' . esc_attr( wp_unslash( $value ) ) . '" />';
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -72,7 +72,7 @@ class WC_Widget_Layered_Nav_Filters extends WC_Widget {
|
|||
* To support quote characters, first they are decoded from " entities, then URL encoded.
|
||||
*/
|
||||
if ( get_search_query() ) {
|
||||
$link = add_query_arg( 's', rawurlencode( htmlspecialchars_decode( get_search_query() ) ), $link );
|
||||
$link = add_query_arg( 's', rawurlencode( htmlspecialchars_decode( get_search_query( false ) ) ), $link );
|
||||
}
|
||||
|
||||
// Post Type Arg
|
||||
|
|
|
@ -356,7 +356,7 @@ class WC_Widget_Layered_Nav extends WC_Widget {
|
|||
* To support quote characters, first they are decoded from " entities, then URL encoded.
|
||||
*/
|
||||
if ( get_search_query() ) {
|
||||
$link = add_query_arg( 's', rawurlencode( htmlspecialchars_decode( get_search_query() ) ), $link );
|
||||
$link = add_query_arg( 's', rawurlencode( htmlspecialchars_decode( get_search_query( false ) ) ), $link );
|
||||
}
|
||||
|
||||
// Post Type Arg.
|
||||
|
|
23
package.json
23
package.json
|
@ -15,7 +15,7 @@
|
|||
"test:single": "cross-env NODE_CONFIG_DIR='./tests/e2e-tests/config' BABEL_ENV=commonjs mocha --compilers js:babel-register"
|
||||
},
|
||||
"devDependencies": {
|
||||
"autoprefixer": "^6.7.7",
|
||||
"autoprefixer": "~7.1.6",
|
||||
"babel": "^6.5.2",
|
||||
"babel-cli": "^6.14.0",
|
||||
"babel-eslint": "^7.0.0",
|
||||
|
@ -26,24 +26,25 @@
|
|||
"chai-as-promised": "^6.0.0",
|
||||
"chromedriver": "^2.33.0",
|
||||
"config": "^1.24.0",
|
||||
"cross-env": "^3.0.0",
|
||||
"cross-env": "~5.1.1",
|
||||
"grunt": "~1.0.1",
|
||||
"grunt-checktextdomain": "~1.0.0",
|
||||
"grunt-contrib-clean": "~1.0.0",
|
||||
"grunt-contrib-concat": "1.0.1",
|
||||
"grunt-contrib-cssmin": "~2.2.0",
|
||||
"grunt-checktextdomain": "~1.0.1",
|
||||
"grunt-contrib-clean": "~1.1.0",
|
||||
"grunt-contrib-concat": "~1.0.1",
|
||||
"grunt-contrib-cssmin": "~2.2.1",
|
||||
"grunt-contrib-jshint": "~1.1.0",
|
||||
"grunt-contrib-uglify": "~3.0.0",
|
||||
"grunt-contrib-uglify": "~3.1.0",
|
||||
"grunt-contrib-watch": "~1.0.0",
|
||||
"grunt-phpcs": "~0.4.0",
|
||||
"grunt-postcss": "~0.8.0",
|
||||
"grunt-postcss": "~0.9.0",
|
||||
"grunt-rtlcss": "~2.0.1",
|
||||
"grunt-shell": "~2.1.0",
|
||||
"grunt-sass": "~2.0.0",
|
||||
"grunt-stylelint": "~0.8.0",
|
||||
"grunt-wp-i18n": "~1.0.0",
|
||||
"grunt-shell": "~2.1.0",
|
||||
"grunt-stylelint": "~0.9.0",
|
||||
"grunt-wp-i18n": "~1.0.1",
|
||||
"istanbul": "^1.0.0-alpha",
|
||||
"mocha": "^3.0.2",
|
||||
"stylelint": "~8.2.0",
|
||||
"wc-e2e-page-objects": "0.4.0"
|
||||
},
|
||||
"engines": {
|
||||
|
|
|
@ -10,10 +10,10 @@
|
|||
* happen. When this occurs the version of the template file will be bumped and
|
||||
* the readme will list any important changes.
|
||||
*
|
||||
* @see https://docs.woocommerce.com/document/template-structure/
|
||||
* @author WooThemes
|
||||
* @package WooCommerce/Templates/Emails
|
||||
* @version 2.5.0
|
||||
* @see https://docs.woocommerce.com/document/template-structure/
|
||||
* @author WooThemes
|
||||
* @package WooCommerce/Templates/Emails
|
||||
* @version 3.3.0
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
|
@ -21,17 +21,37 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Executes the e-mail header.
|
||||
*
|
||||
* @hooked WC_Emails::email_header() Output the email header
|
||||
*/
|
||||
do_action( 'woocommerce_email_header', $email_heading, $email ); ?>
|
||||
|
||||
<?php if ( $order->has_status( 'pending' ) ) : ?>
|
||||
<p><?php printf( __( 'An order has been created for you on %1$s. To pay for this order please use the following link: %2$s', 'woocommerce' ), get_bloginfo( 'name', 'display' ), '<a href="' . esc_url( $order->get_checkout_payment_url() ) . '">' . __( 'pay', 'woocommerce' ) . '</a>' ); ?></p>
|
||||
<p>
|
||||
<?php
|
||||
printf(
|
||||
wp_kses(
|
||||
/* translators: %1s item is the name of the site, %2s is a html link */
|
||||
__( 'An order has been created for you on %1$s. To pay for this order please use the following link: %2$s', 'woocommerce' ),
|
||||
array(
|
||||
'a' => array(
|
||||
'href' => array(),
|
||||
),
|
||||
)
|
||||
),
|
||||
esc_html( get_bloginfo( 'name', 'display' ) ),
|
||||
'<a href="' . esc_url( $order->get_checkout_payment_url() ) . '">' . esc_html__( 'Submit payment online.', 'woocommerce' ) . '</a>'
|
||||
);
|
||||
?>
|
||||
</p>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Hook for the woocommerce_email_order_details
|
||||
*
|
||||
* @hooked WC_Emails::order_details() Shows the order details table.
|
||||
* @hooked WC_Structured_Data::generate_order_data() Generates structured data.
|
||||
* @hooked WC_Structured_Data::output_structured_data() Outputs structured data.
|
||||
|
@ -40,17 +60,23 @@ do_action( 'woocommerce_email_header', $email_heading, $email ); ?>
|
|||
do_action( 'woocommerce_email_order_details', $order, $sent_to_admin, $plain_text, $email );
|
||||
|
||||
/**
|
||||
* Hook for the woocommerce_email_order_meta
|
||||
*
|
||||
* @hooked WC_Emails::order_meta() Shows order meta data.
|
||||
*/
|
||||
do_action( 'woocommerce_email_order_meta', $order, $sent_to_admin, $plain_text, $email );
|
||||
|
||||
/**
|
||||
* Hook for woocommerce_email_customer_details
|
||||
*
|
||||
* @hooked WC_Emails::customer_details() Shows customer details
|
||||
* @hooked WC_Emails::email_address() Shows email address
|
||||
*/
|
||||
do_action( 'woocommerce_email_customer_details', $order, $sent_to_admin, $plain_text, $email );
|
||||
|
||||
/**
|
||||
* Executes the email footer
|
||||
*
|
||||
* @hooked WC_Emails::email_footer() Output the email footer
|
||||
*/
|
||||
do_action( 'woocommerce_email_footer', $email );
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
* @see https://docs.woocommerce.com/document/template-structure/
|
||||
* @author WooThemes
|
||||
* @package WooCommerce/Templates
|
||||
* @version 3.0.0
|
||||
* @version 3.3.0
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
|
@ -22,13 +22,14 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|||
|
||||
global $product;
|
||||
|
||||
echo apply_filters( 'woocommerce_loop_add_to_cart_link',
|
||||
sprintf( '<a rel="nofollow" href="%s" data-quantity="%s" data-product_id="%s" data-product_sku="%s" class="%s">%s</a>',
|
||||
echo apply_filters( 'woocommerce_loop_add_to_cart_link', // WPCS: XSS ok.
|
||||
sprintf( '<a rel="nofollow" href="%s" data-quantity="%s" data-product_id="%s" data-product_sku="%s" class="%s" aria-label="%s">%s</a>',
|
||||
esc_url( $product->add_to_cart_url() ),
|
||||
esc_attr( isset( $quantity ) ? $quantity : 1 ),
|
||||
esc_attr( $product->get_id() ),
|
||||
esc_attr( $product->get_sku() ),
|
||||
esc_attr( isset( $class ) ? $class : 'button' ),
|
||||
esc_attr( $product->add_to_cart_description() ),
|
||||
esc_html( $product->add_to_cart_text() )
|
||||
),
|
||||
$product );
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
* @see https://docs.woocommerce.com/document/template-structure/
|
||||
* @author WooThemes
|
||||
* @package WooCommerce/Templates
|
||||
* @version 3.2.0
|
||||
* @version 3.3.0
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
|
@ -25,7 +25,7 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|||
<h2 class="woocommerce-order-downloads__title"><?php _e( 'Downloads', 'woocommerce' ); ?></h2>
|
||||
<?php endif; ?>
|
||||
|
||||
<table class="woocommerce-table woocommerce-table--order-downloads shop_table order_details">
|
||||
<table class="woocommerce-table woocommerce-table--order-downloads shop_table shop_table_responsive order_details">
|
||||
<thead>
|
||||
<tr>
|
||||
<?php foreach ( wc_get_account_downloads_columns() as $column_id => $column_name ) : ?>
|
||||
|
|
|
@ -171,7 +171,7 @@ class WC_Tests_API_Orders extends WC_REST_Unit_Test_Case {
|
|||
array(
|
||||
'method_id' => 'flat_rate',
|
||||
'method_title' => 'Flat rate',
|
||||
'total' => 10,
|
||||
'total' => '10',
|
||||
),
|
||||
),
|
||||
) );
|
||||
|
|
|
@ -75,6 +75,8 @@ class Product_Reviews extends WC_REST_Unit_Test_Case {
|
|||
),
|
||||
),
|
||||
), $product_reviews );
|
||||
|
||||
$product->delete( true );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -87,6 +89,7 @@ class Product_Reviews extends WC_REST_Unit_Test_Case {
|
|||
$product = WC_Helper_Product::create_simple_product();
|
||||
$response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v2/products/' . $product->get_id() . '/reviews' ) );
|
||||
$this->assertEquals( 401, $response->get_status() );
|
||||
$product->delete( true );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -124,6 +127,7 @@ class Product_Reviews extends WC_REST_Unit_Test_Case {
|
|||
'email' => 'woo@woo.local',
|
||||
'verified' => false,
|
||||
), $data );
|
||||
$product->delete( true );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -137,6 +141,7 @@ class Product_Reviews extends WC_REST_Unit_Test_Case {
|
|||
$product_review_id = WC_Helper_Product::create_product_review( $product->get_id() );
|
||||
$response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v2/products/' . $product->get_id() . '/reviews/' . $product_review_id ) );
|
||||
$this->assertEquals( 401, $response->get_status() );
|
||||
$product->delete( true );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -149,6 +154,7 @@ class Product_Reviews extends WC_REST_Unit_Test_Case {
|
|||
$product = WC_Helper_Product::create_simple_product();
|
||||
$response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v2/products/' . $product->get_id() . '/reviews/0' ) );
|
||||
$this->assertEquals( 404, $response->get_status() );
|
||||
$product->delete( true );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -180,6 +186,7 @@ class Product_Reviews extends WC_REST_Unit_Test_Case {
|
|||
'email' => 'woo@woo.local',
|
||||
'verified' => false,
|
||||
), $data );
|
||||
$product->delete( true );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -223,6 +230,7 @@ class Product_Reviews extends WC_REST_Unit_Test_Case {
|
|||
$data = $response->get_data();
|
||||
|
||||
$this->assertEquals( 400, $response->get_status() );
|
||||
$product->delete( true );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -255,6 +263,7 @@ class Product_Reviews extends WC_REST_Unit_Test_Case {
|
|||
$this->assertEquals( 'Justin', $data['name'] );
|
||||
$this->assertEquals( 'woo2@woo.local', $data['email'] );
|
||||
$this->assertEquals( 3, $data['rating'] );
|
||||
$product->delete( true );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -277,6 +286,7 @@ class Product_Reviews extends WC_REST_Unit_Test_Case {
|
|||
$data = $response->get_data();
|
||||
|
||||
$this->assertEquals( 401, $response->get_status() );
|
||||
$product->delete( true );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -298,6 +308,7 @@ class Product_Reviews extends WC_REST_Unit_Test_Case {
|
|||
$data = $response->get_data();
|
||||
|
||||
$this->assertEquals( 404, $response->get_status() );
|
||||
$product->delete( true );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -314,6 +325,7 @@ class Product_Reviews extends WC_REST_Unit_Test_Case {
|
|||
$request->set_param( 'force', true );
|
||||
$response = $this->server->dispatch( $request );
|
||||
$this->assertEquals( 200, $response->get_status() );
|
||||
$product->delete( true );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -330,6 +342,7 @@ class Product_Reviews extends WC_REST_Unit_Test_Case {
|
|||
$response = $this->server->dispatch( $request );
|
||||
|
||||
$this->assertEquals( 401, $response->get_status() );
|
||||
$product->delete( true );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -347,6 +360,7 @@ class Product_Reviews extends WC_REST_Unit_Test_Case {
|
|||
$response = $this->server->dispatch( $request );
|
||||
|
||||
$this->assertEquals( 404, $response->get_status() );
|
||||
$product->delete( true );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -394,6 +408,7 @@ class Product_Reviews extends WC_REST_Unit_Test_Case {
|
|||
$data = $response->get_data();
|
||||
|
||||
$this->assertEquals( 3, count( $data ) );
|
||||
$product->delete( true );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -418,5 +433,6 @@ class Product_Reviews extends WC_REST_Unit_Test_Case {
|
|||
$this->assertArrayHasKey( 'name', $properties );
|
||||
$this->assertArrayHasKey( 'email', $properties );
|
||||
$this->assertArrayHasKey( 'verified', $properties );
|
||||
$product->delete( true );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,6 +51,11 @@ class Products_API extends WC_REST_Unit_Test_Case {
|
|||
$this->assertEquals( 'DUMMY SKU', $products[0]['sku'] );
|
||||
$this->assertEquals( 'Dummy External Product', $products[1]['name'] );
|
||||
$this->assertEquals( 'DUMMY EXTERNAL SKU', $products[1]['sku'] );
|
||||
|
||||
foreach ( $products as $key => $value ) {
|
||||
$product = wc_get_product( $value['id'] );
|
||||
$product->delete( true );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -63,6 +68,13 @@ class Products_API extends WC_REST_Unit_Test_Case {
|
|||
WC_Helper_Product::create_simple_product();
|
||||
$response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v2/products' ) );
|
||||
$this->assertEquals( 401, $response->get_status() );
|
||||
|
||||
// Remove product.
|
||||
wp_set_current_user( $this->user );
|
||||
$response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v2/products' ) );
|
||||
$products = $response->get_data();
|
||||
$product = wc_get_product( $products[0]['id'] );
|
||||
$product->delete( true );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -85,6 +97,7 @@ class Products_API extends WC_REST_Unit_Test_Case {
|
|||
'sku' => 'DUMMY EXTERNAL SKU',
|
||||
'regular_price' => 10,
|
||||
), $product );
|
||||
$simple->delete( true );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -97,6 +110,7 @@ class Products_API extends WC_REST_Unit_Test_Case {
|
|||
$product = WC_Helper_Product::create_simple_product();
|
||||
$response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v2/products/' . $product->get_id() ) );
|
||||
$this->assertEquals( 401, $response->get_status() );
|
||||
$product->delete( true );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -116,6 +130,7 @@ class Products_API extends WC_REST_Unit_Test_Case {
|
|||
$response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v2/products' ) );
|
||||
$variations = $response->get_data();
|
||||
$this->assertEquals( 0, count( $variations ) );
|
||||
$product->delete( true );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -130,6 +145,7 @@ class Products_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 );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -179,6 +195,7 @@ class Products_API extends WC_REST_Unit_Test_Case {
|
|||
$this->assertEquals( 'FIXED-SKU', $data['sku'] );
|
||||
$this->assertContains( 'Dr1Bczxq4q', $data['images'][0]['src'] );
|
||||
$this->assertContains( 'test upload image', $data['images'][0]['alt'] );
|
||||
$product->delete( true );
|
||||
|
||||
// test variable product (variations are tested in product-variations.php)
|
||||
$product = WC_Helper_Product::create_variation_product();
|
||||
|
@ -463,6 +480,11 @@ class Products_API extends WC_REST_Unit_Test_Case {
|
|||
$products = $response->get_data();
|
||||
|
||||
$this->assertEquals( 8, count( $products ) );
|
||||
|
||||
foreach ( $products as $key => $value ) {
|
||||
$product = wc_get_product( $value['id'] );
|
||||
$product->delete( true );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -137,6 +137,7 @@ class WC_Tests_Discounts extends WC_Unit_Test_Case {
|
|||
$discounts = new WC_Discounts();
|
||||
$discounts->set_items_from_cart( false );
|
||||
$this->assertEquals( array(), $discounts->get_items() );
|
||||
$product->delete( true );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -173,6 +174,7 @@ class WC_Tests_Discounts extends WC_Unit_Test_Case {
|
|||
$discounts->set_items_from_cart( WC()->cart );
|
||||
$discounts->apply_coupon( $coupon );
|
||||
$this->assertEquals( 0, $discounts->get_discounted_price( current( $discounts->get_items() ) ), print_r( $discounts->get_discounts(), true ) );
|
||||
$product->delete( true );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -185,6 +187,7 @@ class WC_Tests_Discounts extends WC_Unit_Test_Case {
|
|||
public function test_calculations( $test_data ) {
|
||||
$this->last_test_data = $test_data;
|
||||
$discounts = new WC_Discounts();
|
||||
$products = array();
|
||||
|
||||
if ( isset( $test_data['tax_rate'] ) ) {
|
||||
WC_Tax::_insert_tax_rate( $test_data['tax_rate'] );
|
||||
|
@ -196,13 +199,13 @@ class WC_Tests_Discounts extends WC_Unit_Test_Case {
|
|||
}
|
||||
}
|
||||
|
||||
foreach ( $test_data['cart'] as $item ) {
|
||||
$product = WC_Helper_Product::create_simple_product();
|
||||
$product->set_regular_price( $item['price'] );
|
||||
$product->set_tax_status( 'taxable' );
|
||||
$product->save();
|
||||
$this->store_product( $product );
|
||||
WC()->cart->add_to_cart( $product->get_id(), $item['qty'] );
|
||||
foreach ( $test_data['cart'] as $key => $item ) {
|
||||
$products[ $key ] = WC_Helper_Product::create_simple_product();
|
||||
$products[ $key ]->set_regular_price( $item['price'] );
|
||||
$products[ $key ]->set_tax_status( 'taxable' );
|
||||
$products[ $key ]->save();
|
||||
$this->store_product( $products[ $key ] );
|
||||
WC()->cart->add_to_cart( $products[ $key ]->get_id(), $item['qty'] );
|
||||
}
|
||||
|
||||
$discounts->set_items_from_cart( WC()->cart );
|
||||
|
@ -222,6 +225,10 @@ class WC_Tests_Discounts extends WC_Unit_Test_Case {
|
|||
}
|
||||
|
||||
$this->assertEquals( $test_data['expected_total_discount'], $discount_total, 'Failed (' . print_r( $test_data, true ) . ' - ' . print_r( $discounts->get_discounts(), true ) . ')' );
|
||||
|
||||
foreach ( $products as $product ) {
|
||||
$product->delete( true );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -880,7 +880,7 @@ class WC_Tests_Formatting_Functions extends WC_Unit_Test_Case {
|
|||
*/
|
||||
public function test_wc_do_oembeds() {
|
||||
// In this case should only return the URL back, since oEmbed will run other actions on frontend.
|
||||
$this->assertEquals( 'https://wordpress.tv/2015/10/19/mike-jolley-user-onboarding-for-wordpress-plugins/', wc_do_oembeds( 'https://wordpress.tv/2015/10/19/mike-jolley-user-onboarding-for-wordpress-plugins/' ) );
|
||||
$this->assertEquals( "<iframe width='500' height='281' src='https://videopress.com/embed/9sRCUigm?hd=0' frameborder='0' allowfullscreen></iframe><script src='https://v0.wordpress.com/js/next/videopress-iframe.js?m=1435166243'></script>", wc_do_oembeds( 'https://wordpress.tv/2015/10/19/mike-jolley-user-onboarding-for-wordpress-plugins/' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -11,7 +11,7 @@ class WC_Tests_Product_CSV_Importer extends WC_Unit_Test_Case {
|
|||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $csv_file = string;
|
||||
protected $csv_file = '';
|
||||
|
||||
/**
|
||||
* Load up the importer classes since they aren't loaded by default.
|
||||
|
|
|
@ -73,10 +73,11 @@ class WC_Tests_Product_Data extends WC_Unit_Test_Case {
|
|||
$this->assertEquals( $product->get_date_on_sale_to()->getTimestamp(), 1477267200 );
|
||||
|
||||
$image_url = media_sideload_image( "https://cldup.com/Dr1Bczxq4q.png", $product->get_id(), '', 'src' );
|
||||
$image_id = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE guid='%s';", $image_url ) );
|
||||
$image_id = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM {$wpdb->posts} WHERE guid='%s';", $image_url ) );
|
||||
$product->set_image_id( $image_id[0] );
|
||||
$product->save();
|
||||
$this->assertEquals( $image_id[0], $product->get_image_id() );
|
||||
$product->delete( true );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -70,6 +70,7 @@ class WC_Test_Shortcode_Products extends WC_Unit_Test_Case {
|
|||
'posts_per_page' => -1,
|
||||
'meta_query' => $meta_query,
|
||||
'tax_query' => $tax_query,
|
||||
'fields' => 'ids',
|
||||
);
|
||||
$this->assertEquals( $expected, $shortcode->get_query_args() );
|
||||
|
||||
|
@ -88,6 +89,7 @@ class WC_Test_Shortcode_Products extends WC_Unit_Test_Case {
|
|||
'posts_per_page' => -1,
|
||||
'meta_query' => $meta_query,
|
||||
'tax_query' => $tax_query,
|
||||
'fields' => 'ids',
|
||||
);
|
||||
$this->assertEquals( $expected2, $shortcode2->get_query_args() );
|
||||
|
||||
|
@ -106,6 +108,7 @@ class WC_Test_Shortcode_Products extends WC_Unit_Test_Case {
|
|||
'meta_query' => $meta_query,
|
||||
'tax_query' => $tax_query,
|
||||
'post__in' => array( '1', '2', '3' ),
|
||||
'fields' => 'ids',
|
||||
);
|
||||
$expected3['meta_query'][] = array(
|
||||
'key' => '_sku',
|
||||
|
@ -135,6 +138,7 @@ class WC_Test_Shortcode_Products extends WC_Unit_Test_Case {
|
|||
'meta_query' => $meta_query,
|
||||
'tax_query' => $tax_query,
|
||||
'meta_key' => '',
|
||||
'fields' => 'ids',
|
||||
);
|
||||
$expected4['tax_query'][] = array(
|
||||
'taxonomy' => 'product_cat',
|
||||
|
@ -164,6 +168,7 @@ class WC_Test_Shortcode_Products extends WC_Unit_Test_Case {
|
|||
'posts_per_page' => 12,
|
||||
'meta_query' => $meta_query,
|
||||
'tax_query' => $tax_query,
|
||||
'fields' => 'ids',
|
||||
);
|
||||
|
||||
$this->assertEquals( $expected5, $shortcode5->get_query_args() );
|
||||
|
@ -184,6 +189,7 @@ class WC_Test_Shortcode_Products extends WC_Unit_Test_Case {
|
|||
'meta_query' => $meta_query,
|
||||
'tax_query' => $tax_query,
|
||||
'p' => '1',
|
||||
'fields' => 'ids',
|
||||
);
|
||||
|
||||
$this->assertEquals( $expected6, $shortcode6->get_query_args() );
|
||||
|
@ -208,6 +214,7 @@ class WC_Test_Shortcode_Products extends WC_Unit_Test_Case {
|
|||
'meta_query' => $meta_query,
|
||||
'tax_query' => $tax_query,
|
||||
'post__in' => array_merge( array( 0 ), wc_get_product_ids_on_sale() ),
|
||||
'fields' => 'ids',
|
||||
);
|
||||
|
||||
$this->assertEquals( $expected7, $shortcode7->get_query_args() );
|
||||
|
@ -230,6 +237,7 @@ class WC_Test_Shortcode_Products extends WC_Unit_Test_Case {
|
|||
'meta_query' => $meta_query,
|
||||
'tax_query' => $tax_query,
|
||||
'meta_key' => 'total_sales',
|
||||
'fields' => 'ids',
|
||||
);
|
||||
|
||||
$this->assertEquals( $expected8, $shortcode8->get_query_args() );
|
||||
|
@ -253,6 +261,7 @@ class WC_Test_Shortcode_Products extends WC_Unit_Test_Case {
|
|||
'posts_per_page' => 12,
|
||||
'meta_query' => $meta_query,
|
||||
'tax_query' => $tax_query,
|
||||
'fields' => 'ids',
|
||||
);
|
||||
|
||||
$this->assertEquals( $expected9, $shortcode9->get_query_args() );
|
||||
|
@ -285,6 +294,7 @@ class WC_Test_Shortcode_Products extends WC_Unit_Test_Case {
|
|||
'include_children' => false,
|
||||
),
|
||||
) ),
|
||||
'fields' => 'ids',
|
||||
);
|
||||
|
||||
$this->assertEquals( $expected10, $shortcode10->get_query_args() );
|
||||
|
@ -315,6 +325,7 @@ class WC_Test_Shortcode_Products extends WC_Unit_Test_Case {
|
|||
'operator' => 'IN',
|
||||
),
|
||||
) ),
|
||||
'fields' => 'ids',
|
||||
);
|
||||
|
||||
$this->assertEquals( $expected11, $shortcode11->get_query_args() );
|
||||
|
@ -341,6 +352,7 @@ class WC_Test_Shortcode_Products extends WC_Unit_Test_Case {
|
|||
'include_children' => false,
|
||||
),
|
||||
),
|
||||
'fields' => 'ids',
|
||||
);
|
||||
|
||||
$this->assertEquals( $expected12, $shortcode12->get_query_args() );
|
||||
|
@ -373,6 +385,7 @@ class WC_Test_Shortcode_Products extends WC_Unit_Test_Case {
|
|||
'include_children' => false,
|
||||
),
|
||||
),
|
||||
'fields' => 'ids',
|
||||
);
|
||||
|
||||
$this->assertEquals( $expected13, $shortcode13->get_query_args() );
|
||||
|
@ -405,6 +418,7 @@ class WC_Test_Shortcode_Products extends WC_Unit_Test_Case {
|
|||
'include_children' => false,
|
||||
),
|
||||
),
|
||||
'fields' => 'ids',
|
||||
);
|
||||
|
||||
$this->assertEquals( $expected14, $shortcode14->get_query_args() );
|
||||
|
|
Loading…
Reference in New Issue