Merge branch 'master' into feature/webhook-crud

This commit is contained in:
Claudio Sanches 2017-11-28 15:09:10 -02:00
commit c6f8e95b97
92 changed files with 2493 additions and 1726 deletions

View File

@ -6,7 +6,6 @@ sudo: false
php:
- 5.6
- 7.0
- 7.1
env:
- WP_VERSION=latest WP_MULTISITE=0
@ -20,6 +19,8 @@ matrix:
dist: precise
- php: 5.2
dist: precise
- php: 7.1
env: WP_VERSION=latest WP_MULTISITE=0 RUN_PHPCS=1
- php: 7.1
env: WP_VERSION=latest WP_MULTISITE=0 RUN_CODE_COVERAGE=1
allow_failures:
@ -27,7 +28,6 @@ matrix:
before_script:
- export PATH="$HOME/.composer/vendor/bin:$PATH"
- if [[ $TRAVIS_PHP_VERSION == '7.1' ]]; then composer install; fi
- bash tests/bin/install.sh woocommerce_test root '' localhost $WP_VERSION
- bash tests/bin/travis.sh before
@ -37,3 +37,10 @@ script:
after_script:
- bash tests/bin/travis.sh after
# Specifies that Travis should create builds for master and release branches and also tags.
branches:
only:
- master
- /^\d+\.\d+(\.\d+)?(-\S*)?$/
- /^release\//

View File

@ -334,9 +334,9 @@ module.exports = function( grunt ) {
// Register tasks
grunt.registerTask( 'default', [
'jshint',
'uglify',
'css'
'js',
'css',
'i18n'
]);
grunt.registerTask( 'js', [
@ -358,8 +358,13 @@ module.exports = function( grunt ) {
'shell:apigen'
]);
// Only an alias to 'default' task.
grunt.registerTask( 'dev', [
'default',
'default'
]);
grunt.registerTask( 'i18n', [
'checktextdomain',
'makepot'
]);

View File

@ -145,7 +145,7 @@
classes = _.indexBy( model.get( 'classes' ), 'term_id' ),
changes = {},
size = _.size( classes ),
newRow = _.extend( {}, data.default_class, {
newRow = _.extend( {}, data.default_shipping_class, {
term_id: 'new-' + size + '-' + Date.now(),
editing: true,
newRow : true

View File

@ -9,7 +9,7 @@
},
"require-dev": {
"squizlabs/php_codesniffer": "*",
"wp-coding-standards/wpcs": "0.13.1",
"wp-coding-standards/wpcs": "^0.14",
"phpunit/phpunit": "6.2.3",
"woocommerce/woocommerce-git-hooks": "1.0.3",
"wimg/php-compatibility": "^8.0",

14
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"content-hash": "9a9c7e81cc3a30935c03b1b2d64c201c",
"content-hash": "f8dbe5807f695e87ad3453a8b629b6bf",
"packages": [
{
"name": "composer/installers",
@ -1783,16 +1783,16 @@
},
{
"name": "wp-coding-standards/wpcs",
"version": "0.13.1",
"version": "0.14.0",
"source": {
"type": "git",
"url": "https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards.git",
"reference": "1f64b1a0b5b789822d0303436ee4e30e0135e4dc"
"reference": "8cadf48fa1c70b2381988e0a79e029e011a8f41c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/WordPress-Coding-Standards/WordPress-Coding-Standards/zipball/1f64b1a0b5b789822d0303436ee4e30e0135e4dc",
"reference": "1f64b1a0b5b789822d0303436ee4e30e0135e4dc",
"url": "https://api.github.com/repos/WordPress-Coding-Standards/WordPress-Coding-Standards/zipball/8cadf48fa1c70b2381988e0a79e029e011a8f41c",
"reference": "8cadf48fa1c70b2381988e0a79e029e011a8f41c",
"shasum": ""
},
"require": {
@ -1800,7 +1800,7 @@
"squizlabs/php_codesniffer": "^2.9.0 || ^3.0.2"
},
"suggest": {
"dealerdirect/phpcodesniffer-composer-installer": "^0.4.1"
"dealerdirect/phpcodesniffer-composer-installer": "^0.4.3"
},
"type": "phpcodesniffer-standard",
"notification-url": "https://packagist.org/downloads/",
@ -1819,7 +1819,7 @@
"standards",
"wordpress"
],
"time": "2017-08-05T16:08:58+00:00"
"time": "2017-11-01T15:10:46+00:00"
}
],
"aliases": [],

View File

@ -285,7 +285,7 @@ abstract class WC_Data {
if ( ! $has_setter_or_getter ) {
return false;
}
/* translators: %s: $key Key to check */
wc_doing_it_wrong( __FUNCTION__, sprintf( __( 'Generic add/update/get meta methods should not be used for internal meta data, including "%s". Use getters and setters.', 'woocommerce' ), $key ), '3.2.0' );
return true;
@ -400,7 +400,7 @@ abstract class WC_Data {
* @param string $value
* @param int $meta_id
*/
public function update_meta_data( $key, $value, $meta_id = '' ) {
public function update_meta_data( $key, $value, $meta_id = 0 ) {
if ( $this->is_internal_meta_key( $key ) ) {
$function = 'set_' . $key;

View File

@ -1,4 +1,12 @@
<?php
/**
* Abstract deprecated hooks
*
* @package WooCommerce\Abstracts
* @since 3.0.0
* @version 3.3.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
@ -7,8 +15,6 @@ if ( ! defined( 'ABSPATH' ) ) {
* WC_Deprecated_Hooks class maps old actions and filters to new ones. This is the base class for handling those deprecated hooks.
*
* Based on the WCS_Hook_Deprecator class by Prospress.
*
* @since 3.0.0
*/
abstract class WC_Deprecated_Hooks {
@ -19,6 +25,13 @@ abstract class WC_Deprecated_Hooks {
*/
protected $deprecated_hooks = array();
/**
* Array of versions on each hook has been deprecated.
*
* @var array
*/
protected $deprecated_version = array();
/**
* Constructor.
*/
@ -30,14 +43,14 @@ abstract class WC_Deprecated_Hooks {
/**
* Hook into the new hook so we can handle deprecated hooks once fired.
*
* @param string $hook_name
* @param string $hook_name Hook name.
*/
abstract function hook_in( $hook_name );
abstract public function hook_in( $hook_name );
/**
* Get old hooks to map to new hook.
*
* @param string $new_hook
* @param string $new_hook New hook name.
* @return array
*/
public function get_old_hooks( $new_hook ) {
@ -66,29 +79,39 @@ abstract class WC_Deprecated_Hooks {
/**
* If the old hook is in-use, trigger it.
*
* @param string $new_hook
* @param string $old_hook
* @param array $new_callback_args
* @param mixed $return_value
* @param string $new_hook New hook name.
* @param string $old_hook Old hook name.
* @param array $new_callback_args New callback args.
* @param mixed $return_value Returned value.
* @return mixed
*/
abstract function handle_deprecated_hook( $new_hook, $old_hook, $new_callback_args, $return_value );
abstract public function handle_deprecated_hook( $new_hook, $old_hook, $new_callback_args, $return_value );
/**
* Get deprecated version.
*
* @param string $old_hook Old hook name.
* @return string
*/
protected function get_deprecated_version( $old_hook ) {
return ! empty( $this->deprecated_version[ $old_hook ] ) ? $this->deprecated_version[ $old_hook ] : WC_VERSION;
}
/**
* Display a deprecated notice for old hooks.
*
* @param string $old_hook
* @param string $new_hook
* @param string $old_hook Old hook.
* @param string $new_hook New hook.
*/
protected function display_notice( $old_hook, $new_hook ) {
wc_deprecated_function( sprintf( 'The "%s" hook uses out of date data structures and', esc_html( $old_hook ) ), WC_VERSION, esc_html( $new_hook ) );
wc_deprecated_hook( esc_html( $old_hook ), esc_html( $this->get_deprecated_version( $old_hook ) ), esc_html( $new_hook ) );
}
/**
* Fire off a legacy hook with it's args.
*
* @param string $old_hook
* @param array $new_callback_args
* @param string $old_hook Old hook name.
* @param array $new_callback_args New callback args.
* @return mixed
*/
abstract protected function trigger_hook( $old_hook, $new_callback_args );

View File

@ -708,7 +708,7 @@ abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order {
}
}
return apply_filters( 'woocommerce_order_get_items', $items, $this );
return apply_filters( 'woocommerce_order_get_items', $items, $this, $types );
}
/**
@ -1599,7 +1599,7 @@ abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order {
public function get_subtotal_to_display( $compound = false, $tax_display = '' ) {
$tax_display = $tax_display ? $tax_display : get_option( 'woocommerce_tax_display_cart' );
$subtotal = 0;
if ( ! $compound ) {
foreach ( $this->get_items() as $item ) {
$subtotal += $item->get_subtotal();

View File

@ -1520,7 +1520,7 @@ class WC_Product extends WC_Abstract_Legacy_Product {
* @return bool
*/
public function is_shipping_taxable() {
return $this->get_tax_status() === 'taxable' || $this->get_tax_status() === 'shipping';
return $this->needs_shipping() && ( $this->get_tax_status() === 'taxable' || $this->get_tax_status() === 'shipping' );
}
/**

View File

@ -1664,7 +1664,7 @@ class WC_Admin_Setup_Wizard {
$docs_url = 'https://docs.woocommerce.com/documentation/plugins/woocommerce/getting-started/?utm_source=setupwizard&utm_medium=product&utm_content=docs&utm_campaign=woocommerceplugin';
$help_text = sprintf(
/* translators: %1$s: link to videos, %2$s: link to docs */
__( 'Watch our <a href="%1$s" target="_blank">guided tour videos</a> to learn more about WooCommerce, and visit WooCommerce.com to learn more about <a href="%2$s" target="_blank">getting started</a>.' ),
__( 'Watch our <a href="%1$s" target="_blank">guided tour videos</a> to learn more about WooCommerce, and visit WooCommerce.com to learn more about <a href="%2$s" target="_blank">getting started</a>.', 'woocommerce' ),
$videos_url,
$docs_url
);

View File

@ -321,11 +321,9 @@ class WC_Helper {
/**
* Get available subscriptions filters.
*
* @param array Optional subscriptions array to generate counts.
*
* @return array An array of filter keys and labels.
*/
public static function get_filters( $subscriptions = null ) {
public static function get_filters() {
$filters = array(
'all' => __( 'All', 'woocommerce' ),
'active' => __( 'Active', 'woocommerce' ),

View File

@ -299,22 +299,29 @@ class WC_Admin_List_Table_Products extends WC_Admin_List_Table {
* Render any custom filters and search inputs for the list table.
*/
protected function render_filters() {
$current_category_slug = isset( $_REQUEST['product_cat'] ) ? wc_clean( wp_unslash( $_REQUEST['product_cat'] ) ) : false; // WPCS: input var ok, sanitization ok.
$current_product_type = isset( $_REQUEST['product_type'] ) ? wc_clean( wp_unslash( $_REQUEST['product_type'] ) ) : false; // WPCS: input var ok, sanitization ok.
// @codingStandardsIgnoreStart
$current_category = $current_category_slug ? get_term_by( 'slug', $current_category_slug, 'product_cat' ): false;
// @codingStandardsIgnoreEnd
?>
<select class="wc-category-search" name="product_cat" data-placeholder="<?php esc_attr_e( 'Filter by category', 'woocommerce' ); ?>" data-allow_clear="true">
<?php if ( $current_category_slug && $current_category ) : ?>
<option value="<?php echo esc_attr( $current_category_slug ); ?>" selected="selected"><?php echo esc_html( $current_category->name ); ?><option>
<?php endif; ?>
</select>
<?php
// Category Filtering.
$categories_count = (int) wp_count_terms( 'product_cat' );
$terms = get_terms( 'product_type' );
$output = '<select name="product_type" id="dropdown_product_type">';
$output .= '<option value="">' . __( 'Filter by product type', 'woocommerce' ) . '</option>';
if ( $categories_count <= apply_filters( 'woocommerce_product_category_filter_threshold', 100 ) ) {
wc_product_dropdown_categories( array(
'option_select_text' => __( 'Filter by category', 'woocommerce' ),
) );
} else {
$current_category_slug = isset( $_GET['product_cat'] ) ? wc_clean( wp_unslash( $_GET['product_cat'] ) ) : false; // WPCS: input var ok, CSRF ok.
$current_category = $current_category_slug ? get_term_by( 'slug', $current_category_slug, 'product_cat' ) : false;
?>
<select class="wc-category-search" name="product_cat" data-placeholder="<?php esc_attr_e( 'Filter by category', 'woocommerce' ); ?>" data-allow_clear="true">
<?php if ( $current_category_slug && $current_category ) : ?>
<option value="<?php echo esc_attr( $current_category_slug ); ?>" selected="selected"><?php echo esc_html( $current_category->name ); ?><option>
<?php endif; ?>
</select>
<?php
}
// Product type filtering.
$current_product_type = isset( $_REQUEST['product_type'] ) ? wc_clean( wp_unslash( $_REQUEST['product_type'] ) ) : false; // WPCS: input var ok, sanitization ok.
$terms = get_terms( 'product_type' );
$output = '<select name="product_type" id="dropdown_product_type"><option value="">' . __( 'Filter by product type', 'woocommerce' ) . '</option>';
foreach ( $terms as $term ) {
$output .= '<option value="' . sanitize_title( $term->name ) . '" ';

View File

@ -284,12 +284,18 @@ class WC_Meta_Box_Product_Data {
$attribute_key = sanitize_title( $attribute->get_name() );
if ( ! is_null( $index ) ) {
$value = isset( $_POST[ $key_prefix . $attribute_key ][ $index ] ) ? stripslashes( $_POST[ $key_prefix . $attribute_key ][ $index ] ) : '';
$value = isset( $_POST[ $key_prefix . $attribute_key ][ $index ] ) ? wp_unslash( $_POST[ $key_prefix . $attribute_key ][ $index ] ) : '';
} else {
$value = isset( $_POST[ $key_prefix . $attribute_key ] ) ? stripslashes( $_POST[ $key_prefix . $attribute_key ] ) : '';
$value = isset( $_POST[ $key_prefix . $attribute_key ] ) ? wp_unslash( $_POST[ $key_prefix . $attribute_key ] ) : '';
}
if ( $attribute->is_taxonomy() ) {
// Don't use wc_clean as it destroys sanitized characters.
$value = sanitize_title( $value );
} else {
$value = html_entity_decode( wc_clean( $value ), ENT_QUOTES, get_bloginfo( 'charset' ) ); // WPCS: sanitization ok.
}
$value = $attribute->is_taxonomy() ? sanitize_title( $value ) : wc_clean( $value ); // Don't use wc_clean as it destroys sanitized characters in terms.
$attributes[ $attribute_key ] = $value;
}
}

View File

@ -5,7 +5,7 @@ if ( ! defined( 'ABSPATH' ) ) {
?>
<div class="wc-metabox closed">
<h3 class="fixed">
<button type="button" data-permission_id="<?php echo esc_attr( $download->get_id() ); ?>" rel="<?php echo esc_attr( $download->get_product_id() ) . ',' . esc_attr( $download->get_download_id() ); ?>" class="revoke_access button"><?php _e( 'Revoke access', 'woocommerce' ); ?></button>
<button type="button" data-permission_id="<?php echo esc_attr( $download->get_id() ); ?>" rel="<?php echo esc_attr( $download->get_product_id() ) . ',' . esc_attr( $download->get_download_id() ); ?>" class="revoke_access button"><?php esc_html_e( 'Revoke access', 'woocommerce' ); ?></button>
<div class="handlediv" aria-label="<?php esc_attr_e( 'Click to toggle', 'woocommerce' ); ?>"></div>
<strong><?php
printf(
@ -16,19 +16,19 @@ if ( ! defined( 'ABSPATH' ) ) {
esc_html( wc_get_filename_from_url( $product->get_file_download_path( $download->get_download_id() ) ) )
);
printf( _n( 'Downloaded %s time', 'Downloaded %s times', $download->get_download_count(), 'woocommerce' ), esc_html( $download->get_download_count() ) )
?></strong>
?></strong>
</h3>
<table cellpadding="0" cellspacing="0" class="wc-metabox-content">
<tbody>
<tr>
<td>
<label><?php esc_html_e( 'Downloads remaining', 'woocommerce' ); ?></label>
<input type="hidden" name="permission_id[<?php echo $loop; ?>]" value="<?php echo esc_attr( $download->get_id() ); ?>" />
<input type="number" step="1" min="0" class="short" name="downloads_remaining[<?php echo $loop; ?>]" value="<?php echo esc_attr( $download->get_downloads_remaining() ); ?>" placeholder="<?php esc_attr_e( 'Unlimited', 'woocommerce' ); ?>" />
<input type="hidden" name="permission_id[<?php echo esc_attr( $loop ); ?>]" value="<?php echo esc_attr( $download->get_id() ); ?>" />
<input type="number" step="1" min="0" class="short" name="downloads_remaining[<?php echo esc_attr( $loop ); ?>]" value="<?php echo esc_attr( $download->get_downloads_remaining() ); ?>" placeholder="<?php esc_attr_e( 'Unlimited', 'woocommerce' ); ?>" />
</td>
<td>
<label><?php esc_html_e( 'Access expires', 'woocommerce' ); ?></label>
<input type="text" class="short date-picker" name="access_expires[<?php echo $loop; ?>]" value="<?php echo ! is_null( $download->get_access_expires() ) ? date_i18n( 'Y-m-d', $download->get_access_expires()->getTimestamp() ) : ''; ?>" maxlength="10" placeholder="<?php esc_attr_e( 'Never', 'woocommerce' ); ?>" pattern="<?php echo esc_attr( apply_filters( 'woocommerce_date_input_html_pattern', '[0-9]{4}-(0[1-9]|1[012])-(0[1-9]|1[0-9]|2[0-9]|3[01])' ) ); ?>" />
<input type="text" class="short date-picker" name="access_expires[<?php echo esc_attr( $loop ); ?>]" value="<?php echo ! is_null( $download->get_access_expires() ) ? esc_attr( date_i18n( 'Y-m-d', $download->get_access_expires()->getTimestamp() ) ) : ''; ?>" maxlength="10" placeholder="<?php esc_attr_e( 'Never', 'woocommerce' ); ?>" pattern="<?php echo esc_attr( apply_filters( 'woocommerce_date_input_html_pattern', '[0-9]{4}-(0[1-9]|1[012])-(0[1-9]|1[0-9]|2[0-9]|3[01])' ) ); ?>" />
</td>
<td>
<label><?php esc_html_e( 'Customer download link', 'woocommerce' ); ?></label>

View File

@ -10,7 +10,7 @@ if ( ! defined( 'ABSPATH' ) ) {
exit;
}
?>
<tr class="fee <?php echo ( ! empty( $class ) ) ? $class : ''; ?>" data-order_item_id="<?php echo esc_attr( $item_id ); ?>">
<tr class="fee <?php echo ( ! empty( $class ) ) ? esc_attr( $class ) : ''; ?>" data-order_item_id="<?php echo esc_attr( $item_id ); ?>">
<td class="thumb"><div></div></td>
<td class="name">
@ -22,7 +22,7 @@ if ( ! defined( 'ABSPATH' ) ) {
<input type="hidden" class="order_item_id" name="order_item_id[]" value="<?php echo esc_attr( $item_id ); ?>" />
<input type="hidden" name="order_item_tax_class[<?php echo absint( $item_id ); ?>]" value="<?php echo esc_attr( $item->get_tax_class() ); ?>" />
</div>
<?php do_action( 'woocommerce_after_order_fee_item_name', $item_id, $item, null ) ?>
<?php do_action( 'woocommerce_after_order_fee_item_name', $item_id, $item, null ); ?>
</td>
<?php do_action( 'woocommerce_admin_order_item_values', null, $item, absint( $item_id ) ); ?>
@ -41,10 +41,10 @@ if ( ! defined( 'ABSPATH' ) ) {
?>
</div>
<div class="edit" style="display: none;">
<input type="text" name="line_total[<?php echo absint( $item_id ); ?>]" placeholder="<?php echo wc_format_localized_price( 0 ); ?>" value="<?php echo esc_attr( wc_format_localized_price( $item->get_total() ) ); ?>" class="line_total wc_input_price" />
<input type="text" name="line_total[<?php echo absint( $item_id ); ?>]" placeholder="<?php echo esc_attr( wc_format_localized_price( 0 ) ); ?>" value="<?php echo esc_attr( wc_format_localized_price( $item->get_total() ) ); ?>" class="line_total wc_input_price" />
</div>
<div class="refund" style="display: none;">
<input type="text" name="refund_line_total[<?php echo absint( $item_id ); ?>]" placeholder="<?php echo wc_format_localized_price( 0 ); ?>" class="refund_line_total wc_input_price" />
<input type="text" name="refund_line_total[<?php echo absint( $item_id ); ?>]" placeholder="<?php echo esc_attr( wc_format_localized_price( 0 ) ); ?>" class="refund_line_total wc_input_price" />
</div>
</td>
@ -65,10 +65,10 @@ if ( ! defined( 'ABSPATH' ) ) {
?>
</div>
<div class="edit" style="display: none;">
<input type="text" name="line_tax[<?php echo absint( $item_id ); ?>][<?php echo esc_attr( $tax_item_id ); ?>]" placeholder="<?php echo wc_format_localized_price( 0 ); ?>" value="<?php echo ( isset( $tax_item_total ) ) ? esc_attr( wc_format_localized_price( $tax_item_total ) ) : ''; ?>" class="line_tax wc_input_price" />
<input type="text" name="line_tax[<?php echo absint( $item_id ); ?>][<?php echo esc_attr( $tax_item_id ); ?>]" placeholder="<?php echo esc_attr( wc_format_localized_price( 0 ) ); ?>" value="<?php echo ( isset( $tax_item_total ) ) ? esc_attr( wc_format_localized_price( $tax_item_total ) ) : ''; ?>" class="line_tax wc_input_price" />
</div>
<div class="refund" style="display: none;">
<input type="text" name="refund_line_tax[<?php echo absint( $item_id ); ?>][<?php echo esc_attr( $tax_item_id ); ?>]" placeholder="<?php echo wc_format_localized_price( 0 ); ?>" class="refund_line_tax wc_input_price" data-tax_id="<?php echo esc_attr( $tax_item_id ); ?>" />
<input type="text" name="refund_line_tax[<?php echo absint( $item_id ); ?>][<?php echo esc_attr( $tax_item_id ); ?>]" placeholder="<?php echo esc_attr( wc_format_localized_price( 0 ) ); ?>" class="refund_line_tax wc_input_price" data-tax_id="<?php echo esc_attr( $tax_item_id ); ?>" />
</div>
</td>

View File

@ -18,8 +18,9 @@ $hidden_order_itemmeta = apply_filters( 'woocommerce_hidden_order_itemmeta', arr
?><div class="view">
<?php if ( $meta_data = $item->get_formatted_meta_data( '' ) ) : ?>
<table cellspacing="0" class="display_meta">
<?php foreach ( $meta_data as $meta_id => $meta ) :
if ( in_array( $meta->key, $hidden_order_itemmeta ) ) {
<?php
foreach ( $meta_data as $meta_id => $meta ) :
if ( in_array( $meta->key, $hidden_order_itemmeta, true ) ) {
continue;
}
?>
@ -35,8 +36,9 @@ $hidden_order_itemmeta = apply_filters( 'woocommerce_hidden_order_itemmeta', arr
<table class="meta" cellspacing="0">
<tbody class="meta_items">
<?php if ( $meta_data = $item->get_formatted_meta_data( '' ) ) : ?>
<?php foreach ( $meta_data as $meta_id => $meta ) :
if ( in_array( $meta->key, $hidden_order_itemmeta ) ) {
<?php
foreach ( $meta_data as $meta_id => $meta ) :
if ( in_array( $meta->key, $hidden_order_itemmeta, true ) ) {
continue;
}
?>
@ -52,7 +54,7 @@ $hidden_order_itemmeta = apply_filters( 'woocommerce_hidden_order_itemmeta', arr
</tbody>
<tfoot>
<tr>
<td colspan="4"><button class="add_order_item_meta button"><?php _e( 'Add&nbsp;meta', 'woocommerce' ); ?></button></td>
<td colspan="4"><button class="add_order_item_meta button"><?php esc_html_e( 'Add&nbsp;meta', 'woocommerce' ); ?></button></td>
</tr>
</tfoot>
</table>

View File

@ -12,7 +12,7 @@ $product = $item->get_product();
$product_link = $product ? admin_url( 'post.php?post=' . $item->get_product_id() . '&action=edit' ) : '';
$thumbnail = $product ? apply_filters( 'woocommerce_admin_order_item_thumbnail', $product->get_image( 'thumbnail', array( 'title' => '' ), false ), $item_id, $item ) : '';
?>
<tr class="item <?php echo apply_filters( 'woocommerce_admin_html_order_item_class', ( ! empty( $class ) ? $class : '' ), $item, $order ); ?>" data-order_item_id="<?php echo esc_attr( $item_id ); ?>">
<tr class="item <?php echo esc_attr( apply_filters( 'woocommerce_admin_html_order_item_class', ( ! empty( $class ) ? $class : '' ), $item, $order ) ); ?>" data-order_item_id="<?php echo esc_attr( $item_id ); ?>">
<td class="thumb">
<?php echo '<div class="wc-order-item-thumbnail">' . wp_kses_post( $thumbnail ) . '</div>'; ?>
</td>
@ -21,11 +21,11 @@ $thumbnail = $product ? apply_filters( 'woocommerce_admin_order_item_thumbnai
echo $product_link ? '<a href="' . esc_url( $product_link ) . '" class="wc-order-item-name">' . esc_html( $item->get_name() ) . '</a>' : '<div class="wc-order-item-name">' . esc_html( $item->get_name() ) . '</div>';
if ( $product && $product->get_sku() ) {
echo '<div class="wc-order-item-sku"><strong>' . __( 'SKU:', 'woocommerce' ) . '</strong> ' . esc_html( $product->get_sku() ) . '</div>';
echo '<div class="wc-order-item-sku"><strong>' . esc_html__( 'SKU:', 'woocommerce' ) . '</strong> ' . esc_html( $product->get_sku() ) . '</div>';
}
if ( $item->get_variation_id() ) {
echo '<div class="wc-order-item-variation"><strong>' . __( 'Variation ID:', 'woocommerce' ) . '</strong> ';
echo '<div class="wc-order-item-variation"><strong>' . esc_html__( 'Variation ID:', 'woocommerce' ) . '</strong> ';
if ( 'product_variation' === get_post_type( $item->get_variation_id() ) ) {
echo esc_html( $item->get_variation_id() );
} else {
@ -38,9 +38,9 @@ $thumbnail = $product ? apply_filters( 'woocommerce_admin_order_item_thumbnai
<input type="hidden" class="order_item_id" name="order_item_id[]" value="<?php echo esc_attr( $item_id ); ?>" />
<input type="hidden" name="order_item_tax_class[<?php echo absint( $item_id ); ?>]" value="<?php echo esc_attr( $item->get_tax_class() ); ?>" />
<?php do_action( 'woocommerce_before_order_itemmeta', $item_id, $item, $product ) ?>
<?php do_action( 'woocommerce_before_order_itemmeta', $item_id, $item, $product ); ?>
<?php include( 'html-order-item-meta.php' ); ?>
<?php do_action( 'woocommerce_after_order_itemmeta', $item_id, $item, $product ) ?>
<?php do_action( 'woocommerce_after_order_itemmeta', $item_id, $item, $product ); ?>
</td>
<?php do_action( 'woocommerce_admin_order_item_values', $product, $item, absint( $item_id ) ); ?>
@ -67,10 +67,10 @@ $thumbnail = $product ? apply_filters( 'woocommerce_admin_order_item_thumbnai
?>
</div>
<div class="edit" style="display: none;">
<input type="number" step="<?php echo apply_filters( 'woocommerce_quantity_input_step', '1', $product ); ?>" min="0" autocomplete="off" name="order_item_qty[<?php echo absint( $item_id ); ?>]" placeholder="0" value="<?php echo esc_attr( $item->get_quantity() ); ?>" data-qty="<?php echo esc_attr( $item->get_quantity() ); ?>" size="4" class="quantity" />
<input type="number" step="<?php echo esc_attr( apply_filters( 'woocommerce_quantity_input_step', '1', $product ) ); ?>" min="0" autocomplete="off" name="order_item_qty[<?php echo absint( $item_id ); ?>]" placeholder="0" value="<?php echo esc_attr( $item->get_quantity() ); ?>" data-qty="<?php echo esc_attr( $item->get_quantity() ); ?>" size="4" class="quantity" />
</div>
<div class="refund" style="display: none;">
<input type="number" step="<?php echo apply_filters( 'woocommerce_quantity_input_step', '1', $product ); ?>" min="0" max="<?php echo $item->get_quantity(); ?>" autocomplete="off" name="refund_order_item_qty[<?php echo absint( $item_id ); ?>]" placeholder="0" size="4" class="refund_order_item_qty" />
<input type="number" step="<?php echo esc_attr( apply_filters( 'woocommerce_quantity_input_step', '1', $product ) ); ?>" min="0" max="<?php echo absint( $item->get_quantity() ); ?>" autocomplete="off" name="refund_order_item_qty[<?php echo absint( $item_id ); ?>]" placeholder="0" size="4" class="refund_order_item_qty" />
</div>
</td>
<td class="line_cost" width="1%" data-sort-value="<?php echo esc_attr( $item->get_total() ); ?>">
@ -91,16 +91,16 @@ $thumbnail = $product ? apply_filters( 'woocommerce_admin_order_item_thumbnai
<div class="split-input">
<div class="input">
<label><?php esc_attr_e( 'Pre-discount:', 'woocommerce' ); ?></label>
<input type="text" name="line_subtotal[<?php echo absint( $item_id ); ?>]" placeholder="<?php echo wc_format_localized_price( 0 ); ?>" value="<?php echo esc_attr( wc_format_localized_price( $item->get_subtotal() ) ); ?>" class="line_subtotal wc_input_price" data-subtotal="<?php echo esc_attr( wc_format_localized_price( $item->get_subtotal() ) ); ?>" />
<input type="text" name="line_subtotal[<?php echo absint( $item_id ); ?>]" placeholder="<?php echo esc_attr( wc_format_localized_price( 0 ) ); ?>" value="<?php echo esc_attr( wc_format_localized_price( $item->get_subtotal() ) ); ?>" class="line_subtotal wc_input_price" data-subtotal="<?php echo esc_attr( wc_format_localized_price( $item->get_subtotal() ) ); ?>" />
</div>
<div class="input">
<label><?php esc_attr_e( 'Total:', 'woocommerce' ); ?></label>
<input type="text" name="line_total[<?php echo absint( $item_id ); ?>]" placeholder="<?php echo wc_format_localized_price( 0 ); ?>" value="<?php echo esc_attr( wc_format_localized_price( $item->get_total() ) ); ?>" class="line_total wc_input_price" data-tip="<?php esc_attr_e( 'After pre-tax discounts.', 'woocommerce' ); ?>" data-total="<?php echo esc_attr( wc_format_localized_price( $item->get_total() ) ); ?>" />
<input type="text" name="line_total[<?php echo absint( $item_id ); ?>]" placeholder="<?php echo esc_attr( wc_format_localized_price( 0 ) ); ?>" value="<?php echo esc_attr( wc_format_localized_price( $item->get_total() ) ); ?>" class="line_total wc_input_price" data-tip="<?php esc_attr_e( 'After pre-tax discounts.', 'woocommerce' ); ?>" data-total="<?php echo esc_attr( wc_format_localized_price( $item->get_total() ) ); ?>" />
</div>
</div>
</div>
<div class="refund" style="display: none;">
<input type="text" name="refund_line_total[<?php echo absint( $item_id ); ?>]" placeholder="<?php echo wc_format_localized_price( 0 ); ?>" class="refund_line_total wc_input_price" />
<input type="text" name="refund_line_total[<?php echo absint( $item_id ); ?>]" placeholder="<?php echo esc_attr( wc_format_localized_price( 0 ) ); ?>" class="refund_line_total wc_input_price" />
</div>
</td>
@ -114,7 +114,7 @@ $thumbnail = $product ? apply_filters( 'woocommerce_admin_order_item_thumbnai
<td class="line_tax" width="1%">
<div class="view">
<?php
if ( '' != $tax_item_total ) {
if ( '' !== $tax_item_total ) {
echo wc_price( wc_round_tax_total( $tax_item_total ), array( 'currency' => $order->get_currency() ) );
} else {
echo '&ndash;';
@ -137,16 +137,16 @@ $thumbnail = $product ? apply_filters( 'woocommerce_admin_order_item_thumbnai
<div class="split-input">
<div class="input">
<label><?php esc_attr_e( 'Pre-discount:', 'woocommerce' ); ?></label>
<input type="text" name="line_subtotal_tax[<?php echo absint( $item_id ); ?>][<?php echo esc_attr( $tax_item_id ); ?>]" placeholder="<?php echo wc_format_localized_price( 0 ); ?>" value="<?php echo esc_attr( wc_format_localized_price( $tax_item_subtotal ) ); ?>" class="line_subtotal_tax wc_input_price" data-subtotal_tax="<?php echo esc_attr( wc_format_localized_price( $tax_item_subtotal ) ); ?>" data-tax_id="<?php echo esc_attr( $tax_item_id ); ?>" />
<input type="text" name="line_subtotal_tax[<?php echo absint( $item_id ); ?>][<?php echo esc_attr( $tax_item_id ); ?>]" placeholder="<?php echo esc_attr( wc_format_localized_price( 0 ) ); ?>" value="<?php echo esc_attr( wc_format_localized_price( $tax_item_subtotal ) ); ?>" class="line_subtotal_tax wc_input_price" data-subtotal_tax="<?php echo esc_attr( wc_format_localized_price( $tax_item_subtotal ) ); ?>" data-tax_id="<?php echo esc_attr( $tax_item_id ); ?>" />
</div>
<div class="input">
<label><?php esc_attr_e( 'Total:', 'woocommerce' ); ?></label>
<input type="text" name="line_tax[<?php echo absint( $item_id ); ?>][<?php echo esc_attr( $tax_item_id ); ?>]" placeholder="<?php echo wc_format_localized_price( 0 ); ?>" value="<?php echo esc_attr( wc_format_localized_price( $tax_item_total ) ); ?>" class="line_tax wc_input_price" data-total_tax="<?php echo esc_attr( wc_format_localized_price( $tax_item_total ) ); ?>" data-tax_id="<?php echo esc_attr( $tax_item_id ); ?>" />
<input type="text" name="line_tax[<?php echo absint( $item_id ); ?>][<?php echo esc_attr( $tax_item_id ); ?>]" placeholder="<?php echo esc_attr( wc_format_localized_price( 0 ) ); ?>" value="<?php echo esc_attr( wc_format_localized_price( $tax_item_total ) ); ?>" class="line_tax wc_input_price" data-total_tax="<?php echo esc_attr( wc_format_localized_price( $tax_item_total ) ); ?>" data-tax_id="<?php echo esc_attr( $tax_item_id ); ?>" />
</div>
</div>
</div>
<div class="refund" style="display: none;">
<input type="text" name="refund_line_tax[<?php echo absint( $item_id ); ?>][<?php echo esc_attr( $tax_item_id ); ?>]" placeholder="<?php echo wc_format_localized_price( 0 ); ?>" class="refund_line_tax wc_input_price" data-tax_id="<?php echo esc_attr( $tax_item_id ); ?>" />
<input type="text" name="refund_line_tax[<?php echo absint( $item_id ); ?>][<?php echo esc_attr( $tax_item_id ); ?>]" placeholder="<?php echo esc_attr( wc_format_localized_price( 0 ) ); ?>" class="refund_line_tax wc_input_price" data-tax_id="<?php echo esc_attr( $tax_item_id ); ?>" />
</div>
</td>
<?php

View File

@ -26,23 +26,24 @@ if ( wc_tax_enabled() ) {
<table cellpadding="0" cellspacing="0" class="woocommerce_order_items">
<thead>
<tr>
<th class="item sortable" colspan="2" data-sort="string-ins"><?php _e( 'Item', 'woocommerce' ); ?></th>
<th class="item sortable" colspan="2" data-sort="string-ins"><?php esc_html_e( 'Item', 'woocommerce' ); ?></th>
<?php do_action( 'woocommerce_admin_order_item_headers', $order ); ?>
<th class="item_cost sortable" data-sort="float"><?php _e( 'Cost', 'woocommerce' ); ?></th>
<th class="quantity sortable" data-sort="int"><?php _e( 'Qty', 'woocommerce' ); ?></th>
<th class="line_cost sortable" data-sort="float"><?php _e( 'Total', 'woocommerce' ); ?></th>
<th class="item_cost sortable" data-sort="float"><?php esc_html_e( 'Cost', 'woocommerce' ); ?></th>
<th class="quantity sortable" data-sort="int"><?php esc_html_e( 'Qty', 'woocommerce' ); ?></th>
<th class="line_cost sortable" data-sort="float"><?php esc_html_e( 'Total', 'woocommerce' ); ?></th>
<?php
if ( ! empty( $order_taxes ) ) :
foreach ( $order_taxes as $tax_id => $tax_item ) :
$tax_class = wc_get_tax_class_by_tax_id( $tax_item['rate_id'] );
$tax_class_name = isset( $classes_options[ $tax_class ] ) ? $classes_options[ $tax_class ] : __( 'Tax', 'woocommerce' );
$column_label = ! empty( $tax_item['label'] ) ? $tax_item['label'] : __( 'Tax', 'woocommerce' );
/* translators: %1$s: tax item name %2$s: tax class name */
$column_tip = sprintf( esc_html__( '%1$s (%2$s)', 'woocommerce' ), $tax_item['name'], $tax_class_name );
?>
<th class="line_tax tips" data-tip="<?php echo esc_attr( $column_tip ); ?>">
<?php echo esc_attr( $column_label ); ?>
<input type="hidden" class="order-tax-id" name="order_taxes[<?php echo $tax_id; ?>]" value="<?php echo esc_attr( $tax_item['rate_id'] ); ?>">
<a class="delete-order-tax" href="#" data-rate_id="<?php echo $tax_id; ?>"></a>
<input type="hidden" class="order-tax-id" name="order_taxes[<?php echo esc_attr( $tax_id ); ?>]" value="<?php echo esc_attr( $tax_item['rate_id'] ); ?>">
<a class="delete-order-tax" href="#" data-rate_id="<?php echo esc_attr( $tax_id ); ?>"></a>
</th>
<?php
endforeach;
@ -94,11 +95,11 @@ if ( wc_tax_enabled() ) {
</div>
<div class="wc-order-data-row wc-order-item-bulk-edit" style="display:none;">
<?php if ( $order->is_editable() ) : ?>
<button type="button" class="button bulk-delete-items"><?php _e( 'Delete selected row(s)', 'woocommerce' ); ?></button>
<button type="button" class="button bulk-delete-items"><?php esc_html_e( 'Delete selected row(s)', 'woocommerce' ); ?></button>
<?php endif; ?>
<button type="button" class="button bulk-decrease-stock"><?php _e( 'Reduce stock', 'woocommerce' ); ?></button>
<button type="button" class="button bulk-increase-stock"><?php _e( 'Increase stock', 'woocommerce' ); ?></button>
<button type="button" class="button bulk-decrease-stock"><?php esc_html_e( 'Reduce stock', 'woocommerce' ); ?></button>
<button type="button" class="button bulk-increase-stock"><?php esc_html_e( 'Increase stock', 'woocommerce' ); ?></button>
<?php do_action( 'woocommerce_admin_order_item_bulk_actions', $order ); ?>
</div>
<div class="wc-order-data-row wc-order-totals-items wc-order-items-editable">
@ -108,7 +109,7 @@ if ( wc_tax_enabled() ) {
?>
<div class="wc-used-coupons">
<ul class="wc_coupon_list"><?php
echo '<li><strong>' . __( 'Coupon(s)', 'woocommerce' ) . '</strong></li>';
echo '<li><strong>' . esc_html__( 'Coupon(s)', 'woocommerce' ) . '</strong></li>';
foreach ( $coupons as $item_id => $item ) {
$post_id = $wpdb->get_var( $wpdb->prepare( "SELECT ID FROM {$wpdb->posts} WHERE post_title = %s AND post_type = 'shop_coupon' AND post_status = 'publish' LIMIT 1;", $item->get_code() ) );
@ -126,7 +127,7 @@ if ( wc_tax_enabled() ) {
<table class="wc-order-totals">
<?php if ( 0 < $order->get_total_discount() ) : ?>
<tr>
<td class="label"><?php _e( 'Discount:', 'woocommerce' ); ?></td>
<td class="label"><?php esc_html_e( 'Discount:', 'woocommerce' ); ?></td>
<td width="1%"></td>
<td class="total">
<?php echo wc_price( $order->get_total_discount(), array( 'currency' => $order->get_currency() ) ); ?>
@ -138,10 +139,12 @@ if ( wc_tax_enabled() ) {
<?php if ( $order->get_shipping_methods() ) : ?>
<tr>
<td class="label"><?php _e( 'Shipping:', 'woocommerce' ); ?></td>
<td class="label"><?php esc_html_e( 'Shipping:', 'woocommerce' ); ?></td>
<td width="1%"></td>
<td class="total"><?php
if ( ( $refunded = $order->get_total_shipping_refunded() ) > 0 ) {
<td class="total">
<?php
$refunded = $order->get_total_shipping_refunded();
if ( $refunded > 0 ) {
echo '<del>' . strip_tags( wc_price( $order->get_shipping_total(), array( 'currency' => $order->get_currency() ) ) ) . '</del> <ins>' . wc_price( $order->get_shipping_total() - $refunded, array( 'currency' => $order->get_currency() ) ) . '</ins>';
} else {
echo wc_price( $order->get_shipping_total(), array( 'currency' => $order->get_currency() ) );
@ -155,15 +158,18 @@ if ( wc_tax_enabled() ) {
<?php if ( wc_tax_enabled() ) : ?>
<?php foreach ( $order->get_tax_totals() as $code => $tax ) : ?>
<tr>
<td class="label"><?php echo $tax->label; ?>:</td>
<td class="label"><?php echo esc_html( $tax->label ); ?>:</td>
<td width="1%"></td>
<td class="total"><?php
if ( ( $refunded = $order->get_total_tax_refunded_by_rate_id( $tax->rate_id ) ) > 0 ) {
<td class="total">
<?php
$refunded = $order->get_total_tax_refunded_by_rate_id( $tax->rate_id );
if ( $refunded > 0 ) {
echo '<del>' . strip_tags( $tax->formatted_amount ) . '</del> <ins>' . wc_price( WC_Tax::round( $tax->amount, wc_get_price_decimals() ) - WC_Tax::round( $refunded, wc_get_price_decimals() ), array( 'currency' => $order->get_currency() ) ) . '</ins>';
} else {
echo $tax->formatted_amount;
}
?></td>
?>
</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
@ -171,7 +177,7 @@ if ( wc_tax_enabled() ) {
<?php do_action( 'woocommerce_admin_order_totals_after_tax', $order->get_id() ); ?>
<tr>
<td class="label"><?php _e( 'Total', 'woocommerce' ); ?>:</td>
<td class="label"><?php esc_html_e( 'Total', 'woocommerce' ); ?>:</td>
<td width="1%"></td>
<td class="total">
<?php echo $order->get_formatted_order_total(); ?>
@ -182,7 +188,7 @@ if ( wc_tax_enabled() ) {
<?php if ( $order->get_total_refunded() ) : ?>
<tr>
<td class="label refunded-total"><?php _e( 'Refunded', 'woocommerce' ); ?>:</td>
<td class="label refunded-total"><?php esc_html_e( 'Refunded', 'woocommerce' ); ?>:</td>
<td width="1%"></td>
<td class="total refunded-total">-<?php echo wc_price( $order->get_total_refunded(), array( 'currency' => $order->get_currency() ) ); ?></td>
</tr>
@ -196,63 +202,63 @@ if ( wc_tax_enabled() ) {
<div class="wc-order-data-row wc-order-bulk-actions wc-order-data-row-toggle">
<p class="add-items">
<?php if ( $order->is_editable() ) : ?>
<button type="button" class="button add-line-item"><?php _e( 'Add item(s)', 'woocommerce' ); ?></button>
<button type="button" class="button add-coupon"><?php _e( 'Apply coupon', 'woocommerce' ); ?></button>
<button type="button" class="button add-line-item"><?php esc_html_e( 'Add item(s)', 'woocommerce' ); ?></button>
<button type="button" class="button add-coupon"><?php esc_html_e( 'Apply coupon', 'woocommerce' ); ?></button>
<?php else : ?>
<span class="description"><?php echo wc_help_tip( __( 'To edit this order change the status back to "Pending"', 'woocommerce' ) ); ?> <?php _e( 'This order is no longer editable.', 'woocommerce' ); ?></span>
<span class="description"><?php echo wc_help_tip( __( 'To edit this order change the status back to "Pending"', 'woocommerce' ) ); ?> <?php esc_html_e( 'This order is no longer editable.', 'woocommerce' ); ?></span>
<?php endif; ?>
<?php if ( 0 < $order->get_total() - $order->get_total_refunded() || 0 < absint( $order->get_item_count() - $order->get_item_count_refunded() ) ) : ?>
<button type="button" class="button refund-items"><?php _e( 'Refund', 'woocommerce' ); ?></button>
<button type="button" class="button refund-items"><?php esc_html_e( 'Refund', 'woocommerce' ); ?></button>
<?php endif; ?>
<?php
// allow adding custom buttons
do_action( 'woocommerce_order_item_add_action_buttons', $order );
?>
<?php if ( $order->is_editable() ) : ?>
<button type="button" class="button button-primary calculate-action"><?php _e( 'Recalculate', 'woocommerce' ); ?></button>
<button type="button" class="button button-primary calculate-action"><?php esc_html_e( 'Recalculate', 'woocommerce' ); ?></button>
<?php endif; ?>
</p>
</div>
<div class="wc-order-data-row wc-order-add-item wc-order-data-row-toggle" style="display:none;">
<button type="button" class="button add-order-item"><?php _e( 'Add product(s)', 'woocommerce' ); ?></button>
<button type="button" class="button add-order-fee"><?php _e( 'Add fee', 'woocommerce' ); ?></button>
<button type="button" class="button add-order-shipping"><?php _e( 'Add shipping', 'woocommerce' ); ?></button>
<button type="button" class="button add-order-item"><?php esc_html_e( 'Add product(s)', 'woocommerce' ); ?></button>
<button type="button" class="button add-order-fee"><?php esc_html_e( 'Add fee', 'woocommerce' ); ?></button>
<button type="button" class="button add-order-shipping"><?php esc_html_e( 'Add shipping', 'woocommerce' ); ?></button>
<?php if ( wc_tax_enabled() ) : ?>
<button type="button" class="button add-order-tax"><?php _e( 'Add tax', 'woocommerce' ); ?></button>
<button type="button" class="button add-order-tax"><?php esc_html_e( 'Add tax', 'woocommerce' ); ?></button>
<?php endif; ?>
<?php
// allow adding custom buttons
do_action( 'woocommerce_order_item_add_line_buttons', $order );
?>
<button type="button" class="button cancel-action"><?php _e( 'Cancel', 'woocommerce' ); ?></button>
<button type="button" class="button button-primary save-action"><?php _e( 'Save', 'woocommerce' ); ?></button>
<button type="button" class="button cancel-action"><?php esc_html_e( 'Cancel', 'woocommerce' ); ?></button>
<button type="button" class="button button-primary save-action"><?php esc_html_e( 'Save', 'woocommerce' ); ?></button>
</div>
<?php if ( 0 < $order->get_total() - $order->get_total_refunded() || 0 < absint( $order->get_item_count() - $order->get_item_count_refunded() ) ) : ?>
<div class="wc-order-data-row wc-order-refund-items wc-order-data-row-toggle" style="display: none;">
<table class="wc-order-totals">
<?php if ( 'yes' === get_option( 'woocommerce_manage_stock' ) ) : ?>
<tr>
<td class="label"><label for="restock_refunded_items"><?php _e( 'Restock refunded items', 'woocommerce' ); ?>:</label></td>
<td class="label"><label for="restock_refunded_items"><?php esc_html_e( 'Restock refunded items', 'woocommerce' ); ?>:</label></td>
<td class="total"><input type="checkbox" id="restock_refunded_items" name="restock_refunded_items" checked="checked" /></td>
</tr>
<?php endif; ?>
<tr>
<td class="label"><?php _e( 'Amount already refunded', 'woocommerce' ); ?>:</td>
<td class="label"><?php esc_html_e( 'Amount already refunded', 'woocommerce' ); ?>:</td>
<td class="total">-<?php echo wc_price( $order->get_total_refunded(), array( 'currency' => $order->get_currency() ) ); ?></td>
</tr>
<tr>
<td class="label"><?php _e( 'Total available to refund', 'woocommerce' ); ?>:</td>
<td class="label"><?php esc_html_e( 'Total available to refund', 'woocommerce' ); ?>:</td>
<td class="total"><?php echo wc_price( $order->get_total() - $order->get_total_refunded(), array( 'currency' => $order->get_currency() ) ); ?></td>
</tr>
<tr>
<td class="label"><label for="refund_amount"><?php _e( 'Refund amount', 'woocommerce' ); ?>:</label></td>
<td class="label"><label for="refund_amount"><?php esc_html_e( 'Refund amount', 'woocommerce' ); ?>:</label></td>
<td class="total">
<input type="text" id="refund_amount" name="refund_amount" class="wc_input_price" />
<div class="clear"></div>
</td>
</tr>
<tr>
<td class="label"><label for="refund_reason"><?php echo wc_help_tip( __( 'Note: the refund reason will be visible by the customer.', 'woocommerce' ) ); ?> <?php _e( 'Reason for refund (optional):', 'woocommerce' ); ?></label></td>
<td class="label"><label for="refund_reason"><?php echo wc_help_tip( __( 'Note: the refund reason will be visible by the customer.', 'woocommerce' ) ); ?> <?php esc_html_e( 'Reason for refund (optional):', 'woocommerce' ); ?></label></td>
<td class="total">
<input type="text" id="refund_reason" name="refund_reason" />
<div class="clear"></div>
@ -266,9 +272,11 @@ if ( wc_tax_enabled() ) {
$gateway_supports_refunds = false !== $payment_gateway && $payment_gateway->supports( 'refunds' );
$gateway_name = false !== $payment_gateway ? ( ! empty( $payment_gateway->method_title ) ? $payment_gateway->method_title : $payment_gateway->get_title() ) : __( 'Payment gateway', 'woocommerce' );
?>
<button type="button" class="button <?php echo $gateway_supports_refunds ? 'button-primary do-api-refund' : 'tips disabled'; ?>" <?php echo $gateway_supports_refunds ? '' : 'data-tip="' . esc_attr__( 'The payment gateway used to place this order does not support automatic refunds.', 'woocommerce' ) . '"'; ?>><?php printf( __( 'Refund %1$s via %2$s', 'woocommerce' ), $refund_amount, $gateway_name ); ?></button>
<button type="button" class="button button-primary do-manual-refund tips" data-tip="<?php esc_attr_e( 'You will need to manually issue a refund through your payment gateway after using this.', 'woocommerce' ); ?>"><?php printf( __( 'Refund %s manually', 'woocommerce' ), $refund_amount ); ?></button>
<button type="button" class="button cancel-action"><?php _e( 'Cancel', 'woocommerce' ); ?></button>
<?php /* translators: refund amount, gateway name */ ?>
<button type="button" class="button <?php echo $gateway_supports_refunds ? 'button-primary do-api-refund' : 'tips disabled'; ?>" <?php echo $gateway_supports_refunds ? '' : 'data-tip="' . esc_attr__( 'The payment gateway used to place this order does not support automatic refunds.', 'woocommerce' ) . '"'; ?>><?php printf( esc_html__( 'Refund %1$s via %2$s', 'woocommerce' ), $refund_amount, $gateway_name ); ?></button>
<?php /* translators: refund amount */ ?>
<button type="button" class="button button-primary do-manual-refund tips" data-tip="<?php esc_attr_e( 'You will need to manually issue a refund through your payment gateway after using this.', 'woocommerce' ); ?>"><?php printf( esc_html__( 'Refund %s manually', 'woocommerce' ), $refund_amount ); ?></button>
<button type="button" class="button cancel-action"><?php esc_html_e( 'Cancel', 'woocommerce' ); ?></button>
<input type="hidden" id="refunded_amount" name="refunded_amount" value="<?php echo esc_attr( $order->get_total_refunded() ); ?>" />
<div class="clear"></div>
</div>
@ -280,7 +288,7 @@ if ( wc_tax_enabled() ) {
<div class="wc-backbone-modal-content">
<section class="wc-backbone-modal-main" role="main">
<header class="wc-backbone-modal-header">
<h1><?php _e( 'Add products', 'woocommerce' ); ?></h1>
<h1><?php esc_html_e( 'Add products', 'woocommerce' ); ?></h1>
<button class="modal-close modal-close-link dashicons dashicons-no-alt">
<span class="screen-reader-text">Close modal panel</span>
</button>
@ -292,7 +300,7 @@ if ( wc_tax_enabled() ) {
</article>
<footer>
<div class="inner">
<button id="btn-ok" class="button button-primary button-large"><?php _e( 'Add', 'woocommerce' ); ?></button>
<button id="btn-ok" class="button button-primary button-large"><?php esc_html_e( 'Add', 'woocommerce' ); ?></button>
</div>
</footer>
</section>
@ -306,7 +314,7 @@ if ( wc_tax_enabled() ) {
<div class="wc-backbone-modal-content">
<section class="wc-backbone-modal-main" role="main">
<header class="wc-backbone-modal-header">
<h1><?php _e( 'Add tax', 'woocommerce' ); ?></h1>
<h1><?php esc_html_e( 'Add tax', 'woocommerce' ); ?></h1>
<button class="modal-close modal-close-link dashicons dashicons-no-alt">
<span class="screen-reader-text">Close modal panel</span>
</button>
@ -317,10 +325,10 @@ if ( wc_tax_enabled() ) {
<thead>
<tr>
<th>&nbsp;</th>
<th><?php _e( 'Rate name', 'woocommerce' ); ?></th>
<th><?php _e( 'Tax class', 'woocommerce' ); ?></th>
<th><?php _e( 'Rate code', 'woocommerce' ); ?></th>
<th><?php _e( 'Rate %', 'woocommerce' ); ?></th>
<th><?php esc_html_e( 'Rate name', 'woocommerce' ); ?></th>
<th><?php esc_html_e( 'Tax class', 'woocommerce' ); ?></th>
<th><?php esc_html_e( 'Rate code', 'woocommerce' ); ?></th>
<th><?php esc_html_e( 'Rate %', 'woocommerce' ); ?></th>
</tr>
</thead>
<?php
@ -341,7 +349,7 @@ if ( wc_tax_enabled() ) {
</table>
<?php if ( absint( $wpdb->get_var( "SELECT COUNT(tax_rate_id) FROM {$wpdb->prefix}woocommerce_tax_rates;" ) ) > 100 ) : ?>
<p>
<label for="manual_tax_rate_id"><?php _e( 'Or, enter tax rate ID:', 'woocommerce' ); ?></label><br/>
<label for="manual_tax_rate_id"><?php esc_html_e( 'Or, enter tax rate ID:', 'woocommerce' ); ?></label><br/>
<input type="number" name="manual_tax_rate_id" id="manual_tax_rate_id" step="1" placeholder="<?php esc_attr_e( 'Optional', 'woocommerce' ); ?>" />
</p>
<?php endif; ?>
@ -349,7 +357,7 @@ if ( wc_tax_enabled() ) {
</article>
<footer>
<div class="inner">
<button id="btn-ok" class="button button-primary button-large"><?php _e( 'Add', 'woocommerce' ); ?></button>
<button id="btn-ok" class="button button-primary button-large"><?php esc_html_e( 'Add', 'woocommerce' ); ?></button>
</div>
</footer>
</section>

View File

@ -8,7 +8,7 @@ if ( ! defined( 'ABSPATH' ) ) {
*/
$who_refunded = new WP_User( $refund->get_refunded_by() );
?>
<tr class="refund <?php echo ( ! empty( $class ) ) ? $class : ''; ?>" data-order_refund_id="<?php echo $refund->get_id(); ?>">
<tr class="refund <?php echo ( ! empty( $class ) ) ? esc_attr( $class ) : ''; ?>" data-order_refund_id="<?php echo esc_attr( $refund->get_id() ); ?>">
<td class="thumb"><div></div></td>
<td class="name">
@ -16,11 +16,12 @@ $who_refunded = new WP_User( $refund->get_refunded_by() );
if ( $who_refunded->exists() ) {
printf(
/* translators: 1: refund id 2: refund date 3: username */
__( 'Refund #%1$s - %2$s by %3$s', 'woocommerce' ),
esc_html__( 'Refund #%1$s - %2$s by %3$s', 'woocommerce' ),
$refund->get_id(),
wc_format_datetime( $refund->get_date_created(), get_option( 'date_format' ) . ', ' . get_option( 'time_format' ) ),
sprintf(
'<abbr class="refund_by" title="%1$s">%2$s</abbr>',
/* translators: 1: ID who refunded */
sprintf( esc_attr__( 'ID: %d', 'woocommerce' ), absint( $who_refunded->ID ) ),
esc_html( $who_refunded->display_name )
)
@ -28,7 +29,7 @@ $who_refunded = new WP_User( $refund->get_refunded_by() );
} else {
printf(
/* translators: 1: refund id 2: refund date */
__( 'Refund #%1$s - %2$s', 'woocommerce' ),
esc_html__( 'Refund #%1$s - %2$s', 'woocommerce' ),
$refund->get_id(),
wc_format_datetime( $refund->get_date_created(), get_option( 'date_format' ) . ', ' . get_option( 'time_format' ) )
);

View File

@ -9,7 +9,7 @@ if ( ! defined( 'ABSPATH' ) ) {
exit;
}
?>
<tr class="shipping <?php echo ( ! empty( $class ) ) ? $class : ''; ?>" data-order_item_id="<?php echo esc_attr( $item_id ); ?>">
<tr class="shipping <?php echo ( ! empty( $class ) ) ? esc_attr( $class ) : ''; ?>" data-order_item_id="<?php echo esc_attr( $item_id ); ?>">
<td class="thumb"><div></div></td>
<td class="name">
@ -21,7 +21,7 @@ if ( ! defined( 'ABSPATH' ) ) {
<input type="text" class="shipping_method_name" placeholder="<?php esc_attr_e( 'Shipping name', 'woocommerce' ); ?>" name="shipping_method_title[<?php echo esc_attr( $item_id ); ?>]" value="<?php echo esc_attr( $item->get_name() ); ?>" />
<select class="shipping_method" name="shipping_method[<?php echo esc_attr( $item_id ); ?>]">
<optgroup label="<?php esc_attr_e( 'Shipping method', 'woocommerce' ); ?>">
<option value=""><?php _e( 'N/A', 'woocommerce' ); ?></option>
<option value=""><?php esc_html_e( 'N/A', 'woocommerce' ); ?></option>
<?php
$found_method = false;
@ -36,18 +36,18 @@ if ( ! defined( 'ABSPATH' ) ) {
}
if ( ! $found_method && $item->get_method_id() ) {
echo '<option value="' . esc_attr( $item->get_method_id() ) . '" selected="selected">' . __( 'Other', 'woocommerce' ) . '</option>';
echo '<option value="' . esc_attr( $item->get_method_id() ) . '" selected="selected">' . esc_html__( 'Other', 'woocommerce' ) . '</option>';
} else {
echo '<option value="other">' . __( 'Other', 'woocommerce' ) . '</option>';
echo '<option value="other">' . esc_html__( 'Other', 'woocommerce' ) . '</option>';
}
?>
</optgroup>
</select>
</div>
<?php do_action( 'woocommerce_before_order_itemmeta', $item_id, $item, null ) ?>
<?php do_action( 'woocommerce_before_order_itemmeta', $item_id, $item, null ); ?>
<?php include( 'html-order-item-meta.php' ); ?>
<?php do_action( 'woocommerce_after_order_itemmeta', $item_id, $item, null ) ?>
<?php do_action( 'woocommerce_after_order_itemmeta', $item_id, $item, null ); ?>
</td>
<?php do_action( 'woocommerce_admin_order_item_values', null, $item, absint( $item_id ) ); ?>
@ -59,17 +59,17 @@ if ( ! defined( 'ABSPATH' ) ) {
<div class="view">
<?php
echo wc_price( $item->get_total(), array( 'currency' => $order->get_currency() ) );
if ( $refunded = $order->get_total_refunded_for_item( $item_id, 'shipping' ) ) {
$refunded = $order->get_total_refunded_for_item( $item_id, 'shipping' );
if ( $refunded ) {
echo '<small class="refunded">-' . wc_price( $refunded, array( 'currency' => $order->get_currency() ) ) . '</small>';
}
?>
</div>
<div class="edit" style="display: none;">
<input type="text" name="shipping_cost[<?php echo esc_attr( $item_id ); ?>]" placeholder="<?php echo wc_format_localized_price( 0 ); ?>" value="<?php echo esc_attr( wc_format_localized_price( $item->get_total() ) ); ?>" class="line_total wc_input_price" />
<input type="text" name="shipping_cost[<?php echo esc_attr( $item_id ); ?>]" placeholder="<?php echo esc_attr( wc_format_localized_price( 0 ) ); ?>" value="<?php echo esc_attr( wc_format_localized_price( $item->get_total() ) ); ?>" class="line_total wc_input_price" />
</div>
<div class="refund" style="display: none;">
<input type="text" name="refund_line_total[<?php echo absint( $item_id ); ?>]" placeholder="<?php echo wc_format_localized_price( 0 ); ?>" class="refund_line_total wc_input_price" />
<input type="text" name="refund_line_total[<?php echo absint( $item_id ); ?>]" placeholder="<?php echo esc_attr( wc_format_localized_price( 0 ) ); ?>" class="refund_line_total wc_input_price" />
</div>
</td>
@ -83,17 +83,17 @@ if ( ! defined( 'ABSPATH' ) ) {
<div class="view">
<?php
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' ) ) {
$refunded = $order->get_tax_refunded_for_item( $item_id, $tax_item_id, 'shipping' );
if ( $refunded ) {
echo '<small class="refunded">-' . wc_price( $refunded, array( 'currency' => $order->get_currency() ) ) . '</small>';
}
?>
</div>
<div class="edit" style="display: none;">
<input type="text" name="shipping_taxes[<?php echo absint( $item_id ); ?>][<?php echo esc_attr( $tax_item_id ); ?>]" placeholder="<?php echo wc_format_localized_price( 0 ); ?>" value="<?php echo ( isset( $tax_item_total ) ) ? esc_attr( wc_format_localized_price( $tax_item_total ) ) : ''; ?>" class="line_tax wc_input_price" />
<input type="text" name="shipping_taxes[<?php echo absint( $item_id ); ?>][<?php echo esc_attr( $tax_item_id ); ?>]" placeholder="<?php echo esc_attr( wc_format_localized_price( 0 ) ); ?>" value="<?php echo ( isset( $tax_item_total ) ) ? esc_attr( wc_format_localized_price( $tax_item_total ) ) : ''; ?>" class="line_tax wc_input_price" />
</div>
<div class="refund" style="display: none;">
<input type="text" name="refund_line_tax[<?php echo absint( $item_id ); ?>][<?php echo esc_attr( $tax_item_id ); ?>]" placeholder="<?php echo wc_format_localized_price( 0 ); ?>" class="refund_line_tax wc_input_price" data-tax_id="<?php echo esc_attr( $tax_item_id ); ?>" />
<input type="text" name="refund_line_tax[<?php echo absint( $item_id ); ?>][<?php echo esc_attr( $tax_item_id ); ?>]" placeholder="<?php echo esc_attr( wc_format_localized_price( 0 ) ); ?>" class="refund_line_tax wc_input_price" data-tax_id="<?php echo esc_attr( $tax_item_id ); ?>" />
</div>
</td>
<?php

View File

@ -5,7 +5,7 @@ if ( ! defined( 'ABSPATH' ) ) {
?>
<div data-taxonomy="<?php echo esc_attr( $attribute->get_taxonomy() ); ?>" class="woocommerce_attribute wc-metabox closed <?php echo esc_attr( implode( ' ', $metabox_class ) ); ?>" rel="<?php echo esc_attr( $attribute->get_position() ); ?>">
<h3>
<a href="#" class="remove_row delete"><?php _e( 'Remove', 'woocommerce' ); ?></a>
<a href="#" class="remove_row delete"><?php esc_html_e( 'Remove', 'woocommerce' ); ?></a>
<div class="handlediv" title="<?php esc_attr_e( 'Click to toggle', 'woocommerce' ); ?>"></div>
<strong class="attribute_name"><?php echo esc_html( wc_attribute_label( $attribute->get_name() ) ); ?></strong>
</h3>
@ -14,24 +14,26 @@ if ( ! defined( 'ABSPATH' ) ) {
<tbody>
<tr>
<td class="attribute_name">
<label><?php _e( 'Name', 'woocommerce' ); ?>:</label>
<label><?php esc_html_e( 'Name', 'woocommerce' ); ?>:</label>
<?php if ( $attribute->is_taxonomy() ) : ?>
<strong><?php echo esc_html( wc_attribute_label( $attribute->get_name() ) ); ?></strong>
<input type="hidden" name="attribute_names[<?php echo $i; ?>]" value="<?php echo esc_attr( $attribute->get_name() ); ?>" />
<input type="hidden" name="attribute_names[<?php echo esc_attr( $i ); ?>]" value="<?php echo esc_attr( $attribute->get_name() ); ?>" />
<?php else : ?>
<input type="text" class="attribute_name" name="attribute_names[<?php echo $i; ?>]" value="<?php echo esc_attr( $attribute->get_name() ); ?>" />
<input type="text" class="attribute_name" name="attribute_names[<?php echo esc_attr( $i ); ?>]" value="<?php echo esc_attr( $attribute->get_name() ); ?>" />
<?php endif; ?>
<input type="hidden" name="attribute_position[<?php echo $i; ?>]" class="attribute_position" value="<?php echo esc_attr( $attribute->get_position() ); ?>" />
<input type="hidden" name="attribute_position[<?php echo esc_attr( $i ); ?>]" class="attribute_position" value="<?php echo esc_attr( $attribute->get_position() ); ?>" />
</td>
<td rowspan="3">
<label><?php _e( 'Value(s)', 'woocommerce' ); ?>:</label>
<label><?php esc_html_e( 'Value(s)', 'woocommerce' ); ?>:</label>
<?php if ( $attribute->is_taxonomy() && ( $attribute_taxonomy = $attribute->get_taxonomy_object() ) ) : ?>
<?php
if ( $attribute->is_taxonomy() && $attribute_taxonomy = $attribute->get_taxonomy_object() ) :
?>
<?php if ( 'select' === $attribute_taxonomy->attribute_type ) : ?>
<select multiple="multiple" data-placeholder="<?php esc_attr_e( 'Select terms', 'woocommerce' ); ?>" class="multiselect attribute_values wc-enhanced-select" name="attribute_values[<?php echo $i; ?>][]">
<select multiple="multiple" data-placeholder="<?php esc_attr_e( 'Select terms', 'woocommerce' ); ?>" class="multiselect attribute_values wc-enhanced-select" name="attribute_values[<?php echo esc_attr( $i ); ?>][]">
<?php
$args = array(
'orderby' => 'name',
@ -42,18 +44,18 @@ if ( ! defined( 'ABSPATH' ) ) {
foreach ( $all_terms as $term ) {
$options = $attribute->get_options();
$options = ! empty( $options ) ? $options : array();
echo '<option value="' . esc_attr( $term->term_id ) . '" ' . selected( in_array( $term->term_id, $options ), true, false ) . '>' . esc_attr( apply_filters( 'woocommerce_product_attribute_term_name', $term->name, $term ) ) . '</option>';
echo '<option value="' . esc_attr( $term->term_id ) . '" ' . selected( in_array( $term->term_id, $options, true ), true, false ) . '>' . esc_attr( apply_filters( 'woocommerce_product_attribute_term_name', $term->name, $term ) ) . '</option>';
}
}
?>
</select>
<button class="button plus select_all_attributes"><?php _e( 'Select all', 'woocommerce' ); ?></button>
<button class="button minus select_no_attributes"><?php _e( 'Select none', 'woocommerce' ); ?></button>
<button class="button fr plus add_new_attribute"><?php _e( 'Add new', 'woocommerce' ); ?></button>
<button class="button plus select_all_attributes"><?php esc_html_e( 'Select all', 'woocommerce' ); ?></button>
<button class="button minus select_no_attributes"><?php esc_html_e( 'Select none', 'woocommerce' ); ?></button>
<button class="button fr plus add_new_attribute"><?php esc_html_e( 'Add new', 'woocommerce' ); ?></button>
<?php elseif ( 'text' == $attribute_taxonomy->attribute_type ) : ?>
<?php elseif ( 'text' === $attribute_taxonomy->attribute_type ) : ?>
<input type="text" name="attribute_values[<?php echo $i; ?>]" value="<?php
<input type="text" name="attribute_values[<?php echo esc_attr( $i ); ?>]" value="<?php
// Text attributes should list terms pipe separated
echo esc_attr( wc_implode_text_attributes( wp_list_pluck( $attribute->get_terms(), 'name' ) ) );
@ -70,21 +72,21 @@ if ( ! defined( 'ABSPATH' ) ) {
<?php do_action( 'woocommerce_product_option_terms', $attribute_taxonomy, $i ); ?>
<?php else : ?>
<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 /* translators: %s: WC_DELIMITER */ ?>
<textarea name="attribute_values[<?php echo esc_attr( $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>
</tr>
<tr>
<td>
<label><input type="checkbox" class="checkbox" <?php checked( $attribute->get_visible(), true ); ?> name="attribute_visibility[<?php echo $i; ?>]" value="1" /> <?php _e( 'Visible on the product page', 'woocommerce' ); ?></label>
<label><input type="checkbox" class="checkbox" <?php checked( $attribute->get_visible(), true ); ?> name="attribute_visibility[<?php echo esc_attr( $i ); ?>]" value="1" /> <?php esc_html_e( 'Visible on the product page', 'woocommerce' ); ?></label>
</td>
</tr>
<tr>
<td>
<div class="enable_variation show_if_variable">
<label><input type="checkbox" class="checkbox" <?php checked( $attribute->get_variation(), true ); ?> name="attribute_variation[<?php echo $i; ?>]" value="1" /> <?php _e( 'Used for variations', 'woocommerce' ); ?></label>
<label><input type="checkbox" class="checkbox" <?php checked( $attribute->get_variation(), true ); ?> name="attribute_variation[<?php echo esc_attr( $i ); ?>]" value="1" /> <?php esc_html_e( 'Used for variations', 'woocommerce' ); ?></label>
</div>
</td>
</tr>

View File

@ -6,10 +6,10 @@ if ( ! defined( 'ABSPATH' ) ) {
<div id="product_attributes" class="panel wc-metaboxes-wrapper hidden">
<div class="toolbar toolbar-top">
<span class="expand-close">
<a href="#" class="expand_all"><?php _e( 'Expand', 'woocommerce' ); ?></a> / <a href="#" class="close_all"><?php _e( 'Close', 'woocommerce' ); ?></a>
<a href="#" class="expand_all"><?php esc_html_e( 'Expand', 'woocommerce' ); ?></a> / <a href="#" class="close_all"><?php esc_html_e( 'Close', 'woocommerce' ); ?></a>
</span>
<select name="attribute_taxonomy" class="attribute_taxonomy">
<option value=""><?php _e( 'Custom product attribute', 'woocommerce' ); ?></option>
<option value=""><?php esc_html_e( 'Custom product attribute', 'woocommerce' ); ?></option>
<?php
global $wc_product_attributes;
@ -25,7 +25,7 @@ if ( ! defined( 'ABSPATH' ) ) {
}
?>
</select>
<button type="button" class="button add_attribute"><?php _e( 'Add', 'woocommerce' ); ?></button>
<button type="button" class="button add_attribute"><?php esc_html_e( 'Add', 'woocommerce' ); ?></button>
</div>
<div class="product_attributes wc-metaboxes">
<?php
@ -48,9 +48,9 @@ if ( ! defined( 'ABSPATH' ) ) {
</div>
<div class="toolbar">
<span class="expand-close">
<a href="#" class="expand_all"><?php _e( 'Expand', 'woocommerce' ); ?></a> / <a href="#" class="close_all"><?php _e( 'Close', 'woocommerce' ); ?></a>
<a href="#" class="expand_all"><?php esc_html_e( 'Expand', 'woocommerce' ); ?></a> / <a href="#" class="close_all"><?php esc_html_e( 'Close', 'woocommerce' ); ?></a>
</span>
<button type="button" class="button save_attributes button-primary"><?php _e( 'Save attributes', 'woocommerce' ); ?></button>
<button type="button" class="button save_attributes button-primary"><?php esc_html_e( 'Save attributes', 'woocommerce' ); ?></button>
</div>
<?php do_action( 'woocommerce_product_options_attributes' ); ?>
</div>

View File

@ -46,10 +46,10 @@ if ( ! defined( 'ABSPATH' ) ) {
$sale_price_dates_to = $product_object->get_date_on_sale_to( 'edit' ) && ( $date = $product_object->get_date_on_sale_to( 'edit' )->getOffsetTimestamp() ) ? date_i18n( 'Y-m-d', $date ) : '';
echo '<p class="form-field sale_price_dates_fields">
<label for="_sale_price_dates_from">' . __( 'Sale price dates', 'woocommerce' ) . '</label>
<input type="text" class="short" name="_sale_price_dates_from" id="_sale_price_dates_from" value="' . esc_attr( $sale_price_dates_from ) . '" placeholder="' . _x( 'From&hellip;', 'placeholder', 'woocommerce' ) . ' YYYY-MM-DD" maxlength="10" pattern="' . esc_attr( apply_filters( 'woocommerce_date_input_html_pattern', '[0-9]{4}-(0[1-9]|1[012])-(0[1-9]|1[0-9]|2[0-9]|3[01])' ) ) . '" />
<input type="text" class="short" name="_sale_price_dates_to" id="_sale_price_dates_to" value="' . esc_attr( $sale_price_dates_to ) . '" placeholder="' . _x( 'To&hellip;', 'placeholder', 'woocommerce' ) . ' YYYY-MM-DD" maxlength="10" pattern="' . esc_attr( apply_filters( 'woocommerce_date_input_html_pattern', '[0-9]{4}-(0[1-9]|1[012])-(0[1-9]|1[0-9]|2[0-9]|3[01])' ) ) . '" />
<a href="#" class="description cancel_sale_schedule">' . __( 'Cancel', 'woocommerce' ) . '</a>' . wc_help_tip( __( 'The sale will end at the beginning of the set date.', 'woocommerce' ) ) . '
<label for="_sale_price_dates_from">' . esc_html__( 'Sale price dates', 'woocommerce' ) . '</label>
<input type="text" class="short" name="_sale_price_dates_from" id="_sale_price_dates_from" value="' . esc_attr( $sale_price_dates_from ) . '" placeholder="' . esc_html( _x( 'From&hellip;', 'placeholder', 'woocommerce' ) ) . ' YYYY-MM-DD" maxlength="10" pattern="' . esc_attr( apply_filters( 'woocommerce_date_input_html_pattern', '[0-9]{4}-(0[1-9]|1[012])-(0[1-9]|1[0-9]|2[0-9]|3[01])' ) ) . '" />
<input type="text" class="short" name="_sale_price_dates_to" id="_sale_price_dates_to" value="' . esc_attr( $sale_price_dates_to ) . '" placeholder="' . esc_html( _x( 'To&hellip;', 'placeholder', 'woocommerce' ) ) . ' YYYY-MM-DD" maxlength="10" pattern="' . esc_attr( apply_filters( 'woocommerce_date_input_html_pattern', '[0-9]{4}-(0[1-9]|1[012])-(0[1-9]|1[0-9]|2[0-9]|3[01])' ) ) . '" />
<a href="#" class="description cancel_sale_schedule">' . esc_html__( 'Cancel', 'woocommerce' ) . '</a>' . wc_help_tip( __( 'The sale will end at the beginning of the set date.', 'woocommerce' ) ) . '
</p>';
do_action( 'woocommerce_product_options_pricing' );
@ -58,19 +58,20 @@ if ( ! defined( 'ABSPATH' ) ) {
<div class="options_group show_if_downloadable hidden">
<div class="form-field downloadable_files">
<label><?php _e( 'Downloadable files', 'woocommerce' ); ?></label>
<label><?php esc_html_e( 'Downloadable files', 'woocommerce' ); ?></label>
<table class="widefat">
<thead>
<tr>
<th class="sort">&nbsp;</th>
<th><?php _e( 'Name', 'woocommerce' ); ?> <?php echo wc_help_tip( __( 'This is the name of the download shown to the customer.', 'woocommerce' ) ); ?></th>
<th colspan="2"><?php _e( 'File URL', 'woocommerce' ); ?> <?php echo wc_help_tip( __( 'This is the URL or absolute path to the file which customers will get access to. URLs entered here should already be encoded.', 'woocommerce' ) ); ?></th>
<th><?php esc_html_e( 'Name', 'woocommerce' ); ?> <?php echo wc_help_tip( __( 'This is the name of the download shown to the customer.', 'woocommerce' ) ); ?></th>
<th colspan="2"><?php esc_html_e( 'File URL', 'woocommerce' ); ?> <?php echo wc_help_tip( __( 'This is the URL or absolute path to the file which customers will get access to. URLs entered here should already be encoded.', 'woocommerce' ) ); ?></th>
<th>&nbsp;</th>
</tr>
</thead>
<tbody>
<?php
if ( $downloadable_files = $product_object->get_downloads( 'edit' ) ) {
$downloadable_files = $product_object->get_downloads( 'edit' );
if ( $downloadable_files ) {
foreach ( $downloadable_files as $key => $file ) {
include( 'html-product-download.php' );
}
@ -89,7 +90,7 @@ if ( ! defined( 'ABSPATH' ) ) {
ob_start();
include( 'html-product-download.php' );
echo esc_attr( ob_get_clean() );
?>"><?php _e( 'Add File', 'woocommerce' ); ?></a>
?>"><?php esc_html_e( 'Add File', 'woocommerce' ); ?></a>
</th>
</tr>
</tfoot>

View File

@ -11,7 +11,7 @@ if ( ! defined( 'ABSPATH' ) ) {
woocommerce_wp_text_input( array(
'id' => '_sku',
'value' => $product_object->get_sku( 'edit' ),
'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' ),
) );

View File

@ -7,7 +7,7 @@ if ( ! defined( 'ABSPATH' ) ) {
<div class="options_group show_if_grouped">
<p class="form-field">
<label for="grouped_products"><?php _e( 'Grouped products', 'woocommerce' ); ?></label>
<label for="grouped_products"><?php esc_html_e( 'Grouped products', 'woocommerce' ); ?></label>
<select class="wc-product-search" multiple="multiple" style="width: 50%;" id="grouped_products" name="grouped_products[]" data-sortable="true" data-placeholder="<?php esc_attr_e( 'Search for a product&hellip;', 'woocommerce' ); ?>" data-action="woocommerce_json_search_products" data-exclude="<?php echo intval( $post->ID ); ?>">
<?php
$product_ids = $product_object->get_children( 'edit' );
@ -25,7 +25,7 @@ if ( ! defined( 'ABSPATH' ) ) {
<div class="options_group">
<p class="form-field">
<label for="upsell_ids"><?php _e( 'Upsells', 'woocommerce' ); ?></label>
<label for="upsell_ids"><?php esc_html_e( 'Upsells', 'woocommerce' ); ?></label>
<select class="wc-product-search" multiple="multiple" style="width: 50%;" id="upsell_ids" name="upsell_ids[]" data-placeholder="<?php esc_attr_e( 'Search for a product&hellip;', 'woocommerce' ); ?>" data-action="woocommerce_json_search_products_and_variations" data-exclude="<?php echo intval( $post->ID ); ?>">
<?php
$product_ids = $product_object->get_upsell_ids( 'edit' );
@ -41,7 +41,7 @@ if ( ! defined( 'ABSPATH' ) ) {
</p>
<p class="form-field hide_if_grouped hide_if_external">
<label for="crosssell_ids"><?php _e( 'Cross-sells', 'woocommerce' ); ?></label>
<label for="crosssell_ids"><?php esc_html_e( 'Cross-sells', 'woocommerce' ); ?></label>
<select class="wc-product-search" multiple="multiple" style="width: 50%;" id="crosssell_ids" name="crosssell_ids[]" data-placeholder="<?php esc_attr_e( 'Search for a product&hellip;', 'woocommerce' ); ?>" data-action="woocommerce_json_search_products_and_variations" data-exclude="<?php echo intval( $post->ID ); ?>">
<?php
$product_ids = $product_object->get_cross_sell_ids( 'edit' );

View File

@ -32,8 +32,8 @@ if ( ! defined( 'ABSPATH' ) ) {
<ul class="product_data_tabs wc-tabs">
<?php foreach ( self::get_product_data_tabs() as $key => $tab ) : ?>
<li class="<?php echo $key; ?>_options <?php echo $key; ?>_tab <?php echo esc_attr( isset( $tab['class'] ) ? implode( ' ' , (array) $tab['class'] ) : '' ); ?>">
<a href="#<?php echo $tab['target']; ?>"><span><?php echo esc_html( $tab['label'] ); ?></span></a>
<li class="<?php echo esc_attr( $key ); ?>_options <?php echo esc_attr( $key ); ?>_tab <?php echo esc_attr( isset( $tab['class'] ) ? implode( ' ' , (array) $tab['class'] ) : '' ); ?>">
<a href="#<?php echo esc_attr( $tab['target'] ); ?>"><span><?php echo esc_html( $tab['label'] ); ?></span></a>
</li>
<?php endforeach; ?>
<?php do_action( 'woocommerce_product_write_panel_tabs' ); ?>

View File

@ -21,6 +21,7 @@ if ( ! defined( 'ABSPATH' ) ) {
if ( wc_product_dimensions_enabled() ) {
?><p class="form-field dimensions_field">
<?php /* translators: WooCommerce dimension unit*/ ?>
<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' ) ) ); ?>" />
@ -47,7 +48,7 @@ if ( ! defined( 'ABSPATH' ) ) {
'class' => 'select short',
);
?><p class="form-field dimensions_field">
<label for="product_shipping_class"><?php _e( 'Shipping class', 'woocommerce' ); ?></label>
<label for="product_shipping_class"><?php esc_html_e( 'Shipping class', 'woocommerce' ); ?></label>
<?php wp_dropdown_categories( $args ); ?>
<?php echo wc_help_tip( __( 'Shipping classes are used by certain shipping methods to group similar products.', 'woocommerce' ) ); ?>
</p><?php

View File

@ -9,20 +9,21 @@ if ( ! defined( 'ABSPATH' ) ) {
<?php if ( ! count( $variation_attributes ) ) : ?>
<div id="message" class="inline notice woocommerce-message">
<p><?php _e( 'Before you can add a variation you need to add some variation attributes on the <strong>Attributes</strong> tab.', 'woocommerce' ); ?></p>
<p><a class="button-primary" href="<?php echo esc_url( apply_filters( 'woocommerce_docs_url', 'https://docs.woocommerce.com/document/variable-product/', 'product-variations' ) ); ?>" target="_blank"><?php _e( 'Learn more', 'woocommerce' ); ?></a></p>
<p><?php esc_html_e( 'Before you can add a variation you need to add some variation attributes on the <strong>Attributes</strong> tab.', 'woocommerce' ); ?></p>
<p><a class="button-primary" href="<?php echo esc_url( apply_filters( 'woocommerce_docs_url', 'https://docs.woocommerce.com/document/variable-product/', 'product-variations' ) ); ?>" target="_blank"><?php esc_html_e( 'Learn more', 'woocommerce' ); ?></a></p>
</div>
<?php else : ?>
<div class="toolbar toolbar-variations-defaults">
<div class="variations-defaults">
<strong><?php _e( 'Default Form Values', 'woocommerce' ); ?>: <?php echo wc_help_tip( __( 'These are the attributes that will be pre-selected on the frontend.', 'woocommerce' ) ); ?></strong>
<strong><?php esc_html_e( 'Default Form Values', 'woocommerce' ); ?>: <?php echo wc_help_tip( __( 'These are the attributes that will be pre-selected on the frontend.', 'woocommerce' ) ); ?></strong>
<?php
foreach ( $variation_attributes as $attribute ) {
$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 ); ?>">
<?php /* translators: WooCommerce attribute label */ ?>
<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 ) : ?>
@ -43,59 +44,60 @@ if ( ! defined( 'ABSPATH' ) ) {
<div class="toolbar toolbar-top">
<select id="field_to_edit" class="variation_actions">
<option data-global="true" value="add_variation"><?php _e( 'Add variation', 'woocommerce' ); ?></option>
<option data-global="true" value="link_all_variations"><?php _e( 'Create variations from all attributes', 'woocommerce' ); ?></option>
<option value="delete_all"><?php _e( 'Delete all variations', 'woocommerce' ); ?></option>
<option data-global="true" value="add_variation"><?php esc_html_e( 'Add variation', 'woocommerce' ); ?></option>
<option data-global="true" value="link_all_variations"><?php esc_html_e( 'Create variations from all attributes', 'woocommerce' ); ?></option>
<option value="delete_all"><?php esc_html_e( 'Delete all variations', 'woocommerce' ); ?></option>
<optgroup label="<?php esc_attr_e( 'Status', 'woocommerce' ); ?>">
<option value="toggle_enabled"><?php _e( 'Toggle &quot;Enabled&quot;', 'woocommerce' ); ?></option>
<option value="toggle_downloadable"><?php _e( 'Toggle &quot;Downloadable&quot;', 'woocommerce' ); ?></option>
<option value="toggle_virtual"><?php _e( 'Toggle &quot;Virtual&quot;', 'woocommerce' ); ?></option>
<option value="toggle_enabled"><?php esc_html_e( 'Toggle &quot;Enabled&quot;', 'woocommerce' ); ?></option>
<option value="toggle_downloadable"><?php esc_html_e( 'Toggle &quot;Downloadable&quot;', 'woocommerce' ); ?></option>
<option value="toggle_virtual"><?php esc_html_e( 'Toggle &quot;Virtual&quot;', 'woocommerce' ); ?></option>
</optgroup>
<optgroup label="<?php esc_attr_e( 'Pricing', 'woocommerce' ); ?>">
<option value="variable_regular_price"><?php _e( 'Set regular prices', 'woocommerce' ); ?></option>
<option value="variable_regular_price_increase"><?php _e( 'Increase regular prices (fixed amount or percentage)', 'woocommerce' ); ?></option>
<option value="variable_regular_price_decrease"><?php _e( 'Decrease regular prices (fixed amount or percentage)', 'woocommerce' ); ?></option>
<option value="variable_sale_price"><?php _e( 'Set sale prices', 'woocommerce' ); ?></option>
<option value="variable_sale_price_increase"><?php _e( 'Increase sale prices (fixed amount or percentage)', 'woocommerce' ); ?></option>
<option value="variable_sale_price_decrease"><?php _e( 'Decrease sale prices (fixed amount or percentage)', 'woocommerce' ); ?></option>
<option value="variable_sale_schedule"><?php _e( 'Set scheduled sale dates', 'woocommerce' ); ?></option>
<option value="variable_regular_price"><?php esc_html_e( 'Set regular prices', 'woocommerce' ); ?></option>
<option value="variable_regular_price_increase"><?php esc_html_e( 'Increase regular prices (fixed amount or percentage)', 'woocommerce' ); ?></option>
<option value="variable_regular_price_decrease"><?php esc_html_e( 'Decrease regular prices (fixed amount or percentage)', 'woocommerce' ); ?></option>
<option value="variable_sale_price"><?php esc_html_e( 'Set sale prices', 'woocommerce' ); ?></option>
<option value="variable_sale_price_increase"><?php esc_html_e( 'Increase sale prices (fixed amount or percentage)', 'woocommerce' ); ?></option>
<option value="variable_sale_price_decrease"><?php esc_html_e( 'Decrease sale prices (fixed amount or percentage)', 'woocommerce' ); ?></option>
<option value="variable_sale_schedule"><?php esc_html_e( 'Set scheduled sale dates', 'woocommerce' ); ?></option>
</optgroup>
<optgroup label="<?php esc_attr_e( 'Inventory', 'woocommerce' ); ?>">
<option value="toggle_manage_stock"><?php _e( 'Toggle &quot;Manage stock&quot;', 'woocommerce' ); ?></option>
<option value="variable_stock"><?php _e( 'Stock', 'woocommerce' ); ?></option>
<option value="variable_stock_status_instock"><?php _e( 'Set Status - In stock', 'woocommerce' ); ?></option>
<option value="variable_stock_status_outofstock"><?php _e( 'Set Status - Out of stock', 'woocommerce' ); ?></option>
<option value="toggle_manage_stock"><?php esc_html_e( 'Toggle &quot;Manage stock&quot;', 'woocommerce' ); ?></option>
<option value="variable_stock"><?php esc_html_e( 'Stock', 'woocommerce' ); ?></option>
<option value="variable_stock_status_instock"><?php esc_html_e( 'Set Status - In stock', 'woocommerce' ); ?></option>
<option value="variable_stock_status_outofstock"><?php esc_html_e( 'Set Status - Out of stock', 'woocommerce' ); ?></option>
</optgroup>
<optgroup label="<?php esc_attr_e( 'Shipping', 'woocommerce' ); ?>">
<option value="variable_length"><?php _e( 'Length', 'woocommerce' ); ?></option>
<option value="variable_width"><?php _e( 'Width', 'woocommerce' ); ?></option>
<option value="variable_height"><?php _e( 'Height', 'woocommerce' ); ?></option>
<option value="variable_weight"><?php _e( 'Weight', 'woocommerce' ); ?></option>
<option value="variable_length"><?php esc_html_e( 'Length', 'woocommerce' ); ?></option>
<option value="variable_width"><?php esc_html_e( 'Width', 'woocommerce' ); ?></option>
<option value="variable_height"><?php esc_html_e( 'Height', 'woocommerce' ); ?></option>
<option value="variable_weight"><?php esc_html_e( 'Weight', 'woocommerce' ); ?></option>
</optgroup>
<optgroup label="<?php esc_attr_e( 'Downloadable products', 'woocommerce' ); ?>">
<option value="variable_download_limit"><?php _e( 'Download limit', 'woocommerce' ); ?></option>
<option value="variable_download_expiry"><?php _e( 'Download expiry', 'woocommerce' ); ?></option>
<option value="variable_download_limit"><?php esc_html_e( 'Download limit', 'woocommerce' ); ?></option>
<option value="variable_download_expiry"><?php esc_html_e( 'Download expiry', 'woocommerce' ); ?></option>
</optgroup>
<?php do_action( 'woocommerce_variable_product_bulk_edit_actions' ); ?>
</select>
<a class="button bulk_edit do_variation_action"><?php _e( 'Go', 'woocommerce' ); ?></a>
<a class="button bulk_edit do_variation_action"><?php esc_html_e( 'Go', 'woocommerce' ); ?></a>
<div class="variations-pagenav">
<span class="displaying-num"><?php printf( _n( '%s item', '%s items', $variations_count, 'woocommerce' ), $variations_count ); ?></span>
<?php /* translators: variations count */ ?>
<span class="displaying-num"><?php printf( esc_html( _n( '%s item', '%s items', $variations_count, 'woocommerce' ), $variations_count ) ); ?></span>
<span class="expand-close">
(<a href="#" class="expand_all"><?php _e( 'Expand', 'woocommerce' ); ?></a> / <a href="#" class="close_all"><?php _e( 'Close', 'woocommerce' ); ?></a>)
(<a href="#" class="expand_all"><?php esc_html_e( 'Expand', 'woocommerce' ); ?></a> / <a href="#" class="close_all"><?php esc_html_e( 'Close', 'woocommerce' ); ?></a>)
</span>
<span class="pagination-links">
<a class="first-page disabled" title="<?php esc_attr_e( 'Go to the first page', 'woocommerce' ); ?>" href="#">&laquo;</a>
<a class="prev-page disabled" title="<?php esc_attr_e( 'Go to the previous page', 'woocommerce' ); ?>" href="#">&lsaquo;</a>
<span class="paging-select">
<label for="current-page-selector-1" class="screen-reader-text"><?php _e( 'Select Page', 'woocommerce' ); ?></label>
<label for="current-page-selector-1" class="screen-reader-text"><?php esc_html_e( 'Select Page', 'woocommerce' ); ?></label>
<select class="page-selector" id="current-page-selector-1" title="<?php esc_attr_e( 'Current page', 'woocommerce' ); ?>">
<?php for ( $i = 1; $i <= $variations_total_pages; $i++ ) : ?>
<option value="<?php echo $i; ?>"><?php echo $i; ?></option>
<?php endfor; ?>
</select>
<?php _ex( 'of', 'number of pages', 'woocommerce' ); ?> <span class="total-pages"><?php echo $variations_total_pages; ?></span>
<?php _ex( 'of', 'number of pages', 'woocommerce' ); ?> <span class="total-pages"><?php echo esc_html( $variations_total_pages ); ?></span>
</span>
<a class="next-page" title="<?php esc_attr_e( 'Go to the next page', 'woocommerce' ); ?>" href="#">&rsaquo;</a>
<a class="last-page" title="<?php esc_attr_e( 'Go to the last page', 'woocommerce' ); ?>" href="#">&raquo;</a>
@ -106,24 +108,25 @@ if ( ! defined( 'ABSPATH' ) ) {
<div class="woocommerce_variations wc-metaboxes" data-attributes="<?php
// esc_attr does not double encode - htmlspecialchars does
echo htmlspecialchars( json_encode( wc_list_pluck( $variation_attributes, 'get_data' ) ) );
?>" data-total="<?php echo $variations_count; ?>" data-total_pages="<?php echo $variations_total_pages; ?>" data-page="1" data-edited="false">
echo htmlspecialchars( wp_json_encode( wc_list_pluck( $variation_attributes, 'get_data' ) ) );
?>" data-total="<?php echo esc_attr( $variations_count ); ?>" data-total_pages="<?php echo esc_attr( $variations_total_pages ); ?>" data-page="1" data-edited="false">
</div>
<div class="toolbar">
<button type="button" class="button-primary save-variation-changes" disabled="disabled"><?php _e( 'Save changes', 'woocommerce' ); ?></button>
<button type="button" class="button cancel-variation-changes" disabled="disabled"><?php _e( 'Cancel', 'woocommerce' ); ?></button>
<button type="button" class="button-primary save-variation-changes" disabled="disabled"><?php esc_html_e( 'Save changes', 'woocommerce' ); ?></button>
<button type="button" class="button cancel-variation-changes" disabled="disabled"><?php esc_html_e( 'Cancel', 'woocommerce' ); ?></button>
<div class="variations-pagenav">
<?php /* translators: variations count*/ ?>
<span class="displaying-num"><?php printf( _n( '%s item', '%s items', $variations_count, 'woocommerce' ), $variations_count ); ?></span>
<span class="expand-close">
(<a href="#" class="expand_all"><?php _e( 'Expand', 'woocommerce' ); ?></a> / <a href="#" class="close_all"><?php _e( 'Close', 'woocommerce' ); ?></a>)
(<a href="#" class="expand_all"><?php esc_html_e( 'Expand', 'woocommerce' ); ?></a> / <a href="#" class="close_all"><?php esc_html_e( 'Close', 'woocommerce' ); ?></a>)
</span>
<span class="pagination-links">
<a class="first-page disabled" title="<?php esc_attr_e( 'Go to the first page', 'woocommerce' ); ?>" href="#">&laquo;</a>
<a class="prev-page disabled" title="<?php esc_attr_e( 'Go to the previous page', 'woocommerce' ); ?>" href="#">&lsaquo;</a>
<span class="paging-select">
<label for="current-page-selector-1" class="screen-reader-text"><?php _e( 'Select Page', 'woocommerce' ); ?></label>
<label for="current-page-selector-1" class="screen-reader-text"><?php esc_html_e( 'Select Page', 'woocommerce' ); ?></label>
<select class="page-selector" id="current-page-selector-1" title="<?php esc_attr_e( 'Current page', 'woocommerce' ); ?>">
<?php for ( $i = 1; $i <= $variations_total_pages; $i++ ) : ?>
<option value="<?php echo $i; ?>"><?php echo $i; ?></option>

View File

@ -9,7 +9,7 @@ if ( ! defined( 'ABSPATH' ) ) {
<input type="text" class="input_text" placeholder="<?php esc_attr_e( 'File name', 'woocommerce' ); ?>" name="_wc_file_names[]" value="<?php echo esc_attr( $file['name'] ); ?>" />
<input type="hidden" name="_wc_file_hashes[]" value="<?php echo esc_attr( $key ); ?>" />
</td>
<td class="file_url"><input type="text" class="input_text" placeholder="<?php esc_attr_e( "http://", 'woocommerce' ); ?>" name="_wc_file_urls[]" value="<?php echo esc_attr( $file['file'] ); ?>" /></td>
<td class="file_url_choose" width="1%"><a href="#" class="button upload_file_button" data-choose="<?php esc_attr_e( 'Choose file', 'woocommerce' ); ?>" data-update="<?php esc_attr_e( 'Insert file URL', 'woocommerce' ); ?>"><?php echo str_replace( ' ', '&nbsp;', __( 'Choose file', 'woocommerce' ) ); ?></a></td>
<td width="1%"><a href="#" class="delete"><?php _e( 'Delete', 'woocommerce' ); ?></a></td>
<td class="file_url"><input type="text" class="input_text" placeholder="<?php esc_attr_e( 'http://', 'woocommerce' ); ?>" name="_wc_file_urls[]" value="<?php echo esc_attr( $file['file'] ); ?>" /></td>
<td class="file_url_choose" width="1%"><a href="#" class="button upload_file_button" data-choose="<?php esc_attr_e( 'Choose file', 'woocommerce' ); ?>" data-update="<?php esc_attr_e( 'Insert file URL', 'woocommerce' ); ?>"><?php echo esc_html__( 'Choose file', 'woocommerce' ); ?></a></td>
<td width="1%"><a href="#" class="delete"><?php esc_html_e( 'Delete', 'woocommerce' ); ?></a></td>
</tr>

View File

@ -5,10 +5,10 @@ if ( ! defined( 'ABSPATH' ) ) {
?>
<tr>
<td class="file_name">
<input type="text" class="input_text" placeholder="<?php esc_attr_e( 'File name', 'woocommerce' ); ?>" name="_wc_variation_file_names[<?php echo $variation_id; ?>][]" value="<?php echo esc_attr( $file['name'] ); ?>" />
<input type="hidden" name="_wc_variation_file_hashes[<?php echo $variation_id; ?>][]" value="<?php echo esc_attr( $key ); ?>" />
<input type="text" class="input_text" placeholder="<?php esc_attr_e( 'File name', 'woocommerce' ); ?>" name="_wc_variation_file_names[<?php echo esc_attr( $variation_id ); ?>][]" value="<?php echo esc_attr( $file['name'] ); ?>" />
<input type="hidden" name="_wc_variation_file_hashes[<?php echo esc_attr( $variation_id ); ?>][]" value="<?php echo esc_attr( $key ); ?>" />
</td>
<td class="file_url"><input type="text" class="input_text" placeholder="<?php esc_attr_e( "http://", 'woocommerce' ); ?>" name="_wc_variation_file_urls[<?php echo $variation_id; ?>][]" value="<?php echo esc_attr( $file['file'] ); ?>" /></td>
<td class="file_url_choose" width="1%"><a href="#" class="button upload_file_button" data-choose="<?php esc_attr_e( 'Choose file', 'woocommerce' ); ?>" data-update="<?php esc_attr_e( 'Insert file URL', 'woocommerce' ); ?>"><?php echo str_replace( ' ', '&nbsp;', __( 'Choose file', 'woocommerce' ) ); ?></a></td>
<td width="1%"><a href="#" class="delete"><?php _e( 'Delete', 'woocommerce' ); ?></a></td>
<td class="file_url"><input type="text" class="input_text" placeholder="<?php esc_attr_e( 'http://', 'woocommerce' ); ?>" name="_wc_variation_file_urls[<?php echo esc_attr( $variation_id ); ?>][]" value="<?php echo esc_attr( $file['file'] ); ?>" /></td>
<td class="file_url_choose" width="1%"><a href="#" class="button upload_file_button" data-choose="<?php esc_attr_e( 'Choose file', 'woocommerce' ); ?>" data-update="<?php esc_attr_e( 'Insert file URL', 'woocommerce' ); ?>"><?php esc_html_e( 'Choose file', 'woocommerce' ); ?></a></td>
<td width="1%"><a href="#" class="delete"><?php esc_html_e( 'Delete', 'woocommerce' ); ?></a></td>
</tr>

View File

@ -13,7 +13,7 @@ if ( ! defined( 'ABSPATH' ) ) {
?>
<div class="woocommerce_variation wc-metabox closed">
<h3>
<a href="#" class="remove_variation delete" rel="<?php echo esc_attr( $variation_id ); ?>"><?php _e( 'Remove', 'woocommerce' ); ?></a>
<a href="#" class="remove_variation delete" rel="<?php echo esc_attr( $variation_id ); ?>"><?php esc_html_e( 'Remove', 'woocommerce' ); ?></a>
<div class="handlediv" aria-label="<?php esc_attr_e( 'Click to toggle', 'woocommerce' ); ?>"></div>
<div class="tips sort" data-tip="<?php esc_attr_e( 'Drag and drop, or click to set admin variation order', 'woocommerce' ); ?>"></div>
<strong>#<?php echo esc_html( $variation_id ); ?> </strong>
@ -44,14 +44,14 @@ if ( ! defined( 'ABSPATH' ) ) {
<?php
}
?>
<input type="hidden" name="variable_post_id[<?php echo $loop; ?>]" value="<?php echo esc_attr( $variation_id ); ?>" />
<input type="hidden" class="variation_menu_order" name="variation_menu_order[<?php echo $loop; ?>]" value="<?php echo esc_attr( $variation_object->get_menu_order( 'edit' ) ); ?>" />
<input type="hidden" name="variable_post_id[<?php echo esc_attr( $loop ); ?>]" value="<?php echo esc_attr( $variation_id ); ?>" />
<input type="hidden" class="variation_menu_order" name="variation_menu_order[<?php echo esc_attr( $loop ); ?>]" value="<?php echo esc_attr( $variation_object->get_menu_order( 'edit' ) ); ?>" />
</h3>
<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' ) ? 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' ) ); ?>" />
<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 esc_attr( $loop ); ?>]" class="upload_image_id" value="<?php echo esc_attr( $variation_object->get_image_id( 'edit' ) ); ?>" />
</a>
</p>
<?php
@ -70,22 +70,22 @@ if ( ! defined( 'ABSPATH' ) ) {
?>
<p class="form-row form-row-full options">
<label>
<?php _e( 'Enabled', 'woocommerce' ); ?>:
<input type="checkbox" class="checkbox" name="variable_enabled[<?php echo $loop; ?>]" <?php checked( in_array( $variation_object->get_status( 'edit' ), array( 'publish', false ) ), true ); ?> />
<?php esc_html_e( 'Enabled', 'woocommerce' ); ?>:
<input type="checkbox" class="checkbox" name="variable_enabled[<?php echo $loop; ?>]" <?php checked( in_array( $variation_object->get_status( 'edit' ), array( 'publish', false ), true ), true ); ?> />
</label>
<label class="tips" data-tip="<?php _e( 'Enable this option if access is given to a downloadable file upon purchase of a product', 'woocommerce' ); ?>">
<?php _e( 'Downloadable', 'woocommerce' ); ?>:
<input type="checkbox" class="checkbox variable_is_downloadable" name="variable_is_downloadable[<?php echo $loop; ?>]" <?php checked( $variation_object->get_downloadable( 'edit' ), true ); ?> />
<label class="tips" data-tip="<?php esc_html_e( 'Enable this option if access is given to a downloadable file upon purchase of a product', 'woocommerce' ); ?>">
<?php esc_html_e( 'Downloadable', 'woocommerce' ); ?>:
<input type="checkbox" class="checkbox variable_is_downloadable" name="variable_is_downloadable[<?php echo esc_attr( $loop ); ?>]" <?php checked( $variation_object->get_downloadable( 'edit' ), true ); ?> />
</label>
<label class="tips" data-tip="<?php _e( 'Enable this option if a product is not shipped or there is no shipping cost', 'woocommerce' ); ?>">
<?php _e( 'Virtual', 'woocommerce' ); ?>:
<input type="checkbox" class="checkbox variable_is_virtual" name="variable_is_virtual[<?php echo $loop; ?>]" <?php checked( $variation_object->get_virtual( 'edit' ), true ); ?> />
<label class="tips" data-tip="<?php esc_html_e( 'Enable this option if a product is not shipped or there is no shipping cost', 'woocommerce' ); ?>">
<?php esc_html_e( 'Virtual', 'woocommerce' ); ?>:
<input type="checkbox" class="checkbox variable_is_virtual" name="variable_is_virtual[<?php echo esc_attr( $loop ); ?>]" <?php checked( $variation_object->get_virtual( 'edit' ), true ); ?> />
</label>
<?php if ( 'yes' === get_option( 'woocommerce_manage_stock' ) ) : ?>
<label class="tips" data-tip="<?php _e( 'Enable this option to enable stock management at variation level', 'woocommerce' ); ?>">
<?php _e( 'Manage stock?', 'woocommerce' ); ?>
<input type="checkbox" class="checkbox variable_manage_stock" name="variable_manage_stock[<?php echo $loop; ?>]" <?php checked( $variation_object->get_manage_stock( 'edit' ), true ); ?> />
<label class="tips" data-tip="<?php esc_html_e( 'Enable this option to enable stock management at variation level', 'woocommerce' ); ?>">
<?php esc_html_e( 'Manage stock?', 'woocommerce' ); ?>
<input type="checkbox" class="checkbox variable_manage_stock" name="variable_manage_stock[<?php echo esc_attr( $loop ); ?>]" <?php checked( $variation_object->get_manage_stock( 'edit' ), true ); ?> />
</label>
<?php endif; ?>
@ -94,8 +94,8 @@ if ( ! defined( 'ABSPATH' ) ) {
<div class="variable_pricing">
<?php
/* translators: %s: currency symbol */
$label = sprintf(
/* translators: %s: currency symbol */
__( 'Regular price (%s)', 'woocommerce' ),
get_woocommerce_currency_symbol()
);
@ -109,9 +109,9 @@ if ( ! defined( 'ABSPATH' ) ) {
'wrapper_class' => 'form-row form-row-first',
'placeholder' => __( 'Variation price (required)', 'woocommerce' ),
) );
/* translators: %s: currency symbol */
$label = sprintf(
/* translators: %s: currency symbol */
__( 'Sale price (%s)', 'woocommerce' ),
get_woocommerce_currency_symbol()
);
@ -121,7 +121,7 @@ if ( ! defined( 'ABSPATH' ) ) {
'name' => "variable_sale_price[{$loop}]",
'value' => wc_format_localized_price( $variation_object->get_sale_price( 'edit' ) ),
'data_type' => 'price',
'label' => $label . ' <a href="#" class="sale_schedule">' . __( 'Schedule', 'woocommerce' ) . '</a><a href="#" class="cancel_sale_schedule hidden">' . __( 'Cancel schedule', 'woocommerce' ) . '</a>',
'label' => $label . ' <a href="#" class="sale_schedule">' . esc_html__( 'Schedule', 'woocommerce' ) . '</a><a href="#" class="cancel_sale_schedule hidden">' . esc_html__( 'Cancel schedule', 'woocommerce' ) . '</a>',
'wrapper_class' => 'form-row form-row-last',
) );
@ -135,7 +135,7 @@ if ( ! defined( 'ABSPATH' ) ) {
</p>
<p class="form-row form-row-last">
<label>' . __( 'Sale end date', 'woocommerce' ) . '</label>
<input type="text" class="sale_price_dates_to" name="variable_sale_price_dates_to[' . $loop . ']" value="' . esc_attr( $sale_price_dates_to ) . '" placeholder="' . _x( 'To&hellip;', 'placeholder', 'woocommerce' ) . ' YYYY-MM-DD" maxlength="10" pattern="' . esc_attr( apply_filters( 'woocommerce_date_input_html_pattern', '[0-9]{4}-(0[1-9]|1[012])-(0[1-9]|1[0-9]|2[0-9]|3[01])' ) ) . '" />
<input type="text" class="sale_price_dates_to" name="variable_sale_price_dates_to[' . esc_attr( $loop ) . ']" value="' . esc_attr( $sale_price_dates_to ) . '" placeholder="' . esc_html_x( 'To&hellip;', 'placeholder', 'woocommerce' ) . ' YYYY-MM-DD" maxlength="10" pattern="' . esc_attr( apply_filters( 'woocommerce_date_input_html_pattern', '[0-9]{4}-(0[1-9]|1[012])-(0[1-9]|1[0-9]|2[0-9]|3[01])' ) ) . '" />
</p>
</div>';
@ -170,7 +170,7 @@ if ( ! defined( 'ABSPATH' ) ) {
'wrapper_class' => 'form-row form-row-first',
) );
echo '<input type="hidden" name="variable_original_stock[' . $loop . ']" value="' . esc_attr( wc_stock_amount( $variation_object->get_stock_quantity( 'edit' ) ) ) . '" />';
echo '<input type="hidden" name="variable_original_stock[' . esc_attr( $loop ) . ']" value="' . esc_attr( wc_stock_amount( $variation_object->get_stock_quantity( 'edit' ) ) ) . '" />';
woocommerce_wp_select( array(
'id' => "variable_backorders{$loop}",
@ -211,8 +211,8 @@ if ( ! defined( 'ABSPATH' ) ) {
) );
if ( wc_product_weight_enabled() ) {
/* translators: %s: weight unit */
$label = sprintf(
/* translators: %s: weight unit */
__( 'Weight (%s)', 'woocommerce' ),
esc_html( get_option( 'woocommerce_weight_unit' ) )
);
@ -238,17 +238,17 @@ if ( ! defined( 'ABSPATH' ) ) {
?><p class="form-field form-row dimensions_field hide_if_variation_virtual form-row-last">
<label for="product_length"><?php
/* translators: %s: dimension unit */
printf(
__( 'Dimensions (L&times;W&times;H) (%s)', 'woocommerce' ),
/* translators: %s: dimension unit */
esc_html__( 'Dimensions (L&times;W&times;H) (%s)', 'woocommerce' ),
get_option( 'woocommerce_dimension_unit' )
);
?></label>
<?php echo wc_help_tip( __( 'Length x width x height in decimal form', 'woocommerce' ) ); ?>
<span class="wrap">
<input id="product_length" placeholder="<?php echo $parent_length ? esc_attr( $parent_length ) : esc_attr__( 'Length', 'woocommerce' ); ?>" class="input-text wc_input_decimal" size="6" type="text" name="variable_length[<?php echo $loop; ?>]" value="<?php echo esc_attr( wc_format_localized_decimal( $variation_object->get_length( 'edit' ) ) ); ?>" />
<input placeholder="<?php echo $parent_width ? esc_attr( $parent_width ) : esc_attr__( 'Width', 'woocommerce' ); ?>" class="input-text wc_input_decimal" size="6" type="text" name="variable_width[<?php echo $loop; ?>]" value="<?php echo esc_attr( wc_format_localized_decimal( $variation_object->get_width( 'edit' ) ) ); ?>" />
<input placeholder="<?php echo $parent_height ? esc_attr( $parent_height ) : esc_attr__( 'Height', 'woocommerce' ); ?>" class="input-text wc_input_decimal last" size="6" type="text" name="variable_height[<?php echo $loop; ?>]" value="<?php echo esc_attr( wc_format_localized_decimal( $variation_object->get_height( 'edit' ) ) ); ?>" />
<input id="product_length" placeholder="<?php echo $parent_length ? esc_attr( $parent_length ) : esc_attr__( 'Length', 'woocommerce' ); ?>" class="input-text wc_input_decimal" size="6" type="text" name="variable_length[<?php echo esc_attr( $loop ); ?>]" value="<?php echo esc_attr( wc_format_localized_decimal( $variation_object->get_length( 'edit' ) ) ); ?>" />
<input placeholder="<?php echo $parent_width ? esc_attr( $parent_width ) : esc_attr__( 'Width', 'woocommerce' ); ?>" class="input-text wc_input_decimal" size="6" type="text" name="variable_width[<?php echo esc_attr( $loop ); ?>]" value="<?php echo esc_attr( wc_format_localized_decimal( $variation_object->get_width( 'edit' ) ) ); ?>" />
<input placeholder="<?php echo $parent_height ? esc_attr( $parent_height ) : esc_attr__( 'Height', 'woocommerce' ); ?>" class="input-text wc_input_decimal last" size="6" type="text" name="variable_height[<?php echo esc_attr( $loop ); ?>]" value="<?php echo esc_attr( wc_format_localized_decimal( $variation_object->get_height( 'edit' ) ) ); ?>" />
</span>
</p><?php
}
@ -267,7 +267,7 @@ if ( ! defined( 'ABSPATH' ) ) {
</div>
<div>
<p class="form-row hide_if_variation_virtual form-row-full"><label><?php _e( 'Shipping class', 'woocommerce' ); ?></label> <?php
<p class="form-row hide_if_variation_virtual form-row-full"><label><?php esc_html_e( 'Shipping class', 'woocommerce' ); ?></label> <?php
wp_dropdown_categories( array(
'taxonomy' => 'product_shipping_class',
'hide_empty' => 0,
@ -319,12 +319,12 @@ if ( ! defined( 'ABSPATH' ) ) {
</div>
<div class="show_if_variation_downloadable" style="display: none;">
<div class="form-row form-row-full downloadable_files">
<label><?php _e( 'Downloadable files', 'woocommerce' ); ?></label>
<label><?php esc_html_e( 'Downloadable files', 'woocommerce' ); ?></label>
<table class="widefat">
<thead>
<div>
<th><?php _e( 'Name', 'woocommerce' ); ?> <?php echo wc_help_tip( __( 'This is the name of the download shown to the customer.', 'woocommerce' ) ); ?></th>
<th colspan="2"><?php _e( 'File URL', 'woocommerce' ); ?> <?php echo wc_help_tip( __( 'This is the URL or absolute path to the file which customers will get access to. URLs entered here should already be encoded.', 'woocommerce' ) ); ?></th>
<th><?php esc_html_e( 'Name', 'woocommerce' ); ?> <?php echo wc_help_tip( __( 'This is the name of the download shown to the customer.', 'woocommerce' ) ); ?></th>
<th colspan="2"><?php esc_html_e( 'File URL', 'woocommerce' ); ?> <?php echo wc_help_tip( __( 'This is the URL or absolute path to the file which customers will get access to. URLs entered here should already be encoded.', 'woocommerce' ) ); ?></th>
<th>&nbsp;</th>
</div>
</thead>
@ -349,7 +349,7 @@ if ( ! defined( 'ABSPATH' ) ) {
ob_start();
include( 'html-product-variation-download.php' );
echo esc_attr( ob_get_clean() );
?>"><?php _e( 'Add file', 'woocommerce' ); ?></a>
?>"><?php esc_html_e( 'Add file', 'woocommerce' ); ?></a>
</th>
</div>
</tfoot>

View File

@ -658,8 +658,12 @@ class WC_Admin_Report {
return;
}
if ( ! isset( $_GET['wc_reports_nonce'] ) || ! wp_verify_nonce( $_GET['wc_reports_nonce'], 'custom_range' ) ) {
wp_safe_redirect( remove_query_arg( array( 'start_date', 'end_date', 'range', 'wc_reports_nonce' ) ) );
if ( ! isset( $_GET['wc_reports_nonce'] ) || ! wp_verify_nonce( sanitize_key( $_GET['wc_reports_nonce'] ), 'custom_range' ) ) { // WPCS: input var ok, CSRF ok.
wp_die(
/* translators: %1$s: open link, %2$s: close link */
sprintf( esc_html__( 'This report link has expired. %1$sClick here to view the filtered report%2$s.', 'woocommerce' ), '<a href="' . esc_url( wp_nonce_url( esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) ), 'custom_range', 'wc_reports_nonce' ) ) . '">', '</a>' ), // @codingStandardsIgnoreLine.
esc_attr__( 'Confirm navigation', 'woocommerce' )
);
exit;
}
}

View File

@ -507,7 +507,7 @@ class WC_REST_Coupons_Controller extends WC_REST_Legacy_Coupons_Controller {
),
'value' => array(
'description' => __( 'Meta value.', 'woocommerce' ),
'type' => 'string',
'type' => 'mixed',
'context' => array( 'view', 'edit' ),
),
),

View File

@ -354,7 +354,7 @@ class WC_REST_Customers_Controller extends WC_REST_Customers_V1_Controller {
),
'value' => array(
'description' => __( 'Meta value.', 'woocommerce' ),
'type' => 'string',
'type' => 'mixed',
'context' => array( 'view', 'edit' ),
),
),

View File

@ -401,7 +401,7 @@ class WC_REST_Order_Refunds_Controller extends WC_REST_Orders_Controller {
),
'value' => array(
'description' => __( 'Meta value.', 'woocommerce' ),
'type' => 'string',
'type' => 'mixed',
'context' => array( 'view', 'edit' ),
),
),
@ -422,12 +422,12 @@ class WC_REST_Order_Refunds_Controller extends WC_REST_Orders_Controller {
),
'name' => array(
'description' => __( 'Product name.', 'woocommerce' ),
'type' => 'string',
'type' => 'mixed',
'context' => array( 'view', 'edit' ),
),
'product_id' => array(
'description' => __( 'Product ID.', 'woocommerce' ),
'type' => 'integer',
'type' => 'mixed',
'context' => array( 'view', 'edit' ),
),
'variation_id' => array(
@ -513,7 +513,7 @@ class WC_REST_Order_Refunds_Controller extends WC_REST_Orders_Controller {
),
'value' => array(
'description' => __( 'Meta value.', 'woocommerce' ),
'type' => 'string',
'type' => 'mixed',
'context' => array( 'view', 'edit' ),
),
),

View File

@ -597,8 +597,9 @@ class WC_REST_Orders_Controller extends WC_REST_Legacy_Orders_Controller {
protected function maybe_set_item_meta_data( $item, $posted ) {
if ( ! empty( $posted['meta_data'] ) && is_array( $posted['meta_data'] ) ) {
foreach ( $posted['meta_data'] as $meta ) {
if ( isset( $meta['key'], $meta['value'] ) ) {
$item->update_meta_data( $meta['key'], $meta['value'], isset( $meta['id'] ) ? $meta['id'] : '' );
if ( isset( $meta['key'] ) ) {
$value = isset( $meta['value'] ) ? $meta['value'] : null;
$item->update_meta_data( $meta['key'], $value, isset( $meta['id'] ) ? $meta['id'] : '' );
}
}
}
@ -1118,7 +1119,7 @@ class WC_REST_Orders_Controller extends WC_REST_Legacy_Orders_Controller {
),
'value' => array(
'description' => __( 'Meta value.', 'woocommerce' ),
'type' => 'string',
'type' => 'mixed',
'context' => array( 'view', 'edit' ),
),
),
@ -1139,12 +1140,12 @@ class WC_REST_Orders_Controller extends WC_REST_Legacy_Orders_Controller {
),
'name' => array(
'description' => __( 'Product name.', 'woocommerce' ),
'type' => 'string',
'type' => 'mixed',
'context' => array( 'view', 'edit' ),
),
'product_id' => array(
'description' => __( 'Product ID.', 'woocommerce' ),
'type' => 'integer',
'type' => 'mixed',
'context' => array( 'view', 'edit' ),
),
'variation_id' => array(
@ -1230,7 +1231,7 @@ class WC_REST_Orders_Controller extends WC_REST_Legacy_Orders_Controller {
),
'value' => array(
'description' => __( 'Meta value.', 'woocommerce' ),
'type' => 'string',
'type' => 'mixed',
'context' => array( 'view', 'edit' ),
),
),
@ -1321,7 +1322,7 @@ class WC_REST_Orders_Controller extends WC_REST_Legacy_Orders_Controller {
),
'value' => array(
'description' => __( 'Meta value.', 'woocommerce' ),
'type' => 'string',
'type' => 'mixed',
'context' => array( 'view', 'edit' ),
),
),
@ -1345,12 +1346,12 @@ class WC_REST_Orders_Controller extends WC_REST_Legacy_Orders_Controller {
),
'method_title' => array(
'description' => __( 'Shipping method name.', 'woocommerce' ),
'type' => 'string',
'type' => 'mixed',
'context' => array( 'view', 'edit' ),
),
'method_id' => array(
'description' => __( 'Shipping method ID.', 'woocommerce' ),
'type' => 'string',
'type' => 'mixed',
'context' => array( 'view', 'edit' ),
),
'total' => array(
@ -1407,7 +1408,7 @@ class WC_REST_Orders_Controller extends WC_REST_Legacy_Orders_Controller {
),
'value' => array(
'description' => __( 'Meta value.', 'woocommerce' ),
'type' => 'string',
'type' => 'mixed',
'context' => array( 'view', 'edit' ),
),
),
@ -1431,7 +1432,7 @@ class WC_REST_Orders_Controller extends WC_REST_Legacy_Orders_Controller {
),
'name' => array(
'description' => __( 'Fee name.', 'woocommerce' ),
'type' => 'string',
'type' => 'mixed',
'context' => array( 'view', 'edit' ),
),
'tax_class' => array(
@ -1505,7 +1506,7 @@ class WC_REST_Orders_Controller extends WC_REST_Legacy_Orders_Controller {
),
'value' => array(
'description' => __( 'Meta value.', 'woocommerce' ),
'type' => 'string',
'type' => 'mixed',
'context' => array( 'view', 'edit' ),
),
),
@ -1529,7 +1530,7 @@ class WC_REST_Orders_Controller extends WC_REST_Legacy_Orders_Controller {
),
'code' => array(
'description' => __( 'Coupon code.', 'woocommerce' ),
'type' => 'string',
'type' => 'mixed',
'context' => array( 'view', 'edit' ),
),
'discount' => array(
@ -1563,7 +1564,7 @@ class WC_REST_Orders_Controller extends WC_REST_Legacy_Orders_Controller {
),
'value' => array(
'description' => __( 'Meta value.', 'woocommerce' ),
'type' => 'string',
'type' => 'mixed',
'context' => array( 'view', 'edit' ),
),
),

View File

@ -945,7 +945,7 @@ class WC_REST_Product_Variations_Controller extends WC_REST_Products_Controller
),
'value' => array(
'description' => __( 'Meta value.', 'woocommerce' ),
'type' => 'string',
'type' => 'mixed',
'context' => array( 'view', 'edit' ),
),
),

View File

@ -1991,7 +1991,7 @@ class WC_REST_Products_Controller extends WC_REST_Legacy_Products_Controller {
),
'value' => array(
'description' => __( 'Meta value.', 'woocommerce' ),
'type' => 'string',
'type' => 'mixed',
'context' => array( 'view', 'edit' ),
),
),

View File

@ -378,7 +378,7 @@ class WC_REST_Order_Refunds_V1_Controller extends WC_REST_Orders_V1_Controller {
),
'name' => array(
'description' => __( 'Product name.', 'woocommerce' ),
'type' => 'string',
'type' => 'mixed',
'context' => array( 'view', 'edit' ),
'readonly' => true,
),
@ -390,7 +390,7 @@ class WC_REST_Order_Refunds_V1_Controller extends WC_REST_Orders_V1_Controller {
),
'product_id' => array(
'description' => __( 'Product ID.', 'woocommerce' ),
'type' => 'integer',
'type' => 'mixed',
'context' => array( 'view', 'edit' ),
),
'variation_id' => array(
@ -486,7 +486,7 @@ class WC_REST_Order_Refunds_V1_Controller extends WC_REST_Orders_V1_Controller {
),
'value' => array(
'description' => __( 'Meta value.', 'woocommerce' ),
'type' => 'string',
'type' => 'mixed',
'context' => array( 'view', 'edit' ),
'readonly' => true,
),

View File

@ -1211,7 +1211,7 @@ class WC_REST_Orders_V1_Controller extends WC_REST_Posts_Controller {
),
'name' => array(
'description' => __( 'Product name.', 'woocommerce' ),
'type' => 'string',
'type' => 'mixed',
'context' => array( 'view', 'edit' ),
'readonly' => true,
),
@ -1223,7 +1223,7 @@ class WC_REST_Orders_V1_Controller extends WC_REST_Posts_Controller {
),
'product_id' => array(
'description' => __( 'Product ID.', 'woocommerce' ),
'type' => 'integer',
'type' => 'mixed',
'context' => array( 'view', 'edit' ),
),
'variation_id' => array(
@ -1319,7 +1319,7 @@ class WC_REST_Orders_V1_Controller extends WC_REST_Posts_Controller {
),
'value' => array(
'description' => __( 'Meta value.', 'woocommerce' ),
'type' => 'string',
'type' => 'mixed',
'context' => array( 'view', 'edit' ),
'readonly' => true,
),
@ -1397,12 +1397,12 @@ class WC_REST_Orders_V1_Controller extends WC_REST_Posts_Controller {
),
'method_title' => array(
'description' => __( 'Shipping method name.', 'woocommerce' ),
'type' => 'string',
'type' => 'mixed',
'context' => array( 'view', 'edit' ),
),
'method_id' => array(
'description' => __( 'Shipping method ID.', 'woocommerce' ),
'type' => 'string',
'type' => 'mixed',
'context' => array( 'view', 'edit' ),
),
'total' => array(
@ -1457,7 +1457,7 @@ class WC_REST_Orders_V1_Controller extends WC_REST_Posts_Controller {
),
'name' => array(
'description' => __( 'Fee name.', 'woocommerce' ),
'type' => 'string',
'type' => 'mixed',
'context' => array( 'view', 'edit' ),
),
'tax_class' => array(
@ -1528,7 +1528,7 @@ class WC_REST_Orders_V1_Controller extends WC_REST_Posts_Controller {
),
'code' => array(
'description' => __( 'Coupon code.', 'woocommerce' ),
'type' => 'string',
'type' => 'mixed',
'context' => array( 'view', 'edit' ),
),
'discount' => array(

View File

@ -388,7 +388,7 @@ class WC_AJAX {
}
/**
* AJAX add to cart.
* AJAX remove from cart.
*/
public static function remove_from_cart() {
ob_start();
@ -1735,9 +1735,6 @@ class WC_AJAX {
wp_send_json_success( $response_data );
} catch ( Exception $e ) {
if ( $refund && is_a( $refund, 'WC_Order_Refund' ) ) {
wp_delete_post( $refund->get_id(), true );
}
wp_send_json_error( array( 'error' => $e->getMessage() ) );
}
}

View File

@ -227,7 +227,7 @@ final class WC_Cart_Totals {
$item->taxable = 'taxable' === $cart_item['data']->get_tax_status();
$item->price_includes_tax = wc_prices_include_tax();
$item->quantity = $cart_item['quantity'];
$item->price = wc_add_number_precision_deep( $cart_item['data']->get_price() ) * $cart_item['quantity'];
$item->price = wc_add_number_precision_deep( $cart_item['data']->get_price() * $cart_item['quantity'] );
$item->product = $cart_item['data'];
$item->tax_rates = $this->get_item_tax_rates( $item );
$this->items[ $cart_item_key ] = $item;
@ -349,8 +349,8 @@ final class WC_Cart_Totals {
$shipping_line->tax_class = get_option( 'woocommerce_shipping_tax_class' );
$shipping_line->taxable = true;
$shipping_line->total = wc_add_number_precision_deep( $shipping_object->cost );
$shipping_line->taxes = wc_add_number_precision_deep( $shipping_object->taxes );
$shipping_line->total_tax = wc_add_number_precision_deep( array_sum( $shipping_object->taxes ) );
$shipping_line->taxes = wc_add_number_precision_deep( $shipping_object->taxes, false );
$shipping_line->total_tax = wc_add_number_precision_deep( array_sum( $shipping_object->taxes ), false );
if ( ! $this->round_at_subtotal() ) {
$shipping_line->total_tax = wc_round_tax_total( $shipping_line->total_tax, wc_get_rounding_precision() );
@ -423,7 +423,7 @@ final class WC_Cart_Totals {
* @return object
*/
protected function remove_item_base_taxes( $item ) {
if ( $item->price_includes_tax ) {
if ( $item->price_includes_tax && $item->taxable ) {
$base_tax_rates = WC_Tax::get_base_tax_rates( $item->product->get_tax_class( 'unfiltered' ) );
// Work out a new base price without the shop's base tax.
@ -449,7 +449,7 @@ final class WC_Cart_Totals {
* @return object
*/
protected function adjust_non_base_location_price( $item ) {
if ( $item->price_includes_tax ) {
if ( $item->price_includes_tax && $item->taxable ) {
$base_tax_rates = WC_Tax::get_base_tax_rates( $item->product->get_tax_class( 'unfiltered' ) );
if ( $item->tax_rates !== $base_tax_rates ) {

View File

@ -981,6 +981,23 @@ class WC_Cart extends WC_Legacy_Cart {
return array_unique( $found_tax_classes );
}
/**
* Get all tax classes for shipping based on the items in the cart.
*
* @return array
*/
public function get_cart_item_tax_classes_for_shipping() {
$found_tax_classes = array();
foreach ( WC()->cart->get_cart() as $item ) {
if ( $item['data'] && ( $item['data']->is_shipping_taxable() ) ) {
$found_tax_classes[] = $item['data']->get_tax_class();
}
}
return array_unique( $found_tax_classes );
}
/**
* Determines the value that the customer spent and the subtotal
* displayed, used for things like coupon validation.
@ -1085,7 +1102,7 @@ class WC_Cart extends WC_Legacy_Cart {
}
// Load cart item data - may be added by other plugins.
$cart_item_data = (array) apply_filters( 'woocommerce_add_cart_item_data', $cart_item_data, $product_id, $variation_id );
$cart_item_data = (array) apply_filters( 'woocommerce_add_cart_item_data', $cart_item_data, $product_id, $variation_id, $quantity );
// Generate a ID based on product ID, variation ID, variation data, and other cart item data.
$cart_id = $this->generate_cart_id( $product_id, $variation_id, $variation, $cart_item_data );

View File

@ -469,7 +469,7 @@ class WC_Checkout {
* @param WC_Cart $cart
*/
public function create_order_tax_lines( &$order, $cart ) {
foreach ( array_keys( $cart->get_cart_contents_taxes() + $cart->get_shipping_taxes() ) as $tax_rate_id ) {
foreach ( array_keys( $cart->get_cart_contents_taxes() + $cart->get_shipping_taxes() + $cart->get_fee_taxes() ) as $tax_rate_id ) {
if ( $tax_rate_id && apply_filters( 'woocommerce_cart_remove_taxes_zero_rate_id', 'zero-rated' ) !== $tax_rate_id ) {
$item = new WC_Order_Item_Tax();
$item->set_props( array(

View File

@ -218,7 +218,10 @@ class WC_Comments {
$stats = get_transient( 'wc_count_comments' );
if ( ! $stats ) {
$stats = array();
$stats = array(
'total_comments' => 0,
'all' => 0,
);
$count = $wpdb->get_results( "
SELECT comment_approved, COUNT(*) AS num_comments
@ -227,7 +230,6 @@ class WC_Comments {
GROUP BY comment_approved
", ARRAY_A );
$total = 0;
$approved = array(
'0' => 'moderated',
'1' => 'approved',
@ -238,16 +240,17 @@ class WC_Comments {
foreach ( (array) $count as $row ) {
// Don't count post-trashed toward totals.
if ( 'post-trashed' !== $row['comment_approved'] && 'trash' !== $row['comment_approved'] ) {
$total += $row['num_comments'];
if ( ! in_array( $row['comment_approved'], array( 'post-trashed', 'trash', 'spam' ), true ) ) {
$stats['all'] += $row['num_comments'];
$stats['total_comments'] += $row['num_comments'];
} elseif ( ! in_array( $row['comment_approved'], array( 'post-trashed', 'trash' ), true ) ) {
$stats['total_comments'] += $row['num_comments'];
}
if ( isset( $approved[ $row['comment_approved'] ] ) ) {
$stats[ $approved[ $row['comment_approved'] ] ] = $row['num_comments'];
}
}
$stats['total_comments'] = $total;
$stats['all'] = $total;
foreach ( $approved as $key ) {
if ( empty( $stats[ $key ] ) ) {
$stats[ $key ] = 0;

View File

@ -1,12 +1,18 @@
<?php
/**
* Deprecated action hooks
*
* @package WooCommerce\Abstracts
* @since 3.0.0
* @version 3.3.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Handles deprecation notices and triggering of legacy action hooks.
*
* @since 3.0.0
*/
class WC_Deprecated_Action_Hooks extends WC_Deprecated_Hooks {
@ -16,7 +22,7 @@ class WC_Deprecated_Action_Hooks extends WC_Deprecated_Hooks {
* @var array
*/
protected $deprecated_hooks = array(
'woocommerce_new_order_item' => array(
'woocommerce_new_order_item' => array(
'woocommerce_order_add_shipping',
'woocommerce_order_add_coupon',
'woocommerce_order_add_tax',
@ -25,21 +31,45 @@ class WC_Deprecated_Action_Hooks extends WC_Deprecated_Hooks {
'woocommerce_add_order_item_meta',
'woocommerce_add_order_fee_meta',
),
'woocommerce_update_order_item' => array(
'woocommerce_update_order_item' => array(
'woocommerce_order_edit_product',
'woocommerce_order_update_coupon',
'woocommerce_order_update_shipping',
'woocommerce_order_update_fee',
'woocommerce_order_update_tax',
),
'woocommerce_new_payment_token' => 'woocommerce_payment_token_created',
'woocommerce_new_product_variation' => 'woocommerce_create_product_variation',
'woocommerce_order_details_after_order_table_items' => 'woocommerce_order_items_table'
'woocommerce_new_payment_token' => 'woocommerce_payment_token_created',
'woocommerce_new_product_variation' => 'woocommerce_create_product_variation',
'woocommerce_order_details_after_order_table_items' => 'woocommerce_order_items_table',
);
/**
* Array of versions on each hook has been deprecated.
*
* @var array
*/
protected $deprecated_version = array(
'woocommerce_order_add_shipping' => '3.0.0',
'woocommerce_order_add_coupon' => '3.0.0',
'woocommerce_order_add_tax' => '3.0.0',
'woocommerce_order_add_fee' => '3.0.0',
'woocommerce_add_shipping_order_item' => '3.0.0',
'woocommerce_add_order_item_meta' => '3.0.0',
'woocommerce_add_order_fee_meta' => '3.0.0',
'woocommerce_order_edit_product' => '3.0.0',
'woocommerce_order_update_coupon' => '3.0.0',
'woocommerce_order_update_shipping' => '3.0.0',
'woocommerce_order_update_fee' => '3.0.0',
'woocommerce_order_update_tax' => '3.0.0',
'woocommerce_payment_token_created' => '3.0.0',
'woocommerce_create_product_variation' => '3.0.0',
'woocommerce_order_items_table' => '3.0.0',
);
/**
* Hook into the new hook so we can handle deprecated hooks once fired.
* @param string $hook_name
*
* @param string $hook_name Hook name.
*/
public function hook_in( $hook_name ) {
add_action( $hook_name, array( $this, 'maybe_handle_deprecated_hook' ), -1000, 8 );
@ -48,10 +78,10 @@ class WC_Deprecated_Action_Hooks extends WC_Deprecated_Hooks {
/**
* If the old hook is in-use, trigger it.
*
* @param string $new_hook
* @param string $old_hook
* @param array $new_callback_args
* @param mixed $return_value
* @param string $new_hook New hook name.
* @param string $old_hook Old hook name.
* @param array $new_callback_args New callback args.
* @param mixed $return_value Returned value.
* @return mixed
*/
public function handle_deprecated_hook( $new_hook, $old_hook, $new_callback_args, $return_value ) {
@ -65,14 +95,14 @@ class WC_Deprecated_Action_Hooks extends WC_Deprecated_Hooks {
/**
* Fire off a legacy hook with it's args.
*
* @param string $old_hook
* @param array $new_callback_args
* @param string $old_hook Old hook name.
* @param array $new_callback_args New callback args.
* @return mixed
*/
protected function trigger_hook( $old_hook, $new_callback_args ) {
switch ( $old_hook ) {
case 'woocommerce_order_add_shipping' :
case 'woocommerce_order_add_fee' :
case 'woocommerce_order_add_shipping':
case 'woocommerce_order_add_fee':
$item_id = $new_callback_args[0];
$item = $new_callback_args[1];
$order_id = $new_callback_args[2];
@ -80,7 +110,7 @@ class WC_Deprecated_Action_Hooks extends WC_Deprecated_Hooks {
do_action( $old_hook, $order_id, $item_id, $item );
}
break;
case 'woocommerce_order_add_coupon' :
case 'woocommerce_order_add_coupon':
$item_id = $new_callback_args[0];
$item = $new_callback_args[1];
$order_id = $new_callback_args[2];
@ -88,7 +118,7 @@ class WC_Deprecated_Action_Hooks extends WC_Deprecated_Hooks {
do_action( $old_hook, $order_id, $item_id, $item->get_code(), $item->get_discount(), $item->get_discount_tax() );
}
break;
case 'woocommerce_order_add_tax' :
case 'woocommerce_order_add_tax':
$item_id = $new_callback_args[0];
$item = $new_callback_args[1];
$order_id = $new_callback_args[2];
@ -96,7 +126,7 @@ class WC_Deprecated_Action_Hooks extends WC_Deprecated_Hooks {
do_action( $old_hook, $order_id, $item_id, $item->get_rate_id(), $item->get_tax_total(), $item->get_shipping_tax_total() );
}
break;
case 'woocommerce_add_shipping_order_item' :
case 'woocommerce_add_shipping_order_item':
$item_id = $new_callback_args[0];
$item = $new_callback_args[1];
$order_id = $new_callback_args[2];
@ -104,7 +134,7 @@ class WC_Deprecated_Action_Hooks extends WC_Deprecated_Hooks {
do_action( $old_hook, $order_id, $item_id, $item->legacy_package_key );
}
break;
case 'woocommerce_add_order_item_meta' :
case 'woocommerce_add_order_item_meta':
$item_id = $new_callback_args[0];
$item = $new_callback_args[1];
$order_id = $new_callback_args[2];
@ -112,7 +142,7 @@ class WC_Deprecated_Action_Hooks extends WC_Deprecated_Hooks {
do_action( $old_hook, $item_id, $item->legacy_values, $item->legacy_cart_item_key );
}
break;
case 'woocommerce_add_order_fee_meta' :
case 'woocommerce_add_order_fee_meta':
$item_id = $new_callback_args[0];
$item = $new_callback_args[1];
$order_id = $new_callback_args[2];
@ -120,7 +150,7 @@ class WC_Deprecated_Action_Hooks extends WC_Deprecated_Hooks {
do_action( $old_hook, $order_id, $item_id, $item->legacy_fee, $item->legacy_fee_key );
}
break;
case 'woocommerce_order_edit_product' :
case 'woocommerce_order_edit_product':
$item_id = $new_callback_args[0];
$item = $new_callback_args[1];
$order_id = $new_callback_args[2];
@ -128,15 +158,15 @@ class WC_Deprecated_Action_Hooks extends WC_Deprecated_Hooks {
do_action( $old_hook, $order_id, $item_id, $item, $item->get_product() );
}
break;
case 'woocommerce_order_update_coupon' :
case 'woocommerce_order_update_shipping' :
case 'woocommerce_order_update_fee' :
case 'woocommerce_order_update_tax' :
case 'woocommerce_order_update_coupon':
case 'woocommerce_order_update_shipping':
case 'woocommerce_order_update_fee':
case 'woocommerce_order_update_tax':
if ( ! is_a( $item, 'WC_Order_Item_Product' ) ) {
do_action( $old_hook, $order_id, $item_id, $item );
}
break;
default :
default:
do_action_ref_array( $old_hook, $new_callback_args );
break;
}

View File

@ -1,12 +1,18 @@
<?php
/**
* Deprecated filter hooks
*
* @package WooCommerce\Abstracts
* @since 3.0.0
* @version 3.3.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Handles deprecation notices and triggering of legacy filter hooks.
*
* @since 3.0.0
* Handles deprecation notices and triggering of legacy filter hooks
*/
class WC_Deprecated_Filter_Hooks extends WC_Deprecated_Hooks {
@ -54,9 +60,53 @@ class WC_Deprecated_Filter_Hooks extends WC_Deprecated_Hooks {
'woocommerce_credit_card_type_labels' => 'wocommerce_credit_card_type_labels',
);
/**
* Array of versions on each hook has been deprecated.
*
* @var array
*/
protected $deprecated_version = array(
'woocommerce_email_order_schema_markup' => '3.0.0',
'add_to_cart_fragments' => '3.0.0',
'add_to_cart_redirect' => '3.0.0',
'woocommerce_product_width' => '3.0.0',
'woocommerce_product_height' => '3.0.0',
'woocommerce_product_length' => '3.0.0',
'woocommerce_product_weight' => '3.0.0',
'woocommerce_get_sku' => '3.0.0',
'woocommerce_get_price' => '3.0.0',
'woocommerce_get_regular_price' => '3.0.0',
'woocommerce_get_sale_price' => '3.0.0',
'woocommerce_product_tax_class' => '3.0.0',
'woocommerce_get_stock_quantity' => '3.0.0',
'woocommerce_get_product_attributes' => '3.0.0',
'woocommerce_product_gallery_attachment_ids' => '3.0.0',
'woocommerce_product_review_count' => '3.0.0',
'woocommerce_product_files' => '3.0.0',
'woocommerce_get_currency' => '3.0.0',
'woocommerce_order_amount_discount_total' => '3.0.0',
'woocommerce_order_amount_discount_tax' => '3.0.0',
'woocommerce_order_amount_shipping_total' => '3.0.0',
'woocommerce_order_amount_shipping_tax' => '3.0.0',
'woocommerce_order_amount_cart_tax' => '3.0.0',
'woocommerce_order_amount_total' => '3.0.0',
'woocommerce_order_amount_total_tax' => '3.0.0',
'woocommerce_order_amount_total_discount' => '3.0.0',
'woocommerce_order_amount_subtotal' => '3.0.0',
'woocommerce_order_tax_totals' => '3.0.0',
'woocommerce_refund_amount' => '3.0.0',
'woocommerce_refund_reason' => '3.0.0',
'default_checkout_country' => '3.0.0',
'default_checkout_state' => '3.0.0',
'default_checkout_postcode' => '3.0.0',
'woocommerce_debug_posting' => '3.0.0',
'wocommerce_credit_card_type_labels' => '3.0.0',
);
/**
* Hook into the new hook so we can handle deprecated hooks once fired.
* @param string $hook_name
*
* @param string $hook_name Hook name.
*/
public function hook_in( $hook_name ) {
add_filter( $hook_name, array( $this, 'maybe_handle_deprecated_hook' ), -1000, 8 );
@ -65,10 +115,10 @@ class WC_Deprecated_Filter_Hooks extends WC_Deprecated_Hooks {
/**
* If the old hook is in-use, trigger it.
*
* @param string $new_hook
* @param string $old_hook
* @param array $new_callback_args
* @param mixed $return_value
* @param string $new_hook New hook name.
* @param string $old_hook Old hook name.
* @param array $new_callback_args New callback args.
* @param mixed $return_value Returned value.
* @return mixed
*/
public function handle_deprecated_hook( $new_hook, $old_hook, $new_callback_args, $return_value ) {
@ -82,8 +132,8 @@ class WC_Deprecated_Filter_Hooks extends WC_Deprecated_Hooks {
/**
* Fire off a legacy hook with it's args.
*
* @param string $old_hook
* @param array $new_callback_args
* @param string $old_hook Old hook name.
* @param array $new_callback_args New callback args.
* @return mixed
*/
protected function trigger_hook( $old_hook, $new_callback_args ) {

View File

@ -887,7 +887,7 @@ class WC_Form_Handler {
// Don't use wc_clean as it destroys sanitized characters.
$value = sanitize_title( wp_unslash( $_REQUEST[ $taxonomy ] ) );
} else {
$value = wc_clean( wp_unslash( $_REQUEST[ $taxonomy ] ) ); // WPCS: sanitization ok.
$value = html_entity_decode( wc_clean( wp_unslash( $_REQUEST[ $taxonomy ] ) ), ENT_QUOTES, get_bloginfo( 'charset' ) ); // WPCS: sanitization ok.
}
// Allow if valid or show error.

View File

@ -21,11 +21,21 @@ if ( ! defined( 'ABSPATH' ) ) {
*/
class WC_Geolocation {
/** URL to the geolocation database we're using */
const GEOLITE_DB = 'http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz';
/**
* GeoLite IPv4 DB.
*/
const GEOLITE_DB = 'http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz';
/**
* GeoLite IPv6 DB.
*/
const GEOLITE_IPV6_DB = 'http://geolite.maxmind.com/download/geoip/database/GeoIPv6.dat.gz';
/** @var array API endpoints for looking up user IP address */
/**
* API endpoints for looking up user IP address.
*
* @var array
*/
private static $ip_lookup_apis = array(
'icanhazip' => 'http://icanhazip.com',
'ipify' => 'http://api.ipify.org/',
@ -35,7 +45,11 @@ class WC_Geolocation {
'ip.appspot' => 'http://ip.appspot.com',
);
/** @var array API endpoints for geolocating an IP address */
/**
* API endpoints for geolocating an IP address
*
* @var array
*/
private static $geoip_apis = array(
'freegeoip' => 'https://freegeoip.net/json/%s',
'ipinfo.io' => 'https://ipinfo.io/%s/json',
@ -46,7 +60,7 @@ class WC_Geolocation {
* Hook in tabs.
*/
public static function init() {
// Only download the database from MaxMind if the geolocation function is enabled, or a plugin specifically requests it
// Only download the database from MaxMind if the geolocation function is enabled, or a plugin specifically requests it.
if ( 'geolocation' === get_option( 'woocommerce_default_customer_address' ) || apply_filters( 'woocommerce_geolocation_update_database_periodically', false ) ) {
add_action( 'woocommerce_geoip_updater', array( __CLASS__, 'update_database' ) );
}
@ -55,8 +69,9 @@ class WC_Geolocation {
/**
* Maybe trigger a DB update for the first time.
* @param string $new_value
* @param string $old_value
*
* @param string $new_value New value.
* @param string $old_value Old value.
* @return string
*/
public static function maybe_update_database( $new_value, $old_value ) {
@ -66,46 +81,20 @@ class WC_Geolocation {
return $new_value;
}
/**
* Check if is a valid IP address.
*
* @since 3.0.6
* @param string $ip_address IP address.
* @return string|bool The valid IP address, otherwise false.
*/
private static function is_ip_address( $ip_address ) {
// WP 4.7+ only.
if ( function_exists( 'rest_is_ip_address' ) ) {
return rest_is_ip_address( $ip_address );
}
// Support for WordPress 4.4 to 4.6.
if ( ! class_exists( 'Requests_IPv6', false ) ) {
include_once( dirname( __FILE__ ) . '/vendor/class-requests-ipv6.php' );
}
$ipv4_pattern = '/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/';
if ( ! preg_match( $ipv4_pattern, $ip_address ) && ! Requests_IPv6::check_ipv6( $ip_address ) ) {
return false;
}
return $ip_address;
}
/**
* Get current user IP Address.
*
* @return string
*/
public static function get_ip_address() {
if ( isset( $_SERVER['HTTP_X_REAL_IP'] ) ) {
return $_SERVER['HTTP_X_REAL_IP'];
} elseif ( isset( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) {
if ( isset( $_SERVER['HTTP_X_REAL_IP'] ) ) { // WPCS: input var ok, CSRF ok.
return sanitize_text_field( wp_unslash( $_SERVER['HTTP_X_REAL_IP'] ) ); // WPCS: input var ok, CSRF ok.
} elseif ( isset( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) { // WPCS: input var ok, CSRF ok.
// Proxy servers can send through this header like this: X-Forwarded-For: client1, proxy1, proxy2
// Make sure we always only send through the first IP in the list which should always be the client IP.
return (string) self::is_ip_address( trim( current( explode( ',', $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) ) );
} elseif ( isset( $_SERVER['REMOTE_ADDR'] ) ) {
return $_SERVER['REMOTE_ADDR'];
return (string) rest_is_ip_address( trim( current( explode( ',', sanitize_text_field( wp_unslash( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) ) ) ) ); // WPCS: input var ok, CSRF ok.
} elseif ( isset( $_SERVER['REMOTE_ADDR'] ) ) { // @codingStandardsIgnoreLine
return sanitize_text_field( wp_unslash( $_SERVER['REMOTE_ADDR'] ) ); // @codingStandardsIgnoreLine
}
return '';
}
@ -114,6 +103,7 @@ class WC_Geolocation {
* Get user IP Address using an external service.
* This is used mainly as a fallback for users on localhost where
* get_ip_address() will be a local IP and non-geolocatable.
*
* @return string
*/
public static function get_external_ip_address() {
@ -148,8 +138,9 @@ class WC_Geolocation {
/**
* Geolocate an IP address.
* @param string $ip_address
* @param bool $fallback If true, fallbacks to alternative IP detection (can be slower).
*
* @param string $ip_address IP Address.
* @param bool $fallback If true, fallbacks to alternative IP detection (can be slower).
* @param bool $api_fallback If true, uses geolocation APIs if the database file doesn't exist (can be slower).
* @return array
*/
@ -158,19 +149,19 @@ class WC_Geolocation {
$country_code = apply_filters( 'woocommerce_geolocate_ip', false, $ip_address, $fallback, $api_fallback );
if ( false === $country_code ) {
// If GEOIP is enabled in CloudFlare, we can use that (Settings -> CloudFlare Settings -> Settings Overview)
if ( ! empty( $_SERVER['HTTP_CF_IPCOUNTRY'] ) ) {
$country_code = sanitize_text_field( strtoupper( $_SERVER['HTTP_CF_IPCOUNTRY'] ) );
// WP.com VIP has a variable available.
} elseif ( ! empty( $_SERVER['GEOIP_COUNTRY_CODE'] ) ) {
$country_code = sanitize_text_field( strtoupper( $_SERVER['GEOIP_COUNTRY_CODE'] ) );
// VIP Go has a variable available also.
} elseif ( ! empty( $_SERVER['HTTP_X_COUNTRY_CODE'] ) ) {
$country_code = sanitize_text_field( strtoupper( $_SERVER['HTTP_X_COUNTRY_CODE'] ) );
// If GEOIP is enabled in CloudFlare, we can use that (Settings -> CloudFlare Settings -> Settings Overview).
if ( ! empty( $_SERVER['HTTP_CF_IPCOUNTRY'] ) ) { // WPCS: input var ok, CSRF ok.
$country_code = strtoupper( sanitize_text_field( wp_unslash( $_SERVER['HTTP_CF_IPCOUNTRY'] ) ) ); // WPCS: input var ok, CSRF ok.
} elseif ( ! empty( $_SERVER['GEOIP_COUNTRY_CODE'] ) ) { // WPCS: input var ok, CSRF ok.
// WP.com VIP has a variable available.
$country_code = strtoupper( sanitize_text_field( wp_unslash( $_SERVER['GEOIP_COUNTRY_CODE'] ) ) ); // WPCS: input var ok, CSRF ok.
} elseif ( ! empty( $_SERVER['HTTP_X_COUNTRY_CODE'] ) ) { // WPCS: input var ok, CSRF ok.
// VIP Go has a variable available also.
$country_code = strtoupper( sanitize_text_field( wp_unslash( $_SERVER['HTTP_X_COUNTRY_CODE'] ) ) ); // WPCS: input var ok, CSRF ok.
} else {
$ip_address = $ip_address ? $ip_address : self::get_ip_address();
if ( self::is_IPv6( $ip_address ) ) {
if ( self::is_ipv6( $ip_address ) ) {
$database = self::get_local_database_path( 'v6' );
} else {
$database = self::get_local_database_path();
@ -185,7 +176,7 @@ class WC_Geolocation {
}
if ( ! $country_code && $fallback ) {
// May be a local environment - find external IP
// May be a local environment - find external IP.
return self::geolocate_ip( self::get_external_ip_address(), false, $api_fallback );
}
}
@ -199,11 +190,12 @@ class WC_Geolocation {
/**
* Path to our local db.
* @param string $version
*
* @param string $version Version.
* @return string
*/
public static function get_local_database_path( $version = 'v4' ) {
$version = ( 'v4' == $version ) ? '' : 'v6';
$version = 'v4' === $version ? '' : 'v6';
$upload_dir = wp_upload_dir();
return apply_filters( 'woocommerce_geolocation_local_database_path', $upload_dir['basedir'] . '/GeoIP' . $version . '.dat', $version );
@ -220,7 +212,7 @@ class WC_Geolocation {
return;
}
require_once( ABSPATH . 'wp-admin/includes/file.php' );
require_once ABSPATH . 'wp-admin/includes/file.php';
$tmp_databases = array(
'v4' => download_url( self::GEOLITE_DB ),
@ -229,20 +221,20 @@ class WC_Geolocation {
foreach ( $tmp_databases as $tmp_database_version => $tmp_database_path ) {
if ( ! is_wp_error( $tmp_database_path ) ) {
$gzhandle = @gzopen( $tmp_database_path, 'r' );
$handle = @fopen( self::get_local_database_path( $tmp_database_version ), 'w' );
$gzhandle = @gzopen( $tmp_database_path, 'r' ); // @codingStandardsIgnoreLine
$handle = @fopen( self::get_local_database_path( $tmp_database_version ), 'w' ); // @codingStandardsIgnoreLine
if ( $gzhandle && $handle ) {
while ( $string = gzread( $gzhandle, 4096 ) ) {
fwrite( $handle, $string, strlen( $string ) );
while ( $string = gzread( $gzhandle, 4096 ) ) { // @codingStandardsIgnoreLine
fwrite( $handle, $string, strlen( $string ) ); // @codingStandardsIgnoreLine
}
gzclose( $gzhandle );
$s_array = fstat( $handle );
fclose( $handle );
fclose( $handle ); // @codingStandardsIgnoreLine
if ( ! isset( $s_array['size'] ) || 0 === $s_array['size'] ) {
$logger->notice( 'Empty database file, deleting local copy.', array( 'source' => 'geolocation' ) );
// Delete empty DB, we do not want to keep empty files around.
@unlink( self::get_local_database_path( $tmp_database_version ) );
@unlink( self::get_local_database_path( $tmp_database_version ) ); // @codingStandardsIgnoreLine
// Reschedule download of DB.
wp_clear_scheduled_hook( 'woocommerce_geoip_updater' );
wp_schedule_event( strtotime( 'first tuesday of next month' ), 'monthly', 'woocommerce_geoip_updater' );
@ -250,7 +242,7 @@ class WC_Geolocation {
} else {
$logger->notice( 'Unable to open database file', array( 'source' => 'geolocation' ) );
}
@unlink( $tmp_database_path );
@unlink( $tmp_database_path ); // @codingStandardsIgnoreLine
} else {
$logger->notice(
'Unable to download GeoIP Database: ' . $tmp_database_path->get_error_message(),
@ -262,17 +254,18 @@ class WC_Geolocation {
/**
* Use MAXMIND GeoLite database to geolocation the user.
* @param string $ip_address
*
* @param string $ip_address IP address.
* @return string
*/
private static function geolocate_via_db( $ip_address ) {
if ( ! class_exists( 'WC_Geo_IP', false ) ) {
include_once( WC_ABSPATH . 'includes/class-wc-geo-ip.php' );
include_once WC_ABSPATH . 'includes/class-wc-geo-ip.php';
}
$gi = new WC_Geo_IP();
if ( self::is_IPv6( $ip_address ) ) {
if ( self::is_ipv6( $ip_address ) ) {
$database = self::get_local_database_path( 'v6' );
if ( ! self::get_file_size( $database ) ) {
return false;
@ -301,14 +294,14 @@ class WC_Geolocation {
* @return bool|int
*/
private static function get_file_size( $filename ) {
$handle = @fopen( $filename, 'r' );
$s_array = fstat( $handle );
@fclose( $handle );
$handle = @fopen( $filename, 'r' ); // @codingStandardsIgnoreLine
$s_array = fstat( $handle ); // @codingStandardsIgnoreLine
@fclose( $handle ); // @codingStandardsIgnoreLine
if ( ! isset( $s_array['size'] ) || 0 === $s_array['size'] ) {
$logger = wc_get_logger();
$logger->notice( 'Empty database file, deleting local copy.', array( 'source' => 'geolocation' ) );
// Delete the file as we do not want to keep empty files around.
@unlink( $filename );
@unlink( $filename ); // @codingStandardsIgnoreLine
return false;
}
return $s_array['size'];
@ -316,7 +309,8 @@ class WC_Geolocation {
/**
* Use APIs to Geolocate the user.
* @param string $ip_address
*
* @param string $ip_address IP address.
* @return string|bool
*/
private static function geolocate_via_api( $ip_address ) {
@ -333,21 +327,21 @@ class WC_Geolocation {
if ( ! is_wp_error( $response ) && $response['body'] ) {
switch ( $service_name ) {
case 'ipinfo.io' :
case 'ipinfo.io':
$data = json_decode( $response['body'] );
$country_code = isset( $data->country ) ? $data->country : '';
break;
case 'ip-api.com' :
break;
case 'ip-api.com':
$data = json_decode( $response['body'] );
$country_code = isset( $data->countryCode ) ? $data->countryCode : '';
break;
case 'freegeoip' :
$country_code = isset( $data->countryCode ) ? $data->countryCode : ''; // @codingStandardsIgnoreLine
break;
case 'freegeoip':
$data = json_decode( $response['body'] );
$country_code = isset( $data->country_code ) ? $data->country_code : '';
break;
default :
break;
default:
$country_code = apply_filters( 'woocommerce_geolocation_geoip_response_' . $service_name, '', $response['body'] );
break;
break;
}
$country_code = sanitize_text_field( strtoupper( $country_code ) );
@ -369,10 +363,10 @@ class WC_Geolocation {
*
* @since 2.4.0
*
* @param string $ip_address
* @param string $ip_address IP Address.
* @return bool
*/
private static function is_IPv6( $ip_address ) {
private static function is_ipv6( $ip_address ) {
return false !== filter_var( $ip_address, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 );
}
}

View File

@ -96,7 +96,11 @@ class WC_Install {
),
'3.3.0' => array(
'wc_update_330_image_options',
<<<<<<< HEAD
'wc_update_330_webhooks',
=======
'wc_update_330_set_default_product_cat',
>>>>>>> master
'wc_update_330_db_version',
),
);
@ -127,7 +131,7 @@ class WC_Install {
* Init background updates
*/
public static function init_background_updater() {
include_once( dirname( __FILE__ ) . '/class-wc-background-updater.php' );
include_once dirname( __FILE__ ) . '/class-wc-background-updater.php';
self::$background_updater = new WC_Background_Updater();
}
@ -201,7 +205,7 @@ class WC_Install {
* @since 3.2.0
*/
private static function remove_admin_notices() {
include_once( dirname( __FILE__ ) . '/admin/class-wc-admin-notices.php' );
include_once dirname( __FILE__ ) . '/admin/class-wc-admin-notices.php';
WC_Admin_Notices::remove_all_notices();
}
@ -318,7 +322,8 @@ class WC_Install {
/**
* Update DB version to current.
* @param string $version
*
* @param string|null $version New WooCommerce DB version or null.
*/
public static function update_db_version( $version = null ) {
delete_option( 'woocommerce_db_version' );
@ -327,7 +332,8 @@ class WC_Install {
/**
* Add more cron schedules.
* @param array $schedules
*
* @param array $schedules List of WP scheduled cron jobs.
* @return array
*/
public static function cron_schedules( $schedules ) {
@ -367,30 +373,32 @@ class WC_Install {
* Create pages that the plugin relies on, storing page IDs in variables.
*/
public static function create_pages() {
include_once( dirname( __FILE__ ) . '/admin/wc-admin-functions.php' );
include_once dirname( __FILE__ ) . '/admin/wc-admin-functions.php';
$pages = apply_filters( 'woocommerce_create_pages', array(
'shop' => array(
'name' => _x( 'shop', 'Page slug', 'woocommerce' ),
'title' => _x( 'Shop', 'Page title', 'woocommerce' ),
'content' => '',
),
'cart' => array(
'name' => _x( 'cart', 'Page slug', 'woocommerce' ),
'title' => _x( 'Cart', 'Page title', 'woocommerce' ),
'content' => '[' . apply_filters( 'woocommerce_cart_shortcode_tag', 'woocommerce_cart' ) . ']',
),
'checkout' => array(
'name' => _x( 'checkout', 'Page slug', 'woocommerce' ),
'title' => _x( 'Checkout', 'Page title', 'woocommerce' ),
'content' => '[' . apply_filters( 'woocommerce_checkout_shortcode_tag', 'woocommerce_checkout' ) . ']',
),
'myaccount' => array(
'name' => _x( 'my-account', 'Page slug', 'woocommerce' ),
'title' => _x( 'My account', 'Page title', 'woocommerce' ),
'content' => '[' . apply_filters( 'woocommerce_my_account_shortcode_tag', 'woocommerce_my_account' ) . ']',
),
) );
$pages = apply_filters(
'woocommerce_create_pages', array(
'shop' => array(
'name' => _x( 'shop', 'Page slug', 'woocommerce' ),
'title' => _x( 'Shop', 'Page title', 'woocommerce' ),
'content' => '',
),
'cart' => array(
'name' => _x( 'cart', 'Page slug', 'woocommerce' ),
'title' => _x( 'Cart', 'Page title', 'woocommerce' ),
'content' => '[' . apply_filters( 'woocommerce_cart_shortcode_tag', 'woocommerce_cart' ) . ']',
),
'checkout' => array(
'name' => _x( 'checkout', 'Page slug', 'woocommerce' ),
'title' => _x( 'Checkout', 'Page title', 'woocommerce' ),
'content' => '[' . apply_filters( 'woocommerce_checkout_shortcode_tag', 'woocommerce_checkout' ) . ']',
),
'myaccount' => array(
'name' => _x( 'my-account', 'Page slug', 'woocommerce' ),
'title' => _x( 'My account', 'Page title', 'woocommerce' ),
'content' => '[' . apply_filters( 'woocommerce_my_account_shortcode_tag', 'woocommerce_my_account' ) . ']',
),
)
);
foreach ( $pages as $key => $page ) {
wc_create_page( esc_sql( $page['name'] ), 'woocommerce_' . $key . '_page_id', $page['title'], $page['content'], ! empty( $page['parent'] ) ? wc_get_page_id( $page['parent'] ) : '' );
@ -405,8 +413,8 @@ class WC_Install {
* Sets up the default options used on the settings page.
*/
private static function create_options() {
// Include settings so that we can run through defaults
include_once( dirname( __FILE__ ) . '/admin/class-wc-admin-settings.php' );
// Include settings so that we can run through defaults.
include_once dirname( __FILE__ ) . '/admin/class-wc-admin-settings.php';
$settings = WC_Admin_Settings::get_settings_pages();
@ -432,7 +440,7 @@ class WC_Install {
*/
public static function create_terms() {
$taxonomies = array(
'product_type' => array(
'product_type' => array(
'simple',
'grouped',
'variable',
@ -453,32 +461,54 @@ class WC_Install {
foreach ( $taxonomies as $taxonomy => $terms ) {
foreach ( $terms as $term ) {
if ( ! get_term_by( 'name', $term, $taxonomy ) ) {
if ( ! get_term_by( 'name', $term, $taxonomy ) ) { // @codingStandardsIgnoreLine.
wp_insert_term( $term, $taxonomy );
}
}
}
$woocommerce_default_category = get_option( 'default_product_cat', 0 );
if ( ! $woocommerce_default_category || ! term_exists( $woocommerce_default_category, 'product_cat' ) ) {
$default_product_cat_id = 0;
$default_product_cat_slug = sanitize_title( _x( 'Uncategorized', 'Default category slug', 'woocommerce' ) );
$default_product_cat = get_term_by( 'slug', $default_product_cat_slug, 'product_cat' ); // @codingStandardsIgnoreLine.
if ( $default_product_cat ) {
$default_product_cat_id = absint( $default_product_cat->term_taxonomy_id );
} else {
$result = wp_insert_term( _x( 'Uncategorized', 'Default category slug', 'woocommerce' ), 'product_cat', array( 'slug' => $default_product_cat_slug ) );
if ( ! empty( $result['term_taxonomy_id'] ) ) {
$default_product_cat_id = absint( $result['term_taxonomy_id'] );
}
}
if ( $default_product_cat_id ) {
update_option( 'default_product_cat', $default_product_cat_id );
}
}
}
/**
* Set up the database tables which the plugin needs to function.
*
* Tables:
* woocommerce_attribute_taxonomies - Table for storing attribute taxonomies - these are user defined
* woocommerce_termmeta - Term meta table - sadly WordPress does not have termmeta so we need our own
* woocommerce_downloadable_product_permissions - Table for storing user and guest download permissions.
* KEY(order_id, product_id, download_id) used for organizing downloads on the My Account page
* woocommerce_order_items - Order line items are stored in a table to make them easily queryable for reports
* woocommerce_order_itemmeta - Order line item meta is stored in a table for storing extra data.
* woocommerce_tax_rates - Tax Rates are stored inside 2 tables making tax queries simple and efficient.
* woocommerce_tax_rate_locations - Each rate can be applied to more than one postcode/city hence the second table.
* woocommerce_attribute_taxonomies - Table for storing attribute taxonomies - these are user defined
* woocommerce_termmeta - Term meta table - sadly WordPress does not have termmeta so we need our own
* woocommerce_downloadable_product_permissions - Table for storing user and guest download permissions.
* KEY(order_id, product_id, download_id) used for organizing downloads on the My Account page
* woocommerce_order_items - Order line items are stored in a table to make them easily queryable for reports
* woocommerce_order_itemmeta - Order line item meta is stored in a table for storing extra data.
* woocommerce_tax_rates - Tax Rates are stored inside 2 tables making tax queries simple and efficient.
* woocommerce_tax_rate_locations - Each rate can be applied to more than one postcode/city hence the second table.
*/
private static function create_tables() {
global $wpdb;
$wpdb->hide_errors();
require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
require_once ABSPATH . 'wp-admin/includes/upgrade.php';
/**
* Before updating with DBDELTA, remove any primary keys which could be
@ -504,7 +534,7 @@ class WC_Install {
/**
* Get Table schema.
*
* https://github.com/woocommerce/woocommerce/wiki/Database-Description/
* See https://github.com/woocommerce/woocommerce/wiki/Database-Description/
*
* A note on indexes; Indexes have a maximum size of 767 bytes. Historically, we haven't need to be concerned about that.
* As of WordPress 4.2, however, we moved to utf8mb4, which uses 4 bytes per character. This means that an index which
@ -730,56 +760,64 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta (
}
if ( ! isset( $wp_roles ) ) {
$wp_roles = new WP_Roles();
$wp_roles = new WP_Roles(); // @codingStandardsIgnoreLine
}
// Customer role
add_role( 'customer', __( 'Customer', 'woocommerce' ), array(
'read' => true,
) );
// Customer role.
add_role(
'customer',
__( 'Customer', 'woocommerce' ),
array(
'read' => true,
)
);
// Shop manager role
add_role( 'shop_manager', __( 'Shop manager', 'woocommerce' ), array(
'level_9' => true,
'level_8' => true,
'level_7' => true,
'level_6' => true,
'level_5' => true,
'level_4' => true,
'level_3' => true,
'level_2' => true,
'level_1' => true,
'level_0' => true,
'read' => true,
'read_private_pages' => true,
'read_private_posts' => true,
'edit_users' => true,
'edit_posts' => true,
'edit_pages' => true,
'edit_published_posts' => true,
'edit_published_pages' => true,
'edit_private_pages' => true,
'edit_private_posts' => true,
'edit_others_posts' => true,
'edit_others_pages' => true,
'publish_posts' => true,
'publish_pages' => true,
'delete_posts' => true,
'delete_pages' => true,
'delete_private_pages' => true,
'delete_private_posts' => true,
'delete_published_pages' => true,
'delete_published_posts' => true,
'delete_others_posts' => true,
'delete_others_pages' => true,
'manage_categories' => true,
'manage_links' => true,
'moderate_comments' => true,
'upload_files' => true,
'export' => true,
'import' => true,
'list_users' => true,
) );
// Shop manager role.
add_role(
'shop_manager',
__( 'Shop manager', 'woocommerce' ),
array(
'level_9' => true,
'level_8' => true,
'level_7' => true,
'level_6' => true,
'level_5' => true,
'level_4' => true,
'level_3' => true,
'level_2' => true,
'level_1' => true,
'level_0' => true,
'read' => true,
'read_private_pages' => true,
'read_private_posts' => true,
'edit_users' => true,
'edit_posts' => true,
'edit_pages' => true,
'edit_published_posts' => true,
'edit_published_pages' => true,
'edit_private_pages' => true,
'edit_private_posts' => true,
'edit_others_posts' => true,
'edit_others_pages' => true,
'publish_posts' => true,
'publish_pages' => true,
'delete_posts' => true,
'delete_pages' => true,
'delete_private_pages' => true,
'delete_private_posts' => true,
'delete_published_pages' => true,
'delete_published_posts' => true,
'delete_others_posts' => true,
'delete_others_pages' => true,
'manage_categories' => true,
'manage_links' => true,
'moderate_comments' => true,
'upload_files' => true,
'export' => true,
'import' => true,
'list_users' => true,
)
);
$capabilities = self::get_core_capabilities();
@ -796,7 +834,7 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta (
*
* @return array
*/
private static function get_core_capabilities() {
private static function get_core_capabilities() {
$capabilities = array();
$capabilities['core'] = array(
@ -809,7 +847,7 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta (
foreach ( $capability_types as $capability_type ) {
$capabilities[ $capability_type ] = array(
// Post type
// Post type.
"edit_{$capability_type}",
"read_{$capability_type}",
"delete_{$capability_type}",
@ -824,7 +862,7 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta (
"edit_private_{$capability_type}s",
"edit_published_{$capability_type}s",
// Terms
// Terms.
"manage_{$capability_type}_terms",
"edit_{$capability_type}_terms",
"delete_{$capability_type}_terms",
@ -836,7 +874,7 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta (
}
/**
* woocommerce_remove_roles function.
* Remove WooCommerce roles.
*/
public static function remove_roles() {
global $wp_roles;
@ -846,7 +884,7 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta (
}
if ( ! isset( $wp_roles ) ) {
$wp_roles = new WP_Roles();
$wp_roles = new WP_Roles(); // @codingStandardsIgnoreLine
}
$capabilities = self::get_core_capabilities();
@ -866,44 +904,45 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta (
* Create files/directories.
*/
private static function create_files() {
// Bypass if filesystem is read-only and/or non-standard upload system is used
// Bypass if filesystem is read-only and/or non-standard upload system is used.
if ( apply_filters( 'woocommerce_install_skip_create_files', false ) ) {
return;
}
// Install files and folders for uploading files and prevent hotlinking
// Install files and folders for uploading files and prevent hotlinking.
$upload_dir = wp_upload_dir();
$download_method = get_option( 'woocommerce_file_download_method', 'force' );
$files = array(
array(
'base' => $upload_dir['basedir'] . '/woocommerce_uploads',
'file' => 'index.html',
'content' => '',
'base' => $upload_dir['basedir'] . '/woocommerce_uploads',
'file' => 'index.html',
'content' => '',
),
array(
'base' => WC_LOG_DIR,
'file' => '.htaccess',
'content' => 'deny from all',
'base' => WC_LOG_DIR,
'file' => '.htaccess',
'content' => 'deny from all',
),
array(
'base' => WC_LOG_DIR,
'file' => 'index.html',
'content' => '',
'base' => WC_LOG_DIR,
'file' => 'index.html',
'content' => '',
),
);
if ( 'redirect' !== $download_method ) {
$files[] = array(
'base' => $upload_dir['basedir'] . '/woocommerce_uploads',
'file' => '.htaccess',
'content' => 'deny from all',
'base' => $upload_dir['basedir'] . '/woocommerce_uploads',
'file' => '.htaccess',
'content' => 'deny from all',
);
}
foreach ( $files as $file ) {
if ( wp_mkdir_p( $file['base'] ) && ! file_exists( trailingslashit( $file['base'] ) . $file['file'] ) ) {
if ( $file_handle = @fopen( trailingslashit( $file['base'] ) . $file['file'], 'w' ) ) {
$file_handle = @fopen( trailingslashit( $file['base'] ) . $file['file'], 'w' );
if ( $file_handle ) {
fwrite( $file_handle, $file['content'] );
fclose( $file_handle );
}
@ -914,8 +953,8 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta (
/**
* Show action links on the plugin screen.
*
* @param mixed $links Plugin Action links
* @return array
* @param mixed $links Plugin Action links.
* @return array
*/
public static function plugin_action_links( $links ) {
$action_links = array(
@ -928,9 +967,9 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta (
/**
* Show row meta on the plugin screen.
*
* @param mixed $links Plugin Row Meta
* @param mixed $file Plugin Base file
* @return array
* @param mixed $links Plugin Row Meta.
* @param mixed $file Plugin Base file.
* @return array
*/
public static function plugin_row_meta( $links, $file ) {
if ( WC_PLUGIN_BASENAME == $file ) {
@ -948,7 +987,8 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta (
/**
* Uninstall tables when MU blog is deleted.
* @param array $tables
*
* @param array $tables List of tables that will be deleted by WP.
* @return string[]
*/
public static function wpmu_drop_tables( $tables ) {
@ -973,7 +1013,8 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta (
/**
* Get slug from path
* @param string $key
*
* @param string $key Plugin relative path. Example: woocommerce/woocommerce.php.
* @return string
*/
private static function format_plugin_slug( $key ) {
@ -985,8 +1026,10 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta (
/**
* Install a plugin from .org in the background via a cron job (used by
* installer - opt in).
* @param string $plugin_to_install_id
* @param array $plugin_to_install
*
* @param string $plugin_to_install_id Plugin ID.
* @param array $plugin_to_install Plugin information.
* @throws Exception If unable to proceed with plugin installation.
* @since 2.6.0
*/
public static function background_installer( $plugin_to_install_id, $plugin_to_install ) {
@ -994,14 +1037,14 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta (
wp_clear_scheduled_hook( 'woocommerce_plugin_background_installer', func_get_args() );
if ( ! empty( $plugin_to_install['repo-slug'] ) ) {
require_once( ABSPATH . 'wp-admin/includes/file.php' );
require_once( ABSPATH . 'wp-admin/includes/plugin-install.php' );
require_once( ABSPATH . 'wp-admin/includes/class-wp-upgrader.php' );
require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
require_once ABSPATH . 'wp-admin/includes/file.php';
require_once ABSPATH . 'wp-admin/includes/plugin-install.php';
require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
require_once ABSPATH . 'wp-admin/includes/plugin.php';
WP_Filesystem();
$skin = new Automatic_Upgrader_Skin;
$skin = new Automatic_Upgrader_Skin();
$upgrader = new WP_Upgrader( $skin );
$installed_plugins = array_map( array( __CLASS__, 'format_plugin_slug' ), array_keys( get_plugins() ) );
$plugin_slug = $plugin_to_install['repo-slug'];
@ -1009,7 +1052,7 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta (
$installed = false;
$activate = false;
// See if the plugin is installed already
// See if the plugin is installed already.
if ( in_array( $plugin_to_install['repo-slug'], $installed_plugins ) ) {
$installed = true;
$activate = ! is_plugin_active( $plugin );
@ -1017,28 +1060,31 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta (
// Install this thing!
if ( ! $installed ) {
// Suppress feedback
// Suppress feedback.
ob_start();
try {
$plugin_information = plugins_api( 'plugin_information', array(
'slug' => $plugin_to_install['repo-slug'],
'fields' => array(
'short_description' => false,
'sections' => false,
'requires' => false,
'rating' => false,
'ratings' => false,
'downloaded' => false,
'last_updated' => false,
'added' => false,
'tags' => false,
'homepage' => false,
'donate_link' => false,
'author_profile' => false,
'author' => false,
),
) );
$plugin_information = plugins_api(
'plugin_information',
array(
'slug' => $plugin_to_install['repo-slug'],
'fields' => array(
'short_description' => false,
'sections' => false,
'requires' => false,
'rating' => false,
'ratings' => false,
'downloaded' => false,
'last_updated' => false,
'added' => false,
'tags' => false,
'homepage' => false,
'donate_link' => false,
'author_profile' => false,
'author' => false,
),
)
);
if ( is_wp_error( $plugin_information ) ) {
throw new Exception( $plugin_information->get_error_message() );
@ -1057,17 +1103,19 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta (
throw new Exception( $working_dir->get_error_message() );
}
$result = $upgrader->install_package( array(
'source' => $working_dir,
'destination' => WP_PLUGIN_DIR,
'clear_destination' => false,
'abort_if_destination_exists' => false,
'clear_working' => true,
'hook_extra' => array(
'type' => 'plugin',
'action' => 'install',
),
) );
$result = $upgrader->install_package(
array(
'source' => $working_dir,
'destination' => WP_PLUGIN_DIR,
'clear_destination' => false,
'abort_if_destination_exists' => false,
'clear_working' => true,
'hook_extra' => array(
'type' => 'plugin',
'action' => 'install',
),
)
);
if ( is_wp_error( $result ) ) {
throw new Exception( $result->get_error_message() );
@ -1079,6 +1127,7 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta (
WC_Admin_Notices::add_custom_notice(
$plugin_to_install_id . '_install_error',
sprintf(
// translators: 1: plugin name, 2: error message, 3: URL to install plugin manually.
__( '%1$s could not be installed (%2$s). <a href="%3$s">Please install it manually by clicking here.</a>', 'woocommerce' ),
$plugin_to_install['name'],
$e->getMessage(),
@ -1087,13 +1136,13 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta (
);
}
// Discard feedback
// Discard feedback.
ob_end_clean();
}
wp_clean_plugins_cache();
// Activate this thing
// Activate this thing.
if ( $activate ) {
try {
$result = activate_plugin( $plugin );
@ -1105,6 +1154,7 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta (
WC_Admin_Notices::add_custom_notice(
$plugin_to_install_id . '_install_error',
sprintf(
// translators: 1: plugin name, 2: URL to WP plugin page.
__( '%1$s was installed but could not be activated. <a href="%2$s">Please activate it manually by clicking here.</a>', 'woocommerce' ),
$plugin_to_install['name'],
admin_url( 'plugins.php' )
@ -1118,7 +1168,8 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta (
/**
* Install a theme from .org in the background via a cron job (used by installer - opt in).
*
* @param string $theme_slug
* @param string $theme_slug Theme slug.
* @throws Exception If unable to proceed with theme installation.
* @since 3.1.0
*/
public static function theme_background_installer( $theme_slug ) {
@ -1126,25 +1177,27 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta (
wp_clear_scheduled_hook( 'woocommerce_theme_background_installer', func_get_args() );
if ( ! empty( $theme_slug ) ) {
// Suppress feedback
// Suppress feedback.
ob_start();
try {
$theme = wp_get_theme( $theme_slug );
if ( ! $theme->exists() ) {
require_once( ABSPATH . 'wp-admin/includes/file.php' );
include_once( ABSPATH . 'wp-admin/includes/class-wp-upgrader.php' );
include_once( ABSPATH . 'wp-admin/includes/theme.php' );
require_once ABSPATH . 'wp-admin/includes/file.php';
include_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
include_once ABSPATH . 'wp-admin/includes/theme.php';
WP_Filesystem();
$skin = new Automatic_Upgrader_Skin;
$skin = new Automatic_Upgrader_Skin();
$upgrader = new Theme_Upgrader( $skin );
$api = themes_api( 'theme_information', array(
'slug' => $theme_slug,
'fields' => array( 'sections' => false ),
) );
$api = themes_api(
'theme_information', array(
'slug' => $theme_slug,
'fields' => array( 'sections' => false ),
)
);
$result = $upgrader->install( $api->download_link );
if ( is_wp_error( $result ) ) {
@ -1161,6 +1214,7 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta (
WC_Admin_Notices::add_custom_notice(
$theme_slug . '_install_error',
sprintf(
// translators: 1: theme slug, 2: error message, 3: URL to install theme manually.
__( '%1$s could not be installed (%2$s). <a href="%3$s">Please install it manually by clicking here.</a>', 'woocommerce' ),
$theme_slug,
$e->getMessage(),
@ -1169,7 +1223,7 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta (
);
}
// Discard feedback
// Discard feedback.
ob_end_clean();
}
}

View File

@ -258,7 +258,7 @@ class WC_Order_Item extends WC_Data implements ArrayAccess {
$meta->value = rawurldecode( (string) $meta->value );
$attribute_key = str_replace( 'attribute_', '', $meta->key );
$display_key = wc_attribute_label( $attribute_key, $product );
$display_value = $meta->value;
$display_value = sanitize_text_field( $meta->value );
if ( taxonomy_exists( $attribute_key ) ) {
$term = get_term_by( 'slug', $meta->value, $attribute_key );

View File

@ -31,6 +31,7 @@ class WC_Post_Data {
add_filter( 'post_type_link', array( __CLASS__, 'variation_post_link' ), 10, 2 );
add_action( 'shutdown', array( __CLASS__, 'do_deferred_product_sync' ), 10 );
add_action( 'set_object_terms', array( __CLASS__, 'set_object_terms' ), 10, 6 );
add_action( 'set_object_terms', array( __CLASS__, 'force_default_term' ), 10, 5 );
add_action( 'transition_post_status', array( __CLASS__, 'transition_post_status' ), 10, 3 );
add_action( 'woocommerce_product_set_stock_status', array( __CLASS__, 'delete_product_query_transients' ) );
@ -500,6 +501,27 @@ class WC_Post_Data {
public static function flush_object_meta_cache( $meta_id, $object_id, $meta_key, $meta_value ) {
WC_Cache_Helper::incr_cache_prefix( 'object_' . $object_id );
}
/**
* Ensure default category gets set.
*
* @since 3.3.0
* @param int $object_id Product ID.
* @param array $terms Terms array.
* @param array $tt_ids Term ids array.
* @param string $taxonomy Taxonomy name.
* @param bool $append Are we appending or setting terms.
*/
public static function force_default_term( $object_id, $terms, $tt_ids, $taxonomy, $append ) {
if ( ! $append && 'product_cat' === $taxonomy && empty( $tt_ids ) && 'product' === get_post_type( $object_id ) ) {
$default_term = absint( get_option( 'default_product_cat', 0 ) );
$tt_ids = array_map( 'absint', $tt_ids );
if ( $default_term && ! in_array( $default_term, $tt_ids, true ) ) {
wp_set_post_terms( $object_id, array( $default_term ), 'product_cat', true );
}
}
}
}
WC_Post_Data::init();

View File

@ -29,6 +29,7 @@ class WC_Post_types {
add_action( 'init', array( __CLASS__, 'register_post_status' ), 9 );
add_action( 'init', array( __CLASS__, 'support_jetpack_omnisearch' ) );
add_filter( 'rest_api_allowed_post_types', array( __CLASS__, 'rest_api_allowed_post_types' ) );
add_action( 'woocommerce_after_register_post_type', array( __CLASS__, 'maybe_flush_rewrite_rules' ) );
add_action( 'woocommerce_flush_rewrite_rules', array( __CLASS__, 'flush_rewrite_rules' ) );
}
@ -493,6 +494,18 @@ class WC_Post_types {
}
}
/**
* Flush rules if the event is queued.
*
* @since 3.3.0
*/
public static function maybe_flush_rewrite_rules() {
if ( 'true' === get_option( 'woocommerce_queue_flush_rewrite_rules' ) ) {
delete_option( 'woocommerce_queue_flush_rewrite_rules' );
self::flush_rewrite_rules();
}
}
/**
* Flush rewrite rules.
*/

View File

@ -3,7 +3,7 @@
* Contains the query functions for WooCommerce which alter the front-end post queries and loops
*
* @version 3.2.0
* @package WooCommerce/Classes
* @package WooCommerce\Classes
* @author Automattic
*/
@ -50,7 +50,9 @@ class WC_Query {
* Get any errors from querystring.
*/
public function get_errors() {
if ( ! empty( $_GET['wc_error'] ) && ( $error = sanitize_text_field( $_GET['wc_error'] ) ) && ! wc_has_notice( $error, 'error' ) ) {
$error = ! empty( $_GET['wc_error'] ) ? sanitize_text_field( wp_unslash( $_GET['wc_error'] ) ) : ''; // WPCS: input var ok, CSRF ok.
if ( $error && ! wc_has_notice( $error, 'error' ) ) {
wc_add_notice( $error, 'error' );
}
}
@ -81,53 +83,54 @@ class WC_Query {
/**
* Get page title for an endpoint.
* @param string
*
* @param string $endpoint Endpoint key.
* @return string
*/
public function get_endpoint_title( $endpoint ) {
global $wp;
switch ( $endpoint ) {
case 'order-pay' :
case 'order-pay':
$title = __( 'Pay for order', 'woocommerce' );
break;
case 'order-received' :
break;
case 'order-received':
$title = __( 'Order received', 'woocommerce' );
break;
case 'orders' :
break;
case 'orders':
if ( ! empty( $wp->query_vars['orders'] ) ) {
/* translators: %s: page */
$title = sprintf( __( 'Orders (page %d)', 'woocommerce' ), intval( $wp->query_vars['orders'] ) );
} else {
$title = __( 'Orders', 'woocommerce' );
}
break;
case 'view-order' :
break;
case 'view-order':
$order = wc_get_order( $wp->query_vars['view-order'] );
/* translators: %s: order number */
$title = ( $order ) ? sprintf( __( 'Order #%s', 'woocommerce' ), $order->get_order_number() ) : '';
break;
case 'downloads' :
break;
case 'downloads':
$title = __( 'Downloads', 'woocommerce' );
break;
case 'edit-account' :
break;
case 'edit-account':
$title = __( 'Account details', 'woocommerce' );
break;
case 'edit-address' :
break;
case 'edit-address':
$title = __( 'Addresses', 'woocommerce' );
break;
case 'payment-methods' :
break;
case 'payment-methods':
$title = __( 'Payment methods', 'woocommerce' );
break;
case 'add-payment-method' :
break;
case 'add-payment-method':
$title = __( 'Add payment method', 'woocommerce' );
break;
case 'lost-password' :
break;
case 'lost-password':
$title = __( 'Lost password', 'woocommerce' );
break;
default :
break;
default:
$title = '';
break;
break;
}
return apply_filters( 'woocommerce_endpoint_' . $endpoint . '_title', $title, $endpoint );
@ -145,7 +148,7 @@ class WC_Query {
$myaccount_page_id = get_option( 'woocommerce_myaccount_page_id' );
$checkout_page_id = get_option( 'woocommerce_checkout_page_id' );
if ( in_array( $page_on_front, array( $myaccount_page_id, $checkout_page_id ) ) ) {
if ( in_array( $page_on_front, array( $myaccount_page_id, $checkout_page_id ), true ) ) {
return EP_ROOT | EP_PAGES;
}
}
@ -159,7 +162,7 @@ class WC_Query {
public function add_endpoints() {
$mask = $this->get_endpoints_mask();
foreach ( $this->query_vars as $key => $var ) {
foreach ( $this->get_query_vars() as $key => $var ) {
if ( ! empty( $var ) ) {
add_rewrite_endpoint( $var, $mask );
}
@ -170,7 +173,8 @@ class WC_Query {
* Add query vars.
*
* @access public
* @param array $vars
*
* @param array $vars Query vars.
* @return array
*/
public function add_query_vars( $vars ) {
@ -210,10 +214,10 @@ class WC_Query {
public function parse_request() {
global $wp;
// Map query vars to their keys, or get them if endpoints are not supported
// Map query vars to their keys, or get them if endpoints are not supported.
foreach ( $this->get_query_vars() as $key => $var ) {
if ( isset( $_GET[ $var ] ) ) {
$wp->query_vars[ $key ] = $_GET[ $var ];
if ( isset( $_GET[ $var ] ) ) { // WPCS: input var ok, CSRF ok.
$wp->query_vars[ $key ] = sanitize_text_field( wp_unslash( $_GET[ $var ] ) ); // WPCS: input var ok, CSRF ok.
} elseif ( isset( $wp->query_vars[ $var ] ) ) {
$wp->query_vars[ $key ] = $wp->query_vars[ $var ];
}
@ -223,8 +227,7 @@ class WC_Query {
/**
* Are we currently on the front page?
*
* @param object $q
*
* @param WP_Query $q Query instance.
* @return bool
*/
private function is_showing_page_on_front( $q ) {
@ -234,8 +237,7 @@ class WC_Query {
/**
* Is the front page a page we define?
*
* @param int $page_id
*
* @param int $page_id Page ID.
* @return bool
*/
private function page_on_front_is( $page_id ) {
@ -245,18 +247,18 @@ class WC_Query {
/**
* Hook into pre_get_posts to do the main product query.
*
* @param object $q query object
* @param WP_Query $q Query instance.
*/
public function pre_get_posts( $q ) {
// We only want to affect the main query
// We only want to affect the main query.
if ( ! $q->is_main_query() ) {
return;
}
// Fix for endpoints on the homepage
// Fix for endpoints on the homepage.
if ( $this->is_showing_page_on_front( $q ) && ! $this->page_on_front_is( $q->get( 'page_id' ) ) ) {
$_query = wp_parse_args( $q->query );
if ( ! empty( $_query ) && array_intersect( array_keys( $_query ), array_keys( $this->query_vars ) ) ) {
if ( ! empty( $_query ) && array_intersect( array_keys( $_query ), array_keys( $this->get_query_vars() ) ) ) {
$q->is_page = true;
$q->is_home = false;
$q->is_singular = true;
@ -276,14 +278,14 @@ class WC_Query {
}
}
// Fix product feeds
// Fix product feeds.
if ( $q->is_feed() && $q->is_post_type_archive( 'product' ) ) {
$q->is_comment_feed = false;
}
// Special check for shops with the product archive on front
// Special check for shops with the product archive on front.
if ( $q->is_page() && 'page' === get_option( 'show_on_front' ) && absint( $q->get( 'page_id' ) ) === wc_get_page_id( 'shop' ) ) {
// This is a front-page shop
// This is a front-page shop.
$q->set( 'post_type', 'product' );
$q->set( 'page_id', '' );
@ -291,54 +293,55 @@ class WC_Query {
$q->set( 'paged', $q->query['paged'] );
}
// Define a variable so we know this is the front page shop later on
// Define a variable so we know this is the front page shop later on.
wc_maybe_define_constant( 'SHOP_IS_ON_FRONT', true );
// Get the actual WP page to avoid errors and let us use is_front_page()
// This is hacky but works. Awaiting https://core.trac.wordpress.org/ticket/21096
// Get the actual WP page to avoid errors and let us use is_front_page().
// This is hacky but works. Awaiting https://core.trac.wordpress.org/ticket/21096.
global $wp_post_types;
$shop_page = get_post( wc_get_page_id( 'shop' ) );
$shop_page = get_post( wc_get_page_id( 'shop' ) );
$wp_post_types['product']->ID = $shop_page->ID;
$wp_post_types['product']->post_title = $shop_page->post_title;
$wp_post_types['product']->post_name = $shop_page->post_name;
$wp_post_types['product']->post_type = $shop_page->post_type;
$wp_post_types['product']->ancestors = get_ancestors( $shop_page->ID, $shop_page->post_type );
$wp_post_types['product']->ID = $shop_page->ID;
$wp_post_types['product']->post_title = $shop_page->post_title;
$wp_post_types['product']->post_name = $shop_page->post_name;
$wp_post_types['product']->post_type = $shop_page->post_type;
$wp_post_types['product']->ancestors = get_ancestors( $shop_page->ID, $shop_page->post_type );
// Fix conditional Functions like is_front_page
// Fix conditional Functions like is_front_page.
$q->is_singular = false;
$q->is_post_type_archive = true;
$q->is_archive = true;
$q->is_page = true;
// Remove post type archive name from front page title tag
// Remove post type archive name from front page title tag.
add_filter( 'post_type_archive_title', '__return_empty_string', 5 );
// Fix WP SEO
// Fix WP SEO.
if ( class_exists( 'WPSEO_Meta' ) ) {
add_filter( 'wpseo_metadesc', array( $this, 'wpseo_metadesc' ) );
add_filter( 'wpseo_metakey', array( $this, 'wpseo_metakey' ) );
}
// Only apply to product categories, the product post archive, the shop page, product tags, and product attribute taxonomies
} elseif ( ! $q->is_post_type_archive( 'product' ) && ! $q->is_tax( get_object_taxonomies( 'product' ) ) ) {
// Only apply to product categories, the product post archive, the shop page, product tags, and product attribute taxonomies.
return;
}
$this->product_query( $q );
// And remove the pre_get_posts hook
// And remove the pre_get_posts hook.
$this->remove_product_query();
}
/**
* Search post excerpt.
*
* @deprecated 3.2.0 - Not needed anymore since WordPress 4.5.
* @param string $deprecated Deprecated.
*/
public function search_post_excerpt( $where = '' ) {
public function search_post_excerpt( $deprecated = '' ) {
wc_deprecated_function( 'WC_Query::search_post_excerpt', '3.2.0', 'Excerpt added to search query by default since WordPress 4.5.' );
return $where;
return $deprecated;
}
/**
@ -346,7 +349,6 @@ class WC_Query {
*
* Hooked into wpseo_ hook already, so no need for function_exist.
*
* @access public
* @return string
*/
public function wpseo_metadesc() {
@ -366,9 +368,10 @@ class WC_Query {
}
/**
* Query the products, applying sorting/ordering etc. This applies to the main wordpress loop.
* Query the products, applying sorting/ordering etc.
* This applies to the main WordPress loop.
*
* @param mixed $q
* @param WP_Query $q Query instance.
*/
public function product_query( $q ) {
if ( ! is_feed() ) {
@ -381,7 +384,7 @@ class WC_Query {
}
}
// Query vars that affect posts shown
// Query vars that affect posts shown.
$q->set( 'meta_query', $this->get_meta_query( $q->get( 'meta_query' ), true ) );
$q->set( 'tax_query', $this->get_tax_query( $q->get( 'tax_query' ), true ) );
$q->set( 'posts_per_page', $q->get( 'posts_per_page' ) ? $q->get( 'posts_per_page' ) : apply_filters( 'loop_shop_per_page', get_option( 'posts_per_page' ) ) );
@ -391,7 +394,6 @@ class WC_Query {
do_action( 'woocommerce_product_query', $q, $this );
}
/**
* Remove the query.
*/
@ -411,6 +413,7 @@ class WC_Query {
/**
* Remove the posts_where filter.
*
* @deprecated 3.2.0 - Nothing to remove anymore because search_post_excerpt() is deprecated.
*/
public function remove_posts_where() {
@ -420,19 +423,17 @@ class WC_Query {
/**
* Returns an array of arguments for ordering products based on the selected values.
*
* @access public
*
* @param string $orderby
* @param string $order
* @param string $orderby Order by.
* @param string $order Sorting order.
*
* @return array
*/
public function get_catalog_ordering_args( $orderby = '', $order = '' ) {
// Get ordering from query string unless defined
// Get ordering from query string unless defined.
if ( ! $orderby ) {
$orderby_value = isset( $_GET['orderby'] ) ? wc_clean( (string) $_GET['orderby'] ) : apply_filters( 'woocommerce_default_catalog_orderby', get_option( 'woocommerce_default_catalog_orderby' ) );
$orderby_value = isset( $_GET['orderby'] ) ? wc_clean( wp_unslash( (string) $_GET['orderby'] ) ) : apply_filters( 'woocommerce_default_catalog_orderby', get_option( 'woocommerce_default_catalog_orderby' ) ); // WPCS: input var ok, CSRF ok.
// Get order + orderby args from string
// Get order + orderby args from string.
$orderby_value = explode( '-', $orderby_value );
$orderby = esc_attr( $orderby_value[0] );
$order = ! empty( $orderby_value[1] ) ? $orderby_value[1] : $order;
@ -443,49 +444,49 @@ class WC_Query {
$args = array(
'orderby' => 'relevance',
'order' => 'DESC',
'meta_key' => '',
'meta_key' => '', // WPCS: slow query ok.
);
// Set to default. Menu order for non-searches, relevance for searches.
if ( ! is_search() ) {
$args['orderby'] = 'menu_order title';
$args['order'] = ( 'DESC' === $order ) ? 'DESC' : 'ASC';
$args['meta_key'] = '';
$args['meta_key'] = ''; // WPCS: slow query ok.
}
switch ( $orderby ) {
case 'rand' :
case 'rand':
$args['orderby'] = 'rand';
break;
case 'date' :
case 'date':
$args['orderby'] = 'date ID';
$args['order'] = ( 'ASC' === $order ) ? 'ASC' : 'DESC';
break;
case 'price' :
case 'price':
if ( 'DESC' === $order ) {
add_filter( 'posts_clauses', array( $this, 'order_by_price_desc_post_clauses' ) );
} else {
add_filter( 'posts_clauses', array( $this, 'order_by_price_asc_post_clauses' ) );
}
break;
case 'popularity' :
$args['meta_key'] = 'total_sales';
case 'popularity':
$args['meta_key'] = 'total_sales'; // WPCS: slow query ok.
// Sorting handled later though a hook
// Sorting handled later though a hook.
add_filter( 'posts_clauses', array( $this, 'order_by_popularity_post_clauses' ) );
break;
case 'rating' :
$args['meta_key'] = '_wc_average_rating';
case 'rating':
$args['meta_key'] = '_wc_average_rating'; // WPCS: slow query ok.
$args['orderby'] = array(
'meta_value_num' => 'DESC',
'ID' => 'ASC',
);
break;
case 'title' :
case 'title':
$args['orderby'] = 'title';
$args['order'] = ( 'DESC' === $order ) ? 'DESC' : 'ASC';
break;
case 'relevance' :
case 'relevance':
$args['orderby'] = 'relevance';
$args['order'] = 'DESC';
break;
@ -497,8 +498,7 @@ class WC_Query {
/**
* Handle numeric price sorting.
*
* @access public
* @param array $args
* @param array $args Query args.
* @return array
*/
public function order_by_price_asc_post_clauses( $args ) {
@ -527,8 +527,7 @@ class WC_Query {
/**
* Handle numeric price sorting.
*
* @access public
* @param array $args
* @param array $args Query args.
* @return array
*/
public function order_by_price_desc_post_clauses( $args ) {
@ -560,8 +559,7 @@ class WC_Query {
*
* This lets us sort by meta value desc, and have a second orderby param.
*
* @access public
* @param array $args
* @param array $args Query args.
* @return array
*/
public function order_by_popularity_post_clauses( $args ) {
@ -574,7 +572,7 @@ class WC_Query {
* Order by rating post clauses.
*
* @deprecated 3.0.0
* @param array $args
* @param array $args Query args.
* @return array
*/
public function order_by_rating_post_clauses( $args ) {
@ -597,8 +595,8 @@ class WC_Query {
/**
* Appends meta queries to an array.
*
* @param array $meta_query
* @param bool $main_query
* @param array $meta_query Meta query.
* @param bool $main_query If is main query.
* @return array
*/
public function get_meta_query( $meta_query = array(), $main_query = false ) {
@ -611,18 +609,21 @@ class WC_Query {
/**
* Appends tax queries to an array.
* @param array $tax_query
* @param bool $main_query
*
* @param array $tax_query Tax query.
* @param bool $main_query If is main query.
* @return array
*/
public function get_tax_query( $tax_query = array(), $main_query = false ) {
if ( ! is_array( $tax_query ) ) {
$tax_query = array( 'relation' => 'AND' );
$tax_query = array(
'relation' => 'AND',
);
}
// Layered nav filters on terms.
if ( $main_query && ( $_chosen_attributes = $this->get_layered_nav_chosen_attributes() ) ) {
foreach ( $_chosen_attributes as $taxonomy => $data ) {
if ( $main_query ) {
foreach ( $this->get_layered_nav_chosen_attributes() as $taxonomy => $data ) {
$tax_query[] = array(
'taxonomy' => $taxonomy,
'field' => 'slug',
@ -642,11 +643,11 @@ class WC_Query {
}
// Filter by rating.
if ( isset( $_GET['rating_filter'] ) ) {
$rating_filter = array_filter( array_map( 'absint', explode( ',', $_GET['rating_filter'] ) ) );
if ( isset( $_GET['rating_filter'] ) ) { // WPCS: input var ok, CSRF ok.
$rating_filter = array_filter( array_map( 'absint', explode( ',', $_GET['rating_filter'] ) ) ); // WPCS: input var ok, CSRF ok, Sanitization ok.
$rating_terms = array();
for ( $i = 1; $i <= 5; $i ++ ) {
if ( in_array( $i, $rating_filter ) && isset( $product_visibility_terms[ 'rated-' . $i ] ) ) {
if ( in_array( $i, $rating_filter, true ) && isset( $product_visibility_terms[ 'rated-' . $i ] ) ) {
$rating_terms[] = $product_visibility_terms[ 'rated-' . $i ];
}
}
@ -675,11 +676,12 @@ class WC_Query {
/**
* Return a meta query for filtering by price.
*
* @return array
*/
private function price_filter_meta_query() {
if ( isset( $_GET['max_price'] ) || isset( $_GET['min_price'] ) ) {
$meta_query = wc_get_min_max_price_meta_query( $_GET );
if ( isset( $_GET['max_price'] ) || isset( $_GET['min_price'] ) ) { // WPCS: input var ok, CSRF ok.
$meta_query = wc_get_min_max_price_meta_query( $_GET ); // WPCS: input var ok, CSRF ok.
$meta_query['price_filter'] = true;
return $meta_query;
@ -702,7 +704,7 @@ class WC_Query {
* Returns a meta query to handle product visibility.
*
* @deprecated 3.0.0 Replaced with taxonomy.
* @param string $compare (default: 'IN')
* @param string $compare Compare type.
* @return array
*/
public function visibility_meta_query( $compare = 'IN' ) {
@ -713,7 +715,7 @@ class WC_Query {
* Returns a meta query to handle product stock status.
*
* @deprecated 3.0.0 Replaced with taxonomy.
* @param string $status (default: 'instock')
* @param string $status Status.
* @return array
*/
public function stock_status_meta_query( $status = 'instock' ) {
@ -722,6 +724,7 @@ class WC_Query {
/**
* Get the tax query which was used by the main query.
*
* @return array
*/
public static function get_main_tax_query() {
@ -734,6 +737,7 @@ class WC_Query {
/**
* Get the meta query which was used by the main query.
*
* @return array
*/
public static function get_main_meta_query() {
@ -769,7 +773,7 @@ class WC_Query {
}
$like = '%' . $wpdb->esc_like( $term ) . '%';
$sql[] = $wpdb->prepare( "(($wpdb->posts.post_title $like_op %s) $andor_op ($wpdb->posts.post_excerpt $like_op %s) $andor_op ($wpdb->posts.post_content $like_op %s))", $like, $like, $like );
$sql[] = $wpdb->prepare( "(($wpdb->posts.post_title $like_op %s) $andor_op ($wpdb->posts.post_excerpt $like_op %s) $andor_op ($wpdb->posts.post_content $like_op %s))", $like, $like, $like ); // WPCS: db call ok, cache ok, unprepared SQL ok.
}
if ( ! empty( $sql ) && ! is_user_logged_in() ) {
@ -781,23 +785,26 @@ class WC_Query {
/**
* Layered Nav Init.
*
* @return array
*/
public static function get_layered_nav_chosen_attributes() {
if ( ! is_array( self::$_chosen_attributes ) ) {
self::$_chosen_attributes = array();
if ( $attribute_taxonomies = wc_get_attribute_taxonomies() ) {
$attribute_taxonomies = wc_get_attribute_taxonomies();
if ( $attribute_taxonomies ) {
foreach ( $attribute_taxonomies as $tax ) {
$attribute = wc_sanitize_taxonomy_name( $tax->attribute_name );
$taxonomy = wc_attribute_taxonomy_name( $attribute );
$filter_terms = ! empty( $_GET[ 'filter_' . $attribute ] ) ? explode( ',', wc_clean( $_GET[ 'filter_' . $attribute ] ) ) : array();
$filter_terms = ! empty( $_GET[ 'filter_' . $attribute ] ) ? explode( ',', wc_clean( wp_unslash( $_GET[ 'filter_' . $attribute ] ) ) ) : array(); // WPCS: input var ok, CSRF ok.
if ( empty( $filter_terms ) || ! taxonomy_exists( $taxonomy ) ) {
continue;
}
$query_type = ! empty( $_GET[ 'query_type_' . $attribute ] ) && in_array( $_GET[ 'query_type_' . $attribute ], array( 'and', 'or' ) ) ? wc_clean( $_GET[ 'query_type_' . $attribute ] ) : '';
self::$_chosen_attributes[ $taxonomy ]['terms'] = array_map( 'sanitize_title', $filter_terms ); // Ensures correct encoding
$query_type = ! empty( $_GET[ 'query_type_' . $attribute ] ) && in_array( wp_unslash( $_GET[ 'query_type_' . $attribute ] ), array( 'and', 'or' ), true ) ? wc_clean( wp_unslash( $_GET[ 'query_type_' . $attribute ] ) ) : ''; // WPCS: input var ok, CSRF ok.
self::$_chosen_attributes[ $taxonomy ]['terms'] = array_map( 'sanitize_title', $filter_terms ); // Ensures correct encoding.
self::$_chosen_attributes[ $taxonomy ]['query_type'] = $query_type ? $query_type : apply_filters( 'woocommerce_layered_nav_default_query_type', 'and' );
}
}
@ -806,6 +813,8 @@ class WC_Query {
}
/**
* Layered nav init.
*
* @deprecated 2.6.0
*/
public function layered_nav_init() {
@ -814,6 +823,7 @@ class WC_Query {
/**
* Get an unpaginated list all product IDs (both filtered and unfiltered). Makes use of transients.
*
* @deprecated 2.6.0 due to performance concerns
*/
public function get_products_in_view() {
@ -822,11 +832,12 @@ class WC_Query {
/**
* Layered Nav post filter.
*
* @deprecated 2.6.0 due to performance concerns
*
* @param $filtered_posts
* @param mixed $deprecated Deprecated.
*/
public function layered_nav_query( $filtered_posts ) {
public function layered_nav_query( $deprecated ) {
wc_deprecated_function( 'layered_nav_query', '2.6' );
}
}

View File

@ -579,7 +579,7 @@ class WC_Tax {
} elseif ( WC()->cart->get_cart() ) {
// This will be per order shipping - loop through the order and find the highest tax class rate
$cart_tax_classes = WC()->cart->get_cart_item_tax_classes();
$cart_tax_classes = WC()->cart->get_cart_item_tax_classes_for_shipping();
// No tax classes = no taxable items.
if ( empty( $cart_tax_classes ) ) {

View File

@ -1,4 +1,10 @@
<?php
/**
* Abstract_WC_Order_Data_Store_CPT class file.
*
* @package WooCommerce/Classes
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
@ -46,25 +52,31 @@ abstract class Abstract_WC_Order_Data_Store_CPT extends WC_Data_Store_WP impleme
/**
* Method to create a new order in the database.
* @param WC_Order $order
*
* @param WC_Order $order Order object.
*/
public function create( &$order ) {
$order->set_version( WC_VERSION );
$order->set_date_created( current_time( 'timestamp', true ) );
$order->set_currency( $order->get_currency() ? $order->get_currency() : get_woocommerce_currency() );
$id = wp_insert_post( apply_filters( 'woocommerce_new_order_data', array(
'post_date' => gmdate( 'Y-m-d H:i:s', $order->get_date_created( 'edit' )->getOffsetTimestamp() ),
'post_date_gmt' => gmdate( 'Y-m-d H:i:s', $order->get_date_created( 'edit' )->getTimestamp() ),
'post_type' => $order->get_type( 'edit' ),
'post_status' => 'wc-' . ( $order->get_status( 'edit' ) ? $order->get_status( 'edit' ) : apply_filters( 'woocommerce_default_order_status', 'pending' ) ),
'ping_status' => 'closed',
'post_author' => 1,
'post_title' => $this->get_post_title(),
'post_password' => uniqid( 'order_' ),
'post_parent' => $order->get_parent_id( 'edit' ),
'post_excerpt' => $this->get_post_excerpt( $order ),
) ), true );
$id = wp_insert_post(
apply_filters(
'woocommerce_new_order_data',
array(
'post_date' => gmdate( 'Y-m-d H:i:s', $order->get_date_created( 'edit' )->getOffsetTimestamp() ),
'post_date_gmt' => gmdate( 'Y-m-d H:i:s', $order->get_date_created( 'edit' )->getTimestamp() ),
'post_type' => $order->get_type( 'edit' ),
'post_status' => 'wc-' . ( $order->get_status( 'edit' ) ? $order->get_status( 'edit' ) : apply_filters( 'woocommerce_default_order_status', 'pending' ) ),
'ping_status' => 'closed',
'post_author' => 1,
'post_title' => $this->get_post_title(),
'post_password' => uniqid( 'order_' ),
'post_parent' => $order->get_parent_id( 'edit' ),
'post_excerpt' => $this->get_post_excerpt( $order ),
)
), true
);
if ( $id && ! is_wp_error( $id ) ) {
$order->set_id( $id );
@ -78,23 +90,26 @@ abstract class Abstract_WC_Order_Data_Store_CPT extends WC_Data_Store_WP impleme
/**
* Method to read an order from the database.
*
* @param WC_Data $order
* @param WC_Data $order Order object.
*
* @throws Exception
* @throws Exception If passed order is invalid.
*/
public function read( &$order ) {
$order->set_defaults();
$post_object = get_post( $order->get_id() );
if ( ! $order->get_id() || ! ( $post_object = get_post( $order->get_id() ) ) || ! in_array( $post_object->post_type, wc_get_order_types() ) ) {
if ( ! $order->get_id() || ! $post_object || ! in_array( $post_object->post_type, wc_get_order_types() ) ) {
throw new Exception( __( 'Invalid order.', 'woocommerce' ) );
}
$order->set_props( array(
'parent_id' => $post_object->post_parent,
'date_created' => 0 < $post_object->post_date_gmt ? wc_string_to_timestamp( $post_object->post_date_gmt ) : null,
'date_modified' => 0 < $post_object->post_modified_gmt ? wc_string_to_timestamp( $post_object->post_modified_gmt ) : null,
'status' => $post_object->post_status,
) );
$order->set_props(
array(
'parent_id' => $post_object->post_parent,
'date_created' => 0 < $post_object->post_date_gmt ? wc_string_to_timestamp( $post_object->post_date_gmt ) : null,
'date_modified' => 0 < $post_object->post_modified_gmt ? wc_string_to_timestamp( $post_object->post_modified_gmt ) : null,
'status' => $post_object->post_status,
)
);
$this->read_order_data( $order, $post_object );
$order->read_meta_data();
@ -112,7 +127,8 @@ abstract class Abstract_WC_Order_Data_Store_CPT extends WC_Data_Store_WP impleme
/**
* Method to update an order in the database.
* @param WC_Order $order
*
* @param WC_Order $order Order object.
*/
public function update( &$order ) {
$order->save_meta_data();
@ -155,14 +171,20 @@ abstract class Abstract_WC_Order_Data_Store_CPT extends WC_Data_Store_WP impleme
/**
* Method to delete an order from the database.
* @param WC_Order $order
* @param array $args Array of args to pass to the delete method.
*
* @param WC_Order $order Order object.
* @param array $args Array of args to pass to the delete method.
*
* @return void
*/
public function delete( &$order, $args = array() ) {
$id = $order->get_id();
$args = wp_parse_args( $args, array(
'force_delete' => false,
) );
$args = wp_parse_args(
$args,
array(
'force_delete' => false,
)
);
if ( ! $id ) {
return;
@ -188,7 +210,7 @@ abstract class Abstract_WC_Order_Data_Store_CPT extends WC_Data_Store_WP impleme
/**
* Excerpt for post.
*
* @param WC_order $order
* @param WC_order $order Order object.
* @return string
*/
protected function get_post_excerpt( $order ) {
@ -210,24 +232,26 @@ abstract class Abstract_WC_Order_Data_Store_CPT extends WC_Data_Store_WP impleme
/**
* Read order data. Can be overridden by child classes to load other props.
*
* @param WC_Order $order
* @param object $post_object
* @param WC_Order $order Order object.
* @param object $post_object Post object.
* @since 3.0.0
*/
protected function read_order_data( &$order, $post_object ) {
$id = $order->get_id();
$order->set_props( array(
'currency' => get_post_meta( $id, '_order_currency', true ),
'discount_total' => get_post_meta( $id, '_cart_discount', true ),
'discount_tax' => get_post_meta( $id, '_cart_discount_tax', true ),
'shipping_total' => get_post_meta( $id, '_order_shipping', true ),
'shipping_tax' => get_post_meta( $id, '_order_shipping_tax', true ),
'cart_tax' => get_post_meta( $id, '_order_tax', true ),
'total' => get_post_meta( $id, '_order_total', true ),
'version' => get_post_meta( $id, '_order_version', true ),
'prices_include_tax' => metadata_exists( 'post', $id, '_prices_include_tax' ) ? 'yes' === get_post_meta( $id, '_prices_include_tax', true ) : 'yes' === get_option( 'woocommerce_prices_include_tax' ),
) );
$order->set_props(
array(
'currency' => get_post_meta( $id, '_order_currency', true ),
'discount_total' => get_post_meta( $id, '_cart_discount', true ),
'discount_tax' => get_post_meta( $id, '_cart_discount_tax', true ),
'shipping_total' => get_post_meta( $id, '_order_shipping', true ),
'shipping_tax' => get_post_meta( $id, '_order_shipping_tax', true ),
'cart_tax' => get_post_meta( $id, '_order_tax', true ),
'total' => get_post_meta( $id, '_order_total', true ),
'version' => get_post_meta( $id, '_order_version', true ),
'prices_include_tax' => metadata_exists( 'post', $id, '_prices_include_tax' ) ? 'yes' === get_post_meta( $id, '_prices_include_tax', true ) : 'yes' === get_option( 'woocommerce_prices_include_tax' ),
)
);
// Gets extra data associated with the order if needed.
foreach ( $order->get_extra_data_keys() as $key ) {
@ -241,7 +265,7 @@ abstract class Abstract_WC_Order_Data_Store_CPT extends WC_Data_Store_WP impleme
/**
* Helper method that updates all the post meta for an order based on it's settings in the WC_Order class.
*
* @param $order WC_Order
* @param WC_Order $order Order object.
* @since 3.0.0
*/
protected function update_post_meta( &$order ) {
@ -278,7 +302,7 @@ abstract class Abstract_WC_Order_Data_Store_CPT extends WC_Data_Store_WP impleme
/**
* Clear any caches.
*
* @param WC_Order $order
* @param WC_Order $order Order object.
* @since 3.0.0
*/
protected function clear_caches( &$order ) {
@ -290,8 +314,8 @@ abstract class Abstract_WC_Order_Data_Store_CPT extends WC_Data_Store_WP impleme
/**
* Read order items of a specific type from the database for this order.
*
* @param WC_Order $order
* @param string $type
* @param WC_Order $order Order object.
* @param string $type Order item type.
* @return array
*/
public function read_items( $order, $type ) {
@ -301,8 +325,9 @@ abstract class Abstract_WC_Order_Data_Store_CPT extends WC_Data_Store_WP impleme
$items = wp_cache_get( 'order-items-' . $order->get_id(), 'orders' );
if ( false === $items ) {
$get_items_sql = $wpdb->prepare( "SELECT order_item_type, order_item_id, order_id, order_item_name FROM {$wpdb->prefix}woocommerce_order_items WHERE order_id = %d ORDER BY order_item_id;", $order->get_id() );
$items = $wpdb->get_results( $get_items_sql );
$items = $wpdb->get_results(
$wpdb->prepare( "SELECT order_item_type, order_item_id, order_id, order_item_name FROM {$wpdb->prefix}woocommerce_order_items WHERE order_id = %d ORDER BY order_item_id;", $order->get_id() )
);
foreach ( $items as $item ) {
wp_cache_set( 'item-' . $item->order_item_id, $item, 'order-items' );
}
@ -323,7 +348,7 @@ abstract class Abstract_WC_Order_Data_Store_CPT extends WC_Data_Store_WP impleme
/**
* Remove all line items (products, coupons, shipping, taxes) from the order.
*
* @param WC_Order $order
* @param WC_Order $order Order object.
* @param string $type Order item type. Default null.
*/
public function delete_items( $order, $type = null ) {
@ -341,7 +366,7 @@ abstract class Abstract_WC_Order_Data_Store_CPT extends WC_Data_Store_WP impleme
/**
* Get token ids for an order.
*
* @param WC_Order $order
* @param WC_Order $order Order object.
* @return array
*/
public function get_payment_token_ids( $order ) {
@ -352,8 +377,8 @@ abstract class Abstract_WC_Order_Data_Store_CPT extends WC_Data_Store_WP impleme
/**
* Update token ids for an order.
*
* @param WC_Order $order
* @param array $token_ids
* @param WC_Order $order Order object.
* @param array $token_ids Payment token ids.
*/
public function update_payment_token_ids( $order, $token_ids ) {
update_post_meta( $order->get_id(), '_payment_tokens', $token_ids );

View File

@ -1,4 +1,10 @@
<?php
/**
* WC_Order_Data_Store_CPT class file.
*
* @package WooCommerce/Classes
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
@ -14,6 +20,7 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement
/**
* Data stored in meta keys, but not considered "meta" for an order.
*
* @since 3.0.0
* @var array
*/
@ -70,7 +77,8 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement
/**
* Method to create a new order in the database.
* @param WC_Order $order
*
* @param WC_Order $order Order object.
*/
public function create( &$order ) {
$order->set_order_key( 'wc_' . apply_filters( 'woocommerce_generate_order_key', uniqid( 'order_' ) ) );
@ -81,8 +89,8 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement
/**
* Read order data. Can be overridden by child classes to load other props.
*
* @param WC_Order $order
* @param object $post_object
* @param WC_Order $order Order object.
* @param object $post_object Post object.
* @since 3.0.0
*/
protected function read_order_data( &$order, $post_object ) {
@ -99,45 +107,48 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement
$date_paid = get_post_meta( $id, '_paid_date', true );
}
$order->set_props( array(
'order_key' => get_post_meta( $id, '_order_key', true ),
'customer_id' => get_post_meta( $id, '_customer_user', true ),
'billing_first_name' => get_post_meta( $id, '_billing_first_name', true ),
'billing_last_name' => get_post_meta( $id, '_billing_last_name', true ),
'billing_company' => get_post_meta( $id, '_billing_company', true ),
'billing_address_1' => get_post_meta( $id, '_billing_address_1', true ),
'billing_address_2' => get_post_meta( $id, '_billing_address_2', true ),
'billing_city' => get_post_meta( $id, '_billing_city', true ),
'billing_state' => get_post_meta( $id, '_billing_state', true ),
'billing_postcode' => get_post_meta( $id, '_billing_postcode', true ),
'billing_country' => get_post_meta( $id, '_billing_country', true ),
'billing_email' => get_post_meta( $id, '_billing_email', true ),
'billing_phone' => get_post_meta( $id, '_billing_phone', true ),
'shipping_first_name' => get_post_meta( $id, '_shipping_first_name', true ),
'shipping_last_name' => get_post_meta( $id, '_shipping_last_name', true ),
'shipping_company' => get_post_meta( $id, '_shipping_company', true ),
'shipping_address_1' => get_post_meta( $id, '_shipping_address_1', true ),
'shipping_address_2' => get_post_meta( $id, '_shipping_address_2', true ),
'shipping_city' => get_post_meta( $id, '_shipping_city', true ),
'shipping_state' => get_post_meta( $id, '_shipping_state', true ),
'shipping_postcode' => get_post_meta( $id, '_shipping_postcode', true ),
'shipping_country' => get_post_meta( $id, '_shipping_country', true ),
'payment_method' => get_post_meta( $id, '_payment_method', true ),
'payment_method_title' => get_post_meta( $id, '_payment_method_title', true ),
'transaction_id' => get_post_meta( $id, '_transaction_id', true ),
'customer_ip_address' => get_post_meta( $id, '_customer_ip_address', true ),
'customer_user_agent' => get_post_meta( $id, '_customer_user_agent', true ),
'created_via' => get_post_meta( $id, '_created_via', true ),
'date_completed' => $date_completed,
'date_paid' => $date_paid,
'cart_hash' => get_post_meta( $id, '_cart_hash', true ),
'customer_note' => $post_object->post_excerpt,
) );
$order->set_props(
array(
'order_key' => get_post_meta( $id, '_order_key', true ),
'customer_id' => get_post_meta( $id, '_customer_user', true ),
'billing_first_name' => get_post_meta( $id, '_billing_first_name', true ),
'billing_last_name' => get_post_meta( $id, '_billing_last_name', true ),
'billing_company' => get_post_meta( $id, '_billing_company', true ),
'billing_address_1' => get_post_meta( $id, '_billing_address_1', true ),
'billing_address_2' => get_post_meta( $id, '_billing_address_2', true ),
'billing_city' => get_post_meta( $id, '_billing_city', true ),
'billing_state' => get_post_meta( $id, '_billing_state', true ),
'billing_postcode' => get_post_meta( $id, '_billing_postcode', true ),
'billing_country' => get_post_meta( $id, '_billing_country', true ),
'billing_email' => get_post_meta( $id, '_billing_email', true ),
'billing_phone' => get_post_meta( $id, '_billing_phone', true ),
'shipping_first_name' => get_post_meta( $id, '_shipping_first_name', true ),
'shipping_last_name' => get_post_meta( $id, '_shipping_last_name', true ),
'shipping_company' => get_post_meta( $id, '_shipping_company', true ),
'shipping_address_1' => get_post_meta( $id, '_shipping_address_1', true ),
'shipping_address_2' => get_post_meta( $id, '_shipping_address_2', true ),
'shipping_city' => get_post_meta( $id, '_shipping_city', true ),
'shipping_state' => get_post_meta( $id, '_shipping_state', true ),
'shipping_postcode' => get_post_meta( $id, '_shipping_postcode', true ),
'shipping_country' => get_post_meta( $id, '_shipping_country', true ),
'payment_method' => get_post_meta( $id, '_payment_method', true ),
'payment_method_title' => get_post_meta( $id, '_payment_method_title', true ),
'transaction_id' => get_post_meta( $id, '_transaction_id', true ),
'customer_ip_address' => get_post_meta( $id, '_customer_ip_address', true ),
'customer_user_agent' => get_post_meta( $id, '_customer_user_agent', true ),
'created_via' => get_post_meta( $id, '_created_via', true ),
'date_completed' => $date_completed,
'date_paid' => $date_paid,
'cart_hash' => get_post_meta( $id, '_cart_hash', true ),
'customer_note' => $post_object->post_excerpt,
)
);
}
/**
* Method to update an order in the database.
* @param WC_Order $order
*
* @param WC_Order $order Order object.
*/
public function update( &$order ) {
// Before updating, ensure date paid is set if missing.
@ -154,7 +165,7 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement
/**
* Helper method that updates all the post meta for an order based on it's settings in the WC_Order class.
*
* @param WC_Order $order
* @param WC_Order $order Order object.
* @since 3.0.0
*/
protected function update_post_meta( &$order ) {
@ -201,7 +212,7 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement
}
$address_props = array(
'billing' => array(
'billing' => array(
'_billing_first_name' => 'billing_first_name',
'_billing_last_name' => 'billing_last_name',
'_billing_company' => 'billing_company',
@ -259,7 +270,7 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement
/**
* Excerpt for post.
*
* @param WC_Order $order
* @param WC_Order $order Order object.
* @return string
*/
protected function get_post_excerpt( $order ) {
@ -269,19 +280,22 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement
/**
* Get amount already refunded.
*
* @param WC_Order $order
* @param WC_Order $order Order object.
* @return string
*/
public function get_total_refunded( $order ) {
global $wpdb;
$total = $wpdb->get_var( $wpdb->prepare( "
SELECT SUM( postmeta.meta_value )
FROM $wpdb->postmeta AS postmeta
INNER JOIN $wpdb->posts AS posts ON ( posts.post_type = 'shop_order_refund' AND posts.post_parent = %d )
WHERE postmeta.meta_key = '_refund_amount'
AND postmeta.post_id = posts.ID
", $order->get_id() ) );
$total = $wpdb->get_var(
$wpdb->prepare(
"SELECT SUM( postmeta.meta_value )
FROM $wpdb->postmeta AS postmeta
INNER JOIN $wpdb->posts AS posts ON ( posts.post_type = 'shop_order_refund' AND posts.post_parent = %d )
WHERE postmeta.meta_key = '_refund_amount'
AND postmeta.post_id = posts.ID",
$order->get_id()
)
);
return $total;
}
@ -289,20 +303,23 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement
/**
* Get the total tax refunded.
*
* @param WC_Order $order
* @param WC_Order $order Order object.
* @return float
*/
public function get_total_tax_refunded( $order ) {
global $wpdb;
$total = $wpdb->get_var( $wpdb->prepare( "
SELECT SUM( order_itemmeta.meta_value )
FROM {$wpdb->prefix}woocommerce_order_itemmeta AS order_itemmeta
INNER JOIN $wpdb->posts AS posts ON ( posts.post_type = 'shop_order_refund' AND posts.post_parent = %d )
INNER JOIN {$wpdb->prefix}woocommerce_order_items AS order_items ON ( order_items.order_id = posts.ID AND order_items.order_item_type = 'tax' )
WHERE order_itemmeta.order_item_id = order_items.order_item_id
AND order_itemmeta.meta_key IN ('tax_amount', 'shipping_tax_amount')
", $order->get_id() ) );
$total = $wpdb->get_var(
$wpdb->prepare(
"SELECT SUM( order_itemmeta.meta_value )
FROM {$wpdb->prefix}woocommerce_order_itemmeta AS order_itemmeta
INNER JOIN $wpdb->posts AS posts ON ( posts.post_type = 'shop_order_refund' AND posts.post_parent = %d )
INNER JOIN {$wpdb->prefix}woocommerce_order_items AS order_items ON ( order_items.order_id = posts.ID AND order_items.order_item_type = 'tax' )
WHERE order_itemmeta.order_item_id = order_items.order_item_id
AND order_itemmeta.meta_key IN ('tax_amount', 'shipping_tax_amount')",
$order->get_id()
)
);
return abs( $total );
}
@ -310,20 +327,23 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement
/**
* Get the total shipping refunded.
*
* @param WC_Order $order
* @param WC_Order $order Order object.
* @return float
*/
public function get_total_shipping_refunded( $order ) {
global $wpdb;
$total = $wpdb->get_var( $wpdb->prepare( "
SELECT SUM( order_itemmeta.meta_value )
FROM {$wpdb->prefix}woocommerce_order_itemmeta AS order_itemmeta
INNER JOIN $wpdb->posts AS posts ON ( posts.post_type = 'shop_order_refund' AND posts.post_parent = %d )
INNER JOIN {$wpdb->prefix}woocommerce_order_items AS order_items ON ( order_items.order_id = posts.ID AND order_items.order_item_type = 'shipping' )
WHERE order_itemmeta.order_item_id = order_items.order_item_id
AND order_itemmeta.meta_key IN ('cost')
", $order->get_id() ) );
$total = $wpdb->get_var(
$wpdb->prepare(
"SELECT SUM( order_itemmeta.meta_value )
FROM {$wpdb->prefix}woocommerce_order_itemmeta AS order_itemmeta
INNER JOIN $wpdb->posts AS posts ON ( posts.post_type = 'shop_order_refund' AND posts.post_parent = %d )
INNER JOIN {$wpdb->prefix}woocommerce_order_items AS order_items ON ( order_items.order_id = posts.ID AND order_items.order_item_type = 'shipping' )
WHERE order_itemmeta.order_item_id = order_items.order_item_id
AND order_itemmeta.meta_key IN ('cost')",
$order->get_id()
)
);
return abs( $total );
}
@ -331,7 +351,7 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement
/**
* Finds an Order ID based on an order key.
*
* @param string $order_key An order key has generated by
* @param string $order_key An order key has generated by.
* @return int The ID of an order, or 0 if the order could not be found
*/
public function get_order_id_by_order_key( $order_key ) {
@ -342,7 +362,7 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement
/**
* Return count of orders with a specific status.
*
* @param string $status
* @param string $status Order status. Function wc_get_order_statuses() returns a list of valid statuses.
* @return int
*/
public function get_order_count( $status ) {
@ -356,7 +376,7 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement
* @deprecated 3.1.0 - Use wc_get_orders instead.
* @see wc_get_orders()
*
* @param array $args
* @param array $args List of args passed to wc_get_orders().
*
* @return array|object
*/
@ -368,19 +388,19 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement
/**
* Generate meta query for wc_get_orders.
*
* @param array $values
* @param string $relation
* @param array $values List of customers ids or emails.
* @param string $relation 'or' or 'and' relation used to build the WP meta_query.
* @return array
*/
private function get_orders_generate_customer_meta_query( $values, $relation = 'or' ) {
$meta_query = array(
'relation' => strtoupper( $relation ),
'relation' => strtoupper( $relation ),
'customer_emails' => array(
'key' => '_billing_email',
'value' => array(),
'compare' => 'IN',
),
'customer_ids' => array(
'customer_ids' => array(
'key' => '_customer_user',
'value' => array(),
'compare' => 'IN',
@ -418,19 +438,24 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement
/**
* Get unpaid orders after a certain date,
*
* @param int $date timestamp
* @param int $date Timestamp.
* @return array
*/
public function get_unpaid_orders( $date ) {
global $wpdb;
$unpaid_orders = $wpdb->get_col( $wpdb->prepare( "
SELECT posts.ID
FROM {$wpdb->posts} AS posts
WHERE posts.post_type IN ('" . implode( "','", wc_get_order_types() ) . "')
AND posts.post_status = 'wc-pending'
AND posts.post_modified < %s
", date( 'Y-m-d H:i:s', absint( $date ) ) ) );
$unpaid_orders = $wpdb->get_col(
$wpdb->prepare(
// @codingStandardsIgnoreStart
"SELECT posts.ID
FROM {$wpdb->posts} AS posts
WHERE posts.post_type IN ('" . implode( "','", wc_get_order_types() ) . "')
AND posts.post_status = 'wc-pending'
AND posts.post_modified < %s",
// @codingStandardsIgnoreEnd
date( 'Y-m-d H:i:s', absint( $date ) )
)
);
return $unpaid_orders;
}
@ -438,7 +463,7 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement
/**
* Search order data for a term and return ids.
*
* @param string $term
* @param string $term Searched term.
* @return array of ids
*/
public function search_orders( $term ) {
@ -448,36 +473,45 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement
* Searches on meta data can be slow - this lets you choose what fields to search.
* 3.0.0 added _billing_address and _shipping_address meta which contains all address data to make this faster.
* This however won't work on older orders unless updated, so search a few others (expand this using the filter if needed).
*
* @var array
*/
$search_fields = array_map( 'wc_clean', apply_filters( 'woocommerce_shop_order_search_fields', array(
'_billing_address_index',
'_shipping_address_index',
'_billing_last_name',
'_billing_email',
) ) );
$order_ids = array();
$search_fields = array_map(
'wc_clean', apply_filters(
'woocommerce_shop_order_search_fields', array(
'_billing_address_index',
'_shipping_address_index',
'_billing_last_name',
'_billing_email',
)
)
);
$order_ids = array();
if ( is_numeric( $term ) ) {
$order_ids[] = absint( $term );
}
if ( ! empty( $search_fields ) ) {
$order_ids = array_unique( array_merge(
$order_ids,
$wpdb->get_col(
$wpdb->prepare( "SELECT DISTINCT p1.post_id FROM {$wpdb->postmeta} p1 WHERE p1.meta_value LIKE '%%%s%%'", $wpdb->esc_like( wc_clean( $term ) ) ) . " AND p1.meta_key IN ('" . implode( "','", array_map( 'esc_sql', $search_fields ) ) . "')"
),
$wpdb->get_col(
$wpdb->prepare( "
SELECT order_id
FROM {$wpdb->prefix}woocommerce_order_items as order_items
WHERE order_item_name LIKE '%%%s%%'
",
$wpdb->esc_like( wc_clean( $term ) )
$order_ids = array_unique(
array_merge(
$order_ids,
$wpdb->get_col(
$wpdb->prepare(
"SELECT DISTINCT p1.post_id FROM {$wpdb->postmeta} p1 WHERE p1.meta_value LIKE %s AND p1.meta_key IN ('" . implode( "','", array_map( 'esc_sql', $search_fields ) ) . "')", // @codingStandardsIgnoreLine
'%' . $wpdb->esc_like( wc_clean( $term ) ) . '%'
)
),
$wpdb->get_col(
$wpdb->prepare(
"SELECT order_id
FROM {$wpdb->prefix}woocommerce_order_items as order_items
WHERE order_item_name LIKE %s",
'%' . $wpdb->esc_like( wc_clean( $term ) ) . '%'
)
)
)
) );
);
}
return apply_filters( 'woocommerce_shop_order_search_results', $order_ids, $term, $search_fields );
@ -486,7 +520,7 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement
/**
* Gets information about whether permissions were generated yet.
*
* @param WC_Order|int $order
* @param WC_Order|int $order Order ID or order object.
* @return bool
*/
public function get_download_permissions_granted( $order ) {
@ -497,8 +531,8 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement
/**
* Stores information about whether permissions were generated yet.
*
* @param WC_Order|int $order
* @param bool $set
* @param WC_Order|int $order Order ID or order object.
* @param bool $set True or false.
*/
public function set_download_permissions_granted( $order, $set ) {
$order_id = WC_Order_Factory::get_order_id( $order );
@ -508,7 +542,7 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement
/**
* Gets information about whether sales were recorded.
*
* @param WC_Order|int $order
* @param WC_Order|int $order Order ID or order object.
* @return bool
*/
public function get_recorded_sales( $order ) {
@ -519,8 +553,8 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement
/**
* Stores information about whether sales were recorded.
*
* @param WC_Order|int $order
* @param bool $set
* @param WC_Order|int $order Order ID or order object.
* @param bool $set True or false.
*/
public function set_recorded_sales( $order, $set ) {
$order_id = WC_Order_Factory::get_order_id( $order );
@ -530,7 +564,7 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement
/**
* Gets information about whether coupon counts were updated.
*
* @param WC_Order|int $order
* @param WC_Order|int $order Order ID or order object.
* @return bool
*/
public function get_recorded_coupon_usage_counts( $order ) {
@ -541,8 +575,8 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement
/**
* Stores information about whether coupon counts were updated.
*
* @param WC_Order|int $order
* @param bool $set
* @param WC_Order|int $order Order ID or order object.
* @param bool $set True or false.
*/
public function set_recorded_coupon_usage_counts( $order, $set ) {
$order_id = WC_Order_Factory::get_order_id( $order );
@ -552,7 +586,7 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement
/**
* Gets information about whether stock was reduced.
*
* @param WC_Order|int $order
* @param WC_Order|int $order Order ID or order object.
* @return bool
*/
public function get_stock_reduced( $order ) {
@ -563,8 +597,8 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement
/**
* Stores information about whether stock was reduced.
*
* @param WC_Order|int $order
* @param bool $set
* @param WC_Order|int $order Order ID or order object.
* @param bool $set True or false.
*/
public function set_stock_reduced( $order, $set ) {
$order_id = WC_Order_Factory::get_order_id( $order );
@ -575,7 +609,7 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement
* Get the order type based on Order ID.
*
* @since 3.0.0
* @param int $order_id
* @param int $order_id Order ID.
* @return string
*/
public function get_order_type( $order_id ) {
@ -586,7 +620,7 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement
* Get valid WP_Query args from a WC_Order_Query's query variables.
*
* @since 3.1.0
* @param array $query_vars query vars from a WC_Order_Query
* @param array $query_vars query vars from a WC_Order_Query.
* @return array
*/
protected function get_wp_query_args( $query_vars ) {
@ -654,7 +688,7 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement
}
if ( isset( $query_vars['customer'] ) && '' !== $query_vars['customer'] && array() !== $query_vars['customer'] ) {
$values = is_array( $query_vars['customer'] ) ? $query_vars['customer'] : array( $query_vars['customer'] );
$values = is_array( $query_vars['customer'] ) ? $query_vars['customer'] : array( $query_vars['customer'] );
$customer_query = $this->get_orders_generate_customer_meta_query( $values );
if ( is_wp_error( $customer_query ) ) {
$wp_query_args['errors'][] = $customer_query;
@ -675,7 +709,7 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement
*
* @since 3.1.0
*
* @param array $query_vars query vars from a WC_Order_Query
* @param array $query_vars query vars from a WC_Order_Query.
*
* @return array|object
*/
@ -684,8 +718,8 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement
if ( ! empty( $args['errors'] ) ) {
$query = (object) array(
'posts' => array(),
'found_posts' => 0,
'posts' => array(),
'found_posts' => 0,
'max_num_pages' => 0,
);
} else {

View File

@ -585,15 +585,21 @@ class WC_Product_Data_Store_CPT extends WC_Data_Store_WP implements WC_Object_Da
/**
* For all stored terms in all taxonomies, save them to the DB.
*
* @param WC_Product
* @param bool Force update. Used during create.
* @param WC_Product $product Product object.
* @param bool $force Force update. Used during create.
* @since 3.0.0
*/
protected function update_terms( &$product, $force = false ) {
$changes = $product->get_changes();
if ( $force || array_key_exists( 'category_ids', $changes ) ) {
wp_set_post_terms( $product->get_id(), $product->get_category_ids( 'edit' ), 'product_cat', false );
$categories = $product->get_category_ids( 'edit' );
if ( empty( $categories ) && get_option( 'default_product_cat', 0 ) ) {
$categories = array( get_option( 'default_product_cat', 0 ) );
}
wp_set_post_terms( $product->get_id(), $categories, 'product_cat', false );
}
if ( $force || array_key_exists( 'tag_ids', $changes ) ) {
wp_set_post_terms( $product->get_id(), $product->get_tag_ids( 'edit' ), 'product_tag', false );

View File

@ -133,7 +133,7 @@ abstract class WC_Product_Importer implements WC_Importer_Interface {
public function get_params() {
return $this->params;
}
/**
* Get file pointer position from the last read.
*
@ -503,7 +503,7 @@ abstract class WC_Product_Importer implements WC_Importer_Interface {
* @param int $product_id Product ID.
* @return int
*/
protected function get_attachment_id_from_url( $url, $product_id ) {
public function get_attachment_id_from_url( $url, $product_id ) {
if ( empty( $url ) ) {
return 0;
}
@ -590,7 +590,7 @@ abstract class WC_Product_Importer implements WC_Importer_Interface {
* @param string $name Attribute name.
* @return int
*/
protected function get_attribute_taxonomy_id( $raw_name ) {
public function get_attribute_taxonomy_id( $raw_name ) {
global $wpdb, $wc_product_attributes;
// These are exported as labels, so convert the label to a name if possible first.

View File

@ -128,23 +128,23 @@ class WC_Legacy_API {
public function includes() {
// API server / response handlers.
include_once( dirname( __FILE__ ) . '/api/legacy/v3/class-wc-api-exception.php' );
include_once( dirname( __FILE__ ) . '/api/legacy/v3/class-wc-api-server.php' );
include_once( dirname( __FILE__ ) . '/api/legacy/v3/interface-wc-api-handler.php' );
include_once( dirname( __FILE__ ) . '/api/legacy/v3/class-wc-api-json-handler.php' );
include_once( dirname( __FILE__ ) . '/../api/legacy/v3/class-wc-api-exception.php' );
include_once( dirname( __FILE__ ) . '/../api/legacy/v3/class-wc-api-server.php' );
include_once( dirname( __FILE__ ) . '/../api/legacy/v3/interface-wc-api-handler.php' );
include_once( dirname( __FILE__ ) . '/../api/legacy/v3/class-wc-api-json-handler.php' );
// Authentication.
include_once( dirname( __FILE__ ) . '/api/legacy/v3/class-wc-api-authentication.php' );
include_once( dirname( __FILE__ ) . '/../api/legacy/v3/class-wc-api-authentication.php' );
$this->authentication = new WC_API_Authentication();
include_once( dirname( __FILE__ ) . '/api/legacy/v3/class-wc-api-resource.php' );
include_once( dirname( __FILE__ ) . '/api/legacy/v3/class-wc-api-coupons.php' );
include_once( dirname( __FILE__ ) . '/api/legacy/v3/class-wc-api-customers.php' );
include_once( dirname( __FILE__ ) . '/api/legacy/v3/class-wc-api-orders.php' );
include_once( dirname( __FILE__ ) . '/api/legacy/v3/class-wc-api-products.php' );
include_once( dirname( __FILE__ ) . '/api/legacy/v3/class-wc-api-reports.php' );
include_once( dirname( __FILE__ ) . '/api/legacy/v3/class-wc-api-taxes.php' );
include_once( dirname( __FILE__ ) . '/api/legacy/v3/class-wc-api-webhooks.php' );
include_once( dirname( __FILE__ ) . '/../api/legacy/v3/class-wc-api-resource.php' );
include_once( dirname( __FILE__ ) . '/../api/legacy/v3/class-wc-api-coupons.php' );
include_once( dirname( __FILE__ ) . '/../api/legacy/v3/class-wc-api-customers.php' );
include_once( dirname( __FILE__ ) . '/../api/legacy/v3/class-wc-api-orders.php' );
include_once( dirname( __FILE__ ) . '/../api/legacy/v3/class-wc-api-products.php' );
include_once( dirname( __FILE__ ) . '/../api/legacy/v3/class-wc-api-reports.php' );
include_once( dirname( __FILE__ ) . '/../api/legacy/v3/class-wc-api-taxes.php' );
include_once( dirname( __FILE__ ) . '/../api/legacy/v3/class-wc-api-webhooks.php' );
// Allow plugins to load other response handlers or resource classes.
do_action( 'woocommerce_api_loaded' );
@ -186,20 +186,20 @@ class WC_Legacy_API {
private function handle_v1_rest_api_request() {
// Include legacy required files for v1 REST API request.
include_once( dirname( __FILE__ ) . '/api/legacy/v1/class-wc-api-server.php' );
include_once( dirname( __FILE__ ) . '/api/legacy/v1/interface-wc-api-handler.php' );
include_once( dirname( __FILE__ ) . '/api/legacy/v1/class-wc-api-json-handler.php' );
include_once( dirname( __FILE__ ) . '/api/legacy/v1/class-wc-api-xml-handler.php' );
include_once( dirname( __FILE__ ) . '/../api/legacy/v1/class-wc-api-server.php' );
include_once( dirname( __FILE__ ) . '/../api/legacy/v1/interface-wc-api-handler.php' );
include_once( dirname( __FILE__ ) . '/../api/legacy/v1/class-wc-api-json-handler.php' );
include_once( dirname( __FILE__ ) . '/../api/legacy/v1/class-wc-api-xml-handler.php' );
include_once( dirname( __FILE__ ) . '/api/legacy/v1/class-wc-api-authentication.php' );
include_once( dirname( __FILE__ ) . '/../api/legacy/v1/class-wc-api-authentication.php' );
$this->authentication = new WC_API_Authentication();
include_once( dirname( __FILE__ ) . '/api/legacy/v1/class-wc-api-resource.php' );
include_once( dirname( __FILE__ ) . '/api/legacy/v1/class-wc-api-coupons.php' );
include_once( dirname( __FILE__ ) . '/api/legacy/v1/class-wc-api-customers.php' );
include_once( dirname( __FILE__ ) . '/api/legacy/v1/class-wc-api-orders.php' );
include_once( dirname( __FILE__ ) . '/api/legacy/v1/class-wc-api-products.php' );
include_once( dirname( __FILE__ ) . '/api/legacy/v1/class-wc-api-reports.php' );
include_once( dirname( __FILE__ ) . '/../api/legacy/v1/class-wc-api-resource.php' );
include_once( dirname( __FILE__ ) . '/../api/legacy/v1/class-wc-api-coupons.php' );
include_once( dirname( __FILE__ ) . '/../api/legacy/v1/class-wc-api-customers.php' );
include_once( dirname( __FILE__ ) . '/../api/legacy/v1/class-wc-api-orders.php' );
include_once( dirname( __FILE__ ) . '/../api/legacy/v1/class-wc-api-products.php' );
include_once( dirname( __FILE__ ) . '/../api/legacy/v1/class-wc-api-reports.php' );
// Allow plugins to load other response handlers or resource classes.
do_action( 'woocommerce_api_loaded' );
@ -232,21 +232,21 @@ class WC_Legacy_API {
* @deprecated 2.6.0
*/
private function handle_v2_rest_api_request() {
include_once( dirname( __FILE__ ) . '/api/legacy/v2/class-wc-api-exception.php' );
include_once( dirname( __FILE__ ) . '/api/legacy/v2/class-wc-api-server.php' );
include_once( dirname( __FILE__ ) . '/api/legacy/v2/interface-wc-api-handler.php' );
include_once( dirname( __FILE__ ) . '/api/legacy/v2/class-wc-api-json-handler.php' );
include_once( dirname( __FILE__ ) . '/../api/legacy/v2/class-wc-api-exception.php' );
include_once( dirname( __FILE__ ) . '/../api/legacy/v2/class-wc-api-server.php' );
include_once( dirname( __FILE__ ) . '/../api/legacy/v2/interface-wc-api-handler.php' );
include_once( dirname( __FILE__ ) . '/../api/legacy/v2/class-wc-api-json-handler.php' );
include_once( dirname( __FILE__ ) . '/api/legacy/v2/class-wc-api-authentication.php' );
include_once( dirname( __FILE__ ) . '/../api/legacy/v2/class-wc-api-authentication.php' );
$this->authentication = new WC_API_Authentication();
include_once( dirname( __FILE__ ) . '/api/legacy/v2/class-wc-api-resource.php' );
include_once( dirname( __FILE__ ) . '/api/legacy/v2/class-wc-api-coupons.php' );
include_once( dirname( __FILE__ ) . '/api/legacy/v2/class-wc-api-customers.php' );
include_once( dirname( __FILE__ ) . '/api/legacy/v2/class-wc-api-orders.php' );
include_once( dirname( __FILE__ ) . '/api/legacy/v2/class-wc-api-products.php' );
include_once( dirname( __FILE__ ) . '/api/legacy/v2/class-wc-api-reports.php' );
include_once( dirname( __FILE__ ) . '/api/legacy/v2/class-wc-api-webhooks.php' );
include_once( dirname( __FILE__ ) . '/../api/legacy/v2/class-wc-api-resource.php' );
include_once( dirname( __FILE__ ) . '/../api/legacy/v2/class-wc-api-coupons.php' );
include_once( dirname( __FILE__ ) . '/../api/legacy/v2/class-wc-api-customers.php' );
include_once( dirname( __FILE__ ) . '/../api/legacy/v2/class-wc-api-orders.php' );
include_once( dirname( __FILE__ ) . '/../api/legacy/v2/class-wc-api-products.php' );
include_once( dirname( __FILE__ ) . '/../api/legacy/v2/class-wc-api-reports.php' );
include_once( dirname( __FILE__ ) . '/../api/legacy/v2/class-wc-api-webhooks.php' );
// allow plugins to load other response handlers or resource classes.
do_action( 'woocommerce_api_loaded' );

View File

@ -211,7 +211,7 @@ class WC_Shortcode_Products {
*/
protected function set_skus_query_args( &$query_args ) {
if ( ! empty( $this->attributes['skus'] ) ) {
$skus = array_map( 'trim', explode( ',', $this->attributes['skus'] ) );
$skus = array_map( 'trim', explode( ',', $this->attributes['skus'] ) );
$query_args['meta_query'][] = array(
'key' => '_sku',
'value' => 1 === count( $skus ) ? $skus[0] : $skus,
@ -263,12 +263,10 @@ class WC_Shortcode_Products {
*/
protected function set_categories_query_args( &$query_args ) {
if ( ! empty( $this->attributes['category'] ) ) {
$ordering_args = WC()->query->get_catalog_ordering_args( $query_args['orderby'], $query_args['order'] );
$ordering_args = WC()->query->get_catalog_ordering_args( $query_args['orderby'], $query_args['order'] );
$query_args['orderby'] = $ordering_args['orderby'];
$query_args['order'] = $ordering_args['order'];
// @codingStandardsIgnoreStart
$query_args['meta_key'] = $ordering_args['meta_key'];
// @codingStandardsIgnoreEnd
$query_args['meta_key'] = $ordering_args['meta_key']; // @codingStandardsIgnoreLine
$query_args['tax_query'][] = array(
'taxonomy' => 'product_cat',
@ -296,9 +294,7 @@ class WC_Shortcode_Products {
* @param array $query_args Query args.
*/
protected function set_best_selling_products_query_args( &$query_args ) {
// @codingStandardsIgnoreStart
$query_args['meta_key'] = 'total_sales';
// @codingStandardsIgnoreEnd
$query_args['meta_key'] = 'total_sales'; // @codingStandardsIgnoreLine
$query_args['order'] = 'DESC';
$query_args['orderby'] = 'meta_value_num';
}
@ -310,7 +306,7 @@ class WC_Shortcode_Products {
* @param array $query_args Query args.
*/
protected function set_visibility_hidden_query_args( &$query_args ) {
$this->custom_visibility = true;
$this->custom_visibility = true;
$query_args['tax_query'][] = array(
'taxonomy' => 'product_visibility',
'terms' => array( 'exclude-from-catalog', 'exclude-from-search' ),
@ -327,7 +323,7 @@ class WC_Shortcode_Products {
* @param array $query_args Query args.
*/
protected function set_visibility_catalog_query_args( &$query_args ) {
$this->custom_visibility = true;
$this->custom_visibility = true;
$query_args['tax_query'][] = array(
'taxonomy' => 'product_visibility',
'terms' => 'exclude-from-search',
@ -351,7 +347,7 @@ class WC_Shortcode_Products {
* @param array $query_args Query args.
*/
protected function set_visibility_search_query_args( &$query_args ) {
$this->custom_visibility = true;
$this->custom_visibility = true;
$query_args['tax_query'][] = array(
'taxonomy' => 'product_visibility',
'terms' => 'exclude-from-catalog',
@ -515,9 +511,8 @@ class WC_Shortcode_Products {
woocommerce_product_loop_start();
foreach ( $products_ids as $product_id ) {
$post_object = get_post( $product_id );
$GLOBALS['post'] =& $post_object; // WPCS: override ok.
setup_postdata( $post_object );
$GLOBALS['post'] = get_post( $product_id ); // WPCS: override ok.
setup_postdata( $GLOBALS['post'] );
// Set custom product visibility when quering hidden products.
add_action( 'woocommerce_product_is_visible', array( $this, 'set_product_as_visible' ) );
@ -554,8 +549,8 @@ class WC_Shortcode_Products {
public static function order_by_rating_post_clauses( $args ) {
global $wpdb;
$args['where'] .= " AND $wpdb->commentmeta.meta_key = 'rating' ";
$args['join'] .= "LEFT JOIN $wpdb->comments ON($wpdb->posts.ID = $wpdb->comments.comment_post_ID) LEFT JOIN $wpdb->commentmeta ON($wpdb->comments.comment_ID = $wpdb->commentmeta.comment_id)";
$args['where'] .= " AND $wpdb->commentmeta.meta_key = 'rating' ";
$args['join'] .= "LEFT JOIN $wpdb->comments ON($wpdb->posts.ID = $wpdb->comments.comment_post_ID) LEFT JOIN $wpdb->commentmeta ON($wpdb->comments.comment_ID = $wpdb->commentmeta.comment_id)";
$args['orderby'] = "$wpdb->commentmeta.meta_value DESC";
$args['groupby'] = "$wpdb->posts.ID";

View File

@ -1,188 +0,0 @@
<?php
/**
* Class to validate and to work with IPv6 addresses
*
* @package Requests
* @subpackage Utilities
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Class to validate and to work with IPv6 addresses
*
* This was originally based on the PEAR class of the same name, but has been
* entirely rewritten.
*
* @package Requests
* @subpackage Utilities
*/
class Requests_IPv6 {
/**
* Uncompresses an IPv6 address
*
* RFC 4291 allows you to compress consecutive zero pieces in an address to
* '::'. This method expects a valid IPv6 address and expands the '::' to
* the required number of zero pieces.
*
* Example: FF01::101 -> FF01:0:0:0:0:0:0:101
* ::1 -> 0:0:0:0:0:0:0:1
*
* @author Alexander Merz <alexander.merz@web.de>
* @author elfrink at introweb dot nl
* @author Josh Peck <jmp at joshpeck dot org>
* @copyright 2003-2005 The PHP Group
* @license http://www.opensource.org/licenses/bsd-license.php
* @param string $ip An IPv6 address
* @return string The uncompressed IPv6 address
*/
public static function uncompress( $ip ) {
if ( substr_count( $ip, '::' ) !== 1 ) {
return $ip;
}
list($ip1, $ip2) = explode( '::', $ip );
$c1 = ( '' == $ip1 ) ? -1 : substr_count( $ip1, ':' );
$c2 = ( '' == $ip2 ) ? -1 : substr_count( $ip2, ':' );
if ( strpos( $ip2, '.' ) !== false ) {
$c2++;
}
// ::
if ( -1 === $c1 && -1 === $c2 ) {
$ip = '0:0:0:0:0:0:0:0';
} // ::xxx
elseif ( -1 === $c1 ) {
$fill = str_repeat( '0:', 7 - $c2 );
$ip = str_replace( '::', $fill, $ip );
} // xxx::
elseif ( -1 === $c2 ) {
$fill = str_repeat( ':0', 7 - $c1 );
$ip = str_replace( '::', $fill, $ip );
} // xxx::xxx
else {
$fill = ':' . str_repeat( '0:', 6 - $c2 - $c1 );
$ip = str_replace( '::', $fill, $ip );
}
return $ip;
}
/**
* Compresses an IPv6 address
*
* RFC 4291 allows you to compress consecutive zero pieces in an address to
* '::'. This method expects a valid IPv6 address and compresses consecutive
* zero pieces to '::'.
*
* Example: FF01:0:0:0:0:0:0:101 -> FF01::101
* 0:0:0:0:0:0:0:1 -> ::1
*
* @see uncompress()
* @param string $ip An IPv6 address
* @return string The compressed IPv6 address
*/
public static function compress( $ip ) {
// Prepare the IP to be compressed
$ip = self::uncompress( $ip );
$ip_parts = self::split_v6_v4( $ip );
// Replace all leading zeros
$ip_parts[0] = preg_replace( '/(^|:)0+([0-9])/', '\1\2', $ip_parts[0] );
// Find bunches of zeros
if ( preg_match_all( '/(?:^|:)(?:0(?::|$))+/', $ip_parts[0], $matches, PREG_OFFSET_CAPTURE ) ) {
$max = 0;
$pos = null;
foreach ( $matches[0] as $match ) {
if ( strlen( $match[0] ) > $max ) {
$max = strlen( $match[0] );
$pos = $match[1];
}
}
$ip_parts[0] = substr_replace( $ip_parts[0], '::', $pos, $max );
}
if ( '' !== $ip_parts[1] ) {
return implode( ':', $ip_parts );
} else {
return $ip_parts[0];
}
}
/**
* Splits an IPv6 address into the IPv6 and IPv4 representation parts
*
* RFC 4291 allows you to represent the last two parts of an IPv6 address
* using the standard IPv4 representation
*
* Example: 0:0:0:0:0:0:13.1.68.3
* 0:0:0:0:0:FFFF:129.144.52.38
*
* @param string $ip An IPv6 address
* @return string[] [0] contains the IPv6 represented part, and [1] the IPv4 represented part
*/
protected static function split_v6_v4( $ip ) {
if ( strpos( $ip, '.' ) !== false ) {
$pos = strrpos( $ip, ':' );
$ipv6_part = substr( $ip, 0, $pos );
$ipv4_part = substr( $ip, $pos + 1 );
return array( $ipv6_part, $ipv4_part );
} else {
return array( $ip, '' );
}
}
/**
* Checks an IPv6 address
*
* Checks if the given IP is a valid IPv6 address
*
* @param string $ip An IPv6 address
* @return bool true if $ip is a valid IPv6 address
*/
public static function check_ipv6( $ip ) {
$ip = self::uncompress( $ip );
list($ipv6, $ipv4) = self::split_v6_v4( $ip );
$ipv6 = explode( ':', $ipv6 );
$ipv4 = explode( '.', $ipv4 );
if ( count( $ipv6 ) === 8 && count( $ipv4 ) === 1 || count( $ipv6 ) === 6 && count( $ipv4 ) === 4 ) {
foreach ( $ipv6 as $ipv6_part ) {
// The section can't be empty
if ( '' === $ipv6_part ) {
return false;
}
// Nor can it be over four characters
if ( strlen( $ipv6_part ) > 4 ) {
return false;
}
// Remove leading zeros (this is safe because of the above)
$ipv6_part = ltrim( $ipv6_part, '0' );
if ( '' === $ipv6_part ) {
$ipv6_part = '0';
}
// Check the value is valid
$value = hexdec( $ipv6_part );
if ( dechex( $value ) !== strtolower( $ipv6_part ) || $value < 0 || $value > 0xFFFF ) {
return false;
}
}
if ( count( $ipv4 ) === 4 ) {
foreach ( $ipv4 as $ipv4_part ) {
$value = (int) $ipv4_part;
if ( (string) $value !== $ipv4_part || $value < 0 || $value > 0xFF ) {
return false;
}
}
}
return true;
} else {
return false;
}
}
}

View File

@ -1507,11 +1507,13 @@ function wc_get_rounding_precision() {
*
* @since 3.2.0
* @param float $value Number to add precision to.
* @return int
* @param bool $round Should we round after adding precision?
* @return int|float
*/
function wc_add_number_precision( $value ) {
function wc_add_number_precision( $value, $round = true ) {
$precision = pow( 10, wc_get_price_decimals() );
return intval( round( $value * $precision ) );
$value = $value * $precision;
return $round ? intval( round( $value ) ) : $value;
}
/**
@ -1531,15 +1533,16 @@ function wc_remove_number_precision( $value ) {
*
* @since 3.2.0
* @param array $value Number to add precision to.
* @param bool $round Should we round after adding precision?
* @return int
*/
function wc_add_number_precision_deep( $value ) {
function wc_add_number_precision_deep( $value, $round = true ) {
if ( is_array( $value ) ) {
foreach ( $value as $key => $subvalue ) {
$value[ $key ] = wc_add_number_precision_deep( $subvalue );
$value[ $key ] = wc_add_number_precision_deep( $subvalue, $round );
}
} else {
$value = wc_add_number_precision( $value );
$value = wc_add_number_precision( $value, $round );
}
return $value;
}

View File

@ -4,10 +4,10 @@
*
* Where functions come to die.
*
* @author WooThemes
* @category Core
* @package WooCommerce/Functions
* @version 2.1.0
* @author Automattic
* @category Core
* @package WooCommerce\Functions
* @version 3.3.0
*/
if ( ! defined( 'ABSPATH' ) ) {
@ -17,17 +17,20 @@ if ( ! defined( 'ABSPATH' ) ) {
/**
* Runs a deprecated action with notice only if used.
*
* @since 3.0.0
* @param string $action
* @param array $args
* @param string $deprecated_in
* @param string $replacement
* @since 3.0.0
* @param string $tag The name of the action hook.
* @param array $args Array of additional function arguments to be passed to do_action().
* @param string $version The version of WooCommerce that deprecated the hook.
* @param string $replacement The hook that should have been used.
* @param string $message A message regarding the change.
*/
function wc_do_deprecated_action( $action, $args, $deprecated_in, $replacement ) {
if ( has_action( $action ) ) {
wc_deprecated_function( 'Action: ' . $action, $deprecated_in, $replacement );
do_action_ref_array( $action, $args );
function wc_do_deprecated_action( $tag, $args, $version, $replacement = null, $message = null ) {
if ( ! has_action( $tag ) ) {
return;
}
wc_deprecated_hook( $tag, $version, $replacement, $message );
do_action_ref_array( $tag, $args );
}
/**
@ -51,6 +54,31 @@ function wc_deprecated_function( $function, $version, $replacement = null ) {
// @codingStandardsIgnoreEnd
}
/**
* Wrapper for deprecated hook so we can apply some extra logic.
*
* @since 3.3.0
* @param string $hook The hook that was used.
* @param string $version The version of WordPress that deprecated the hook.
* @param string $replacement The hook that should have been used.
* @param string $message A message regarding the change.
*/
function wc_deprecated_hook( $hook, $version, $replacement = null, $message = null ) {
// @codingStandardsIgnoreStart
if ( is_ajax() ) {
do_action( 'deprecated_hook_run', $hook, $replacement, $version, $message );
$message = empty( $message ) ? '' : ' ' . $message;
$log_string = "{$hook} is deprecated since version {$version}";
$log_string .= $replacement ? "! Use {$replacement} instead." : ' with no alternative available.';
error_log( $log_string . $message );
} else {
_deprecated_hook( $hook, $version, $replacement, $message );
}
// @codingStandardsIgnoreEnd
}
/**
* When catching an exception, this allows us to log it if unexpected.
*

View File

@ -587,6 +587,9 @@ function wc_create_refund( $args = array() ) {
do_action( 'woocommerce_order_refunded', $order->get_id(), $refund->get_id() );
} catch ( Exception $e ) {
if ( isset( $refund ) && is_a( $refund, 'WC_Order_Refund' ) ) {
wp_delete_post( $refund->get_id(), true );
}
return new WP_Error( 'error', $e->getMessage() );
}

View File

@ -4,30 +4,29 @@
*
* Functions related to pages and menus.
*
* @author WooThemes
* @author Automattic
* @category Core
* @package WooCommerce/Functions
* @package WooCommerce\Functions
* @version 2.6.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
exit; // Exit if accessed directly.
}
/**
* Replace a page title with the endpoint title.
* @param string $title
*
* @param string $title Post title.
* @return string
*/
function wc_page_endpoint_title( $title ) {
global $wp_query;
if ( ! is_null( $wp_query ) && ! is_admin() && is_main_query() && in_the_loop() && is_page() && is_wc_endpoint_url() ) {
$endpoint = WC()->query->get_current_endpoint();
if ( $endpoint_title = WC()->query->get_endpoint_title( $endpoint ) ) {
$title = $endpoint_title;
}
$endpoint = WC()->query->get_current_endpoint();
$endpoint_title = WC()->query->get_endpoint_title( $endpoint );
$title = $endpoint_title ? $endpoint_title : $title;
remove_filter( 'the_title', 'wc_page_endpoint_title' );
}
@ -40,12 +39,11 @@ add_filter( 'the_title', 'wc_page_endpoint_title' );
/**
* Retrieve page ids - used for myaccount, edit_address, shop, cart, checkout, pay, view_order, terms. returns -1 if no page is found.
*
* @param string $page
* @param string $page Page slug.
* @return int
*/
function wc_get_page_id( $page ) {
if ( 'pay' == $page || 'thanks' == $page ) {
if ( 'pay' === $page || 'thanks' === $page ) {
wc_deprecated_argument( __FUNCTION__, '2.1', 'The "pay" and "thanks" pages are no-longer used - an endpoint is added to the checkout instead. To get a valid link use the WC_Order::get_checkout_payment_url() or WC_Order::get_checkout_order_received_url() methods instead.' );
$page = 'checkout';
@ -64,7 +62,7 @@ function wc_get_page_id( $page ) {
/**
* Retrieve page permalink.
*
* @param string $page
* @param string $page page slug.
* @return string
*/
function wc_get_page_permalink( $page ) {
@ -78,9 +76,9 @@ function wc_get_page_permalink( $page ) {
*
* Gets the URL for an endpoint, which varies depending on permalink settings.
*
* @param string $endpoint
* @param string $value
* @param string $permalink
* @param string $endpoint Endpoint slug.
* @param string $value Query param value.
* @param string $permalink Permalink.
*
* @return string
*/
@ -89,13 +87,14 @@ function wc_get_endpoint_url( $endpoint, $value = '', $permalink = '' ) {
$permalink = get_permalink();
}
// Map endpoint to options
$endpoint = ! empty( WC()->query->query_vars[ $endpoint ] ) ? WC()->query->query_vars[ $endpoint ] : $endpoint;
$value = ( get_option( 'woocommerce_myaccount_edit_address_endpoint', 'edit-address' ) === $endpoint ) ? wc_edit_address_i18n( $value ) : $value;
// Map endpoint to options.
$query_vars = WC()->query->get_query_vars();
$endpoint = ! empty( $query_vars[ $endpoint ] ) ? $query_vars[ $endpoint ] : $endpoint;
$value = ( get_option( 'woocommerce_myaccount_edit_address_endpoint', 'edit-address' ) === $endpoint ) ? wc_edit_address_i18n( $value ) : $value;
if ( get_option( 'permalink_structure' ) ) {
if ( strstr( $permalink, '?' ) ) {
$query_string = '?' . parse_url( $permalink, PHP_URL_QUERY );
$query_string = '?' . wp_parse_url( $permalink, PHP_URL_QUERY );
$permalink = current( explode( '?', $permalink ) );
} else {
$query_string = '';
@ -123,8 +122,8 @@ function wc_nav_menu_items( $items ) {
if ( empty( $item->url ) ) {
continue;
}
$path = parse_url( $item->url, PHP_URL_PATH );
$query = parse_url( $item->url, PHP_URL_QUERY );
$path = wp_parse_url( $item->url, PHP_URL_PATH );
$query = wp_parse_url( $item->url, PHP_URL_QUERY );
if ( strstr( $path, $customer_logout ) || strstr( $query, $customer_logout ) ) {
unset( $items[ $key ] );
@ -141,43 +140,41 @@ add_filter( 'wp_nav_menu_objects', 'wc_nav_menu_items', 10 );
/**
* Fix active class in nav for shop page.
*
* @param array $menu_items
* @param array $menu_items Menu items.
* @return array
*/
function wc_nav_menu_item_classes( $menu_items ) {
if ( ! is_woocommerce() ) {
return $menu_items;
}
$shop_page = (int) wc_get_page_id( 'shop' );
$shop_page = (int) wc_get_page_id( 'shop' );
$page_for_posts = (int) get_option( 'page_for_posts' );
if ( ! empty( $menu_items ) && is_array( $menu_items ) ) {
foreach ( $menu_items as $key => $menu_item ) {
$classes = (array) $menu_item->classes;
$menu_id = (int) $menu_item->object_id;
// Unset active class for blog page
if ( $page_for_posts == $menu_item->object_id ) {
// Unset active class for blog page.
if ( $page_for_posts === $menu_id ) {
$menu_items[ $key ]->current = false;
if ( in_array( 'current_page_parent', $classes ) ) {
unset( $classes[ array_search( 'current_page_parent', $classes ) ] );
if ( in_array( 'current_page_parent', $classes, true ) ) {
unset( $classes[ array_search( 'current_page_parent', $classes, true ) ] );
}
if ( in_array( 'current-menu-item', $classes ) ) {
unset( $classes[ array_search( 'current-menu-item', $classes ) ] );
if ( in_array( 'current-menu-item', $classes, true ) ) {
unset( $classes[ array_search( 'current-menu-item', $classes, true ) ] );
}
// Set active state if this is the shop page link
} elseif ( is_shop() && $shop_page == $menu_item->object_id && 'page' === $menu_item->object ) {
} elseif ( is_shop() && $shop_page === $menu_id && 'page' === $menu_item->object ) {
// Set active state if this is the shop page link.
$menu_items[ $key ]->current = true;
$classes[] = 'current-menu-item';
$classes[] = 'current_page_item';
// Set parent state if this is a product page
} elseif ( is_singular( 'product' ) && $shop_page == $menu_item->object_id ) {
} elseif ( is_singular( 'product' ) && $shop_page === $menu_id ) {
// Set parent state if this is a product page.
$classes[] = 'current_page_parent';
}
@ -193,10 +190,9 @@ add_filter( 'wp_nav_menu_objects', 'wc_nav_menu_item_classes', 2 );
/**
* Fix active class in wp_list_pages for shop page.
*
* https://github.com/woocommerce/woocommerce/issues/177.
* See details in https://github.com/woocommerce/woocommerce/issues/177.
*
* @author Jessor, Peter Sterling
* @param string $pages
* @param string $pages Pages list.
* @return string
*/
function wc_list_pages( $pages ) {

View File

@ -4,9 +4,9 @@
*
* Functions for the templating system.
*
* @author WooThemes
* @author Automattic
* @category Core
* @package WooCommerce/Functions
* @package WooCommerce\Functions
* @version 2.5.0
*/
@ -20,7 +20,7 @@ if ( ! defined( 'ABSPATH' ) ) {
function wc_template_redirect() {
global $wp_query, $wp;
if ( ! empty( $_GET['page_id'] ) && '' === get_option( 'permalink_structure' ) && wc_get_page_id( 'shop' ) == $_GET['page_id'] ) {
if ( ! empty( $_GET['page_id'] ) && '' === get_option( 'permalink_structure' ) && wc_get_page_id( 'shop' ) === absint( $_GET['page_id'] ) ) { // WPCS: input var ok, CSRF ok.
// When default permalinks are enabled, redirect shop page to post type archive url.
wp_safe_redirect( get_post_type_archive_link( 'product' ) );
@ -33,11 +33,7 @@ function wc_template_redirect() {
wp_redirect( wc_get_page_permalink( 'cart' ) );
exit;
} elseif (
isset( $wp->query_vars['customer-logout'] ) &&
! empty( $_REQUEST['_wpnonce'] ) &&
wp_verify_nonce( sanitize_key( $_REQUEST['_wpnonce'] ), 'customer-logout' )
) {
} elseif ( isset( $wp->query_vars['customer-logout'] ) && ! empty( $_REQUEST['_wpnonce'] ) && wp_verify_nonce( sanitize_key( $_REQUEST['_wpnonce'] ), 'customer-logout' ) ) { // WPCS: input var ok, CSRF ok.
// Logout.
wp_redirect( str_replace( '&amp;', '&', wp_logout_url( wc_get_page_permalink( 'myaccount' ) ) ) );
@ -97,8 +93,8 @@ add_action( 'template_redirect', 'wc_send_frame_options_header' );
* @since 2.5.3
*/
function wc_prevent_endpoint_indexing() {
if ( is_wc_endpoint_url() || isset( $_GET['download_file'] ) ) {
@header( 'X-Robots-Tag: noindex' );
if ( is_wc_endpoint_url() || isset( $_GET['download_file'] ) ) { // WPCS: input var ok, CSRF ok.
@header( 'X-Robots-Tag: noindex' ); // @codingStandardsIgnoreLine
}
}
add_action( 'template_redirect', 'wc_prevent_endpoint_indexing' );
@ -142,7 +138,7 @@ function wc_setup_product_data( $post ) {
$the_post = $post;
}
if ( empty( $the_post->post_type ) || ! in_array( $the_post->post_type, array( 'product', 'product_variation' ) ) ) {
if ( empty( $the_post->post_type ) || ! in_array( $the_post->post_type, array( 'product', 'product_variation' ), true ) ) {
return;
}
@ -156,8 +152,6 @@ if ( ! function_exists( 'woocommerce_reset_loop' ) ) {
/**
* Reset the loop's index and columns when we're done outputting a product loop.
*
* @subpackage Loop
*/
function woocommerce_reset_loop() {
$GLOBALS['woocommerce_loop'] = array(
@ -189,6 +183,7 @@ function wc_products_rss_feed() {
if ( $term ) {
$feed = add_query_arg( 'product_cat', $term->slug, get_post_type_archive_feed_link( 'product' ) );
/* translators: %s: category name */
echo '<link rel="alternate" type="application/rss+xml" title="' . esc_attr( sprintf( __( 'New products added to %s', 'woocommerce' ), $term->name ) ) . '" href="' . esc_url( $feed ) . '" />';
}
} elseif ( is_tax( 'product_tag' ) ) {
@ -197,7 +192,8 @@ 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( esc_attr__( 'New products tagged %s', 'woocommerce' ), urlencode( $term->name ) ) . '" href="' . esc_url( $feed ) . '" />';
/* translators: %s: tag name */
echo '<link rel="alternate" type="application/rss+xml" title="' . sprintf( esc_attr__( 'New products tagged %s', 'woocommerce' ), rawurlencode( $term->name ) ) . '" href="' . esc_url( $feed ) . '" />';
}
}
}
@ -259,7 +255,7 @@ function wc_body_class( $classes ) {
$classes[] = 'woocommerce-demo-store';
}
foreach ( WC()->query->query_vars as $key => $value ) {
foreach ( WC()->query->get_query_vars() as $key => $value ) {
if ( is_wc_endpoint_url( $key ) ) {
$classes[] = 'woocommerce-' . sanitize_html_class( $key );
}
@ -289,7 +285,7 @@ function wc_product_cat_class( $class = '', $category = null ) {
function wc_get_loop_class() {
global $woocommerce_loop;
$woocommerce_loop['loop'] = ! empty( $woocommerce_loop['loop'] ) ? $woocommerce_loop['loop'] + 1 : 1;
$woocommerce_loop['loop'] = ! empty( $woocommerce_loop['loop'] ) ? $woocommerce_loop['loop'] + 1 : 1;
$woocommerce_loop['columns'] = max( 1, ! empty( $woocommerce_loop['columns'] ) ? $woocommerce_loop['columns'] : apply_filters( 'loop_shop_columns', 4 ) );
if ( 0 === ( $woocommerce_loop['loop'] - 1 ) % $woocommerce_loop['columns'] || 1 === $woocommerce_loop['columns'] ) {
@ -331,7 +327,7 @@ function wc_get_product_cat_class( $class = '', $category = null ) {
* @return array
*/
function wc_product_post_class( $classes, $class = '', $post_id = '' ) {
if ( ! $post_id || ! in_array( get_post_type( $post_id ), array( 'product', 'product_variation' ) ) ) {
if ( ! $post_id || ! in_array( get_post_type( $post_id ), array( 'product', 'product_variation' ), true ) ) {
return $classes;
}
@ -379,7 +375,8 @@ function wc_product_post_class( $classes, $class = '', $post_id = '' ) {
}
}
if ( false !== ( $key = array_search( 'hentry', $classes ) ) ) {
$key = array_search( 'hentry', $classes, true );
if ( false !== $key ) {
unset( $classes[ $key ] );
}
@ -398,7 +395,7 @@ function wc_product_post_class( $classes, $class = '', $post_id = '' ) {
*/
function wc_query_string_form_fields( $values = null, $exclude = array(), $current_key = '', $return = false ) {
if ( is_null( $values ) ) {
$values = $_GET;
$values = $_GET; // WPCS: input var ok, CSRF ok.
}
$html = '';
@ -440,13 +437,13 @@ if ( ! function_exists( 'woocommerce_content' ) ) {
if ( is_singular( 'product' ) ) {
while ( have_posts() ) : the_post();
while ( have_posts() ) :
the_post();
wc_get_template_part( 'content', 'single-product' );
endwhile;
} else { ?>
} else {
?>
<?php if ( apply_filters( 'woocommerce_show_page_title', true ) ) : ?>
@ -464,7 +461,8 @@ if ( ! function_exists( 'woocommerce_content' ) ) {
<?php woocommerce_product_subcategories(); ?>
<?php while ( have_posts() ) : the_post(); ?>
<?php while ( have_posts() ) : ?>
<?php the_post(); ?>
<?php wc_get_template_part( 'content', 'product' ); ?>
@ -474,12 +472,17 @@ if ( ! function_exists( 'woocommerce_content' ) ) {
<?php do_action( 'woocommerce_after_shop_loop' ); ?>
<?php elseif ( ! woocommerce_product_subcategories( array( 'before' => woocommerce_product_loop_start( false ), 'after' => woocommerce_product_loop_end( false ) ) ) ) : ?>
<?php
elseif ( ! woocommerce_product_subcategories( array(
'before' => woocommerce_product_loop_start( false ),
'after' => woocommerce_product_loop_end( false ),
) ) ) :
?>
<?php do_action( 'woocommerce_no_products_found' ); ?>
<?php endif;
<?php
endif;
}
}
}
@ -552,9 +555,11 @@ if ( ! function_exists( 'woocommerce_page_title' ) ) {
function woocommerce_page_title( $echo = true ) {
if ( is_search() ) {
/* translators: %s: search query */
$page_title = sprintf( __( 'Search results: &ldquo;%s&rdquo;', 'woocommerce' ), get_search_query() );
if ( get_query_var( 'paged' ) ) {
/* translators: %s: page number */
$page_title .= sprintf( __( '&nbsp;&ndash; Page %s', 'woocommerce' ), get_query_var( 'paged' ) );
}
} elseif ( is_tax() ) {
@ -679,8 +684,6 @@ if ( ! function_exists( 'woocommerce_taxonomy_archive_description' ) ) {
/**
* Show an archive description on taxonomy archives.
*
* @subpackage Archives
*/
function woocommerce_taxonomy_archive_description() {
if ( is_product_taxonomy() && 0 === absint( get_query_var( 'paged' ) ) ) {
@ -720,8 +723,6 @@ if ( ! function_exists( 'woocommerce_template_loop_add_to_cart' ) ) {
/**
* Get the add to cart template for the loop.
*
* @subpackage Loop
*
* @param array $args Arguments.
*/
function woocommerce_template_loop_add_to_cart( $args = array() ) {
@ -731,10 +732,10 @@ if ( ! function_exists( 'woocommerce_template_loop_add_to_cart' ) ) {
$defaults = array(
'quantity' => 1,
'class' => implode( ' ', array_filter( array(
'button',
'product_type_' . $product->get_type(),
$product->is_purchasable() && $product->is_in_stock() ? 'add_to_cart_button' : '',
$product->supports( 'ajax_add_to_cart' ) ? 'ajax_add_to_cart' : '',
'button',
'product_type_' . $product->get_type(),
$product->is_purchasable() && $product->is_in_stock() ? 'add_to_cart_button' : '',
$product->supports( 'ajax_add_to_cart' ) ? 'ajax_add_to_cart' : '',
) ) ),
);
@ -748,8 +749,6 @@ if ( ! function_exists( 'woocommerce_template_loop_product_thumbnail' ) ) {
/**
* Get the product thumbnail for the loop.
*
* @subpackage Loop
*/
function woocommerce_template_loop_product_thumbnail() {
echo woocommerce_get_product_thumbnail(); // WPCS: XSS ok.
@ -759,8 +758,6 @@ if ( ! function_exists( 'woocommerce_template_loop_price' ) ) {
/**
* Get the product price for the loop.
*
* @subpackage Loop
*/
function woocommerce_template_loop_price() {
wc_get_template( 'loop/price.php' );
@ -770,8 +767,6 @@ if ( ! function_exists( 'woocommerce_template_loop_rating' ) ) {
/**
* Display the average rating in the loop.
*
* @subpackage Loop
*/
function woocommerce_template_loop_rating() {
wc_get_template( 'loop/rating.php' );
@ -781,8 +776,6 @@ if ( ! function_exists( 'woocommerce_show_product_loop_sale_flash' ) ) {
/**
* Get the sale flash for the loop.
*
* @subpackage Loop
*/
function woocommerce_show_product_loop_sale_flash() {
wc_get_template( 'loop/sale-flash.php' );
@ -794,7 +787,6 @@ if ( ! function_exists( 'woocommerce_get_product_thumbnail' ) ) {
/**
* Get the product thumbnail, or the placeholder if not set.
*
* @subpackage Loop
* @param string $size (default: 'woocommerce_thumbnail').
* @param int $deprecated1 Deprecated since WooCommerce 2.0 (default: 0).
* @param int $deprecated2 Deprecated since WooCommerce 2.0 (default: 0).
@ -813,8 +805,6 @@ if ( ! function_exists( 'woocommerce_result_count' ) ) {
/**
* Output the result count text (Showing x - x of x results).
*
* @subpackage Loop
*/
function woocommerce_result_count() {
wc_get_template( 'loop/result-count.php' );
@ -825,8 +815,6 @@ if ( ! function_exists( 'woocommerce_catalog_ordering' ) ) {
/**
* Output the product sorting options.
*
* @subpackage Loop
*/
function woocommerce_catalog_ordering() {
global $wp_query;
@ -835,7 +823,7 @@ if ( ! function_exists( 'woocommerce_catalog_ordering' ) ) {
return;
}
$orderby = isset( $_GET['orderby'] ) ? wc_clean( wp_unslash( $_GET['orderby'] ) ) : apply_filters( 'woocommerce_default_catalog_orderby', get_option( 'woocommerce_default_catalog_orderby' ) );
$orderby = isset( $_GET['orderby'] ) ? wc_clean( wp_unslash( $_GET['orderby'] ) ) : apply_filters( 'woocommerce_default_catalog_orderby', get_option( 'woocommerce_default_catalog_orderby' ) ); // WPCS: input var ok, CSRF ok.
$show_default_orderby = 'menu_order' === apply_filters( 'woocommerce_default_catalog_orderby', get_option( 'woocommerce_default_catalog_orderby' ) );
$catalog_orderby_options = apply_filters( 'woocommerce_catalog_orderby', array(
'menu_order' => __( 'Default sorting', 'woocommerce' ),
@ -847,7 +835,9 @@ if ( ! function_exists( 'woocommerce_catalog_ordering' ) ) {
) );
if ( $wp_query->is_search() ) {
$catalog_orderby_options = array_merge( array( 'relevance' => __( 'Relevance', 'woocommerce' ) ), $catalog_orderby_options );
$catalog_orderby_options = array_merge( array(
'relevance' => __( 'Relevance', 'woocommerce' ),
), $catalog_orderby_options );
unset( $catalog_orderby_options['menu_order'] );
if ( 'menu_order' === $orderby ) {
$orderby = 'relevance';
@ -862,7 +852,11 @@ if ( ! function_exists( 'woocommerce_catalog_ordering' ) ) {
unset( $catalog_orderby_options['rating'] );
}
wc_get_template( 'loop/orderby.php', array( 'catalog_orderby_options' => $catalog_orderby_options, 'orderby' => $orderby, 'show_default_orderby' => $show_default_orderby ) );
wc_get_template( 'loop/orderby.php', array(
'catalog_orderby_options' => $catalog_orderby_options,
'orderby' => $orderby,
'show_default_orderby' => $show_default_orderby,
) );
}
}
@ -870,8 +864,6 @@ if ( ! function_exists( 'woocommerce_pagination' ) ) {
/**
* Output the pagination.
*
* @subpackage Loop
*/
function woocommerce_pagination() {
wc_get_template( 'loop/pagination.php' );
@ -886,8 +878,6 @@ if ( ! function_exists( 'woocommerce_show_product_images' ) ) {
/**
* Output the product image before the single product summary.
*
* @subpackage Product
*/
function woocommerce_show_product_images() {
wc_get_template( 'single-product/product-image.php' );
@ -897,8 +887,6 @@ if ( ! function_exists( 'woocommerce_show_product_thumbnails' ) ) {
/**
* Output the product thumbnails.
*
* @subpackage Product
*/
function woocommerce_show_product_thumbnails() {
wc_get_template( 'single-product/product-thumbnails.php' );
@ -909,8 +897,6 @@ if ( ! function_exists( 'woocommerce_output_product_data_tabs' ) ) {
/**
* Output the product tabs.
*
* @subpackage Product/Tabs
*/
function woocommerce_output_product_data_tabs() {
wc_get_template( 'single-product/tabs/tabs.php' );
@ -920,8 +906,6 @@ if ( ! function_exists( 'woocommerce_template_single_title' ) ) {
/**
* Output the product title.
*
* @subpackage Product
*/
function woocommerce_template_single_title() {
wc_get_template( 'single-product/title.php' );
@ -931,8 +915,6 @@ if ( ! function_exists( 'woocommerce_template_single_rating' ) ) {
/**
* Output the product rating.
*
* @subpackage Product
*/
function woocommerce_template_single_rating() {
if ( post_type_supports( 'product', 'comments' ) ) {
@ -944,8 +926,6 @@ if ( ! function_exists( 'woocommerce_template_single_price' ) ) {
/**
* Output the product price.
*
* @subpackage Product
*/
function woocommerce_template_single_price() {
wc_get_template( 'single-product/price.php' );
@ -955,8 +935,6 @@ if ( ! function_exists( 'woocommerce_template_single_excerpt' ) ) {
/**
* Output the product short description (excerpt).
*
* @subpackage Product
*/
function woocommerce_template_single_excerpt() {
wc_get_template( 'single-product/short-description.php' );
@ -966,8 +944,6 @@ if ( ! function_exists( 'woocommerce_template_single_meta' ) ) {
/**
* Output the product meta.
*
* @subpackage Product
*/
function woocommerce_template_single_meta() {
wc_get_template( 'single-product/meta.php' );
@ -977,8 +953,6 @@ if ( ! function_exists( 'woocommerce_template_single_sharing' ) ) {
/**
* Output the product sharing.
*
* @subpackage Product
*/
function woocommerce_template_single_sharing() {
wc_get_template( 'single-product/share.php' );
@ -988,8 +962,6 @@ if ( ! function_exists( 'woocommerce_show_product_sale_flash' ) ) {
/**
* Output the product sale flash.
*
* @subpackage Product
*/
function woocommerce_show_product_sale_flash() {
wc_get_template( 'single-product/sale-flash.php' );
@ -1000,8 +972,6 @@ if ( ! function_exists( 'woocommerce_template_single_add_to_cart' ) ) {
/**
* Trigger the single product add to cart action.
*
* @subpackage Product
*/
function woocommerce_template_single_add_to_cart() {
global $product;
@ -1012,8 +982,6 @@ if ( ! function_exists( 'woocommerce_simple_add_to_cart' ) ) {
/**
* Output the simple product add to cart area.
*
* @subpackage Product
*/
function woocommerce_simple_add_to_cart() {
wc_get_template( 'single-product/add-to-cart/simple.php' );
@ -1023,8 +991,6 @@ if ( ! function_exists( 'woocommerce_grouped_add_to_cart' ) ) {
/**
* Output the grouped product add to cart area.
*
* @subpackage Product
*/
function woocommerce_grouped_add_to_cart() {
global $product;
@ -1044,8 +1010,6 @@ if ( ! function_exists( 'woocommerce_variable_add_to_cart' ) ) {
/**
* Output the variable product add to cart area.
*
* @subpackage Product
*/
function woocommerce_variable_add_to_cart() {
global $product;
@ -1068,8 +1032,6 @@ if ( ! function_exists( 'woocommerce_external_add_to_cart' ) ) {
/**
* Output the external product add to cart area.
*
* @subpackage Product
*/
function woocommerce_external_add_to_cart() {
global $product;
@ -1139,8 +1101,6 @@ if ( ! function_exists( 'woocommerce_product_description_tab' ) ) {
/**
* Output the description tab content.
*
* @subpackage Product/Tabs
*/
function woocommerce_product_description_tab() {
wc_get_template( 'single-product/tabs/description.php' );
@ -1150,8 +1110,6 @@ if ( ! function_exists( 'woocommerce_product_additional_information_tab' ) ) {
/**
* Output the attributes tab content.
*
* @subpackage Product/Tabs
*/
function woocommerce_product_additional_information_tab() {
wc_get_template( 'single-product/tabs/additional-information.php' );
@ -1162,8 +1120,7 @@ if ( ! function_exists( 'woocommerce_product_reviews_tab' ) ) {
/**
* Output the reviews tab content.
*
* @deprecated 2.4.0 Unused
* @subpackage Product/Tabs
* @deprecated 2.4.0 Unused.
*/
function woocommerce_product_reviews_tab() {
wc_deprecated_function( 'woocommerce_product_reviews_tab', '2.4' );
@ -1202,6 +1159,7 @@ if ( ! function_exists( 'woocommerce_default_product_tabs' ) ) {
// Reviews tab - shows comments.
if ( comments_open() ) {
$tabs['reviews'] = array(
/* translators: %s: reviews count */
'title' => sprintf( __( 'Reviews (%d)', 'woocommerce' ), $product->get_review_count() ),
'priority' => 30,
'callback' => 'comments_template',
@ -1224,7 +1182,7 @@ if ( ! function_exists( 'woocommerce_sort_product_tabs' ) ) {
// Make sure the $tabs parameter is an array.
if ( ! is_array( $tabs ) ) {
trigger_error( 'Function woocommerce_sort_product_tabs() expects an array as the first parameter. Defaulting to empty array.' );
trigger_error( 'Function woocommerce_sort_product_tabs() expects an array as the first parameter. Defaulting to empty array.' ); // @codingStandardsIgnoreLine
$tabs = array();
}
@ -1256,14 +1214,17 @@ if ( ! function_exists( 'woocommerce_comments' ) ) {
/**
* Output the Review comments template.
*
* @subpackage Product
* @param WP_Comment $comment Comment object.
* @param array $args Arguments.
* @param int $depth Depth.
*/
function woocommerce_comments( $comment, $args, $depth ) {
$GLOBALS['comment'] = $comment; // WPCS: override ok.
wc_get_template( 'single-product/review.php', array( 'comment' => $comment, 'args' => $args, 'depth' => $depth ) );
wc_get_template( 'single-product/review.php', array(
'comment' => $comment,
'args' => $args,
'depth' => $depth,
) );
}
}
@ -1319,15 +1280,13 @@ if ( ! function_exists( 'woocommerce_output_related_products' ) ) {
/**
* Output the related products.
*
* @subpackage Product
*/
function woocommerce_output_related_products() {
$args = array(
'posts_per_page' => 4,
'columns' => 4,
'orderby' => 'rand',
'posts_per_page' => 4,
'columns' => 4,
'orderby' => 'rand',
);
woocommerce_related_products( apply_filters( 'woocommerce_output_related_products_args', $args ) );
@ -1420,8 +1379,6 @@ if ( ! function_exists( 'woocommerce_shipping_calculator' ) ) {
/**
* Output the cart shipping calculator.
*
* @subpackage Cart
*/
function woocommerce_shipping_calculator() {
wc_get_template( 'cart/shipping-calculator.php' );
@ -1432,8 +1389,6 @@ if ( ! function_exists( 'woocommerce_cart_totals' ) ) {
/**
* Output the cart totals.
*
* @subpackage Cart
*/
function woocommerce_cart_totals() {
if ( is_checkout() ) {
@ -1486,8 +1441,6 @@ if ( ! function_exists( 'woocommerce_button_proceed_to_checkout' ) ) {
/**
* Output the proceed to checkout button.
*
* @subpackage Cart
*/
function woocommerce_button_proceed_to_checkout() {
wc_get_template( 'cart/proceed-to-checkout-button.php' );
@ -1498,8 +1451,6 @@ if ( ! function_exists( 'woocommerce_widget_shopping_cart_button_view_cart' ) )
/**
* Output the view cart button.
*
* @subpackage Cart
*/
function woocommerce_widget_shopping_cart_button_view_cart() {
echo '<a href="' . esc_url( wc_get_cart_url() ) . '" class="button wc-forward">' . esc_html__( 'View cart', 'woocommerce' ) . '</a>';
@ -1510,8 +1461,6 @@ if ( ! function_exists( 'woocommerce_widget_shopping_cart_proceed_to_checkout' )
/**
* Output the proceed to checkout button.
*
* @subpackage Cart
*/
function woocommerce_widget_shopping_cart_proceed_to_checkout() {
echo '<a href="' . esc_url( wc_get_checkout_url() ) . '" class="button checkout wc-forward">' . esc_html__( 'Checkout', 'woocommerce' ) . '</a>';
@ -1546,7 +1495,6 @@ if ( ! function_exists( 'woocommerce_login_form' ) ) {
/**
* Output the WooCommerce Login Form.
*
* @subpackage Forms
* @param array $args Arguments.
*/
function woocommerce_login_form( $args = array() ) {
@ -1567,11 +1515,11 @@ if ( ! function_exists( 'woocommerce_checkout_login_form' ) ) {
/**
* Output the WooCommerce Checkout Login Form.
*
* @subpackage Checkout
*/
function woocommerce_checkout_login_form() {
wc_get_template( 'checkout/form-login.php', array( 'checkout' => WC()->checkout() ) );
wc_get_template( 'checkout/form-login.php', array(
'checkout' => WC()->checkout(),
) );
}
}
@ -1616,12 +1564,12 @@ if ( ! function_exists( 'woocommerce_order_review' ) ) {
/**
* Output the Order review table for the checkout.
*
* @subpackage Checkout
*
* @param bool $deprecated Deprecated param.
*/
function woocommerce_order_review( $deprecated = false ) {
wc_get_template( 'checkout/review-order.php', array( 'checkout' => WC()->checkout() ) );
wc_get_template( 'checkout/review-order.php', array(
'checkout' => WC()->checkout(),
) );
}
}
@ -1629,8 +1577,6 @@ if ( ! function_exists( 'woocommerce_checkout_payment' ) ) {
/**
* Output the Payment Methods on the checkout.
*
* @subpackage Checkout
*/
function woocommerce_checkout_payment() {
if ( WC()->cart->needs_payment() ) {
@ -1652,11 +1598,11 @@ if ( ! function_exists( 'woocommerce_checkout_coupon_form' ) ) {
/**
* Output the Coupon form for the checkout.
*
* @subpackage Checkout
*/
function woocommerce_checkout_coupon_form() {
wc_get_template( 'checkout/form-coupon.php', array( 'checkout' => WC()->checkout() ) );
wc_get_template( 'checkout/form-coupon.php', array(
'checkout' => WC()->checkout(),
) );
}
}
@ -1665,7 +1611,6 @@ if ( ! function_exists( 'woocommerce_products_will_display' ) ) {
/**
* Check if we will be showing products or not (and not sub-categories only).
*
* @subpackage Loop
* @return bool
*/
function woocommerce_products_will_display() {
@ -1687,19 +1632,18 @@ if ( ! function_exists( 'woocommerce_products_will_display' ) ) {
if ( is_product_category() ) {
switch ( get_woocommerce_term_meta( $term->term_id, 'display_type', true ) ) {
case 'subcategories' :
case 'subcategories':
// Nothing - we want to continue to see if there are products/subcats.
break;
case 'products' :
case 'both' :
break;
case 'products':
case 'both':
return true;
break;
default :
default:
// Default - no setting.
if ( get_option( 'woocommerce_category_archive_display' ) != 'subcategories' ) {
if ( get_option( 'woocommerce_category_archive_display' ) !== 'subcategories' ) {
return true;
}
break;
break;
}
}
@ -1708,10 +1652,11 @@ if ( ! function_exists( 'woocommerce_products_will_display' ) ) {
return true;
}
$transient_name = 'wc_products_will_display_' . $term->term_id . '_' . WC_Cache_Helper::get_transient_version( 'product_query' );
$transient_name = 'wc_products_will_display_' . $term->term_id . '_' . WC_Cache_Helper::get_transient_version( 'product_query' );
$products_will_display = get_transient( $transient_name );
if ( false === ( $products_will_display = get_transient( $transient_name ) ) ) {
$has_children = $wpdb->get_col( $wpdb->prepare( "SELECT term_id FROM {$wpdb->term_taxonomy} WHERE parent = %d AND taxonomy = %s", $term->term_id, $term->taxonomy ) ); // WPCS: cache ok.
if ( false === $products_will_display ) {
$has_children = $wpdb->get_col( $wpdb->prepare( "SELECT term_id FROM {$wpdb->term_taxonomy} WHERE parent = %d AND taxonomy = %s", $term->term_id, $term->taxonomy ) ); // WPCS: db call ok, cache ok.
if ( $has_children ) {
// Check terms have products inside - parents first. If products are found inside, subcats will be shown instead of products so we can return false.
@ -1744,7 +1689,6 @@ if ( ! function_exists( 'woocommerce_product_subcategories' ) ) {
/**
* Display product sub categories as thumbnails.
*
* @subpackage Loop
* @param array $args Arguments.
* @return null|boolean
*/
@ -1777,21 +1721,20 @@ if ( ! function_exists( 'woocommerce_product_subcategories' ) ) {
}
// Find the category + category parent, if applicable.
$term = get_queried_object();
$parent_id = empty( $term->term_id ) ? 0 : $term->term_id;
$term = get_queried_object();
$parent_id = empty( $term->term_id ) ? 0 : $term->term_id;
if ( is_product_category() ) {
$display_type = get_woocommerce_term_meta( $term->term_id, 'display_type', true );
switch ( $display_type ) {
case 'products' :
case 'products':
return;
break;
case '' :
case '':
if ( '' === get_option( 'woocommerce_category_archive_display' ) ) {
return;
}
break;
break;
}
}
@ -1806,7 +1749,9 @@ if ( ! function_exists( 'woocommerce_product_subcategories' ) ) {
) ) );
if ( apply_filters( 'woocommerce_product_subcategories_hide_empty', true ) ) {
$product_categories = wp_list_filter( $product_categories, array( 'count' => 0 ), 'NOT' );
$product_categories = wp_list_filter( $product_categories, array(
'count' => 0,
), 'NOT' );
}
if ( $product_categories ) {
@ -1823,16 +1768,16 @@ if ( ! function_exists( 'woocommerce_product_subcategories' ) ) {
$display_type = get_woocommerce_term_meta( $term->term_id, 'display_type', true );
switch ( $display_type ) {
case 'subcategories' :
case 'subcategories':
$wp_query->post_count = 0;
$wp_query->max_num_pages = 0;
break;
case '' :
break;
case '':
if ( 'subcategories' === get_option( 'woocommerce_category_archive_display' ) ) {
$wp_query->post_count = 0;
$wp_query->max_num_pages = 0;
}
break;
break;
}
}
@ -1854,12 +1799,11 @@ if ( ! function_exists( 'woocommerce_subcategory_thumbnail' ) ) {
* Show subcategory thumbnails.
*
* @param mixed $category Category.
* @subpackage Loop
*/
function woocommerce_subcategory_thumbnail( $category ) {
$small_thumbnail_size = apply_filters( 'subcategory_archive_thumbnail_size', 'woocommerce_thumbnail' );
$dimensions = wc_get_image_size( $small_thumbnail_size );
$thumbnail_id = get_woocommerce_term_meta( $category->term_id, 'thumbnail_id', true );
$small_thumbnail_size = apply_filters( 'subcategory_archive_thumbnail_size', 'woocommerce_thumbnail' );
$dimensions = wc_get_image_size( $small_thumbnail_size );
$thumbnail_id = get_woocommerce_term_meta( $category->term_id, 'thumbnail_id', true );
if ( $thumbnail_id ) {
$image = wp_get_attachment_image_src( $thumbnail_id, $small_thumbnail_size );
@ -1868,7 +1812,8 @@ if ( ! function_exists( 'woocommerce_subcategory_thumbnail' ) ) {
$image_sizes = function_exists( 'wp_get_attachment_image_sizes' ) ? wp_get_attachment_image_sizes( $thumbnail_id, $small_thumbnail_size ) : false;
} else {
$image = wc_placeholder_img_src();
$image_srcset = $image_sizes = false;
$image_srcset = false;
$image_sizes = false;
}
if ( $image ) {
@ -1892,7 +1837,6 @@ if ( ! function_exists( 'woocommerce_order_details_table' ) ) {
* Displays order details in a table.
*
* @param mixed $order_id Order ID.
* @subpackage Orders
*/
function woocommerce_order_details_table( $order_id ) {
if ( ! $order_id ) {
@ -1929,7 +1873,6 @@ if ( ! function_exists( 'woocommerce_order_again_button' ) ) {
* Display an 'order again' button on the view order page.
*
* @param object $order Order.
* @subpackage Orders
*/
function woocommerce_order_again_button( $order ) {
if ( ! $order || ! $order->has_status( apply_filters( 'woocommerce_valid_order_statuses_for_order_again', array( 'completed' ) ) ) || ! is_user_logged_in() ) {
@ -1949,12 +1892,9 @@ if ( ! function_exists( 'woocommerce_form_field' ) ) {
/**
* Outputs a checkout/address form field.
*
* @subpackage Forms
*
* @param string $key Key.
* @param mixed $args Arguments.
* @param string $value (default: null).
*
* @return string
*/
function woocommerce_form_field( $key, $args, $value = null ) {
@ -2031,8 +1971,7 @@ if ( ! function_exists( 'woocommerce_form_field' ) ) {
$field_container = '<p class="form-row %1$s" id="%2$s" data-priority="' . esc_attr( $sort ) . '">%3$s</p>';
switch ( $args['type'] ) {
case 'country' :
case 'country':
$countries = 'shipping_country' === $key ? WC()->countries->get_shipping_countries() : WC()->countries->get_allowed_countries();
if ( 1 === count( $countries ) ) {
@ -2056,7 +1995,7 @@ if ( ! function_exists( 'woocommerce_form_field' ) ) {
}
break;
case 'state' :
case 'state':
/* Get country this state field is representing */
$for_country = isset( $args['country'] ) ? $args['country'] : WC()->checkout->get_value( 'billing_state' === $key ? 'billing_country' : 'shipping_country' );
$states = WC()->countries->get_states( $for_country );
@ -2085,30 +2024,27 @@ if ( ! function_exists( 'woocommerce_form_field' ) ) {
}
break;
case 'textarea' :
case 'textarea':
$field .= '<textarea name="' . esc_attr( $key ) . '" class="input-text ' . esc_attr( implode( ' ', $args['input_class'] ) ) . '" id="' . esc_attr( $args['id'] ) . '" placeholder="' . esc_attr( $args['placeholder'] ) . '" ' . ( empty( $args['custom_attributes']['rows'] ) ? ' rows="2"' : '' ) . ( empty( $args['custom_attributes']['cols'] ) ? ' cols="5"' : '' ) . implode( ' ', $custom_attributes ) . '>' . esc_textarea( $value ) . '</textarea>';
break;
case 'checkbox' :
case 'checkbox':
$field = '<label class="checkbox ' . implode( ' ', $args['label_class'] ) . '" ' . implode( ' ', $custom_attributes ) . '>
<input type="' . esc_attr( $args['type'] ) . '" class="input-checkbox ' . esc_attr( implode( ' ', $args['input_class'] ) ) . '" name="' . esc_attr( $key ) . '" id="' . esc_attr( $args['id'] ) . '" value="1" ' . checked( $value, 1, false ) . ' /> '
. $args['label'] . $required . '</label>';
break;
case 'password' :
case 'text' :
case 'email' :
case 'tel' :
case 'number' :
case 'password':
case 'text':
case 'email':
case 'tel':
case 'number':
$field .= '<input type="' . esc_attr( $args['type'] ) . '" class="input-text ' . esc_attr( implode( ' ', $args['input_class'] ) ) . '" name="' . esc_attr( $key ) . '" id="' . esc_attr( $args['id'] ) . '" placeholder="' . esc_attr( $args['placeholder'] ) . '" value="' . esc_attr( $value ) . '" ' . implode( ' ', $custom_attributes ) . ' />';
break;
case 'select' :
$options = $field = '';
case 'select':
$field = '';
$options = '';
if ( ! empty( $args['options'] ) ) {
foreach ( $args['options'] as $option_key => $option_text ) {
@ -2128,8 +2064,7 @@ if ( ! function_exists( 'woocommerce_form_field' ) ) {
}
break;
case 'radio' :
case 'radio':
$label_id = current( array_keys( $args['options'] ) );
if ( ! empty( $args['options'] ) ) {
@ -2145,7 +2080,7 @@ if ( ! function_exists( 'woocommerce_form_field' ) ) {
if ( ! empty( $field ) ) {
$field_html = '';
if ( $args['label'] && 'checkbox' != $args['type'] ) {
if ( $args['label'] && 'checkbox' !== $args['type'] ) {
$field_html .= '<label for="' . esc_attr( $label_id ) . '" class="' . esc_attr( implode( ' ', $args['label_class'] ) ) . '">' . $args['label'] . $required . '</label>';
}
@ -2181,11 +2116,10 @@ if ( ! function_exists( 'get_product_search_form' ) ) {
*
* The default searchform uses html5.
*
* @subpackage Forms
* @param bool $echo (default: true).
* @return string
*/
function get_product_search_form( $echo = true ) {
function get_product_search_form( $echo = true ) {
global $product_search_form_index;
ob_start();
@ -2263,7 +2197,7 @@ if ( ! function_exists( 'wc_dropdown_variation_attribute_options' ) ) {
'options' => false,
'attribute' => false,
'product' => false,
'selected' => false,
'selected' => false,
'name' => '',
'id' => '',
'class' => '',
@ -2290,10 +2224,12 @@ if ( ! function_exists( 'wc_dropdown_variation_attribute_options' ) ) {
if ( ! empty( $options ) ) {
if ( $product && taxonomy_exists( $attribute ) ) {
// Get terms if this is a taxonomy - ordered. We need the names too.
$terms = wc_get_product_terms( $product->get_id(), $attribute, array( 'fields' => 'all' ) );
$terms = wc_get_product_terms( $product->get_id(), $attribute, array(
'fields' => 'all',
) );
foreach ( $terms as $term ) {
if ( in_array( $term->slug, $options ) ) {
if ( in_array( $term->slug, $options, true ) ) {
$html .= '<option value="' . esc_attr( $term->slug ) . '" ' . selected( sanitize_title( $args['selected'] ), $term->slug, false ) . '>' . esc_html( apply_filters( 'woocommerce_variation_option_name', $term->name ) ) . '</option>';
}
}
@ -2360,7 +2296,11 @@ if ( ! function_exists( 'woocommerce_account_orders' ) ) {
*/
function woocommerce_account_orders( $current_page ) {
$current_page = empty( $current_page ) ? 1 : absint( $current_page );
$customer_orders = wc_get_orders( apply_filters( 'woocommerce_my_account_my_orders_query', array( 'customer' => get_current_user_id(), 'page' => $current_page, 'paginate' => true ) ) );
$customer_orders = wc_get_orders( apply_filters( 'woocommerce_my_account_my_orders_query', array(
'customer' => get_current_user_id(),
'page' => $current_page,
'paginate' => true,
) ) );
wc_get_template(
'myaccount/orders.php',
@ -2504,10 +2444,10 @@ if ( ! function_exists( 'wc_display_item_meta' ) ) {
$html = '';
$args = wp_parse_args( $args, array(
'before' => '<ul class="wc-item-meta"><li>',
'after' => '</li></ul>',
'separator' => '</li><li>',
'echo' => true,
'autop' => false,
'after' => '</li></ul>',
'separator' => '</li><li>',
'echo' => true,
'autop' => false,
) );
foreach ( $item->get_formatted_meta_data() as $meta_id => $meta ) {
@ -2549,7 +2489,9 @@ if ( ! function_exists( 'wc_display_item_downloads' ) ) {
'show_url' => false,
) );
if ( is_object( $item ) && $item->is_type( 'line_item' ) && ( $downloads = $item->get_item_downloads() ) ) {
$downloads = is_object( $item ) && $item->is_type( 'line_item' ) ? $item->get_item_downloads() : array();
if ( $downloads ) {
$i = 0;
foreach ( $downloads as $file ) {
$i ++;
@ -2557,6 +2499,7 @@ if ( ! function_exists( 'wc_display_item_downloads' ) ) {
if ( $args['show_url'] ) {
$strings[] = '<strong class="wc-item-download-label">' . esc_html( $file['name'] ) . ':</strong> ' . esc_html( $file['download_url'] );
} else {
/* translators: %d: downloads count */
$prefix = count( $downloads ) > 1 ? sprintf( __( 'Download %d', 'woocommerce' ), $i ) : __( 'Download', 'woocommerce' );
$strings[] = '<strong class="wc-item-download-label">' . $prefix . ':</strong> <a href="' . esc_url( $file['download_url'] ) . '" target="_blank">' . esc_html( $file['name'] ) . '</a>';
}

View File

@ -50,21 +50,22 @@ function wc_update_200_file_paths() {
*/
function wc_update_200_permalinks() {
// Setup default permalinks if shop page is defined.
$permalinks = get_option( 'woocommerce_permalinks' );
$shop_page_id = wc_get_page_id( 'shop' );
$permalinks = get_option( 'woocommerce_permalinks' );
$shop_page_id = wc_get_page_id( 'shop' );
if ( empty( $permalinks ) && $shop_page_id > 0 ) {
$base_slug = $shop_page_id > 0 && get_post( $shop_page_id ) ? get_page_uri( $shop_page_id ) : 'shop';
$base_slug = $shop_page_id > 0 && get_post( $shop_page_id ) ? get_page_uri( $shop_page_id ) : 'shop';
$category_base = get_option( 'woocommerce_prepend_shop_page_to_urls' ) == 'yes' ? trailingslashit( $base_slug ) : '';
$category_slug = get_option( 'woocommerce_product_category_slug' ) ? get_option( 'woocommerce_product_category_slug' ) : _x( 'product-category', 'slug', 'woocommerce' );
$tag_slug = get_option( 'woocommerce_product_tag_slug' ) ? get_option( 'woocommerce_product_tag_slug' ) : _x( 'product-tag', 'slug', 'woocommerce' );
$category_base = get_option( 'woocommerce_prepend_shop_page_to_urls' ) == 'yes' ? trailingslashit( $base_slug ) : '';
$category_slug = get_option( 'woocommerce_product_category_slug' ) ? get_option( 'woocommerce_product_category_slug' ) : _x( 'product-category', 'slug', 'woocommerce' );
$tag_slug = get_option( 'woocommerce_product_tag_slug' ) ? get_option( 'woocommerce_product_tag_slug' ) : _x( 'product-tag', 'slug', 'woocommerce' );
if ( 'yes' == get_option( 'woocommerce_prepend_shop_page_to_products' ) ) {
$product_base = trailingslashit( $base_slug );
} else {
if ( ( $product_slug = get_option( 'woocommerce_product_slug' ) ) !== false && ! empty( $product_slug ) ) {
$product_slug = get_option( 'woocommerce_product_slug' );
if ( false !== $product_slug && ! empty( $product_slug ) ) {
$product_base = trailingslashit( $product_slug );
} else {
$product_base = trailingslashit( _x( 'product', 'slug', 'woocommerce' ) );
@ -76,10 +77,10 @@ function wc_update_200_permalinks() {
}
$permalinks = array(
'product_base' => untrailingslashit( $product_base ),
'category_base' => untrailingslashit( $category_base . $category_slug ),
'attribute_base' => untrailingslashit( $category_base ),
'tag_base' => untrailingslashit( $category_base . $tag_slug ),
'product_base' => untrailingslashit( $product_base ),
'category_base' => untrailingslashit( $category_base . $category_slug ),
'attribute_base' => untrailingslashit( $category_base ),
'tag_base' => untrailingslashit( $category_base . $tag_slug ),
);
update_option( 'woocommerce_permalinks', $permalinks );
@ -119,7 +120,7 @@ function wc_update_200_taxrates() {
global $wpdb;
// Update tax rates.
$loop = 0;
$loop = 0;
$tax_rates = get_option( 'woocommerce_tax_rates' );
if ( $tax_rates ) {
@ -210,7 +211,7 @@ function wc_update_200_taxrates() {
}
/**
* Upadte order item line items for 2.0
* Update order item line items for 2.0
*
* @return void
*/
@ -219,10 +220,9 @@ function wc_update_200_line_items() {
// Now its time for the massive update to line items - move them to the new DB tables.
// Reverse with UPDATE `wpwc_postmeta` SET meta_key = '_order_items' WHERE meta_key = '_order_items_old'.
$order_item_rows = $wpdb->get_results( "
SELECT meta_value, post_id FROM {$wpdb->postmeta}
WHERE meta_key = '_order_items'
" );
$order_item_rows = $wpdb->get_results(
"SELECT meta_value, post_id FROM {$wpdb->postmeta} WHERE meta_key = '_order_items'"
);
foreach ( $order_item_rows as $order_item_row ) {
@ -231,21 +231,24 @@ function wc_update_200_line_items() {
foreach ( $order_items as $order_item ) {
if ( ! isset( $order_item['line_total'] ) && isset( $order_item['taxrate'] ) && isset( $order_item['cost'] ) ) {
$order_item['line_tax'] = number_format( ( $order_item['cost'] * $order_item['qty'] ) * ( $order_item['taxrate'] / 100 ), 2, '.', '' );
$order_item['line_total'] = $order_item['cost'] * $order_item['qty'];
$order_item['line_subtotal_tax'] = $order_item['line_tax'];
$order_item['line_subtotal'] = $order_item['line_total'];
$order_item['line_tax'] = number_format( ( $order_item['cost'] * $order_item['qty'] ) * ( $order_item['taxrate'] / 100 ), 2, '.', '' );
$order_item['line_total'] = $order_item['cost'] * $order_item['qty'];
$order_item['line_subtotal_tax'] = $order_item['line_tax'];
$order_item['line_subtotal'] = $order_item['line_total'];
}
$order_item['line_tax'] = isset( $order_item['line_tax'] ) ? $order_item['line_tax'] : 0;
$order_item['line_total'] = isset( $order_item['line_total'] ) ? $order_item['line_total'] : 0;
$order_item['line_subtotal_tax'] = isset( $order_item['line_subtotal_tax'] ) ? $order_item['line_subtotal_tax'] : 0;
$order_item['line_subtotal'] = isset( $order_item['line_subtotal'] ) ? $order_item['line_subtotal'] : 0;
$order_item['line_tax'] = isset( $order_item['line_tax'] ) ? $order_item['line_tax'] : 0;
$order_item['line_total'] = isset( $order_item['line_total'] ) ? $order_item['line_total'] : 0;
$order_item['line_subtotal_tax'] = isset( $order_item['line_subtotal_tax'] ) ? $order_item['line_subtotal_tax'] : 0;
$order_item['line_subtotal'] = isset( $order_item['line_subtotal'] ) ? $order_item['line_subtotal'] : 0;
$item_id = wc_add_order_item( $order_item_row->post_id, array(
'order_item_name' => $order_item['name'],
'order_item_type' => 'line_item',
) );
$item_id = wc_add_order_item(
$order_item_row->post_id,
array(
'order_item_name' => $order_item['name'],
'order_item_type' => 'line_item',
)
);
// Add line item meta.
if ( $item_id ) {
@ -274,19 +277,25 @@ function wc_update_200_line_items() {
// Insert meta rows at once.
if ( count( $meta_rows ) > 0 ) {
$wpdb->query( $wpdb->prepare( "
INSERT INTO {$wpdb->prefix}woocommerce_order_itemmeta ( order_item_id, meta_key, meta_value )
VALUES " . implode( ',', $meta_rows ) . ';
', $order_item_row->post_id ) );
$wpdb->query(
$wpdb->prepare(
"INSERT INTO {$wpdb->prefix}woocommerce_order_itemmeta ( order_item_id, meta_key, meta_value )
VALUES " . implode( ',', $meta_rows ) . ';', // @codingStandardsIgnoreLine
$order_item_row->post_id
)
);
}
// Delete from DB (rename).
$wpdb->query( $wpdb->prepare( "
UPDATE {$wpdb->postmeta}
SET meta_key = '_order_items_old'
WHERE meta_key = '_order_items'
AND post_id = %d
", $order_item_row->post_id ) );
$wpdb->query(
$wpdb->prepare(
"UPDATE {$wpdb->postmeta}
SET meta_key = '_order_items_old'
WHERE meta_key = '_order_items'
AND post_id = %d",
$order_item_row->post_id
)
);
}
unset( $meta_rows, $item_id, $order_item );
@ -295,10 +304,10 @@ function wc_update_200_line_items() {
// Do the same kind of update for order_taxes - move to lines.
// Reverse with UPDATE `wpwc_postmeta` SET meta_key = '_order_taxes' WHERE meta_key = '_order_taxes_old'.
$order_tax_rows = $wpdb->get_results( "
SELECT meta_value, post_id FROM {$wpdb->postmeta}
WHERE meta_key = '_order_taxes'
" );
$order_tax_rows = $wpdb->get_results(
"SELECT meta_value, post_id FROM {$wpdb->postmeta}
WHERE meta_key = '_order_taxes'"
);
foreach ( $order_tax_rows as $order_tax_row ) {
@ -311,10 +320,12 @@ function wc_update_200_line_items() {
continue;
}
$item_id = wc_add_order_item( $order_tax_row->post_id, array(
'order_item_name' => $order_tax['label'],
'order_item_type' => 'tax',
) );
$item_id = wc_add_order_item(
$order_tax_row->post_id, array(
'order_item_name' => $order_tax['label'],
'order_item_type' => 'tax',
)
);
// Add line item meta.
if ( $item_id ) {
@ -324,12 +335,15 @@ function wc_update_200_line_items() {
}
// Delete from DB (rename).
$wpdb->query( $wpdb->prepare( "
UPDATE {$wpdb->postmeta}
SET meta_key = '_order_taxes_old'
WHERE meta_key = '_order_taxes'
AND post_id = %d
", $order_tax_row->post_id ) );
$wpdb->query(
$wpdb->prepare(
"UPDATE {$wpdb->postmeta}
SET meta_key = '_order_taxes_old'
WHERE meta_key = '_order_taxes'
AND post_id = %d",
$order_tax_row->post_id
)
);
unset( $tax_amount );
}
@ -347,11 +361,13 @@ function wc_update_200_images() {
// cleaning up afterwards like nice people do.
foreach ( array( 'catalog', 'single', 'thumbnail' ) as $value ) {
$old_settings = array_filter( array(
'width' => get_option( 'woocommerce_' . $value . '_image_width' ),
'height' => get_option( 'woocommerce_' . $value . '_image_height' ),
'crop' => get_option( 'woocommerce_' . $value . '_image_crop' ),
) );
$old_settings = array_filter(
array(
'width' => get_option( 'woocommerce_' . $value . '_image_width' ),
'height' => get_option( 'woocommerce_' . $value . '_image_height' ),
'crop' => get_option( 'woocommerce_' . $value . '_image_crop' ),
)
);
if ( ! empty( $old_settings ) && update_option( 'shop_' . $value . '_image_size', $old_settings ) ) {
@ -521,8 +537,8 @@ function wc_update_220_shipping() {
*/
function wc_update_220_order_status() {
global $wpdb;
$wpdb->query( "
UPDATE {$wpdb->posts} as posts
$wpdb->query(
"UPDATE {$wpdb->posts} as posts
LEFT JOIN {$wpdb->term_relationships} AS rel ON posts.ID = rel.object_id
LEFT JOIN {$wpdb->term_taxonomy} AS tax USING( term_taxonomy_id )
LEFT JOIN {$wpdb->terms} AS term USING( term_id )
@ -530,11 +546,10 @@ function wc_update_220_order_status() {
WHERE posts.post_type = 'shop_order'
AND posts.post_status = 'publish'
AND tax.taxonomy = 'shop_order_status'
AND term.slug LIKE 'pending%';
"
AND term.slug LIKE 'pending%';"
);
$wpdb->query( "
UPDATE {$wpdb->posts} as posts
$wpdb->query(
"UPDATE {$wpdb->posts} as posts
LEFT JOIN {$wpdb->term_relationships} AS rel ON posts.ID = rel.object_id
LEFT JOIN {$wpdb->term_taxonomy} AS tax USING( term_taxonomy_id )
LEFT JOIN {$wpdb->terms} AS term USING( term_id )
@ -542,11 +557,10 @@ function wc_update_220_order_status() {
WHERE posts.post_type = 'shop_order'
AND posts.post_status = 'publish'
AND tax.taxonomy = 'shop_order_status'
AND term.slug LIKE 'processing%';
"
AND term.slug LIKE 'processing%';"
);
$wpdb->query( "
UPDATE {$wpdb->posts} as posts
$wpdb->query(
"UPDATE {$wpdb->posts} as posts
LEFT JOIN {$wpdb->term_relationships} AS rel ON posts.ID = rel.object_id
LEFT JOIN {$wpdb->term_taxonomy} AS tax USING( term_taxonomy_id )
LEFT JOIN {$wpdb->terms} AS term USING( term_id )
@ -554,11 +568,10 @@ function wc_update_220_order_status() {
WHERE posts.post_type = 'shop_order'
AND posts.post_status = 'publish'
AND tax.taxonomy = 'shop_order_status'
AND term.slug LIKE 'on-hold%';
"
AND term.slug LIKE 'on-hold%';"
);
$wpdb->query( "
UPDATE {$wpdb->posts} as posts
$wpdb->query(
"UPDATE {$wpdb->posts} as posts
LEFT JOIN {$wpdb->term_relationships} AS rel ON posts.ID = rel.object_id
LEFT JOIN {$wpdb->term_taxonomy} AS tax USING( term_taxonomy_id )
LEFT JOIN {$wpdb->terms} AS term USING( term_id )
@ -566,11 +579,10 @@ function wc_update_220_order_status() {
WHERE posts.post_type = 'shop_order'
AND posts.post_status = 'publish'
AND tax.taxonomy = 'shop_order_status'
AND term.slug LIKE 'completed%';
"
AND term.slug LIKE 'completed%';"
);
$wpdb->query( "
UPDATE {$wpdb->posts} as posts
$wpdb->query(
"UPDATE {$wpdb->posts} as posts
LEFT JOIN {$wpdb->term_relationships} AS rel ON posts.ID = rel.object_id
LEFT JOIN {$wpdb->term_taxonomy} AS tax USING( term_taxonomy_id )
LEFT JOIN {$wpdb->terms} AS term USING( term_id )
@ -578,11 +590,10 @@ function wc_update_220_order_status() {
WHERE posts.post_type = 'shop_order'
AND posts.post_status = 'publish'
AND tax.taxonomy = 'shop_order_status'
AND term.slug LIKE 'cancelled%';
"
AND term.slug LIKE 'cancelled%';"
);
$wpdb->query( "
UPDATE {$wpdb->posts} as posts
$wpdb->query(
"UPDATE {$wpdb->posts} as posts
LEFT JOIN {$wpdb->term_relationships} AS rel ON posts.ID = rel.object_id
LEFT JOIN {$wpdb->term_taxonomy} AS tax USING( term_taxonomy_id )
LEFT JOIN {$wpdb->terms} AS term USING( term_id )
@ -590,11 +601,10 @@ function wc_update_220_order_status() {
WHERE posts.post_type = 'shop_order'
AND posts.post_status = 'publish'
AND tax.taxonomy = 'shop_order_status'
AND term.slug LIKE 'refunded%';
"
AND term.slug LIKE 'refunded%';"
);
$wpdb->query( "
UPDATE {$wpdb->posts} as posts
$wpdb->query(
"UPDATE {$wpdb->posts} as posts
LEFT JOIN {$wpdb->term_relationships} AS rel ON posts.ID = rel.object_id
LEFT JOIN {$wpdb->term_taxonomy} AS tax USING( term_taxonomy_id )
LEFT JOIN {$wpdb->terms} AS term USING( term_id )
@ -602,8 +612,7 @@ function wc_update_220_order_status() {
WHERE posts.post_type = 'shop_order'
AND posts.post_status = 'publish'
AND tax.taxonomy = 'shop_order_status'
AND term.slug LIKE 'failed%';
"
AND term.slug LIKE 'failed%';"
);
}
@ -615,15 +624,15 @@ function wc_update_220_order_status() {
function wc_update_220_variations() {
global $wpdb;
// Update variations which manage stock.
$update_variations = $wpdb->get_results( "
SELECT DISTINCT posts.ID AS variation_id, posts.post_parent AS variation_parent FROM {$wpdb->posts} as posts
$update_variations = $wpdb->get_results(
"SELECT DISTINCT posts.ID AS variation_id, posts.post_parent AS variation_parent FROM {$wpdb->posts} as posts
LEFT OUTER JOIN {$wpdb->postmeta} AS postmeta ON posts.ID = postmeta.post_id AND postmeta.meta_key = '_stock'
LEFT OUTER JOIN {$wpdb->postmeta} as postmeta2 ON posts.ID = postmeta2.post_id AND postmeta2.meta_key = '_manage_stock'
WHERE posts.post_type = 'product_variation'
AND postmeta.meta_value IS NOT NULL
AND postmeta.meta_value != ''
AND postmeta2.meta_value IS NULL
" );
AND postmeta2.meta_value IS NULL"
);
foreach ( $update_variations as $variation ) {
$parent_backorders = get_post_meta( $variation->variation_parent, '_backorders', true );
@ -735,10 +744,15 @@ function wc_update_240_shipping_methods() {
$has_classes = count( WC()->shipping->get_shipping_classes() ) > 0;
$cost_key = $has_classes ? 'no_class_cost' : 'cost';
$min_fee = $shipping_method->get_option( 'minimum_fee' );
$math_cost_strings = array( 'cost' => array(), 'no_class_cost' => array() );
$math_cost_strings[ $cost_key ][] = $shipping_method->get_option( 'cost' );
$math_cost_strings = array(
'cost' => array(),
'no_class_cost' => array(),
);
if ( $fee = $shipping_method->get_option( 'fee' ) ) {
$math_cost_strings[ $cost_key ][] = $shipping_method->get_option( 'cost' );
$fee = $shipping_method->get_option( 'fee' );
if ( $fee ) {
$math_cost_strings[ $cost_key ][] = strstr( $fee, '%' ) ? '[fee percent="' . str_replace( '%', '', $fee ) . '" min="' . esc_attr( $min_fee ) . '"]' : $fee;
}
@ -747,7 +761,9 @@ function wc_update_240_shipping_methods() {
$math_cost_strings[ $rate_key ] = $math_cost_strings['no_class_cost'];
}
if ( $flat_rates = array_filter( (array) get_option( $flat_rate_option_key, array() ) ) ) {
$flat_rates = array_filter( (array) get_option( $flat_rate_option_key, array() ) );
if ( $flat_rates ) {
foreach ( $flat_rates as $shipping_class => $rate ) {
$rate_key = 'class_cost_' . $shipping_class;
if ( $rate['cost'] || $rate['fee'] ) {
@ -798,7 +814,7 @@ function wc_update_240_api_keys() {
// Get user data.
foreach ( $api_users as $_user ) {
$user = get_userdata( $_user->user_id );
$user = get_userdata( $_user->user_id );
$apps_keys[] = array(
'user_id' => $user->ID,
'permissions' => $user->woocommerce_api_key_permissions,
@ -835,6 +851,33 @@ function wc_update_240_api_keys() {
}
/**
<<<<<<< HEAD
=======
* Update webhooks for 2.4
*
* @return void
*/
function wc_update_240_webhooks() {
/**
* Webhooks.
* Make sure order.update webhooks get the woocommerce_order_edit_status hook.
*/
$order_update_webhooks = get_posts(
array(
'posts_per_page' => -1,
'post_type' => 'shop_webhook',
'meta_key' => '_topic',
'meta_value' => 'order.updated',
)
);
foreach ( $order_update_webhooks as $order_update_webhook ) {
$webhook = new WC_Webhook( $order_update_webhook->ID );
$webhook->set_topic( 'order.updated' );
}
}
/**
>>>>>>> master
* Update refunds for 2.4
*
* @return void
@ -845,11 +888,13 @@ function wc_update_240_refunds() {
* Refunds for full refunded orders.
* Update fully refunded orders to ensure they have a refund line item so reports add up.
*/
$refunded_orders = get_posts( array(
'posts_per_page' => -1,
'post_type' => 'shop_order',
'post_status' => array( 'wc-refunded' ),
) );
$refunded_orders = get_posts(
array(
'posts_per_page' => -1,
'post_type' => 'shop_order',
'post_status' => array( 'wc-refunded' ),
)
);
// Ensure emails are disabled during this update routine.
remove_all_actions( 'woocommerce_order_status_refunded_notification' );
@ -859,22 +904,27 @@ function wc_update_240_refunds() {
foreach ( $refunded_orders as $refunded_order ) {
$order_total = get_post_meta( $refunded_order->ID, '_order_total', true );
$refunded_total = $wpdb->get_var( $wpdb->prepare( "
SELECT SUM( postmeta.meta_value )
FROM $wpdb->postmeta AS postmeta
INNER JOIN $wpdb->posts AS posts ON ( posts.post_type = 'shop_order_refund' AND posts.post_parent = %d )
WHERE postmeta.meta_key = '_refund_amount'
AND postmeta.post_id = posts.ID
", $refunded_order->ID ) );
$refunded_total = $wpdb->get_var(
$wpdb->prepare(
"SELECT SUM( postmeta.meta_value )
FROM $wpdb->postmeta AS postmeta
INNER JOIN $wpdb->posts AS posts ON ( posts.post_type = 'shop_order_refund' AND posts.post_parent = %d )
WHERE postmeta.meta_key = '_refund_amount'
AND postmeta.post_id = posts.ID",
$refunded_order->ID
)
);
if ( $order_total > $refunded_total ) {
wc_create_refund( array(
'amount' => $order_total - $refunded_total,
'reason' => __( 'Order fully refunded', 'woocommerce' ),
'order_id' => $refunded_order->ID,
'line_items' => array(),
'date' => $refunded_order->post_modified,
) );
wc_create_refund(
array(
'amount' => $order_total - $refunded_total,
'reason' => __( 'Order fully refunded', 'woocommerce' ),
'order_id' => $refunded_order->ID,
'line_items' => array(),
'date' => $refunded_order->post_modified,
)
);
}
}
@ -899,13 +949,13 @@ function wc_update_241_variations() {
global $wpdb;
// Select variations that don't have any _stock_status implemented on WooCommerce 2.2.
$update_variations = $wpdb->get_results( "
SELECT DISTINCT posts.ID AS variation_id, posts.post_parent AS variation_parent
$update_variations = $wpdb->get_results(
"SELECT DISTINCT posts.ID AS variation_id, posts.post_parent AS variation_parent
FROM {$wpdb->posts} as posts
LEFT OUTER JOIN {$wpdb->postmeta} AS postmeta ON posts.ID = postmeta.post_id AND postmeta.meta_key = '_stock_status'
WHERE posts.post_type = 'product_variation'
AND postmeta.meta_value IS NULL
" );
AND postmeta.meta_value IS NULL"
);
foreach ( $update_variations as $variation ) {
// Get the parent _stock_status.
@ -1043,11 +1093,13 @@ function wc_update_260_zone_methods() {
// Move data.
foreach ( $old_methods as $old_method ) {
$wpdb->insert( $wpdb->prefix . 'woocommerce_shipping_zone_methods', array(
'zone_id' => $old_method->zone_id,
'method_id' => $old_method->shipping_method_type,
'method_order' => $old_method->shipping_method_order,
) );
$wpdb->insert(
$wpdb->prefix . 'woocommerce_shipping_zone_methods', array(
'zone_id' => $old_method->zone_id,
'method_id' => $old_method->shipping_method_type,
'method_order' => $old_method->shipping_method_order,
)
);
$new_instance_id = $wpdb->insert_id;
@ -1108,13 +1160,13 @@ function wc_update_260_refunds() {
/**
* Refund item qty should be negative.
*/
$wpdb->query( "
UPDATE {$wpdb->prefix}woocommerce_order_itemmeta as item_meta
LEFT JOIN {$wpdb->prefix}woocommerce_order_items as items ON item_meta.order_item_id = items.order_item_id
LEFT JOIN {$wpdb->posts} as posts ON items.order_id = posts.ID
SET item_meta.meta_value = item_meta.meta_value * -1
WHERE item_meta.meta_value > 0 AND item_meta.meta_key = '_qty' AND posts.post_type = 'shop_order_refund'
" );
$wpdb->query(
"UPDATE {$wpdb->prefix}woocommerce_order_itemmeta as item_meta
LEFT JOIN {$wpdb->prefix}woocommerce_order_items as items ON item_meta.order_item_id = items.order_item_id
LEFT JOIN {$wpdb->posts} as posts ON items.order_id = posts.ID
SET item_meta.meta_value = item_meta.meta_value * -1
WHERE item_meta.meta_value > 0 AND item_meta.meta_key = '_qty' AND posts.post_type = 'shop_order_refund'"
);
}
/**
@ -1127,6 +1179,33 @@ function wc_update_260_db_version() {
}
/**
<<<<<<< HEAD
=======
* Update webhooks for 3.0
*
* @return void
*/
function wc_update_300_webhooks() {
/**
* Make sure product.update webhooks get the woocommerce_product_quick_edit_save
* and woocommerce_product_bulk_edit_save hooks.
*/
$product_update_webhooks = get_posts(
array(
'posts_per_page' => -1,
'post_type' => 'shop_webhook',
'meta_key' => '_topic',
'meta_value' => 'product.updated',
)
);
foreach ( $product_update_webhooks as $product_update_webhook ) {
$webhook = new WC_Webhook( $product_update_webhook->ID );
$webhook->set_topic( 'product.updated' );
}
}
/**
>>>>>>> master
* Add an index to the field comment_type to improve the response time of the query
* used by WC_Comments::wp_count_comments() to get the number of comments by type.
*/
@ -1153,12 +1232,14 @@ function wc_update_300_grouped_products() {
foreach ( $parents as $parent_id ) {
$parent = wc_get_product( $parent_id );
if ( $parent && $parent->is_type( 'grouped' ) ) {
$children_ids = get_posts( array(
'post_parent' => $parent_id,
'posts_per_page' => -1,
'post_type' => 'product',
'fields' => 'ids',
) );
$children_ids = get_posts(
array(
'post_parent' => $parent_id,
'posts_per_page' => -1,
'post_type' => 'product',
'fields' => 'ids',
)
);
update_post_meta( $parent_id, '_children', $children_ids );
// Update children to remove the parent.
@ -1197,39 +1278,57 @@ function wc_update_300_product_visibility() {
WC_Install::create_terms();
if ( $featured_term = get_term_by( 'name', 'featured', 'product_visibility' ) ) {
$featured_term = get_term_by( 'name', 'featured', 'product_visibility' );
if ( $featured_term ) {
$wpdb->query( $wpdb->prepare( "INSERT IGNORE INTO {$wpdb->term_relationships} SELECT post_id, %d, 0 FROM {$wpdb->postmeta} WHERE meta_key = '_featured' AND meta_value = 'yes';", $featured_term->term_taxonomy_id ) );
}
if ( $exclude_search_term = get_term_by( 'name', 'exclude-from-search', 'product_visibility' ) ) {
$exclude_search_term = get_term_by( 'name', 'exclude-from-search', 'product_visibility' );
if ( $exclude_search_term ) {
$wpdb->query( $wpdb->prepare( "INSERT IGNORE INTO {$wpdb->term_relationships} SELECT post_id, %d, 0 FROM {$wpdb->postmeta} WHERE meta_key = '_visibility' AND meta_value IN ('hidden', 'catalog');", $exclude_search_term->term_taxonomy_id ) );
}
if ( $exclude_catalog_term = get_term_by( 'name', 'exclude-from-catalog', 'product_visibility' ) ) {
$exclude_catalog_term = get_term_by( 'name', 'exclude-from-catalog', 'product_visibility' );
if ( $exclude_catalog_term ) {
$wpdb->query( $wpdb->prepare( "INSERT IGNORE INTO {$wpdb->term_relationships} SELECT post_id, %d, 0 FROM {$wpdb->postmeta} WHERE meta_key = '_visibility' AND meta_value IN ('hidden', 'search');", $exclude_catalog_term->term_taxonomy_id ) );
}
if ( $outofstock_term = get_term_by( 'name', 'outofstock', 'product_visibility' ) ) {
$outofstock_term = get_term_by( 'name', 'outofstock', 'product_visibility' );
if ( $outofstock_term ) {
$wpdb->query( $wpdb->prepare( "INSERT IGNORE INTO {$wpdb->term_relationships} SELECT post_id, %d, 0 FROM {$wpdb->postmeta} WHERE meta_key = '_stock_status' AND meta_value = 'outofstock';", $outofstock_term->term_taxonomy_id ) );
}
if ( $rating_term = get_term_by( 'name', 'rated-1', 'product_visibility' ) ) {
$rating_term = get_term_by( 'name', 'rated-1', 'product_visibility' );
if ( $rating_term ) {
$wpdb->query( $wpdb->prepare( "INSERT IGNORE INTO {$wpdb->term_relationships} SELECT post_id, %d, 0 FROM {$wpdb->postmeta} WHERE meta_key = '_wc_average_rating' AND ROUND( meta_value ) = 1;", $rating_term->term_taxonomy_id ) );
}
if ( $rating_term = get_term_by( 'name', 'rated-2', 'product_visibility' ) ) {
$rating_term = get_term_by( 'name', 'rated-2', 'product_visibility' );
if ( $rating_term ) {
$wpdb->query( $wpdb->prepare( "INSERT IGNORE INTO {$wpdb->term_relationships} SELECT post_id, %d, 0 FROM {$wpdb->postmeta} WHERE meta_key = '_wc_average_rating' AND ROUND( meta_value ) = 2;", $rating_term->term_taxonomy_id ) );
}
if ( $rating_term = get_term_by( 'name', 'rated-3', 'product_visibility' ) ) {
$rating_term = get_term_by( 'name', 'rated-3', 'product_visibility' );
if ( $rating_term ) {
$wpdb->query( $wpdb->prepare( "INSERT IGNORE INTO {$wpdb->term_relationships} SELECT post_id, %d, 0 FROM {$wpdb->postmeta} WHERE meta_key = '_wc_average_rating' AND ROUND( meta_value ) = 3;", $rating_term->term_taxonomy_id ) );
}
if ( $rating_term = get_term_by( 'name', 'rated-4', 'product_visibility' ) ) {
$rating_term = get_term_by( 'name', 'rated-4', 'product_visibility' );
if ( $rating_term ) {
$wpdb->query( $wpdb->prepare( "INSERT IGNORE INTO {$wpdb->term_relationships} SELECT post_id, %d, 0 FROM {$wpdb->postmeta} WHERE meta_key = '_wc_average_rating' AND ROUND( meta_value ) = 4;", $rating_term->term_taxonomy_id ) );
}
if ( $rating_term = get_term_by( 'name', 'rated-5', 'product_visibility' ) ) {
$rating_term = get_term_by( 'name', 'rated-5', 'product_visibility' );
if ( $rating_term ) {
$wpdb->query( $wpdb->prepare( "INSERT IGNORE INTO {$wpdb->term_relationships} SELECT post_id, %d, 0 FROM {$wpdb->postmeta} WHERE meta_key = '_wc_average_rating' AND ROUND( meta_value ) = 5;", $rating_term->term_taxonomy_id ) );
}
}
@ -1329,12 +1428,10 @@ function wc_update_320_mexican_states() {
foreach ( $mx_states as $old => $new ) {
$wpdb->query(
$wpdb->prepare(
"
UPDATE $wpdb->postmeta
SET meta_value = %s
WHERE meta_key IN ( '_billing_state', '_shipping_state' )
AND meta_value = %s
",
"UPDATE $wpdb->postmeta
SET meta_value = %s
WHERE meta_key IN ( '_billing_state', '_shipping_state' )
AND meta_value = %s",
$new, $old
)
);
@ -1422,6 +1519,33 @@ function wc_update_330_webhooks() {
}
unregister_post_type( 'shop_webhook' );
/**
* Assign default cat to all products with no cats.
*/
function wc_update_330_set_default_product_cat() {
global $wpdb;
$default_category = get_option( 'default_product_cat', 0 );
if ( $default_category ) {
$result = $wpdb->query( $wpdb->prepare( "
INSERT INTO {$wpdb->term_relationships} (object_id, term_taxonomy_id)
SELECT DISTINCT posts.ID, %s FROM {$wpdb->posts} posts
LEFT JOIN
(
SELECT object_id FROM {$wpdb->term_relationships} term_relationships
LEFT JOIN {$wpdb->term_taxonomy} term_taxonomy ON term_relationships.term_taxonomy_id = term_taxonomy.term_taxonomy_id
WHERE term_taxonomy.taxonomy = 'product_cat'
) AS tax_query
ON posts.ID = tax_query.object_id
WHERE posts.post_type = 'product'
AND tax_query.object_id IS NULL
", $default_category ) );
wp_cache_flush();
delete_transient( 'wc_term_counts' );
wp_update_term_count_now( array( $default_category ), 'product_cat' );
}
}
/**

View File

@ -148,7 +148,19 @@ function wc_update_new_customer_past_orders( $customer_id ) {
if ( ! empty( $customer_orders ) ) {
foreach ( $customer_orders as $order_id ) {
update_post_meta( $order_id, '_customer_user', $customer->ID );
$order = wc_get_order( $order_id );
if ( ! $order ) {
continue;
}
$order->set_customer_id( $customer->ID );
$order->save();
if ( $order->has_downloadable_item() ) {
$data_store = WC_Data_Store::load( 'customer-download' );
$data_store->delete_by_order_id( $order->get_id() );
wc_downloadable_product_permissions( $order->get_id(), true );
}
do_action( 'woocommerce_update_new_customer_past_order', $order_id, $customer );

View File

@ -264,7 +264,7 @@ class WC_Widget_Layered_Nav extends WC_Widget {
continue;
}
echo '<option value="' . esc_attr( $term->slug ) . '" ' . selected( $option_is_set, true, false ) . '>' . esc_html( $term->name ) . '</option>';
echo '<option value="' . esc_attr( urldecode( $term->slug ) ) . '" ' . selected( $option_is_set, true, false ) . '>' . esc_html( $term->name ) . '</option>';
}
echo '</select>';

View File

@ -10,6 +10,8 @@
"license": "GPL-3.0+",
"main": "Gruntfile.js",
"scripts": {
"build": "grunt",
"build-watch": "grunt watch",
"test": "cross-env NODE_CONFIG_DIR='./tests/e2e-tests/config' BABEL_ENV=commonjs mocha \"tests/e2e-tests\" --compilers js:babel-register --recursive",
"test:grep": "cross-env NODE_CONFIG_DIR='./tests/e2e-tests/config' BABEL_ENV=commonjs mocha \"tests/e2e-tests\" --compilers js:babel-register --grep ",
"test:single": "cross-env NODE_CONFIG_DIR='./tests/e2e-tests/config' BABEL_ENV=commonjs mocha --compilers js:babel-register"
@ -45,7 +47,7 @@
"istanbul": "^1.0.0-alpha",
"mocha": "^3.0.2",
"stylelint": "~8.2.0",
"wc-e2e-page-objects": "0.4.0"
"wc-e2e-page-objects": "0.5.0"
},
"engines": {
"node": ">=6.9.4",

View File

@ -11,14 +11,25 @@
<exclude-pattern>includes/gateways/simplify-commerce/includes/</exclude-pattern>
<exclude-pattern>includes/libraries/</exclude-pattern>
<exclude-pattern>includes/api/legacy/</exclude-pattern>
<exclude-pattern>*/node_modules/*</exclude-pattern>
<exclude-pattern>*/vendor/*</exclude-pattern>
<!-- Configs -->
<config name="minimum_supported_wp_version" value="4.7" />
<config name="testVersion" value="5.2-"/>
<!-- Rules -->
<rule ref="PHPCompatibility"/>
<rule ref="WordPress">
<exclude name="WordPress.VIP.RestrictedFunctions" />
<exclude name="WordPress.VIP.DirectDatabaseQuery.NoCaching" />
<exclude name="WordPress.VIP.DirectDatabaseQuery.SchemaChange" />
<exclude name="WordPress.VIP.FileSystemWritesDisallow.file_ops_fwrite" />
<exclude name="WordPress.VIP.OrderByRand" />
<exclude name="WordPress.VIP.RestrictedFunctions" />
<exclude name="WordPress.VIP.RestrictedVariables.user_meta__wpdb__usermeta" />
<exclude name="WordPress.VIP.PostsPerPage.posts_per_page_posts_per_page" />
</rule>
<rule ref="WordPress.VIP.ValidatedSanitizedInput">
<properties>
<property name="customSanitizingFunctions" type="array" value="wc_clean,wc_sanitize_tooltip,wc_format_decimal,wc_stock_amount" />
@ -28,5 +39,13 @@
<properties>
<property name="customEscapingFunctions" type="array" value="wc_help_tip,wc_sanitize_tooltip" />
</properties>
</rule>
</rule>
<rule ref="WordPress.WP.I18n">
<properties>
<property name="text_domain" type="array" value="woocommerce" />
</properties>
</rule>
<rule ref="WordPress.Files.FileName.InvalidClassFileName">
<exclude-pattern>includes/**/abstract-*.php</exclude-pattern>
</rule>
</ruleset>

View File

@ -1,8 +1,8 @@
=== WooCommerce ===
Contributors: automattic, mikejolley, jameskoster, claudiosanches, jshreve, coderkevin, claudiulodro, woothemes, iCaleb
Tags: ecommerce, e-commerce, store, sales, sell, shop, cart, checkout, downloadable, downloads, paypal, storefront, woo commerce
Requires at least: 4.5
Tested up to: 4.8
Requires at least: 4.7
Tested up to: 4.9
Stable tag: 3.2.0
License: GPLv3
License URI: https://www.gnu.org/licenses/gpl-3.0.html

View File

@ -1,6 +1,6 @@
#!/usr/bin/env bash
if [[ $TRAVIS_PHP_VERSION == '7.1' ]]; then
if [[ ${RUN_PHPCS} == 1 ]]; then
CHANGED_FILES=`git diff --name-only --diff-filter=ACMR $TRAVIS_COMMIT_RANGE | grep \\\\.php | awk '{print}' ORS=' '`
IGNORE="tests/cli/,apigen/,includes/gateways/simplify-commerce/includes/,includes/libraries/,includes/api/legacy/"

View File

@ -3,24 +3,16 @@
if [ $1 == 'before' ]; then
# Composer install fails in PHP 5.2
[[ ${TRAVIS_PHP_VERSION} == '5.2' ]] && exit;
# No Xdebug and therefore no coverage in PHP 5.3
[[ ${TRAVIS_PHP_VERSION} == '5.3' ]] && exit;
if [[ ${TRAVIS_PHP_VERSION:0:2} == "5." ]]; then
composer global require "phpunit/phpunit=4.8.*"
else
composer global require "phpunit/phpunit=6.2.*"
fi
# Remove Xdebug from PHP runtime for all PHP version except 7.1 to speed up builds.
# We need Xdebug enabled in the PHP 7.1 build job as it is used to generate code coverage.
if [[ ${RUN_CODE_COVERAGE} != 1 ]]; then
phpenv config-rm xdebug.ini
fi
if [[ ${RUN_PHPCS} == 1 ]]; then
composer install
fi
fi
if [ $1 == 'after' ]; then

View File

@ -12,7 +12,8 @@ let manager;
let driver;
test.describe( 'Cart page', function() {
test.before( 'open browser', function() {
// open browser
test.before( function() {
this.timeout( config.get( 'startBrowserTimeoutMs' ) );
manager = new WebDriverManager( 'chrome', { baseUrl: config.get( 'url' ) } );
@ -93,7 +94,7 @@ test.describe( 'Cart page', function() {
);
} );
test.it( 'should go to the checkout page when "Proceed to Chcekout" is clicked', () => {
test.it( 'should go to the checkout page when "Proceed to Checkout" is clicked', () => {
const cartPage = new CartPage( driver, { url: manager.getPageUrl( '/cart' ) } );
const checkoutPage = cartPage.checkout();
@ -104,7 +105,8 @@ test.describe( 'Cart page', function() {
);
} );
test.after( 'quit browser', () => {
// quit browser
test.after( () => {
manager.quitBrowser();
} );
} );

View File

@ -26,7 +26,8 @@ let manager;
let driver;
test.describe( 'Checkout Page', function() {
test.before( 'open browser', function() {
// open browser
test.before( function() {
this.timeout( config.get( 'startBrowserTimeoutMs' ) );
manager = new WebDriverManager( 'chrome', { baseUrl: config.get( 'url' ) } );
@ -148,7 +149,8 @@ test.describe( 'Checkout Page', function() {
);
} );
test.after( 'quit browser', () => {
// quit browser
test.after( () => {
manager.quitBrowser();
} );
} );

View File

@ -16,7 +16,8 @@ let manager;
let driver;
test.describe( 'Single Product Page', function() {
test.before( 'open browser', function() {
// open browser
test.before( function() {
this.timeout( config.get( 'startBrowserTimeoutMs' ) );
manager = new WebDriverManager( 'chrome', { baseUrl: config.get( 'url' ) } );
@ -52,7 +53,8 @@ test.describe( 'Single Product Page', function() {
assert.eventually.equal( cartPage.hasItem( 'Hoodie - Green' ), true );
} );
test.after( 'quit browser', () => {
// quit browser
test.after( () => {
manager.quitBrowser();
} );
} );

View File

@ -12,7 +12,8 @@ let manager;
let driver;
test.describe( 'Add New Coupon Page', function() {
test.before( 'open browser', function() {
// open browser
test.before( function() {
this.timeout( config.get( 'startBrowserTimeoutMs' ) );
manager = new WebDriverManager( 'chrome', { baseUrl: config.get( 'url' ) } );
@ -45,7 +46,8 @@ test.describe( 'Add New Coupon Page', function() {
assert.eventually.ok( couponPage.hasNotice( 'Coupon updated.' ) );
} );
test.after( 'quit browser', () => {
// quit browser
test.after( () => {
manager.quitBrowser();
} );
} );

View File

@ -12,7 +12,8 @@ let manager;
let driver;
test.describe( 'Add New Order Page', function() {
test.before( 'open browser', function() {
// open browser
test.before( function() {
this.timeout( config.get( 'startBrowserTimeoutMs' ) );
manager = new WebDriverManager( 'chrome', { baseUrl: config.get( 'url' ) } );
@ -46,7 +47,8 @@ test.describe( 'Add New Order Page', function() {
assert.eventually.ok( orderNotes.hasNote( 'Order status changed from Pending payment to Processing.' ) );
} );
test.after( 'quit browser', () => {
// quit browser
test.after( () => {
manager.quitBrowser();
} );
} );

View File

@ -13,7 +13,8 @@ let manager;
let driver;
test.describe( 'Add New Product Page', function() {
test.before( 'open browser', function() {
// open browser
test.before( function() {
this.timeout( config.get( 'startBrowserTimeoutMs' ) );
manager = new WebDriverManager( 'chrome', { baseUrl: config.get( 'url' ) } );
@ -24,7 +25,8 @@ test.describe( 'Add New Product Page', function() {
this.timeout( config.get( 'mochaTimeoutMs' ) );
test.before( 'login', () => {
// login
test.before( () => {
const wpLogin = new WPLogin( driver, { url: manager.getPageUrl( '/wp-login.php' ) } );
wpLogin.login( config.get( 'users.admin.username' ), config.get( 'users.admin.password' ) );
} );
@ -121,7 +123,8 @@ test.describe( 'Add New Product Page', function() {
assert.eventually.ok( product.hasNotice( '1 product moved to the Trash.' ) );
} );
test.after( 'quit browser', () => {
// quit browser
test.after( () => {
manager.quitBrowser();
} );
} );

View File

@ -13,7 +13,8 @@ let manager;
let driver;
test.describe( 'WooCommerce General Settings', function() {
test.before( 'open browser', function() {
// open browser
test.before( function() {
this.timeout( config.get( 'startBrowserTimeoutMs' ) );
manager = new WebDriverManager( 'chrome', { baseUrl: config.get( 'url' ) } );
@ -24,7 +25,8 @@ test.describe( 'WooCommerce General Settings', function() {
this.timeout( config.get( 'mochaTimeoutMs' ) );
test.before( 'login', () => {
// login
test.before( () => {
const wpLogin = new WPLogin( driver, { url: manager.getPageUrl( '/wp-login.php' ) } );
wpLogin.login( config.get( 'users.admin.username' ), config.get( 'users.admin.password' ) );
} );
@ -64,7 +66,8 @@ test.describe( 'WooCommerce General Settings', function() {
assert.eventually.ok( settings.hasNotice( 'Your settings have been saved.' ) );
} );
test.after( 'quit browser', () => {
// quit browser
test.after( () => {
manager.quitBrowser();
} );
} );

View File

@ -13,7 +13,8 @@ let manager;
let driver;
test.describe( 'WooCommerce Products > Downloadable Products Settings', function() {
test.before( 'open browser', function() {
// open browser
test.before( function() {
this.timeout( config.get( 'startBrowserTimeoutMs' ) );
manager = new WebDriverManager( 'chrome', { baseUrl: config.get( 'url' ) } );
@ -24,7 +25,8 @@ test.describe( 'WooCommerce Products > Downloadable Products Settings', function
this.timeout( config.get( 'mochaTimeoutMs' ) );
test.before( 'login', () => {
// login
test.before( () => {
const wpLogin = new WPLogin( driver, { url: manager.getPageUrl( '/wp-login.php' ) } );
wpLogin.login( config.get( 'users.admin.username' ), config.get( 'users.admin.password' ) );
} );
@ -49,7 +51,8 @@ test.describe( 'WooCommerce Products > Downloadable Products Settings', function
assert.eventually.ok( settings.hasNotice( 'Your settings have been saved.' ) );
} );
test.after( 'quit browser', () => {
// quit browser
test.after( () => {
manager.quitBrowser();
} );
} );

View File

@ -13,7 +13,8 @@ let manager;
let driver;
test.describe( 'WooCommerce Tax Settings', function() {
test.before( 'open browser', function() {
// open browser
test.before( function() {
this.timeout( config.get( 'startBrowserTimeoutMs' ) );
manager = new WebDriverManager( 'chrome', { baseUrl: config.get( 'url' ) } );
@ -24,7 +25,8 @@ test.describe( 'WooCommerce Tax Settings', function() {
this.timeout( config.get( 'mochaTimeoutMs' ) );
test.before( 'login', () => {
// login
test.before( () => {
const wpLogin = new WPLogin( driver, { url: manager.getPageUrl( '/wp-login.php' ) } );
wpLogin.login( config.get( 'users.admin.username' ), config.get( 'users.admin.password' ) );
} );
@ -93,7 +95,8 @@ test.describe( 'WooCommerce Tax Settings', function() {
assert.eventually.ifError( settings.hasSubTab( 'Fancy rates' ) );
} );
test.after( 'quit browser', () => {
// quit browser
test.after( () => {
manager.quitBrowser();
} );
} );

View File

@ -81,6 +81,21 @@ class WC_Unit_Test_Case extends WP_UnitTestCase {
$this->assertInstanceOf( 'WP_Error', $actual, $message );
}
/**
* Throws an exception with an optional message and code.
*
* Note: can't use `throwException` as that's reserved.
*
* @since 3.3-dev
* @param string $message
* @param int $code
* @throws \Exception
*/
public function throwAnException( $message = null, $code = null ) {
$message = $message ? $message : "We're all doomed!";
throw new Exception( $message, $code );
}
/**
* Backport assertNotFalse to PHPUnit 3.6.12 which only runs in PHP 5.2.
*

View File

@ -16,15 +16,15 @@ class WC_Helper_Order {
$order = wc_get_order( $order_id );
// Delete all products in the order
foreach ( $order->get_items() as $item ) :
// Delete all products in the order.
foreach ( $order->get_items() as $item ) {
WC_Helper_Product::delete_product( $item['product_id'] );
endforeach;
}
WC_Helper_Shipping::delete_simple_flat_rate();
// Delete the order post
wp_delete_post( $order_id, true );
// Delete the order post.
$order->delete( true );
}
/**

View File

@ -267,12 +267,13 @@ class WC_Tests_API_Orders extends WC_REST_Unit_Test_Case {
/**
* Tests updating an order.
*
* @since 3.0.0
*/
public function test_update_order() {
wp_set_current_user( $this->user );
$order = WC_Helper_Order::create_order();
$request = new WP_REST_Request( 'POST', '/wc/v2/orders/' . $order->get_id() );
$order = WC_Helper_Order::create_order();
$request = new WP_REST_Request( 'PUT', '/wc/v2/orders/' . $order->get_id() );
$request->set_body_params( array(
'payment_method' => 'test-update',
'billing' => array(
@ -288,17 +289,56 @@ class WC_Tests_API_Orders extends WC_REST_Unit_Test_Case {
$this->assertEquals( 'Fish', $data['billing']['first_name'] );
$this->assertEquals( 'Face', $data['billing']['last_name'] );
wp_delete_post( $order->get_id(), true );
WC_Helper_Order::delete_order( $order->get_id() );
}
/**
* Tests updating an order and removing items.
*
* @since 3.0.0
*/
public function test_update_order_remove_items() {
wp_set_current_user( $this->user );
$order = WC_Helper_Order::create_order();
$fee = new WC_Order_Item_Fee();
$fee->set_props( array(
'name' => 'Some Fee',
'tax_status' => 'taxable',
'total' => '100',
'tax_class' => '',
) );
$order->add_item( $fee );
$order->save();
$request = new WP_REST_Request( 'PUT', '/wc/v2/orders/' . $order->get_id() );
$fee_data = current( $order->get_items( 'fee' ) );
$request->set_body_params( array(
'fee_lines' => array(
array(
'id' => $fee_data->get_id(),
'name' => null,
),
),
) );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( 200, $response->get_status() );
$this->assertTrue( empty( $data['fee_lines'] ) );
WC_Helper_Order::delete_order( $order->get_id() );
}
/**
* Tests updating an order without the correct permissions.
*
* @since 3.0.0
*/
public function test_update_order_without_permission() {
wp_set_current_user( 0 );
$order = WC_Helper_Order::create_order();
$request = new WP_REST_Request( 'POST', '/wc/v2/orders/' . $order->get_id() );
$order = WC_Helper_Order::create_order();
$request = new WP_REST_Request( 'PUT', '/wc/v2/orders/' . $order->get_id() );
$request->set_body_params( array(
'payment_method' => 'test-update',
'billing' => array(
@ -308,6 +348,7 @@ class WC_Tests_API_Orders extends WC_REST_Unit_Test_Case {
) );
$response = $this->server->dispatch( $request );
$this->assertEquals( 401, $response->get_status() );
WC_Helper_Order::delete_order( $order->get_id() );
}
/**

View File

@ -69,11 +69,41 @@ class WC_Tests_Customer_Functions extends WC_Unit_Test_Case {
$order2 = new WC_Order;
$order2->save();
// Test download permissions
$prod_download = new WC_Product_Download;
$prod_download->set_file( plugin_dir_url( __FILE__ ) . '/assets/images/help.png' );
$prod_download->set_id( 'download' );
$product = new WC_Product_Simple;
$product->set_downloadable( 'yes' );
$product->set_downloads( array( $prod_download ) );
$product->save();
$order3 = new WC_Order;
$item = new WC_Order_Item_Product();
$item->set_props( array(
'product' => $product,
'quantity' => 1,
) );
$order3->set_billing_email( 'test@example.com' );
$order3->set_status( 'completed' );
$order3->add_item( $item );
$order3->save();
$downloads = wc_get_customer_available_downloads( $customer_id );
$this->assertEquals( 0, count( $downloads ) );
// Link orders that haven't been linked.
$linked = wc_update_new_customer_past_orders( $customer_id );
$this->assertEquals( 1, $linked );
$this->assertEquals( 2, $linked );
$order1 = wc_get_order( $order1->get_id() );
$this->assertEquals( $customer_id, $order1->get_customer_id() );
$order3 = wc_get_order( $order3->get_id() );
$this->assertEquals( $customer_id, $order3->get_customer_id() );
// Test download permissions.
$downloads = wc_get_customer_available_downloads( $customer_id );
$this->assertEquals( 1, count( $downloads ) );
// Don't link linked orders again.
$linked = wc_update_new_customer_past_orders( $customer_id );

View File

@ -1656,6 +1656,21 @@ class WC_Tests_CRUD_Orders extends WC_Unit_Test_Case {
$this->assertEquals( 4, $object->get_remaining_refund_items() );
}
/**
* Test that if an exception is thrown when creating a refund, the refund is deleted from database.
*/
function test_refund_exception() {
$order = WC_Helper_Order::create_order();
add_action( 'woocommerce_create_refund', array( $this, 'throwAnException' ) );
$refund = wc_create_refund( array(
'order_id' => $order->get_id(),
'amount' => $order->get_total(),
'line_items' => array(),
) );
remove_action( 'woocommerce_create_refund', array( $this, 'throwAnException' ) );
$this->assertEmpty( $order->get_refunds() );
}
/**
* Test apply_coupon and remove_coupon with a fixed discount coupon.
* @since 3.2.0

View File

@ -40,6 +40,7 @@ class WC_Tests_Deprecated_Hooks extends WC_Unit_Test_Case {
function setUp() {
add_filter( 'deprecated_function_trigger_error', '__return_false' );
add_filter( 'deprecated_hook_trigger_error', '__return_false' );
$this->handlers = WC()->deprecated_hook_handlers;
}

View File

@ -6,8 +6,6 @@
* Version: 3.3-dev
* Author: Automattic
* Author URI: https://woocommerce.com
* Requires at least: 4.5
* Tested up to: 4.7
*
* Text Domain: woocommerce
* Domain Path: /i18n/languages/