Merge branch 'master' into update/gdpr-checkout-customizer

This commit is contained in:
Mike Jolley 2018-04-16 18:02:28 +01:00
commit 860e7a5d23
75 changed files with 3877 additions and 2426 deletions

View File

@ -1,5 +1,49 @@
== Changelog ==
= 3.3.5 - 2018-04-10 =
* Fix - Shop page notice should not appear when edting the "Hello World!" page.
* Fix - Inconsistent order item refund sign.
* Fix - Change `wc_get_price_excluding_tax` to not round the return value so calculations in admin are not pre-rounded.
* Fix - Use minimum price instead of maximum price when ordering variable products from low to high on term archives.
* Fix - `order` and `orderby` on shop page when using rewrite rules.
* Fix - Ajax loading spinner when using twentyseventeen theme.
* Fix - Out of Stock products change stock to On Backorder when imported to update existing products.
* Fix - Visibility dropdown not responding in quick edit when stock management is disabled.
* Fix - Featured paramenter in products endpoint on REST API.
* Fix - Linebreaks in order item meta.
* Fix - Product rating count when updated by admin.
* Tweak - Define array before attempting to append to it.
* Tweak - Change WC WP-CLI commands default per_page value to 100.
* Tweak - Ensure background process class returns `data` as an array.
* Tweak - Increase orders table checkbox column size on small devices.
* Tweak - Better support for infinite scroll in Jetpack.
= 3.3.4 - 2018-03-20 =
* Fix - Fixed undefined index after running setup wizard two times on fresh install.
* Fix - wc_get_loop_class; force columns to be a minimum of 1.
* Fix - Added loading spinner to WC panels in menu admin.
* Fix - Use relative scheme for AJAX endpoint to avoid errors when using a mix of HTTP and HTTPS.
* Fix - Fix SelectWoo templateSelection property.
* Fix - Layered nav support on unsupported theme archives.
* Fix - Prevent full refresh when editing store notice in the customizer.
* Fix - Only append tax label in email content if taxes are enabled.
* Fix - More reliable Jetpack detection.
* Fix - Check if product has weight before calculate weight total in cart.
* Fix - Correctly handle default ordering on the search page.
* Fix - Fix default product category handling in installer.
* Fix - Properly check slugs when updating attributes.
* Fix - Use gallery thumbnail size for variation image switcher.
* Fix - Clear subcategory cache when updating product categories.
* Fix - Round fractional cents when out of base.
* Fix - Inherit 'is variation' from existing attribute during csv import.
* Fix - Set is_shortcode loop prop when outputting subcategories.
* Fix - Reload gateways after updating the order.
* Tweak - Use wc_get_default_products_per_row as the default for product shortcodes.
* Tweak - Add post_excerpt to product search.
* Tweak - Update the description of the user tracking notice in the onboarding wizard.
* Tweak - Add extra data in order mobile view (status and date).
* Tweak - Add profile link to order screen.
= 3.3.3 - 2018-02-21 =
* Fix - Fixed is_numeric check which was affecting order subtotals/totals when using comma decimal separator.
* Fix - Add missing direct script access checks to loop templates.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -826,6 +826,11 @@ table.wc_status_table--tools {
margin-left: 10px;
}
label.stock_status_field {
clear: both;
float: left;
}
.dimensions div {
display: block;
margin: 0.2em 0;
@ -2882,23 +2887,19 @@ table.wc_shipping {
th, td {
display: table-cell !important;
padding: 1em !important;
vertical-align: top;
line-height: 1.75em;
}
td {
&.wc_emails td {
vertical-align: middle;
padding: 7px;
line-height: 2em;
}
tr:nth-child( odd ) td {
background: #f9f9f9;
}
th {
padding: 9px 7px !important;
vertical-align: middle;
}
td.name {
font-weight: 700;
}
@ -2920,16 +2921,10 @@ table.wc_shipping {
margin: 0;
}
}
th.sort {
width: 28px;
padding: 0;
}
td.sort {
padding: 0 7px;
cursor: move;
font-size: 15px;
text-align: center;
vertical-align: middle;
&::before {
content: '\f333';
@ -2941,8 +2936,12 @@ table.wc_shipping {
width: 17px;
float: left;
height: 100%;
line-height: 24px;
}
}
.wc-payment-gateway-method-name {
display: block;
}
.wc-email-settings-table-name {
font-weight: 700;
span {
@ -2958,18 +2957,6 @@ table.wc_shipping {
margin: 0 auto;
}
}
.wc-email-settings-table-actions a {
@include ir();
padding: 0 !important;
height: 2em !important;
width: 2em;
&::after {
@include icon('\f111');
font-family: 'Dashicons';
line-height: 1.85;
}
}
}
.wc-shipping-zone-settings {
th {
@ -3059,9 +3046,6 @@ table.wc-shipping-zones, table.wc-shipping-zone-methods, table.wc-shipping-class
text-align: center;
}
}
tbody td {
padding: 1.5em 1em !important;
}
td.wc-shipping-zones-blank-state, td.wc-shipping-zone-method-blank-state {
background: #f7f1f6 !important;
overflow: hidden;
@ -3298,6 +3282,8 @@ table.wc-shipping-zones, table.wc-shipping-zone-methods, table.wc-shipping-class
text-indent: -9999px;
border-radius: 10em;
position: relative;
margin-top: -1px;
vertical-align: text-top;
&:before {
content: "";
@ -3625,6 +3611,7 @@ img.help_tip {
}
}
.wc_payment_gateways_wrapper,
.wc_emails_wrapper {
padding: 0 15px 10px 0;
}

View File

@ -1,3 +1,35 @@
/**
* WooCommerce Photoswipe styles.
* 1. These styles are required to overwrite default theme button styles (Twenty Twelve adds gradients via background-image).
* 2. For zooming on mobile.
*/
.woocommerce img.pswp__img,
.woocommerce-page img.pswp__img {
max-width: none; /* 2 */
}
button.pswp__button {
box-shadow: none !important;
background-image: url('default-skin/default-skin.png') !important;
}
button.pswp__button,
button.pswp__button:hover,
button.pswp__button--arrow--left::before,
button.pswp__button--arrow--right::before {
background-color: transparent !important; /* 1 */
}
button.pswp__button--arrow--left,
button.pswp__button--arrow--right,
button.pswp__button--arrow--left:hover,
button.pswp__button--arrow--right:hover {
background-image: none !important; /* 1 */
}
button.pswp__button--close:hover {
background-position: 0 -44px;
}
button.pswp__button--zoom:hover {
background-position: -88px 0;
}
/*! PhotoSwipe main CSS by Dmitry Semenov | photoswipe.com | MIT license */
/*
Styles for basic PhotoSwipe functionality (sliding area, open/close transitions)

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -570,30 +570,6 @@ table.variations {
}
}
/**
* Photoswipe
* 1. These styles are required to overwrite default theme button styles (Twenty Twelve adds gradients via background-image).
*/
button.pswp__button,
button.pswp__button:hover,
button.pswp__button--arrow--left::before,
button.pswp__button--arrow--right::before {
background-color: transparent !important; /* 1 */
}
button.pswp__button--close:hover {
background-position: 0 -44px;
}
button.pswp__button--zoom:hover {
background-position: -88px 0;
}
.pswp img {
max-width: none;
}
/**
* Widgets
*/

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1673,47 +1673,6 @@ p.demo_store,
}
}
/**
* Photoswipe
* 1. These styles are required to overwrite default theme button styles (Twenty Twelve adds gradients via background-image).
* 2. For zooming on mobile.
*/
.pswp {
z-index: 999999;
}
.woocommerce img.pswp__img,
.woocommerce-page img.pswp__img {
max-width: none; /* 2 */
}
button.pswp__button {
box-shadow: none !important;
background-image: url('photoswipe/default-skin/default-skin.png') !important;
}
button.pswp__button,
button.pswp__button:hover,
button.pswp__button--arrow--left::before,
button.pswp__button--arrow--right::before {
background-color: transparent !important; /* 1 */
}
button.pswp__button--arrow--left,
button.pswp__button--arrow--right,
button.pswp__button--arrow--left:hover,
button.pswp__button--arrow--right:hover {
background-image: none !important; /* 1 */
}
button.pswp__button--close:hover {
background-position: 0 -44px;
}
button.pswp__button--zoom:hover {
background-position: -88px 0;
}
.woocommerce-message,
.woocommerce-error,
.woocommerce-info {

View File

@ -297,4 +297,50 @@ jQuery( function ( $ ) {
// Attribute term table
$( 'table.attributes-table tbody tr:nth-child(odd)' ).addClass( 'alternate' );
// Toggle gateway on/off.
$( '.wc_gateways' ).on( 'click', '.wc-payment-gateway-method-toggle-enabled', function() {
var $link = $( this ),
$row = $link.closest( 'tr' ),
$table = $row.closest( 'div' ),
$toggle = $link.find( '.woocommerce-input-toggle' );
var data = {
action: 'woocommerce_toggle_gateway_enabled',
security: woocommerce_admin.nonces.gateway_toggle,
gateway_id: $row.data( 'gateway_id' )
};
$table.block({
message: null,
overlayCSS: {
background: '#fff',
opacity: 0.6
}
});
$.ajax( {
url: woocommerce_admin.ajax_url,
data: data,
dataType : 'json',
type : 'POST',
success: function( response ) {
if ( true === response.data ) {
$toggle.removeClass( 'woocommerce-input-toggle--enabled, woocommerce-input-toggle--disabled' );
$toggle.addClass( 'woocommerce-input-toggle--enabled' );
} else if ( false === response.data ) {
$toggle.removeClass( 'woocommerce-input-toggle--enabled, woocommerce-input-toggle--disabled' );
$toggle.addClass( 'woocommerce-input-toggle--disabled' );
} else if ( 'needs_setup' === response.data ) {
window.location.href = $link.attr( 'href' );
}
},
complete: function() {
$table.unblock();
}
} );
return false;
});
});

File diff suppressed because one or more lines are too long

View File

@ -329,6 +329,7 @@ jQuery( function( $ ) {
complete: function() {
unblock( $form );
unblock( $( 'div.cart_totals' ) );
$.scroll_to_notices( $( '[role="alert"]' ) );
}
} );
},
@ -512,6 +513,7 @@ jQuery( function( $ ) {
complete: function() {
unblock( $form );
unblock( $( 'div.cart_totals' ) );
$.scroll_to_notices( $( '[role="alert"]' ) );
}
} );
},
@ -540,6 +542,7 @@ jQuery( function( $ ) {
complete: function() {
unblock( $form );
unblock( $( 'div.cart_totals' ) );
$.scroll_to_notices( $( '[role="alert"]' ) );
}
} );
},

File diff suppressed because one or more lines are too long

View File

@ -512,24 +512,12 @@ jQuery( function( $ ) {
$( document.body ).trigger( 'checkout_error' );
},
scroll_to_notices: function() {
var scrollElement = $( '.woocommerce-NoticeGroup-updateOrderReview, .woocommerce-NoticeGroup-checkout' ),
isSmoothScrollSupported = 'scrollBehavior' in document.documentElement.style;
var scrollElement = $( '.woocommerce-NoticeGroup-updateOrderReview, .woocommerce-NoticeGroup-checkout' );
if ( ! scrollElement.length ) {
scrollElement = $( '.form.checkout' );
}
if ( scrollElement.length ) {
if ( isSmoothScrollSupported ) {
scrollElement[0].scrollIntoView({
behavior: 'smooth'
});
} else {
$( 'html, body' ).animate( {
scrollTop: ( scrollElement.offset().top - 100 )
}, 1000 );
}
}
$.scroll_to_notices( scrollElement );
}
};

File diff suppressed because one or more lines are too long

View File

@ -63,4 +63,21 @@ jQuery( function( $ ) {
parent.removeClass( 'currentTarget' );
} );
// Common scroll to element code.
$.scroll_to_notices = function( scrollElement ) {
var isSmoothScrollSupported = 'scrollBehavior' in document.documentElement.style;
if ( scrollElement.length ) {
if ( isSmoothScrollSupported ) {
scrollElement[0].scrollIntoView({
behavior: 'smooth'
});
} else {
$( 'html, body' ).animate( {
scrollTop: ( scrollElement.offset().top - 100 )
}, 1000 );
}
}
};
});

View File

@ -1 +1 @@
jQuery(function(e){e(".woocommerce-ordering").on("change","select.orderby",function(){e(this).closest("form").submit()}),e("input.qty:not(.product-quantity input.qty)").each(function(){var o=parseFloat(e(this).attr("min"));o>=0&&parseFloat(e(this).val())<o&&e(this).val(o)}),e(".woocommerce-store-notice__dismiss-link").click(function(){Cookies.set("store_notice","hidden",{path:"/"}),e(".woocommerce-store-notice").hide()}),"hidden"===Cookies.get("store_notice")?e(".woocommerce-store-notice").hide():e(".woocommerce-store-notice").show(),e(document.body).on("click",function(){e(".woocommerce-input-wrapper span.description:visible").prop("aria-hidden",!0).slideUp(250)}),e(".woocommerce-input-wrapper").on("click",function(e){e.stopPropagation()}),e(".woocommerce-input-wrapper :input").on("keydown",function(o){var i=e(this).parent().find("span.description");if(27===o.which&&i.length&&i.is(":visible"))return i.prop("aria-hidden",!0).slideUp(250),o.preventDefault(),!1}).on("focus",function(){var o=e(this).parent(),i=o.find("span.description");o.addClass("currentTarget"),e(".woocommerce-input-wrapper:not(.currentTarget) span.description:visible").prop("aria-hidden",!0).slideUp(250),i.length&&i.is(":hidden")&&i.prop("aria-hidden",!1).slideDown(250),o.removeClass("currentTarget")})});
jQuery(function(o){o(".woocommerce-ordering").on("change","select.orderby",function(){o(this).closest("form").submit()}),o("input.qty:not(.product-quantity input.qty)").each(function(){var e=parseFloat(o(this).attr("min"));e>=0&&parseFloat(o(this).val())<e&&o(this).val(e)}),o(".woocommerce-store-notice__dismiss-link").click(function(){Cookies.set("store_notice","hidden",{path:"/"}),o(".woocommerce-store-notice").hide()}),"hidden"===Cookies.get("store_notice")?o(".woocommerce-store-notice").hide():o(".woocommerce-store-notice").show(),o(document.body).on("click",function(){o(".woocommerce-input-wrapper span.description:visible").prop("aria-hidden",!0).slideUp(250)}),o(".woocommerce-input-wrapper").on("click",function(o){o.stopPropagation()}),o(".woocommerce-input-wrapper :input").on("keydown",function(e){var i=o(this).parent().find("span.description");if(27===e.which&&i.length&&i.is(":visible"))return i.prop("aria-hidden",!0).slideUp(250),e.preventDefault(),!1}).on("focus",function(){var e=o(this).parent(),i=e.find("span.description");e.addClass("currentTarget"),o(".woocommerce-input-wrapper:not(.currentTarget) span.description:visible").prop("aria-hidden",!0).slideUp(250),i.length&&i.is(":hidden")&&i.prop("aria-hidden",!1).slideDown(250),e.removeClass("currentTarget")}),o.scroll_to_notices=function(e){var i="scrollBehavior"in document.documentElement.style;e.length&&(i?e[0].scrollIntoView({behavior:"smooth"}):o("html, body").animate({scrollTop:e.offset().top-100},1e3))}});

File diff suppressed because it is too large Load Diff

View File

