Merge branch 'master' into update/order-screen-refinements

This commit is contained in:
Mike Jolley 2017-12-04 13:44:27 +00:00
commit 5d42a64b73
57 changed files with 2193 additions and 1500 deletions

View File

@ -27,6 +27,22 @@
], ],
"post-update-cmd": [ "post-update-cmd": [
"WooCommerce\\GitHooks\\Hooks::postHooks" "WooCommerce\\GitHooks\\Hooks::postHooks"
],
"test": [
"phpunit"
],
"phpcs": [
"phpcs -s -p --standard=./phpcs.ruleset.xml"
],
"phpcbf": [
"phpcs -p --standard=./phpcs.ruleset.xml"
] ]
},
"extra": {
"scripts-description": {
"test": "Run unit tests",
"phpcs": "Analyze code against the WordPress coding standards with PHP_CodeSniffer",
"phpcbf": "Fix coding standards warnings/errors automatically with PHP Code Beautifier"
}
} }
} }

View File

@ -14,30 +14,30 @@ if ( ! defined( 'ABSPATH' ) ) {
} }
$states['IE'] = array( $states['IE'] = array(
'CW' => __( 'Carlow', 'woocommerce' ),
'CN' => __( 'Cavan', 'woocommerce' ),
'CE' => __( 'Clare', 'woocommerce' ), 'CE' => __( 'Clare', 'woocommerce' ),
'CK' => __( 'Cork', 'woocommerce' ), 'CK' => __( 'Cork', 'woocommerce' ),
'CN' => __( 'Cavan', 'woocommerce' ),
'CW' => __( 'Carlow', 'woocommerce' ),
'DL' => __( 'Donegal', 'woocommerce' ), 'DL' => __( 'Donegal', 'woocommerce' ),
'DN' => __( 'Dublin', 'woocommerce' ), 'DN' => __( 'Dublin', 'woocommerce' ),
'GY' => __( 'Galway', 'woocommerce' ), 'GY' => __( 'Galway', 'woocommerce' ),
'KY' => __( 'Kerry', 'woocommerce' ),
'KE' => __( 'Kildare', 'woocommerce' ), 'KE' => __( 'Kildare', 'woocommerce' ),
'KK' => __( 'Kilkenny', 'woocommerce' ), 'KK' => __( 'Kilkenny', 'woocommerce' ),
'KY' => __( 'Kerry', 'woocommerce' ), 'LS' => __( 'Laois', 'woocommerce' ),
'LM' => __( 'Leitrim', 'woocommerce' ),
'LK' => __( 'Limerick', 'woocommerce' ),
'LD' => __( 'Longford', 'woocommerce' ), 'LD' => __( 'Longford', 'woocommerce' ),
'LH' => __( 'Louth', 'woocommerce' ), 'LH' => __( 'Louth', 'woocommerce' ),
'LK' => __( 'Limerick', 'woocommerce' ), 'MO' => __( 'Mayo', 'woocommerce' ),
'LM' => __( 'Leitrim', 'woocommerce' ),
'LS' => __( 'Laois', 'woocommerce' ),
'MH' => __( 'Meath', 'woocommerce' ), 'MH' => __( 'Meath', 'woocommerce' ),
'MN' => __( 'Monaghan', 'woocommerce' ), 'MN' => __( 'Monaghan', 'woocommerce' ),
'MO' => __( 'Mayo', 'woocommerce' ),
'OY' => __( 'Offaly', 'woocommerce' ), 'OY' => __( 'Offaly', 'woocommerce' ),
'RN' => __( 'Roscommon', 'woocommerce' ), 'RN' => __( 'Roscommon', 'woocommerce' ),
'SO' => __( 'Sligo', 'woocommerce' ), 'SO' => __( 'Sligo', 'woocommerce' ),
'TY' => __( 'Tipperary', 'woocommerce' ), 'TY' => __( 'Tipperary', 'woocommerce' ),
'WD' => __( 'Waterford', 'woocommerce' ), 'WD' => __( 'Waterford', 'woocommerce' ),
'WH' => __( 'Westmeath', 'woocommerce' ), 'WH' => __( 'Westmeath', 'woocommerce' ),
'WW' => __( 'Wicklow', 'woocommerce' ),
'WX' => __( 'Wexford', 'woocommerce' ), 'WX' => __( 'Wexford', 'woocommerce' ),
'WW' => __( 'Wicklow', 'woocommerce' )
); );

View File

@ -14,51 +14,51 @@ if ( ! defined( 'ABSPATH' ) ) {
} }
$states['JP'] = array( $states['JP'] = array(
'JP01' => __( 'Hokkaido', 'woocommerce' ), 'JP01' => __( 'Hokkaido-dō', 'woocommerce' ),
'JP02' => __( 'Aomori', 'woocommerce' ), 'JP02' => __( 'Aomori-ken', 'woocommerce' ),
'JP03' => __( 'Iwate', 'woocommerce' ), 'JP03' => __( 'Iwate-ken', 'woocommerce' ),
'JP04' => __( 'Miyagi', 'woocommerce' ), 'JP04' => __( 'Miyagi-ken', 'woocommerce' ),
'JP05' => __( 'Akita', 'woocommerce' ), 'JP05' => __( 'Akita-ken', 'woocommerce' ),
'JP06' => __( 'Yamagata', 'woocommerce' ), 'JP06' => __( 'Yamagata-ken', 'woocommerce' ),
'JP07' => __( 'Fukushima', 'woocommerce' ), 'JP07' => __( 'Fukushima-ken', 'woocommerce' ),
'JP08' => __( 'Ibaraki', 'woocommerce' ), 'JP08' => __( 'Ibaraki-ken', 'woocommerce' ),
'JP09' => __( 'Tochigi', 'woocommerce' ), 'JP09' => __( 'Tochigi-ken', 'woocommerce' ),
'JP10' => __( 'Gunma', 'woocommerce' ), 'JP10' => __( 'Gunma-ken', 'woocommerce' ),
'JP11' => __( 'Saitama', 'woocommerce' ), 'JP11' => __( 'Saitama-ken', 'woocommerce' ),
'JP12' => __( 'Chiba', 'woocommerce' ), 'JP12' => __( 'Chiba-ken', 'woocommerce' ),
'JP13' => __( 'Tokyo', 'woocommerce' ), 'JP13' => __( 'Tokyo-to', 'woocommerce' ),
'JP14' => __( 'Kanagawa', 'woocommerce' ), 'JP14' => __( 'Kanagawa-ken', 'woocommerce' ),
'JP15' => __( 'Niigata', 'woocommerce' ), 'JP15' => __( 'Niigata-ken', 'woocommerce' ),
'JP16' => __( 'Toyama', 'woocommerce' ), 'JP16' => __( 'Toyama-ken', 'woocommerce' ),
'JP17' => __( 'Ishikawa', 'woocommerce' ), 'JP17' => __( 'Ishikawa-ken', 'woocommerce' ),
'JP18' => __( 'Fukui', 'woocommerce' ), 'JP18' => __( 'Fukui-ken', 'woocommerce' ),
'JP19' => __( 'Yamanashi', 'woocommerce' ), 'JP19' => __( 'Yamanashi-ken', 'woocommerce' ),
'JP20' => __( 'Nagano', 'woocommerce' ), 'JP20' => __( 'Nagano-ken', 'woocommerce' ),
'JP21' => __( 'Gifu', 'woocommerce' ), 'JP21' => __( 'Gifu-ken', 'woocommerce' ),
'JP22' => __( 'Shizuoka', 'woocommerce' ), 'JP22' => __( 'Shizuoka-ken', 'woocommerce' ),
'JP23' => __( 'Aichi', 'woocommerce' ), 'JP23' => __( 'Aichi-ken', 'woocommerce' ),
'JP24' => __( 'Mie', 'woocommerce' ), 'JP24' => __( 'Mie-ken', 'woocommerce' ),
'JP25' => __( 'Shiga', 'woocommerce' ), 'JP25' => __( 'Shiga-ken', 'woocommerce' ),
'JP26' => __( 'Kyoto', 'woocommerce' ), 'JP26' => __( 'Kyoto-fu', 'woocommerce' ),
'JP27' => __( 'Osaka', 'woocommerce' ), 'JP27' => __( 'Osaka-fu', 'woocommerce' ),
'JP28' => __( 'Hyogo', 'woocommerce' ), 'JP28' => __( 'Hyogo-ken', 'woocommerce' ),
'JP29' => __( 'Nara', 'woocommerce' ), 'JP29' => __( 'Nara-ken', 'woocommerce' ),
'JP30' => __( 'Wakayama', 'woocommerce' ), 'JP30' => __( 'Wakayama-ken', 'woocommerce' ),
'JP31' => __( 'Tottori', 'woocommerce' ), 'JP31' => __( 'Tottori-ken', 'woocommerce' ),
'JP32' => __( 'Shimane', 'woocommerce' ), 'JP32' => __( 'Shimane-ken', 'woocommerce' ),
'JP33' => __( 'Okayama', 'woocommerce' ), 'JP33' => __( 'Okayama-ken', 'woocommerce' ),
'JP34' => __( 'Hiroshima', 'woocommerce' ), 'JP34' => __( 'Hiroshima-ken', 'woocommerce' ),
'JP35' => __( 'Yamaguchi', 'woocommerce' ), 'JP35' => __( 'Yamaguchi-ken', 'woocommerce' ),
'JP36' => __( 'Tokushima', 'woocommerce' ), 'JP36' => __( 'Tokushima-ken', 'woocommerce' ),
'JP37' => __( 'Kagawa', 'woocommerce' ), 'JP37' => __( 'Kagawa-ken', 'woocommerce' ),
'JP38' => __( 'Ehime', 'woocommerce' ), 'JP38' => __( 'Ehime-ken', 'woocommerce' ),
'JP39' => __( 'Kochi', 'woocommerce' ), 'JP39' => __( 'Kochi-ken', 'woocommerce' ),
'JP40' => __( 'Fukuoka', 'woocommerce' ), 'JP40' => __( 'Fukuoka-ken', 'woocommerce' ),
'JP41' => __( 'Saga', 'woocommerce' ), 'JP41' => __( 'Saga-ken', 'woocommerce' ),
'JP42' => __( 'Nagasaki', 'woocommerce' ), 'JP42' => __( 'Nagasaki-ken', 'woocommerce' ),
'JP43' => __( 'Kumamoto', 'woocommerce' ), 'JP43' => __( 'Kumamoto-ken', 'woocommerce' ),
'JP44' => __( 'Oita', 'woocommerce' ), 'JP44' => __( 'Oita-ken', 'woocommerce' ),
'JP45' => __( 'Miyazaki', 'woocommerce' ), 'JP45' => __( 'Miyazaki-ken', 'woocommerce' ),
'JP46' => __( 'Kagoshima', 'woocommerce' ), 'JP46' => __( 'Kagoshima-ken', 'woocommerce' ),
'JP47' => __( 'Okinawa', 'woocommerce' ), 'JP47' => __( 'Okinawa-ken', 'woocommerce' ),
); );

View File

@ -1,4 +1,12 @@
<?php <?php
/**
* Abstract deprecated hooks
*
* @package WooCommerce\Abstracts
* @since 3.0.0
* @version 3.3.0
*/
if ( ! defined( 'ABSPATH' ) ) { if ( ! defined( 'ABSPATH' ) ) {
exit; 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. * 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. * Based on the WCS_Hook_Deprecator class by Prospress.
*
* @since 3.0.0
*/ */
abstract class WC_Deprecated_Hooks { abstract class WC_Deprecated_Hooks {
@ -19,6 +25,13 @@ abstract class WC_Deprecated_Hooks {
*/ */
protected $deprecated_hooks = array(); protected $deprecated_hooks = array();
/**
* Array of versions on each hook has been deprecated.
*
* @var array
*/
protected $deprecated_version = array();
/** /**
* Constructor. * Constructor.
*/ */
@ -30,14 +43,14 @@ abstract class WC_Deprecated_Hooks {
/** /**
* Hook into the new hook so we can handle deprecated hooks once fired. * 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. * Get old hooks to map to new hook.
* *
* @param string $new_hook * @param string $new_hook New hook name.
* @return array * @return array
*/ */
public function get_old_hooks( $new_hook ) { 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. * If the old hook is in-use, trigger it.
* *
* @param string $new_hook * @param string $new_hook New hook name.
* @param string $old_hook * @param string $old_hook Old hook name.
* @param array $new_callback_args * @param array $new_callback_args New callback args.
* @param mixed $return_value * @param mixed $return_value Returned value.
* @return mixed * @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. * Display a deprecated notice for old hooks.
* *
* @param string $old_hook * @param string $old_hook Old hook.
* @param string $new_hook * @param string $new_hook New hook.
*/ */
protected function display_notice( $old_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. * Fire off a legacy hook with it's args.
* *
* @param string $old_hook * @param string $old_hook Old hook name.
* @param array $new_callback_args * @param array $new_callback_args New callback args.
* @return mixed * @return mixed
*/ */
abstract protected function trigger_hook( $old_hook, $new_callback_args ); 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 = '' ) { public function get_subtotal_to_display( $compound = false, $tax_display = '' ) {
$tax_display = $tax_display ? $tax_display : get_option( 'woocommerce_tax_display_cart' ); $tax_display = $tax_display ? $tax_display : get_option( 'woocommerce_tax_display_cart' );
$subtotal = 0; $subtotal = 0;
if ( ! $compound ) { if ( ! $compound ) {
foreach ( $this->get_items() as $item ) { foreach ( $this->get_items() as $item ) {
$subtotal += $item->get_subtotal(); $subtotal += $item->get_subtotal();

View File

@ -83,11 +83,11 @@ class WC_Admin_Settings {
self::add_message( __( 'Your settings have been saved.', 'woocommerce' ) ); self::add_message( __( 'Your settings have been saved.', 'woocommerce' ) );
self::check_download_folder_protection(); self::check_download_folder_protection();
// Clear any unwanted data and flush rules // Clear any unwanted data and flush rules on next init.
add_option( 'woocommerce_queue_flush_rewrite_rules', 'true' );
delete_transient( 'woocommerce_cache_excluded_uris' ); delete_transient( 'woocommerce_cache_excluded_uris' );
WC()->query->init_query_vars(); WC()->query->init_query_vars();
WC()->query->add_endpoints(); WC()->query->add_endpoints();
wp_schedule_single_event( time(), 'woocommerce_flush_rewrite_rules' );
do_action( 'woocommerce_settings_saved' ); do_action( 'woocommerce_settings_saved' );
} }

View File

@ -115,7 +115,7 @@ class WC_Admin_Status {
} }
// Bulk actions // Bulk actions
if ( isset( $_GET['action'] ) && isset( $_GET['log'] ) ) { if ( isset( $_REQUEST['action'] ) && isset( $_REQUEST['log'] ) ) {
self::log_table_bulk_actions(); self::log_table_bulk_actions();
} }
@ -315,9 +315,9 @@ class WC_Admin_Status {
wp_die( __( 'Action failed. Please refresh the page and retry.', 'woocommerce' ) ); wp_die( __( 'Action failed. Please refresh the page and retry.', 'woocommerce' ) );
} }
$log_ids = array_map( 'absint', (array) $_GET['log'] ); $log_ids = array_map( 'absint', (array) $_REQUEST['log'] );
if ( 'delete' === $_GET['action'] || 'delete' === $_GET['action2'] ) { if ( 'delete' === $_REQUEST['action'] || 'delete' === $_REQUEST['action2'] ) {
WC_Log_Handler_DB::delete( $log_ids ); WC_Log_Handler_DB::delete( $log_ids );
wp_safe_redirect( esc_url_raw( admin_url( 'admin.php?page=wc-status&tab=logs' ) ) ); wp_safe_redirect( esc_url_raw( admin_url( 'admin.php?page=wc-status&tab=logs' ) ) );
exit(); exit();

View File

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

View File

@ -232,7 +232,7 @@ class WC_Admin_List_Table_Products extends WC_Admin_List_Table {
$termlist[] = '<a href="' . esc_url( admin_url( 'edit.php?product_cat=' . $term->slug . '&post_type=product' ) ) . ' ">' . esc_html( $term->name ) . '</a>'; $termlist[] = '<a href="' . esc_url( admin_url( 'edit.php?product_cat=' . $term->slug . '&post_type=product' ) ) . ' ">' . esc_html( $term->name ) . '</a>';
} }
echo implode( ', ', $termlist ); // WPCS: XSS ok. echo apply_filters( 'woocommerce_admin_product_term_list', implode( ', ', $termlist ), 'product_cat', $this->object->get_id(), $termlist, $terms ); // WPCS: XSS ok.
} }
} }
@ -248,7 +248,7 @@ class WC_Admin_List_Table_Products extends WC_Admin_List_Table {
$termlist[] = '<a href="' . esc_url( admin_url( 'edit.php?product_tag=' . $term->slug . '&post_type=product' ) ) . ' ">' . esc_html( $term->name ) . '</a>'; $termlist[] = '<a href="' . esc_url( admin_url( 'edit.php?product_tag=' . $term->slug . '&post_type=product' ) ) . ' ">' . esc_html( $term->name ) . '</a>';
} }
echo implode( ', ', $termlist ); // WPCS: XSS ok. echo apply_filters( 'woocommerce_admin_product_term_list', implode( ', ', $termlist ), 'product_tag', $this->object->get_id(), $termlist, $terms ); // WPCS: XSS ok.
} }
} }
@ -298,22 +298,29 @@ class WC_Admin_List_Table_Products extends WC_Admin_List_Table {
* Render any custom filters and search inputs for the list table. * Render any custom filters and search inputs for the list table.
*/ */
protected function render_filters() { 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. // Category Filtering.
$current_product_type = isset( $_REQUEST['product_type'] ) ? wc_clean( wp_unslash( $_REQUEST['product_type'] ) ) : false; // WPCS: input var ok, sanitization ok. $categories_count = (int) wp_count_terms( 'product_cat' );
// @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
$terms = get_terms( 'product_type' ); if ( $categories_count <= apply_filters( 'woocommerce_product_category_filter_threshold', 100 ) ) {
$output = '<select name="product_type" id="dropdown_product_type">'; wc_product_dropdown_categories( array(
$output .= '<option value="">' . __( 'Filter by product type', 'woocommerce' ) . '</option>'; '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 ) { foreach ( $terms as $term ) {
$output .= '<option value="' . sanitize_title( $term->name ) . '" '; $output .= '<option value="' . sanitize_title( $term->name ) . '" ';

View File

@ -658,8 +658,12 @@ class WC_Admin_Report {
return; return;
} }
if ( ! isset( $_GET['wc_reports_nonce'] ) || ! wp_verify_nonce( $_GET['wc_reports_nonce'], 'custom_range' ) ) { if ( ! isset( $_GET['wc_reports_nonce'] ) || ! wp_verify_nonce( sanitize_key( $_GET['wc_reports_nonce'] ), 'custom_range' ) ) { // WPCS: input var ok, CSRF ok.
wp_safe_redirect( remove_query_arg( array( 'start_date', 'end_date', 'range', 'wc_reports_nonce' ) ) ); 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; exit;
} }
} }

View File

@ -185,7 +185,7 @@ class WC_REST_Product_Categories_Controller extends WC_REST_Product_Categories_V
'format' => 'uri', 'format' => 'uri',
'context' => array( 'view', 'edit' ), 'context' => array( 'view', 'edit' ),
), ),
'name' => array( 'title' => array(
'description' => __( 'Image name.', 'woocommerce' ), 'description' => __( 'Image name.', 'woocommerce' ),
'type' => 'string', 'type' => 'string',
'context' => array( 'view', 'edit' ), 'context' => array( 'view', 'edit' ),

View File

@ -240,7 +240,7 @@ class WC_REST_Product_Categories_V1_Controller extends WC_REST_Terms_Controller
'format' => 'uri', 'format' => 'uri',
'context' => array( 'view', 'edit' ), 'context' => array( 'view', 'edit' ),
), ),
'name' => array( 'title' => array(
'description' => __( 'Image name.', 'woocommerce' ), 'description' => __( 'Image name.', 'woocommerce' ),
'type' => 'string', 'type' => 'string',
'context' => array( 'view', 'edit' ), 'context' => array( 'view', 'edit' ),

View File

@ -378,7 +378,7 @@ class WC_REST_Report_Sales_V1_Controller extends WC_REST_Controller {
), ),
'date_min' => array( 'date_min' => array(
/* translators: %s: date format */ /* translators: %s: date format */
'description' => sprintf( __( 'Return sales for a specific start date, the date need to be in the %s format.', 'woocommerce' ), 'YYYY-MM-AA' ), 'description' => sprintf( __( 'Return sales for a specific start date, the date need to be in the %s format.', 'woocommerce' ), 'YYYY-MM-DD' ),
'type' => 'string', 'type' => 'string',
'format' => 'date', 'format' => 'date',
'validate_callback' => 'wc_rest_validate_reports_request_arg', 'validate_callback' => 'wc_rest_validate_reports_request_arg',
@ -386,7 +386,7 @@ class WC_REST_Report_Sales_V1_Controller extends WC_REST_Controller {
), ),
'date_max' => array( 'date_max' => array(
/* translators: %s: date format */ /* translators: %s: date format */
'description' => sprintf( __( 'Return sales for a specific end date, the date need to be in the %s format.', 'woocommerce' ), 'YYYY-MM-AA' ), 'description' => sprintf( __( 'Return sales for a specific end date, the date need to be in the %s format.', 'woocommerce' ), 'YYYY-MM-DD' ),
'type' => 'string', 'type' => 'string',
'format' => 'date', 'format' => 'date',
'validate_callback' => 'wc_rest_validate_reports_request_arg', 'validate_callback' => 'wc_rest_validate_reports_request_arg',

View File

@ -1664,9 +1664,6 @@ class WC_AJAX {
wp_send_json_success( $response_data ); wp_send_json_success( $response_data );
} catch ( Exception $e ) { } 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() ) ); wp_send_json_error( array( 'error' => $e->getMessage() ) );
} }
} }

