Merge branch 'master' into fix-13498

# Conflicts:
#	includes/class-wc-order.php
#	tests/unit-tests/crud/data.php
This commit is contained in:
Mike Jolley 2017-03-15 15:52:40 +00:00
commit d55653a408
68 changed files with 810 additions and 401 deletions

View File

@ -21,6 +21,7 @@ matrix:
env: WP_VERSION=latest WP_MULTISITE=1 PHP_LATEST_STABLE=7.1
before_script:
- export PATH="$HOME/.composer/vendor/bin:$PATH"
- bash tests/bin/install.sh woocommerce_test root '' localhost $WP_VERSION
- bash tests/bin/travis.sh before

View File

@ -21,10 +21,10 @@
this.$attributeFields.unbind( 'change ' );
// Methods.
this.getChosenAttributes = this.getChosenAttributes.bind( this );
this.getChosenAttributes = this.getChosenAttributes.bind( this );
this.findMatchingVariations = this.findMatchingVariations.bind( this );
this.isMatch = this.isMatch.bind( this );
this.toggleResetLink = this.toggleResetLink.bind( this );
this.isMatch = this.isMatch.bind( this );
this.toggleResetLink = this.toggleResetLink.bind( this );
// Events.
$form.on( 'click', '.reset_variations', { variationForm: this }, this.onReset );
@ -527,7 +527,9 @@
* Reset the slide position if the variation has a different image than the current one
*/
$.fn.wc_maybe_trigger_slide_position_reset = function( variation ) {
var $form = $( this ),
var $form = $( this ),
$product = $form.closest( '.product' ),
$product_gallery = $product.find( '.images' ),
reset_slide_position = false,
new_image_id = ( variation && variation.image_id ) ? variation.image_id : '';
@ -538,7 +540,7 @@
$form.attr( 'current-image', new_image_id );
if ( reset_slide_position ) {
$( 'body' ).trigger( 'woocommerce_gallery_reset_slide_position' );
$product_gallery.trigger( 'woocommerce_gallery_reset_slide_position' );
}
};
@ -548,9 +550,9 @@
$.fn.wc_variations_image_update = function( variation ) {
var $form = this,
$product = $form.closest( '.product' ),
$product_gallery = $product.find( '.images' ),
$gallery_img = $product.find( '.flex-control-nav li:eq(0) img' ),
$gallery_wrapper = $product.find( '.woocommerce-product-gallery__wrapper ' ),
$product_img_wrap = $gallery_wrapper.find( '.woocommerce-product-gallery__image, .woocommerce-product-gallery__image--placeholder' ).eq( 0 ),
$product_img_wrap = $product_gallery.find( '.woocommerce-product-gallery__image, .woocommerce-product-gallery__image--placeholder' ).eq( 0 ),
$product_img = $product_img_wrap.find( '.wp-post-image' );
if ( variation && variation.image && variation.image.src && variation.image.src.length > 1 ) {
@ -561,9 +563,9 @@
$product_img.wc_set_variation_attr( 'sizes', variation.image.sizes );
$product_img.wc_set_variation_attr( 'title', variation.image.title );
$product_img.wc_set_variation_attr( 'alt', variation.image.alt );
$product_img.wc_set_variation_attr( 'data-large-image', variation.image.full_src );
$product_img.wc_set_variation_attr( 'data-large-image-width', variation.image.full_src_w );
$product_img.wc_set_variation_attr( 'data-large-image-height', variation.image.full_src_h );
$product_img.wc_set_variation_attr( 'data-large_image', variation.image.full_src );
$product_img.wc_set_variation_attr( 'data-large_image_width', variation.image.full_src_w );
$product_img.wc_set_variation_attr( 'data-large_image_height', variation.image.full_src_h );
$product_img_wrap.wc_set_variation_attr( 'data-thumb', variation.image.src );
$gallery_img.wc_set_variation_attr( 'src', variation.image.src );
} else {
@ -574,16 +576,15 @@
$product_img.wc_reset_variation_attr( 'sizes' );
$product_img.wc_reset_variation_attr( 'title' );
$product_img.wc_reset_variation_attr( 'alt' );
$product_img.wc_reset_variation_attr( 'data-large-image' );
$product_img.wc_reset_variation_attr( 'data-large-image-width' );
$product_img.wc_reset_variation_attr( 'data-large-image-height' );
$product_img.wc_reset_variation_attr( 'data-large_image' );
$product_img.wc_reset_variation_attr( 'data-large_image_width' );
$product_img.wc_reset_variation_attr( 'data-large_image_height' );
$product_img_wrap.wc_reset_variation_attr( 'data-thumb' );
$product_img.wc_reset_variation_attr( 'large-image' );
$gallery_img.wc_reset_variation_attr( 'src' );
}
window.setTimeout( function() {
$( 'body' ).trigger( 'woocommerce_init_gallery' );
$product_gallery.trigger( 'woocommerce_gallery_init_zoom' );
$form.wc_maybe_trigger_slide_position_reset( variation );
$( window ).trigger( 'resize' );
}, 10 );

File diff suppressed because one or more lines are too long

View File

@ -1,13 +1,13 @@
/*global wc_single_product_params, PhotoSwipe, PhotoSwipeUI_Default */
jQuery( function( $ ) {
// wc_single_product_params is required to continue, ensure the object exists
// wc_single_product_params is required to continue.
if ( typeof wc_single_product_params === 'undefined' ) {
return false;
}
// Tabs
$( 'body' )
// Tabs
.on( 'init', '.wc-tabs-wrapper, .woocommerce-tabs', function() {
$( '.wc-tab, .woocommerce-tabs .panel:not(.panel .panel)' ).hide();
@ -22,7 +22,7 @@ jQuery( function( $ ) {
} else {
$tabs.find( 'li:first a' ).click();
}
})
} )
.on( 'click', '.wc-tabs li a, ul.tabs li a', function( e ) {
e.preventDefault();
var $tab = $( this );
@ -34,16 +34,16 @@ jQuery( function( $ ) {
$tab.closest( 'li' ).addClass( 'active' );
$tabs_wrapper.find( $tab.attr( 'href' ) ).show();
})
} )
// Review link
.on( 'click', 'a.woocommerce-review-link', function() {
$( '.reviews_tab a' ).click();
return true;
})
} )
// Star ratings for comments
.on( 'init', '#rating', function() {
$( '#rating' ).hide().before( '<p class="stars"><span><a class="star-1" href="#">1</a><a class="star-2" href="#">2</a><a class="star-3" href="#">3</a><a class="star-4" href="#">4</a><a class="star-5" href="#">5</a></span></p>' );
})
} )
.on( 'click', '#respond p.stars a', function() {
var $star = $( this ),
$rating = $( this ).closest( '#respond' ).find( '#rating' ),
@ -55,7 +55,7 @@ jQuery( function( $ ) {
$container.addClass( 'selected' );
return false;
})
} )
.on( 'click', '#respond #submit', function() {
var $rating = $( this ).closest( '#respond' ).find( '#rating' ),
rating = $rating.val();
@ -65,173 +65,206 @@ jQuery( function( $ ) {
return false;
}
})
.on( 'woocommerce_init_gallery', function() {
if ( $.isFunction( $.fn.zoom ) && wc_single_product_params.zoom_enabled ) {
wc_product_gallery.init_zoom();
}
});
} );
//Init Tabs and Star Ratings
// Init Tabs and Star Ratings
$( '.wc-tabs-wrapper, .woocommerce-tabs, #rating' ).trigger( 'init' );
/**
* Product gallery class.
*/
var wc_product_gallery = {
var ProductGallery = function( $target, args ) {
this.$target = $target;
this.$images = $( '.woocommerce-product-gallery__image', $target );
/**
* Initialize gallery actions and events.
*/
init: function() {
if ( $.isFunction( $.fn.flexslider ) && wc_single_product_params.flexslider_enabled ) {
this.init_flexslider();
}
if ( $.isFunction( $.fn.zoom ) && wc_single_product_params.zoom_enabled ) {
this.init_zoom();
}
if ( typeof PhotoSwipe !== 'undefined' && wc_single_product_params.photoswipe_enabled ) {
this.init_photoswipe();
}
},
// Make this object available.
$target.data( 'product_gallery', this );
/**
* Initialize flexSlider.
*/
init_flexslider: function() {
$( '.woocommerce-product-gallery' ).flexslider({
selector: '.woocommerce-product-gallery__wrapper > .woocommerce-product-gallery__image',
animation: wc_single_product_params.flexslider.animation,
smoothHeight: wc_single_product_params.flexslider.smoothHeight,
directionNav: wc_single_product_params.flexslider.directionNav,
controlNav: wc_single_product_params.flexslider.controlNav,
slideshow: wc_single_product_params.flexslider.slideshow,
animationSpeed: wc_single_product_params.flexslider.animationSpeed,
animationLoop: wc_single_product_params.flexslider.animationLoop, // Breaks photoswipe pagination if true.
start: function() {
var $images = $( '.woocommerce-product-gallery__image' );
var largest_height = 0;
// Pick functionality to initialize...
this.flexslider_enabled = $.isFunction( $.fn.flexslider ) && wc_single_product_params.flexslider_enabled;
this.zoom_enabled = $.isFunction( $.fn.zoom ) && wc_single_product_params.zoom_enabled;
this.photoswipe_enabled = typeof PhotoSwipe !== 'undefined' && wc_single_product_params.photoswipe_enabled;
$images.each( function() {
var height = $( this ).height();
// ...also taking args into account.
if ( args ) {
this.flexslider_enabled = false === args.photoswipe_enabled ? false : this.flexslider_enabled;
this.zoom_enabled = false === args.zoom_enabled ? false : this.zoom_enabled;
this.photoswipe_enabled = false === args.photoswipe_enabled ? false : this.photoswipe_enabled;
}
if ( height > largest_height ) {
largest_height = height;
}
});
// Bind functions to this.
this.initFlexslider = this.initFlexslider.bind( this );
this.initZoom = this.initZoom.bind( this );
this.initPhotoswipe = this.initPhotoswipe.bind( this );
this.onResetSlidePosition = this.onResetSlidePosition.bind( this );
this.getGalleryItems = this.getGalleryItems.bind( this );
this.openPhotoswipe = this.openPhotoswipe.bind( this );
$images.each( function() {
$( this ).css( 'min-height', largest_height );
});
}
});
if ( this.flexslider_enabled ) {
this.initFlexslider();
$target.on( 'woocommerce_gallery_reset_slide_position', this.onResetSlidePosition );
}
$( 'body' ).on( 'woocommerce_gallery_reset_slide_position', function(){
$( '.woocommerce-product-gallery' ).flexslider( 0 );
} );
},
if ( this.zoom_enabled ) {
this.initZoom();
$target.on( 'woocommerce_gallery_init_zoom', this.initZoom );
}
/**
* Init zoom.
*/
init_zoom: function() {
var zoom_target = $( '.woocommerce-product-gallery__image' ),
enable_zoom = false;
if ( ! wc_single_product_params.flexslider_enabled ) {
zoom_target = zoom_target.first();
}
$( zoom_target ).each( function( index, target ) {
var image = $( target ).find( 'img' );
if ( image.attr( 'width' ) > $( '.woocommerce-product-gallery' ).width() ) {
enable_zoom = true;
return false;
}
} );
// But only zoom if the img is larger than its container.
if ( enable_zoom ) {
zoom_target.trigger( 'zoom.destroy' );
zoom_target.zoom({
touch: false
});
}
},
/**
* Get product gallery image items.
*/
get_gallery_items: function() {
var $slides = $( '.woocommerce-product-gallery__wrapper' ).children(),
items = [],
index = $slides.filter( '.' + 'flex-active-slide' ).index();
if ( $slides.length > 0 ) {
$slides.each( function( i, el ) {
var img = $( el ).find( 'img' ),
large_image_src = img.attr( 'data-large-image' ),
large_image_w = img.attr( 'data-large-image-width' ),
large_image_h = img.attr( 'data-large-image-height' ),
item = {
src: large_image_src,
w: large_image_w,
h: large_image_h,
title: img.attr( 'title' )
};
items.push( item );
});
}
return {
index: index,
items: items
};
},
/**
* Init PhotoSwipe.
*/
init_photoswipe: function() {
if ( wc_single_product_params.zoom_enabled ) {
$( '.woocommerce-product-gallery--with-images' ).prepend( '<a href="#" class="woocommerce-product-gallery__trigger">🔍</a>' );
$( document ).on( 'click', '.woocommerce-product-gallery__trigger', this.trigger_photoswipe );
}
$( document ).on( 'click', '.woocommerce-product-gallery__image a', this.trigger_photoswipe );
},
/**
* Initialise photoswipe.
*/
trigger_photoswipe: function( e ) {
e.preventDefault();
var pswpElement = $( '.pswp' )[0],
items = wc_product_gallery.get_gallery_items(),
target = $( e.target ),
clicked;
if ( ! target.is( '.woocommerce-product-gallery__trigger' ) ) {
clicked = e.target.closest( 'figure' );
} else {
clicked = target.parents( '.woocommerce-product-gallery' ).find( '.flex-active-slide' );
}
var options = {
index: $( clicked ).index(),
shareEl: false,
closeOnScroll: false,
history: false,
hideAnimationDuration: 0,
showAnimationDuration: 0
};
// Initializes and opens PhotoSwipe.
var gallery = new PhotoSwipe( pswpElement, PhotoSwipeUI_Default, items.items, options );
gallery.init();
if ( this.photoswipe_enabled ) {
this.initPhotoswipe();
}
};
wc_product_gallery.init();
});
/**
* Initialize flexSlider.
*/
ProductGallery.prototype.initFlexslider = function() {
var images = this.$images;
this.$target.flexslider( {
selector: '.woocommerce-product-gallery__wrapper > .woocommerce-product-gallery__image',
animation: wc_single_product_params.flexslider.animation,
smoothHeight: wc_single_product_params.flexslider.smoothHeight,
directionNav: wc_single_product_params.flexslider.directionNav,
controlNav: wc_single_product_params.flexslider.controlNav,
slideshow: wc_single_product_params.flexslider.slideshow,
animationSpeed: wc_single_product_params.flexslider.animationSpeed,
animationLoop: wc_single_product_params.flexslider.animationLoop, // Breaks photoswipe pagination if true.
start: function() {
var largest_height = 0;
images.each( function() {
var height = $( this ).height();
if ( height > largest_height ) {
largest_height = height;
}
} );
images.each( function() {
$( this ).css( 'min-height', largest_height );
} );
}
} );
};
/**
* Init zoom.
*/
ProductGallery.prototype.initZoom = function() {
var zoomTarget = this.$images,
galleryWidth = this.$target.width(),
zoomEnabled = false;
if ( ! this.flexslider_enabled ) {
zoomTarget = zoomTarget.first();
}
$( zoomTarget ).each( function( index, target ) {
var image = $( target ).find( 'img' );
if ( image.attr( 'width' ) > galleryWidth ) {
zoomEnabled = true;
return false;
}
} );
// But only zoom if the img is larger than its container.
if ( zoomEnabled ) {
zoomTarget.trigger( 'zoom.destroy' );
zoomTarget.zoom( {
touch: false
} );
}
};
/**
* Init PhotoSwipe.
*/
ProductGallery.prototype.initPhotoswipe = function() {
if ( this.zoom_enabled && this.$images.length > 0 ) {
this.$target.prepend( '<a href="#" class="woocommerce-product-gallery__trigger">🔍</a>' );
this.$target.on( 'click', '.woocommerce-product-gallery__trigger', this.openPhotoswipe );
}
this.$target.on( 'click', '.woocommerce-product-gallery__image a', this.openPhotoswipe );
};
/**
* Reset slide position to 0.
*/
ProductGallery.prototype.onResetSlidePosition = function() {
this.$target.flexslider( 0 );
};
/**
* Get product gallery image items.
*/
ProductGallery.prototype.getGalleryItems = function() {
var $slides = this.$images,
items = [];
if ( $slides.length > 0 ) {
$slides.each( function( i, el ) {
var img = $( el ).find( 'img' ),
large_image_src = img.attr( 'data-large_image' ),
large_image_w = img.attr( 'data-large_image_width' ),
large_image_h = img.attr( 'data-large_image_height' ),
item = {
src: large_image_src,
w: large_image_w,
h: large_image_h,
title: img.attr( 'title' )
};
items.push( item );
} );
}
return items;
};
/**
* Open photoswipe modal.
*/
ProductGallery.prototype.openPhotoswipe = function( e ) {
e.preventDefault();
var pswpElement = $( '.pswp' )[0],
items = this.getGalleryItems(),
eventTarget = $( e.target ),
clicked;
if ( ! eventTarget.is( '.woocommerce-product-gallery__trigger' ) ) {
clicked = eventTarget.closest( '.woocommerce-product-gallery__image' );
} else {
clicked = this.$target.find( '.flex-active-slide' );
}
var options = {
index: $( clicked ).index(),
shareEl: false,
closeOnScroll: false,
history: false,
hideAnimationDuration: 0,
showAnimationDuration: 0
};
// Initializes and opens PhotoSwipe.
var photoswipe = new PhotoSwipe( pswpElement, PhotoSwipeUI_Default, items, options );
photoswipe.init();
};
/**
* Function to call wc_product_gallery on jquery selector.
*/
$.fn.wc_product_gallery = function( args ) {
new ProductGallery( this, args );
return this;
};
/*
* Initialize all galleries on page.
*/
$( '.woocommerce-product-gallery' ).each( function() {
$( this ).wc_product_gallery();
} );
} );