@ -14,10 +14,10 @@ $states['IE'] = array(
'CW' => __( 'Carlow', 'woocommerce' ),
'CN' => __( 'Cavan', 'woocommerce' ),
'CE' => __( 'Clare', 'woocommerce' ),
'CK' => __( 'Cork', 'woocommerce' ),
'CO' => __( 'Cork', 'woocommerce' ),
'DL' => __( 'Donegal', 'woocommerce' ),
'DN' => __( 'Dublin', 'woocommerce' ),
'GY' => __( 'Galway', 'woocommerce' ),
'D' => __( 'Dublin', 'woocommerce' ),
'G' => __( 'Galway', 'woocommerce' ),
'KY' => __( 'Kerry', 'woocommerce' ),
'KE' => __( 'Kildare', 'woocommerce' ),
'KK' => __( 'Kilkenny', 'woocommerce' ),
@ -32,7 +32,7 @@ $states['IE'] = array(
'OY' => __( 'Offaly', 'woocommerce' ),
'RN' => __( 'Roscommon', 'woocommerce' ),
'SO' => __( 'Sligo', 'woocommerce' ),
'TY' => __( 'Tipperary', 'woocommerce' ),
'TA' => __( 'Tipperary', 'woocommerce' ),
'WD' => __( 'Waterford', 'woocommerce' ),
'WH' => __( 'Westmeath', 'woocommerce' ),
'WX' => __( 'Wexford', 'woocommerce' ),

29
i18n/states/LR.php Normal file
View File

@ -0,0 +1,29 @@
<?php
/**
* Liberia provinces
*
* @package WooCommerce/i18n
* @version 3.0.0
*/
global $states;
defined( 'ABSPATH' ) || exit;
$states['LR'] = array(
'BM' => __( 'Bomi', 'woocommerce' ),
'BN' => __( 'Bong', 'woocommerce' ),
'GA' => __( 'Gbarpolu', 'woocommerce' ),
'GB' => __( 'Grand Bassa', 'woocommerce' ),
'GC' => __( 'Grand Cape Mount', 'woocommerce' ),
'GG' => __( 'Grand Gedeh', 'woocommerce' ),
'GK' => __( 'Grand Kru', 'woocommerce' ),
'LO' => __( 'Lofa ', 'woocommerce' ),
'MA' => __( 'Margibi', 'woocommerce' ),
'MY' => __( 'Maryland', 'woocommerce' ),
'MO' => __( 'Montserrado', 'woocommerce' ),
'NM' => __( 'Nimba', 'woocommerce' ),
'RV' => __( 'Rivercess', 'woocommerce' ),
'RG' => __( 'River Gee', 'woocommerce' ),
'SN' => __( 'Sinoe', 'woocommerce' ),
);

View File

@ -706,7 +706,7 @@ abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order {
* Return an array of items/products within this order.
*
* @param string|array $types Types of line items to get (array or string).
* @return Array of WC_Order_item
* @return WC_Order_Item[]
*/
public function get_items( $types = 'line_item' ) {
$items = array();
@ -730,7 +730,7 @@ abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order {
/**
* Return an array of fees within this order.
*
* @return array
* @return WC_Order_item_Fee[]
*/
public function get_fees() {
return $this->get_items( 'fee' );
@ -739,7 +739,7 @@ abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order {
/**
* Return an array of taxes within this order.
*
* @return array
* @return WC_Order_Item_Tax[]
*/
public function get_taxes() {
return $this->get_items( 'tax' );
@ -748,7 +748,7 @@ abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order {
/**
* Return an array of shipping costs within this order.
*
* @return array
* @return WC_Order_Item_Shipping[]
*/
public function get_shipping_methods() {
return $this->get_items( 'shipping' );
@ -788,7 +788,7 @@ abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order {
* Gets the count of order items of a certain type.
*
* @param string $item_type Item type to lookup.
* @return string
* @return int|string
*/
public function get_item_count( $item_type = '' ) {
$items = $this->get_items( empty( $item_type ) ? 'line_item' : $item_type );
@ -802,7 +802,7 @@ abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order {
}
/**
* Get an order item object, based on it's type.
* Get an order item object, based on its type.
*
* @since 3.0.0
* @param int $item_id ID of item to get.
@ -1062,7 +1062,7 @@ abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order {
}
/**
* After applying coupons via the WC_Disounts class, update line items.
* After applying coupons via the WC_Discounts class, update line items.
*
* @since 3.2.0
* @param WC_Discounts $discounts Discounts class.
@ -1087,7 +1087,7 @@ abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order {
}
/**
* After applying coupons via the WC_Disounts class, update or create coupon items.
* After applying coupons via the WC_Discounts class, update or create coupon items.
*
* @since 3.2.0
* @param WC_Discounts $discounts Discounts class.
@ -1134,7 +1134,7 @@ abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order {
/**
* Add a product line item to the order. This is the only line item type with
* it's own method because it saves looking up order amounts (costs are added up for you).
* its own method because it saves looking up order amounts (costs are added up for you).
*
* @param WC_Product $product Product object.
* @param int $qty Quantity to add.

View File

@ -178,7 +178,9 @@ abstract class WC_Payment_Gateway extends WC_Settings_API {
* Output the gateway settings screen.
*/
public function admin_options() {
echo '<h2>' . esc_html( $this->get_method_title() ) . '</h2>';
echo '<h2>' . esc_html( $this->get_method_title() );
wc_back_link( __( 'Return to payments', 'woocommerce' ), admin_url( 'admin.php?page=wc-settings&tab=checkout' ) );
echo '</h2>';
echo wp_kses_post( wpautop( $this->get_method_description() ) );
parent::admin_options();
}
@ -191,6 +193,19 @@ abstract class WC_Payment_Gateway extends WC_Settings_API {
$this->enabled = ! empty( $this->settings['enabled'] ) && 'yes' === $this->settings['enabled'] ? 'yes' : 'no';
}
/**
* Return whether or not this gateway still requires setup to function.
*
* When this gateway is toggled on via AJAX, if this returns true a
* redirect will occur to the settings page instead.
*
* @since 3.4.0
* @return bool
*/
public function needs_setup() {
return false;
}
/**
* Get the return url (thank you page).
*
@ -388,6 +403,18 @@ abstract class WC_Payment_Gateway extends WC_Settings_API {
return apply_filters( 'woocommerce_payment_gateway_supports', in_array( $feature, $this->supports ), $feature, $this );
}
/**
* Can the order be refunded via this gateway?
*
* Should be extended by gateways to do their own checks.
*
* @param WC_Order $order Order object.
* @return bool If false, the automatic refund button is hidden in the UI.
*/
public function can_refund_order( $order ) {
return $order && $this->supports( 'refunds' );
}
/**
* Core credit card form which gateways can used if needed. Deprecated - inherit WC_Payment_Gateway_CC instead.
*

View File

@ -177,6 +177,24 @@ abstract class WC_Settings_API {
return $_POST; // WPCS: CSRF ok, input var ok.
}
/**
* Update a single option.
*
* @since 3.4.0
* @param string $key Option key.
* @param mixed $value Value to set.
* @return bool was anything saved?
*/
public function update_option( $key, $value = '' ) {
if ( empty( $this->settings ) ) {
$this->init_settings();
}
$this->settings[ $key ] = $value;
return update_option( $this->get_option_key(), apply_filters( 'woocommerce_settings_api_sanitized_fields_' . $this->id, $this->settings ) );
}
/**
* Processes and saves options.
* If there is an error thrown, will continue to save and validate fields, but will leave the erroring field out.

View File

@ -70,7 +70,7 @@ class WC_Admin_API_Keys_Table_List extends WP_List_Table {
* @return string
*/
public function column_title( $key ) {
$url = admin_url( 'admin.php?page=wc-settings&tab=api&section=keys&edit-key=' . $key['key_id'] );
$url = admin_url( 'admin.php?page=wc-settings&tab=advanced&section=keys&edit-key=' . $key['key_id'] );
$output = '<strong>';
$output .= '<a href="' . esc_url( $url ) . '" class="row-title">';
@ -92,7 +92,7 @@ class WC_Admin_API_Keys_Table_List extends WP_List_Table {
add_query_arg(
array(
'revoke-key' => $key['key_id'],
), admin_url( 'admin.php?page=wc-settings&tab=api&section=keys' )
), admin_url( 'admin.php?page=wc-settings&tab=advanced&section=keys' )
), 'revoke'
)
) . '">' . esc_html__( 'Revoke', 'woocommerce' ) . '</a>',

View File

@ -27,7 +27,7 @@ class WC_Admin_API_Keys {
* @return bool
*/
private function is_api_keys_settings_page() {
return isset( $_GET['page'], $_GET['tab'], $_GET['section'] ) && 'wc-settings' === $_GET['page'] && 'api' === $_GET['tab'] && 'keys' === $_GET['section']; // WPCS: input var okay, CSRF ok.
return isset( $_GET['page'], $_GET['tab'], $_GET['section'] ) && 'wc-settings' === $_GET['page'] && 'advanced' === $_GET['tab'] && 'keys' === $_GET['section']; // WPCS: input var okay, CSRF ok.
}
/**
@ -72,7 +72,7 @@ class WC_Admin_API_Keys {
private static function table_list_output() {
global $wpdb, $keys_table_list;
echo '<h2>' . esc_html__( 'Keys/Apps', 'woocommerce' ) . ' <a href="' . esc_url( admin_url( 'admin.php?page=wc-settings&tab=api&section=keys&create-key=1' ) ) . '" class="add-new-h2">' . esc_html__( 'Add key', 'woocommerce' ) . '</a></h2>';
echo '<h2>' . esc_html__( 'REST API', 'woocommerce' ) . ' <a href="' . esc_url( admin_url( 'admin.php?page=wc-settings&tab=advanced&section=keys&create-key=1' ) ) . '" class="add-new-h2">' . esc_html__( 'Add key', 'woocommerce' ) . '</a></h2>';
// Get the API keys count.
$count = $wpdb->get_var( "SELECT COUNT(key_id) FROM {$wpdb->prefix}woocommerce_api_keys WHERE 1 = 1;" );
@ -91,7 +91,7 @@ class WC_Admin_API_Keys {
echo '<div class="woocommerce-BlankState woocommerce-BlankState--api">';
?>
<h2 class="woocommerce-BlankState-message"><?php esc_html_e( 'The WooCommerce REST API allows external apps to view and manage store data. Access is granted only to those with valid API keys.', 'woocommerce' ); ?></h2>
<a class="woocommerce-BlankState-cta button-primary button" href="<?php echo esc_url( admin_url( 'admin.php?page=wc-settings&tab=api&section=keys&create-key=1' ) ); ?>"><?php esc_html_e( 'Create an API key', 'woocommerce' ); ?></a>
<a class="woocommerce-BlankState-cta button-primary button" href="<?php echo esc_url( admin_url( 'admin.php?page=wc-settings&tab=advanced&section=keys&create-key=1' ) ); ?>"><?php esc_html_e( 'Create an API key', 'woocommerce' ); ?></a>
<style type="text/css">#posts-filter .wp-list-table, #posts-filter .tablenav.top, .tablenav.bottom .actions { display: none; }</style>
<?php
}
@ -175,7 +175,7 @@ class WC_Admin_API_Keys {
}
}
wp_redirect( esc_url_raw( add_query_arg( array( 'revoked' => 1 ), admin_url( 'admin.php?page=wc-settings&tab=api&section=keys' ) ) ) );
wp_redirect( esc_url_raw( add_query_arg( array( 'revoked' => 1 ), admin_url( 'admin.php?page=wc-settings&tab=advanced&section=keys' ) ) ) );
exit();
}

View File

@ -169,10 +169,14 @@ if ( ! class_exists( 'WC_Admin_Assets', false ) ) :
'i18_delete_product_notice' => __( 'This product has produced sales and may be linked to existing orders. Are you sure you want to delete it?', 'woocommerce' ),
'decimal_point' => $decimal,
'mon_decimal_point' => wc_get_price_decimal_separator(),
'ajax_url' => admin_url( 'admin-ajax.php' ),
'strings' => array(
'import_products' => __( 'Import', 'woocommerce' ),
'export_products' => __( 'Export', 'woocommerce' ),
),
'nonces' => array(
'gateway_toggle' => wp_create_nonce( 'woocommerce-toggle-payment-gateway-enabled' ),
),
'urls' => array(
'import_products' => current_user_can( 'import' ) ? esc_url_raw( admin_url( 'edit.php?post_type=product&page=product_importer' ) ) : null,
'export_products' => current_user_can( 'export' ) ? esc_url_raw( admin_url( 'edit.php?post_type=product&page=product_exporter' ) ) : null,

View File

@ -65,7 +65,7 @@ class WC_Admin_Meta_Boxes {
add_action( 'woocommerce_process_shop_coupon_meta', 'WC_Meta_Box_Coupon_Data::save', 10, 2 );
// Save Rating Meta Boxes.
add_action( 'comment_edit_redirect', 'WC_Meta_Box_Product_Reviews::save', 1, 2 );
add_filter( 'wp_update_comment_data', 'WC_Meta_Box_Product_Reviews::save', 1 );
// Error handling (for showing errors from meta boxes on next page load).
add_action( 'admin_notices', array( $this, 'output_errors' ) );

View File

@ -51,11 +51,11 @@ if ( ! class_exists( 'WC_Admin_Settings', false ) ) :
$settings[] = include 'settings/class-wc-settings-products.php';
$settings[] = include 'settings/class-wc-settings-tax.php';
$settings[] = include 'settings/class-wc-settings-shipping.php';
$settings[] = include 'settings/class-wc-settings-checkout.php';
$settings[] = include 'settings/class-wc-settings-payment-gateways.php';
$settings[] = include 'settings/class-wc-settings-accounts.php';
$settings[] = include 'settings/class-wc-settings-emails.php';
$settings[] = include 'settings/class-wc-settings-integrations.php';
$settings[] = include 'settings/class-wc-settings-rest-api.php';
$settings[] = include 'settings/class-wc-settings-advanced.php';
self::$settings = apply_filters( 'woocommerce_get_settings_pages', $settings );
}

View File

@ -86,7 +86,7 @@ class WC_Admin_Webhooks_Table_List extends WP_List_Table {
add_query_arg(
array(
'delete' => $webhook->get_id(),
), admin_url( 'admin.php?page=wc-settings&tab=api&section=webhooks' )
), admin_url( 'admin.php?page=wc-settings&tab=advanced&section=webhooks' )
), 'delete-webhook'
)
) . '">' . esc_html__( 'Delete permanently', 'woocommerce' ) . '</a>',

View File

@ -43,7 +43,7 @@ class WC_Admin_Webhooks {
* @return bool
*/
private function is_webhook_settings_page() {
return isset( $_GET['page'], $_GET['tab'], $_GET['section'] ) && 'wc-settings' === $_GET['page'] && 'api' === $_GET['tab'] && 'webhooks' === $_GET['section']; // WPCS: input var okay, CSRF ok.
return isset( $_GET['page'], $_GET['tab'], $_GET['section'] ) && 'wc-settings' === $_GET['page'] && 'advanced' === $_GET['tab'] && 'webhooks' === $_GET['section']; // WPCS: input var okay, CSRF ok.
}
/**
@ -127,7 +127,7 @@ class WC_Admin_Webhooks {
do_action( 'woocommerce_webhook_options_save', $webhook->get_id() );
if ( $errors ) {
// Redirect to webhook edit page to avoid settings save actions.
wp_safe_redirect( admin_url( 'admin.php?page=wc-settings&tab=api&section=webhooks&edit-webhook=' . $webhook->get_id() . '&error=' . rawurlencode( implode( '|', $errors ) ) ) );
wp_safe_redirect( admin_url( 'admin.php?page=wc-settings&tab=advanced&section=webhooks&edit-webhook=' . $webhook->get_id() . '&error=' . rawurlencode( implode( '|', $errors ) ) ) );
exit();
} elseif ( isset( $_POST['webhook_status'] ) && 'active' === $_POST['webhook_status'] && $webhook->get_pending_delivery() ) { // WPCS: input var okay, CSRF ok.
// Ping the webhook at the first time that is activated.
@ -135,13 +135,13 @@ class WC_Admin_Webhooks {
if ( is_wp_error( $result ) ) {
// Redirect to webhook edit page to avoid settings save actions.
wp_safe_redirect( admin_url( 'admin.php?page=wc-settings&tab=api&section=webhooks&edit-webhook=' . $webhook->get_id() . '&error=' . rawurlencode( $result->get_error_message() ) ) );
wp_safe_redirect( admin_url( 'admin.php?page=wc-settings&tab=advanced&section=webhooks&edit-webhook=' . $webhook->get_id() . '&error=' . rawurlencode( $result->get_error_message() ) ) );
exit();
}
}
// Redirect to webhook edit page to avoid settings save actions.
wp_safe_redirect( admin_url( 'admin.php?page=wc-settings&tab=api&section=webhooks&edit-webhook=' . $webhook->get_id() . '&updated=1' ) );
wp_safe_redirect( admin_url( 'admin.php?page=wc-settings&tab=advanced&section=webhooks&edit-webhook=' . $webhook->get_id() . '&updated=1' ) );
exit();
}
@ -160,7 +160,7 @@ class WC_Admin_Webhooks {
$status = isset( $_GET['status'] ) ? '&status=' . sanitize_text_field( wp_unslash( $_GET['status'] ) ) : ''; // WPCS: input var okay, CSRF ok.
// Redirect to webhooks page.
wp_safe_redirect( admin_url( 'admin.php?page=wc-settings&tab=api&section=webhooks' . $status . '&deleted=' . $qty ) );
wp_safe_redirect( admin_url( 'admin.php?page=wc-settings&tab=advanced&section=webhooks' . $status . '&deleted=' . $qty ) );
exit();
}
@ -292,7 +292,7 @@ class WC_Admin_Webhooks {
private static function table_list_output() {
global $webhooks_table_list;
echo '<h2>' . esc_html__( 'Webhooks', 'woocommerce' ) . ' <a href="' . esc_url( admin_url( 'admin.php?page=wc-settings&tab=api&section=webhooks&edit-webhook=0' ) ) . '" class="add-new-h2">' . esc_html__( 'Add webhook', 'woocommerce' ) . '</a></h2>';
echo '<h2>' . esc_html__( 'Webhooks', 'woocommerce' ) . ' <a href="' . esc_url( admin_url( 'admin.php?page=wc-settings&tab=advanced&section=webhooks&edit-webhook=0' ) ) . '" class="add-new-h2">' . esc_html__( 'Add webhook', 'woocommerce' ) . '</a></h2>';
// Get the webhooks count.
$data_store = WC_Data_Store::load( 'webhook' );
@ -312,7 +312,7 @@ class WC_Admin_Webhooks {
echo '<div class="woocommerce-BlankState woocommerce-BlankState--webhooks">';
?>
<h2 class="woocommerce-BlankState-message"><?php esc_html_e( 'Webhooks are event notifications sent to URLs of your choice. They can be used to integrate with third-party services which support them.', 'woocommerce' ); ?></h2>
<a class="woocommerce-BlankState-cta button-primary button" href="<?php echo esc_url( admin_url( 'admin.php?page=wc-settings&tab=api&section=webhooks&edit-webhook=0' ) ); ?>"><?php esc_html_e( 'Create a new webhook', 'woocommerce' ); ?></a>
<a class="woocommerce-BlankState-cta button-primary button" href="<?php echo esc_url( admin_url( 'admin.php?page=wc-settings&tab=advanced&section=webhooks&edit-webhook=0' ) ); ?>"><?php esc_html_e( 'Create a new webhook', 'woocommerce' ); ?></a>
<style type="text/css">#posts-filter .wp-list-table, #posts-filter .tablenav.top, .tablenav.bottom .actions { display: none; }</style>
<?php
}

View File

@ -27,7 +27,8 @@ class WC_Meta_Box_Coupon_Data {
public static function output( $post ) {
wp_nonce_field( 'woocommerce_save_data', 'woocommerce_meta_nonce' );
$coupon = new WC_Coupon( $post->ID );
$coupon_id = absint( $post->ID );
$coupon = new WC_Coupon( $coupon_id );
?>
@ -78,6 +79,7 @@ class WC_Meta_Box_Coupon_Data {
'id' => 'discount_type',
'label' => __( 'Discount type', 'woocommerce' ),
'options' => wc_get_coupon_types(),
'value' => $coupon->get_discount_type( 'edit' ),
)
);
@ -90,6 +92,7 @@ class WC_Meta_Box_Coupon_Data {
'description' => __( 'Value of the coupon.', 'woocommerce' ),
'data_type' => 'price',
'desc_tip' => true,
'value' => $coupon->get_amount( 'edit' ),
)
);
@ -100,12 +103,13 @@ class WC_Meta_Box_Coupon_Data {
'id' => 'free_shipping',
'label' => __( 'Allow free shipping', 'woocommerce' ),
'description' => sprintf( __( 'Check this box if the coupon grants free shipping. A <a href="%s" target="_blank">free shipping method</a> must be enabled in your shipping zone and be set to require "a valid free shipping coupon" (see the "Free Shipping Requires" setting).', 'woocommerce' ), 'https://docs.woocommerce.com/document/free-shipping/' ),
'value' => wc_bool_to_string( $coupon->get_free_shipping( 'edit' ) ),
)
);
}
// Expiry date.
$expiry_date = $coupon->get_date_expires() ? $coupon->get_date_expires()->date( 'Y-m-d' ) : '';
$expiry_date = $coupon->get_date_expires( 'edit' ) ? $coupon->get_date_expires( 'edit' )->date( 'Y-m-d' ) : '';
woocommerce_wp_text_input(
array(
'id' => 'expiry_date',
@ -138,6 +142,7 @@ class WC_Meta_Box_Coupon_Data {
'description' => __( 'This field allows you to set the minimum spend (subtotal) allowed to use the coupon.', 'woocommerce' ),
'data_type' => 'price',
'desc_tip' => true,
'value' => $coupon->get_minimum_amount( 'edit' ),
)
);
@ -150,6 +155,7 @@ class WC_Meta_Box_Coupon_Data {
'description' => __( 'This field allows you to set the maximum spend (subtotal) allowed when using the coupon.', 'woocommerce' ),
'data_type' => 'price',
'desc_tip' => true,
'value' => $coupon->get_maximum_amount( 'edit' ),
)
);
@ -159,6 +165,7 @@ class WC_Meta_Box_Coupon_Data {
'id' => 'individual_use',
'label' => __( 'Individual use only', 'woocommerce' ),
'description' => __( 'Check this box if the coupon cannot be used in conjunction with other coupons.', 'woocommerce' ),
'value' => wc_bool_to_string( $coupon->get_individual_use( 'edit' ) ),
)
);
@ -168,6 +175,7 @@ class WC_Meta_Box_Coupon_Data {
'id' => 'exclude_sale_items',
'label' => __( 'Exclude sale items', 'woocommerce' ),
'description' => __( 'Check this box if the coupon should not apply to items on sale. Per-item coupons will only work if the item is not on sale. Per-cart coupons will only work if there are items in the cart that are not on sale.', 'woocommerce' ),
'value' => wc_bool_to_string( $coupon->get_exclude_sale_items( 'edit' ) ),
)
);
@ -179,7 +187,7 @@ class WC_Meta_Box_Coupon_Data {
<label><?php _e( 'Products', 'woocommerce' ); ?></label>
<select class="wc-product-search" multiple="multiple" style="width: 50%;" name="product_ids[]" data-placeholder="<?php esc_attr_e( 'Search for a product&hellip;', 'woocommerce' ); ?>" data-action="woocommerce_json_search_products_and_variations">
<?php
$product_ids = $coupon->get_product_ids();
$product_ids = $coupon->get_product_ids( 'edit' );
foreach ( $product_ids as $product_id ) {
$product = wc_get_product( $product_id );
@ -197,7 +205,7 @@ class WC_Meta_Box_Coupon_Data {
<label><?php _e( 'Exclude products', 'woocommerce' ); ?></label>
<select class="wc-product-search" multiple="multiple" style="width: 50%;" name="exclude_product_ids[]" data-placeholder="<?php esc_attr_e( 'Search for a product&hellip;', 'woocommerce' ); ?>" data-action="woocommerce_json_search_products_and_variations">
<?php
$product_ids = $coupon->get_excluded_product_ids();
$product_ids = $coupon->get_excluded_product_ids( 'edit' );
foreach ( $product_ids as $product_id ) {
$product = wc_get_product( $product_id );
@ -219,7 +227,7 @@ class WC_Meta_Box_Coupon_Data {
<label for="product_categories"><?php _e( 'Product categories', 'woocommerce' ); ?></label>
<select id="product_categories" name="product_categories[]" style="width: 50%;" class="wc-enhanced-select" multiple="multiple" data-placeholder="<?php esc_attr_e( 'Any category', 'woocommerce' ); ?>">
<?php
$category_ids = $coupon->get_product_categories();
$category_ids = $coupon->get_product_categories( 'edit' );
$categories = get_terms( 'product_cat', 'orderby=name&hide_empty=0' );
if ( $categories ) {
@ -236,7 +244,7 @@ class WC_Meta_Box_Coupon_Data {
<label for="exclude_product_categories"><?php _e( 'Exclude categories', 'woocommerce' ); ?></label>
<select id="exclude_product_categories" name="exclude_product_categories[]" style="width: 50%;" class="wc-enhanced-select" multiple="multiple" data-placeholder="<?php esc_attr_e( 'No categories', 'woocommerce' ); ?>">
<?php
$category_ids = $coupon->get_excluded_product_categories();
$category_ids = $coupon->get_excluded_product_categories( 'edit' );
$categories = get_terms( 'product_cat', 'orderby=name&hide_empty=0' );
if ( $categories ) {
@ -258,7 +266,7 @@ class WC_Meta_Box_Coupon_Data {
'label' => __( 'Email restrictions', 'woocommerce' ),
'placeholder' => __( 'No restrictions', 'woocommerce' ),
'description' => __( 'List of allowed emails to check against the customer billing email when an order is placed. Separate email addresses with commas. You can also use an asterisk (*) to match parts of an email. For example "*@gmail.com" would match all gmail addresses.', 'woocommerce' ),
'value' => implode( ', ', (array) $coupon->get_email_restrictions() ),
'value' => implode( ', ', (array) $coupon->get_email_restrictions( 'edit' ) ),
'desc_tip' => true,
'type' => 'email',
'class' => '',
@ -288,7 +296,7 @@ class WC_Meta_Box_Coupon_Data {
'step' => 1,
'min' => 0,
),
'value' => $coupon->get_usage_limit() ? $coupon->get_usage_limit() : '',
'value' => $coupon->get_usage_limit( 'edit' ) ? $coupon->get_usage_limit( 'edit' ) : '',
)
);
@ -306,7 +314,7 @@ class WC_Meta_Box_Coupon_Data {
'step' => 1,
'min' => 0,
),
'value' => $coupon->get_limit_usage_to_x_items() ? $coupon->get_limit_usage_to_x_items() : '',
'value' => $coupon->get_limit_usage_to_x_items( 'edit' ) ? $coupon->get_limit_usage_to_x_items( 'edit' ) : '',
)
);
@ -324,7 +332,7 @@ class WC_Meta_Box_Coupon_Data {
'step' => 1,
'min' => 0,
),
'value' => $coupon->get_usage_limit_per_user() ? $coupon->get_usage_limit_per_user() : '',
'value' => $coupon->get_usage_limit_per_user( 'edit' ) ? $coupon->get_usage_limit_per_user( 'edit' ) : '',
)
);
?>

View File

@ -409,6 +409,7 @@ class WC_Meta_Box_Order_Data {
array(
'id' => '_transaction_id',
'label' => __( 'Transaction ID', 'woocommerce' ),
'value' => $order->get_transaction_id( 'edit' ),
)
);
?>

View File

@ -40,17 +40,22 @@ class WC_Meta_Box_Product_Reviews {
/**
* Save meta box data
*
* @param mixed $location
* @param int $comment_id
* @param mixed $data
*
* @return mixed
*/
public static function save( $location, $comment_id ) {
public static function save( $data ) {
// Not allowed, return regular value without updating meta
if ( ! wp_verify_nonce( $_POST['woocommerce_meta_nonce'], 'woocommerce_save_data' ) && ! isset( $_POST['rating'] ) ) {
return $location;
return $data;
}
if ( $_POST['rating'] > 5 || $_POST['rating'] < 0 ) {
return $data;
}
$comment_id = $data['comment_ID'];
// Update meta
update_comment_meta(
$comment_id,
@ -59,6 +64,6 @@ class WC_Meta_Box_Product_Reviews {
);
// Return regular value after updating
return $location;
return $data;
}
}

View File

@ -292,12 +292,14 @@ if ( wc_tax_enabled() ) {
<div class="clear"></div>
<div class="refund-actions">
<?php
$refund_amount = '<span class="wc-order-refund-amount">' . wc_price( 0, array( 'currency' => $order->get_currency() ) ) . '</span>';
$gateway_supports_refunds = false !== $payment_gateway && $payment_gateway->supports( 'refunds' );
$gateway_name = false !== $payment_gateway ? ( ! empty( $payment_gateway->method_title ) ? $payment_gateway->method_title : $payment_gateway->get_title() ) : __( 'Payment gateway', 'woocommerce' );
$refund_amount = '<span class="wc-order-refund-amount">' . wc_price( 0, array( 'currency' => $order->get_currency() ) ) . '</span>';
$gateway_name = false !== $payment_gateway ? ( ! empty( $payment_gateway->method_title ) ? $payment_gateway->method_title : $payment_gateway->get_title() ) : __( 'Payment gateway', 'woocommerce' );
if ( false !== $payment_gateway && $payment_gateway->can_refund_order( $order ) ) {
/* translators: refund amount, gateway name */
echo '<button type="button" class="button button-primary do-api-refund">' . sprintf( esc_html__( 'Refund %1$s via %2$s', 'woocommerce' ), wp_kses_post( $refund_amount ), esc_html( $gateway_name ) ) . '</button>';
}
?>
<?php /* translators: refund amount, gateway name */ ?>
<button type="button" class="button <?php echo $gateway_supports_refunds ? 'button-primary do-api-refund' : 'tips disabled'; ?>" <?php echo $gateway_supports_refunds ? '' : 'data-tip="' . esc_attr__( 'The payment gateway used to place this order does not support automatic refunds.', 'woocommerce' ) . '"'; ?>><?php printf( esc_html__( 'Refund %1$s via %2$s', 'woocommerce' ), $refund_amount, $gateway_name ); ?></button>
<?php /* translators: refund amount */ ?>
<button type="button" class="button button-primary do-manual-refund tips" data-tip="<?php esc_attr_e( 'You will need to manually issue a refund through your payment gateway after using this.', 'woocommerce' ); ?>"><?php printf( esc_html__( 'Refund %s manually', 'woocommerce' ), $refund_amount ); ?></button>
<button type="button" class="button cancel-action"><?php esc_html_e( 'Cancel', 'woocommerce' ); ?></button>

View File

@ -1,216 +1,111 @@
<?php
/**
* WooCommerce Account Settings
* WooCommerce Account Settings.
*
* @author WooThemes
* @category Admin
* @package WooCommerce/Admin
* @version 2.1.0
* @package WooCommerce/Admin
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
defined( 'ABSPATH' ) || exit;
if ( class_exists( 'WC_Settings_Accounts', false ) ) {
return new WC_Settings_Accounts();
}
if ( ! class_exists( 'WC_Settings_Accounts', false ) ) :
/**
* WC_Settings_Accounts.
*/
class WC_Settings_Accounts extends WC_Settings_Page {
/**
* WC_Settings_Accounts.
* Constructor.
*/
class WC_Settings_Accounts extends WC_Settings_Page {
/**
* Constructor.
*/
public function __construct() {
$this->id = 'account';
$this->label = __( 'Accounts', 'woocommerce' );
parent::__construct();
}
/**
* Get settings array.
*
* @return array
*/
public function get_settings() {
$settings = apply_filters(
'woocommerce_' . $this->id . '_settings', array(
array(
'title' => __( 'Account pages', 'woocommerce' ),
'type' => 'title',
'desc' => __( 'These pages need to be set so that WooCommerce knows where to send users to access account related functionality.', 'woocommerce' ),
'id' => 'account_page_options',
),
array(
'title' => __( 'My account page', 'woocommerce' ),
'desc' => sprintf( __( 'Page contents: [%s]', 'woocommerce' ), apply_filters( 'woocommerce_my_account_shortcode_tag', 'woocommerce_my_account' ) ),
'id' => 'woocommerce_myaccount_page_id',
'type' => 'single_select_page',
'default' => '',
'class' => 'wc-enhanced-select-nostd',
'css' => 'min-width:300px;',
'desc_tip' => true,
),
array(
'type' => 'sectionend',
'id' => 'account_page_options',
),
array(
'title' => '',
'type' => 'title',
'id' => 'account_registration_options',
),
array(
'title' => __( 'Customer registration', 'woocommerce' ),
'desc' => __( 'Enable customer registration on the "Checkout" page.', 'woocommerce' ),
'id' => 'woocommerce_enable_signup_and_login_from_checkout',
'default' => 'yes',
'type' => 'checkbox',
'checkboxgroup' => 'start',
'autoload' => false,
),
array(
'desc' => __( 'Enable customer registration on the "My account" page.', 'woocommerce' ),
'id' => 'woocommerce_enable_myaccount_registration',
'default' => 'no',
'type' => 'checkbox',
'checkboxgroup' => 'end',
'autoload' => false,
),
array(
'title' => __( 'Login', 'woocommerce' ),
'desc' => __( 'Display returning customer login reminder on the "Checkout" page.', 'woocommerce' ),
'id' => 'woocommerce_enable_checkout_login_reminder',
'default' => 'yes',
'type' => 'checkbox',
'checkboxgroup' => 'start',
'autoload' => false,
),
array(
'title' => __( 'Account creation', 'woocommerce' ),
'desc' => __( 'Automatically generate username from customer email.', 'woocommerce' ),
'id' => 'woocommerce_registration_generate_username',
'default' => 'yes',
'type' => 'checkbox',
'checkboxgroup' => 'start',
'autoload' => false,
),
array(
'desc' => __( 'Automatically generate customer password', 'woocommerce' ),
'id' => 'woocommerce_registration_generate_password',
'default' => 'no',
'type' => 'checkbox',
'checkboxgroup' => 'end',
'autoload' => false,
),
array(
'type' => 'sectionend',
'id' => 'account_registration_options',
),
array(
'title' => __( 'My account endpoints', 'woocommerce' ),
'type' => 'title',
'desc' => __( 'Endpoints are appended to your page URLs to handle specific actions on the accounts pages. They should be unique and can be left blank to disable the endpoint.', 'woocommerce' ),
'id' => 'account_endpoint_options',
),
array(
'title' => __( 'Orders', 'woocommerce' ),
'desc' => __( 'Endpoint for the "My account &rarr; Orders" page.', 'woocommerce' ),
'id' => 'woocommerce_myaccount_orders_endpoint',
'type' => 'text',
'default' => 'orders',
'desc_tip' => true,
),
array(
'title' => __( 'View order', 'woocommerce' ),
'desc' => __( 'Endpoint for the "My account &rarr; View order" page.', 'woocommerce' ),
'id' => 'woocommerce_myaccount_view_order_endpoint',
'type' => 'text',
'default' => 'view-order',
'desc_tip' => true,
),
array(
'title' => __( 'Downloads', 'woocommerce' ),
'desc' => __( 'Endpoint for the "My account &rarr; Downloads" page.', 'woocommerce' ),
'id' => 'woocommerce_myaccount_downloads_endpoint',
'type' => 'text',
'default' => 'downloads',
'desc_tip' => true,
),
array(
'title' => __( 'Edit account', 'woocommerce' ),
'desc' => __( 'Endpoint for the "My account &rarr; Edit account" page.', 'woocommerce' ),
'id' => 'woocommerce_myaccount_edit_account_endpoint',
'type' => 'text',
'default' => 'edit-account',
'desc_tip' => true,
),
array(
'title' => __( 'Addresses', 'woocommerce' ),
'desc' => __( 'Endpoint for the "My account &rarr; Addresses" page.', 'woocommerce' ),
'id' => 'woocommerce_myaccount_edit_address_endpoint',
'type' => 'text',
'default' => 'edit-address',
'desc_tip' => true,
),
array(
'title' => __( 'Payment methods', 'woocommerce' ),
'desc' => __( 'Endpoint for the "My account &rarr; Payment methods" page.', 'woocommerce' ),
'id' => 'woocommerce_myaccount_payment_methods_endpoint',
'type' => 'text',
'default' => 'payment-methods',
'desc_tip' => true,
),
array(
'title' => __( 'Lost password', 'woocommerce' ),
'desc' => __( 'Endpoint for the "My account &rarr; Lost password" page.', 'woocommerce' ),
'id' => 'woocommerce_myaccount_lost_password_endpoint',
'type' => 'text',
'default' => 'lost-password',
'desc_tip' => true,
),
array(
'title' => __( 'Logout', 'woocommerce' ),
'desc' => __( 'Endpoint for the triggering logout. You can add this to your menus via a custom link: yoursite.com/?customer-logout=true', 'woocommerce' ),
'id' => 'woocommerce_logout_endpoint',
'type' => 'text',
'default' => 'customer-logout',
'desc_tip' => true,
),
array(
'type' => 'sectionend',
'id' => 'account_endpoint_options',
),
)
);
return apply_filters( 'woocommerce_get_settings_' . $this->id, $settings );
}
public function __construct() {
$this->id = 'account';
$this->label = __( 'Accounts &amp; Privacy', 'woocommerce' );
parent::__construct();
}
endif;
/**
* Get settings array.
*
* @return array
*/
public function get_settings() {
$settings = apply_filters(
'woocommerce_' . $this->id . '_settings', array(
array(
'title' => '',
'type' => 'title',
'id' => 'account_registration_options',
),
array(
'title' => __( 'Guest checkout', 'woocommerce' ),
'desc' => __( 'Allow customers to place orders without an account.', 'woocommerce' ),
'id' => 'woocommerce_enable_guest_checkout',
'default' => 'yes',
'type' => 'checkbox',
'checkboxgroup' => 'start',
'autoload' => false,
),
array(
'title' => __( 'Login', 'woocommerce' ),
'desc' => __( 'Allow customers to log into an existing account during checkout', 'woocommerce' ),
'id' => 'woocommerce_enable_checkout_login_reminder',
'default' => 'yes',
'type' => 'checkbox',
'checkboxgroup' => 'end',
'autoload' => false,
),
array(
'title' => __( 'Account creation', 'woocommerce' ),
'desc' => __( 'Allow customers to create an account during checkout.', 'woocommerce' ),
'id' => 'woocommerce_enable_signup_and_login_from_checkout',
'default' => 'yes',
'type' => 'checkbox',
'checkboxgroup' => 'start',
'autoload' => false,
),
array(
'desc' => __( 'Allow customers to create an account on the "My account" page.', 'woocommerce' ),
'id' => 'woocommerce_enable_myaccount_registration',
'default' => 'no',
'type' => 'checkbox',
'checkboxgroup' => '',
'autoload' => false,
),
array(
'desc' => __( 'When creating an account, automatically generate a username from the customer\'s email address.', 'woocommerce' ),
'id' => 'woocommerce_registration_generate_username',
'default' => 'yes',
'type' => 'checkbox',
'checkboxgroup' => '',
'autoload' => false,
),
array(
'desc' => __( 'When creating an account, automatically generate an account password.', 'woocommerce' ),
'id' => 'woocommerce_registration_generate_password',
'default' => 'no',
'type' => 'checkbox',
'checkboxgroup' => 'end',
'autoload' => false,
),
array(
'type' => 'sectionend',
'id' => 'account_registration_options',
),
)
);
return apply_filters( 'woocommerce_get_settings_' . $this->id, $settings );
}
}
return new WC_Settings_Accounts();

View File

@ -0,0 +1,409 @@
<?php
/**
* WooCommerce advanced settings
*
* @package WooCommerce/Admin
*/
defined( 'ABSPATH' ) || exit;
/**
* Settings for API.
*/
if ( class_exists( 'WC_Settings_Advanced', false ) ) {
return new WC_Settings_Advanced();
}
/**
* WC_Settings_Advanced.
*/
class WC_Settings_Advanced extends WC_Settings_Page {
/**
* Constructor.
*/
public function __construct() {
$this->id = 'advanced';
$this->label = __( 'Advanced', 'woocommerce' );
add_action( 'woocommerce_settings_form_method_tab_' . $this->id, array( $this, 'form_method' ) );
parent::__construct();
$this->notices();
}
/**
* Get sections.
*
* @return array
*/
public function get_sections() {
$sections = array(
'' => __( 'Page setup', 'woocommerce' ),
'keys' => __( 'REST API', 'woocommerce' ),
'webhooks' => __( 'Webhooks', 'woocommerce' ),
'legacy_api' => __( 'Legacy API', 'woocommerce' ),
);
return apply_filters( 'woocommerce_get_sections_' . $this->id, $sections );
}
/**
* Get settings array.
*
* @param string $current_section Current section slug.
* @return array
*/
public function get_settings( $current_section = '' ) {
$settings = array();
if ( '' === $current_section ) {
$settings = apply_filters(
'woocommerce_settings_pages', array(
array(
'title' => __( 'Page setup', 'woocommerce' ),
'desc' => __( 'These pages need to be set so that WooCommerce knows where to send users to checkout.', 'woocommerce' ),
'type' => 'title',
'id' => 'advanced_page_options',
),
array(
'title' => __( 'Cart page', 'woocommerce' ),
/* Translators: %s Page contents. */
'desc' => sprintf( __( 'Page contents: [%s]', 'woocommerce' ), apply_filters( 'woocommerce_cart_shortcode_tag', 'woocommerce_cart' ) ),
'id' => 'woocommerce_cart_page_id',
'type' => 'single_select_page',
'default' => '',
'class' => 'wc-enhanced-select-nostd',
'css' => 'min-width:300px;',
'desc_tip' => true,
),
array(
'title' => __( 'Checkout page', 'woocommerce' ),
/* Translators: %s Page contents. */
'desc' => sprintf( __( 'Page contents: [%s]', 'woocommerce' ), apply_filters( 'woocommerce_checkout_shortcode_tag', 'woocommerce_checkout' ) ),
'id' => 'woocommerce_checkout_page_id',
'type' => 'single_select_page',
'default' => '',
'class' => 'wc-enhanced-select-nostd',
'css' => 'min-width:300px;',
'desc_tip' => true,
),
array(
'title' => __( 'My account page', 'woocommerce' ),
/* Translators: %s Page contents. */
'desc' => sprintf( __( 'Page contents: [%s]', 'woocommerce' ), apply_filters( 'woocommerce_my_account_shortcode_tag', 'woocommerce_my_account' ) ),
'id' => 'woocommerce_myaccount_page_id',
'type' => 'single_select_page',
'default' => '',
'class' => 'wc-enhanced-select-nostd',
'css' => 'min-width:300px;',
'desc_tip' => true,
),
array(
'title' => __( 'Terms and conditions', 'woocommerce' ),
'desc' => __( 'If you define a "Terms" page the customer will be asked if they accept them when checking out.', 'woocommerce' ),
'id' => 'woocommerce_terms_page_id',
'default' => '',
'class' => 'wc-enhanced-select-nostd',
'css' => 'min-width:300px;',
'type' => 'single_select_page',
'args' => array( 'exclude' => wc_get_page_id( 'checkout' ) ),
'desc_tip' => true,
'autoload' => false,
),
array(
'type' => 'sectionend',
'id' => 'advanced_page_options',
),
array(
'title' => '',
'type' => 'title',
'id' => 'checkout_process_options',
),
'force_ssl_checkout' => array(
'title' => __( 'Secure checkout', 'woocommerce' ),
'desc' => __( 'Force secure checkout', 'woocommerce' ),
'id' => 'woocommerce_force_ssl_checkout',
'default' => 'no',
'type' => 'checkbox',
'checkboxgroup' => 'start',
'show_if_checked' => 'option',
/* Translators: %s Docs URL. */
'desc_tip' => sprintf( __( 'Force SSL (HTTPS) on the checkout pages (<a href="%s" target="_blank">an SSL Certificate is required</a>).', 'woocommerce' ), 'https://docs.woocommerce.com/document/ssl-and-https/#section-3' ),
),
'unforce_ssl_checkout' => array(
'desc' => __( 'Force HTTP when leaving the checkout', 'woocommerce' ),
'id' => 'woocommerce_unforce_ssl_checkout',
'default' => 'no',
'type' => 'checkbox',
'checkboxgroup' => 'end',
'show_if_checked' => 'yes',
),
array(
'type' => 'sectionend',
'id' => 'checkout_process_options',
),
array(
'title' => __( 'Checkout endpoints', 'woocommerce' ),
'type' => 'title',
'desc' => __( 'Endpoints are appended to your page URLs to handle specific actions during the checkout process. They should be unique.', 'woocommerce' ),
'id' => 'account_endpoint_options',
),
array(
'title' => __( 'Pay', 'woocommerce' ),
'desc' => __( 'Endpoint for the "Checkout &rarr; Pay" page.', 'woocommerce' ),
'id' => 'woocommerce_checkout_pay_endpoint',
'type' => 'text',
'default' => 'order-pay',
'desc_tip' => true,
),
array(
'title' => __( 'Order received', 'woocommerce' ),
'desc' => __( 'Endpoint for the "Checkout &rarr; Order received" page.', 'woocommerce' ),
'id' => 'woocommerce_checkout_order_received_endpoint',
'type' => 'text',
'default' => 'order-received',
'desc_tip' => true,
),
array(
'title' => __( 'Add payment method', 'woocommerce' ),
'desc' => __( 'Endpoint for the "Checkout &rarr; Add payment method" page.', 'woocommerce' ),
'id' => 'woocommerce_myaccount_add_payment_method_endpoint',
'type' => 'text',
'default' => 'add-payment-method',
'desc_tip' => true,
),
array(
'title' => __( 'Delete payment method', 'woocommerce' ),
'desc' => __( 'Endpoint for the delete payment method page.', 'woocommerce' ),
'id' => 'woocommerce_myaccount_delete_payment_method_endpoint',
'type' => 'text',
'default' => 'delete-payment-method',
'desc_tip' => true,
),
array(
'title' => __( 'Set default payment method', 'woocommerce' ),
'desc' => __( 'Endpoint for the setting a default payment method page.', 'woocommerce' ),
'id' => 'woocommerce_myaccount_set_default_payment_method_endpoint',
'type' => 'text',
'default' => 'set-default-payment-method',
'desc_tip' => true,
),
array(
'type' => 'sectionend',
'id' => 'checkout_endpoint_options',
),
array(
'title' => __( 'Account endpoints', 'woocommerce' ),
'type' => 'title',
'desc' => __( 'Endpoints are appended to your page URLs to handle specific actions on the accounts pages. They should be unique and can be left blank to disable the endpoint.', 'woocommerce' ),
'id' => 'account_endpoint_options',
),
array(
'title' => __( 'Orders', 'woocommerce' ),
'desc' => __( 'Endpoint for the "My account &rarr; Orders" page.', 'woocommerce' ),
'id' => 'woocommerce_myaccount_orders_endpoint',
'type' => 'text',
'default' => 'orders',
'desc_tip' => true,
),
array(
'title' => __( 'View order', 'woocommerce' ),
'desc' => __( 'Endpoint for the "My account &rarr; View order" page.', 'woocommerce' ),
'id' => 'woocommerce_myaccount_view_order_endpoint',
'type' => 'text',
'default' => 'view-order',
'desc_tip' => true,
),
array(
'title' => __( 'Downloads', 'woocommerce' ),
'desc' => __( 'Endpoint for the "My account &rarr; Downloads" page.', 'woocommerce' ),
'id' => 'woocommerce_myaccount_downloads_endpoint',
'type' => 'text',
'default' => 'downloads',
'desc_tip' => true,
),
array(
'title' => __( 'Edit account', 'woocommerce' ),
'desc' => __( 'Endpoint for the "My account &rarr; Edit account" page.', 'woocommerce' ),
'id' => 'woocommerce_myaccount_edit_account_endpoint',
'type' => 'text',
'default' => 'edit-account',
'desc_tip' => true,
),
array(
'title' => __( 'Addresses', 'woocommerce' ),
'desc' => __( 'Endpoint for the "My account &rarr; Addresses" page.', 'woocommerce' ),
'id' => 'woocommerce_myaccount_edit_address_endpoint',
'type' => 'text',
'default' => 'edit-address',
'desc_tip' => true,
),
array(
'title' => __( 'Payment methods', 'woocommerce' ),
'desc' => __( 'Endpoint for the "My account &rarr; Payment methods" page.', 'woocommerce' ),
'id' => 'woocommerce_myaccount_payment_methods_endpoint',
'type' => 'text',
'default' => 'payment-methods',
'desc_tip' => true,
),
array(
'title' => __( 'Lost password', 'woocommerce' ),
'desc' => __( 'Endpoint for the "My account &rarr; Lost password" page.', 'woocommerce' ),
'id' => 'woocommerce_myaccount_lost_password_endpoint',
'type' => 'text',
'default' => 'lost-password',
'desc_tip' => true,
),
array(
'title' => __( 'Logout', 'woocommerce' ),
'desc' => __( 'Endpoint for the triggering logout. You can add this to your menus via a custom link: yoursite.com/?customer-logout=true', 'woocommerce' ),
'id' => 'woocommerce_logout_endpoint',
'type' => 'text',
'default' => 'customer-logout',
'desc_tip' => true,
),
array(
'type' => 'sectionend',
'id' => 'account_endpoint_options',
),
)
);
if ( wc_site_is_https() ) {
unset( $settings['unforce_ssl_checkout'], $settings['force_ssl_checkout'] );
}
} elseif ( 'legacy_api' === $current_section ) {
$settings = apply_filters(
'woocommerce_settings_rest_api', array(
array(
'title' => '',
'type' => 'title',
'desc' => '',
'id' => 'legacy_api_options',
),
array(
'title' => __( 'Legacy API', 'woocommerce' ),
'desc' => __( 'Enable the legacy REST API', 'woocommerce' ),
'id' => 'woocommerce_api_enabled',
'type' => 'checkbox',
'default' => 'no',
),
array(
'type' => 'sectionend',
'id' => 'legacy_api_options',
),
)
);
}
return apply_filters( 'woocommerce_get_settings_' . $this->id, $settings, $current_section );
}
/**
* Form method.
*
* @param string $method Method name.
* @return string
*/
public function form_method( $method ) {
global $current_section;
if ( 'keys' === $current_section ) {
if ( isset( $_GET['create-key'] ) || isset( $_GET['edit-key'] ) ) { // WPCS: input var okay, CSRF ok.
return 'post';
}
return 'get';
}
return 'post';
}
/**
* Notices.
*/
private function notices() {
if ( isset( $_GET['section'] ) && 'webhooks' === $_GET['section'] ) { // WPCS: input var okay, CSRF ok.
WC_Admin_Webhooks::notices();
}
if ( isset( $_GET['section'] ) && 'keys' === $_GET['section'] ) { // WPCS: input var okay, CSRF ok.
WC_Admin_API_Keys::notices();
}
}
/**
* Output the settings.
*/
public function output() {
global $current_section;
if ( 'webhooks' === $current_section ) {
WC_Admin_Webhooks::page_output();
} elseif ( 'keys' === $current_section ) {
WC_Admin_API_Keys::page_output();
} else {
$settings = $this->get_settings( $current_section );
WC_Admin_Settings::output_fields( $settings );
}
}
/**
* Save settings.
*/
public function save() {
global $current_section;
if ( apply_filters( 'woocommerce_rest_api_valid_to_save', ! in_array( $current_section, array( 'keys', 'webhooks' ), true ) ) ) {
$settings = $this->get_settings( $current_section );
// Prevent the T&Cs and checkout page from being set to the same page.
if ( isset( $_POST['woocommerce_terms_page_id'], $_POST['woocommerce_checkout_page_id'] ) && $_POST['woocommerce_terms_page_id'] === $_POST['woocommerce_checkout_page_id'] ) { // WPCS: input var ok, CSRF ok.
$_POST['woocommerce_terms_page_id'] = '';
}
WC_Admin_Settings::save_fields( $settings );
if ( $current_section ) {
do_action( 'woocommerce_update_options_' . $this->id . '_' . $current_section );
}
}
}
}
/**
* WC_Settings_Rest_API class.
*
* @deprecated 3.4 in favour of WC_Settings_Advanced.
* @todo remove in 4.0.
*/
class WC_Settings_Rest_API extends WC_Settings_Advanced {} // @codingStandardsIgnoreLine.
return new WC_Settings_Advanced();

View File

@ -1,380 +1,11 @@
<?php // @codingStandardsIgnoreLine.
<?php // @codingStandardsIgnoreFile.
/**
* WooCommerce Checkout Settings
* Settings class file.
*
* @package WooCommerce/Admin
* @version 2.5.0
* @deprecated 3.4.0 Replaced with class-wc-settings-payment-gateways.php.
* @todo remove in 4.0.
*/
defined( 'ABSPATH' ) || exit;
if ( class_exists( 'WC_Settings_Payment_Gateways', false ) ) {
return new WC_Settings_Payment_Gateways();
}
/**
* WC_Settings_Payment_Gateways.
*/
class WC_Settings_Payment_Gateways extends WC_Settings_Page {
/**
* Constructor.
*/
public function __construct() {
$this->id = 'checkout';
$this->label = _x( 'Checkout', 'Settings tab label', 'woocommerce' );
add_action( 'woocommerce_admin_field_payment_gateways', array( $this, 'payment_gateways_setting' ) );
parent::__construct();
}
/**
* Get sections.
*
* @return array
*/
public function get_sections() {
$sections = array(
'' => __( 'Checkout options', 'woocommerce' ),
);
if ( ! defined( 'WC_INSTALLING' ) ) {
$payment_gateways = WC()->payment_gateways->payment_gateways();
foreach ( $payment_gateways as $gateway ) {
$title = empty( $gateway->method_title ) ? ucfirst( $gateway->id ) : $gateway->method_title;
$sections[ strtolower( $gateway->id ) ] = esc_html( $title );
}
}
return apply_filters( 'woocommerce_get_sections_' . $this->id, $sections );
}
/**
* Get settings array.
*
* @param string $current_section Section being shown.
* @return array
*/
public function get_settings( $current_section = '' ) {
$settings = array();
if ( '' === $current_section ) {
$settings = apply_filters(
'woocommerce_payment_gateways_settings', array(
array(
'title' => __( 'Checkout process', 'woocommerce' ),
'type' => 'title',
'id' => 'checkout_process_options',
),
array(
'title' => __( 'Coupons', 'woocommerce' ),
'desc' => __( 'Enable the use of coupons', 'woocommerce' ),
'id' => 'woocommerce_enable_coupons',
'default' => 'yes',
'type' => 'checkbox',
'checkboxgroup' => 'start',
'desc_tip' => __( 'Coupons can be applied from the cart and checkout pages.', 'woocommerce' ),
),
array(
'desc' => __( 'Calculate coupon discounts sequentially', 'woocommerce' ),
'id' => 'woocommerce_calc_discounts_sequentially',
'default' => 'no',
'type' => 'checkbox',
'desc_tip' => __( 'When applying multiple coupons, apply the first coupon to the full price and the second coupon to the discounted price and so on.', 'woocommerce' ),
'checkboxgroup' => 'end',
'autoload' => false,
),
array(
'title' => __( 'Checkout process', 'woocommerce' ),
'desc' => __( 'Enable guest checkout', 'woocommerce' ),
'desc_tip' => __( 'Allows customers to checkout without creating an account.', 'woocommerce' ),
'id' => 'woocommerce_enable_guest_checkout',
'default' => 'yes',
'type' => 'checkbox',
'checkboxgroup' => 'start',
'autoload' => false,
),
array(
'desc' => __( 'Force secure checkout', 'woocommerce' ),
'id' => 'woocommerce_force_ssl_checkout',
'default' => 'no',
'type' => 'checkbox',
'checkboxgroup' => '',
'show_if_checked' => 'option',
/* Translators: %s Docs URL. */
'desc_tip' => sprintf( __( 'Force SSL (HTTPS) on the checkout pages (<a href="%s" target="_blank">an SSL Certificate is required</a>).', 'woocommerce' ), 'https://docs.woocommerce.com/document/ssl-and-https/#section-3' ),
),
'unforce_ssl_checkout' => array(
'desc' => __( 'Force HTTP when leaving the checkout', 'woocommerce' ),
'id' => 'woocommerce_unforce_ssl_checkout',
'default' => 'no',
'type' => 'checkbox',
'checkboxgroup' => 'end',
'show_if_checked' => 'yes',
),
array(
'type' => 'sectionend',
'id' => 'checkout_process_options',
),
array(
'title' => __( 'Checkout pages', 'woocommerce' ),
'desc' => __( 'These pages need to be set so that WooCommerce knows where to send users to checkout.', 'woocommerce' ),
'type' => 'title',
'id' => 'checkout_page_options',
),
array(
'title' => __( 'Cart page', 'woocommerce' ),
/* Translators: %s Page contents. */
'desc' => sprintf( __( 'Page contents: [%s]', 'woocommerce' ), apply_filters( 'woocommerce_cart_shortcode_tag', 'woocommerce_cart' ) ),
'id' => 'woocommerce_cart_page_id',
'type' => 'single_select_page',
'default' => '',
'class' => 'wc-enhanced-select-nostd',
'css' => 'min-width:300px;',
'desc_tip' => true,
),
array(
'title' => __( 'Checkout page', 'woocommerce' ),
/* Translators: %s Page contents. */
'desc' => sprintf( __( 'Page contents: [%s]', 'woocommerce' ), apply_filters( 'woocommerce_checkout_shortcode_tag', 'woocommerce_checkout' ) ),
'id' => 'woocommerce_checkout_page_id',
'type' => 'single_select_page',
'default' => '',
'class' => 'wc-enhanced-select-nostd',
'css' => 'min-width:300px;',
'desc_tip' => true,
),
array(
'type' => 'sectionend',
'id' => 'checkout_page_options',
),
array(
'title' => __( 'Checkout endpoints', 'woocommerce' ),
'type' => 'title',
'desc' => __( 'Endpoints are appended to your page URLs to handle specific actions during the checkout process. They should be unique.', 'woocommerce' ),
'id' => 'account_endpoint_options',
),
array(
'title' => __( 'Pay', 'woocommerce' ),
'desc' => __( 'Endpoint for the "Checkout &rarr; Pay" page.', 'woocommerce' ),
'id' => 'woocommerce_checkout_pay_endpoint',
'type' => 'text',
'default' => 'order-pay',
'desc_tip' => true,
),
array(
'title' => __( 'Order received', 'woocommerce' ),
'desc' => __( 'Endpoint for the "Checkout &rarr; Order received" page.', 'woocommerce' ),
'id' => 'woocommerce_checkout_order_received_endpoint',
'type' => 'text',
'default' => 'order-received',
'desc_tip' => true,
),
array(
'title' => __( 'Add payment method', 'woocommerce' ),
'desc' => __( 'Endpoint for the "Checkout &rarr; Add payment method" page.', 'woocommerce' ),
'id' => 'woocommerce_myaccount_add_payment_method_endpoint',
'type' => 'text',
'default' => 'add-payment-method',
'desc_tip' => true,
),
array(
'title' => __( 'Delete payment method', 'woocommerce' ),
'desc' => __( 'Endpoint for the delete payment method page.', 'woocommerce' ),
'id' => 'woocommerce_myaccount_delete_payment_method_endpoint',
'type' => 'text',
'default' => 'delete-payment-method',
'desc_tip' => true,
),
array(
'title' => __( 'Set default payment method', 'woocommerce' ),
'desc' => __( 'Endpoint for the setting a default payment method page.', 'woocommerce' ),
'id' => 'woocommerce_myaccount_set_default_payment_method_endpoint',
'type' => 'text',
'default' => 'set-default-payment-method',
'desc_tip' => true,
),
array(
'type' => 'sectionend',
'id' => 'checkout_endpoint_options',
),
array(
'title' => __( 'Payment gateways', 'woocommerce' ),
'desc' => __( 'Installed gateways are listed below. Drag and drop gateways to control their display order on the frontend.', 'woocommerce' ),
'type' => 'title',
'id' => 'payment_gateways_options',
),
array(
'type' => 'payment_gateways',
),
array(
'type' => 'sectionend',
'id' => 'payment_gateways_options',
),
)
);
if ( wc_site_is_https() ) {
unset( $settings['unforce_ssl_checkout'] );
}
}
return apply_filters( 'woocommerce_get_settings_' . $this->id, $settings, $current_section );
}
/**
* Output the settings.
*/
public function output() {
global $current_section;
// Load gateways so we can show any global options they may have.
$payment_gateways = WC()->payment_gateways->payment_gateways();
if ( $current_section ) {
foreach ( $payment_gateways as $gateway ) {
if ( in_array( $current_section, array( $gateway->id, sanitize_title( get_class( $gateway ) ) ), true ) ) {
$gateway->admin_options();
break;
}
}
} else {
$settings = $this->get_settings();
WC_Admin_Settings::output_fields( $settings );
}
}
/**
* Output payment gateway settings.
*/
public function payment_gateways_setting() {
?>
<tr valign="top">
<th scope="row" class="titledesc"><?php esc_html_e( 'Gateway display order', 'woocommerce' ); ?></th>
<td class="forminp">
<table class="wc_gateways widefat" cellspacing="0">
<thead>
<tr>
<?php
$columns = apply_filters(
'woocommerce_payment_gateways_setting_columns', array(
'sort' => '',
'name' => __( 'Gateway', 'woocommerce' ),
'id' => __( 'Gateway ID', 'woocommerce' ),
'status' => __( 'Enabled', 'woocommerce' ),
)
);
foreach ( $columns as $key => $column ) {
echo '<th class="' . esc_attr( $key ) . '">' . esc_html( $column ) . '</th>';
}
?>
</tr>
</thead>
<tbody>
<?php
foreach ( WC()->payment_gateways->payment_gateways() as $gateway ) {
echo '<tr>';
foreach ( $columns as $key => $column ) {
switch ( $key ) {
case 'sort':
echo '<td width="1%" class="sort">
<input type="hidden" name="gateway_order[]" value="' . esc_attr( $gateway->id ) . '" />
</td>';
break;
case 'name':
$method_title = $gateway->get_title() ? $gateway->get_title() : __( '(no title)', 'woocommerce' );
echo '<td class="name">
<a href="' . esc_url( admin_url( 'admin.php?page=wc-settings&tab=checkout&section=' . strtolower( $gateway->id ) ) ) . '">' . esc_html( $method_title ) . '</a>
</td>';
break;
case 'id':
echo '<td class="id">' . esc_html( $gateway->id ) . '</td>';
break;
case 'status':
echo '<td class="status">';
echo ( 'yes' === $gateway->enabled ) ? '<span class="status-enabled tips" data-tip="' . esc_attr__( 'Yes', 'woocommerce' ) . '">' . esc_html__( 'Yes', 'woocommerce' ) . '</span>' : '-';
echo '</td>';
break;
default:
do_action( 'woocommerce_payment_gateways_setting_column_' . $key, $gateway );
break;
}
}
echo '</tr>';
}
?>
</tbody>
</table>
</td>
</tr>
<?php
}
/**
* Save settings.
*/
public function save() {
global $current_section;
$wc_payment_gateways = WC_Payment_Gateways::instance();
if ( ! $current_section ) {
// Prevent the T&Cs and checkout page from being set to the same page.
if ( isset( $_POST['woocommerce_terms_page_id'], $_POST['woocommerce_checkout_page_id'] ) && $_POST['woocommerce_terms_page_id'] === $_POST['woocommerce_checkout_page_id'] ) { // WPCS: input var ok, CSRF ok.
$_POST['woocommerce_terms_page_id'] = '';
}
WC_Admin_Settings::save_fields( $this->get_settings() );
$wc_payment_gateways->process_admin_options();
$wc_payment_gateways->init();
} else {
foreach ( $wc_payment_gateways->payment_gateways() as $gateway ) {
if ( in_array( $current_section, array( $gateway->id, sanitize_title( get_class( $gateway ) ) ), true ) ) {
do_action( 'woocommerce_update_options_payment_gateways_' . $gateway->id );
$wc_payment_gateways->init();
}
}
}
if ( $current_section ) {
do_action( 'woocommerce_update_options_' . $this->id . '_' . $current_section );
}
}
}
return new WC_Settings_Payment_Gateways();
return include 'class-wc-settings-payment-gateways.php';

View File

@ -2,338 +2,333 @@
/**
* WooCommerce Email Settings
*
* @author WooThemes
* @category Admin
* @package WooCommerce/Admin
* @version 2.1.0
* @package WooCommerce/Admin
* @version 2.1.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
defined( 'ABSPATH' ) || exit;
if ( class_exists( 'WC_Settings_Emails', false ) ) {
return new WC_Settings_Emails();
}
if ( ! class_exists( 'WC_Settings_Emails', false ) ) :
/**
* WC_Settings_Emails.
*/
class WC_Settings_Emails extends WC_Settings_Page {
/**
* WC_Settings_Emails.
* Constructor.
*/
class WC_Settings_Emails extends WC_Settings_Page {
public function __construct() {
$this->id = 'email';
$this->label = __( 'Emails', 'woocommerce' );
/**
* Constructor.
*/
public function __construct() {
$this->id = 'email';
$this->label = __( 'Emails', 'woocommerce' );
add_action( 'woocommerce_admin_field_email_notification', array( $this, 'email_notification_setting' ) );
parent::__construct();
}
add_action( 'woocommerce_admin_field_email_notification', array( $this, 'email_notification_setting' ) );
parent::__construct();
}
/**
* Get sections.
*
* @return array
*/
public function get_sections() {
$sections = array(
'' => __( 'Email options', 'woocommerce' ),
);
return apply_filters( 'woocommerce_get_sections_' . $this->id, $sections );
}
/**
* Get sections.
*
* @return array
*/
public function get_sections() {
$sections = array(
'' => __( 'Email options', 'woocommerce' ),
);
return apply_filters( 'woocommerce_get_sections_' . $this->id, $sections );
}
/**
* Get settings array.
*
* @return array
*/
public function get_settings() {
$settings = apply_filters(
'woocommerce_email_settings', array(
/**
* Get settings array.
*
* @return array
*/
public function get_settings() {
$settings = apply_filters(
'woocommerce_email_settings', array(
array(
'title' => __( 'Email notifications', 'woocommerce' ),
'desc' => __( 'Email notifications sent from WooCommerce are listed below. Click on an email to configure it.', 'woocommerce' ),
'type' => 'title',
'id' => 'email_notification_settings',
),
array(
'title' => __( 'Email notifications', 'woocommerce' ),
'desc' => __( 'Email notifications sent from WooCommerce are listed below. Click on an email to configure it.', 'woocommerce' ),
'type' => 'title',
'id' => 'email_notification_settings',
array( 'type' => 'email_notification' ),
array(
'type' => 'sectionend',
'id' => 'email_notification_settings',
),
array(
'type' => 'sectionend',
'id' => 'email_recipient_options',
),
array(
'title' => __( 'Email sender options', 'woocommerce' ),
'type' => 'title',
'desc' => '',
'id' => 'email_options',
),
array(
'title' => __( '"From" name', 'woocommerce' ),
'desc' => __( 'How the sender name appears in outgoing WooCommerce emails.', 'woocommerce' ),
'id' => 'woocommerce_email_from_name',
'type' => 'text',
'css' => 'min-width:300px;',
'default' => esc_attr( get_bloginfo( 'name', 'display' ) ),
'autoload' => false,
'desc_tip' => true,
),
array(
'title' => __( '"From" address', 'woocommerce' ),
'desc' => __( 'How the sender email appears in outgoing WooCommerce emails.', 'woocommerce' ),
'id' => 'woocommerce_email_from_address',
'type' => 'email',
'custom_attributes' => array(
'multiple' => 'multiple',
),
'css' => 'min-width:300px;',
'default' => get_option( 'admin_email' ),
'autoload' => false,
'desc_tip' => true,
),
array( 'type' => 'email_notification' ),
array(
'type' => 'sectionend',
'id' => 'email_options',
),
array(
'type' => 'sectionend',
'id' => 'email_notification_settings',
),
array(
'title' => __( 'Email template', 'woocommerce' ),
'type' => 'title',
'desc' => sprintf( __( 'This section lets you customize the WooCommerce emails. <a href="%s" target="_blank">Click here to preview your email template</a>.', 'woocommerce' ), wp_nonce_url( admin_url( '?preview_woocommerce_mail=true' ), 'preview-mail' ) ),
'id' => 'email_template_options',
),
array(
'type' => 'sectionend',
'id' => 'email_recipient_options',
),
array(
'title' => __( 'Header image', 'woocommerce' ),
'desc' => __( 'URL to an image you want to show in the email header. Upload images using the media uploader (Admin > Media).', 'woocommerce' ),
'id' => 'woocommerce_email_header_image',
'type' => 'text',
'css' => 'min-width:300px;',
'placeholder' => __( 'N/A', 'woocommerce' ),
'default' => '',
'autoload' => false,
'desc_tip' => true,
),
array(
'title' => __( 'Email sender options', 'woocommerce' ),
'type' => 'title',
'desc' => '',
'id' => 'email_options',
),
array(
'title' => __( 'Footer text', 'woocommerce' ),
'desc' => __( 'The text to appear in the footer of WooCommerce emails.', 'woocommerce' ) . ' ' . sprintf( __( 'Available placeholders: %s', 'woocommerce' ), '{site_title}' ),
'id' => 'woocommerce_email_footer_text',
'css' => 'width:300px; height: 75px;',
'placeholder' => __( 'N/A', 'woocommerce' ),
'type' => 'textarea',
'default' => '{site_title}',
'autoload' => false,
'desc_tip' => true,
),
array(
'title' => __( '"From" name', 'woocommerce' ),
'desc' => __( 'How the sender name appears in outgoing WooCommerce emails.', 'woocommerce' ),
'id' => 'woocommerce_email_from_name',
'type' => 'text',
'css' => 'min-width:300px;',
'default' => esc_attr( get_bloginfo( 'name', 'display' ) ),
'autoload' => false,
'desc_tip' => true,
),
array(
'title' => __( 'Base color', 'woocommerce' ),
/* translators: %s: default color */
'desc' => sprintf( __( 'The base color for WooCommerce email templates. Default %s.', 'woocommerce' ), '<code>#96588a</code>' ),
'id' => 'woocommerce_email_base_color',
'type' => 'color',
'css' => 'width:6em;',
'default' => '#96588a',
'autoload' => false,
'desc_tip' => true,
),
array(
'title' => __( '"From" address', 'woocommerce' ),
'desc' => __( 'How the sender email appears in outgoing WooCommerce emails.', 'woocommerce' ),
'id' => 'woocommerce_email_from_address',
'type' => 'email',
'custom_attributes' => array(
'multiple' => 'multiple',
),
'css' => 'min-width:300px;',
'default' => get_option( 'admin_email' ),
'autoload' => false,
'desc_tip' => true,
),
array(
'title' => __( 'Background color', 'woocommerce' ),
/* translators: %s: default color */
'desc' => sprintf( __( 'The background color for WooCommerce email templates. Default %s.', 'woocommerce' ), '<code>#f7f7f7</code>' ),
'id' => 'woocommerce_email_background_color',
'type' => 'color',
'css' => 'width:6em;',
'default' => '#f7f7f7',
'autoload' => false,
'desc_tip' => true,
),
array(
'type' => 'sectionend',
'id' => 'email_options',
),
array(
'title' => __( 'Body background color', 'woocommerce' ),
/* translators: %s: default color */
'desc' => sprintf( __( 'The main body background color. Default %s.', 'woocommerce' ), '<code>#ffffff</code>' ),
'id' => 'woocommerce_email_body_background_color',
'type' => 'color',
'css' => 'width:6em;',
'default' => '#ffffff',
'autoload' => false,
'desc_tip' => true,
),
array(
'title' => __( 'Email template', 'woocommerce' ),
'type' => 'title',
'desc' => sprintf( __( 'This section lets you customize the WooCommerce emails. <a href="%s" target="_blank">Click here to preview your email template</a>.', 'woocommerce' ), wp_nonce_url( admin_url( '?preview_woocommerce_mail=true' ), 'preview-mail' ) ),
'id' => 'email_template_options',
),
array(
'title' => __( 'Body text color', 'woocommerce' ),
/* translators: %s: default color */
'desc' => sprintf( __( 'The main body text color. Default %s.', 'woocommerce' ), '<code>#3c3c3c</code>' ),
'id' => 'woocommerce_email_text_color',
'type' => 'color',
'css' => 'width:6em;',
'default' => '#3c3c3c',
'autoload' => false,
'desc_tip' => true,
),
array(
'title' => __( 'Header image', 'woocommerce' ),
'desc' => __( 'URL to an image you want to show in the email header. Upload images using the media uploader (Admin > Media).', 'woocommerce' ),
'id' => 'woocommerce_email_header_image',
'type' => 'text',
'css' => 'min-width:300px;',
'placeholder' => __( 'N/A', 'woocommerce' ),
'default' => '',
'autoload' => false,
'desc_tip' => true,
),
array(
'type' => 'sectionend',
'id' => 'email_template_options',
),
array(
'title' => __( 'Footer text', 'woocommerce' ),
'desc' => __( 'The text to appear in the footer of WooCommerce emails.', 'woocommerce' )
. ' ' . sprintf( __( 'Available placeholders: %s', 'woocommerce' ), '{site_title}' ),
'id' => 'woocommerce_email_footer_text',
'css' => 'width:300px; height: 75px;',
'placeholder' => __( 'N/A', 'woocommerce' ),
'type' => 'textarea',
'default' => '{site_title}',
'autoload' => false,
'desc_tip' => true,
),
)
);
array(
'title' => __( 'Base color', 'woocommerce' ),
/* translators: %s: default color */
'desc' => sprintf( __( 'The base color for WooCommerce email templates. Default %s.', 'woocommerce' ), '<code>#96588a</code>' ),
'id' => 'woocommerce_email_base_color',
'type' => 'color',
'css' => 'width:6em;',
'default' => '#96588a',
'autoload' => false,
'desc_tip' => true,
),
return apply_filters( 'woocommerce_get_settings_' . $this->id, $settings );
}
array(
'title' => __( 'Background color', 'woocommerce' ),
/* translators: %s: default color */
'desc' => sprintf( __( 'The background color for WooCommerce email templates. Default %s.', 'woocommerce' ), '<code>#f7f7f7</code>' ),
'id' => 'woocommerce_email_background_color',
'type' => 'color',
'css' => 'width:6em;',
'default' => '#f7f7f7',
'autoload' => false,
'desc_tip' => true,
),
/**
* Output the settings.
*/
public function output() {
global $current_section;
array(
'title' => __( 'Body background color', 'woocommerce' ),
/* translators: %s: default color */
'desc' => sprintf( __( 'The main body background color. Default %s.', 'woocommerce' ), '<code>#ffffff</code>' ),
'id' => 'woocommerce_email_body_background_color',
'type' => 'color',
'css' => 'width:6em;',
'default' => '#ffffff',
'autoload' => false,
'desc_tip' => true,
),
// Define emails that can be customised here.
$mailer = WC()->mailer();
$email_templates = $mailer->get_emails();
array(
'title' => __( 'Body text color', 'woocommerce' ),
/* translators: %s: default color */
'desc' => sprintf( __( 'The main body text color. Default %s.', 'woocommerce' ), '<code>#3c3c3c</code>' ),
'id' => 'woocommerce_email_text_color',
'type' => 'color',
'css' => 'width:6em;',
'default' => '#3c3c3c',
'autoload' => false,
'desc_tip' => true,
),
array(
'type' => 'sectionend',
'id' => 'email_template_options',
),
)
);
return apply_filters( 'woocommerce_get_settings_' . $this->id, $settings );
}
/**
* Output the settings.
*/
public function output() {
global $current_section;
// Define emails that can be customised here.
$mailer = WC()->mailer();
$email_templates = $mailer->get_emails();
if ( $current_section ) {
foreach ( $email_templates as $email_key => $email ) {
if ( strtolower( $email_key ) == $current_section ) {
$email->admin_options();
break;
}
}
} else {
$settings = $this->get_settings();
WC_Admin_Settings::output_fields( $settings );
}
}
/**
* Save settings.
*/
public function save() {
global $current_section;
if ( ! $current_section ) {
WC_Admin_Settings::save_fields( $this->get_settings() );
} else {
$wc_emails = WC_Emails::instance();
if ( in_array( $current_section, array_map( 'sanitize_title', array_keys( $wc_emails->get_emails() ) ) ) ) {
foreach ( $wc_emails->get_emails() as $email_id => $email ) {
if ( sanitize_title( $email_id ) === $current_section ) {
do_action( 'woocommerce_update_options_' . $this->id . '_' . $email->id );
}
}
} else {
do_action( 'woocommerce_update_options_' . $this->id . '_' . $current_section );
if ( $current_section ) {
foreach ( $email_templates as $email_key => $email ) {
if ( strtolower( $email_key ) === $current_section ) {
$email->admin_options();
break;
}
}
}
/**
* Output email notification settings.
*/
public function email_notification_setting() {
// Define emails that can be customised here.
$mailer = WC()->mailer();
$email_templates = $mailer->get_emails();
?>
<tr valign="top">
<td class="wc_emails_wrapper" colspan="2">
<table class="wc_emails widefat" cellspacing="0">
<thead>
<tr>
<?php
$columns = apply_filters(
'woocommerce_email_setting_columns', array(
'status' => '',
'name' => __( 'Email', 'woocommerce' ),
'email_type' => __( 'Content type', 'woocommerce' ),
'recipient' => __( 'Recipient(s)', 'woocommerce' ),
'actions' => '',
)
);
foreach ( $columns as $key => $column ) {
echo '<th class="wc-email-settings-table-' . esc_attr( $key ) . '">' . esc_html( $column ) . '</th>';
}
?>
</tr>
</thead>
<tbody>
<?php
foreach ( $email_templates as $email_key => $email ) {
echo '<tr>';
foreach ( $columns as $key => $column ) {
switch ( $key ) {
case 'name':
echo '<td class="wc-email-settings-table-' . esc_attr( $key ) . '">
<a href="' . admin_url( 'admin.php?page=wc-settings&tab=email&section=' . strtolower( $email_key ) ) . '">' . $email->get_title() . '</a>
' . wc_help_tip( $email->get_description() ) . '
</td>';
break;
case 'recipient':
echo '<td class="wc-email-settings-table-' . esc_attr( $key ) . '">
' . esc_html( $email->is_customer_email() ? __( 'Customer', 'woocommerce' ) : $email->get_recipient() ) . '
</td>';
break;
case 'status':
echo '<td class="wc-email-settings-table-' . esc_attr( $key ) . '">';
if ( $email->is_manual() ) {
echo '<span class="status-manual tips" data-tip="' . esc_attr__( 'Manually sent', 'woocommerce' ) . '">' . esc_html__( 'Manual', 'woocommerce' ) . '</span>';
} elseif ( $email->is_enabled() ) {
echo '<span class="status-enabled tips" data-tip="' . esc_attr__( 'Enabled', 'woocommerce' ) . '">' . esc_html__( 'Yes', 'woocommerce' ) . '</span>';
} else {
echo '<span class="status-disabled tips" data-tip="' . esc_attr__( 'Disabled', 'woocommerce' ) . '">-</span>';
}
echo '</td>';
break;
case 'email_type':
echo '<td class="wc-email-settings-table-' . esc_attr( $key ) . '">
' . esc_html( $email->get_content_type() ) . '
</td>';
break;
case 'actions':
echo '<td class="wc-email-settings-table-' . esc_attr( $key ) . '">
<a class="button alignright tips" data-tip="' . esc_attr__( 'Configure', 'woocommerce' ) . '" href="' . admin_url( 'admin.php?page=wc-settings&tab=email&section=' . strtolower( $email_key ) ) . '">' . esc_html__( 'Configure', 'woocommerce' ) . '</a>
</td>';
break;
default:
do_action( 'woocommerce_email_setting_column_' . $key, $email );
break;
}
}
echo '</tr>';
}
?>
</tbody>
</table>
</td>
</tr>
<?php
} else {
$settings = $this->get_settings();
WC_Admin_Settings::output_fields( $settings );
}
}
endif;
/**
* Save settings.
*/
public function save() {
global $current_section;
if ( ! $current_section ) {
WC_Admin_Settings::save_fields( $this->get_settings() );
} else {
$wc_emails = WC_Emails::instance();
if ( in_array( $current_section, array_map( 'sanitize_title', array_keys( $wc_emails->get_emails() ) ), true ) ) {
foreach ( $wc_emails->get_emails() as $email_id => $email ) {
if ( sanitize_title( $email_id ) === $current_section ) {
do_action( 'woocommerce_update_options_' . $this->id . '_' . $email->id );
}
}
} else {
do_action( 'woocommerce_update_options_' . $this->id . '_' . $current_section );
}
}
}
/**
* Output email notification settings.
*/
public function email_notification_setting() {
// Define emails that can be customised here.
$mailer = WC()->mailer();
$email_templates = $mailer->get_emails();
?>
<tr valign="top">
<td class="wc_emails_wrapper" colspan="2">
<table class="wc_emails widefat" cellspacing="0">
<thead>
<tr>
<?php
$columns = apply_filters(
'woocommerce_email_setting_columns', array(
'status' => '',
'name' => __( 'Email', 'woocommerce' ),
'email_type' => __( 'Content type', 'woocommerce' ),
'recipient' => __( 'Recipient(s)', 'woocommerce' ),
'actions' => '',
)
);
foreach ( $columns as $key => $column ) {
echo '<th class="wc-email-settings-table-' . esc_attr( $key ) . '">' . esc_html( $column ) . '</th>';
}
?>
</tr>
</thead>
<tbody>
<?php
foreach ( $email_templates as $email_key => $email ) {
echo '<tr>';
foreach ( $columns as $key => $column ) {
switch ( $key ) {
case 'name':
echo '<td class="wc-email-settings-table-' . esc_attr( $key ) . '">
<a href="' . admin_url( 'admin.php?page=wc-settings&tab=email&section=' . strtolower( $email_key ) ) . '">' . $email->get_title() . '</a>
' . wc_help_tip( $email->get_description() ) . '
</td>';
break;
case 'recipient':
echo '<td class="wc-email-settings-table-' . esc_attr( $key ) . '">
' . esc_html( $email->is_customer_email() ? __( 'Customer', 'woocommerce' ) : $email->get_recipient() ) . '
</td>';
break;
case 'status':
echo '<td class="wc-email-settings-table-' . esc_attr( $key ) . '">';
if ( $email->is_manual() ) {
echo '<span class="status-manual tips" data-tip="' . esc_attr__( 'Manually sent', 'woocommerce' ) . '">' . esc_html__( 'Manual', 'woocommerce' ) . '</span>';
} elseif ( $email->is_enabled() ) {
echo '<span class="status-enabled tips" data-tip="' . esc_attr__( 'Enabled', 'woocommerce' ) . '">' . esc_html__( 'Yes', 'woocommerce' ) . '</span>';
} else {
echo '<span class="status-disabled tips" data-tip="' . esc_attr__( 'Disabled', 'woocommerce' ) . '">-</span>';
}
echo '</td>';
break;
case 'email_type':
echo '<td class="wc-email-settings-table-' . esc_attr( $key ) . '">
' . esc_html( $email->get_content_type() ) . '
</td>';
break;
case 'actions':
echo '<td class="wc-email-settings-table-' . esc_attr( $key ) . '">
<a class="button alignright" href="' . admin_url( 'admin.php?page=wc-settings&tab=email&section=' . strtolower( $email_key ) ) . '">' . esc_html__( 'Manage', 'woocommerce' ) . '</a>
</td>';
break;
default:
do_action( 'woocommerce_email_setting_column_' . $key, $email );
break;
}
}
echo '</tr>';
}
?>
</tbody>
</table>
</td>
</tr>
<?php
}
}
return new WC_Settings_Emails();

View File

@ -2,8 +2,7 @@
/**
* WooCommerce General Settings
*
* @package WooCommerce/Admin
* @version 2.1.0
* @package WooCommerce/Admin
*/
defined( 'ABSPATH' ) || exit;
@ -189,11 +188,34 @@ class WC_Settings_General extends WC_Settings_Page {
),
array(
'title' => __( 'Enable taxes', 'woocommerce' ),
'desc' => __( 'Enable taxes and tax calculations', 'woocommerce' ),
'id' => 'woocommerce_calc_taxes',
'default' => 'no',
'type' => 'checkbox',
'title' => __( 'Enable taxes', 'woocommerce' ),
'desc' => __( 'Enable tax rates and calculations', 'woocommerce' ),
'id' => 'woocommerce_calc_taxes',
'default' => 'no',
'type' => 'checkbox',
'desc_tip' => __( 'Rates will be configurable and taxes will be calculated during checkout.', 'woocommerce' ),
),
array(
'title' => __( 'Enable coupons', 'woocommerce' ),
'desc' => __( 'Enable the use of coupon codes', 'woocommerce' ),
'id' => 'woocommerce_enable_coupons',
'default' => 'yes',
'type' => 'checkbox',
'checkboxgroup' => 'start',
'show_if_checked' => 'option',
'desc_tip' => __( 'Coupons can be applied from the cart and checkout pages.', 'woocommerce' ),
),
array(
'desc' => __( 'Calculate coupon discounts sequentially', 'woocommerce' ),
'id' => 'woocommerce_calc_discounts_sequentially',
'default' => 'no',
'type' => 'checkbox',
'desc_tip' => __( 'When applying multiple coupons, apply the first coupon to the full price and the second coupon to the discounted price and so on.', 'woocommerce' ),
'show_if_checked' => 'yes',
'checkboxgroup' => 'end',
'autoload' => false,
),
array(

View File

@ -0,0 +1,220 @@
<?php // @codingStandardsIgnoreLine.
/**
* WooCommerce Checkout Settings
*
* @package WooCommerce/Admin
*/
defined( 'ABSPATH' ) || exit;
if ( class_exists( 'WC_Settings_Payment_Gateways', false ) ) {
return new WC_Settings_Payment_Gateways();
}
/**
* WC_Settings_Payment_Gateways.
*/
class WC_Settings_Payment_Gateways extends WC_Settings_Page {
/**
* Constructor.
*/
public function __construct() {
$this->id = 'checkout'; // @todo In future versions this may make more sense as 'payment' however to avoid breakage lets leave this alone until we refactor settings APIs in general.
$this->label = _x( 'Payments', 'Settings tab label', 'woocommerce' );
add_action( 'woocommerce_admin_field_payment_gateways', array( $this, 'payment_gateways_setting' ) );
parent::__construct();
}
/**
* Get sections.
*
* @return array
*/
public function get_sections() {
$sections = array(
'' => __( 'Payment methods', 'woocommerce' ),
);
return apply_filters( 'woocommerce_get_sections_' . $this->id, $sections );
}
/**
* Get settings array.
*
* @param string $current_section Section being shown.
* @return array
*/
public function get_settings( $current_section = '' ) {
$settings = array();
if ( '' === $current_section ) {
$settings = apply_filters(
'woocommerce_payment_gateways_settings', array(
array(
'title' => __( 'Payment methods', 'woocommerce' ),
'desc' => __( 'Installed payment methods are listed below. Drag and drop gateways to control their display order on the frontend.', 'woocommerce' ),
'type' => 'title',
'id' => 'payment_gateways_options',
),
array(
'type' => 'payment_gateways',
),
array(
'type' => 'sectionend',
'id' => 'payment_gateways_options',
),
)
);
}
return apply_filters( 'woocommerce_get_settings_' . $this->id, $settings, $current_section );
}
/**
* Output the settings.
*/
public function output() {
global $current_section;
// Load gateways so we can show any global options they may have.
$payment_gateways = WC()->payment_gateways->payment_gateways();
if ( $current_section ) {
foreach ( $payment_gateways as $gateway ) {
if ( in_array( $current_section, array( $gateway->id, sanitize_title( get_class( $gateway ) ) ), true ) ) {
if ( isset( $_GET['toggle_enabled'] ) ) { // WPCS: input var ok, CSRF ok.
$enabled = $gateway->get_option( 'enabled' );
if ( $enabled ) {
$gateway->settings['enabled'] = wc_string_to_bool( $enabled ) ? 'no' : 'yes';
}
}
$gateway->admin_options();
break;
}
}
} else {
$settings = $this->get_settings();
WC_Admin_Settings::output_fields( $settings );
}
}
/**
* Output payment gateway settings.
*/
public function payment_gateways_setting() {
?>
<tr valign="top">
<td class="wc_payment_gateways_wrapper" colspan="2">
<table class="wc_gateways widefat" cellspacing="0">
<thead>
<tr>
<?php
$default_columns = array(
'sort' => '',
'name' => __( 'Method', 'woocommerce' ),
'status' => __( 'Enabled', 'woocommerce' ),
'description' => __( 'Description', 'woocommerce' ),
'action' => '',
);
$columns = apply_filters( 'woocommerce_payment_gateways_setting_columns', $default_columns );
foreach ( $columns as $key => $column ) {
echo '<th class="' . esc_attr( $key ) . '">' . esc_html( $column ) . '</th>';
}
?>
</tr>
</thead>
<tbody>
<?php
foreach ( WC()->payment_gateways->payment_gateways() as $gateway ) {
echo '<tr data-gateway_id="' . esc_attr( $gateway->id ) . '">';
foreach ( $columns as $key => $column ) {
if ( ! array_key_exists( $key, $default_columns ) ) {
do_action( 'woocommerce_payment_gateways_setting_column_' . $key, $gateway );
continue;
}
$width = '';
if ( in_array( $key, array( 'sort', 'status', 'action' ), true ) ) {
$width = '1%';
}
echo '<td class="' . esc_attr( $key ) . '" width="' . esc_attr( $width ) . '">';
switch ( $key ) {
case 'sort':
echo '<input type="hidden" name="gateway_order[]" value="' . esc_attr( $gateway->id ) . '" />';
break;
case 'name':
$method_title = $gateway->get_title() ? $gateway->get_title() : __( '(no title)', 'woocommerce' );
echo '<a href="' . esc_url( admin_url( 'admin.php?page=wc-settings&tab=checkout&section=' . strtolower( $gateway->id ) ) ) . '">' . esc_html( $method_title ) . '</a>';
break;
case 'description':
echo '<strong class="wc-payment-gateway-method-name">' . wp_kses_post( $gateway->get_method_title() ) . '</strong>';
echo wp_kses_post( $gateway->get_method_description() );
break;
case 'action':
if ( wc_string_to_bool( $gateway->enabled ) ) {
echo '<a class="button alignright" href="' . esc_url( admin_url( 'admin.php?page=wc-settings&tab=checkout&section=' . strtolower( $gateway->id ) ) ) . '">' . esc_html__( 'Manage', 'woocommerce' ) . '</a>';
} else {
echo '<a class="button alignright" href="' . esc_url( admin_url( 'admin.php?page=wc-settings&tab=checkout&section=' . strtolower( $gateway->id ) ) ) . '">' . esc_html__( 'Set up', 'woocommerce' ) . '</a>';
}
break;
case 'status':
echo '<a class="wc-payment-gateway-method-toggle-enabled" href="' . esc_url( admin_url( 'admin.php?page=wc-settings&tab=checkout&section=' . strtolower( $gateway->id ) ) ) . '">';
if ( wc_string_to_bool( $gateway->enabled ) ) {
echo '<span class="woocommerce-input-toggle woocommerce-input-toggle--enabled">' . esc_attr__( 'Yes', 'woocommerce' ) . '</span>';
} else {
echo '<span class="woocommerce-input-toggle woocommerce-input-toggle--disabled">' . esc_attr__( 'No', 'woocommerce' ) . '</span>';
}
echo '</a>';
break;
}
echo '</td>';
}
echo '</tr>';
}
?>
</tbody>
</table>
</td>
</tr>
<?php
}
/**
* Save settings.
*/
public function save() {
global $current_section;
$wc_payment_gateways = WC_Payment_Gateways::instance();
if ( ! $current_section ) {
WC_Admin_Settings::save_fields( $this->get_settings() );
$wc_payment_gateways->process_admin_options();
$wc_payment_gateways->init();
} else {
foreach ( $wc_payment_gateways->payment_gateways() as $gateway ) {
if ( in_array( $current_section, array( $gateway->id, sanitize_title( get_class( $gateway ) ) ), true ) ) {
do_action( 'woocommerce_update_options_payment_gateways_' . $gateway->id );
$wc_payment_gateways->init();
}
}
}
if ( $current_section ) {
do_action( 'woocommerce_update_options_' . $this->id . '_' . $current_section );
}
}
}
return new WC_Settings_Payment_Gateways();

View File

@ -1,159 +0,0 @@
<?php
/**
* WooCommerce API Settings
*
* @author Automattic
* @category Admin
* @package WooCommerce/Admin
* @version 3.3.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
/**
* Settings for API.
*/
if ( class_exists( 'WC_Settings_Rest_API', false ) ) {
return new WC_Settings_Rest_API();
}
/**
* WC_Settings_Rest_API.
*/
class WC_Settings_Rest_API extends WC_Settings_Page {
/**
* Constructor.
*/
public function __construct() {
$this->id = 'api';
$this->label = __( 'API', 'woocommerce' );
add_action( 'woocommerce_settings_form_method_tab_' . $this->id, array( $this, 'form_method' ) );
parent::__construct();
$this->notices();
}
/**
* Get sections.
*
* @return array
*/
public function get_sections() {
$sections = array(
'' => __( 'Settings', 'woocommerce' ),
'keys' => __( 'Keys/Apps', 'woocommerce' ),
'webhooks' => __( 'Webhooks', 'woocommerce' ),
);
return apply_filters( 'woocommerce_get_sections_' . $this->id, $sections );
}
/**
* Get settings array.
*
* @param string $current_section Current section slug.
* @return array
*/
public function get_settings( $current_section = '' ) {
$settings = array();
if ( '' === $current_section ) {
$settings = apply_filters(
'woocommerce_settings_rest_api', array(
array(
'title' => __( 'General options', 'woocommerce' ),
'type' => 'title',
'desc' => '',
'id' => 'general_options',
),
array(
'title' => __( 'Legacy API', 'woocommerce' ),
'desc' => __( 'Enable the legacy REST API', 'woocommerce' ),
'id' => 'woocommerce_api_enabled',
'type' => 'checkbox',
'default' => 'no',
),
array(
'type' => 'sectionend',
'id' => 'general_options',
),
)
);
}
return apply_filters( 'woocommerce_get_settings_' . $this->id, $settings, $current_section );
}
/**
* Form method.
*
* @param string $method Method name.
*
* @return string
*/
public function form_method( $method ) {
global $current_section;
if ( 'keys' === $current_section ) {
if ( isset( $_GET['create-key'] ) || isset( $_GET['edit-key'] ) ) { // WPCS: input var okay, CSRF ok.
return 'post';
}
return 'get';
}
return 'post';
}
/**
* Notices.
*/
private function notices() {
if ( isset( $_GET['section'] ) && 'webhooks' === $_GET['section'] ) { // WPCS: input var okay, CSRF ok.
WC_Admin_Webhooks::notices();
}
if ( isset( $_GET['section'] ) && 'keys' === $_GET['section'] ) { // WPCS: input var okay, CSRF ok.
WC_Admin_API_Keys::notices();
}
}
/**
* Output the settings.
*/
public function output() {
global $current_section;
if ( 'webhooks' === $current_section ) {
WC_Admin_Webhooks::page_output();
} elseif ( 'keys' === $current_section ) {
WC_Admin_API_Keys::page_output();
} else {
$settings = $this->get_settings( $current_section );
WC_Admin_Settings::output_fields( $settings );
}
}
/**
* Save settings.
*/
public function save() {
global $current_section;
if ( apply_filters( 'woocommerce_rest_api_valid_to_save', ! in_array( $current_section, array( 'keys', 'webhooks' ), true ) ) ) {
$settings = $this->get_settings();
WC_Admin_Settings::save_fields( $settings );
if ( $current_section ) {
do_action( 'woocommerce_update_options_' . $this->id . '_' . $current_section );
}
}
}
}
return new WC_Settings_Rest_API();

View File

@ -0,0 +1,11 @@
<?php // @codingStandardsIgnoreFile.
/**
* Settings class file.
*
* @deprecated 3.4.0 Replaced with class-wc-settings-advanced.php.
* @todo remove in 4.0.
*/
defined( 'ABSPATH' ) || exit;
return include 'class-wc-settings-advanced.php';

View File

@ -75,7 +75,7 @@ if ( ! defined( 'ABSPATH' ) ) {
<thead>
<tr>
<th class="wc-shipping-zone-method-sort"></th>
<th class="wc-shipping-zone-method-title"><?php esc_html_e( 'Shipping method title', 'woocommerce' ); ?></th>
<th class="wc-shipping-zone-method-title"><?php esc_html_e( 'Title', 'woocommerce' ); ?></th>
<th class="wc-shipping-zone-method-enabled"><?php esc_html_e( 'Enabled', 'woocommerce' ); ?></th>
<th class="wc-shipping-zone-method-description"><?php esc_html_e( 'Description', 'woocommerce' ); ?></th>
</tr>

View File

@ -106,7 +106,7 @@ if ( ! defined( 'ABSPATH' ) ) {
?>
<p class="submit">
<?php submit_button( __( 'Save changes', 'woocommerce' ), 'primary', 'update_api_key', false ); ?>
<a style="color: #a00; text-decoration: none; margin-left: 10px;" href="<?php echo esc_url( wp_nonce_url( add_query_arg( array( 'revoke-key' => $key_id ), admin_url( 'admin.php?page=wc-settings&tab=api&section=keys' ) ), 'revoke' ) ); ?>"><?php _e( 'Revoke key', 'woocommerce' ); ?></a>
<a style="color: #a00; text-decoration: none; margin-left: 10px;" href="<?php echo esc_url( wp_nonce_url( add_query_arg( array( 'revoke-key' => $key_id ), admin_url( 'admin.php?page=wc-settings&tab=advanced&section=keys' ) ), 'revoke' ) ); ?>"><?php _e( 'Revoke key', 'woocommerce' ); ?></a>
</p>
<?php
}

View File

@ -174,7 +174,7 @@ if ( ! defined( 'ABSPATH' ) ) {
add_query_arg(
array(
'delete' => $webhook->get_id(),
), admin_url( 'admin.php?page=wc-settings&tab=api&section=webhooks' )
), admin_url( 'admin.php?page=wc-settings&tab=advanced&section=webhooks' )
), 'delete-webhook'
);
?>

View File

@ -37,7 +37,7 @@ if ( ! $tab_exists ) {
self::show_messages();
do_action( 'woocommerce_settings_' . $current_tab );
do_action( 'woocommerce_settings_tabs_' . $current_tab ); // @deprecated hook
do_action( 'woocommerce_settings_tabs_' . $current_tab ); // @deprecated hook. @todo remove in 4.0.
?>
<p class="submit">
<?php if ( empty( $GLOBALS['hide_save_button'] ) ) : ?>

View File

@ -510,6 +510,9 @@ class WC_REST_Orders_Controller extends WC_REST_Legacy_Orders_Controller {
return $object;
}
// Make sure gateways are loaded so hooks from gateways fire on save/create.
WC()->payment_gateways();
if ( ! is_null( $request['customer_id'] ) && 0 !== $request['customer_id'] ) {
// Make sure customer exists.
if ( false === get_user_by( 'id', $request['customer_id'] ) ) {

View File

@ -246,6 +246,7 @@ class WC_REST_Products_Controller extends WC_REST_Legacy_Products_Controller {
'taxonomy' => 'product_visibility',
'field' => 'name',
'terms' => 'featured',
'operator' => true === $request['featured'] ? 'IN' : 'NOT IN',
);
}

View File

@ -94,6 +94,7 @@ class WC_REST_Legacy_Products_Controller extends WC_REST_CRUD_Controller {
'taxonomy' => 'product_visibility',
'field' => 'name',
'terms' => 'featured',
'operator' => true === $request['featured'] ? 'IN' : 'NOT IN',
);
}

View File

@ -85,67 +85,68 @@ class WC_AJAX {
public static function add_ajax_events() {
// woocommerce_EVENT => nopriv.
$ajax_events = array(
'get_refreshed_fragments' => true,
'apply_coupon' => true,
'remove_coupon' => true,
'update_shipping_method' => true,
'get_cart_totals' => true,
'update_order_review' => true,
'add_to_cart' => true,
'remove_from_cart' => true,
'checkout' => true,
'get_variation' => true,
'get_customer_location' => true,
'feature_product' => false,
'mark_order_status' => false,
'get_order_details' => false,
'add_attribute' => false,
'add_new_attribute' => false,
'remove_variation' => false,
'remove_variations' => false,
'save_attributes' => false,
'add_variation' => false,
'link_all_variations' => false,
'revoke_access_to_download' => false,
'grant_access_to_download' => false,
'get_customer_details' => false,
'add_order_item' => false,
'add_order_fee' => false,
'add_order_shipping' => false,
'add_order_tax' => false,
'add_coupon_discount' => false,
'remove_order_coupon' => false,
'remove_order_item' => false,
'remove_order_tax' => false,
'reduce_order_item_stock' => false,
'increase_order_item_stock' => false,
'add_order_item_meta' => false,
'remove_order_item_meta' => false,
'calc_line_taxes' => false,
'save_order_items' => false,
'load_order_items' => false,
'add_order_note' => false,
'delete_order_note' => false,
'json_search_products' => false,
'json_search_products_and_variations' => false,
'get_refreshed_fragments' => true,
'apply_coupon' => true,
'remove_coupon' => true,
'update_shipping_method' => true,
'get_cart_totals' => true,
'update_order_review' => true,
'add_to_cart' => true,
'remove_from_cart' => true,
'checkout' => true,
'get_variation' => true,
'get_customer_location' => true,
'feature_product' => false,
'mark_order_status' => false,
'get_order_details' => false,
'add_attribute' => false,
'add_new_attribute' => false,
'remove_variation' => false,
'remove_variations' => false,
'save_attributes' => false,
'add_variation' => false,
'link_all_variations' => false,
'revoke_access_to_download' => false,
'grant_access_to_download' => false,
'get_customer_details' => false,
'add_order_item' => false,
'add_order_fee' => false,
'add_order_shipping' => false,
'add_order_tax' => false,
'add_coupon_discount' => false,
'remove_order_coupon' => false,
'remove_order_item' => false,
'remove_order_tax' => false,
'reduce_order_item_stock' => false,
'increase_order_item_stock' => false,
'add_order_item_meta' => false,
'remove_order_item_meta' => false,
'calc_line_taxes' => false,
'save_order_items' => false,
'load_order_items' => false,
'add_order_note' => false,
'delete_order_note' => false,
'json_search_products' => false,
'json_search_products_and_variations' => false,
'json_search_downloadable_products_and_variations' => false,
'json_search_customers' => false,
'json_search_categories' => false,
'term_ordering' => false,
'product_ordering' => false,
'refund_line_items' => false,
'delete_refund' => false,
'rated' => false,
'update_api_key' => false,
'load_variations' => false,
'save_variations' => false,
'bulk_edit_variations' => false,
'tax_rates_save_changes' => false,
'shipping_zones_save_changes' => false,
'shipping_zone_add_method' => false,
'shipping_zone_methods_save_changes' => false,
'shipping_zone_methods_save_settings' => false,
'shipping_classes_save_changes' => false,
'json_search_customers' => false,
'json_search_categories' => false,
'term_ordering' => false,
'product_ordering' => false,
'refund_line_items' => false,
'delete_refund' => false,
'rated' => false,
'update_api_key' => false,
'load_variations' => false,
'save_variations' => false,
'bulk_edit_variations' => false,
'tax_rates_save_changes' => false,
'shipping_zones_save_changes' => false,
'shipping_zone_add_method' => false,
'shipping_zone_methods_save_changes' => false,
'shipping_zone_methods_save_settings' => false,
'shipping_classes_save_changes' => false,
'toggle_gateway_enabled' => false,
);
foreach ( $ajax_events as $ajax_event => $nopriv ) {
@ -1845,7 +1846,7 @@ class WC_AJAX {
$data['consumer_key'] = $consumer_key;
$data['consumer_secret'] = $consumer_secret;
$data['message'] = __( 'API Key generated successfully. Make sure to copy your new keys now as the secret key will be hidden once you leave this page.', 'woocommerce' );
$data['revoke_url'] = '<a style="color: #a00; text-decoration: none;" href="' . esc_url( wp_nonce_url( add_query_arg( array( 'revoke-key' => $key_id ), admin_url( 'admin.php?page=wc-settings&tab=api&section=keys' ) ), 'revoke' ) ) . '">' . __( 'Revoke key', 'woocommerce' ) . '</a>';
$data['revoke_url'] = '<a style="color: #a00; text-decoration: none;" href="' . esc_url( wp_nonce_url( add_query_arg( array( 'revoke-key' => $key_id ), admin_url( 'admin.php?page=wc-settings&tab=advanced&section=keys' ) ), 'revoke' ) ) . '">' . __( 'Revoke key', 'woocommerce' ) . '</a>';
}
wp_send_json_success( $data );
@ -2660,6 +2661,8 @@ class WC_AJAX {
$shipping_method->set_post_data( $_POST['data'] );
$shipping_method->process_admin_options();
WC_Cache_Helper::get_transient_version( 'shipping', true );
wp_send_json_success(
array(
'zone_id' => $zone->get_id(),
@ -2740,6 +2743,46 @@ class WC_AJAX {
)
);
}
/**
* Toggle payment gateway on or off via AJAX.
*
* @since 3.4.0
*/
public static function toggle_gateway_enabled() {
if ( current_user_can( 'manage_woocommerce' ) && check_ajax_referer( 'woocommerce-toggle-payment-gateway-enabled', 'security' ) ) {
// Load gateways.
$payment_gateways = WC()->payment_gateways->payment_gateways();
// Get posted gateway.
$gateway_id = wc_clean( wp_unslash( $_POST['gateway_id'] ) );
foreach ( $payment_gateways as $gateway ) {
if ( ! in_array( $gateway_id, array( $gateway->id, sanitize_title( get_class( $gateway ) ) ), true ) ) {
continue;
}
$enabled = $gateway->get_option( 'enabled', 'no' );
if ( ! wc_string_to_bool( $enabled ) ) {
if ( $gateway->needs_setup() ) {
wp_send_json_error( 'needs_setup' );
wp_die();
} else {
$gateway->update_option( 'enabled', 'yes' );
}
} else {
// Disable the gateway.
$gateway->update_option( 'enabled', 'no' );
}
wp_send_json_success( ! wc_string_to_bool( $enabled ) );
wp_die();
}
}
wp_send_json_error( 'invalid_gateway_id' );
wp_die();
}
}
WC_AJAX::init();

View File

@ -530,7 +530,11 @@ class WC_Checkout {
'discount_tax' => $cart->get_coupon_discount_tax_amount( $code ),
)
);
$item->add_meta_data( 'coupon_data', $coupon->get_data() );
// Avoid storing used_by - it's not needed and can get large.
$coupon_data = $coupon->get_data();
unset( $coupon_data['used_by'] );
$item->add_meta_data( 'coupon_data', $coupon_data );
/**
* Action hook to adjust item before save.

View File

@ -39,6 +39,19 @@ class WC_Deprecated_Action_Hooks extends WC_Deprecated_Hooks {
'woocommerce_new_payment_token' => 'woocommerce_payment_token_created',
'woocommerce_new_product_variation' => 'woocommerce_create_product_variation',
'woocommerce_order_details_after_order_table_items' => 'woocommerce_order_items_table',
'woocommerce_settings_advanced_page_options' => array(
'woocommerce_settings_checkout_page_options',
'woocommerce_settings_account_page_options',
),
'woocommerce_settings_advanced_page_options_end' => array(
'woocommerce_settings_checkout_page_options_end',
'woocommerce_settings_account_page_options_end',
),
'woocommerce_settings_advanced_page_options_after' => array(
'woocommerce_settings_checkout_page_options_after',
'woocommerce_settings_account_page_options_after',
),
);
/**
@ -47,21 +60,27 @@ class WC_Deprecated_Action_Hooks extends WC_Deprecated_Hooks {
* @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',
'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',
'woocommerce_settings_checkout_page_options' => '3.4.0',
'woocommerce_settings_account_page_options' => '3.4.0',
'woocommerce_settings_checkout_page_options_end' => '3.4.0',
'woocommerce_settings_account_page_options_end' => '3.4.0',
'woocommerce_settings_checkout_page_options_after' => '3.4.0',
'woocommerce_settings_account_page_options_after' => '3.4.0',
);
/**

View File

@ -69,6 +69,8 @@ class WC_Deprecated_Filter_Hooks extends WC_Deprecated_Hooks {
'wc_country_select_params',
'wc_password_strength_meter_params',
),
'woocommerce_settings_tabs_advanced' => 'woocommerce_settings_tabs_api',
'woocommerce_settings_advanced' => 'woocommerce_settings_api',
);
/**
@ -112,6 +114,8 @@ class WC_Deprecated_Filter_Hooks extends WC_Deprecated_Hooks {
'default_checkout_postcode' => '3.0.0',
'woocommerce_debug_posting' => '3.0.0',
'wocommerce_credit_card_type_labels' => '3.0.0',
'woocommerce_settings_tabs_api' => '3.4.0',
'woocommerce_settings_api' => '3.4.0',
);
/**

View File

@ -231,7 +231,7 @@ class WC_Frontend_Scripts {
),
'wc-cart' => array(
'src' => self::get_asset_url( 'assets/js/frontend/cart' . $suffix . '.js' ),
'deps' => array( 'jquery', 'wc-country-select', 'wc-address-i18n' ),
'deps' => array( 'jquery', 'woocommerce', 'wc-country-select', 'wc-address-i18n' ),
'version' => WC_VERSION,
),
'wc-cart-fragments' => array(

View File

@ -99,6 +99,10 @@ class WC_Install {
'wc_update_330_set_paypal_sandbox_credentials',
'wc_update_330_db_version',
),
'3.4.0' => array(
'wc_update_340_irish_states',
'wc_update_340_db_version',
),
);
/**

View File

@ -117,7 +117,7 @@ class WC_Order_Factory {
global $post;
if ( false === $order && is_a( $post, 'WP_Post' ) && 'shop_order' === get_post_type( $post ) ) {
return $post->ID;
return absint( $post->ID );
} elseif ( is_numeric( $order ) ) {
return $order;
} elseif ( $order instanceof WC_Abstract_Order ) {

View File

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

View File

@ -102,8 +102,10 @@ class WC_Product_Factory {
* @return int|bool false on failure
*/
private function get_product_id( $product ) {
if ( false === $product && isset( $GLOBALS['post'], $GLOBALS['post']->ID ) && 'product' === get_post_type( $GLOBALS['post']->ID ) ) {
return $GLOBALS['post']->ID;
global $post;
if ( false === $product && isset( $post, $post->ID ) && 'product' === get_post_type( $post->ID ) ) {
return absint( $post->ID );
} elseif ( is_numeric( $product ) ) {
return $product;
} elseif ( $product instanceof WC_Product ) {

View File

@ -245,7 +245,7 @@ abstract class WC_CSV_Exporter {
$export_row[] = $this->format_data( $column_name );
}
fputcsv( $buffer, $export_row ); // @codingStandardsIgnoreLine
$this->fputcsv( $buffer, $export_row );
return ob_get_clean();
}
@ -299,7 +299,8 @@ abstract class WC_CSV_Exporter {
}
}
fputcsv( $buffer, $export_row ); // @codingStandardsIgnoreLine
$this->fputcsv( $buffer, $export_row );
++ $this->exported_row_count;
}
@ -456,4 +457,32 @@ abstract class WC_CSV_Exporter {
return implode( ', ', $values_to_implode );
}
/**
* Write to the CSV file, ensuring escaping works across versions of
* PHP.
*
* PHP 5.5.4 uses '\' as the default escape character. This is not RFC-4180 compliant.
* \0 disables the escape character.
*
* @see https://bugs.php.net/bug.php?id=43225
* @see https://bugs.php.net/bug.php?id=50686
* @see https://github.com/woocommerce/woocommerce/issues/19514
* @since 3.4.0
* @param resource $buffer Resource we are writing to.
* @param array $export_row Row to export.
*/
protected function fputcsv( $buffer, $export_row ) {
if ( version_compare( PHP_VERSION, '5.5.4', '<' ) ) {
ob_start();
$temp = fopen( 'php://output', 'w' ); // @codingStandardsIgnoreLine
fputcsv( $temp, $export_row, ",", '"' ); // @codingStandardsIgnoreLine
fclose( $temp ); // @codingStandardsIgnoreLine
$row = ob_get_clean();
$row = str_replace( '\\"', '\\""', $row );
fwrite( $buffer, $row ); // @codingStandardsIgnoreLine
} else {
fputcsv( $buffer, $export_row, ",", '"', "\0" ); // @codingStandardsIgnoreLine
}
}
}

View File

@ -37,7 +37,7 @@ class WC_Gateway_BACS extends WC_Payment_Gateway {
$this->icon = apply_filters( 'woocommerce_bacs_icon', '' );
$this->has_fields = false;
$this->method_title = __( 'BACS', 'woocommerce' );
$this->method_description = __( 'Allows payments by BACS, more commonly known as direct bank/wire transfer.', 'woocommerce' );
$this->method_description = __( 'Take payments in-person via BACS. More commonly known as direct bank/wire transfer', 'woocommerce' );
// Load the settings.
$this->init_form_fields();

View File

@ -29,7 +29,7 @@ class WC_Gateway_Cheque extends WC_Payment_Gateway {
$this->icon = apply_filters( 'woocommerce_cheque_icon', '' );
$this->has_fields = false;
$this->method_title = _x( 'Check payments', 'Check payment method', 'woocommerce' );
$this->method_description = __( 'Allows check payments. Why would you take checks in this day and age? Well you probably would not, but it does allow you to make test purchases for testing order emails and the success pages.', 'woocommerce' );
$this->method_description = __( 'Take payments in-person via checks. This offline gateway can also be useful to test purchases.', 'woocommerce' );
// Load the settings.
$this->init_form_fields();

View File

@ -42,7 +42,7 @@ class WC_Gateway_Paypal extends WC_Payment_Gateway {
$this->order_button_text = __( 'Proceed to PayPal', 'woocommerce' );
$this->method_title = __( 'PayPal', 'woocommerce' );
/* translators: %s: Link to WC system status page */
$this->method_description = sprintf( __( 'PayPal Standard sends customers to PayPal to enter their payment information. PayPal IPN requires fsockopen/cURL support to update order statuses after payment. Check the <a href="%s">system status</a> page for more details.', 'woocommerce' ), admin_url( 'admin.php?page=wc-status' ) );
$this->method_description = __( 'PayPal Standard redirects customers to PayPal to enter their payment information.', 'woocommerce' );
$this->supports = array(
'products',
'refunds',
@ -87,6 +87,19 @@ class WC_Gateway_Paypal extends WC_Payment_Gateway {
}
}
/**
* Return whether or not this gateway still requires setup to function.
*
* When this gateway is toggled on via AJAX, if this returns true a
* redirect will occur to the settings page instead.
*
* @since 3.4.0
* @return bool
*/
public function needs_setup() {
return ! is_email( $this->email );
}
/**
* Logging method.
*
@ -294,7 +307,15 @@ class WC_Gateway_Paypal extends WC_Payment_Gateway {
* @return bool
*/
public function can_refund_order( $order ) {
return $order && $order->get_transaction_id();
$has_api_creds = false;
if ( $this->testmode ) {
$has_api_creds = $this->get_option( 'sandbox_api_username' ) && $this->get_option( 'sandbox_api_password' ) && $this->get_option( 'sandbox_api_signature' );
} else {
$has_api_creds = $this->get_option( 'api_username' ) && $this->get_option( 'api_password' ) && $this->get_option( 'api_signature' );
}
return $order && $order->get_transaction_id() && $has_api_creds;
}
/**
@ -321,8 +342,7 @@ class WC_Gateway_Paypal extends WC_Payment_Gateway {
$order = wc_get_order( $order_id );
if ( ! $this->can_refund_order( $order ) ) {
$this->log( 'Refund Failed: No transaction ID', 'error' );
return new WP_Error( 'error', __( 'Refund failed: No transaction ID', 'woocommerce' ) );
return new WP_Error( 'error', __( 'Refund failed.', 'woocommerce' ) );
}
$this->init_api();

View File

@ -46,6 +46,7 @@ class WC_Product_CSV_Importer extends WC_Product_Importer {
'delimiter' => ',', // CSV delimiter.
'prevent_timeouts' => true, // Check memory and time usage and abort if reaching limit.
'enclosure' => '"', // The character used to wrap text in the CSV.
'escape' => "\0", // PHP uses '\' as the default escape character. This is not RFC-4180 compliant. This disables the escape character.
);
$this->params = wp_parse_args( $params, $default_args );
@ -65,7 +66,7 @@ class WC_Product_CSV_Importer extends WC_Product_Importer {
$handle = fopen( $this->file, 'r' ); // @codingStandardsIgnoreLine.
if ( false !== $handle ) {
$this->raw_keys = fgetcsv( $handle, 0, $this->params['delimiter'], $this->params['enclosure'] );
$this->raw_keys = version_compare( PHP_VERSION, '5.3', '>=' ) ? fgetcsv( $handle, 0, $this->params['delimiter'], $this->params['enclosure'], $this->params['escape'] ) : fgetcsv( $handle, 0, $this->params['delimiter'], $this->params['enclosure'] ); // @codingStandardsIgnoreLine
// Remove BOM signature from the first item.
if ( isset( $this->raw_keys[0] ) ) {
@ -77,7 +78,7 @@ class WC_Product_CSV_Importer extends WC_Product_Importer {
}
while ( 1 ) {
$row = fgetcsv( $handle, 0, $this->params['delimiter'], $this->params['enclosure'] );
$row = version_compare( PHP_VERSION, '5.3', '>=' ) ? fgetcsv( $handle, 0, $this->params['delimiter'], $this->params['enclosure'], $this->params['escape'] ) : fgetcsv( $handle, 0, $this->params['delimiter'], $this->params['enclosure'] ); // @codingStandardsIgnoreLine
if ( false !== $row ) {
$this->raw_data[] = $row;

View File

@ -103,6 +103,7 @@ function wc_delete_product_transients( $post_id = 0 ) {
'wc_featured_products',
'wc_outofstock_count',
'wc_low_stock_count',
'wc_count_comments',
);
// Transient names that include an ID.

View File

@ -1633,3 +1633,54 @@ function wc_update_330_set_paypal_sandbox_credentials() {
function wc_update_330_db_version() {
WC_Install::update_db_version( '3.3.0' );
}
/**
* Update state codes for Ireland.
*/
function wc_update_340_irish_states() {
global $wpdb;
$ie_states = array(
'CK' => 'CO',
'DN' => 'D',
'GY' => 'G',
'TY' => 'TA',
);
foreach ( $ie_states as $old => $new ) {
$wpdb->query(
$wpdb->prepare(
"UPDATE $wpdb->postmeta
SET meta_value = %s
WHERE meta_key IN ( '_billing_state', '_shipping_state' )
AND meta_value = %s",
$new, $old
)
);
$wpdb->update(
"{$wpdb->prefix}woocommerce_shipping_zone_locations",
array(
'location_code' => 'IE:' . $new,
),
array(
'location_code' => 'IE:' . $old,
)
);
$wpdb->update(
"{$wpdb->prefix}woocommerce_tax_rates",
array(
'tax_rate_state' => strtoupper( $new ),
),
array(
'tax_rate_state' => strtoupper( $old ),
)
);
}
}
/**
* Update DB Version.
*/
function wc_update_340_db_version() {
WC_Install::update_db_version( '3.4.0' );
}

1080
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -26,7 +26,7 @@
"babel-preset-stage-2": "^6.13.0",
"chai": "^3.5.0",
"chai-as-promised": "^6.0.0",
"chromedriver": "^2.36.0",
"chromedriver": "^2.37.0",
"config": "^1.24.0",
"cross-env": "~5.1.1",
"grunt": "~1.0.1",
@ -47,7 +47,7 @@
"istanbul": "^1.0.0-alpha",
"mocha": "^3.0.2",
"stylelint": "~8.2.0",
"wc-e2e-page-objects": "0.9.0"
"wc-e2e-page-objects": "0.10.0"
},
"engines": {
"node": ">=8.9.3",

View File

@ -162,38 +162,124 @@ Yes you can! Join in on our [GitHub repository](https://github.com/woocommerce/w
= 3.4.0 - 2018-XX-XX =
* Feature - Added a new order widget to the dashboard (on multisite) so you can see your orders across multiple stores on the same WordPress network. #17598
* Feature - Added "display name" input on the My Account page. #19078
* Tweak - Made the system status tool which purges user carts also purge persistent carts.
* Tweak - Fixed settings table styling on mobile.
* Tweak - Don't call WC_Install::install() on downgrades.
* Tweak - Added a function to return a list of custom tables to aid with cleanup.
* Tweak - Display whether or not external object cache is enabled in system status report.
* Tweak - Standardize stock update messages in admin and correctly log who performed the action. When an order note is added after modifying stock manually, update order notes display via AJAX.
* Tweak - Added a santization function for flat rate costs to remove currency symbols.
* Tweak - Display zero value when using shipping classes.
* Tweak - Updated Flexslider to version 2.7.0.
* Tweak - Make sure terms page exists and isnt trashed before using it.
* Tweak - Hash customer email address in download URLs to protect privacy.
* Fix - Properly set orderby and order when calling WC_Customer_Download_Data_Store::get_downloads().
* Fix - Set maxlength for order item meta key to avoid values disapearing if too long.
* Fix - Remove hardcoded /wp-content check for downloads.
* Fix - Prevent shortcode [product_page] redirecting to the actual product's page after add to cart.
* Fix - Make the "main term" logic match for both the breadcrumb and product categories widget.
* Fix - Check parent status too when seeing if variation is purchasable.
* Fix - Made get_on_sale_products respect the setting to hide outofstock products.
* Dev - Gallery meta box is now powered by CRUD.
* Dev - Added support for additional HTML5 input types for settings/checkout forms.
* Dev - Made 'woocommerce_email_downloads_column_' hook format aware.
* Dev - Added extra params to `woocommerce_order_get_downloadable_items`.
* Dev - Allow default value for single_select_country and multi_select_countries.
* Dev - Added CSS classname to grouped product table.
* Dev - Mini cart item link now respects value of $product_permalink.
* Dev - Add missing `woocommerce_update_options__` actions for settings pages that override save method.
* Dev - Added `woocommerce_persistent_cart_enabled` filter.
* Dev - Refactor woocommerce_wp_select so it could be used for a multiselect.
* Dev - Added ability to declare sanitize_callback in settings API.
* Template - Update cart coupon button from input to button type.
* Performance - Optimized saving of orders. Adds a transient for needs_processing, and only saves changes when saving order items.
* Localization - Various spelling and grammar fixes.
* Feature - Product search improvements including stopword support and support for searching for multiple products at the same time. #19096
* Feature - Cash on Delivery gateway can be enabled/disabled for specific shipping methods instead of only method types. #19221
* Feature - Add wildcard email support for coupons. #19331
* Feature - Added support for the GeoLite2 library as a replacement for the deprecated MaxMind GeoIP library. #19419
* Tweak - Standardize stock update messages in admin and correctly log who performed the action. When an order note is added after modifying stock manually, update order notes display via AJAX. #18080
* Tweak - Rollback if payment complete or update status fails to prevent partial order updates on failure. #18175
* Tweak - Made the system status tool which purges user carts also purge persistent carts. #18492
* Tweak - Display whether or not external object cache is enabled in system status report. #18595
* Tweak - Display zero value when using shipping classes. #18624
* Tweak - Fixed settings table styling on mobile. #18655
* Tweak - Updated Flexslider to version 2.7.0. #18779
* Tweak - Enable screen options for list screens. #18817
* Tweak - Don't call WC_Install::install() on downgrades. #18818
* Tweak - Remove user login from reset password link to protect personally identifying info. #18820
* Tweak - Added a function to return a list of custom tables to aid with cleanup. #18831
* Tweak - Enable going backwards in the setup wizard. #18921
* Tweak - Hash customer email address in download URLs to protect privacy. #18957
* Tweak - Make sure terms page exists and isnt trashed before using it. #18993
* Tweak - Toggle when clicking anywhere in toggle row during setup wizard. #19035
* Tweak - Use `read_product` permissions instead of `edit_product` for ajax product search. #19087
* Tweak - Add `priceSpecification` property with `valueAddedTaxIncluded` to product structured data. #19091
* Tweak - Importer remembers mappings across imports. #19110
* Tweak - Made coupon total displayed in cart more consistent. #19166
* Tweak - Remove forced CSS line-heights to improve text input displays across different browers. #19174
* Tweak - Add highlight to T&C checkbox if not checked to show it needs to be checked. #19177
* Tweak - When loading default attributes/variation, if there is no longer a match, reset the form and hide the notice #19190
* Tweak - Removed admin product type column from core and made it into a free feature plugin. #19192
* Tweak - Use `woocommerce-no-js` class to hide JavaScript-only forms and content. #19199
* Tweak - Activate plugins during installation process even if directory doesn't match slug. #19200
* Tweak - Allow category and attribute ids in the `products` shortcode instead of only slugs. #19204
* Tweak - Invalidate cart items when important props like product type are updated. #19255
* Tweak - Don't use mysql functions directly on system status page to prevent errors if they are disabled. #19281
* Tweak - Replaces `have_posts` with `woocommerce_product_loop` which looks to see if there are products, or if the loop is going to be showing something else. #19288
* Tweak - Delete widget options and order notes on uninstall. #19371
* Tweak - Add unique names to all nonces in template fields and forms. #19387
* Tweak - Enable using the tab key to select elements in selectWoo dropdowns. #19416
* Tweak - Added autocomplete attributes to form elements for better autocomplete support. #19426
* Tweak - Removed PayPal line item limit and ensured URLs are shorter than maximum length. #19493
* Tweak - Disable Gutenberg editor on products posts. #19543
* Tweak - Improvements around UI and wording of store setup step in setup wizard. #19550
* Tweak - Only push images to lightbox if an image is found. #19568
* Tweak - Added and improved notices around old PHP versions and disabled geolocation on PHP 5.4 or lower. #19573
* Tweak - The `manage_stock` field in the product API can return a `mixed` type instead of `boolean` for variations. #19598
* Tweak - Link product import/export to WordPress import/export capabilities. #19602
* Tweak - Use `&nbsp;` to separate asterisks in required fields to prevent awkward line breaks. #19610
* Tweak - Load meta box input values using CRUD and edit context. #19670
* Tweak - Scroll to notices on cart/checkout for better mobile visibility. #19699
* Fix - Properly set orderby and order when calling WC_Customer_Download_Data_Store::get_downloads(). #18620
* Fix - Set maxlength for order item meta key to avoid values disapearing if too long. #18918
* Fix - Remove hardcoded /wp-content check for downloads. #18961
* Fix - Made get_on_sale_products respect the setting to hide outofstock products. #18984
* Fix - Prevent shortcode [product_page] redirecting to the actual product's page after add to cart. #19043
* Fix - Make the "main term" logic match for both the breadcrumb and product categories widget. #19044
* Fix - Check parent status too when seeing if variation is purchasable. #19045
* Fix - Fix uppercasing of accented characters. #19086
* Fix - Do not allow updating parent ID from variations after created. #19097
* Fix - Ensure coupon amount is not empty to prevent non-numeric value errors. #19098
* Fix - Ensure shop archive works correctly when `paged=1` is in the URL. #19104
* Fix - Ensure orders created with `woocommerce_adjust_non_base_location_prices` filter active have the same cost on frontend and admin. #19109
* Fix - Handling in the CLI to prevent `Resource does not exist` errors when using commands of a certain format. #19123
* Fix - Use subtotal when calculating discounts in admin/orders to ensure prices are the same as on the frontend. #19159
* Fix - Use `kses` to process download names to prevent escaped HTML displaying in emails.
* Fix - Remove translation from Thailand state file to prevent PayPal errors around unsupported characters. #19219
* Fix - Fix auto-select variation URLs with special characters in them. #19283
* Fix - Introduced `wc_round_discount` and improved consistency of discount rounding. #19291
* Fix - Only add schema for ratings to structured data when ratings are enabled. #19310
* Fix - Prevent default state applying unless the country was also unset in JS state/country inputs. #19338
* Fix - Escape quantity labels correctly to prevent broken html. #19375
* Fix - Delete orphaned variations after product import. #19378
* Fix - Ensure API credentials exist before defining PayPal refund support. #19380
* Fix - Force word-wrapping in the log viewer to prevent layout-breaking long lines. #19503
* Fix - Removes permission checks that were preventing webhooks from displaying properly when no post object existed. #19508
* Fix - Empty cart after completing PayPal payment. #19509
* Fix - Strip tags on aria-labels in Add to Cart template to prevent broken HTML. #19522
* Fix - Update post_modified date when saving products and variations but no other product data. #19595
* Fix - Clear comment count transient when cleaning product transients to prevent incorrect comment count displays. #19664
* Fix - Load gateways before order is saved/email is triggered to ensure all information gets sent/processed. #19667
* Fix - Clear shipping transient when saving shipping method on zones screen. #19668
* Dev - Added refunded_payment prop to orders for determining if payment was refunded via API. #18196
* Dev - Added extra params to `woocommerce_order_get_downloadable_items`. #18408
* Dev - Store shipping method ID and instance ID in separate fields instead of both in one serialized field. #18483
* Dev - Add `woocommerce_rest_insert_system_status_tool` hook that fires after executing a REST system status tool. #18505
* Dev - Gallery meta box is now powered by CRUD. #18511
* Dev - Refactor woocommerce_wp_select so it could be used for a multiselect. #18536
* Dev - Added ability to declare sanitize_callback in settings API. #18554
* Dev - Added support for additional HTML5 input types for settings/checkout forms. #18594
* Dev - Made 'woocommerce_email_downloads_column_' hook format aware. #18600
* Dev - Add missing `woocommerce_update_options__` actions for settings pages that override save method. #18609
* Dev - Allow default value for single_select_country and multi_select_countries. #18754 #18756
* Dev - Added `grouped_form` class to grouped product `form` element. #18786
* Dev - Mini cart item link now respects value of $product_permalink. #18979
* Dev - Added `woocommerce_coupon_get_items_to_validate` filter to enable excluding products from coupon validation. #19002
* Dev - Added `woocommerce_persistent_cart_enabled` filter. #19027
* Dev - Replaced calls to `exit` with `wp_die` in the ajax methods to enable unit testing of those methods.
* Dev - Introduce `woocommerce_coupon_custom_discounts_array` filter to allow post processing on custom coupons. #19148
* Dev - Move jQuery UI styles into WooCommerce assets folder and load them from there. #19173
* Dev - Added `woocommerce_coupon_validate_expiry_date` filter to enable modifying the coupon expiry date check. #19228
* Dev - Added `woocommerce_shipping_calculator_enable_state` filter to enable disabling state section in shipping calculator. #19241
* Dev - Added `woocommerce_bacs_process_payment_order_status` filter allowing plugins to change the order status to the BACS gateway. #19311
* Dev - Added `woocommerce_coupon_sort` filter to allow plugins to override the default coupon apply order. #19339
* Dev - Added `woocommerce_before_output_product_categories` and `woocommerce_after_output_product_categories` filters. #19363
* Dev - Added general `woocommerce_form_field` filter to make it easier to filter all of the form fields. #19388
* Dev - Added `woocommerce_install_get_tables` filter to enable plugins to register new, WooCommerce-specific tables. $19436
* Dev - Use `get_variation_price` method in structured data to grab min/max so filters are ran. #19527
* Dev - Added `woocommerce_helper_suppress_connect_notice` filter to enable suppressing the admin WordPress.com connection message. #19599
* Dev - Moved all photoswipe styles to `photoswipe.css` to make it easy to dequeue all the photoswipe styles. #19673
* Performance - Optimized saving of orders. Adds a transient for needs_processing, and only saves changes when saving order items. #18538
* Performance - Refactored the SQL query for `WC_Customer_Download_Data_Store::get_downloads()` to fetch available downloads faster. #18559
* Performance - Split the layered nav counts into multiple transient records by taxonomy and added a filter to allow bypassing caching. #19225
* Performance - Removed duplicate `SET SESSION SQL_BIG_SELECTS=1` queries. #19502
* Performance - Avoid storing coupon `_used_by` data to prevent DB bloat. #19669
* Template - Update cart coupon button from input to button type. #19059
* Template - Added `woocommerce-form-register` class to registration form. #19486
* Template - Added escaping to publish date. #19530
* Localization - Switched Georgian Lari symbol to new UTF symbol. #19603
* Localization - Use ISO county codes for Irish states. #19658
* Localization - Various spelling, and grammar fixes.
* Localization - Various phrasing improvements.
[See changelog for all versions](https://raw.githubusercontent.com/woocommerce/woocommerce/master/CHANGELOG.txt).

View File

@ -86,7 +86,7 @@ do_action( 'woocommerce_before_cart' ); ?>
// Backorder notification.
if ( $_product->backorders_require_notification() && $_product->is_on_backorder( $cart_item['quantity'] ) ) {
echo '<p class="backorder_notification">' . esc_html__( 'Available on backorder', 'woocommerce' ) . '</p>';
echo wp_kses_post( apply_filters( 'woocommerce_cart_item_backorder_notification', '<p class="backorder_notification">' . esc_html__( 'Available on backorder', 'woocommerce' ) . '</p>' ) );
}
?>
</td>

View File

@ -105,6 +105,7 @@ class WC_Unit_Tests_Bootstrap {
require_once $this->tests_dir . '/framework/class-wc-mock-session-handler.php';
require_once $this->tests_dir . '/framework/class-wc-mock-wc-data.php';
require_once $this->tests_dir . '/framework/class-wc-mock-wc-object-query.php';
require_once $this->tests_dir . '/framework/class-wc-mock-payment-gateway.php';
require_once $this->tests_dir . '/framework/class-wc-payment-token-stub.php';
require_once $this->tests_dir . '/framework/vendor/class-wp-test-spy-rest-server.php';

View File

@ -0,0 +1,21 @@
<?php
class WC_Mock_Payment_Gateway extends WC_Payment_Gateway {
/**
* Constructor for the gateway.
*/
public function __construct() {
$this->id = 'mock';
$this->has_fields = false;
$this->order_button_text = __( 'Proceed to PayPal', 'woocommerce' );
$this->method_title = 'Mock Gateway';
$this->method_description = 'Mock Gateway for unit tests';
$this->supports = array(
'products',
);
// Load the settings.
$this->init_form_fields();
$this->init_settings();
}
}

View File

@ -49,7 +49,7 @@ class Payment_Gateways extends WC_REST_Unit_Test_Case {
'order' => '',
'enabled' => false,
'method_title' => 'Check payments',
'method_description' => 'Allows check payments. Why would you take checks in this day and age? Well you probably would not, but it does allow you to make test purchases for testing order emails and the success pages.',
'method_description' => 'Take payments in-person via checks. This offline gateway can also be useful to test purchases.',
'settings' => array_diff_key( $this->get_settings( 'WC_Gateway_Cheque' ), array( 'enabled' => false, 'description' => false ) ),
'_links' => array(
'self' => array(
@ -96,7 +96,7 @@ class Payment_Gateways extends WC_REST_Unit_Test_Case {
'order' => '',
'enabled' => false,
'method_title' => 'PayPal',
'method_description' => 'PayPal Standard sends customers to PayPal to enter their payment information. PayPal IPN requires fsockopen/cURL support to update order statuses after payment. Check the <a href="http://example.org/wp-admin/admin.php?page=wc-status">system status</a> page for more details.',
'method_description' => 'PayPal Standard redirects customers to PayPal to enter their payment information.',
'settings' => array_diff_key( $this->get_settings( 'WC_Gateway_Paypal' ), array( 'enabled' => false, 'description' => false ) ),
), $paypal );
}

View File

@ -0,0 +1,75 @@
<?php
/**
* Unit tests for gateways.
*
* @package WooCommerce\Tests\Gateways
*/
class WC_Tests_Gateways extends WC_Unit_Test_Case {
/**
* Test for supports() method.
*/
public function test_supports() {
$gateway = new WC_Mock_Payment_Gateway();
$this->assertTrue( $gateway->supports( 'products' ) );
$this->assertFalse( $gateway->supports( 'made-up-feature' ) );
}
/**
* Test for supports() method.
*/
public function test_can_refund_order() {
$gateway = new WC_Mock_Payment_Gateway();
$order = WC_Helper_Order::create_order();
$order->set_payment_method( 'mock' );
$order->set_transaction_id( '12345' );
$order->save();
$this->assertFalse( $gateway->can_refund_order( $order ) );
$gateway->supports[] = 'refunds';
$this->assertTrue( $gateway->can_refund_order( $order ) );
// Cleanup.
$order->delete( true );
}
/**
* Test for PayPal supports() method.
*/
public function test_paypal_can_refund_order() {
$gateway = new WC_Gateway_Paypal();
$order = WC_Helper_Order::create_order();
$order->set_payment_method( 'paypal' );
$order->set_transaction_id( '12345' );
$order->save();
// Refunds won't work without credentials.
$this->assertFalse( $gateway->can_refund_order( $order ) );
// Add API credentials.
$settings = array(
'testmode' => 'yes',
'sandbox_api_username' => 'test',
'sandbox_api_password' => 'test',
'sandbox_api_signature' => 'test',
);
update_option( 'woocommerce_paypal_settings ', $settings );
$gateway = new WC_Gateway_Paypal();
$this->assertTrue( $gateway->can_refund_order( $order ) );
// Refund requires transaction ID.
$order->set_transaction_id( '' );
$order->save();
$this->assertFalse( $gateway->can_refund_order( $order ) );
// Cleanup.
delete_option( 'woocommerce_paypal_settings' );
$order->delete( true );
}
}