View File

@ -423,7 +423,7 @@ final class WC_Cart_Totals {
* @return object * @return object
*/ */
protected function remove_item_base_taxes( $item ) { 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' ) ); $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. // Work out a new base price without the shop's base tax.
@ -449,7 +449,7 @@ final class WC_Cart_Totals {
* @return object * @return object
*/ */
protected function adjust_non_base_location_price( $item ) { 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' ) ); $base_tax_rates = WC_Tax::get_base_tax_rates( $item->product->get_tax_class( 'unfiltered' ) );
if ( $item->tax_rates !== $base_tax_rates ) { if ( $item->tax_rates !== $base_tax_rates ) {

View File

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

View File

@ -1,12 +1,18 @@
<?php <?php
/**
* Deprecated action hooks
*
* @package WooCommerce\Abstracts
* @since 3.0.0
* @version 3.3.0
*/
if ( ! defined( 'ABSPATH' ) ) { if ( ! defined( 'ABSPATH' ) ) {
exit; exit;
} }
/** /**
* Handles deprecation notices and triggering of legacy action hooks. * Handles deprecation notices and triggering of legacy action hooks.
*
* @since 3.0.0
*/ */
class WC_Deprecated_Action_Hooks extends WC_Deprecated_Hooks { class WC_Deprecated_Action_Hooks extends WC_Deprecated_Hooks {
@ -16,7 +22,7 @@ class WC_Deprecated_Action_Hooks extends WC_Deprecated_Hooks {
* @var array * @var array
*/ */
protected $deprecated_hooks = array( protected $deprecated_hooks = array(
'woocommerce_new_order_item' => array( 'woocommerce_new_order_item' => array(
'woocommerce_order_add_shipping', 'woocommerce_order_add_shipping',
'woocommerce_order_add_coupon', 'woocommerce_order_add_coupon',
'woocommerce_order_add_tax', '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_item_meta',
'woocommerce_add_order_fee_meta', 'woocommerce_add_order_fee_meta',
), ),
'woocommerce_update_order_item' => array( 'woocommerce_update_order_item' => array(
'woocommerce_order_edit_product', 'woocommerce_order_edit_product',
'woocommerce_order_update_coupon', 'woocommerce_order_update_coupon',
'woocommerce_order_update_shipping', 'woocommerce_order_update_shipping',
'woocommerce_order_update_fee', 'woocommerce_order_update_fee',
'woocommerce_order_update_tax', 'woocommerce_order_update_tax',
), ),
'woocommerce_new_payment_token' => 'woocommerce_payment_token_created', 'woocommerce_new_payment_token' => 'woocommerce_payment_token_created',
'woocommerce_new_product_variation' => 'woocommerce_create_product_variation', 'woocommerce_new_product_variation' => 'woocommerce_create_product_variation',
'woocommerce_order_details_after_order_table_items' => 'woocommerce_order_items_table' '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. * 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 ) { public function hook_in( $hook_name ) {
add_action( $hook_name, array( $this, 'maybe_handle_deprecated_hook' ), -1000, 8 ); 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. * If the old hook is in-use, trigger it.
* *
* @param string $new_hook * @param string $new_hook New hook name.
* @param string $old_hook * @param string $old_hook Old hook name.
* @param array $new_callback_args * @param array $new_callback_args New callback args.
* @param mixed $return_value * @param mixed $return_value Returned value.
* @return mixed * @return mixed
*/ */
public function handle_deprecated_hook( $new_hook, $old_hook, $new_callback_args, $return_value ) { 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. * Fire off a legacy hook with it's args.
* *
* @param string $old_hook * @param string $old_hook Old hook name.
* @param array $new_callback_args * @param array $new_callback_args New callback args.
* @return mixed * @return mixed
*/ */
protected function trigger_hook( $old_hook, $new_callback_args ) { protected function trigger_hook( $old_hook, $new_callback_args ) {
switch ( $old_hook ) { switch ( $old_hook ) {
case 'woocommerce_order_add_shipping' : case 'woocommerce_order_add_shipping':
case 'woocommerce_order_add_fee' : case 'woocommerce_order_add_fee':
$item_id = $new_callback_args[0]; $item_id = $new_callback_args[0];
$item = $new_callback_args[1]; $item = $new_callback_args[1];
$order_id = $new_callback_args[2]; $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 ); do_action( $old_hook, $order_id, $item_id, $item );
} }
break; break;
case 'woocommerce_order_add_coupon' : case 'woocommerce_order_add_coupon':
$item_id = $new_callback_args[0]; $item_id = $new_callback_args[0];
$item = $new_callback_args[1]; $item = $new_callback_args[1];
$order_id = $new_callback_args[2]; $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() ); do_action( $old_hook, $order_id, $item_id, $item->get_code(), $item->get_discount(), $item->get_discount_tax() );
} }
break; break;
case 'woocommerce_order_add_tax' : case 'woocommerce_order_add_tax':
$item_id = $new_callback_args[0]; $item_id = $new_callback_args[0];
$item = $new_callback_args[1]; $item = $new_callback_args[1];
$order_id = $new_callback_args[2]; $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() ); do_action( $old_hook, $order_id, $item_id, $item->get_rate_id(), $item->get_tax_total(), $item->get_shipping_tax_total() );
} }
break; break;
case 'woocommerce_add_shipping_order_item' : case 'woocommerce_add_shipping_order_item':
$item_id = $new_callback_args[0]; $item_id = $new_callback_args[0];
$item = $new_callback_args[1]; $item = $new_callback_args[1];
$order_id = $new_callback_args[2]; $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 ); do_action( $old_hook, $order_id, $item_id, $item->legacy_package_key );
} }
break; break;
case 'woocommerce_add_order_item_meta' : case 'woocommerce_add_order_item_meta':
$item_id = $new_callback_args[0]; $item_id = $new_callback_args[0];
$item = $new_callback_args[1]; $item = $new_callback_args[1];
$order_id = $new_callback_args[2]; $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 ); do_action( $old_hook, $item_id, $item->legacy_values, $item->legacy_cart_item_key );
} }
break; break;
case 'woocommerce_add_order_fee_meta' : case 'woocommerce_add_order_fee_meta':
$item_id = $new_callback_args[0]; $item_id = $new_callback_args[0];
$item = $new_callback_args[1]; $item = $new_callback_args[1];
$order_id = $new_callback_args[2]; $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 ); do_action( $old_hook, $order_id, $item_id, $item->legacy_fee, $item->legacy_fee_key );
} }
break; break;
case 'woocommerce_order_edit_product' : case 'woocommerce_order_edit_product':
$item_id = $new_callback_args[0]; $item_id = $new_callback_args[0];
$item = $new_callback_args[1]; $item = $new_callback_args[1];
$order_id = $new_callback_args[2]; $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() ); do_action( $old_hook, $order_id, $item_id, $item, $item->get_product() );
} }
break; break;
case 'woocommerce_order_update_coupon' : case 'woocommerce_order_update_coupon':
case 'woocommerce_order_update_shipping' : case 'woocommerce_order_update_shipping':
case 'woocommerce_order_update_fee' : case 'woocommerce_order_update_fee':
case 'woocommerce_order_update_tax' : case 'woocommerce_order_update_tax':
if ( ! is_a( $item, 'WC_Order_Item_Product' ) ) { if ( ! is_a( $item, 'WC_Order_Item_Product' ) ) {
do_action( $old_hook, $order_id, $item_id, $item ); do_action( $old_hook, $order_id, $item_id, $item );
} }
break; break;
default : default:
do_action_ref_array( $old_hook, $new_callback_args ); do_action_ref_array( $old_hook, $new_callback_args );
break; break;
} }

View File