File diff suppressed because one or more lines are too long

View File

@ -256,6 +256,19 @@ abstract class WC_Data {
return $value;
}
/**
* See if meta data exists, since get_meta always returns a '' or array().
*
* @since 2.7.0
* @param string $key
* @return boolean
*/
public function meta_exists( $key = '' ) {
$this->maybe_read_meta_data();
$array_keys = wp_list_pluck( $this->get_meta_data(), 'key' );
return in_array( $key, $array_keys );
}
/**
* Set all meta data from array.
*

View File

@ -103,11 +103,6 @@ abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order {
$this->set_object_read( true );
}
// Set default status if none were read.
if ( ! $this->get_status() ) {
$this->set_status( apply_filters( 'woocommerce_default_order_status', 'pending' ) );
}
$this->data_store = WC_Data_Store::load( $this->data_store_name );
if ( $this->get_id() > 0 ) {
@ -283,7 +278,13 @@ abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order {
* @return string
*/
public function get_status( $context = 'view' ) {
return $this->get_prop( 'status', $context );
$status = $this->get_prop( 'status', $context );
if ( empty( $status ) && 'view' === $context ) {
// In view context, return the default status if no status has been set.
$status = apply_filters( 'woocommerce_default_order_status', 'pending' );
}
return $status;
}
/**

View File

@ -447,7 +447,7 @@ abstract class WC_Payment_Gateway extends WC_Settings_API {
* @since 2.6.0
*/
public function save_payment_method_checkbox() {
echo sprintf(
printf(
'<p class="form-row woocommerce-SavedPaymentMethods-saveNew">
<input id="wc-%1$s-new-payment-method" name="wc-%1$s-new-payment-method" type="checkbox" value="true" style="width:auto;" />
<label for="wc-%1$s-new-payment-method" style="display:inline;">%2$s</label>

View File

@ -130,7 +130,7 @@ class WC_Product extends WC_Abstract_Legacy_Product {
/**
* Get internal type. Should return string and *should be overridden* by child classes.
*
* The product_type property is @deprecated but is used here for BW compat with child classes which may be defining product_type and not have a get_type method.
* The product_type property is deprecated but is used here for BW compat with child classes which may be defining product_type and not have a get_type method.
*
* @since 2.7.0
* @return string

View File

@ -492,12 +492,11 @@ class WC_Admin_Post_Types {
case 'usage' :
$usage_count = $the_coupon->get_usage_count();
$usage_limit = $the_coupon->get_usage_limit();
$usage_url = sprintf( '<a href="%s">%s</a>', admin_url( sprintf( 'edit.php?s=%s&post_status=all&post_type=shop_order', esc_html( $post->post_title ) ) ), esc_html( $usage_count ) );
/* translators: 1: count 2: limit */
printf(
__( '%1$s / %2$s', 'woocommerce' ),
$usage_url,
esc_html( $usage_count ),
esc_html( $usage_limit ? $usage_limit : '&infin;' )
);
break;

View File

@ -142,7 +142,7 @@ class WC_Admin_Setup_Wizard {
<head>
<meta name="viewport" content="width=device-width" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title><?php _e( 'WooCommerce &rsaquo; Setup Wizard', 'woocommerce' ); ?></title>
<title><?php esc_html_e( 'WooCommerce &rsaquo; Setup Wizard', 'woocommerce' ); ?></title>
<?php wp_print_scripts( 'wc-setup' ); ?>
<?php do_action( 'admin_print_styles' ); ?>
<?php do_action( 'admin_head' ); ?>
@ -158,7 +158,7 @@ class WC_Admin_Setup_Wizard {
public function setup_wizard_footer() {
?>
<?php if ( 'next_steps' === $this->step ) : ?>
<a class="wc-return-to-dashboard" href="<?php echo esc_url( admin_url() ); ?>"><?php _e( 'Return to the WordPress Dashboard', 'woocommerce' ); ?></a>
<a class="wc-return-to-dashboard" href="<?php echo esc_url( admin_url() ); ?>"><?php esc_html_e( 'Return to the WordPress Dashboard', 'woocommerce' ); ?></a>
<?php endif; ?>
</body>
</html>
@ -200,12 +200,12 @@ class WC_Admin_Setup_Wizard {
*/
public function wc_setup_introduction() {
?>
<h1><?php _e( 'Welcome to the world of WooCommerce!', 'woocommerce' ); ?></h1>
<h1><?php esc_html_e( 'Welcome to the world of WooCommerce!', 'woocommerce' ); ?></h1>
<p><?php _e( 'Thank you for choosing WooCommerce to power your online store! This quick setup wizard will help you configure the basic settings. <strong>Its completely optional and shouldnt take longer than five minutes.</strong>', 'woocommerce' ); ?></p>
<p><?php _e( 'No time right now? If you dont want to go through the wizard, you can skip and return to the WordPress dashboard. Come back anytime if you change your mind!', 'woocommerce' ); ?></p>
<p><?php esc_html_e( 'No time right now? If you dont want to go through the wizard, you can skip and return to the WordPress dashboard. Come back anytime if you change your mind!', 'woocommerce' ); ?></p>
<p class="wc-setup-actions step">
<a href="<?php echo esc_url( $this->get_next_step_link() ); ?>" class="button-primary button button-large button-next"><?php _e( 'Let\'s go!', 'woocommerce' ); ?></a>
<a href="<?php echo esc_url( admin_url() ); ?>" class="button button-large"><?php _e( 'Not right now', 'woocommerce' ); ?></a>
<a href="<?php echo esc_url( $this->get_next_step_link() ); ?>" class="button-primary button button-large button-next"><?php esc_html_e( 'Let\'s go!', 'woocommerce' ); ?></a>
<a href="<?php echo esc_url( admin_url() ); ?>" class="button button-large"><?php esc_html_e( 'Not right now', 'woocommerce' ); ?></a>
</p>
<?php
}
@ -215,35 +215,35 @@ class WC_Admin_Setup_Wizard {
*/
public function wc_setup_pages() {
?>
<h1><?php _e( 'Page setup', 'woocommerce' ); ?></h1>
<h1><?php esc_html_e( 'Page setup', 'woocommerce' ); ?></h1>
<form method="post">
<p><?php printf( __( 'Your store needs a few essential <a href="%s" target="_blank">pages</a>. The following will be created automatically (if they do not already exist):', 'woocommerce' ), esc_url( admin_url( 'edit.php?post_type=page' ) ) ); ?></p>
<table class="wc-setup-pages" cellspacing="0">
<thead>
<tr>
<th class="page-name"><?php _e( 'Page name', 'woocommerce' ); ?></th>
<th class="page-description"><?php _e( 'Description', 'woocommerce' ); ?></th>
<th class="page-name"><?php esc_html_e( 'Page name', 'woocommerce' ); ?></th>
<th class="page-description"><?php esc_html_e( 'Description', 'woocommerce' ); ?></th>
</tr>
</thead>
<tbody>
<tr>
<td class="page-name"><?php echo _x( 'Shop', 'Page title', 'woocommerce' ); ?></td>
<td><?php _e( 'The shop page will display your products.', 'woocommerce' ); ?></td>
<td><?php esc_html_e( 'The shop page will display your products.', 'woocommerce' ); ?></td>
</tr>
<tr>
<td class="page-name"><?php echo _x( 'Cart', 'Page title', 'woocommerce' ); ?></td>
<td><?php _e( 'The cart page will be where the customers go to view their cart and begin checkout.', 'woocommerce' ); ?></td>
<td><?php esc_html_e( 'The cart page will be where the customers go to view their cart and begin checkout.', 'woocommerce' ); ?></td>
</tr>
<tr>
<td class="page-name"><?php echo _x( 'Checkout', 'Page title', 'woocommerce' ); ?></td>
<td>
<?php _e( 'The checkout page will be where the customers go to pay for their items.', 'woocommerce' ); ?>
<?php esc_html_e( 'The checkout page will be where the customers go to pay for their items.', 'woocommerce' ); ?>
</td>
</tr>
<tr>
<td class="page-name"><?php echo _x( 'My account', 'Page title', 'woocommerce' ); ?></td>
<td>
<?php _e( 'Registered customers will be able to manage their account details and view past orders on this page.', 'woocommerce' ); ?>
<?php esc_html_e( 'Registered customers will be able to manage their account details and view past orders on this page.', 'woocommerce' ); ?>
</td>
</tr>
</tbody>
@ -253,7 +253,7 @@ class WC_Admin_Setup_Wizard {
<p class="wc-setup-actions step">
<input type="submit" class="button-primary button button-large button-next" value="<?php esc_attr_e( 'Continue', 'woocommerce' ); ?>" name="save_step" />
<a href="<?php echo esc_url( $this->get_next_step_link() ); ?>" class="button button-large button-next"><?php _e( 'Skip this step', 'woocommerce' ); ?></a>
<a href="<?php echo esc_url( $this->get_next_step_link() ); ?>" class="button button-large button-next"><?php esc_html_e( 'Skip this step', 'woocommerce' ); ?></a>
<?php wp_nonce_field( 'wc-setup' ); ?>
</p>
</form>
@ -289,11 +289,11 @@ class WC_Admin_Setup_Wizard {
$dimension_unit = get_option( 'woocommerce_dimension_unit', 'cm' );
$weight_unit = get_option( 'woocommerce_weight_unit', 'kg' );
?>
<h1><?php _e( 'Store locale setup', 'woocommerce' ); ?></h1>
<h1><?php esc_html_e( 'Store locale setup', 'woocommerce' ); ?></h1>
<form method="post">
<table class="form-table">
<tr>
<th scope="row"><label for="store_location"><?php _e( 'Where is your store based?', 'woocommerce' ); ?></label></th>
<th scope="row"><label for="store_location"><?php esc_html_e( 'Where is your store based?', 'woocommerce' ); ?></label></th>
<td>
<select id="store_location" name="store_location" style="width:100%;" required data-placeholder="<?php esc_attr_e( 'Choose a country&hellip;', 'woocommerce' ); ?>" class="wc-enhanced-select">
<?php WC()->countries->country_dropdown_options( $country, $state ); ?>
@ -301,10 +301,10 @@ class WC_Admin_Setup_Wizard {
</td>
</tr>
<tr>
<th scope="row"><label for="currency_code"><?php _e( 'Which currency will your store use?', 'woocommerce' ); ?></label></th>
<th scope="row"><label for="currency_code"><?php esc_html_e( 'Which currency will your store use?', 'woocommerce' ); ?></label></th>
<td>
<select id="currency_code" name="currency_code" style="width:100%;" data-placeholder="<?php esc_attr_e( 'Choose a currency&hellip;', 'woocommerce' ); ?>" class="wc-enhanced-select">
<option value=""><?php _e( 'Choose a currency&hellip;', 'woocommerce' ); ?></option>
<option value=""><?php esc_html_e( 'Choose a currency&hellip;', 'woocommerce' ); ?></option>
<?php
foreach ( get_woocommerce_currencies() as $code => $name ) {
echo '<option value="' . esc_attr( $code ) . '" ' . selected( $currency, $code, false ) . '>' . sprintf( esc_html__( '%1$s (%2$s)', 'woocommerce' ), $name, get_woocommerce_currency_symbol( $code ) ) . '</option>';
@ -315,61 +315,61 @@ class WC_Admin_Setup_Wizard {
</td>
</tr>
<tr>
<th scope="row"><label for="currency_pos"><?php _e( 'Currency position', 'woocommerce' ); ?></label></th>
<th scope="row"><label for="currency_pos"><?php esc_html_e( 'Currency position', 'woocommerce' ); ?></label></th>
<td>
<select id="currency_pos" name="currency_pos" class="wc-enhanced-select">
<option value="left" <?php selected( $currency_pos, 'left' ); ?>><?php echo __( 'Left', 'woocommerce' ); ?></option>
<option value="right" <?php selected( $currency_pos, 'right' ); ?>><?php echo __( 'Right', 'woocommerce' ); ?></option>
<option value="left_space" <?php selected( $currency_pos, 'left_space' ); ?>><?php echo __( 'Left with space', 'woocommerce' ); ?></option>
<option value="right_space" <?php selected( $currency_pos, 'right_space' ); ?>><?php echo __( 'Right with space', 'woocommerce' ); ?></option>
<option value="left" <?php selected( $currency_pos, 'left' ); ?>><?php esc_html_e( 'Left', 'woocommerce' ); ?></option>
<option value="right" <?php selected( $currency_pos, 'right' ); ?>><?php esc_html_e( 'Right', 'woocommerce' ); ?></option>
<option value="left_space" <?php selected( $currency_pos, 'left_space' ); ?>><?php esc_html_e( 'Left with space', 'woocommerce' ); ?></option>
<option value="right_space" <?php selected( $currency_pos, 'right_space' ); ?>><?php esc_html_e( 'Right with space', 'woocommerce' ); ?></option>
</select>
</td>
</tr>
<tr>
<th scope="row"><label for="thousand_sep"><?php _e( 'Thousand separator', 'woocommerce' ); ?></label></th>
<th scope="row"><label for="thousand_sep"><?php esc_html_e( 'Thousand separator', 'woocommerce' ); ?></label></th>
<td>
<input type="text" id="thousand_sep" name="thousand_sep" size="2" value="<?php echo esc_attr( $thousand_sep ); ?>" />
</td>
</tr>
<tr>
<th scope="row"><label for="decimal_sep"><?php _e( 'Decimal separator', 'woocommerce' ); ?></label></th>
<th scope="row"><label for="decimal_sep"><?php esc_html_e( 'Decimal separator', 'woocommerce' ); ?></label></th>
<td>
<input type="text" id="decimal_sep" name="decimal_sep" size="2" value="<?php echo esc_attr( $decimal_sep ); ?>" />
</td>
</tr>
<tr>
<th scope="row"><label for="num_decimals"><?php _e( 'Number of decimals', 'woocommerce' ); ?></label></th>
<th scope="row"><label for="num_decimals"><?php esc_html_e( 'Number of decimals', 'woocommerce' ); ?></label></th>
<td>
<input type="text" id="num_decimals" name="num_decimals" size="2" value="<?php echo esc_attr( $num_decimals ); ?>" />
</td>
</tr>
<tr>
<th scope="row"><label for="weight_unit"><?php _e( 'Which unit should be used for product weights?', 'woocommerce' ); ?></label></th>
<th scope="row"><label for="weight_unit"><?php esc_html_e( 'Which unit should be used for product weights?', 'woocommerce' ); ?></label></th>
<td>
<select id="weight_unit" name="weight_unit" class="wc-enhanced-select">
<option value="kg" <?php selected( $weight_unit, 'kg' ); ?>><?php echo __( 'kg', 'woocommerce' ); ?></option>
<option value="g" <?php selected( $weight_unit, 'g' ); ?>><?php echo __( 'g', 'woocommerce' ); ?></option>
<option value="lbs" <?php selected( $weight_unit, 'lbs' ); ?>><?php echo __( 'lbs', 'woocommerce' ); ?></option>
<option value="oz" <?php selected( $weight_unit, 'oz' ); ?>><?php echo __( 'oz', 'woocommerce' ); ?></option>
<option value="kg" <?php selected( $weight_unit, 'kg' ); ?>><?php esc_html_e( 'kg', 'woocommerce' ); ?></option>
<option value="g" <?php selected( $weight_unit, 'g' ); ?>><?php esc_html_e( 'g', 'woocommerce' ); ?></option>
<option value="lbs" <?php selected( $weight_unit, 'lbs' ); ?>><?php esc_html_e( 'lbs', 'woocommerce' ); ?></option>
<option value="oz" <?php selected( $weight_unit, 'oz' ); ?>><?php esc_html_e( 'oz', 'woocommerce' ); ?></option>
</select>
</td>
</tr>
<tr>
<th scope="row"><label for="dimension_unit"><?php _e( 'Which unit should be used for product dimensions?', 'woocommerce' ); ?></label></th>
<th scope="row"><label for="dimension_unit"><?php esc_html_e( 'Which unit should be used for product dimensions?', 'woocommerce' ); ?></label></th>
<td>
<select id="dimension_unit" name="dimension_unit" class="wc-enhanced-select">
<option value="m" <?php selected( $dimension_unit, 'm' ); ?>><?php echo __( 'm', 'woocommerce' ); ?></option>
<option value="cm" <?php selected( $dimension_unit, 'cm' ); ?>><?php echo __( 'cm', 'woocommerce' ); ?></option>
<option value="mm" <?php selected( $dimension_unit, 'mm' ); ?>><?php echo __( 'mm', 'woocommerce' ); ?></option>
<option value="in" <?php selected( $dimension_unit, 'in' ); ?>><?php echo __( 'in', 'woocommerce' ); ?></option>
<option value="yd" <?php selected( $dimension_unit, 'yd' ); ?>><?php echo __( 'yd', 'woocommerce' ); ?></option>
<option value="m" <?php selected( $dimension_unit, 'm' ); ?>><?php esc_html_e( 'm', 'woocommerce' ); ?></option>
<option value="cm" <?php selected( $dimension_unit, 'cm' ); ?>><?php esc_html_e( 'cm', 'woocommerce' ); ?></option>
<option value="mm" <?php selected( $dimension_unit, 'mm' ); ?>><?php esc_html_e( 'mm', 'woocommerce' ); ?></option>
<option value="in" <?php selected( $dimension_unit, 'in' ); ?>><?php esc_html_e( 'in', 'woocommerce' ); ?></option>
<option value="yd" <?php selected( $dimension_unit, 'yd' ); ?>><?php esc_html_e( 'yd', 'woocommerce' ); ?></option>
</select>
</td>
</tr>
</table>
<p class="wc-setup-actions step">
<input type="submit" class="button-primary button button-large button-next" value="<?php esc_attr_e( 'Continue', 'woocommerce' ); ?>" name="save_step" />
<a href="<?php echo esc_url( $this->get_next_step_link() ); ?>" class="button button-large button-next"><?php _e( 'Skip this step', 'woocommerce' ); ?></a>
<a href="<?php echo esc_url( $this->get_next_step_link() ); ?>" class="button button-large button-next"><?php esc_html_e( 'Skip this step', 'woocommerce' ); ?></a>
<?php wp_nonce_field( 'wc-setup' ); ?>
</p>
</form>
@ -409,29 +409,29 @@ class WC_Admin_Setup_Wizard {
*/
public function wc_setup_shipping_taxes() {
?>
<h1><?php _e( 'Shipping &amp; Tax setup', 'woocommerce' ); ?></h1>
<h1><?php esc_html_e( 'Shipping &amp; Tax setup', 'woocommerce' ); ?></h1>
<form method="post">
<p><?php _e( 'If you will be charging sales tax, or shipping physical goods to customers, you can enable these below. This is optional and can be changed later.', 'woocommerce' ); ?></p>
<p><?php esc_html_e( 'If you will be charging sales tax, or shipping physical goods to customers, you can enable these below. This is optional and can be changed later.', 'woocommerce' ); ?></p>
<table class="form-table">
<tr>
<th scope="row"><label for="woocommerce_calc_shipping"><?php _e( 'Will you be shipping products?', 'woocommerce' ); ?></label></th>
<th scope="row"><label for="woocommerce_calc_shipping"><?php esc_html_e( 'Will you be shipping products?', 'woocommerce' ); ?></label></th>
<td>
<input type="checkbox" id="woocommerce_calc_shipping" <?php checked( get_option( 'woocommerce_ship_to_countries', '' ) !== 'disabled', true ); ?> name="woocommerce_calc_shipping" class="input-checkbox" value="1" />
<label for="woocommerce_calc_shipping"><?php _e( 'Yes, I will be shipping physical goods to customers', 'woocommerce' ); ?></label>
<label for="woocommerce_calc_shipping"><?php esc_html_e( 'Yes, I will be shipping physical goods to customers', 'woocommerce' ); ?></label>
</td>
</tr>
<tr>
<th scope="row"><label for="woocommerce_calc_taxes"><?php _e( 'Will you be charging sales tax?', 'woocommerce' ); ?></label></th>
<th scope="row"><label for="woocommerce_calc_taxes"><?php esc_html_e( 'Will you be charging sales tax?', 'woocommerce' ); ?></label></th>
<td>
<input type="checkbox" <?php checked( get_option( 'woocommerce_calc_taxes', 'no' ), 'yes' ); ?> id="woocommerce_calc_taxes" name="woocommerce_calc_taxes" class="input-checkbox" value="1" />
<label for="woocommerce_calc_taxes"><?php _e( 'Yes, I will be charging sales tax', 'woocommerce' ); ?></label>
<label for="woocommerce_calc_taxes"><?php esc_html_e( 'Yes, I will be charging sales tax', 'woocommerce' ); ?></label>
</td>
</tr>
<tr>
<th scope="row"><label for="woocommerce_prices_include_tax"><?php _e( 'How will you enter product prices?', 'woocommerce' ); ?></label></th>
<th scope="row"><label for="woocommerce_prices_include_tax"><?php esc_html_e( 'How will you enter product prices?', 'woocommerce' ); ?></label></th>
<td>
<label><input type="radio" <?php checked( get_option( 'woocommerce_prices_include_tax', 'no' ), 'yes' ); ?> id="woocommerce_prices_include_tax" name="woocommerce_prices_include_tax" class="input-radio" value="yes" /> <?php _e( 'I will enter prices inclusive of tax', 'woocommerce' ); ?></label><br/>
<label><input type="radio" <?php checked( get_option( 'woocommerce_prices_include_tax', 'no' ), 'no' ); ?> id="woocommerce_prices_include_tax" name="woocommerce_prices_include_tax" class="input-radio" value="no" /> <?php _e( 'I will enter prices exclusive of tax', 'woocommerce' ); ?></label>
<label><input type="radio" <?php checked( get_option( 'woocommerce_prices_include_tax', 'no' ), 'yes' ); ?> id="woocommerce_prices_include_tax" name="woocommerce_prices_include_tax" class="input-radio" value="yes" /> <?php esc_html_e( 'I will enter prices inclusive of tax', 'woocommerce' ); ?></label><br/>
<label><input type="radio" <?php checked( get_option( 'woocommerce_prices_include_tax', 'no' ), 'no' ); ?> id="woocommerce_prices_include_tax" name="woocommerce_prices_include_tax" class="input-radio" value="no" /> <?php esc_html_e( 'I will enter prices exclusive of tax', 'woocommerce' ); ?></label>
</td>
</tr>
<?php
@ -459,10 +459,10 @@ class WC_Admin_Setup_Wizard {
<table class="tax-rates">
<thead>
<tr>
<th><?php _e( 'Country', 'woocommerce' ); ?></th>
<th><?php _e( 'State', 'woocommerce' ); ?></th>
<th><?php _e( 'Rate (%)', 'woocommerce' ); ?></th>
<th><?php _e( 'Name', 'woocommerce' ); ?></th>
<th><?php esc_html_e( 'Country', 'woocommerce' ); ?></th>
<th><?php esc_html_e( 'State', 'woocommerce' ); ?></th>
<th><?php esc_html_e( 'Rate (%)', 'woocommerce' ); ?></th>
<th><?php esc_html_e( 'Name', 'woocommerce' ); ?></th>
</tr>
</thead>
<tbody>
@ -490,7 +490,7 @@ class WC_Admin_Setup_Wizard {
</table>
<p class="wc-setup-actions step">
<input type="submit" class="button-primary button button-large button-next" value="<?php esc_attr_e( 'Continue', 'woocommerce' ); ?>" name="save_step" />
<a href="<?php echo esc_url( $this->get_next_step_link() ); ?>" class="button button-large button-next"><?php _e( 'Skip this step', 'woocommerce' ); ?></a>
<a href="<?php echo esc_url( $this->get_next_step_link() ); ?>" class="button button-large button-next"><?php esc_html_e( 'Skip this step', 'woocommerce' ); ?></a>
<?php wp_nonce_field( 'wc-setup' ); ?>
</p>
</form>
@ -639,7 +639,7 @@ class WC_Admin_Setup_Wizard {
public function wc_setup_payments() {
$gateways = $this->get_wizard_payment_gateways();
?>
<h1><?php _e( 'Payments', 'woocommerce' ); ?></h1>
<h1><?php esc_html_e( 'Payments', 'woocommerce' ); ?></h1>
<form method="post" class="wc-wizard-payment-gateway-form">
<p><?php printf( __( 'WooCommerce can accept both online and offline payments. <a href="%1$s" target="_blank">Additional payment methods</a> can be installed later and managed from the <a href="%2$s" target="_blank">checkout settings</a> screen.', 'woocommerce' ), esc_url( admin_url( 'admin.php?page=wc-addons&view=payment-gateways' ) ), esc_url( admin_url( 'admin.php?page=wc-settings&tab=checkout' ) ) ); ?></p>
@ -683,7 +683,7 @@ class WC_Admin_Setup_Wizard {
</ul>
<p class="wc-setup-actions step">
<input type="submit" class="button-primary button button-large button-next" value="<?php esc_attr_e( 'Continue', 'woocommerce' ); ?>" name="save_step" />
<a href="<?php echo esc_url( $this->get_next_step_link() ); ?>" class="button button-large button-next"><?php _e( 'Skip this step', 'woocommerce' ); ?></a>
<a href="<?php echo esc_url( $this->get_next_step_link() ); ?>" class="button button-large button-next"><?php esc_html_e( 'Skip this step', 'woocommerce' ); ?></a>
<?php wp_nonce_field( 'wc-setup' ); ?>
</p>
</form>
@ -746,31 +746,31 @@ class WC_Admin_Setup_Wizard {
<a href="https://twitter.com/share" class="twitter-share-button" data-url="https://woocommerce.com/" data-text="<?php echo esc_attr( $this->tweets[0] ); ?>" data-via="WooCommerce" data-size="large">Tweet</a>
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
<h1><?php _e( 'Your store is ready!', 'woocommerce' ); ?></h1>
<h1><?php esc_html_e( 'Your store is ready!', 'woocommerce' ); ?></h1>
<?php if ( 'unknown' === get_option( 'woocommerce_allow_tracking', 'unknown' ) ) : ?>
<div class="woocommerce-message woocommerce-tracker">
<p><?php printf( __( 'Want to help make WooCommerce even more awesome? Allow WooCommerce to collect non-sensitive diagnostic data and usage information. %1$sFind out more%2$s.', 'woocommerce' ), '<a href="https://woocommerce.com/usage-tracking/" target="_blank">', '</a>' ); ?></p>
<p class="submit">
<a class="button-primary button button-large" href="<?php echo esc_url( wp_nonce_url( add_query_arg( 'wc_tracker_optin', 'true' ), 'wc_tracker_optin', 'wc_tracker_nonce' ) ); ?>"><?php _e( 'Allow', 'woocommerce' ); ?></a>
<a class="button-secondary button button-large skip" href="<?php echo esc_url( wp_nonce_url( add_query_arg( 'wc_tracker_optout', 'true' ), 'wc_tracker_optout', 'wc_tracker_nonce' ) ); ?>"><?php _e( 'No thanks', 'woocommerce' ); ?></a>
<a class="button-primary button button-large" href="<?php echo esc_url( wp_nonce_url( add_query_arg( 'wc_tracker_optin', 'true' ), 'wc_tracker_optin', 'wc_tracker_nonce' ) ); ?>"><?php esc_html_e( 'Allow', 'woocommerce' ); ?></a>
<a class="button-secondary button button-large skip" href="<?php echo esc_url( wp_nonce_url( add_query_arg( 'wc_tracker_optout', 'true' ), 'wc_tracker_optout', 'wc_tracker_nonce' ) ); ?>"><?php esc_html_e( 'No thanks', 'woocommerce' ); ?></a>
</p>
</div>
<?php endif; ?>
<div class="wc-setup-next-steps">
<div class="wc-setup-next-steps-first">
<h2><?php _e( 'Next steps', 'woocommerce' ); ?></h2>
<h2><?php esc_html_e( 'Next steps', 'woocommerce' ); ?></h2>
<ul>
<li class="setup-product"><a class="button button-primary button-large" href="<?php echo esc_url( admin_url( 'post-new.php?post_type=product&tutorial=true' ) ); ?>"><?php _e( 'Create your first product!', 'woocommerce' ); ?></a></li>
<li class="setup-product"><a class="button button-primary button-large" href="<?php echo esc_url( admin_url( 'post-new.php?post_type=product&tutorial=true' ) ); ?>"><?php esc_html_e( 'Create your first product!', 'woocommerce' ); ?></a></li>
</ul>
</div>
<div class="wc-setup-next-steps-last">
<h2><?php _e( 'Learn more', 'woocommerce' ); ?></h2>
<ul>
<li class="video-walkthrough"><a href="https://docs.woocommerce.com/document/woocommerce-guided-tour-videos/?utm_source=setupwizard&utm_medium=product&utm_content=videos&utm_campaign=woocommerceplugin"><?php _e( 'Watch the Guided Tour videos', 'woocommerce' ); ?></a></li>
<li class="newsletter"><a href="https://woocommerce.com/woocommerce-onboarding-email/?utm_source=setupwizard&utm_medium=product&utm_content=newsletter&utm_campaign=woocommerceplugin"><?php _e( 'Get eCommerce advice in your inbox', 'woocommerce' ); ?></a></li>
<li class="learn-more"><a href="https://docs.woocommerce.com/documentation/plugins/woocommerce/getting-started/?utm_source=setupwizard&utm_medium=product&utm_content=docs&utm_campaign=woocommerceplugin"><?php _e( 'Learn more about getting started', 'woocommerce' ); ?></a></li>
<li class="video-walkthrough"><a href="https://docs.woocommerce.com/document/woocommerce-guided-tour-videos/?utm_source=setupwizard&utm_medium=product&utm_content=videos&utm_campaign=woocommerceplugin"><?php esc_html_e( 'Watch the Guided Tour videos', 'woocommerce' ); ?></a></li>
<li class="newsletter"><a href="https://woocommerce.com/woocommerce-onboarding-email/?utm_source=setupwizard&utm_medium=product&utm_content=newsletter&utm_campaign=woocommerceplugin"><?php esc_html_e( 'Get eCommerce advice in your inbox', 'woocommerce' ); ?></a></li>
<li class="learn-more"><a href="https://docs.woocommerce.com/documentation/plugins/woocommerce/getting-started/?utm_source=setupwizard&utm_medium=product&utm_content=docs&utm_campaign=woocommerceplugin"><?php esc_html_e( 'Learn more about getting started', 'woocommerce' ); ?></a></li>
</ul>
</div>
</div>

View File

@ -101,12 +101,12 @@ class WC_Admin_Webhooks_Table_List extends WP_List_Table {
if ( current_user_can( $post_type_object->cap->delete_post, $the_webhook->id ) ) {
if ( 'trash' == $post_status ) {
$actions['untrash'] = '<a aria-label="' . esc_attr__( 'Restore this item from the Trash', 'woocommerce' ) . '" href="' . wp_nonce_url( admin_url( sprintf( $post_type_object->_edit_link . '&amp;action=untrash', $the_webhook->id ) ), 'untrash-post_' . $the_webhook->id ) . '">' . __( 'Restore', 'woocommerce' ) . '</a>';
$actions['untrash'] = '<a aria-label="' . esc_attr__( 'Restore this item from the Trash', 'woocommerce' ) . '" href="' . wp_nonce_url( admin_url( sprintf( $post_type_object->_edit_link . '&amp;action=untrash', $the_webhook->id ) ), 'untrash-post_' . $the_webhook->id ) . '">' . esc_html__( 'Restore', 'woocommerce' ) . '</a>';
} elseif ( EMPTY_TRASH_DAYS ) {
$actions['trash'] = '<a class="submitdelete" aria-label="' . esc_attr( __( 'Move this item to the Trash', 'woocommerce' ) ) . '" href="' . get_delete_post_link( $the_webhook->id ) . '">' . __( 'Trash', 'woocommerce' ) . '</a>';
$actions['trash'] = '<a class="submitdelete" aria-label="' . esc_attr__( 'Move this item to the Trash', 'woocommerce' ) . '" href="' . get_delete_post_link( $the_webhook->id ) . '">' . esc_html__( 'Trash', 'woocommerce' ) . '</a>';
}
if ( 'trash' == $post_status || ! EMPTY_TRASH_DAYS ) {
$actions['delete'] = '<a class="submitdelete" aria-label="' . esc_attr( __( 'Delete this item permanently', 'woocommerce' ) ) . '" href="' . get_delete_post_link( $the_webhook->id, '', true ) . '">' . __( 'Delete permanently', 'woocommerce' ) . '</a>';
$actions['delete'] = '<a class="submitdelete" aria-label="' . esc_attr__( 'Delete this item permanently', 'woocommerce' ) . '" href="' . get_delete_post_link( $the_webhook->id, '', true ) . '">' . esc_html__( 'Delete permanently', 'woocommerce' ) . '</a>';
}
}

View File

@ -479,6 +479,10 @@ class WC_Meta_Box_Order_Data {
$field['id'] = '_billing_' . $key;
}
if ( ! isset( $_POST[ $field['id'] ] ) ) {
continue;
}
if ( is_callable( array( $order, 'set_billing_' . $key ) ) ) {
$props[ 'billing_' . $key ] = wc_clean( $_POST[ $field['id'] ] );
} else {
@ -494,6 +498,10 @@ class WC_Meta_Box_Order_Data {
$field['id'] = '_shipping_' . $key;
}
if ( ! isset( $_POST[ $field['id'] ] ) ) {
continue;
}
if ( is_callable( array( $order, 'set_shipping_' . $key ) ) ) {
$props[ 'shipping_' . $key ] = wc_clean( $_POST[ $field['id'] ] );
} else {

View File

@ -27,7 +27,7 @@ class WC_Meta_Box_Product_Reviews {
?>
<select name="rating" id="rating">
<?php for ( $rating = 1; $rating <= 5; $rating ++ ) {
echo sprintf( '<option value="%1$s"%2$s>%1$s</option>', $rating, selected( $current, $rating, false ) );
printf( '<option value="%1$s"%2$s>%1$s</option>', $rating, selected( $current, $rating, false ) );
} ?>
</select>
<?php

View File

@ -56,7 +56,7 @@ if ( ! defined( 'ABSPATH' ) ) {
<td class="line_tax" width="1%">
<div class="view">
<?php
echo ( '' != $tax_item_total ) ? wc_price( wc_round_tax_total( $tax_item_total ), array( 'currency' => $order->get_currency() ) ) : '&ndash;';
echo ( '' !== $tax_item_total ) ? wc_price( wc_round_tax_total( $tax_item_total ), array( 'currency' => $order->get_currency() ) ) : '&ndash;';
if ( $refunded = $order->get_tax_refunded_for_item( $item_id, $tax_item_id, 'fee' ) ) {
echo '<small class="refunded">-' . wc_price( $refunded, array( 'currency' => $order->get_currency() ) ) . '</small>';

View File

@ -82,7 +82,7 @@ if ( ! defined( 'ABSPATH' ) ) {
<td class="line_tax" width="1%">
<div class="view">
<?php
echo ( '' != $tax_item_total ) ? wc_price( wc_round_tax_total( $tax_item_total ), array( 'currency' => $order->get_currency() ) ) : '&ndash;';
echo ( '' !== $tax_item_total ) ? wc_price( wc_round_tax_total( $tax_item_total ), array( 'currency' => $order->get_currency() ) ) : '&ndash;';
if ( $refunded = $order->get_tax_refunded_for_item( $item_id, $tax_item_id, 'shipping' ) ) {
echo '<small class="refunded">-' . wc_price( $refunded, array( 'currency' => $order->get_currency() ) ) . '</small>';

View File

@ -56,7 +56,7 @@
?>" placeholder="<?php
/* translators: %s: WC_DELIMITER */
echo esc_attr( sprintf( __( '"%s" separate terms', 'woocommerce' ), WC_DELIMITER ) );
printf( esc_attr__( '"%s" separate terms', 'woocommerce' ), WC_DELIMITER );
?>" />
@ -66,7 +66,7 @@
<?php else : ?>
<textarea name="attribute_values[<?php echo $i; ?>]" cols="5" rows="5" placeholder="<?php echo esc_attr( sprintf( __( 'Enter some text, or some attributes by "%s" separating values.', 'woocommerce' ), WC_DELIMITER ) ); ?>"><?php echo esc_textarea( wc_implode_text_attributes( $attribute->get_options() ) ); ?></textarea>
<textarea name="attribute_values[<?php echo $i; ?>]" cols="5" rows="5" placeholder="<?php printf( esc_attr__( 'Enter some text, or some attributes by "%s" separating values.', 'woocommerce' ), WC_DELIMITER ); ?>"><?php echo esc_textarea( wc_implode_text_attributes( $attribute->get_options() ) ); ?></textarea>
<?php endif; ?>
</td>

View File

@ -16,7 +16,7 @@
if ( wc_product_dimensions_enabled() ) {
?><p class="form-field dimensions_field">
<label for="product_length"><?php echo __( 'Dimensions', 'woocommerce' ) . ' (' . get_option( 'woocommerce_dimension_unit' ) . ')'; ?></label>
<label for="product_length"><?php printf( __( 'Dimensions (%s)', 'woocommerce' ), get_option( 'woocommerce_dimension_unit' ) ); ?></label>
<span class="wrap">
<input id="product_length" placeholder="<?php esc_attr_e( 'Length', 'woocommerce' ); ?>" class="input-text wc_input_decimal" size="6" type="text" name="_length" value="<?php echo esc_attr( wc_format_localized_decimal( $product_object->get_length( 'edit' ) ) ); ?>" />
<input placeholder="<?php esc_attr_e( 'Width', 'woocommerce' ); ?>" class="input-text wc_input_decimal" size="6" type="text" name="_width" value="<?php echo esc_attr( wc_format_localized_decimal( $product_object->get_width( 'edit' ) ) ); ?>" />

View File

@ -18,7 +18,7 @@
$selected_value = isset( $default_attributes[ sanitize_title( $attribute->get_name() ) ] ) ? $default_attributes[ sanitize_title( $attribute->get_name() ) ] : '';
?>
<select name="default_attribute_<?php echo sanitize_title( $attribute->get_name() ); ?>" data-current="<?php echo esc_attr( $selected_value ); ?>">
<option value=""><?php echo esc_html( sprintf( __( 'No default %s&hellip;', 'woocommerce' ), wc_attribute_label( $attribute->get_name() ) ) ); ?></option>
<option value=""><?php printf( esc_html__( 'No default %s&hellip;', 'woocommerce' ), wc_attribute_label( $attribute->get_name() ) ); ?></option>
<?php if ( $attribute->is_taxonomy() ) : ?>
<?php foreach ( $attribute->get_terms() as $option ) : ?>
<option <?php selected( $selected_value, $option->slug ); ?> value="<?php echo esc_attr( $option->slug ); ?>"><?php echo esc_html( apply_filters( 'woocommerce_variation_option_name', $option->name ) ); ?></option>

View File

@ -29,7 +29,7 @@ if ( ! defined( 'ABSPATH' ) ) {
<select name="attribute_<?php echo sanitize_title( $attribute->get_name() ) . "[{$loop}]"; ?>">
<option value=""><?php
/* translators: %s: attribute label */
echo sprintf( __( 'Any %s&hellip;', 'woocommerce' ), esc_html( wc_attribute_label( $attribute->get_name() ) ) );
printf( esc_html__( 'Any %s&hellip;', 'woocommerce' ), wc_attribute_label( $attribute->get_name() ) );
?></option>
<?php if ( $attribute->is_taxonomy() ) : ?>
<?php foreach ( $attribute->get_terms() as $option ) : ?>
@ -50,7 +50,7 @@ if ( ! defined( 'ABSPATH' ) ) {
<div class="woocommerce_variable_attributes wc-metabox-content" style="display: none;">
<div class="data">
<p class="form-row form-row-first upload_image">
<a href="#" class="upload_image_button tips <?php echo $variation_object->get_image_id( 'edit' ) ? 'remove' : ''; ?>" data-tip="<?php echo $variation_object->get_image_id( 'edit' ) ? __( 'Remove this image', 'woocommerce' ) : __( 'Upload an image', 'woocommerce' ); ?>" rel="<?php echo esc_attr( $variation_id ); ?>">
<a href="#" class="upload_image_button tips <?php echo $variation_object->get_image_id( 'edit' ) ? 'remove' : ''; ?>" data-tip="<?php echo $variation_object->get_image_id( 'edit' ) ? esc_attr__( 'Remove this image', 'woocommerce' ) : esc_attr__( 'Upload an image', 'woocommerce' ); ?>" rel="<?php echo esc_attr( $variation_id ); ?>">
<img src="<?php echo $variation_object->get_image_id( 'edit' ) ? esc_url( wp_get_attachment_thumb_url( $variation_object->get_image_id( 'edit' ) ) ) : esc_url( wc_placeholder_img_src() ); ?>" /><input type="hidden" name="upload_image_id[<?php echo $loop; ?>]" class="upload_image_id" value="<?php echo esc_attr( $variation_object->get_image_id( 'edit' ) ); ?>" />
</a>
</p>
@ -61,7 +61,7 @@ if ( ! defined( 'ABSPATH' ) ) {
'name' => "variable_sku[{$loop}]",
'value' => $variation_object->get_sku( 'edit' ),
'placeholder' => $variation_object->get_sku(),
'label' => '<abbr title="' . __( 'Stock Keeping Unit', 'woocommerce' ) . '">' . __( 'SKU', 'woocommerce' ) . '</abbr>',
'label' => '<abbr title="' . esc_attr__( 'Stock Keeping Unit', 'woocommerce' ) . '">' . esc_html__( 'SKU', 'woocommerce' ) . '</abbr>',
'desc_tip' => true,
'description' => __( 'SKU refers to a Stock-keeping unit, a unique identifier for each distinct product and service that can be purchased.', 'woocommerce' ),
'wrapper_class' => 'form-row form-row-last',

View File

@ -325,7 +325,7 @@ class WC_Settings_Payment_Gateways extends WC_Settings_Page {
case 'status' :
echo '<td class="status">';
echo ( 'yes' === $gateway->enabled ) ? '<span class="status-enabled tips" data-tip="' . __( 'Yes', 'woocommerce' ) . '">' . __( 'Yes', 'woocommerce' ) . '</span>' : '-';
echo ( 'yes' === $gateway->enabled ) ? '<span class="status-enabled tips" data-tip="' . esc_attr__( 'Yes', 'woocommerce' ) . '">' . esc_html__( 'Yes', 'woocommerce' ) . '</span>' : '-';
echo '</td>';
break;

View File

@ -269,11 +269,11 @@ class WC_Settings_Emails extends WC_Settings_Page {
echo '<td class="wc-email-settings-table-' . esc_attr( $key ) . '">';
if ( $email->is_manual() ) {
echo '<span class="status-manual tips" data-tip="' . __( 'Manually sent', 'woocommerce' ) . '">' . __( 'Manual', 'woocommerce' ) . '</span>';
echo '<span class="status-manual tips" data-tip="' . esc_attr__( 'Manually sent', 'woocommerce' ) . '">' . esc_html__( 'Manual', 'woocommerce' ) . '</span>';
} elseif ( $email->is_enabled() ) {
echo '<span class="status-enabled tips" data-tip="' . __( 'Enabled', 'woocommerce' ) . '">' . __( 'Yes', 'woocommerce' ) . '</span>';
echo '<span class="status-enabled tips" data-tip="' . esc_attr__( 'Enabled', 'woocommerce' ) . '">' . esc_html__( 'Yes', 'woocommerce' ) . '</span>';
} else {
echo '<span class="status-disabled tips" data-tip="' . __( 'Disabled', 'woocommerce' ) . '">-</span>';
echo '<span class="status-disabled tips" data-tip="' . esc_attr__( 'Disabled', 'woocommerce' ) . '">-</span>';
}
echo '</td>';
@ -285,7 +285,7 @@ class WC_Settings_Emails extends WC_Settings_Page {
break;
case 'actions' :
echo '<td class="wc-email-settings-table-' . esc_attr( $key ) . '">
<a class="button alignright tips" data-tip="' . __( 'Configure', 'woocommerce' ) . '" href="' . admin_url( 'admin.php?page=wc-settings&tab=email&section=' . strtolower( $email_key ) ) . '">' . __( 'Configure', 'woocommerce' ) . '</a>
<a class="button alignright tips" data-tip="' . esc_attr__( 'Configure', 'woocommerce' ) . '" href="' . admin_url( 'admin.php?page=wc-settings&tab=email&section=' . strtolower( $email_key ) ) . '">' . esc_html__( 'Configure', 'woocommerce' ) . '</a>
</td>';
break;
default :

View File

@ -50,7 +50,7 @@ if ( ! defined( 'ABSPATH' ) ) {
</table>
<script type="text/html" id="tmpl-wc-tax-table-row">
<tr class="tips" data-tip="<?php echo esc_attr( sprintf( __( 'Tax rate ID: %s', 'woocommerce' ), '{{ data.tax_rate_id }}' ) ); ?>" data-id="{{ data.tax_rate_id }}">
<tr class="tips" data-tip="<?php printf( esc_attr__( 'Tax rate ID: %s', 'woocommerce' ), '{{ data.tax_rate_id }}' ); ?>" data-id="{{ data.tax_rate_id }}">
<td class="country">
<input type="text" value="{{ data.tax_rate_country }}" placeholder="*" name="tax_rate_country[{{ data.tax_rate_id }}]" class="wc_input_country_iso" data-attribute="tax_rate_country" style="text-transform:uppercase" />
</td>

View File

@ -36,7 +36,7 @@ if ( ! defined( 'ABSPATH' ) ) {
</span>
</label>
<label class="change-input">
<input type="text" name="_regular_price" class="text regular_price" placeholder="<?php echo sprintf( __( 'Enter price (%s)', 'woocommerce' ), get_woocommerce_currency_symbol() ); ?>" value="" />
<input type="text" name="_regular_price" class="text regular_price" placeholder="<?php printf( esc_attr__( 'Enter price (%s)', 'woocommerce' ), get_woocommerce_currency_symbol() ); ?>" value="" />
</label>
</div>
@ -61,7 +61,7 @@ if ( ! defined( 'ABSPATH' ) ) {
</span>
</label>
<label class="change-input">
<input type="text" name="_sale_price" class="text sale_price" placeholder="<?php echo sprintf( __( 'Enter sale price (%s)', 'woocommerce' ), get_woocommerce_currency_symbol() ); ?>" value="" />
<input type="text" name="_sale_price" class="text sale_price" placeholder="<?php printf( esc_attr__( 'Enter sale price (%s)', 'woocommerce' ), get_woocommerce_currency_symbol() ); ?>" value="" />
</label>
</div>
@ -130,7 +130,7 @@ if ( ! defined( 'ABSPATH' ) ) {
</span>
</label>
<label class="change-input">
<input type="text" name="_weight" class="text weight" placeholder="<?php echo sprintf( __( '%1$s (%2$s)', 'woocommerce' ), wc_format_localized_decimal( 0 ), get_option( 'woocommerce_weight_unit' ) ); ?>" value="">
<input type="text" name="_weight" class="text weight" placeholder="<?php printf( esc_attr__( '%1$s (%2$s)', 'woocommerce' ), wc_format_localized_decimal( 0 ), get_option( 'woocommerce_weight_unit' ) ); ?>" value="">
</label>
</div>
<?php endif; ?>
@ -154,9 +154,9 @@ if ( ! defined( 'ABSPATH' ) ) {
</span>
</label>
<label class="change-input">
<input type="text" name="_length" class="text length" placeholder="<?php echo sprintf( __( 'Length (%s)', 'woocommerce' ), get_option( 'woocommerce_dimension_unit' ) ); ?>" value="">
<input type="text" name="_width" class="text width" placeholder="<?php echo sprintf( __( 'Width (%s)', 'woocommerce' ), get_option( 'woocommerce_dimension_unit' ) ); ?>" value="">
<input type="text" name="_height" class="text height" placeholder="<?php echo sprintf( __( 'Height (%s)', 'woocommerce' ), get_option( 'woocommerce_dimension_unit' ) ); ?>" value="">
<input type="text" name="_length" class="text length" placeholder="<?php printf( esc_attr__( 'Length (%s)', 'woocommerce' ), get_option( 'woocommerce_dimension_unit' ) ); ?>" value="">
<input type="text" name="_width" class="text width" placeholder="<?php printf( esc_attr__( 'Width (%s)', 'woocommerce' ), get_option( 'woocommerce_dimension_unit' ) ); ?>" value="">
<input type="text" name="_height" class="text height" placeholder="<?php printf( esc_attr__( 'Height (%s)', 'woocommerce' ), get_option( 'woocommerce_dimension_unit' ) ); ?>" value="">
</label>
</div>
<?php endif; ?>
@ -218,7 +218,7 @@ if ( ! defined( 'ABSPATH' ) ) {
<span class="input-text-wrap">
<select class="stock_status" name="_stock_status">
<?php
echo '<option value="">' . __( '— No Change —', 'woocommerce' ) . '</option>';
echo '<option value="">' . esc_html__( '— No Change —', 'woocommerce' ) . '</option>';
foreach ( wc_get_product_stock_status_options() as $key => $value ) {
echo '<option value="' . esc_attr( $key ) . '">' . $value . '</option>';
@ -274,7 +274,7 @@ if ( ! defined( 'ABSPATH' ) ) {
<span class="input-text-wrap">
<select class="backorders" name="_backorders">
<?php
echo '<option value="">' . __( '— No Change —', 'woocommerce' ) . '</option>';
echo '<option value="">' . esc_html__( '— No Change —', 'woocommerce' ) . '</option>';
foreach ( wc_get_product_backorder_options() as $key => $value ) {
echo '<option value="' . esc_attr( $key ) . '">' . $value . '</option>';

View File

@ -210,7 +210,7 @@ class WC_REST_Settings_Controller extends WC_REST_Controller {
),
),
'description' => array(
'description' => __( 'A human readable translation wrapped description. Meant to be used in interfaces', 'woocommerce' ),
'description' => __( 'A human readable translation wrapped description. Meant to be used in interfaces.', 'woocommerce' ),
'type' => 'string',
'arg_options' => array(
'sanitize_callback' => 'sanitize_text_field',

View File

@ -358,7 +358,7 @@ class WC_Cart {
$weight = 0;
foreach ( $this->get_cart() as $cart_item_key => $values ) {
$weight += $values['data']->get_weight() * $values['quantity'];
$weight += (float) $values['data']->get_weight() * $values['quantity'];
}
return apply_filters( 'woocommerce_cart_contents_weight', $weight );

View File

@ -709,8 +709,13 @@ class WC_Coupon extends WC_Legacy_Coupon {
*/
public function increase_usage_count( $used_by = '' ) {
if ( $this->get_id() && $this->data_store ) {
$this->set_prop( 'usage_count', ( $this->get_usage_count( 'edit' ) + 1 ) );
$this->data_store->increase_usage_count( $this, $used_by );
$new_count = $this->data_store->increase_usage_count( $this, $used_by );
// Bypass set_prop and remove pending changes since the data store saves the count already.
$this->data['usage_count'] = $new_count;
if ( isset( $this->changes['usage_count'] ) ) {
unset( $this->changes['usage_count'] );
}
}
}
@ -721,8 +726,13 @@ class WC_Coupon extends WC_Legacy_Coupon {
*/
public function decrease_usage_count( $used_by = '' ) {
if ( $this->get_id() && $this->get_usage_count() > 0 && $this->data_store ) {
$this->set_prop( 'usage_count', ( $this->get_usage_count( 'edit' ) - 1 ) );
$this->data_store->decrease_usage_count( $this, $used_by );
$new_count = $this->data_store->decrease_usage_count( $this, $used_by );
// Bypass set_prop and remove pending changes since the data store saves the count already.
$this->data['usage_count'] = $new_count;
if ( isset( $this->changes['usage_count'] ) ) {
unset( $this->changes['usage_count'] );
}
}
}

View File

@ -75,7 +75,9 @@ class WC_Download_Handler {
$count = $download->get_download_count();
$remaining = $download->get_downloads_remaining();
$download->set_download_count( $count + 1 );
$download->set_downloads_remaining( $remaining - 1 );
if ( '' !== $remaining ) {
$download->set_downloads_remaining( $remaining - 1 );
}
$download->save();
self::download( $product->get_file_download_path( $download->get_download_id() ), $download->get_product_id() );
@ -392,7 +394,7 @@ class WC_Download_Handler {
*/
private static function download_error( $message, $title = '', $status = 404 ) {
if ( ! strstr( $message, '<a ' ) ) {
$message .= ' <a href="' . esc_url( wc_get_page_permalink( 'shop' ) ) . '" class="wc-forward">' . __( 'Go to shop', 'woocommerce' ) . '</a>';
$message .= ' <a href="' . esc_url( wc_get_page_permalink( 'shop' ) ) . '" class="wc-forward">' . esc_html__( 'Go to shop', 'woocommerce' ) . '</a>';
}
wp_die( $message, $title, array( 'response' => $status ) );
}

View File

@ -556,7 +556,7 @@ class WC_Frontend_Scripts {
return array(
'min_password_strength' => apply_filters( 'woocommerce_min_password_strength', 3 ),
'i18n_password_error' => esc_attr__( 'Please enter a stronger password.', 'woocommerce' ),
'i18n_password_hint' => esc_attr__( 'The password should be at least seven characters long. To make it stronger, use upper and lower case letters, numbers and symbols like ! " ? $ % ^ &amp; ).', 'woocommerce' ),
'i18n_password_hint' => esc_attr( wp_get_password_hint() ),
);
break;
}

View File

@ -882,7 +882,7 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta (
*/
public static function plugin_action_links( $links ) {
$action_links = array(
'settings' => '<a href="' . admin_url( 'admin.php?page=wc-settings' ) . '" aria-label="' . esc_attr( __( 'View WooCommerce settings', 'woocommerce' ) ) . '">' . __( 'Settings', 'woocommerce' ) . '</a>',
'settings' => '<a href="' . admin_url( 'admin.php?page=wc-settings' ) . '" aria-label="' . esc_attr__( 'View WooCommerce settings', 'woocommerce' ) . '">' . esc_html__( 'Settings', 'woocommerce' ) . '</a>',
);
return array_merge( $action_links, $links );
@ -898,9 +898,9 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta (
public static function plugin_row_meta( $links, $file ) {
if ( WC_PLUGIN_BASENAME == $file ) {
$row_meta = array(
'docs' => '<a href="' . esc_url( apply_filters( 'woocommerce_docs_url', 'https://docs.woocommerce.com/documentation/plugins/woocommerce/' ) ) . '" aria-label="' . esc_attr( __( 'View WooCommerce documentation', 'woocommerce' ) ) . '">' . __( 'Docs', 'woocommerce' ) . '</a>',
'apidocs' => '<a href="' . esc_url( apply_filters( 'woocommerce_apidocs_url', 'https://docs.woocommerce.com/wc-apidocs/' ) ) . '" aria-label="' . esc_attr( __( 'View WooCommerce API docs', 'woocommerce' ) ) . '">' . __( 'API docs', 'woocommerce' ) . '</a>',
'support' => '<a href="' . esc_url( apply_filters( 'woocommerce_support_url', 'https://woocommerce.com/my-account/tickets/' ) ) . '" aria-label="' . esc_attr( __( 'Visit premium customer support', 'woocommerce' ) ) . '">' . __( 'Premium support', 'woocommerce' ) . '</a>',
'docs' => '<a href="' . esc_url( apply_filters( 'woocommerce_docs_url', 'https://docs.woocommerce.com/documentation/plugins/woocommerce/' ) ) . '" aria-label="' . esc_attr__( 'View WooCommerce documentation', 'woocommerce' ) . '">' . esc_html__( 'Docs', 'woocommerce' ) . '</a>',
'apidocs' => '<a href="' . esc_url( apply_filters( 'woocommerce_apidocs_url', 'https://docs.woocommerce.com/wc-apidocs/' ) ) . '" aria-label="' . esc_attr__( 'View WooCommerce API docs', 'woocommerce' ) . '">' . esc_html__( 'API docs', 'woocommerce' ) . '</a>',
'support' => '<a href="' . esc_url( apply_filters( 'woocommerce_support_url', 'https://woocommerce.com/my-account/tickets/' ) ) . '" aria-label="' . esc_attr__( 'Visit premium customer support', 'woocommerce' ) . '">' . esc_html__( 'Premium support', 'woocommerce' ) . '</a>',
);
return array_merge( $links, $row_meta );

View File

@ -177,6 +177,7 @@ class WC_Order_Item extends WC_Data implements ArrayAccess {
/**
* Expands things like term slugs before return.
*
* @param string $hideprefix (default: _)
* @return array
*/
@ -187,7 +188,7 @@ class WC_Order_Item extends WC_Data implements ArrayAccess {
$product = is_callable( array( $this, 'get_product' ) ) ? $this->get_product() : false;
foreach ( $meta_data as $meta ) {
if ( "" === $meta->value || is_serialized( $meta->value ) || ( $hideprefix_length && substr( $meta->key, 0, $hideprefix_length ) === $hideprefix ) ) {
if ( empty( $meta->id ) || "" === $meta->value || is_array( $meta->value ) || ( $hideprefix_length && substr( $meta->key, 0, $hideprefix_length ) === $hideprefix ) ) {
continue;
}
@ -250,6 +251,7 @@ class WC_Order_Item extends WC_Data implements ArrayAccess {
if ( is_callable( array( $this, $setter ) ) ) {
$this->$setter( $value );
}
return;
}
$this->update_meta_data( $offset, $value );

View File

@ -226,7 +226,7 @@ class WC_Order extends WC_Abstract_Order {
public function set_status( $new_status, $note = '', $manual_update = false ) {
$result = parent::set_status( $new_status );
if ( ! empty( $result['from'] ) && $result['from'] !== $result['to'] ) {
if ( true === $this->object_read && ! empty( $result['from'] ) && $result['from'] !== $result['to'] ) {
$this->status_transition = array(
'from' => ! empty( $this->status_transition['from'] ) ? $this->status_transition['from'] : $result['from'],
'to' => $result['to'],
@ -253,11 +253,10 @@ class WC_Order extends WC_Abstract_Order {
* `payment_complete` method.
*
* @since 2.7.0
* @param $date_paid What to set date paid to. Defaults to current time.
*/
public function maybe_set_date_paid( $date_paid = '' ) {
if ( ! $this->get_date_paid( 'edit' ) && $this->has_status( array( 'processing', 'completed' ) ) ) {
$this->set_date_paid( $date_paid ? $date_paid : current_time( 'timestamp', true ) );
public function maybe_set_date_paid() {
if ( ! $this->get_date_paid( 'edit' ) && $this->has_status( apply_filters( 'woocommerce_payment_complete_order_status', $this->needs_processing() ? 'processing' : 'completed', $this->get_id() ) ) ) {
$this->set_date_paid( current_time( 'timestamp' ) );
}
}
@ -729,7 +728,13 @@ class WC_Order extends WC_Abstract_Order {
* @return WC_DateTime|NULL object if the date is set or null if there is no date.
*/
public function get_date_paid( $context = 'view' ) {
return $this->get_prop( 'date_paid', $context );
$date_paid = $this->get_prop( 'date_paid', $context );
if ( 'view' === $context && ! $date_paid && version_compare( $this->get_version( 'edit' ), '2.7', '<' ) && $this->has_status( apply_filters( 'woocommerce_payment_complete_order_status', $this->needs_processing() ? 'processing' : 'completed', $this->get_id() ) ) ) {
// In view context, return a date if missing.
$date_paid = $this->get_date_created( 'edit' );
}
return $date_paid;
}
/**
@ -1292,7 +1297,7 @@ class WC_Order extends WC_Abstract_Order {
* @since 2.7.0
* @return bool
*/
protected function needs_processing() {
public function needs_processing() {
$needs_processing = false;
if ( sizeof( $this->get_items() ) > 0 ) {

View File

@ -101,21 +101,10 @@ abstract class Abstract_WC_Order_Data_Store_CPT extends WC_Data_Store_WP impleme
/**
* In older versions, discounts may have been stored differently.
* Update them now so if the object is saved, the correct values are
* stored.
* @todo When/if meta is flattened, handle this in the migration script.
* stored. @todo When meta is flattened, handle this during migration.
*/
if ( ! $order->get_version( 'edit' ) || version_compare( $order->get_version( 'edit' ), '2.3.7', '<' ) ) {
if ( $order->get_prices_include_tax( 'edit' ) ) {
$order->set_discount_total( (double) get_post_meta( $order->get_id(), '_cart_discount', true ) - (double) get_post_meta( $order->get_id(), '_cart_discount_tax', true ) );
}
}
/**
* In older versions, paid date may not have been set.
* @todo When/if meta is flattened, handle this in the migration script.
*/
if ( ! $order->get_version( 'edit' ) || version_compare( $order->get_version( 'edit' ), '2.7', '<' ) ) {
$order->maybe_set_date_paid( $order->get_date_created( 'edit' ) );
if ( version_compare( $order->get_version( 'edit' ), '2.3.7', '<' ) && $order->get_prices_include_tax( 'edit' ) ) {
$order->set_discount_total( (double) get_post_meta( $order->get_id(), '_cart_discount', true ) - (double) get_post_meta( $order->get_id(), '_cart_discount_tax', true ) );
}
}
@ -249,6 +238,7 @@ abstract class Abstract_WC_Order_Data_Store_CPT extends WC_Data_Store_WP impleme
);
$props_to_update = $this->get_props_to_update( $order, $meta_key_to_props );
foreach ( $props_to_update as $meta_key => $prop ) {
$value = $order->{"get_$prop"}( 'edit' );

View File

@ -233,13 +233,15 @@ class WC_Coupon_Data_Store_CPT extends WC_Data_Store_WP implements WC_Coupon_Dat
* @since 2.7.0
* @param WC_Coupon
* @param string $used_by Either user ID or billing email
* @return int New usage count
*/
public function increase_usage_count( &$coupon, $used_by = '' ) {
update_post_meta( $coupon->get_id(), 'usage_count', $coupon->get_usage_count( 'edit' ) );
$new_count = $this->update_usage_count_meta( $coupon, 'increase' );
if ( $used_by ) {
add_post_meta( $coupon->get_id(), '_used_by', strtolower( $used_by ) );
$coupon->set_used_by( (array) get_post_meta( $coupon->get_id(), '_used_by' ) );
}
return $new_count;
}
/**
@ -248,10 +250,11 @@ class WC_Coupon_Data_Store_CPT extends WC_Data_Store_WP implements WC_Coupon_Dat
* @since 2.7.0
* @param WC_Coupon
* @param string $used_by Either user ID or billing email
* @return int New usage count
*/
public function decrease_usage_count( &$coupon, $used_by = '' ) {
global $wpdb;
update_post_meta( $coupon->get_id(), 'usage_count', $coupon->get_usage_count() );
$new_count = $this->update_usage_count_meta( $coupon, 'decrease' );
if ( $used_by ) {
/**
* We're doing this the long way because `delete_post_meta( $id, $key, $value )` deletes.
@ -263,6 +266,27 @@ class WC_Coupon_Data_Store_CPT extends WC_Data_Store_WP implements WC_Coupon_Dat
$coupon->set_used_by( (array) get_post_meta( $coupon->get_id(), '_used_by' ) );
}
}
return $new_count;
}
/**
* Increase or decrease the usage count for a coupon by 1.
*
* @since 2.7.0
* @param WC_Coupon
* @param string $operation 'increase' or 'decrease'
* @return int New usage count
*/
private function update_usage_count_meta( &$coupon, $operation = 'increase' ) {
global $wpdb;
$id = $coupon->get_id();
$operator = ( 'increase' === $operation ) ? '+' : '-';
add_post_meta( $id, 'usage_count', $coupon->get_usage_count( 'edit' ), true );
$wpdb->query( $wpdb->prepare( "UPDATE $wpdb->postmeta SET meta_value = meta_value {$operator} 1 WHERE meta_key = 'usage_count' AND post_id = %d;", $id ) );
// Get the latest value direct from the DB, instead of possibly the WP meta cache.
return (int) $wpdb->get_var( $wpdb->prepare( "SELECT meta_value FROM $wpdb->postmeta WHERE meta_key = 'usage_count' AND post_id = %d;", $id ) );
}
/**

View File

@ -141,7 +141,14 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement
* @param WC_Order $order
*/
public function update( &$order ) {
// Before updating, ensure date paid is set if missing.
if ( ! $order->get_date_paid( 'edit' ) && version_compare( $order->get_version( 'edit' ), '2.7', '<' ) && $order->has_status( apply_filters( 'woocommerce_payment_complete_order_status', $order->needs_processing() ? 'processing' : 'completed', $order->get_id() ) ) ) {
$order->set_date_paid( $order->get_date_created( 'edit' ) );
}
// Update the order.
parent::update( $order );
do_action( 'woocommerce_update_order', $order->get_id() );
}

View File

@ -51,17 +51,17 @@ class WC_Payment_Gateway_CC extends WC_Payment_Gateway {
$fields = array();
$cvc_field = '<p class="form-row form-row-last">
<label for="' . esc_attr( $this->id ) . '-card-cvc">' . __( 'Card code', 'woocommerce' ) . ' <span class="required">*</span></label>
<label for="' . esc_attr( $this->id ) . '-card-cvc">' . esc_html__( 'Card code', 'woocommerce' ) . ' <span class="required">*</span></label>
<input id="' . esc_attr( $this->id ) . '-card-cvc" class="input-text wc-credit-card-form-card-cvc" inputmode="numeric" autocomplete="off" autocorrect="no" autocapitalize="no" spellcheck="no" type="tel" maxlength="4" placeholder="' . esc_attr__( 'CVC', 'woocommerce' ) . '" ' . $this->field_name( 'card-cvc' ) . ' style="width:100px" />
</p>';
$default_fields = array(
'card-number-field' => '<p class="form-row form-row-wide">
<label for="' . esc_attr( $this->id ) . '-card-number">' . __( 'Card number', 'woocommerce' ) . ' <span class="required">*</span></label>
<label for="' . esc_attr( $this->id ) . '-card-number">' . esc_html__( 'Card number', 'woocommerce' ) . ' <span class="required">*</span></label>
<input id="' . esc_attr( $this->id ) . '-card-number" class="input-text wc-credit-card-form-card-number" inputmode="numeric" autocomplete="cc-number" autocorrect="no" autocapitalize="no" spellcheck="no" type="tel" placeholder="&bull;&bull;&bull;&bull; &bull;&bull;&bull;&bull; &bull;&bull;&bull;&bull; &bull;&bull;&bull;&bull;" ' . $this->field_name( 'card-number' ) . ' />
</p>',
'card-expiry-field' => '<p class="form-row form-row-first">
<label for="' . esc_attr( $this->id ) . '-card-expiry">' . __( 'Expiry (MM/YY)', 'woocommerce' ) . ' <span class="required">*</span></label>
<label for="' . esc_attr( $this->id ) . '-card-expiry">' . esc_html__( 'Expiry (MM/YY)', 'woocommerce' ) . ' <span class="required">*</span></label>
<input id="' . esc_attr( $this->id ) . '-card-expiry" class="input-text wc-credit-card-form-card-expiry" inputmode="numeric" autocomplete="cc-exp" autocorrect="no" autocapitalize="no" spellcheck="no" type="tel" placeholder="' . esc_attr__( 'MM / YY', 'woocommerce' ) . '" ' . $this->field_name( 'card-expiry' ) . ' />
</p>',
);

View File

@ -37,11 +37,11 @@ class WC_Payment_Gateway_eCheck extends WC_Payment_Gateway {
$default_fields = array(
'routing-number' => '<p class="form-row form-row-first">
<label for="' . esc_attr( $this->id ) . '-routing-number">' . __( 'Routing number', 'woocommerce' ) . ' <span class="required">*</span></label>
<label for="' . esc_attr( $this->id ) . '-routing-number">' . esc_html__( 'Routing number', 'woocommerce' ) . ' <span class="required">*</span></label>
<input id="' . esc_attr( $this->id ) . '-routing-number" class="input-text wc-echeck-form-routing-number" type="text" maxlength="9" autocomplete="off" placeholder="&bull;&bull;&bull;&bull;&bull;&bull;&bull;&bull;&bull;" name="' . esc_attr( $this->id ) . '-routing-number" />
</p>',
'account-number' => '<p class="form-row form-row-wide">
<label for="' . esc_attr( $this->id ) . '-account-number">' . __( 'Account number', 'woocommerce' ) . ' <span class="required">*</span></label>
<label for="' . esc_attr( $this->id ) . '-account-number">' . esc_html__( 'Account number', 'woocommerce' ) . ' <span class="required">*</span></label>
<input id="' . esc_attr( $this->id ) . '-account-number" class="input-text wc-echeck-form-account-number" type="text" autocomplete="off" name="' . esc_attr( $this->id ) . '-account-number" maxlength="17" />
</p>',
);

View File

@ -458,15 +458,16 @@ abstract class WC_Abstract_Legacy_Order extends WC_Data {
}
/**
* has_meta function for order items.
* has_meta function for order items. This is different to the WC_Data
* version and should be removed in future versions.
*
* @param string $order_item_id
* @deprecated
* @return array of meta data.
*/
public function has_meta( $order_item_id ) {
global $wpdb;
wc_deprecated_function( 'has_meta', '2.7', 'WC_Order_item::get_meta_data' );
wc_deprecated_function( 'WC_Order::has_meta( $order_item_id )', '2.7', 'WC_Order_item::get_meta_data' );
return $wpdb->get_results( $wpdb->prepare( "SELECT meta_key, meta_value, meta_id, order_item_id
FROM {$wpdb->prefix}woocommerce_order_itemmeta WHERE order_item_id = %d

View File

@ -30,6 +30,7 @@ abstract class WC_Legacy_Coupon extends WC_Data {
'type',
'discount_type',
'amount',
'coupon_amount',
'code',
'individual_use',
'product_ids',
@ -82,6 +83,7 @@ abstract class WC_Legacy_Coupon extends WC_Data {
$value = $this->get_discount_type();
break;
case 'amount' :
case 'coupon_amount' :
$value = $this->get_amount();
break;
case 'code' :

View File

@ -247,7 +247,14 @@ class WC_Shortcode_My_Account {
$user_data = get_user_by( 'email', $login );
}
do_action( 'lostpassword_post' );
$errors = new WP_Error();
do_action( 'lostpassword_post', $errors );
if ( $errors->get_error_code() ) {
wc_add_notice( $allow->get_error_message(), 'error' );
return false;
}
if ( ! $user_data ) {
wc_add_notice( __( 'Invalid username or email.', 'woocommerce' ), 'error' );

View File

@ -816,10 +816,10 @@ function wc_update_coupon_usage_counts( $order_id ) {
switch ( $action ) {
case 'reduce' :
$coupon->dcr_usage_count( $used_by );
$coupon->decrease_usage_count( $used_by );
break;
case 'increase' :
$coupon->inc_usage_count( $used_by );
$coupon->increase_usage_count( $used_by );
break;
}
}

View File

@ -98,8 +98,8 @@ function wc_delete_order_item( $item_id ) {
function wc_update_order_item_meta( $item_id, $meta_key, $meta_value, $prev_value = '' ) {
$data_store = WC_Data_Store::load( 'order-item' );
if ( $data_store->update_metadata( $item_id, $meta_key, $meta_value, $prev_value ) ) {
$cache_key = WC_Cache_Helper::get_cache_prefix( 'orders' ) . 'item_meta_array_' . $item_id;
wp_cache_delete( $cache_key, 'orders' );
$cache_key = WC_Cache_Helper::get_cache_prefix( 'order-items' ) . 'object_meta_' . $item_id;
wp_cache_delete( $cache_key, 'order-items' );
return true;
}
return false;
@ -118,8 +118,8 @@ function wc_update_order_item_meta( $item_id, $meta_key, $meta_value, $prev_valu
function wc_add_order_item_meta( $item_id, $meta_key, $meta_value, $unique = false ) {
$data_store = WC_Data_Store::load( 'order-item' );
if ( $meta_id = $data_store->add_metadata( $item_id, $meta_key, $meta_value, $unique ) ) {
$cache_key = WC_Cache_Helper::get_cache_prefix( 'orders' ) . 'item_meta_array_' . $item_id;
wp_cache_delete( $cache_key, 'orders' );
$cache_key = WC_Cache_Helper::get_cache_prefix( 'order-items' ) . 'object_meta_' . $item_id;
wp_cache_delete( $cache_key, 'order-items' );
return $meta_id;
}
return 0;
@ -138,8 +138,8 @@ function wc_add_order_item_meta( $item_id, $meta_key, $meta_value, $unique = fal
function wc_delete_order_item_meta( $item_id, $meta_key, $meta_value = '', $delete_all = false ) {
$data_store = WC_Data_Store::load( 'order-item' );
if ( $data_store->delete_metadata( $item_id, $meta_key, $meta_value, $delete_all ) ) {
$cache_key = WC_Cache_Helper::get_cache_prefix( 'orders' ) . 'item_meta_array_' . $item_id;
wp_cache_delete( $cache_key, 'orders' );
$cache_key = WC_Cache_Helper::get_cache_prefix( 'order-items' ) . 'object_meta_' . $item_id;
wp_cache_delete( $cache_key, 'order-items' );
return true;
}
return false;

View File

@ -162,7 +162,7 @@ function wc_products_rss_feed() {
if ( $term ) {
$feed = add_query_arg( 'product_cat', $term->slug, get_post_type_archive_feed_link( 'product' ) );
echo '<link rel="alternate" type="application/rss+xml" title="' . esc_attr( sprintf( __( 'New products added to %s', 'woocommerce' ), $term->name ) ) . '" href="' . esc_url( $feed ) . '" />';
echo '<link rel="alternate" type="application/rss+xml" title="' . sprintf( esc_attr__( 'New products added to %s', 'woocommerce' ), $term->name ) . '" href="' . esc_url( $feed ) . '" />';
}
} elseif ( is_tax( 'product_tag' ) ) {
@ -170,7 +170,7 @@ function wc_products_rss_feed() {
if ( $term ) {
$feed = add_query_arg( 'product_tag', $term->slug, get_post_type_archive_feed_link( 'product' ) );
echo '<link rel="alternate" type="application/rss+xml" title="' . sprintf( __( 'New products tagged %s', 'woocommerce' ), urlencode( $term->name ) ) . '" href="' . esc_url( $feed ) . '" />';
echo '<link rel="alternate" type="application/rss+xml" title="' . sprintf( esc_attr__( 'New products tagged %s', 'woocommerce' ), urlencode( $term->name ) ) . '" href="' . esc_url( $feed ) . '" />';
}
}
}
@ -495,7 +495,7 @@ if ( ! function_exists( 'woocommerce_demo_store' ) ) {
$notice = __( 'This is a demo store for testing purposes &mdash; no orders shall be fulfilled.', 'woocommerce' );
}
echo apply_filters( 'woocommerce_demo_store', '<p class="woocommerce-store-notice demo_store">' . wp_kses_post( $notice ) . ' <a href="#" class="woocommerce-store-notice__dismiss-link">' . __( 'Dismiss', 'woocommerce' ) . '</a></p>', $notice );
echo apply_filters( 'woocommerce_demo_store', '<p class="woocommerce-store-notice demo_store">' . wp_kses_post( $notice ) . ' <a href="#" class="woocommerce-store-notice__dismiss-link">' . esc_html__( 'Dismiss', 'woocommerce' ) . '</a></p>', $notice );
}
}
@ -1425,7 +1425,7 @@ if ( ! function_exists( 'woocommerce_widget_shopping_cart_button_view_cart' ) )
* @subpackage Cart
*/
function woocommerce_widget_shopping_cart_button_view_cart() {
echo '<a href="' . esc_url( wc_get_cart_url() ) . '" class="button wc-forward">' . __( 'View cart', 'woocommerce' ) . '</a>';
echo '<a href="' . esc_url( wc_get_cart_url() ) . '" class="button wc-forward">' . esc_html__( 'View cart', 'woocommerce' ) . '</a>';
}
}
@ -1437,7 +1437,7 @@ if ( ! function_exists( 'woocommerce_widget_shopping_cart_proceed_to_checkout' )
* @subpackage Cart
*/
function woocommerce_widget_shopping_cart_proceed_to_checkout() {
echo '<a href="' . esc_url( wc_get_checkout_url() ) . '" class="button checkout wc-forward">' . __( 'Checkout', 'woocommerce' ) . '</a>';
echo '<a href="' . esc_url( wc_get_checkout_url() ) . '" class="button checkout wc-forward">' . esc_html__( 'Checkout', 'woocommerce' ) . '</a>';
}
}
@ -1939,7 +1939,7 @@ if ( ! function_exists( 'woocommerce_form_field' ) ) {
} else {
$field = '<select name="' . esc_attr( $key ) . '" id="' . esc_attr( $args['id'] ) . '" class="country_to_state country_select ' . esc_attr( implode( ' ', $args['input_class'] ) ) . '" ' . implode( ' ', $custom_attributes ) . '>' . '<option value="">' . __( 'Select a country&hellip;', 'woocommerce' ) . '</option>';
$field = '<select name="' . esc_attr( $key ) . '" id="' . esc_attr( $args['id'] ) . '" class="country_to_state country_select ' . esc_attr( implode( ' ', $args['input_class'] ) ) . '" ' . implode( ' ', $custom_attributes ) . '>' . '<option value="">' . esc_html__( 'Select a country&hellip;', 'woocommerce' ) . '</option>';
foreach ( $countries as $ckey => $cvalue ) {
$field .= '<option value="' . esc_attr( $ckey ) . '" ' . selected( $value, $ckey, false ) . '>' . $cvalue . '</option>';
@ -1968,7 +1968,7 @@ if ( ! function_exists( 'woocommerce_form_field' ) ) {
} elseif ( is_array( $states ) ) {
$field .= '<select name="' . esc_attr( $key ) . '" id="' . esc_attr( $args['id'] ) . '" class="state_select ' . esc_attr( implode( ' ', $args['input_class'] ) ) . '" ' . implode( ' ', $custom_attributes ) . ' data-placeholder="' . esc_attr( $args['placeholder'] ) . '">
<option value="">' . __( 'Select a state&hellip;', 'woocommerce' ) . '</option>';
<option value="">' . esc_html__( 'Select a state&hellip;', 'woocommerce' ) . '</option>';
foreach ( $states as $ckey => $cvalue ) {
$field .= '<option value="' . esc_attr( $ckey ) . '" ' . selected( $value, $ckey, false ) . '>' . $cvalue . '</option>';
@ -2054,11 +2054,8 @@ if ( ! function_exists( 'woocommerce_form_field' ) ) {
}
$container_class = esc_attr( implode( ' ', $args['class'] ) );
$container_id = esc_attr( $args['id'] ) . '_field';
$after = ! empty( $args['clear'] ) ? '<div class="clear"></div>' : '';
$field = sprintf( $field_container, $container_class, $container_id, $field_html ) . $after;
$container_id = esc_attr( $args['id'] ) . '_field';
$field = sprintf( $field_container, $container_class, $container_id, $field_html );
}
$field = apply_filters( 'woocommerce_form_field_' . $args['type'], $field, $key, $args, $value );
@ -2537,8 +2534,8 @@ function wc_get_stock_html( $product ) {
*/
function wc_get_rating_html( $rating ) {
if ( $rating > 0 ) {
$rating_html = '<div class="star-rating" title="' . sprintf( __( 'Rated %s out of 5', 'woocommerce' ), $rating ) . '">';
$rating_html .= '<span style="width:' . ( ( $rating / 5 ) * 100 ) . '%"><strong class="rating">' . $rating . '</strong> ' . __( 'out of 5', 'woocommerce' ) . '</span>';
$rating_html = '<div class="star-rating" title="' . sprintf( esc_attr__( 'Rated %s out of 5', 'woocommerce' ), $rating ) . '">';
$rating_html .= '<span style="width:' . ( ( $rating / 5 ) * 100 ) . '%"><strong class="rating">' . $rating . '</strong> ' . esc_html__( 'out of 5', 'woocommerce' ) . '</span>';
$rating_html .= '</div>';
} else {
$rating_html = '';

View File

@ -216,10 +216,10 @@ function wc_product_dropdown_categories( $args = array(), $deprecated_hierarchic
}
$output = "<select name='product_cat' class='dropdown_product_cat'>";
$output .= '<option value="" ' . selected( $current_product_cat, '', false ) . '>' . __( 'Select a category', 'woocommerce' ) . '</option>';
$output .= '<option value="" ' . selected( $current_product_cat, '', false ) . '>' . esc_html__( 'Select a category', 'woocommerce' ) . '</option>';
$output .= wc_walk_category_dropdown_tree( $terms, 0, $args );
if ( $args['show_uncategorized'] ) {
$output .= '<option value="0" ' . selected( $current_product_cat, '0', false ) . '>' . __( 'Uncategorized', 'woocommerce' ) . '</option>';
$output .= '<option value="0" ' . selected( $current_product_cat, '0', false ) . '>' . esc_html__( 'Uncategorized', 'woocommerce' ) . '</option>';
}
$output .= "</select>";

View File

@ -163,7 +163,7 @@ class WC_Widget_Layered_Nav_Filters extends WC_Widget {
foreach ( $rating_filter as $rating ) {
$link_ratings = implode( ',', array_diff( $rating_filter, array( $rating ) ) );
$link = $link_ratings ? add_query_arg( 'rating_filter', $link_ratings ) : remove_query_arg( 'rating_filter', $base_link );
echo '<li class="chosen"><a aria-label="' . esc_attr__( 'Remove filter', 'woocommerce' ) . '" href="' . esc_url( $link ) . '">' . sprintf( __( 'Rated %s out of 5', 'woocommerce' ), esc_html( $rating ) ) . '</a></li>';
echo '<li class="chosen"><a aria-label="' . esc_attr__( 'Remove filter', 'woocommerce' ) . '" href="' . esc_url( $link ) . '">' . sprintf( esc_html__( 'Rated %s out of 5', 'woocommerce' ), esc_html( $rating ) ) . '</a></li>';
}
}

View File

@ -113,9 +113,9 @@ class WC_Widget_Price_Filter extends WC_Widget {
<div class="price_slider_amount">
<input type="text" id="min_price" name="min_price" value="' . esc_attr( $min_price ) . '" data-min="' . esc_attr( apply_filters( 'woocommerce_price_filter_widget_min_amount', $min ) ) . '" placeholder="' . esc_attr__( 'Min price', 'woocommerce' ) . '" />
<input type="text" id="max_price" name="max_price" value="' . esc_attr( $max_price ) . '" data-max="' . esc_attr( apply_filters( 'woocommerce_price_filter_widget_max_amount', $max ) ) . '" placeholder="' . esc_attr__( 'Max price', 'woocommerce' ) . '" />
<button type="submit" class="button">' . __( 'Filter', 'woocommerce' ) . '</button>
<button type="submit" class="button">' . esc_html__( 'Filter', 'woocommerce' ) . '</button>
<div class="price_label" style="display:none;">
' . __( 'Price:', 'woocommerce' ) . ' <span class="from"></span> &mdash; <span class="to"></span>
' . esc_html__( 'Price:', 'woocommerce' ) . ' <span class="from"></span> &mdash; <span class="to"></span>
</div>
' . wc_query_string_form_fields( null, array( 'min_price', 'max_price' ), '', true ) . '
<div class="clear"></div>

View File

@ -185,7 +185,7 @@ class WC_Widget_Rating_Filter extends WC_Widget {
echo '<a href="' . esc_url( apply_filters( 'woocommerce_rating_filter_link', $link ) ) . '">';
echo '<span class="star-rating">
<span style="width:' . esc_attr( ( $rating / 5 ) * 100 ) . '%">' . sprintf( __( 'Rated %s out of 5', 'woocommerce' ), $rating ) . '</span>
<span style="width:' . esc_attr( ( $rating / 5 ) * 100 ) . '%">' . sprintf( esc_html__( 'Rated %s out of 5', 'woocommerce' ), $rating ) . '</span>
</span> (' . esc_html( $count ) . ')';
echo '</a>';

View File

@ -82,7 +82,7 @@ class WC_Widget_Recent_Reviews extends WC_Widget {
echo $rating_html;
/* translators: %s: review author */
echo '<span class="reviewer">' . sprintf( __( 'by %s', 'woocommerce' ), get_comment_author() ) . '</span>';
echo '<span class="reviewer">' . sprintf( esc_html__( 'by %s', 'woocommerce' ), get_comment_author() ) . '</span>';
echo '</li>';
}

View File

@ -161,7 +161,7 @@ Yes you can! Join in on our [GitHub repository](http://github.com/woocommerce/wo
== Changelog ==
= 2.7.0 - 2017-03-14 =
= 3.0.0 - 2017-04-04 =
* New gallery on single product pages with better mobile support, using PhotoSwipe and Zoom. Declare support with add_theme_support() - wc-product-gallery-zoom, wc-product-gallery-lightbox, wc-product-gallery-slider
* Made the store notice dismissible on the frontend.
* Variable products no longer show striked out prices in combination with ranges for clarity when on sale.
@ -221,10 +221,11 @@ Yes you can! Join in on our [GitHub repository](http://github.com/woocommerce/wo
* Localization - Added inline comments for placeholder strings.
* Localization - Added Nigerian and Pakistan Provinces to i18n/state.
* Localization - US and Poland postcode validation.
* To read more about this release, see our dev blog announcement here: http://wp.me/p6wtcw-Uo
[See changelog for all versions](https://raw.githubusercontent.com/woocommerce/woocommerce/master/CHANGELOG.txt).
== Upgrade Notice ==
= 2.7 =
2.7 is a major update. It is important that you make backups and ensure themes and extensions are 2.7 compatible before upgrading.
= 3.0 =
3.0 is a major update. It is important that you make backups and ensure themes and extensions are 3.0 compatible before upgrading.

View File

@ -60,10 +60,10 @@ if ( 'no' === get_option( 'woocommerce_enable_shipping_calc' ) || ! WC()->cart->
?><span>
<select name="calc_shipping_state" id="calc_shipping_state" placeholder="<?php esc_attr_e( 'State / County', 'woocommerce' ); ?>">
<option value=""><?php _e( 'Select a state&hellip;', 'woocommerce' ); ?></option>
<option value=""><?php esc_html_e( 'Select a state&hellip;', 'woocommerce' ); ?></option>
<?php
foreach ( $states as $ckey => $cvalue )
echo '<option value="' . esc_attr( $ckey ) . '" ' . selected( $current_r, $ckey, false ) . '>' . __( esc_html( $cvalue ), 'woocommerce' ) . '</option>';
echo '<option value="' . esc_attr( $ckey ) . '" ' . selected( $current_r, $ckey, false ) . '>' . esc_html( $cvalue ) . '</option>';
?>
</select>
</span><?php

View File

@ -22,12 +22,14 @@ if ( ! defined( 'ABSPATH' ) ) {
if ( $max_value && $min_value === $max_value ) {
?>
<input type="hidden" name="<?php echo esc_attr( $input_name ); ?>" value="<?php echo esc_attr( $min_value ); ?>" />
<div class="quantity hidden">
<input type="hidden" class="qty" name="<?php echo esc_attr( $input_name ); ?>" value="<?php echo esc_attr( $min_value ); ?>" />
</div>
<?php
} else {
?>
<div class="quantity">
<input type="number" step="<?php echo esc_attr( $step ); ?>" min="<?php echo esc_attr( $min_value ); ?>" max="<?php echo esc_attr( 0 < $max_value ? $max_value : '' ); ?>" name="<?php echo esc_attr( $input_name ); ?>" value="<?php echo esc_attr( $input_value ); ?>" title="<?php echo esc_attr_x( 'Qty', 'Product quantity input tooltip', 'woocommerce' ) ?>" class="input-text qty text" size="4" pattern="<?php echo esc_attr( $pattern ); ?>" inputmode="<?php echo esc_attr( $inputmode ); ?>" />
<input type="number" class="input-text qty text" step="<?php echo esc_attr( $step ); ?>" min="<?php echo esc_attr( $min_value ); ?>" max="<?php echo esc_attr( 0 < $max_value ? $max_value : '' ); ?>" name="<?php echo esc_attr( $input_name ); ?>" value="<?php echo esc_attr( $input_value ); ?>" title="<?php echo esc_attr_x( 'Qty', 'Product quantity input tooltip', 'woocommerce' ) ?>" size="4" pattern="<?php echo esc_attr( $pattern ); ?>" inputmode="<?php echo esc_attr( $inputmode ); ?>" />
</div>
<?php
}

View File

@ -25,7 +25,7 @@ global $post, $product;
?>
<?php if ( $product->is_on_sale() ) : ?>
<?php echo apply_filters( 'woocommerce_sale_flash', '<span class="onsale">' . __( 'Sale!', 'woocommerce' ) . '</span>', $post, $product ); ?>
<?php echo apply_filters( 'woocommerce_sale_flash', '<span class="onsale">' . esc_html__( 'Sale!', 'woocommerce' ) . '</span>', $post, $product ); ?>
<?php endif;

View File

@ -74,9 +74,9 @@ if ( ! comments_open() ) {
'title_reply_after' => '</span>',
'comment_notes_after' => '',
'fields' => array(
'author' => '<p class="comment-form-author">' . '<label for="author">' . __( 'Name', 'woocommerce' ) . ' <span class="required">*</span></label> ' .
'author' => '<p class="comment-form-author">' . '<label for="author">' . esc_html__( 'Name', 'woocommerce' ) . ' <span class="required">*</span></label> ' .
'<input id="author" name="author" type="text" value="' . esc_attr( $commenter['comment_author'] ) . '" size="30" aria-required="true" required /></p>',
'email' => '<p class="comment-form-email"><label for="email">' . __( 'Email', 'woocommerce' ) . ' <span class="required">*</span></label> ' .
'email' => '<p class="comment-form-email"><label for="email">' . esc_html__( 'Email', 'woocommerce' ) . ' <span class="required">*</span></label> ' .
'<input id="email" name="email" type="email" value="' . esc_attr( $commenter['comment_author_email'] ) . '" size="30" aria-required="true" required /></p>',
),
'label_submit' => __( 'Submit', 'woocommerce' ),
@ -89,17 +89,17 @@ if ( ! comments_open() ) {
}
if ( get_option( 'woocommerce_enable_review_rating' ) === 'yes' ) {
$comment_form['comment_field'] = '<p class="comment-form-rating"><label for="rating">' . __( 'Your rating', 'woocommerce' ) . '</label><select name="rating" id="rating" aria-required="true" required>
<option value="">' . __( 'Rate&hellip;', 'woocommerce' ) . '</option>
<option value="5">' . __( 'Perfect', 'woocommerce' ) . '</option>
<option value="4">' . __( 'Good', 'woocommerce' ) . '</option>
<option value="3">' . __( 'Average', 'woocommerce' ) . '</option>
<option value="2">' . __( 'Not that bad', 'woocommerce' ) . '</option>
<option value="1">' . __( 'Very poor', 'woocommerce' ) . '</option>
$comment_form['comment_field'] = '<p class="comment-form-rating"><label for="rating">' . esc_html__( 'Your rating', 'woocommerce' ) . '</label><select name="rating" id="rating" aria-required="true" required>
<option value="">' . esc_html__( 'Rate&hellip;', 'woocommerce' ) . '</option>
<option value="5">' . esc_html__( 'Perfect', 'woocommerce' ) . '</option>
<option value="4">' . esc_html__( 'Good', 'woocommerce' ) . '</option>
<option value="3">' . esc_html__( 'Average', 'woocommerce' ) . '</option>
<option value="2">' . esc_html__( 'Not that bad', 'woocommerce' ) . '</option>
<option value="1">' . esc_html__( 'Very poor', 'woocommerce' ) . '</option>
</select></p>';
}
$comment_form['comment_field'] .= '<p class="comment-form-comment"><label for="comment">' . __( 'Your review', 'woocommerce' ) . ' <span class="required">*</span></label><textarea id="comment" name="comment" cols="45" rows="8" aria-required="true" required></textarea></p>';
$comment_form['comment_field'] .= '<p class="comment-form-comment"><label for="comment">' . esc_html__( 'Your review', 'woocommerce' ) . ' <span class="required">*</span></label><textarea id="comment" name="comment" cols="45" rows="8" aria-required="true" required></textarea></p>';
comment_form( apply_filters( 'woocommerce_product_review_comment_form_args', $comment_form ) );
?>

View File

@ -40,7 +40,7 @@ do_action( 'woocommerce_before_add_to_cart_form' ); ?>
<?php
$selected = isset( $_REQUEST[ 'attribute_' . sanitize_title( $attribute_name ) ] ) ? wc_clean( urldecode( $_REQUEST[ 'attribute_' . sanitize_title( $attribute_name ) ] ) ) : $product->get_variation_default_attribute( $attribute_name );
wc_dropdown_variation_attribute_options( array( 'options' => $options, 'attribute' => $attribute_name, 'product' => $product, 'selected' => $selected ) );
echo end( $attribute_keys ) === $attribute_name ? apply_filters( 'woocommerce_reset_variations_link', '<a class="reset_variations" href="#">' . __( 'Clear', 'woocommerce' ) . '</a>' ) : '';
echo end( $attribute_keys ) === $attribute_name ? apply_filters( 'woocommerce_reset_variations_link', '<a class="reset_variations" href="#">' . esc_html__( 'Clear', 'woocommerce' ) . '</a>' ) : '';
?>
</td>
</tr>

View File

@ -28,7 +28,7 @@ global $product;
<?php if ( wc_product_sku_enabled() && ( $product->get_sku() || $product->is_type( 'variable' ) ) ) : ?>
<span class="sku_wrapper"><?php _e( 'SKU:', 'woocommerce' ); ?> <span class="sku"><?php echo ( $sku = $product->get_sku() ) ? $sku : __( 'N/A', 'woocommerce' ); ?></span></span>
<span class="sku_wrapper"><?php esc_html_e( 'SKU:', 'woocommerce' ); ?> <span class="sku"><?php echo ( $sku = $product->get_sku() ) ? $sku : esc_html__( 'N/A', 'woocommerce' ); ?></span></span>
<?php endif; ?>

View File

@ -19,17 +19,12 @@
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
if ( ! is_product() ) {
return;
}
?>
<!-- Root element of PhotoSwipe. Must have class pswp. -->
<div class="pswp" tabindex="-1" role="dialog" aria-hidden="true">
<!-- Background of PhotoSwipe.
It's a separate element as animating opacity is faster than rgba(). -->
<!-- Background of PhotoSwipe. It's a separate element as animating opacity is faster than rgba(). -->
<div class="pswp__bg"></div>
<!-- Slides wrapper with overflow:hidden. -->

View File

@ -38,20 +38,20 @@ $wrapper_classes = apply_filters( 'woocommerce_single_product_image_gallery_cl
<figure class="woocommerce-product-gallery__wrapper">
<?php
$attributes = array(
'title' => $image_title,
'data-large-image' => $full_size_image[0],
'data-large-image-width' => $full_size_image[1],
'data-large-image-height' => $full_size_image[2],
'title' => $image_title,
'data-large_image' => $full_size_image[0],
'data-large_image_width' => $full_size_image[1],
'data-large_image_height' => $full_size_image[2],
);
if ( has_post_thumbnail() ) {
$html = '<figure data-thumb="' . get_the_post_thumbnail_url( $post->ID, 'shop_thumbnail' ) . '" class="woocommerce-product-gallery__image"><a href="' . esc_url( $full_size_image[0] ) . '">';
$html = '<div data-thumb="' . get_the_post_thumbnail_url( $post->ID, 'shop_thumbnail' ) . '" class="woocommerce-product-gallery__image"><a href="' . esc_url( $full_size_image[0] ) . '">';
$html .= get_the_post_thumbnail( $post->ID, 'shop_single', $attributes );
$html .= '</a></figure>';
$html .= '</a></div>';
} else {
$html = '<figure class="woocommerce-product-gallery__image--placeholder">';
$html = '<div class="woocommerce-product-gallery__image--placeholder">';
$html .= sprintf( '<img src="%s" alt="%s" class="wp-post-image" />', esc_url( wc_placeholder_img_src() ), esc_html__( 'Awaiting product image', 'woocommerce' ) );
$html .= '</figure>';
$html .= '</div>';
}
echo apply_filters( 'woocommerce_single_product_image_thumbnail_html', $html, get_post_thumbnail_id( $post->ID ) );

View File

@ -24,7 +24,7 @@ global $post, $product;
$attachment_ids = $product->get_gallery_image_ids();
if ( $attachment_ids ) {
if ( $attachment_ids && has_post_thumbnail() ) {
foreach ( $attachment_ids as $attachment_id ) {
$full_size_image = wp_get_attachment_image_src( $attachment_id, 'full' );
$thumbnail = wp_get_attachment_image_src( $attachment_id, 'shop_thumbnail' );
@ -33,14 +33,14 @@ if ( $attachment_ids ) {
$attributes = array(
'title' => $image_title,
'data-large-image' => $full_size_image[0],
'data-large-image-width' => $full_size_image[1],
'data-large-image-height' => $full_size_image[2],
'data-large_image' => $full_size_image[0],
'data-large_image_width' => $full_size_image[1],
'data-large_image_height' => $full_size_image[2],
);
$html = '<figure data-thumb="' . esc_url( $thumbnail[0] ) . '" class="woocommerce-product-gallery__image"><a href="' . esc_url( $full_size_image[0] ) . '">';
$html = '<div data-thumb="' . esc_url( $thumbnail[0] ) . '" class="woocommerce-product-gallery__image"><a href="' . esc_url( $full_size_image[0] ) . '">';
$html .= wp_get_attachment_image( $attachment_id, 'shop_single', false, $attributes );
$html .= '</a></figure>';
$html .= '</a></div>';
echo apply_filters( 'woocommerce_single_product_image_thumbnail_html', $html, $attachment_id );
}

View File

@ -25,7 +25,7 @@ global $post, $product;
?>
<?php if ( $product->is_on_sale() ) : ?>
<?php echo apply_filters( 'woocommerce_sale_flash', '<span class="onsale">' . __( 'Sale!', 'woocommerce' ) . '</span>', $post, $product ); ?>
<?php echo apply_filters( 'woocommerce_sale_flash', '<span class="onsale">' . esc_html__( 'Sale!', 'woocommerce' ) . '</span>', $post, $product ); ?>
<?php endif;

View File

@ -9,6 +9,12 @@ if [ $1 == 'before' ]; then
# No Xdebug and therefore no coverage in PHP 5.3
[[ ${TRAVIS_PHP_VERSION} == '5.3' ]] && exit;
if [[ ${TRAVIS_PHP_VERSION:0:2} == "7." ]]; then
composer global require "phpunit/phpunit=5.7.*"
else
composer global require "phpunit/phpunit=4.8.*"
fi
composer self-update
composer install --no-interaction

View File

@ -193,6 +193,22 @@ class WC_Mock_WC_Data extends WC_Data {
);
}
/**
* Set the data to any arbitrary data.
* @param array $data
*/
public function set_data( $data ) {
$this->data = $data;
}
/**
* Set the changes to any arbitrary changes.
* @param array $changes
*/
public function set_changes( $changes ) {
$this->changes = $changes;
}
/**
* Simple save.
*/

View File

@ -126,19 +126,19 @@ class WC_Tests_Coupon_Data_Store extends WC_Unit_Test_Case {
$this->assertEquals( 0, $coupon->get_usage_count() );
$this->assertEmpty( $coupon->get_used_by() );
$coupon->inc_usage_count( 'woo@woo.local' );
$coupon->increase_usage_count( 'woo@woo.local' );
$this->assertEquals( 1, $coupon->get_usage_count() );
$this->assertEquals( array( 'woo@woo.local' ), $coupon->get_used_by() );
$coupon->inc_usage_count( $user_id );
$coupon->inc_usage_count( $user_id );
$coupon->increase_usage_count( $user_id );
$coupon->increase_usage_count( $user_id );
$data_store = WC_Data_Store::load( 'coupon' );
$this->assertEquals( 2, $data_store->get_usage_by_user_id( $coupon, $user_id ) );
$coupon->dcr_usage_count( 'woo@woo.local' );
$coupon->dcr_usage_count( $user_id );
$coupon->decrease_usage_count( 'woo@woo.local' );
$coupon->decrease_usage_count( $user_id );
$this->assertEquals( 1, $coupon->get_usage_count() );
$this->assertEquals( array( 1 ), $coupon->get_used_by() );
}

View File

@ -39,6 +39,7 @@ class WC_Tests_Coupon_Data extends WC_Unit_Test_Case {
'type',
'discount_type',
'amount',
'coupon_amount',
'code',
'individual_use',
'product_ids',
@ -68,6 +69,7 @@ class WC_Tests_Coupon_Data extends WC_Unit_Test_Case {
$this->assertEquals( $coupon->get_discount_type(), $coupon->type );
$this->assertEquals( $coupon->get_discount_type(), $coupon->discount_type );
$this->assertEquals( $coupon->get_amount(), $coupon->amount );
$this->assertEquals( $coupon->get_amount(), $coupon->coupon_amount );
$this->assertEquals( $coupon->get_code(), $coupon->code );
$this->assertEquals( $coupon->get_individual_use(), ( 'yes' === $coupon->individual_use ? true : false ) );
$this->assertEquals( $coupon->get_product_ids(), $coupon->product_ids );

View File

@ -120,6 +120,23 @@ class WC_Tests_CRUD_Data extends WC_Unit_Test_Case {
}
}
/**
* Test seeing if meta exists.
*/
function test_has_meta() {
$object = $this->create_test_post();
$object_id = $object->get_id();
$object->add_meta_data( 'test_meta_key', 'val1', true );
$object->add_meta_data( 'test_multi_meta_key', 'val2' );
$object->add_meta_data( 'test_multi_meta_key', 'val3' );
$object->save_meta_data();
$object = new WC_Mock_WC_Data( $object_id );
$this->assertTrue( $object->meta_exists( 'test_meta_key' ) );
$this->assertTrue( $object->meta_exists( 'test_multi_meta_key' ) );
$this->assertFalse( $object->meta_exists( 'thiskeyisnothere' ) );
}
/**
* Test getting meta that hasn't been set
*/
@ -379,4 +396,64 @@ class WC_Tests_CRUD_Data extends WC_Unit_Test_Case {
// Restore to UTC.
date_default_timezone_set( 'UTC' );
}
/**
* Test applying changes
*/
function test_apply_changes() {
$data = array(
'prop1' => 'value1',
'prop2' => 'value2',
);
$changes = array(
'prop1' => 'new_value1',
'prop3' => 'value3'
);
$object = new WC_Mock_WC_Data;
$object->set_data( $data );
$object->set_changes( $changes );
$object->apply_changes();
$new_data = $object->get_data();
$new_changes = $object->get_changes();
$this->assertEquals( 'new_value1', $new_data['prop1'] );
$this->assertEquals( 'value2', $new_data['prop2'] );
$this->assertEquals( 'value3', $new_data['prop3'] );
$this->assertEmpty( $new_changes );
}
/**
* Test applying changes with a nested array
*/
function test_apply_changes_nested() {
$data = array(
'prop1' => 'value1',
'prop2' => array(
'subprop1' => 1,
'subprop2' => 2,
),
);
$changes = array(
'prop2' => array(
'subprop1' => 1000,
'subprop3' => 3,
),
);
$object = new WC_Mock_WC_Data;
$object->set_data( $data );
$object->set_changes( $changes );
$object->apply_changes();
$new_data = $object->get_data();
$this->assertEquals( 'value1', $new_data['prop1'] );
$this->assertEquals( 1000, $new_data['prop2']['subprop1'] );
$this->assertEquals( 2, $new_data['prop2']['subprop2'] );
$this->assertEquals( 3, $new_data['prop2']['subprop3'] );
}
}

View File

@ -0,0 +1,115 @@
<?php
/**
* Test meta for https://github.com/woocommerce/woocommerce/issues/13533.
*
* @package WooCommerce\Tests\CRUD
*/
class WC_Tests_CRUD_Meta_Data extends WC_Unit_Test_Case {
private $item_id = 0;
private $order_id = 0;
/**
* A callback for the hooks triggered by eg_disappearing_order_meta() and
* eg_disappearing_item_meta() that saves additional meta data on the
* object via by pre-CRUD and CRUD methods.
*/
function add_different_object_meta( $object_id ) {
// Get a new instance of the item or order object
$object = ( $this->item_id == $object_id ) ? WC_Order_Factory::get_order_item( $object_id ) : wc_get_order( $object_id );
$object->add_meta_data( 'random_other', 'This might disappear :cry:.' );
$object->save(); // 'random_other' will be saved correctly, 'random' will also be saved
// Now set some meta data for it using the pre-CRUD approach
if ( $this->item_id == $object_id ) {
wc_update_order_item_meta( $object_id, 'random_other_pre_crud', 'This might disappear too :sob:.' );
} else {
update_post_meta( $object_id, 'random_other_pre_crud', 'This might disappear too :sob:.' );
}
}
/**
* Instantiate an instance of an order line item, save meta on that item, then trigger a hook which only passes the
* item's ID to callbacks. Afterwards, save the existing item without that other meta here and log the result to
* show that data has been removed.
*/
function test_disappearing_item_meta() {
// Setup for testing by making an item.
$item = new WC_Order_Item_Product();
$this->item_id = $item->save();
$item = WC_Order_Factory::get_order_item( $this->item_id );
// First make sure we're starting from a clean slate
$item->delete_meta_data( 'random' );
$item->delete_meta_data( 'random_other' );
$item->delete_meta_data( 'random_other_pre_crud' );
$item->save();
// Now add one piece of meta
$item->add_meta_data( 'random', (string) rand( 0, 0xffffff ) );
$item->save(); // 'random' will be saved correctly
// Run callback that passes just the item's ID to mimic this kind of normal behaviour in WP/WC
$this->add_different_object_meta( $this->item_id );
// Resave our current item that has our meta data, but not the other piece of meta data
$item->save();
// Get a new instance that should have both 'random' and 'random_other' set on it
$new_item = WC_Order_Factory::get_order_item( $this->item_id );
// The original $item should have 1 item of meta - random.
$this->assertCount( 1, $item->get_meta_data() );
$this->assertTrue( in_array( 'random', wp_list_pluck( $item->get_meta_data(), 'key' ) ) );
// The new $item should have 3 items of meta since it's freshly loaded.
$this->assertCount( 3, $new_item->get_meta_data() );
$this->assertTrue( in_array( 'random', wp_list_pluck( $new_item->get_meta_data(), 'key' ) ) );
$this->assertTrue( in_array( 'random_other', wp_list_pluck( $new_item->get_meta_data(), 'key' ) ) );
$this->assertTrue( in_array( 'random_other_pre_crud', wp_list_pluck( $new_item->get_meta_data(), 'key' ) ) );
}
/**
* Instantiate an instance of an order, save meta on that order, then trigger a hook which only passes the order's ID to
* callbacks. Afterwards, save the existing order without that other meta here and log the result to show that data
* has been removed.
*/
function test_disappearing_order_meta() {
// Setup for testing by making an item.
$order = new WC_Order();
$this->order_id = $order->save();
$order = wc_get_order( $this->order_id );
// First make sure we're starting from a clean slate
$order->delete_meta_data( 'random' );
$order->delete_meta_data( 'random_other' );
$order->delete_meta_data( 'random_other_pre_crud' );
$order->save();
// Now add one piece of meta
$order->add_meta_data( 'random', (string) rand( 0, 0xffffff ) );
$order->save(); // 'random' will be saved correctly
// Run callback that passes just the item's ID to mimic this kind of normal behaviour in WP/WC
$this->add_different_object_meta( $this->order_id );
// Resave our current item that has our meta data, but not the other piece of meta data
$order->save();
// Get a new instance of the same order. It should have both 'random' and 'random_other' set on it
$new_order = wc_get_order( $this->order_id );
// The original $order should have 1 item of meta - random.
$this->assertCount( 1, $order->get_meta_data() );
$this->assertTrue( in_array( 'random', wp_list_pluck( $order->get_meta_data(), 'key' ) ) );
// The new $order should have 3 items of meta since it's freshly loaded.
$this->assertCount( 3, $new_order->get_meta_data() );
$this->assertTrue( in_array( 'random', wp_list_pluck( $new_order->get_meta_data(), 'key' ) ) );
$this->assertTrue( in_array( 'random_other', wp_list_pluck( $new_order->get_meta_data(), 'key' ) ) );
$this->assertTrue( in_array( 'random_other_pre_crud', wp_list_pluck( $new_order->get_meta_data(), 'key' ) ) );
}
}

View File

@ -0,0 +1,62 @@
<?php
/**
* Order Item Function Tests
* @package WooCommerce\Tests\Order_Items
* @since 2.7.0
*/
class WC_Tests_Order_Item_Functions extends WC_Unit_Test_Case {
/**
* test_wc_order_item_meta_functions
*
* wc_add_order_item_meta, wc_update_order_item_meta, and
* wc_delete_order_item_meta all make direct updates through
* a datastore. These tests make sure cache is properly busted and
* accessing those values via CRUD returns the correct value.
*
* @since 2.7.0
*/
function test_wc_order_item_meta_functions() {
$meta_value = 'cat';
$meta_value2 = 'dog';
$order = new WC_Order();
$item_1 = new WC_Order_Item_Product();
$item_1->set_props( array(
'product' => WC_Helper_Product::create_simple_product(),
'quantity' => 4,
) );
$order->add_item( $item_1 );
$order->save();
$item = current( $order->get_items() );
$item_id = $item->get_id();
// Test that the initial key doesn't exist.
$item = new WC_Order_Item_Product( $item_id );;
$this->assertEmpty( $item->get_meta( '_test_key' ) );
$this->assertEmpty( wc_get_order_item_meta( $item_id, '_test_key' ) );
// Test making sure cache is properly busted when adding meta.
wc_add_order_item_meta( $item_id, '_test_key', $meta_value );
$item = new WC_Order_Item_Product( $item_id );
$item_meta = $item->get_meta( '_test_key' );
$this->assertEquals( $meta_value, $item_meta );
$this->assertEquals( $meta_value, wc_get_order_item_meta( $item_id, '_test_key' ) );
// Test making sure cache is properly busted when updating meta.
wc_update_order_item_meta( $item_id, '_test_key', $meta_value2 );
$item = new WC_Order_Item_Product( $item_id );
$item_meta = $item->get_meta( '_test_key' );
$this->assertEquals( $meta_value2, $item_meta );
$this->assertEquals( $meta_value2, wc_get_order_item_meta( $item_id, '_test_key' ) );
// Test making sure cache is properly busted when deleting meta.
wc_delete_order_item_meta( $item_id, '_test_key' );
$item = new WC_Order_Item_Product( $item_id );
$item_meta = $item->get_meta( '_test_key' );
$this->assertEmpty( $item->get_meta( '_test_key' ) );
$this->assertEmpty( wc_get_order_item_meta( $item_id, '_test_key' ) );
}
}

View File

@ -814,7 +814,7 @@ class WC_Tests_CRUD_Orders extends WC_Unit_Test_Case {
*/
function test_get_billing_state() {
$object = new WC_Order();
$set_to = 'Boulder';
$set_to = 'Oregon';
$object->set_billing_state( $set_to );
$this->assertEquals( $set_to, $object->get_billing_state() );
}
@ -864,6 +864,21 @@ class WC_Tests_CRUD_Orders extends WC_Unit_Test_Case {
$this->assertEquals( $set_to, $object->get_billing_phone() );
}
/**
* Test: Setting/getting billing settings after an order is saved
*/
function test_set_billing_after_save() {
$object = new WC_Order();
$phone = '123456678';
$object->set_billing_phone( $phone );
$object->save();
$state = 'Oregon';
$object->set_billing_state( $state );
$this->assertEquals( $phone, $object->get_billing_phone() );
$this->assertEquals( $state, $object->get_billing_state() );
}
/**
* Test: get_shipping_first_name
*/
@ -929,7 +944,7 @@ class WC_Tests_CRUD_Orders extends WC_Unit_Test_Case {
*/
function test_get_shipping_state() {
$object = new WC_Order();
$set_to = 'Boulder';
$set_to = 'Oregon';
$object->set_shipping_state( $set_to );
$this->assertEquals( $set_to, $object->get_shipping_state() );
}
@ -954,6 +969,21 @@ class WC_Tests_CRUD_Orders extends WC_Unit_Test_Case {
$this->assertEquals( $set_to, $object->get_shipping_country() );
}
/**
* Test: Setting/getting shipping settings after an order is saved
*/
function test_set_shipping_after_save() {
$object = new WC_Order();
$country = 'US';
$object->set_shipping_country( $country );
$object->save();
$state = 'Oregon';
$object->set_shipping_state( $state );
$this->assertEquals( $country, $object->get_shipping_country() );
$this->assertEquals( $state, $object->get_shipping_state() );
}
/**
* Test: get_payment_method
*/

View File

@ -48,7 +48,7 @@ final class WooCommerce {
/**
* Session instance.
*
* @var WC_Session
* @var WC_Session|WC_Session_Handler
*/
public $session = null;