@ -1,12 +1,18 @@
<?php <?php
/**
* Deprecated filter hooks
*
* @package WooCommerce\Abstracts
* @since 3.0.0
* @version 3.3.0
*/
if ( ! defined( 'ABSPATH' ) ) { if ( ! defined( 'ABSPATH' ) ) {
exit; exit;
} }
/** /**
* Handles deprecation notices and triggering of legacy filter hooks. * Handles deprecation notices and triggering of legacy filter hooks
*
* @since 3.0.0
*/ */
class WC_Deprecated_Filter_Hooks extends WC_Deprecated_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', '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. * 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 ) { public function hook_in( $hook_name ) {
add_filter( $hook_name, array( $this, 'maybe_handle_deprecated_hook' ), -1000, 8 ); 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. * If the old hook is in-use, trigger it.
* *
* @param string $new_hook * @param string $new_hook New hook name.
* @param string $old_hook * @param string $old_hook Old hook name.
* @param array $new_callback_args * @param array $new_callback_args New callback args.
* @param mixed $return_value * @param mixed $return_value Returned value.
* @return mixed * @return mixed
*/ */
public function handle_deprecated_hook( $new_hook, $old_hook, $new_callback_args, $return_value ) { 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. * Fire off a legacy hook with it's args.
* *
* @param string $old_hook * @param string $old_hook Old hook name.
* @param array $new_callback_args * @param array $new_callback_args New callback args.
* @return mixed * @return mixed
*/ */
protected function trigger_hook( $old_hook, $new_callback_args ) { protected function trigger_hook( $old_hook, $new_callback_args ) {

View File

@ -974,7 +974,7 @@ class WC_Form_Handler {
$redirect = wc_get_page_permalink( 'myaccount' ); $redirect = wc_get_page_permalink( 'myaccount' );
} }
wp_redirect( wp_validate_redirect( apply_filters( 'woocommerce_login_redirect', $redirect, $user ), wc_get_page_permalink( 'myaccount' ) ) ); wp_redirect( wp_validate_redirect( apply_filters( 'woocommerce_login_redirect', remove_query_arg( 'wc_error', $redirect ), $user ), wc_get_page_permalink( 'myaccount' ) ) );
exit; exit;
} }
} catch ( Exception $e ) { } catch ( Exception $e ) {

View File

@ -21,11 +21,21 @@ if ( ! defined( 'ABSPATH' ) ) {
*/ */
class WC_Geolocation { 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'; 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( private static $ip_lookup_apis = array(
'icanhazip' => 'http://icanhazip.com', 'icanhazip' => 'http://icanhazip.com',
'ipify' => 'http://api.ipify.org/', 'ipify' => 'http://api.ipify.org/',
@ -35,7 +45,11 @@ class WC_Geolocation {
'ip.appspot' => 'http://ip.appspot.com', '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( private static $geoip_apis = array(
'freegeoip' => 'https://freegeoip.net/json/%s', 'freegeoip' => 'https://freegeoip.net/json/%s',
'ipinfo.io' => 'https://ipinfo.io/%s/json', 'ipinfo.io' => 'https://ipinfo.io/%s/json',
@ -46,7 +60,7 @@ class WC_Geolocation {
* Hook in tabs. * Hook in tabs.
*/ */
public static function init() { 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 ) ) { 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' ) ); 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. * 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 * @return string
*/ */
public static function maybe_update_database( $new_value, $old_value ) { public static function maybe_update_database( $new_value, $old_value ) {
@ -66,46 +81,20 @@ class WC_Geolocation {
return $new_value; 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. * Get current user IP Address.
*
* @return string * @return string
*/ */
public static function get_ip_address() { public static function get_ip_address() {
if ( isset( $_SERVER['HTTP_X_REAL_IP'] ) ) { if ( isset( $_SERVER['HTTP_X_REAL_IP'] ) ) { // WPCS: input var ok, CSRF ok.
return $_SERVER['HTTP_X_REAL_IP']; return sanitize_text_field( wp_unslash( $_SERVER['HTTP_X_REAL_IP'] ) ); // WPCS: input var ok, CSRF ok.
} elseif ( isset( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) { } 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 // 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. // 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'] ) ) ) ); 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'] ) ) { } elseif ( isset( $_SERVER['REMOTE_ADDR'] ) ) { // @codingStandardsIgnoreLine
return $_SERVER['REMOTE_ADDR']; return sanitize_text_field( wp_unslash( $_SERVER['REMOTE_ADDR'] ) ); // @codingStandardsIgnoreLine
} }
return ''; return '';
} }
@ -114,6 +103,7 @@ class WC_Geolocation {
* Get user IP Address using an external service. * Get user IP Address using an external service.
* This is used mainly as a fallback for users on localhost where * This is used mainly as a fallback for users on localhost where
* get_ip_address() will be a local IP and non-geolocatable. * get_ip_address() will be a local IP and non-geolocatable.
*
* @return string * @return string
*/ */
public static function get_external_ip_address() { public static function get_external_ip_address() {
@ -148,8 +138,9 @@ class WC_Geolocation {
/** /**
* Geolocate an IP address. * 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). * @param bool $api_fallback If true, uses geolocation APIs if the database file doesn't exist (can be slower).
* @return array * @return array
*/ */
@ -158,19 +149,19 @@ class WC_Geolocation {
$country_code = apply_filters( 'woocommerce_geolocate_ip', false, $ip_address, $fallback, $api_fallback ); $country_code = apply_filters( 'woocommerce_geolocate_ip', false, $ip_address, $fallback, $api_fallback );
if ( false === $country_code ) { if ( false === $country_code ) {
// If GEOIP is enabled in CloudFlare, we can use that (Settings -> CloudFlare Settings -> Settings Overview) // If GEOIP is enabled in CloudFlare, we can use that (Settings -> CloudFlare Settings -> Settings Overview).
if ( ! empty( $_SERVER['HTTP_CF_IPCOUNTRY'] ) ) { if ( ! empty( $_SERVER['HTTP_CF_IPCOUNTRY'] ) ) { // WPCS: input var ok, CSRF ok.
$country_code = sanitize_text_field( strtoupper( $_SERVER['HTTP_CF_IPCOUNTRY'] ) ); $country_code = strtoupper( sanitize_text_field( wp_unslash( $_SERVER['HTTP_CF_IPCOUNTRY'] ) ) ); // WPCS: input var ok, CSRF ok.
// WP.com VIP has a variable available. } elseif ( ! empty( $_SERVER['GEOIP_COUNTRY_CODE'] ) ) { // WPCS: input var ok, CSRF ok.
} elseif ( ! empty( $_SERVER['GEOIP_COUNTRY_CODE'] ) ) { // WP.com VIP has a variable available.
$country_code = sanitize_text_field( strtoupper( $_SERVER['GEOIP_COUNTRY_CODE'] ) ); $country_code = strtoupper( sanitize_text_field( wp_unslash( $_SERVER['GEOIP_COUNTRY_CODE'] ) ) ); // WPCS: input var ok, CSRF ok.
// VIP Go has a variable available also. } elseif ( ! empty( $_SERVER['HTTP_X_COUNTRY_CODE'] ) ) { // WPCS: input var ok, CSRF ok.
} elseif ( ! empty( $_SERVER['HTTP_X_COUNTRY_CODE'] ) ) { // VIP Go has a variable available also.
$country_code = sanitize_text_field( strtoupper( $_SERVER['HTTP_X_COUNTRY_CODE'] ) ); $country_code = strtoupper( sanitize_text_field( wp_unslash( $_SERVER['HTTP_X_COUNTRY_CODE'] ) ) ); // WPCS: input var ok, CSRF ok.
} else { } else {
$ip_address = $ip_address ? $ip_address : self::get_ip_address(); $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' ); $database = self::get_local_database_path( 'v6' );
} else { } else {
$database = self::get_local_database_path(); $database = self::get_local_database_path();
@ -185,7 +176,7 @@ class WC_Geolocation {
} }
if ( ! $country_code && $fallback ) { 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 ); return self::geolocate_ip( self::get_external_ip_address(), false, $api_fallback );
} }
} }
@ -199,11 +190,12 @@ class WC_Geolocation {
/** /**
* Path to our local db. * Path to our local db.
* @param string $version *
* @param string $version Version.
* @return string * @return string
*/ */
public static function get_local_database_path( $version = 'v4' ) { public static function get_local_database_path( $version = 'v4' ) {
$version = ( 'v4' == $version ) ? '' : 'v6'; $version = 'v4' === $version ? '' : 'v6';
$upload_dir = wp_upload_dir(); $upload_dir = wp_upload_dir();
return apply_filters( 'woocommerce_geolocation_local_database_path', $upload_dir['basedir'] . '/GeoIP' . $version . '.dat', $version ); return apply_filters( 'woocommerce_geolocation_local_database_path', $upload_dir['basedir'] . '/GeoIP' . $version . '.dat', $version );
@ -220,7 +212,7 @@ class WC_Geolocation {
return; return;
} }
require_once( ABSPATH . 'wp-admin/includes/file.php' ); require_once ABSPATH . 'wp-admin/includes/file.php';
$tmp_databases = array( $tmp_databases = array(
'v4' => download_url( self::GEOLITE_DB ), 'v4' => download_url( self::GEOLITE_DB ),
@ -229,20 +221,20 @@ class WC_Geolocation {
foreach ( $tmp_databases as $tmp_database_version => $tmp_database_path ) { foreach ( $tmp_databases as $tmp_database_version => $tmp_database_path ) {
if ( ! is_wp_error( $tmp_database_path ) ) { if ( ! is_wp_error( $tmp_database_path ) ) {
$gzhandle = @gzopen( $tmp_database_path, 'r' ); $gzhandle = @gzopen( $tmp_database_path, 'r' ); // @codingStandardsIgnoreLine
$handle = @fopen( self::get_local_database_path( $tmp_database_version ), 'w' ); $handle = @fopen( self::get_local_database_path( $tmp_database_version ), 'w' ); // @codingStandardsIgnoreLine
if ( $gzhandle && $handle ) { if ( $gzhandle && $handle ) {
while ( $string = gzread( $gzhandle, 4096 ) ) { while ( $string = gzread( $gzhandle, 4096 ) ) { // @codingStandardsIgnoreLine
fwrite( $handle, $string, strlen( $string ) ); fwrite( $handle, $string, strlen( $string ) ); // @codingStandardsIgnoreLine
} }
gzclose( $gzhandle ); gzclose( $gzhandle );
$s_array = fstat( $handle ); $s_array = fstat( $handle );
fclose( $handle ); fclose( $handle ); // @codingStandardsIgnoreLine
if ( ! isset( $s_array['size'] ) || 0 === $s_array['size'] ) { if ( ! isset( $s_array['size'] ) || 0 === $s_array['size'] ) {
$logger->notice( 'Empty database file, deleting local copy.', array( 'source' => 'geolocation' ) ); $logger->notice( 'Empty database file, deleting local copy.', array( 'source' => 'geolocation' ) );
// Delete empty DB, we do not want to keep empty files around. // 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. // Reschedule download of DB.
wp_clear_scheduled_hook( 'woocommerce_geoip_updater' ); wp_clear_scheduled_hook( 'woocommerce_geoip_updater' );
wp_schedule_event( strtotime( 'first tuesday of next month' ), 'monthly', 'woocommerce_geoip_updater' ); wp_schedule_event( strtotime( 'first tuesday of next month' ), 'monthly', 'woocommerce_geoip_updater' );
@ -250,7 +242,7 @@ class WC_Geolocation {
} else { } else {
$logger->notice( 'Unable to open database file', array( 'source' => 'geolocation' ) ); $logger->notice( 'Unable to open database file', array( 'source' => 'geolocation' ) );
} }
@unlink( $tmp_database_path ); @unlink( $tmp_database_path ); // @codingStandardsIgnoreLine
} else { } else {
$logger->notice( $logger->notice(
'Unable to download GeoIP Database: ' . $tmp_database_path->get_error_message(), '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. * Use MAXMIND GeoLite database to geolocation the user.
* @param string $ip_address *
* @param string $ip_address IP address.
* @return string * @return string
*/ */
private static function geolocate_via_db( $ip_address ) { private static function geolocate_via_db( $ip_address ) {
if ( ! class_exists( 'WC_Geo_IP', false ) ) { 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(); $gi = new WC_Geo_IP();
if ( self::is_IPv6( $ip_address ) ) { if ( self::is_ipv6( $ip_address ) ) {
$database = self::get_local_database_path( 'v6' ); $database = self::get_local_database_path( 'v6' );
if ( ! self::get_file_size( $database ) ) { if ( ! self::get_file_size( $database ) ) {
return false; return false;
@ -301,14 +294,14 @@ class WC_Geolocation {
* @return bool|int * @return bool|int
*/ */
private static function get_file_size( $filename ) { private static function get_file_size( $filename ) {
$handle = @fopen( $filename, 'r' ); $handle = @fopen( $filename, 'r' ); // @codingStandardsIgnoreLine
$s_array = fstat( $handle ); $s_array = fstat( $handle ); // @codingStandardsIgnoreLine
@fclose( $handle ); @fclose( $handle ); // @codingStandardsIgnoreLine
if ( ! isset( $s_array['size'] ) || 0 === $s_array['size'] ) { if ( ! isset( $s_array['size'] ) || 0 === $s_array['size'] ) {
$logger = wc_get_logger(); $logger = wc_get_logger();
$logger->notice( 'Empty database file, deleting local copy.', array( 'source' => 'geolocation' ) ); $logger->notice( 'Empty database file, deleting local copy.', array( 'source' => 'geolocation' ) );
// Delete the file as we do not want to keep empty files around. // Delete the file as we do not want to keep empty files around.
@unlink( $filename ); @unlink( $filename ); // @codingStandardsIgnoreLine
return false; return false;
} }
return $s_array['size']; return $s_array['size'];
@ -316,7 +309,8 @@ class WC_Geolocation {
/** /**
* Use APIs to Geolocate the user. * Use APIs to Geolocate the user.
* @param string $ip_address *
* @param string $ip_address IP address.
* @return string|bool * @return string|bool
*/ */
private static function geolocate_via_api( $ip_address ) { private static function geolocate_via_api( $ip_address ) {
@ -333,21 +327,21 @@ class WC_Geolocation {
if ( ! is_wp_error( $response ) && $response['body'] ) { if ( ! is_wp_error( $response ) && $response['body'] ) {
switch ( $service_name ) { switch ( $service_name ) {
case 'ipinfo.io' : case 'ipinfo.io':
$data = json_decode( $response['body'] ); $data = json_decode( $response['body'] );
$country_code = isset( $data->country ) ? $data->country : ''; $country_code = isset( $data->country ) ? $data->country : '';
break; break;
case 'ip-api.com' : case 'ip-api.com':
$data = json_decode( $response['body'] ); $data = json_decode( $response['body'] );
$country_code = isset( $data->countryCode ) ? $data->countryCode : ''; $country_code = isset( $data->countryCode ) ? $data->countryCode : ''; // @codingStandardsIgnoreLine
break; break;
case 'freegeoip' : case 'freegeoip':
$data = json_decode( $response['body'] ); $data = json_decode( $response['body'] );
$country_code = isset( $data->country_code ) ? $data->country_code : ''; $country_code = isset( $data->country_code ) ? $data->country_code : '';
break; break;
default : default:
$country_code = apply_filters( 'woocommerce_geolocation_geoip_response_' . $service_name, '', $response['body'] ); $country_code = apply_filters( 'woocommerce_geolocation_geoip_response_' . $service_name, '', $response['body'] );
break; break;
} }
$country_code = sanitize_text_field( strtoupper( $country_code ) ); $country_code = sanitize_text_field( strtoupper( $country_code ) );
@ -369,10 +363,10 @@ class WC_Geolocation {
* *
* @since 2.4.0 * @since 2.4.0
* *
* @param string $ip_address * @param string $ip_address IP Address.
* @return bool * @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 ); return false !== filter_var( $ip_address, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 );
} }
} }

View File

@ -98,6 +98,7 @@ class WC_Install {
), ),
'3.3.0' => array( '3.3.0' => array(
'wc_update_330_image_options', 'wc_update_330_image_options',
'wc_update_330_set_default_product_cat',
'wc_update_330_db_version', 'wc_update_330_db_version',
), ),
); );
@ -128,7 +129,7 @@ class WC_Install {
* Init background updates * Init background updates
*/ */
public static function init_background_updater() { 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(); self::$background_updater = new WC_Background_Updater();
} }
@ -202,7 +203,7 @@ class WC_Install {
* @since 3.2.0 * @since 3.2.0
*/ */
private static function remove_admin_notices() { 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(); WC_Admin_Notices::remove_all_notices();
} }
@ -319,7 +320,8 @@ class WC_Install {
/** /**
* Update DB version to current. * 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 ) { public static function update_db_version( $version = null ) {
delete_option( 'woocommerce_db_version' ); delete_option( 'woocommerce_db_version' );
@ -328,7 +330,8 @@ class WC_Install {
/** /**
* Add more cron schedules. * Add more cron schedules.
* @param array $schedules *
* @param array $schedules List of WP scheduled cron jobs.
* @return array * @return array
*/ */
public static function cron_schedules( $schedules ) { public static function cron_schedules( $schedules ) {
@ -368,30 +371,32 @@ class WC_Install {
* Create pages that the plugin relies on, storing page IDs in variables. * Create pages that the plugin relies on, storing page IDs in variables.
*/ */
public static function create_pages() { 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( $pages = apply_filters(
'shop' => array( 'woocommerce_create_pages', array(
'name' => _x( 'shop', 'Page slug', 'woocommerce' ), 'shop' => array(
'title' => _x( 'Shop', 'Page title', 'woocommerce' ), 'name' => _x( 'shop', 'Page slug', 'woocommerce' ),
'content' => '', 'title' => _x( 'Shop', 'Page title', 'woocommerce' ),
), 'content' => '',
'cart' => array( ),
'name' => _x( 'cart', 'Page slug', 'woocommerce' ), 'cart' => array(
'title' => _x( 'Cart', 'Page title', 'woocommerce' ), 'name' => _x( 'cart', 'Page slug', 'woocommerce' ),
'content' => '[' . apply_filters( 'woocommerce_cart_shortcode_tag', 'woocommerce_cart' ) . ']', 'title' => _x( 'Cart', 'Page title', 'woocommerce' ),
), 'content' => '[' . apply_filters( 'woocommerce_cart_shortcode_tag', 'woocommerce_cart' ) . ']',
'checkout' => array( ),
'name' => _x( 'checkout', 'Page slug', 'woocommerce' ), 'checkout' => array(
'title' => _x( 'Checkout', 'Page title', 'woocommerce' ), 'name' => _x( 'checkout', 'Page slug', 'woocommerce' ),
'content' => '[' . apply_filters( 'woocommerce_checkout_shortcode_tag', 'woocommerce_checkout' ) . ']', 'title' => _x( 'Checkout', 'Page title', 'woocommerce' ),
), 'content' => '[' . apply_filters( 'woocommerce_checkout_shortcode_tag', 'woocommerce_checkout' ) . ']',
'myaccount' => array( ),
'name' => _x( 'my-account', 'Page slug', 'woocommerce' ), 'myaccount' => array(
'title' => _x( 'My account', 'Page title', 'woocommerce' ), 'name' => _x( 'my-account', 'Page slug', 'woocommerce' ),
'content' => '[' . apply_filters( 'woocommerce_my_account_shortcode_tag', 'woocommerce_my_account' ) . ']', 'title' => _x( 'My account', 'Page title', 'woocommerce' ),
), 'content' => '[' . apply_filters( 'woocommerce_my_account_shortcode_tag', 'woocommerce_my_account' ) . ']',
) ); ),
)
);
foreach ( $pages as $key => $page ) { 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'] ) : '' ); wc_create_page( esc_sql( $page['name'] ), 'woocommerce_' . $key . '_page_id', $page['title'], $page['content'], ! empty( $page['parent'] ) ? wc_get_page_id( $page['parent'] ) : '' );
@ -406,8 +411,8 @@ class WC_Install {
* Sets up the default options used on the settings page. * Sets up the default options used on the settings page.
*/ */
private static function create_options() { private static function create_options() {
// Include settings so that we can run through defaults // Include settings so that we can run through defaults.
include_once( dirname( __FILE__ ) . '/admin/class-wc-admin-settings.php' ); include_once dirname( __FILE__ ) . '/admin/class-wc-admin-settings.php';
$settings = WC_Admin_Settings::get_settings_pages(); $settings = WC_Admin_Settings::get_settings_pages();
@ -433,7 +438,7 @@ class WC_Install {
*/ */
public static function create_terms() { public static function create_terms() {
$taxonomies = array( $taxonomies = array(
'product_type' => array( 'product_type' => array(
'simple', 'simple',
'grouped', 'grouped',
'variable', 'variable',
@ -454,32 +459,54 @@ class WC_Install {
foreach ( $taxonomies as $taxonomy => $terms ) { foreach ( $taxonomies as $taxonomy => $terms ) {
foreach ( $terms as $term ) { foreach ( $terms as $term ) {
if ( ! get_term_by( 'name', $term, $taxonomy ) ) { if ( ! get_term_by( 'name', $term, $taxonomy ) ) { // @codingStandardsIgnoreLine.
wp_insert_term( $term, $taxonomy ); 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. * Set up the database tables which the plugin needs to function.
* *
* Tables: * Tables:
* woocommerce_attribute_taxonomies - Table for storing attribute taxonomies - these are user defined * 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_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. * 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 * 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_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_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_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_tax_rate_locations - Each rate can be applied to more than one postcode/city hence the second table.
*/ */
private static function create_tables() { private static function create_tables() {
global $wpdb; global $wpdb;
$wpdb->hide_errors(); $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 * Before updating with DBDELTA, remove any primary keys which could be
@ -505,7 +532,7 @@ class WC_Install {
/** /**
* Get Table schema. * 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. * 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 * As of WordPress 4.2, however, we moved to utf8mb4, which uses 4 bytes per character. This means that an index which
@ -713,56 +740,64 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta (
} }
if ( ! isset( $wp_roles ) ) { if ( ! isset( $wp_roles ) ) {
$wp_roles = new WP_Roles(); $wp_roles = new WP_Roles(); // @codingStandardsIgnoreLine
} }
// Customer role // Customer role.
add_role( 'customer', __( 'Customer', 'woocommerce' ), array( add_role(
'read' => true, 'customer',
) ); __( 'Customer', 'woocommerce' ),
array(
'read' => true,
)
);
// Shop manager role // Shop manager role.
add_role( 'shop_manager', __( 'Shop manager', 'woocommerce' ), array( add_role(
'level_9' => true, 'shop_manager',
'level_8' => true, __( 'Shop manager', 'woocommerce' ),
'level_7' => true, array(
'level_6' => true, 'level_9' => true,
'level_5' => true, 'level_8' => true,
'level_4' => true, 'level_7' => true,
'level_3' => true, 'level_6' => true,
'level_2' => true, 'level_5' => true,
'level_1' => true, 'level_4' => true,
'level_0' => true, 'level_3' => true,
'read' => true, 'level_2' => true,
'read_private_pages' => true, 'level_1' => true,
'read_private_posts' => true, 'level_0' => true,
'edit_users' => true, 'read' => true,
'edit_posts' => true, 'read_private_pages' => true,
'edit_pages' => true, 'read_private_posts' => true,
'edit_published_posts' => true, 'edit_users' => true,
'edit_published_pages' => true, 'edit_posts' => true,
'edit_private_pages' => true, 'edit_pages' => true,
'edit_private_posts' => true, 'edit_published_posts' => true,
'edit_others_posts' => true, 'edit_published_pages' => true,
'edit_others_pages' => true, 'edit_private_pages' => true,
'publish_posts' => true, 'edit_private_posts' => true,
'publish_pages' => true, 'edit_others_posts' => true,
'delete_posts' => true, 'edit_others_pages' => true,
'delete_pages' => true, 'publish_posts' => true,
'delete_private_pages' => true, 'publish_pages' => true,
'delete_private_posts' => true, 'delete_posts' => true,
'delete_published_pages' => true, 'delete_pages' => true,
'delete_published_posts' => true, 'delete_private_pages' => true,
'delete_others_posts' => true, 'delete_private_posts' => true,
'delete_others_pages' => true, 'delete_published_pages' => true,
'manage_categories' => true, 'delete_published_posts' => true,
'manage_links' => true, 'delete_others_posts' => true,
'moderate_comments' => true, 'delete_others_pages' => true,
'upload_files' => true, 'manage_categories' => true,
'export' => true, 'manage_links' => true,
'import' => true, 'moderate_comments' => true,
'list_users' => true, 'upload_files' => true,
) ); 'export' => true,
'import' => true,
'list_users' => true,
)
);
$capabilities = self::get_core_capabilities(); $capabilities = self::get_core_capabilities();
@ -779,7 +814,7 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta (
* *
* @return array * @return array
*/ */
private static function get_core_capabilities() { private static function get_core_capabilities() {
$capabilities = array(); $capabilities = array();
$capabilities['core'] = array( $capabilities['core'] = array(
@ -792,7 +827,7 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta (
foreach ( $capability_types as $capability_type ) { foreach ( $capability_types as $capability_type ) {
$capabilities[ $capability_type ] = array( $capabilities[ $capability_type ] = array(
// Post type // Post type.
"edit_{$capability_type}", "edit_{$capability_type}",
"read_{$capability_type}", "read_{$capability_type}",
"delete_{$capability_type}", "delete_{$capability_type}",
@ -807,7 +842,7 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta (
"edit_private_{$capability_type}s", "edit_private_{$capability_type}s",
"edit_published_{$capability_type}s", "edit_published_{$capability_type}s",
// Terms // Terms.
"manage_{$capability_type}_terms", "manage_{$capability_type}_terms",
"edit_{$capability_type}_terms", "edit_{$capability_type}_terms",
"delete_{$capability_type}_terms", "delete_{$capability_type}_terms",
@ -819,7 +854,7 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta (
} }
/** /**
* woocommerce_remove_roles function. * Remove WooCommerce roles.
*/ */
public static function remove_roles() { public static function remove_roles() {
global $wp_roles; global $wp_roles;
@ -829,7 +864,7 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta (
} }
if ( ! isset( $wp_roles ) ) { if ( ! isset( $wp_roles ) ) {
$wp_roles = new WP_Roles(); $wp_roles = new WP_Roles(); // @codingStandardsIgnoreLine
} }
$capabilities = self::get_core_capabilities(); $capabilities = self::get_core_capabilities();
@ -849,44 +884,45 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta (
* Create files/directories. * Create files/directories.
*/ */
private static function create_files() { 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 ) ) { if ( apply_filters( 'woocommerce_install_skip_create_files', false ) ) {
return; 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(); $upload_dir = wp_upload_dir();
$download_method = get_option( 'woocommerce_file_download_method', 'force' ); $download_method = get_option( 'woocommerce_file_download_method', 'force' );
$files = array( $files = array(
array( array(
'base' => $upload_dir['basedir'] . '/woocommerce_uploads', 'base' => $upload_dir['basedir'] . '/woocommerce_uploads',
'file' => 'index.html', 'file' => 'index.html',
'content' => '', 'content' => '',
), ),
array( array(
'base' => WC_LOG_DIR, 'base' => WC_LOG_DIR,
'file' => '.htaccess', 'file' => '.htaccess',
'content' => 'deny from all', 'content' => 'deny from all',
), ),
array( array(
'base' => WC_LOG_DIR, 'base' => WC_LOG_DIR,
'file' => 'index.html', 'file' => 'index.html',
'content' => '', 'content' => '',
), ),
); );
if ( 'redirect' !== $download_method ) { if ( 'redirect' !== $download_method ) {
$files[] = array( $files[] = array(
'base' => $upload_dir['basedir'] . '/woocommerce_uploads', 'base' => $upload_dir['basedir'] . '/woocommerce_uploads',
'file' => '.htaccess', 'file' => '.htaccess',
'content' => 'deny from all', 'content' => 'deny from all',
); );
} }
foreach ( $files as $file ) { foreach ( $files as $file ) {
if ( wp_mkdir_p( $file['base'] ) && ! file_exists( trailingslashit( $file['base'] ) . $file['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'] ); fwrite( $file_handle, $file['content'] );
fclose( $file_handle ); fclose( $file_handle );
} }
@ -897,8 +933,8 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta (
/** /**
* Show action links on the plugin screen. * Show action links on the plugin screen.
* *
* @param mixed $links Plugin Action links * @param mixed $links Plugin Action links.
* @return array * @return array
*/ */
public static function plugin_action_links( $links ) { public static function plugin_action_links( $links ) {
$action_links = array( $action_links = array(
@ -911,9 +947,9 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta (
/** /**
* Show row meta on the plugin screen. * Show row meta on the plugin screen.
* *
* @param mixed $links Plugin Row Meta * @param mixed $links Plugin Row Meta.
* @param mixed $file Plugin Base file * @param mixed $file Plugin Base file.
* @return array * @return array
*/ */
public static function plugin_row_meta( $links, $file ) { public static function plugin_row_meta( $links, $file ) {
if ( WC_PLUGIN_BASENAME == $file ) { if ( WC_PLUGIN_BASENAME == $file ) {
@ -931,7 +967,8 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta (
/** /**
* Uninstall tables when MU blog is deleted. * Uninstall tables when MU blog is deleted.
* @param array $tables *
* @param array $tables List of tables that will be deleted by WP.
* @return string[] * @return string[]
*/ */
public static function wpmu_drop_tables( $tables ) { public static function wpmu_drop_tables( $tables ) {
@ -956,7 +993,8 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta (
/** /**
* Get slug from path * Get slug from path
* @param string $key *
* @param string $key Plugin relative path. Example: woocommerce/woocommerce.php.
* @return string * @return string
*/ */
private static function format_plugin_slug( $key ) { private static function format_plugin_slug( $key ) {
@ -968,8 +1006,10 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta (
/** /**
* Install a plugin from .org in the background via a cron job (used by * Install a plugin from .org in the background via a cron job (used by
* installer - opt in). * 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 * @since 2.6.0
*/ */
public static function background_installer( $plugin_to_install_id, $plugin_to_install ) { public static function background_installer( $plugin_to_install_id, $plugin_to_install ) {
@ -977,14 +1017,14 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta (
wp_clear_scheduled_hook( 'woocommerce_plugin_background_installer', func_get_args() ); wp_clear_scheduled_hook( 'woocommerce_plugin_background_installer', func_get_args() );
if ( ! empty( $plugin_to_install['repo-slug'] ) ) { if ( ! empty( $plugin_to_install['repo-slug'] ) ) {
require_once( ABSPATH . 'wp-admin/includes/file.php' ); require_once ABSPATH . 'wp-admin/includes/file.php';
require_once( ABSPATH . 'wp-admin/includes/plugin-install.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/class-wp-upgrader.php';
require_once( ABSPATH . 'wp-admin/includes/plugin.php' ); require_once ABSPATH . 'wp-admin/includes/plugin.php';
WP_Filesystem(); WP_Filesystem();
$skin = new Automatic_Upgrader_Skin; $skin = new Automatic_Upgrader_Skin();
$upgrader = new WP_Upgrader( $skin ); $upgrader = new WP_Upgrader( $skin );
$installed_plugins = array_map( array( __CLASS__, 'format_plugin_slug' ), array_keys( get_plugins() ) ); $installed_plugins = array_map( array( __CLASS__, 'format_plugin_slug' ), array_keys( get_plugins() ) );
$plugin_slug = $plugin_to_install['repo-slug']; $plugin_slug = $plugin_to_install['repo-slug'];
@ -992,7 +1032,7 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta (
$installed = false; $installed = false;
$activate = 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 ) ) { if ( in_array( $plugin_to_install['repo-slug'], $installed_plugins ) ) {
$installed = true; $installed = true;
$activate = ! is_plugin_active( $plugin ); $activate = ! is_plugin_active( $plugin );
@ -1000,28 +1040,31 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta (
// Install this thing! // Install this thing!
if ( ! $installed ) { if ( ! $installed ) {
// Suppress feedback // Suppress feedback.
ob_start(); ob_start();
try { try {
$plugin_information = plugins_api( 'plugin_information', array( $plugin_information = plugins_api(
'slug' => $plugin_to_install['repo-slug'], 'plugin_information',
'fields' => array( array(
'short_description' => false, 'slug' => $plugin_to_install['repo-slug'],
'sections' => false, 'fields' => array(
'requires' => false, 'short_description' => false,
'rating' => false, 'sections' => false,
'ratings' => false, 'requires' => false,
'downloaded' => false, 'rating' => false,
'last_updated' => false, 'ratings' => false,
'added' => false, 'downloaded' => false,
'tags' => false, 'last_updated' => false,
'homepage' => false, 'added' => false,
'donate_link' => false, 'tags' => false,
'author_profile' => false, 'homepage' => false,
'author' => false, 'donate_link' => false,
), 'author_profile' => false,
) ); 'author' => false,
),
)
);
if ( is_wp_error( $plugin_information ) ) { if ( is_wp_error( $plugin_information ) ) {
throw new Exception( $plugin_information->get_error_message() ); throw new Exception( $plugin_information->get_error_message() );
@ -1040,17 +1083,19 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta (
throw new Exception( $working_dir->get_error_message() ); throw new Exception( $working_dir->get_error_message() );
} }
$result = $upgrader->install_package( array( $result = $upgrader->install_package(
'source' => $working_dir, array(
'destination' => WP_PLUGIN_DIR, 'source' => $working_dir,
'clear_destination' => false, 'destination' => WP_PLUGIN_DIR,
'abort_if_destination_exists' => false, 'clear_destination' => false,
'clear_working' => true, 'abort_if_destination_exists' => false,
'hook_extra' => array( 'clear_working' => true,
'type' => 'plugin', 'hook_extra' => array(
'action' => 'install', 'type' => 'plugin',
), 'action' => 'install',
) ); ),
)
);
if ( is_wp_error( $result ) ) { if ( is_wp_error( $result ) ) {
throw new Exception( $result->get_error_message() ); throw new Exception( $result->get_error_message() );
@ -1062,6 +1107,7 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta (
WC_Admin_Notices::add_custom_notice( WC_Admin_Notices::add_custom_notice(
$plugin_to_install_id . '_install_error', $plugin_to_install_id . '_install_error',
sprintf( 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' ), __( '%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'], $plugin_to_install['name'],
$e->getMessage(), $e->getMessage(),
@ -1070,13 +1116,13 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta (
); );
} }
// Discard feedback // Discard feedback.
ob_end_clean(); ob_end_clean();
} }
wp_clean_plugins_cache(); wp_clean_plugins_cache();
// Activate this thing // Activate this thing.
if ( $activate ) { if ( $activate ) {
try { try {
$result = activate_plugin( $plugin ); $result = activate_plugin( $plugin );
@ -1088,6 +1134,7 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta (
WC_Admin_Notices::add_custom_notice( WC_Admin_Notices::add_custom_notice(
$plugin_to_install_id . '_install_error', $plugin_to_install_id . '_install_error',
sprintf( 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' ), __( '%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'], $plugin_to_install['name'],
admin_url( 'plugins.php' ) admin_url( 'plugins.php' )
@ -1101,7 +1148,8 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta (
/** /**
* Install a theme from .org in the background via a cron job (used by installer - opt in). * 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 * @since 3.1.0
*/ */
public static function theme_background_installer( $theme_slug ) { public static function theme_background_installer( $theme_slug ) {
@ -1109,25 +1157,27 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta (
wp_clear_scheduled_hook( 'woocommerce_theme_background_installer', func_get_args() ); wp_clear_scheduled_hook( 'woocommerce_theme_background_installer', func_get_args() );
if ( ! empty( $theme_slug ) ) { if ( ! empty( $theme_slug ) ) {
// Suppress feedback // Suppress feedback.
ob_start(); ob_start();
try { try {
$theme = wp_get_theme( $theme_slug ); $theme = wp_get_theme( $theme_slug );
if ( ! $theme->exists() ) { if ( ! $theme->exists() ) {
require_once( ABSPATH . 'wp-admin/includes/file.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/class-wp-upgrader.php';
include_once( ABSPATH . 'wp-admin/includes/theme.php' ); include_once ABSPATH . 'wp-admin/includes/theme.php';
WP_Filesystem(); WP_Filesystem();
$skin = new Automatic_Upgrader_Skin; $skin = new Automatic_Upgrader_Skin();
$upgrader = new Theme_Upgrader( $skin ); $upgrader = new Theme_Upgrader( $skin );
$api = themes_api( 'theme_information', array( $api = themes_api(
'slug' => $theme_slug, 'theme_information', array(
'fields' => array( 'sections' => false ), 'slug' => $theme_slug,
) ); 'fields' => array( 'sections' => false ),
)
);
$result = $upgrader->install( $api->download_link ); $result = $upgrader->install( $api->download_link );
if ( is_wp_error( $result ) ) { if ( is_wp_error( $result ) ) {
@ -1144,6 +1194,7 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta (
WC_Admin_Notices::add_custom_notice( WC_Admin_Notices::add_custom_notice(
$theme_slug . '_install_error', $theme_slug . '_install_error',
sprintf( 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' ), __( '%1$s could not be installed (%2$s). <a href="%3$s">Please install it manually by clicking here.</a>', 'woocommerce' ),
$theme_slug, $theme_slug,
$e->getMessage(), $e->getMessage(),
@ -1152,7 +1203,7 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta (
); );
} }
// Discard feedback // Discard feedback.
ob_end_clean(); ob_end_clean();
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -31,6 +31,7 @@ class WC_Post_Data {
add_filter( 'post_type_link', array( __CLASS__, 'variation_post_link' ), 10, 2 ); add_filter( 'post_type_link', array( __CLASS__, 'variation_post_link' ), 10, 2 );
add_action( 'shutdown', array( __CLASS__, 'do_deferred_product_sync' ), 10 ); 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__, '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( 'transition_post_status', array( __CLASS__, 'transition_post_status' ), 10, 3 );
add_action( 'woocommerce_product_set_stock_status', array( __CLASS__, 'delete_product_query_transients' ) ); 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 ) { public static function flush_object_meta_cache( $meta_id, $object_id, $meta_key, $meta_value ) {
WC_Cache_Helper::incr_cache_prefix( 'object_' . $object_id ); 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(); 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__, 'register_post_status' ), 9 );
add_action( 'init', array( __CLASS__, 'support_jetpack_omnisearch' ) ); add_action( 'init', array( __CLASS__, 'support_jetpack_omnisearch' ) );
add_filter( 'rest_api_allowed_post_types', array( __CLASS__, 'rest_api_allowed_post_types' ) ); 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' ) ); add_action( 'woocommerce_flush_rewrite_rules', array( __CLASS__, 'flush_rewrite_rules' ) );
} }
@ -529,6 +530,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. * Flush rewrite rules.
*/ */

View File

@ -42,6 +42,7 @@ class WC_Query {
add_action( 'pre_get_posts', array( $this, 'pre_get_posts' ) ); add_action( 'pre_get_posts', array( $this, 'pre_get_posts' ) );
add_action( 'wp', array( $this, 'remove_product_query' ) ); add_action( 'wp', array( $this, 'remove_product_query' ) );
add_action( 'wp', array( $this, 'remove_ordering_args' ) ); add_action( 'wp', array( $this, 'remove_ordering_args' ) );
add_filter( 'get_pagenum_link', array( $this, 'remove_add_to_cart_pagination' ), 10, 1 );
} }
$this->init_query_vars(); $this->init_query_vars();
} }
@ -840,4 +841,14 @@ class WC_Query {
public function layered_nav_query( $deprecated ) { public function layered_nav_query( $deprecated ) {
wc_deprecated_function( 'layered_nav_query', '2.6' ); wc_deprecated_function( 'layered_nav_query', '2.6' );
} }
/**
* Remove the add-to-cart param from pagination urls.
*
* @param string $url URL.
* @return string
*/
public function remove_add_to_cart_pagination( $url ) {
return remove_query_arg( 'add-to-cart', $url );
}
} }

View File

@ -66,13 +66,14 @@ class WC_Regenerate_Images {
$size_settings = wc_get_image_size( $size ); $size_settings = wc_get_image_size( $size );
if ( isset( $imagemeta['sizes'], $imagemeta['sizes'][ $size ] ) ) { if ( in_array( $size, array( 'woocommerce_thumbnail' ), true ) && isset( $imagemeta['sizes'], $imagemeta['sizes'][ $size ] ) ) {
if ( $imagemeta['sizes'][ $size ]['width'] !== $size_settings['width'] || $imagemeta['sizes'][ $size ]['height'] !== $size_settings['height'] ) { if ( $imagemeta['sizes'][ $size ]['width'] !== $size_settings['width'] || $imagemeta['sizes'][ $size ]['height'] !== $size_settings['height'] ) {
$image = self::resize_and_return_image( $attachment_id, $image, $size, $icon ); $image = self::resize_and_return_image( $attachment_id, $image, $size, $icon );
} }
} else { } else {
$image = self::resize_and_return_image( $attachment_id, $image, $size, $icon ); $image = self::resize_and_return_image( $attachment_id, $image, $size, $icon );
} }
return $image; return $image;
} }

View File

@ -87,6 +87,10 @@ class WC_Validation {
case 'PL': case 'PL':
$valid = (bool) preg_match( '/^([0-9]{2})([-])([0-9]{3})$/', $postcode ); $valid = (bool) preg_match( '/^([0-9]{2})([-])([0-9]{3})$/', $postcode );
break; break;
case 'CZ':
case 'SK':
$valid = (bool) preg_match( '/^([0-9]{3})(\s?)([0-9]{2})$/', $postcode );
break;
default : default :
$valid = true; $valid = true;

View File

@ -773,7 +773,12 @@ class WC_Webhook {
break; break;
} }
$prev_post_status = $this->get_status();
$wpdb->update( $wpdb->posts, array( 'post_status' => $post_status ), array( 'ID' => $this->id ) ); $wpdb->update( $wpdb->posts, array( 'post_status' => $post_status ), array( 'ID' => $this->id ) );
do_action( 'woocommerce_webhook_updated_status', $this->id, $post_status, $prev_post_status );
clean_post_cache( $this->id ); clean_post_cache( $this->id );
} }

View File

@ -1,4 +1,10 @@
<?php <?php
/**
* Abstract_WC_Order_Data_Store_CPT class file.
*
* @package WooCommerce/Classes
*/
if ( ! defined( 'ABSPATH' ) ) { if ( ! defined( 'ABSPATH' ) ) {
exit; 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. * Method to create a new order in the database.
* @param WC_Order $order *
* @param WC_Order $order Order object.
*/ */
public function create( &$order ) { public function create( &$order ) {
$order->set_version( WC_VERSION ); $order->set_version( WC_VERSION );
$order->set_date_created( current_time( 'timestamp', true ) ); $order->set_date_created( current_time( 'timestamp', true ) );
$order->set_currency( $order->get_currency() ? $order->get_currency() : get_woocommerce_currency() ); $order->set_currency( $order->get_currency() ? $order->get_currency() : get_woocommerce_currency() );
$id = wp_insert_post( apply_filters( 'woocommerce_new_order_data', array( $id = wp_insert_post(
'post_date' => gmdate( 'Y-m-d H:i:s', $order->get_date_created( 'edit' )->getOffsetTimestamp() ), apply_filters(
'post_date_gmt' => gmdate( 'Y-m-d H:i:s', $order->get_date_created( 'edit' )->getTimestamp() ), 'woocommerce_new_order_data',
'post_type' => $order->get_type( 'edit' ), array(
'post_status' => 'wc-' . ( $order->get_status( 'edit' ) ? $order->get_status( 'edit' ) : apply_filters( 'woocommerce_default_order_status', 'pending' ) ), 'post_date' => gmdate( 'Y-m-d H:i:s', $order->get_date_created( 'edit' )->getOffsetTimestamp() ),
'ping_status' => 'closed', 'post_date_gmt' => gmdate( 'Y-m-d H:i:s', $order->get_date_created( 'edit' )->getTimestamp() ),
'post_author' => 1, 'post_type' => $order->get_type( 'edit' ),
'post_title' => $this->get_post_title(), 'post_status' => 'wc-' . ( $order->get_status( 'edit' ) ? $order->get_status( 'edit' ) : apply_filters( 'woocommerce_default_order_status', 'pending' ) ),
'post_password' => uniqid( 'order_' ), 'ping_status' => 'closed',
'post_parent' => $order->get_parent_id( 'edit' ), 'post_author' => 1,
'post_excerpt' => $this->get_post_excerpt( $order ), 'post_title' => $this->get_post_title(),
) ), true ); '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 ) ) { if ( $id && ! is_wp_error( $id ) ) {
$order->set_id( $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. * 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 ) { public function read( &$order ) {
$order->set_defaults(); $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' ) ); throw new Exception( __( 'Invalid order.', 'woocommerce' ) );
} }
$order->set_props( array( $order->set_props(
'parent_id' => $post_object->post_parent, array(
'date_created' => 0 < $post_object->post_date_gmt ? wc_string_to_timestamp( $post_object->post_date_gmt ) : null, 'parent_id' => $post_object->post_parent,
'date_modified' => 0 < $post_object->post_modified_gmt ? wc_string_to_timestamp( $post_object->post_modified_gmt ) : null, 'date_created' => 0 < $post_object->post_date_gmt ? wc_string_to_timestamp( $post_object->post_date_gmt ) : null,
'status' => $post_object->post_status, '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 ); $this->read_order_data( $order, $post_object );
$order->read_meta_data(); $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. * Method to update an order in the database.
* @param WC_Order $order *
* @param WC_Order $order Order object.
*/ */
public function update( &$order ) { public function update( &$order ) {
$order->save_meta_data(); $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. * 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() ) { public function delete( &$order, $args = array() ) {
$id = $order->get_id(); $id = $order->get_id();
$args = wp_parse_args( $args, array( $args = wp_parse_args(
'force_delete' => false, $args,
) ); array(
'force_delete' => false,
)
);
if ( ! $id ) { if ( ! $id ) {
return; return;
@ -188,7 +210,7 @@ abstract class Abstract_WC_Order_Data_Store_CPT extends WC_Data_Store_WP impleme
/** /**
* Excerpt for post. * Excerpt for post.
* *
* @param WC_order $order * @param WC_order $order Order object.
* @return string * @return string
*/ */
protected function get_post_excerpt( $order ) { 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. * Read order data. Can be overridden by child classes to load other props.
* *
* @param WC_Order $order * @param WC_Order $order Order object.
* @param object $post_object * @param object $post_object Post object.
* @since 3.0.0 * @since 3.0.0
*/ */
protected function read_order_data( &$order, $post_object ) { protected function read_order_data( &$order, $post_object ) {
$id = $order->get_id(); $id = $order->get_id();
$order->set_props( array( $order->set_props(
'currency' => get_post_meta( $id, '_order_currency', true ), array(
'discount_total' => get_post_meta( $id, '_cart_discount', true ), 'currency' => get_post_meta( $id, '_order_currency', true ),
'discount_tax' => get_post_meta( $id, '_cart_discount_tax', true ), 'discount_total' => get_post_meta( $id, '_cart_discount', true ),
'shipping_total' => get_post_meta( $id, '_order_shipping', true ), 'discount_tax' => get_post_meta( $id, '_cart_discount_tax', true ),
'shipping_tax' => get_post_meta( $id, '_order_shipping_tax', true ), 'shipping_total' => get_post_meta( $id, '_order_shipping', true ),
'cart_tax' => get_post_meta( $id, '_order_tax', true ), 'shipping_tax' => get_post_meta( $id, '_order_shipping_tax', true ),
'total' => get_post_meta( $id, '_order_total', true ), 'cart_tax' => get_post_meta( $id, '_order_tax', true ),
'version' => get_post_meta( $id, '_order_version', true ), 'total' => get_post_meta( $id, '_order_total', 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' ), '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. // Gets extra data associated with the order if needed.
foreach ( $order->get_extra_data_keys() as $key ) { 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. * 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 * @since 3.0.0
*/ */
protected function update_post_meta( &$order ) { 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. * Clear any caches.
* *
* @param WC_Order $order * @param WC_Order $order Order object.
* @since 3.0.0 * @since 3.0.0
*/ */
protected function clear_caches( &$order ) { 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. * Read order items of a specific type from the database for this order.
* *
* @param WC_Order $order * @param WC_Order $order Order object.
* @param string $type * @param string $type Order item type.
* @return array * @return array
*/ */
public function read_items( $order, $type ) { 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' ); $items = wp_cache_get( 'order-items-' . $order->get_id(), 'orders' );
if ( false === $items ) { 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(
$items = $wpdb->get_results( $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() )
);
foreach ( $items as $item ) { foreach ( $items as $item ) {
wp_cache_set( 'item-' . $item->order_item_id, $item, 'order-items' ); 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. * 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. * @param string $type Order item type. Default null.
*/ */
public function delete_items( $order, $type = 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. * Get token ids for an order.
* *
* @param WC_Order $order * @param WC_Order $order Order object.
* @return array * @return array
*/ */
public function get_payment_token_ids( $order ) { 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. * Update token ids for an order.
* *
* @param WC_Order $order * @param WC_Order $order Order object.
* @param array $token_ids * @param array $token_ids Payment token ids.
*/ */
public function update_payment_token_ids( $order, $token_ids ) { public function update_payment_token_ids( $order, $token_ids ) {
update_post_meta( $order->get_id(), '_payment_tokens', $token_ids ); update_post_meta( $order->get_id(), '_payment_tokens', $token_ids );

View File

@ -1,4 +1,10 @@
<?php <?php
/**
* WC_Order_Data_Store_CPT class file.
*
* @package WooCommerce/Classes
*/
if ( ! defined( 'ABSPATH' ) ) { if ( ! defined( 'ABSPATH' ) ) {
exit; 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. * Data stored in meta keys, but not considered "meta" for an order.
*
* @since 3.0.0 * @since 3.0.0
* @var array * @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. * Method to create a new order in the database.
* @param WC_Order $order *
* @param WC_Order $order Order object.
*/ */
public function create( &$order ) { public function create( &$order ) {
$order->set_order_key( 'wc_' . apply_filters( 'woocommerce_generate_order_key', uniqid( '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. * Read order data. Can be overridden by child classes to load other props.
* *
* @param WC_Order $order * @param WC_Order $order Order object.
* @param object $post_object * @param object $post_object Post object.
* @since 3.0.0 * @since 3.0.0
*/ */
protected function read_order_data( &$order, $post_object ) { 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 ); $date_paid = get_post_meta( $id, '_paid_date', true );
} }
$order->set_props( array( $order->set_props(
'order_key' => get_post_meta( $id, '_order_key', true ), array(
'customer_id' => get_post_meta( $id, '_customer_user', true ), 'order_key' => get_post_meta( $id, '_order_key', true ),
'billing_first_name' => get_post_meta( $id, '_billing_first_name', true ), 'customer_id' => get_post_meta( $id, '_customer_user', true ),
'billing_last_name' => get_post_meta( $id, '_billing_last_name', true ), 'billing_first_name' => get_post_meta( $id, '_billing_first_name', true ),
'billing_company' => get_post_meta( $id, '_billing_company', true ), 'billing_last_name' => get_post_meta( $id, '_billing_last_name', true ),
'billing_address_1' => get_post_meta( $id, '_billing_address_1', true ), 'billing_company' => get_post_meta( $id, '_billing_company', true ),
'billing_address_2' => get_post_meta( $id, '_billing_address_2', true ), 'billing_address_1' => get_post_meta( $id, '_billing_address_1', true ),
'billing_city' => get_post_meta( $id, '_billing_city', true ), 'billing_address_2' => get_post_meta( $id, '_billing_address_2', true ),
'billing_state' => get_post_meta( $id, '_billing_state', true ), 'billing_city' => get_post_meta( $id, '_billing_city', true ),
'billing_postcode' => get_post_meta( $id, '_billing_postcode', true ), 'billing_state' => get_post_meta( $id, '_billing_state', true ),
'billing_country' => get_post_meta( $id, '_billing_country', true ), 'billing_postcode' => get_post_meta( $id, '_billing_postcode', true ),
'billing_email' => get_post_meta( $id, '_billing_email', true ), 'billing_country' => get_post_meta( $id, '_billing_country', true ),
'billing_phone' => get_post_meta( $id, '_billing_phone', true ), 'billing_email' => get_post_meta( $id, '_billing_email', true ),
'shipping_first_name' => get_post_meta( $id, '_shipping_first_name', true ), 'billing_phone' => get_post_meta( $id, '_billing_phone', true ),
'shipping_last_name' => get_post_meta( $id, '_shipping_last_name', true ), 'shipping_first_name' => get_post_meta( $id, '_shipping_first_name', true ),
'shipping_company' => get_post_meta( $id, '_shipping_company', true ), 'shipping_last_name' => get_post_meta( $id, '_shipping_last_name', true ),
'shipping_address_1' => get_post_meta( $id, '_shipping_address_1', true ), 'shipping_company' => get_post_meta( $id, '_shipping_company', true ),
'shipping_address_2' => get_post_meta( $id, '_shipping_address_2', true ), 'shipping_address_1' => get_post_meta( $id, '_shipping_address_1', true ),
'shipping_city' => get_post_meta( $id, '_shipping_city', true ), 'shipping_address_2' => get_post_meta( $id, '_shipping_address_2', true ),
'shipping_state' => get_post_meta( $id, '_shipping_state', true ), 'shipping_city' => get_post_meta( $id, '_shipping_city', true ),
'shipping_postcode' => get_post_meta( $id, '_shipping_postcode', true ), 'shipping_state' => get_post_meta( $id, '_shipping_state', true ),
'shipping_country' => get_post_meta( $id, '_shipping_country', true ), 'shipping_postcode' => get_post_meta( $id, '_shipping_postcode', true ),
'payment_method' => get_post_meta( $id, '_payment_method', true ), 'shipping_country' => get_post_meta( $id, '_shipping_country', true ),
'payment_method_title' => get_post_meta( $id, '_payment_method_title', true ), 'payment_method' => get_post_meta( $id, '_payment_method', true ),
'transaction_id' => get_post_meta( $id, '_transaction_id', true ), 'payment_method_title' => get_post_meta( $id, '_payment_method_title', true ),
'customer_ip_address' => get_post_meta( $id, '_customer_ip_address', true ), 'transaction_id' => get_post_meta( $id, '_transaction_id', true ),
'customer_user_agent' => get_post_meta( $id, '_customer_user_agent', true ), 'customer_ip_address' => get_post_meta( $id, '_customer_ip_address', true ),
'created_via' => get_post_meta( $id, '_created_via', true ), 'customer_user_agent' => get_post_meta( $id, '_customer_user_agent', true ),
'date_completed' => $date_completed, 'created_via' => get_post_meta( $id, '_created_via', true ),
'date_paid' => $date_paid, 'date_completed' => $date_completed,
'cart_hash' => get_post_meta( $id, '_cart_hash', true ), 'date_paid' => $date_paid,
'customer_note' => $post_object->post_excerpt, 'cart_hash' => get_post_meta( $id, '_cart_hash', true ),
) ); 'customer_note' => $post_object->post_excerpt,
)
);
} }
/** /**
* Method to update an order in the database. * Method to update an order in the database.
* @param WC_Order $order *
* @param WC_Order $order Order object.
*/ */
public function update( &$order ) { public function update( &$order ) {
// Before updating, ensure date paid is set if missing. // 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. * 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 * @since 3.0.0
*/ */
protected function update_post_meta( &$order ) { 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( $address_props = array(
'billing' => array( 'billing' => array(
'_billing_first_name' => 'billing_first_name', '_billing_first_name' => 'billing_first_name',
'_billing_last_name' => 'billing_last_name', '_billing_last_name' => 'billing_last_name',
'_billing_company' => 'billing_company', '_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. * Excerpt for post.
* *
* @param WC_Order $order * @param WC_Order $order Order object.
* @return string * @return string
*/ */
protected function get_post_excerpt( $order ) { 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. * Get amount already refunded.
* *
* @param WC_Order $order * @param WC_Order $order Order object.
* @return string * @return string
*/ */
public function get_total_refunded( $order ) { public function get_total_refunded( $order ) {
global $wpdb; global $wpdb;
$total = $wpdb->get_var( $wpdb->prepare( " $total = $wpdb->get_var(
SELECT SUM( postmeta.meta_value ) $wpdb->prepare(
FROM $wpdb->postmeta AS postmeta "SELECT SUM( postmeta.meta_value )
INNER JOIN $wpdb->posts AS posts ON ( posts.post_type = 'shop_order_refund' AND posts.post_parent = %d ) FROM $wpdb->postmeta AS postmeta
WHERE postmeta.meta_key = '_refund_amount' INNER JOIN $wpdb->posts AS posts ON ( posts.post_type = 'shop_order_refund' AND posts.post_parent = %d )
AND postmeta.post_id = posts.ID WHERE postmeta.meta_key = '_refund_amount'
", $order->get_id() ) ); AND postmeta.post_id = posts.ID",
$order->get_id()
)
);
return $total; 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. * Get the total tax refunded.
* *
* @param WC_Order $order * @param WC_Order $order Order object.
* @return float * @return float
*/ */
public function get_total_tax_refunded( $order ) { public function get_total_tax_refunded( $order ) {
global $wpdb; global $wpdb;
$total = $wpdb->get_var( $wpdb->prepare( " $total = $wpdb->get_var(
SELECT SUM( order_itemmeta.meta_value ) $wpdb->prepare(
FROM {$wpdb->prefix}woocommerce_order_itemmeta AS order_itemmeta "SELECT SUM( order_itemmeta.meta_value )
INNER JOIN $wpdb->posts AS posts ON ( posts.post_type = 'shop_order_refund' AND posts.post_parent = %d ) FROM {$wpdb->prefix}woocommerce_order_itemmeta AS order_itemmeta
INNER JOIN {$wpdb->prefix}woocommerce_order_items AS order_items ON ( order_items.order_id = posts.ID AND order_items.order_item_type = 'tax' ) INNER JOIN $wpdb->posts AS posts ON ( posts.post_type = 'shop_order_refund' AND posts.post_parent = %d )
WHERE order_itemmeta.order_item_id = order_items.order_item_id INNER JOIN {$wpdb->prefix}woocommerce_order_items AS order_items ON ( order_items.order_id = posts.ID AND order_items.order_item_type = 'tax' )
AND order_itemmeta.meta_key IN ('tax_amount', 'shipping_tax_amount') WHERE order_itemmeta.order_item_id = order_items.order_item_id
", $order->get_id() ) ); AND order_itemmeta.meta_key IN ('tax_amount', 'shipping_tax_amount')",
$order->get_id()
)
);
return abs( $total ); 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. * Get the total shipping refunded.
* *
* @param WC_Order $order * @param WC_Order $order Order object.
* @return float * @return float
*/ */
public function get_total_shipping_refunded( $order ) { public function get_total_shipping_refunded( $order ) {
global $wpdb; global $wpdb;
$total = $wpdb->get_var( $wpdb->prepare( " $total = $wpdb->get_var(
SELECT SUM( order_itemmeta.meta_value ) $wpdb->prepare(
FROM {$wpdb->prefix}woocommerce_order_itemmeta AS order_itemmeta "SELECT SUM( order_itemmeta.meta_value )
INNER JOIN $wpdb->posts AS posts ON ( posts.post_type = 'shop_order_refund' AND posts.post_parent = %d ) FROM {$wpdb->prefix}woocommerce_order_itemmeta AS order_itemmeta
INNER JOIN {$wpdb->prefix}woocommerce_order_items AS order_items ON ( order_items.order_id = posts.ID AND order_items.order_item_type = 'shipping' ) INNER JOIN $wpdb->posts AS posts ON ( posts.post_type = 'shop_order_refund' AND posts.post_parent = %d )
WHERE order_itemmeta.order_item_id = order_items.order_item_id INNER JOIN {$wpdb->prefix}woocommerce_order_items AS order_items ON ( order_items.order_id = posts.ID AND order_items.order_item_type = 'shipping' )
AND order_itemmeta.meta_key IN ('cost') WHERE order_itemmeta.order_item_id = order_items.order_item_id
", $order->get_id() ) ); AND order_itemmeta.meta_key IN ('cost')",
$order->get_id()
)
);
return abs( $total ); 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. * 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 * @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 ) { 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. * 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 * @return int
*/ */
public function get_order_count( $status ) { 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. * @deprecated 3.1.0 - Use wc_get_orders instead.
* @see wc_get_orders() * @see wc_get_orders()
* *
* @param array $args * @param array $args List of args passed to wc_get_orders().
* *
* @return array|object * @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. * Generate meta query for wc_get_orders.
* *
* @param array $values * @param array $values List of customers ids or emails.
* @param string $relation * @param string $relation 'or' or 'and' relation used to build the WP meta_query.
* @return array * @return array
*/ */
private function get_orders_generate_customer_meta_query( $values, $relation = 'or' ) { private function get_orders_generate_customer_meta_query( $values, $relation = 'or' ) {
$meta_query = array( $meta_query = array(
'relation' => strtoupper( $relation ), 'relation' => strtoupper( $relation ),
'customer_emails' => array( 'customer_emails' => array(
'key' => '_billing_email', 'key' => '_billing_email',
'value' => array(), 'value' => array(),
'compare' => 'IN', 'compare' => 'IN',
), ),
'customer_ids' => array( 'customer_ids' => array(
'key' => '_customer_user', 'key' => '_customer_user',
'value' => array(), 'value' => array(),
'compare' => 'IN', '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, * Get unpaid orders after a certain date,
* *
* @param int $date timestamp * @param int $date Timestamp.
* @return array * @return array
*/ */
public function get_unpaid_orders( $date ) { public function get_unpaid_orders( $date ) {
global $wpdb; global $wpdb;
$unpaid_orders = $wpdb->get_col( $wpdb->prepare( " $unpaid_orders = $wpdb->get_col(
SELECT posts.ID $wpdb->prepare(
FROM {$wpdb->posts} AS posts // @codingStandardsIgnoreStart
WHERE posts.post_type IN ('" . implode( "','", wc_get_order_types() ) . "') "SELECT posts.ID
AND posts.post_status = 'wc-pending' FROM {$wpdb->posts} AS posts
AND posts.post_modified < %s WHERE posts.post_type IN ('" . implode( "','", wc_get_order_types() ) . "')
", date( 'Y-m-d H:i:s', absint( $date ) ) ) ); AND posts.post_status = 'wc-pending'
AND posts.post_modified < %s",
// @codingStandardsIgnoreEnd
date( 'Y-m-d H:i:s', absint( $date ) )
)
);
return $unpaid_orders; 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. * Search order data for a term and return ids.
* *
* @param string $term * @param string $term Searched term.
* @return array of ids * @return array of ids
*/ */
public function search_orders( $term ) { 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. * 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. * 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). * This however won't work on older orders unless updated, so search a few others (expand this using the filter if needed).
*
* @var array * @var array
*/ */
$search_fields = array_map( 'wc_clean', apply_filters( 'woocommerce_shop_order_search_fields', array( $search_fields = array_map(
'_billing_address_index', 'wc_clean', apply_filters(
'_shipping_address_index', 'woocommerce_shop_order_search_fields', array(
'_billing_last_name', '_billing_address_index',
'_billing_email', '_shipping_address_index',
) ) ); '_billing_last_name',
$order_ids = array(); '_billing_email',
)
)
);
$order_ids = array();
if ( is_numeric( $term ) ) { if ( is_numeric( $term ) ) {
$order_ids[] = absint( $term ); $order_ids[] = absint( $term );
} }
if ( ! empty( $search_fields ) ) { if ( ! empty( $search_fields ) ) {
$order_ids = array_unique( array_merge( $order_ids = array_unique(
$order_ids, array_merge(
$wpdb->get_col( $order_ids,
$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(
$wpdb->get_col( "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->prepare( " '%' . $wpdb->esc_like( wc_clean( $term ) ) . '%'
SELECT order_id )
FROM {$wpdb->prefix}woocommerce_order_items as order_items ),
WHERE order_item_name LIKE '%%%s%%' $wpdb->get_col(
", $wpdb->prepare(
$wpdb->esc_like( wc_clean( $term ) ) "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 ); 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. * 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 * @return bool
*/ */
public function get_download_permissions_granted( $order ) { 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. * Stores information about whether permissions were generated yet.
* *
* @param WC_Order|int $order * @param WC_Order|int $order Order ID or order object.
* @param bool $set * @param bool $set True or false.
*/ */
public function set_download_permissions_granted( $order, $set ) { public function set_download_permissions_granted( $order, $set ) {
$order_id = WC_Order_Factory::get_order_id( $order ); $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. * Gets information about whether sales were recorded.
* *
* @param WC_Order|int $order * @param WC_Order|int $order Order ID or order object.
* @return bool * @return bool
*/ */
public function get_recorded_sales( $order ) { 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. * Stores information about whether sales were recorded.
* *
* @param WC_Order|int $order * @param WC_Order|int $order Order ID or order object.
* @param bool $set * @param bool $set True or false.
*/ */
public function set_recorded_sales( $order, $set ) { public function set_recorded_sales( $order, $set ) {
$order_id = WC_Order_Factory::get_order_id( $order ); $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. * 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 * @return bool
*/ */
public function get_recorded_coupon_usage_counts( $order ) { 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. * Stores information about whether coupon counts were updated.
* *
* @param WC_Order|int $order * @param WC_Order|int $order Order ID or order object.
* @param bool $set * @param bool $set True or false.
*/ */
public function set_recorded_coupon_usage_counts( $order, $set ) { public function set_recorded_coupon_usage_counts( $order, $set ) {
$order_id = WC_Order_Factory::get_order_id( $order ); $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. * Gets information about whether stock was reduced.
* *
* @param WC_Order|int $order * @param WC_Order|int $order Order ID or order object.
* @return bool * @return bool
*/ */
public function get_stock_reduced( $order ) { 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. * Stores information about whether stock was reduced.
* *
* @param WC_Order|int $order * @param WC_Order|int $order Order ID or order object.
* @param bool $set * @param bool $set True or false.
*/ */
public function set_stock_reduced( $order, $set ) { public function set_stock_reduced( $order, $set ) {
$order_id = WC_Order_Factory::get_order_id( $order ); $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. * Get the order type based on Order ID.
* *
* @since 3.0.0 * @since 3.0.0
* @param int $order_id * @param int $order_id Order ID.
* @return string * @return string
*/ */
public function get_order_type( $order_id ) { 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. * Get valid WP_Query args from a WC_Order_Query's query variables.
* *
* @since 3.1.0 * @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 * @return array
*/ */
protected function get_wp_query_args( $query_vars ) { 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'] ) { 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 ); $customer_query = $this->get_orders_generate_customer_meta_query( $values );
if ( is_wp_error( $customer_query ) ) { if ( is_wp_error( $customer_query ) ) {
$wp_query_args['errors'][] = $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 * @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 * @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'] ) ) { if ( ! empty( $args['errors'] ) ) {
$query = (object) array( $query = (object) array(
'posts' => array(), 'posts' => array(),
'found_posts' => 0, 'found_posts' => 0,
'max_num_pages' => 0, 'max_num_pages' => 0,
); );
} else { } 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. * For all stored terms in all taxonomies, save them to the DB.
* *
* @param WC_Product * @param WC_Product $product Product object.
* @param bool Force update. Used during create. * @param bool $force Force update. Used during create.
* @since 3.0.0 * @since 3.0.0
*/ */
protected function update_terms( &$product, $force = false ) { protected function update_terms( &$product, $force = false ) {
$changes = $product->get_changes(); $changes = $product->get_changes();
if ( $force || array_key_exists( 'category_ids', $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 ) ) { if ( $force || array_key_exists( 'tag_ids', $changes ) ) {
wp_set_post_terms( $product->get_id(), $product->get_tag_ids( 'edit' ), 'product_tag', false ); wp_set_post_terms( $product->get_id(), $product->get_tag_ids( 'edit' ), 'product_tag', false );

View File

@ -342,8 +342,12 @@ class WC_Gateway_BACS extends WC_Payment_Gateway {
$order = wc_get_order( $order_id ); $order = wc_get_order( $order_id );
// Mark as on-hold (we're awaiting the payment) if ( $order->get_total() > 0 ) {
$order->update_status( 'on-hold', __( 'Awaiting BACS payment', 'woocommerce' ) ); // Mark as on-hold (we're awaiting the payment)
$order->update_status( 'on-hold', __( 'Awaiting BACS payment', 'woocommerce' ) );
} else {
$order->payment_complete();
}
// Reduce stock levels // Reduce stock levels
wc_reduce_stock_levels( $order_id ); wc_reduce_stock_levels( $order_id );

View File

@ -113,8 +113,12 @@ class WC_Gateway_Cheque extends WC_Payment_Gateway {
$order = wc_get_order( $order_id ); $order = wc_get_order( $order_id );
// Mark as on-hold (we're awaiting the cheque) if ( $order->get_total() > 0 ) {
$order->update_status( 'on-hold', _x( 'Awaiting check payment', 'Check payment method', 'woocommerce' ) ); // Mark as on-hold (we're awaiting the cheque)
$order->update_status( 'on-hold', _x( 'Awaiting check payment', 'Check payment method', 'woocommerce' ) );
} else {
$order->payment_complete();
}
// Reduce stock levels // Reduce stock levels
wc_reduce_stock_levels( $order_id ); wc_reduce_stock_levels( $order_id );

View File

@ -178,8 +178,12 @@ class WC_Gateway_COD extends WC_Payment_Gateway {
public function process_payment( $order_id ) { public function process_payment( $order_id ) {
$order = wc_get_order( $order_id ); $order = wc_get_order( $order_id );
// Mark as processing or on-hold (payment won't be taken until delivery) if ( $order->get_total() > 0 ) {
$order->update_status( apply_filters( 'woocommerce_cod_process_payment_order_status', $order->has_downloadable_item() ? 'on-hold' : 'processing', $order ), __( 'Payment to be made upon delivery.', 'woocommerce' ) ); // Mark as processing or on-hold (payment won't be taken until delivery)
$order->update_status( apply_filters( 'woocommerce_cod_process_payment_order_status', $order->has_downloadable_item() ? 'on-hold' : 'processing', $order ), __( 'Payment to be made upon delivery.', 'woocommerce' ) );
} else {
$order->payment_complete();
}
// Reduce stock levels // Reduce stock levels
wc_reduce_stock_levels( $order_id ); wc_reduce_stock_levels( $order_id );

View File

@ -133,7 +133,7 @@ abstract class WC_Product_Importer implements WC_Importer_Interface {
public function get_params() { public function get_params() {
return $this->params; return $this->params;
} }
/** /**
* Get file pointer position from the last read. * 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. * @param int $product_id Product ID.
* @return int * @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 ) ) { if ( empty( $url ) ) {
return 0; return 0;
} }
@ -590,7 +590,7 @@ abstract class WC_Product_Importer implements WC_Importer_Interface {
* @param string $name Attribute name. * @param string $name Attribute name.
* @return int * @return int
*/ */
protected function get_attribute_taxonomy_id( $raw_name ) { public function get_attribute_taxonomy_id( $raw_name ) {
global $wpdb, $wc_product_attributes; global $wpdb, $wc_product_attributes;
// These are exported as labels, so convert the label to a name if possible first. // 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() { public function includes() {
// API server / response handlers. // 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-exception.php' );
include_once( dirname( __FILE__ ) . '/api/legacy/v3/class-wc-api-server.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/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-json-handler.php' );
// Authentication. // 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(); $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-resource.php' );
include_once( dirname( __FILE__ ) . '/api/legacy/v3/class-wc-api-coupons.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-customers.php' );
include_once( dirname( __FILE__ ) . '/api/legacy/v3/class-wc-api-orders.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-products.php' );
include_once( dirname( __FILE__ ) . '/api/legacy/v3/class-wc-api-reports.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-taxes.php' );
include_once( dirname( __FILE__ ) . '/api/legacy/v3/class-wc-api-webhooks.php' ); include_once( dirname( __FILE__ ) . '/../api/legacy/v3/class-wc-api-webhooks.php' );
// Allow plugins to load other response handlers or resource classes. // Allow plugins to load other response handlers or resource classes.
do_action( 'woocommerce_api_loaded' ); do_action( 'woocommerce_api_loaded' );
@ -186,20 +186,20 @@ class WC_Legacy_API {
private function handle_v1_rest_api_request() { private function handle_v1_rest_api_request() {
// Include legacy required files for 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/class-wc-api-server.php' );
include_once( dirname( __FILE__ ) . '/api/legacy/v1/interface-wc-api-handler.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-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-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(); $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-resource.php' );
include_once( dirname( __FILE__ ) . '/api/legacy/v1/class-wc-api-coupons.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-customers.php' );
include_once( dirname( __FILE__ ) . '/api/legacy/v1/class-wc-api-orders.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-products.php' );
include_once( dirname( __FILE__ ) . '/api/legacy/v1/class-wc-api-reports.php' ); include_once( dirname( __FILE__ ) . '/../api/legacy/v1/class-wc-api-reports.php' );
// Allow plugins to load other response handlers or resource classes. // Allow plugins to load other response handlers or resource classes.
do_action( 'woocommerce_api_loaded' ); do_action( 'woocommerce_api_loaded' );
@ -232,21 +232,21 @@ class WC_Legacy_API {
* @deprecated 2.6.0 * @deprecated 2.6.0
*/ */
private function handle_v2_rest_api_request() { 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-exception.php' );
include_once( dirname( __FILE__ ) . '/api/legacy/v2/class-wc-api-server.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/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-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(); $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-resource.php' );
include_once( dirname( __FILE__ ) . '/api/legacy/v2/class-wc-api-coupons.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-customers.php' );
include_once( dirname( __FILE__ ) . '/api/legacy/v2/class-wc-api-orders.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-products.php' );
include_once( dirname( __FILE__ ) . '/api/legacy/v2/class-wc-api-reports.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-webhooks.php' );
// allow plugins to load other response handlers or resource classes. // allow plugins to load other response handlers or resource classes.
do_action( 'woocommerce_api_loaded' ); do_action( 'woocommerce_api_loaded' );

View File

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

@ -773,7 +773,7 @@ function wc_print_js() {
*/ */
function wc_setcookie( $name, $value, $expire = 0, $secure = false ) { function wc_setcookie( $name, $value, $expire = 0, $secure = false ) {
if ( ! headers_sent() ) { if ( ! headers_sent() ) {
setcookie( $name, $value, $expire, COOKIEPATH ? COOKIEPATH : '/', COOKIE_DOMAIN, $secure ); setcookie( $name, $value, $expire, COOKIEPATH ? COOKIEPATH : '/', COOKIE_DOMAIN, $secure, apply_filters( 'woocommerce_cookie_httponly', false, $name, $value, $expire, $secure ) );
} elseif ( defined( 'WP_DEBUG' ) && WP_DEBUG ) { } elseif ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
headers_sent( $file, $line ); headers_sent( $file, $line );
trigger_error( "{$name} cookie cannot be set - headers already sent by {$file} on line {$line}", E_USER_NOTICE ); trigger_error( "{$name} cookie cannot be set - headers already sent by {$file} on line {$line}", E_USER_NOTICE );

View File

@ -4,10 +4,10 @@
* *
* Where functions come to die. * Where functions come to die.
* *
* @author WooThemes * @author Automattic
* @category Core * @category Core
* @package WooCommerce/Functions * @package WooCommerce\Functions
* @version 2.1.0 * @version 3.3.0
*/ */
if ( ! defined( 'ABSPATH' ) ) { if ( ! defined( 'ABSPATH' ) ) {
@ -17,17 +17,20 @@ if ( ! defined( 'ABSPATH' ) ) {
/** /**
* Runs a deprecated action with notice only if used. * Runs a deprecated action with notice only if used.
* *
* @since 3.0.0 * @since 3.0.0
* @param string $action * @param string $tag The name of the action hook.
* @param array $args * @param array $args Array of additional function arguments to be passed to do_action().
* @param string $deprecated_in * @param string $version The version of WooCommerce that deprecated the hook.
* @param string $replacement * @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 ) { function wc_do_deprecated_action( $tag, $args, $version, $replacement = null, $message = null ) {
if ( has_action( $action ) ) { if ( ! has_action( $tag ) ) {
wc_deprecated_function( 'Action: ' . $action, $deprecated_in, $replacement ); return;
do_action_ref_array( $action, $args );
} }
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 // @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. * 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() ); do_action( 'woocommerce_order_refunded', $order->get_id(), $refund->get_id() );
} catch ( Exception $e ) { } 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() ); return new WP_Error( 'error', $e->getMessage() );
} }

View File

@ -484,10 +484,14 @@ function wc_track_product_view() {
$viewed_products = (array) explode( '|', $_COOKIE['woocommerce_recently_viewed'] ); $viewed_products = (array) explode( '|', $_COOKIE['woocommerce_recently_viewed'] );
} }
if ( ! in_array( $post->ID, $viewed_products ) ) { // Unset if already in viewed products list.
$viewed_products[] = $post->ID; $keys = array_flip( $viewed_products );
if ( isset( $keys[ $post->ID ] ) ) {
unset( $viewed_products[ $keys[ $post->ID ] ] );
} }
$viewed_products[] = $post->ID;
if ( count( $viewed_products ) > 15 ) { if ( count( $viewed_products ) > 15 ) {
array_shift( $viewed_products ); array_shift( $viewed_products );
} }

View File

@ -653,33 +653,45 @@ if ( ! function_exists( 'woocommerce_template_loop_category_title' ) ) {
<?php <?php
} }
} }
/**
* Insert the opening anchor tag for products in the loop. if ( ! function_exists( 'woocommerce_template_loop_product_link_open' ) ) {
*/ /**
function woocommerce_template_loop_product_link_open() { * Insert the opening anchor tag for products in the loop.
echo '<a href="' . esc_url( get_the_permalink() ) . '" class="woocommerce-LoopProduct-link woocommerce-loop-product__link">'; */
} function woocommerce_template_loop_product_link_open() {
/** echo '<a href="' . esc_url( get_the_permalink() ) . '" class="woocommerce-LoopProduct-link woocommerce-loop-product__link">';
* Insert the opening anchor tag for products in the loop. }
*/
function woocommerce_template_loop_product_link_close() {
echo '</a>';
} }
/** if ( ! function_exists( 'woocommerce_template_loop_product_link_close' ) ) {
* Insert the opening anchor tag for categories in the loop. /**
* * Insert the opening anchor tag for products in the loop.
* @param int|object|string $category Category ID, Object or String. */
*/ function woocommerce_template_loop_product_link_close() {
function woocommerce_template_loop_category_link_open( $category ) { echo '</a>';
echo '<a href="' . esc_url( get_term_link( $category, 'product_cat' ) ) . '">'; }
} }
/**
* Insert the closing anchor tag for categories in the loop. if ( ! function_exists( 'woocommerce_template_loop_category_link_open' ) ) {
*/ /**
function woocommerce_template_loop_category_link_close() { * Insert the opening anchor tag for categories in the loop.
echo '</a>'; *
* @param int|object|string $category Category ID, Object or String.
*/
function woocommerce_template_loop_category_link_open( $category ) {
echo '<a href="' . esc_url( get_term_link( $category, 'product_cat' ) ) . '">';
}
} }
if ( ! function_exists( 'woocommerce_template_loop_category_link_close' ) ) {
/**
* Insert the closing anchor tag for categories in the loop.
*/
function woocommerce_template_loop_category_link_close() {
echo '</a>';
}
}
if ( ! function_exists( 'woocommerce_taxonomy_archive_description' ) ) { if ( ! function_exists( 'woocommerce_taxonomy_archive_description' ) ) {
/** /**
@ -1939,7 +1951,7 @@ if ( ! function_exists( 'woocommerce_form_field' ) ) {
// Custom attribute handling. // Custom attribute handling.
$custom_attributes = array(); $custom_attributes = array();
$args['custom_attributes'] = array_filter( (array) $args['custom_attributes'] ); $args['custom_attributes'] = array_filter( (array) $args['custom_attributes'], 'strlen' );
if ( $args['maxlength'] ) { if ( $args['maxlength'] ) {
$args['custom_attributes']['maxlength'] = absint( $args['maxlength'] ); $args['custom_attributes']['maxlength'] = absint( $args['maxlength'] );

View File

@ -50,21 +50,22 @@ function wc_update_200_file_paths() {
*/ */
function wc_update_200_permalinks() { function wc_update_200_permalinks() {
// Setup default permalinks if shop page is defined. // Setup default permalinks if shop page is defined.
$permalinks = get_option( 'woocommerce_permalinks' ); $permalinks = get_option( 'woocommerce_permalinks' );
$shop_page_id = wc_get_page_id( 'shop' ); $shop_page_id = wc_get_page_id( 'shop' );
if ( empty( $permalinks ) && $shop_page_id > 0 ) { 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_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' ); $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' ); $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' ) ) { if ( 'yes' == get_option( 'woocommerce_prepend_shop_page_to_products' ) ) {
$product_base = trailingslashit( $base_slug ); $product_base = trailingslashit( $base_slug );
} else { } 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 ); $product_base = trailingslashit( $product_slug );
} else { } else {
$product_base = trailingslashit( _x( 'product', 'slug', 'woocommerce' ) ); $product_base = trailingslashit( _x( 'product', 'slug', 'woocommerce' ) );
@ -76,10 +77,10 @@ function wc_update_200_permalinks() {
} }
$permalinks = array( $permalinks = array(
'product_base' => untrailingslashit( $product_base ), 'product_base' => untrailingslashit( $product_base ),
'category_base' => untrailingslashit( $category_base . $category_slug ), 'category_base' => untrailingslashit( $category_base . $category_slug ),
'attribute_base' => untrailingslashit( $category_base ), 'attribute_base' => untrailingslashit( $category_base ),
'tag_base' => untrailingslashit( $category_base . $tag_slug ), 'tag_base' => untrailingslashit( $category_base . $tag_slug ),
); );
update_option( 'woocommerce_permalinks', $permalinks ); update_option( 'woocommerce_permalinks', $permalinks );
@ -119,7 +120,7 @@ function wc_update_200_taxrates() {
global $wpdb; global $wpdb;
// Update tax rates. // Update tax rates.
$loop = 0; $loop = 0;
$tax_rates = get_option( 'woocommerce_tax_rates' ); $tax_rates = get_option( 'woocommerce_tax_rates' );
if ( $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 * @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. // 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'. // Reverse with UPDATE `wpwc_postmeta` SET meta_key = '_order_items' WHERE meta_key = '_order_items_old'.
$order_item_rows = $wpdb->get_results( " $order_item_rows = $wpdb->get_results(
SELECT meta_value, post_id FROM {$wpdb->postmeta} "SELECT meta_value, post_id FROM {$wpdb->postmeta} WHERE meta_key = '_order_items'"
WHERE meta_key = '_order_items' );
" );
foreach ( $order_item_rows as $order_item_row ) { foreach ( $order_item_rows as $order_item_row ) {
@ -231,21 +231,24 @@ function wc_update_200_line_items() {
foreach ( $order_items as $order_item ) { foreach ( $order_items as $order_item ) {
if ( ! isset( $order_item['line_total'] ) && isset( $order_item['taxrate'] ) && isset( $order_item['cost'] ) ) { 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_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_total'] = $order_item['cost'] * $order_item['qty'];
$order_item['line_subtotal_tax'] = $order_item['line_tax']; $order_item['line_subtotal_tax'] = $order_item['line_tax'];
$order_item['line_subtotal'] = $order_item['line_total']; $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_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_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_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_subtotal'] = isset( $order_item['line_subtotal'] ) ? $order_item['line_subtotal'] : 0;
$item_id = wc_add_order_item( $order_item_row->post_id, array( $item_id = wc_add_order_item(
'order_item_name' => $order_item['name'], $order_item_row->post_id,
'order_item_type' => 'line_item', array(
) ); 'order_item_name' => $order_item['name'],
'order_item_type' => 'line_item',
)
);
// Add line item meta. // Add line item meta.
if ( $item_id ) { if ( $item_id ) {
@ -274,19 +277,25 @@ function wc_update_200_line_items() {
// Insert meta rows at once. // Insert meta rows at once.
if ( count( $meta_rows ) > 0 ) { if ( count( $meta_rows ) > 0 ) {
$wpdb->query( $wpdb->prepare( " $wpdb->query(
INSERT INTO {$wpdb->prefix}woocommerce_order_itemmeta ( order_item_id, meta_key, meta_value ) $wpdb->prepare(
VALUES " . implode( ',', $meta_rows ) . '; "INSERT INTO {$wpdb->prefix}woocommerce_order_itemmeta ( order_item_id, meta_key, meta_value )
', $order_item_row->post_id ) ); VALUES " . implode( ',', $meta_rows ) . ';', // @codingStandardsIgnoreLine
$order_item_row->post_id
)
);
} }
// Delete from DB (rename). // Delete from DB (rename).
$wpdb->query( $wpdb->prepare( " $wpdb->query(
UPDATE {$wpdb->postmeta} $wpdb->prepare(
SET meta_key = '_order_items_old' "UPDATE {$wpdb->postmeta}
WHERE meta_key = '_order_items' SET meta_key = '_order_items_old'
AND post_id = %d WHERE meta_key = '_order_items'
", $order_item_row->post_id ) ); AND post_id = %d",
$order_item_row->post_id
)
);
} }
unset( $meta_rows, $item_id, $order_item ); 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. // 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'. // Reverse with UPDATE `wpwc_postmeta` SET meta_key = '_order_taxes' WHERE meta_key = '_order_taxes_old'.
$order_tax_rows = $wpdb->get_results( " $order_tax_rows = $wpdb->get_results(
SELECT meta_value, post_id FROM {$wpdb->postmeta} "SELECT meta_value, post_id FROM {$wpdb->postmeta}
WHERE meta_key = '_order_taxes' WHERE meta_key = '_order_taxes'"
" ); );
foreach ( $order_tax_rows as $order_tax_row ) { foreach ( $order_tax_rows as $order_tax_row ) {
@ -311,10 +320,12 @@ function wc_update_200_line_items() {
continue; continue;
} }
$item_id = wc_add_order_item( $order_tax_row->post_id, array( $item_id = wc_add_order_item(
'order_item_name' => $order_tax['label'], $order_tax_row->post_id, array(
'order_item_type' => 'tax', 'order_item_name' => $order_tax['label'],
) ); 'order_item_type' => 'tax',
)
);
// Add line item meta. // Add line item meta.
if ( $item_id ) { if ( $item_id ) {
@ -324,12 +335,15 @@ function wc_update_200_line_items() {
} }
// Delete from DB (rename). // Delete from DB (rename).
$wpdb->query( $wpdb->prepare( " $wpdb->query(
UPDATE {$wpdb->postmeta} $wpdb->prepare(
SET meta_key = '_order_taxes_old' "UPDATE {$wpdb->postmeta}
WHERE meta_key = '_order_taxes' SET meta_key = '_order_taxes_old'
AND post_id = %d WHERE meta_key = '_order_taxes'
", $order_tax_row->post_id ) ); AND post_id = %d",
$order_tax_row->post_id
)
);
unset( $tax_amount ); unset( $tax_amount );
} }
@ -347,11 +361,13 @@ function wc_update_200_images() {
// cleaning up afterwards like nice people do. // cleaning up afterwards like nice people do.
foreach ( array( 'catalog', 'single', 'thumbnail' ) as $value ) { foreach ( array( 'catalog', 'single', 'thumbnail' ) as $value ) {
$old_settings = array_filter( array( $old_settings = array_filter(
'width' => get_option( 'woocommerce_' . $value . '_image_width' ), array(
'height' => get_option( 'woocommerce_' . $value . '_image_height' ), 'width' => get_option( 'woocommerce_' . $value . '_image_width' ),
'crop' => get_option( 'woocommerce_' . $value . '_image_crop' ), '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 ) ) { 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() { function wc_update_220_order_status() {
global $wpdb; global $wpdb;
$wpdb->query( " $wpdb->query(
UPDATE {$wpdb->posts} as posts "UPDATE {$wpdb->posts} as posts
LEFT JOIN {$wpdb->term_relationships} AS rel ON posts.ID = rel.object_id 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->term_taxonomy} AS tax USING( term_taxonomy_id )
LEFT JOIN {$wpdb->terms} AS term USING( term_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' WHERE posts.post_type = 'shop_order'
AND posts.post_status = 'publish' AND posts.post_status = 'publish'
AND tax.taxonomy = 'shop_order_status' AND tax.taxonomy = 'shop_order_status'
AND term.slug LIKE 'pending%'; AND term.slug LIKE 'pending%';"
"
); );
$wpdb->query( " $wpdb->query(
UPDATE {$wpdb->posts} as posts "UPDATE {$wpdb->posts} as posts
LEFT JOIN {$wpdb->term_relationships} AS rel ON posts.ID = rel.object_id 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->term_taxonomy} AS tax USING( term_taxonomy_id )
LEFT JOIN {$wpdb->terms} AS term USING( term_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' WHERE posts.post_type = 'shop_order'
AND posts.post_status = 'publish' AND posts.post_status = 'publish'
AND tax.taxonomy = 'shop_order_status' AND tax.taxonomy = 'shop_order_status'
AND term.slug LIKE 'processing%'; AND term.slug LIKE 'processing%';"
"
); );
$wpdb->query( " $wpdb->query(
UPDATE {$wpdb->posts} as posts "UPDATE {$wpdb->posts} as posts
LEFT JOIN {$wpdb->term_relationships} AS rel ON posts.ID = rel.object_id 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->term_taxonomy} AS tax USING( term_taxonomy_id )
LEFT JOIN {$wpdb->terms} AS term USING( term_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' WHERE posts.post_type = 'shop_order'
AND posts.post_status = 'publish' AND posts.post_status = 'publish'
AND tax.taxonomy = 'shop_order_status' AND tax.taxonomy = 'shop_order_status'
AND term.slug LIKE 'on-hold%'; AND term.slug LIKE 'on-hold%';"
"
); );
$wpdb->query( " $wpdb->query(
UPDATE {$wpdb->posts} as posts "UPDATE {$wpdb->posts} as posts
LEFT JOIN {$wpdb->term_relationships} AS rel ON posts.ID = rel.object_id 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->term_taxonomy} AS tax USING( term_taxonomy_id )
LEFT JOIN {$wpdb->terms} AS term USING( term_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' WHERE posts.post_type = 'shop_order'
AND posts.post_status = 'publish' AND posts.post_status = 'publish'
AND tax.taxonomy = 'shop_order_status' AND tax.taxonomy = 'shop_order_status'
AND term.slug LIKE 'completed%'; AND term.slug LIKE 'completed%';"
"
); );
$wpdb->query( " $wpdb->query(
UPDATE {$wpdb->posts} as posts "UPDATE {$wpdb->posts} as posts
LEFT JOIN {$wpdb->term_relationships} AS rel ON posts.ID = rel.object_id 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->term_taxonomy} AS tax USING( term_taxonomy_id )
LEFT JOIN {$wpdb->terms} AS term USING( term_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' WHERE posts.post_type = 'shop_order'
AND posts.post_status = 'publish' AND posts.post_status = 'publish'
AND tax.taxonomy = 'shop_order_status' AND tax.taxonomy = 'shop_order_status'
AND term.slug LIKE 'cancelled%'; AND term.slug LIKE 'cancelled%';"
"
); );
$wpdb->query( " $wpdb->query(
UPDATE {$wpdb->posts} as posts "UPDATE {$wpdb->posts} as posts
LEFT JOIN {$wpdb->term_relationships} AS rel ON posts.ID = rel.object_id 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->term_taxonomy} AS tax USING( term_taxonomy_id )
LEFT JOIN {$wpdb->terms} AS term USING( term_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' WHERE posts.post_type = 'shop_order'
AND posts.post_status = 'publish' AND posts.post_status = 'publish'
AND tax.taxonomy = 'shop_order_status' AND tax.taxonomy = 'shop_order_status'
AND term.slug LIKE 'refunded%'; AND term.slug LIKE 'refunded%';"
"
); );
$wpdb->query( " $wpdb->query(
UPDATE {$wpdb->posts} as posts "UPDATE {$wpdb->posts} as posts
LEFT JOIN {$wpdb->term_relationships} AS rel ON posts.ID = rel.object_id 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->term_taxonomy} AS tax USING( term_taxonomy_id )
LEFT JOIN {$wpdb->terms} AS term USING( term_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' WHERE posts.post_type = 'shop_order'
AND posts.post_status = 'publish' AND posts.post_status = 'publish'
AND tax.taxonomy = 'shop_order_status' 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() { function wc_update_220_variations() {
global $wpdb; global $wpdb;
// Update variations which manage stock. // Update variations which manage stock.
$update_variations = $wpdb->get_results( " $update_variations = $wpdb->get_results(
SELECT DISTINCT posts.ID AS variation_id, posts.post_parent AS variation_parent FROM {$wpdb->posts} as posts "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 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' 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' WHERE posts.post_type = 'product_variation'
AND postmeta.meta_value IS NOT NULL AND postmeta.meta_value IS NOT NULL
AND postmeta.meta_value != '' AND postmeta.meta_value != ''
AND postmeta2.meta_value IS NULL AND postmeta2.meta_value IS NULL"
" ); );
foreach ( $update_variations as $variation ) { foreach ( $update_variations as $variation ) {
$parent_backorders = get_post_meta( $variation->variation_parent, '_backorders', true ); $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; $has_classes = count( WC()->shipping->get_shipping_classes() ) > 0;
$cost_key = $has_classes ? 'no_class_cost' : 'cost'; $cost_key = $has_classes ? 'no_class_cost' : 'cost';
$min_fee = $shipping_method->get_option( 'minimum_fee' ); $min_fee = $shipping_method->get_option( 'minimum_fee' );
$math_cost_strings = array( 'cost' => array(), 'no_class_cost' => array() ); $math_cost_strings = array(
$math_cost_strings[ $cost_key ][] = $shipping_method->get_option( 'cost' ); '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; $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']; $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 ) { foreach ( $flat_rates as $shipping_class => $rate ) {
$rate_key = 'class_cost_' . $shipping_class; $rate_key = 'class_cost_' . $shipping_class;
if ( $rate['cost'] || $rate['fee'] ) { if ( $rate['cost'] || $rate['fee'] ) {
@ -798,7 +814,7 @@ function wc_update_240_api_keys() {
// Get user data. // Get user data.
foreach ( $api_users as $_user ) { foreach ( $api_users as $_user ) {
$user = get_userdata( $_user->user_id ); $user = get_userdata( $_user->user_id );
$apps_keys[] = array( $apps_keys[] = array(
'user_id' => $user->ID, 'user_id' => $user->ID,
'permissions' => $user->woocommerce_api_key_permissions, 'permissions' => $user->woocommerce_api_key_permissions,
@ -844,12 +860,14 @@ function wc_update_240_webhooks() {
* Webhooks. * Webhooks.
* Make sure order.update webhooks get the woocommerce_order_edit_status hook. * Make sure order.update webhooks get the woocommerce_order_edit_status hook.
*/ */
$order_update_webhooks = get_posts( array( $order_update_webhooks = get_posts(
'posts_per_page' => -1, array(
'post_type' => 'shop_webhook', 'posts_per_page' => -1,
'meta_key' => '_topic', 'post_type' => 'shop_webhook',
'meta_value' => 'order.updated', 'meta_key' => '_topic',
) ); 'meta_value' => 'order.updated',
)
);
foreach ( $order_update_webhooks as $order_update_webhook ) { foreach ( $order_update_webhooks as $order_update_webhook ) {
$webhook = new WC_Webhook( $order_update_webhook->ID ); $webhook = new WC_Webhook( $order_update_webhook->ID );
$webhook->set_topic( 'order.updated' ); $webhook->set_topic( 'order.updated' );
@ -867,11 +885,13 @@ function wc_update_240_refunds() {
* Refunds for full refunded orders. * Refunds for full refunded orders.
* Update fully refunded orders to ensure they have a refund line item so reports add up. * Update fully refunded orders to ensure they have a refund line item so reports add up.
*/ */
$refunded_orders = get_posts( array( $refunded_orders = get_posts(
'posts_per_page' => -1, array(
'post_type' => 'shop_order', 'posts_per_page' => -1,
'post_status' => array( 'wc-refunded' ), 'post_type' => 'shop_order',
) ); 'post_status' => array( 'wc-refunded' ),
)
);
// Ensure emails are disabled during this update routine. // Ensure emails are disabled during this update routine.
remove_all_actions( 'woocommerce_order_status_refunded_notification' ); remove_all_actions( 'woocommerce_order_status_refunded_notification' );
@ -881,22 +901,27 @@ function wc_update_240_refunds() {
foreach ( $refunded_orders as $refunded_order ) { foreach ( $refunded_orders as $refunded_order ) {
$order_total = get_post_meta( $refunded_order->ID, '_order_total', true ); $order_total = get_post_meta( $refunded_order->ID, '_order_total', true );
$refunded_total = $wpdb->get_var( $wpdb->prepare( " $refunded_total = $wpdb->get_var(
SELECT SUM( postmeta.meta_value ) $wpdb->prepare(
FROM $wpdb->postmeta AS postmeta "SELECT SUM( postmeta.meta_value )
INNER JOIN $wpdb->posts AS posts ON ( posts.post_type = 'shop_order_refund' AND posts.post_parent = %d ) FROM $wpdb->postmeta AS postmeta
WHERE postmeta.meta_key = '_refund_amount' INNER JOIN $wpdb->posts AS posts ON ( posts.post_type = 'shop_order_refund' AND posts.post_parent = %d )
AND postmeta.post_id = posts.ID WHERE postmeta.meta_key = '_refund_amount'
", $refunded_order->ID ) ); AND postmeta.post_id = posts.ID",
$refunded_order->ID
)
);
if ( $order_total > $refunded_total ) { if ( $order_total > $refunded_total ) {
wc_create_refund( array( wc_create_refund(
'amount' => $order_total - $refunded_total, array(
'reason' => __( 'Order fully refunded', 'woocommerce' ), 'amount' => $order_total - $refunded_total,
'order_id' => $refunded_order->ID, 'reason' => __( 'Order fully refunded', 'woocommerce' ),
'line_items' => array(), 'order_id' => $refunded_order->ID,
'date' => $refunded_order->post_modified, 'line_items' => array(),
) ); 'date' => $refunded_order->post_modified,
)
);
} }
} }
@ -921,13 +946,13 @@ function wc_update_241_variations() {
global $wpdb; global $wpdb;
// Select variations that don't have any _stock_status implemented on WooCommerce 2.2. // Select variations that don't have any _stock_status implemented on WooCommerce 2.2.
$update_variations = $wpdb->get_results( " $update_variations = $wpdb->get_results(
SELECT DISTINCT posts.ID AS variation_id, posts.post_parent AS variation_parent "SELECT DISTINCT posts.ID AS variation_id, posts.post_parent AS variation_parent
FROM {$wpdb->posts} as posts FROM {$wpdb->posts} as posts
LEFT OUTER JOIN {$wpdb->postmeta} AS postmeta ON posts.ID = postmeta.post_id AND postmeta.meta_key = '_stock_status' 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' WHERE posts.post_type = 'product_variation'
AND postmeta.meta_value IS NULL AND postmeta.meta_value IS NULL"
" ); );
foreach ( $update_variations as $variation ) { foreach ( $update_variations as $variation ) {
// Get the parent _stock_status. // Get the parent _stock_status.
@ -1065,11 +1090,13 @@ function wc_update_260_zone_methods() {
// Move data. // Move data.
foreach ( $old_methods as $old_method ) { foreach ( $old_methods as $old_method ) {
$wpdb->insert( $wpdb->prefix . 'woocommerce_shipping_zone_methods', array( $wpdb->insert(
'zone_id' => $old_method->zone_id, $wpdb->prefix . 'woocommerce_shipping_zone_methods', array(
'method_id' => $old_method->shipping_method_type, 'zone_id' => $old_method->zone_id,
'method_order' => $old_method->shipping_method_order, 'method_id' => $old_method->shipping_method_type,
) ); 'method_order' => $old_method->shipping_method_order,
)
);
$new_instance_id = $wpdb->insert_id; $new_instance_id = $wpdb->insert_id;
@ -1130,13 +1157,13 @@ function wc_update_260_refunds() {
/** /**
* Refund item qty should be negative. * Refund item qty should be negative.
*/ */
$wpdb->query( " $wpdb->query(
UPDATE {$wpdb->prefix}woocommerce_order_itemmeta as item_meta "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->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 LEFT JOIN {$wpdb->posts} as posts ON items.order_id = posts.ID
SET item_meta.meta_value = item_meta.meta_value * -1 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' WHERE item_meta.meta_value > 0 AND item_meta.meta_key = '_qty' AND posts.post_type = 'shop_order_refund'"
" ); );
} }
/** /**
@ -1158,12 +1185,14 @@ function wc_update_300_webhooks() {
* Make sure product.update webhooks get the woocommerce_product_quick_edit_save * Make sure product.update webhooks get the woocommerce_product_quick_edit_save
* and woocommerce_product_bulk_edit_save hooks. * and woocommerce_product_bulk_edit_save hooks.
*/ */
$product_update_webhooks = get_posts( array( $product_update_webhooks = get_posts(
'posts_per_page' => -1, array(
'post_type' => 'shop_webhook', 'posts_per_page' => -1,
'meta_key' => '_topic', 'post_type' => 'shop_webhook',
'meta_value' => 'product.updated', 'meta_key' => '_topic',
) ); 'meta_value' => 'product.updated',
)
);
foreach ( $product_update_webhooks as $product_update_webhook ) { foreach ( $product_update_webhooks as $product_update_webhook ) {
$webhook = new WC_Webhook( $product_update_webhook->ID ); $webhook = new WC_Webhook( $product_update_webhook->ID );
$webhook->set_topic( 'product.updated' ); $webhook->set_topic( 'product.updated' );
@ -1197,12 +1226,14 @@ function wc_update_300_grouped_products() {
foreach ( $parents as $parent_id ) { foreach ( $parents as $parent_id ) {
$parent = wc_get_product( $parent_id ); $parent = wc_get_product( $parent_id );
if ( $parent && $parent->is_type( 'grouped' ) ) { if ( $parent && $parent->is_type( 'grouped' ) ) {
$children_ids = get_posts( array( $children_ids = get_posts(
'post_parent' => $parent_id, array(
'posts_per_page' => -1, 'post_parent' => $parent_id,
'post_type' => 'product', 'posts_per_page' => -1,
'fields' => 'ids', 'post_type' => 'product',
) ); 'fields' => 'ids',
)
);
update_post_meta( $parent_id, '_children', $children_ids ); update_post_meta( $parent_id, '_children', $children_ids );
// Update children to remove the parent. // Update children to remove the parent.
@ -1241,39 +1272,57 @@ function wc_update_300_product_visibility() {
WC_Install::create_terms(); 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 ) ); $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 ) ); $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 ) ); $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 ) ); $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 ) ); $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 ) ); $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 ) ); $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 ) ); $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 ) ); $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 ) );
} }
} }
@ -1373,12 +1422,10 @@ function wc_update_320_mexican_states() {
foreach ( $mx_states as $old => $new ) { foreach ( $mx_states as $old => $new ) {
$wpdb->query( $wpdb->query(
$wpdb->prepare( $wpdb->prepare(
" "UPDATE $wpdb->postmeta
UPDATE $wpdb->postmeta SET meta_value = %s
SET meta_value = %s WHERE meta_key IN ( '_billing_state', '_shipping_state' )
WHERE meta_key IN ( '_billing_state', '_shipping_state' ) AND meta_value = %s",
AND meta_value = %s
",
$new, $old $new, $old
) )
); );
@ -1432,6 +1479,34 @@ function wc_update_330_image_options() {
} }
} }
/**
* 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' );
}
}
/** /**
* Update DB Version. * Update DB Version.
*/ */

View File

@ -449,6 +449,7 @@ function wc_get_customer_available_downloads( $customer_id ) {
'download_id' => $result->download_id, 'download_id' => $result->download_id,
'product_id' => $_product->get_id(), 'product_id' => $_product->get_id(),
'product_name' => $_product->get_name(), 'product_name' => $_product->get_name(),
'product_url' => $_product->is_visible() ? $_product->get_permalink() : '', // Since 3.3.0.
'download_name' => $download_name, 'download_name' => $download_name,
'order_id' => $order->get_id(), 'order_id' => $order->get_id(),
'order_key' => $order->get_order_key(), 'order_key' => $order->get_order_key(),

View File

@ -33,7 +33,7 @@ class WC_Widget_Recently_Viewed extends WC_Widget {
'type' => 'number', 'type' => 'number',
'step' => 1, 'step' => 1,
'min' => 1, 'min' => 1,
'max' => '', 'max' => 15,
'std' => 10, 'std' => 10,
'label' => __( 'Number of products to show', 'woocommerce' ), 'label' => __( 'Number of products to show', 'woocommerce' ),
), ),

View File

@ -10,6 +10,8 @@
"license": "GPL-3.0+", "license": "GPL-3.0+",
"main": "Gruntfile.js", "main": "Gruntfile.js",
"scripts": { "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": "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: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" "test:single": "cross-env NODE_CONFIG_DIR='./tests/e2e-tests/config' BABEL_ENV=commonjs mocha --compilers js:babel-register"

View File

@ -15,15 +15,20 @@
<exclude-pattern>*/vendor/*</exclude-pattern> <exclude-pattern>*/vendor/*</exclude-pattern>
<!-- Configs --> <!-- Configs -->
<config name="minimum_supported_wp_version" value="4.5" /> <config name="minimum_supported_wp_version" value="4.7" />
<config name="testVersion" value="5.2-"/> <config name="testVersion" value="5.2-"/>
<!-- Rules --> <!-- Rules -->
<rule ref="PHPCompatibility"/> <rule ref="PHPCompatibility"/>
<rule ref="WordPress"> <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.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>
<rule ref="WordPress.VIP.ValidatedSanitizedInput"> <rule ref="WordPress.VIP.ValidatedSanitizedInput">
<properties> <properties>
@ -40,4 +45,7 @@
<property name="text_domain" type="array" value="woocommerce" /> <property name="text_domain" type="array" value="woocommerce" />
</properties> </properties>
</rule> </rule>
<rule ref="WordPress.Files.FileName.InvalidClassFileName">
<exclude-pattern>includes/**/abstract-*.php</exclude-pattern>
</rule>
</ruleset> </ruleset>

View File

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

View File

@ -10,8 +10,8 @@
* happen. When this occurs the version of the template file will be bumped and * happen. When this occurs the version of the template file will be bumped and
* the readme will list any important changes. * the readme will list any important changes.
* *
* @see https://docs.woocommerce.com/document/template-structure/ * @see https://docs.woocommerce.com/document/template-structure/
* @author WooThemes * @author Automattic
* @package WooCommerce/Templates * @package WooCommerce/Templates
* @version 3.3.0 * @version 3.3.0
*/ */
@ -22,7 +22,7 @@ if ( ! defined( 'ABSPATH' ) ) {
?> ?>
<section class="woocommerce-order-downloads"> <section class="woocommerce-order-downloads">
<?php if ( isset( $show_title ) ) : ?> <?php if ( isset( $show_title ) ) : ?>
<h2 class="woocommerce-order-downloads__title"><?php _e( 'Downloads', 'woocommerce' ); ?></h2> <h2 class="woocommerce-order-downloads__title"><?php esc_html_e( 'Downloads', 'woocommerce' ); ?></h2>
<?php endif; ?> <?php endif; ?>
<table class="woocommerce-table woocommerce-table--order-downloads shop_table shop_table_responsive order_details"> <table class="woocommerce-table woocommerce-table--order-downloads shop_table shop_table_responsive order_details">
@ -37,32 +37,36 @@ if ( ! defined( 'ABSPATH' ) ) {
<?php foreach ( $downloads as $download ) : ?> <?php foreach ( $downloads as $download ) : ?>
<tr> <tr>
<?php foreach ( wc_get_account_downloads_columns() as $column_id => $column_name ) : ?> <?php foreach ( wc_get_account_downloads_columns() as $column_id => $column_name ) : ?>
<td class="<?php echo esc_attr( $column_id ); ?>" data-title="<?php echo esc_attr( $column_name ); ?>"><?php <td class="<?php echo esc_attr( $column_id ); ?>" data-title="<?php echo esc_attr( $column_name ); ?>">
<?php
if ( has_action( 'woocommerce_account_downloads_column_' . $column_id ) ) { if ( has_action( 'woocommerce_account_downloads_column_' . $column_id ) ) {
do_action( 'woocommerce_account_downloads_column_' . $column_id, $download ); do_action( 'woocommerce_account_downloads_column_' . $column_id, $download );
} else { } else {
switch ( $column_id ) { switch ( $column_id ) {
case 'download-product' : ?> case 'download-product':
<a href="<?php echo esc_url( get_permalink( $download['product_id'] ) ); ?>"><?php echo esc_html( $download['product_name'] ); ?></a> if ( $download['product_url'] ) {
<?php echo '<a href="' . esc_url( $download['product_url'] ) . '">' . esc_html( $download['product_name'] ) . '</a>';
break; } else {
case 'download-file' : ?> echo esc_html( $download['product_name'] );
<a href="<?php echo esc_url( $download['download_url'] ); ?>" class="woocommerce-MyAccount-downloads-file button alt"><?php echo esc_html( $download['download_name'] ); ?></a> }
<?php break;
break; case 'download-file':
case 'download-remaining' : echo '<a href="' . esc_url( $download['download_url'] ) . '" class="woocommerce-MyAccount-downloads-file button alt">' . esc_html( $download['download_name'] ) . '</a>';
echo is_numeric( $download['downloads_remaining'] ) ? esc_html( $download['downloads_remaining'] ) : __( '&infin;', 'woocommerce' ); break;
break; case 'download-remaining':
case 'download-expires' : ?> echo is_numeric( $download['downloads_remaining'] ) ? esc_html( $download['downloads_remaining'] ) : esc_html__( '&infin;', 'woocommerce' );
<?php if ( ! empty( $download['access_expires'] ) ) : ?> break;
<time datetime="<?php echo date( 'Y-m-d', strtotime( $download['access_expires'] ) ); ?>" title="<?php echo esc_attr( strtotime( $download['access_expires'] ) ); ?>"><?php echo date_i18n( get_option( 'date_format' ), strtotime( $download['access_expires'] ) ); ?></time> case 'download-expires':
<?php else : ?> if ( ! empty( $download['access_expires'] ) ) {
<?php _e( 'Never', 'woocommerce' ); ?> echo '<time datetime="' . esc_attr( date( 'Y-m-d', strtotime( $download['access_expires'] ) ) ) . '" title="' . esc_attr( strtotime( $download['access_expires'] ) ) . '">' . esc_html( date_i18n( get_option( 'date_format' ), strtotime( $download['access_expires'] ) ) ) . '</time>';
<?php endif; } else {
break; esc_html_e( 'Never', 'woocommerce' );
}
break;
} }
} }
?></td> ?>
</td>
<?php endforeach; ?> <?php endforeach; ?>
</tr> </tr>
<?php endforeach; ?> <?php endforeach; ?>

View File

@ -15,17 +15,11 @@ if ( ! defined( 'ABSPATH' ) ) {
} }
?> ?>
<script type="text/template" id="tmpl-variation-template"> <script type="text/template" id="tmpl-variation-template">
<div class="woocommerce-variation-description"> <div class="woocommerce-variation-description">{{{ data.variation.variation_description }}}</div>
{{{ data.variation.variation_description }}}
</div>
<div class="woocommerce-variation-price"> <div class="woocommerce-variation-price">{{{ data.variation.price_html }}}</div>
{{{ data.variation.price_html }}}
</div>
<div class="woocommerce-variation-availability"> <div class="woocommerce-variation-availability">{{{ data.variation.availability_html }}}</div>
{{{ data.variation.availability_html }}}
</div>
</script> </script>
<script type="text/template" id="tmpl-unavailable-variation-template"> <script type="text/template" id="tmpl-unavailable-variation-template">
<p><?php _e( 'Sorry, this product is unavailable. Please choose a different combination.', 'woocommerce' ); ?></p> <p><?php _e( 'Sorry, this product is unavailable. Please choose a different combination.', 'woocommerce' ); ?></p>

View File

@ -3,28 +3,16 @@
if [ $1 == 'before' ]; then 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
if [[ ${RUN_PHPCS} == 1 ]]; then
composer install
fi
# Remove Xdebug from PHP runtime for all PHP version except 7.1 to speed up builds. # 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. # 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 if [[ ${RUN_CODE_COVERAGE} != 1 ]]; then
phpenv config-rm xdebug.ini phpenv config-rm xdebug.ini
fi fi
if [[ ${RUN_PHPCS} == 1 ]]; then
composer install
fi
fi fi
if [ $1 == 'after' ]; then if [ $1 == 'after' ]; then

View File

@ -81,6 +81,21 @@ class WC_Unit_Test_Case extends WP_UnitTestCase {
$this->assertInstanceOf( 'WP_Error', $actual, $message ); $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. * Backport assertNotFalse to PHPUnit 3.6.12 which only runs in PHP 5.2.
* *

View File

@ -1318,7 +1318,7 @@ class WC_Tests_CRUD_Orders extends WC_Unit_Test_Case {
$object->set_shipping_state( 'Boulder' ); $object->set_shipping_state( 'Boulder' );
$object->set_shipping_postcode( '00001' ); $object->set_shipping_postcode( '00001' );
$object->set_shipping_country( 'US' ); $object->set_shipping_country( 'US' );
$this->assertEquals( 'https://maps.google.com/maps?&q=34+Stonepants+avenue%2C+Rockville%2C+Bedrock%2C+Boulder%2C+00001%2C+US&z=16', $object->get_shipping_address_map_url() ); $this->assertEquals( 'https://maps.google.com/maps?&q=34%20Stonepants%20avenue%2C%20Rockville%2C%20Bedrock%2C%20Boulder%2C%2000001%2C%20US&z=16', $object->get_shipping_address_map_url() );
} }
/** /**
@ -1656,6 +1656,21 @@ class WC_Tests_CRUD_Orders extends WC_Unit_Test_Case {
$this->assertEquals( 4, $object->get_remaining_refund_items() ); $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. * Test apply_coupon and remove_coupon with a fixed discount coupon.
* @since 3.2.0 * @since 3.2.0

View File

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

View File

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