Merge remote-tracking branch 'upstream/master' into travis-use-latest-php

This commit is contained in:
Rodrigo Primo 2019-12-20 09:17:03 -03:00
commit 70553c52aa
198 changed files with 12551 additions and 5975 deletions

View File

@ -1,9 +0,0 @@
{
"presets": [
"es2015",
"stage-2"
],
"plugins": [
"add-module-exports"
]
}

View File

@ -2,13 +2,19 @@
"root": true,
"env": {
"browser": true,
"node": true
"es6": true,
"node": true,
"jest/globals": true
},
"globals": {
"wp": true,
"wpApiSettings": true,
"wcSettings": true,
"es6": true
"es6": true,
"page": true,
"browser": true,
"context": true,
"jestPuppeteer": true
},
"rules": {
"camelcase": 0,
@ -16,7 +22,19 @@
"max-len": [ 2, { "code": 140 } ],
"no-console": 1
},
"plugins": [
"jest"
],
"extends": [
"plugin:jest/recommended"
],
"parser": "babel-eslint",
"parserOptions": {
"ecmaVersion": 6
"ecmaVersion": 8,
"ecmaFeatures": {
"modules": true,
"experimentalObjectRestSpread": true,
"jsx": true
}
}
}

2
.gitattributes vendored
View File

@ -1,4 +1,5 @@
/.* export-ignore
bin export-ignore
CODE_OF_CONDUCT.md export-ignore
CHANGELOG.txt export-ignore
composer.* export-ignore
@ -9,3 +10,4 @@ phpcs.xml export-ignore
phpunit.* export-ignore
README.md export-ignore
tests export-ignore
renovate.json export-ignore

1
.gitignore vendored
View File

@ -20,6 +20,7 @@ none
# Compiled CSS
/assets/css/*.css
/assets/css/photoswipe/**/*.min.css
# Minified JS
/assets/js/admin/*.min.js

View File

@ -5,6 +5,8 @@ dist: xenial
services:
- xvfb
- mysql
- docker
- docker-compose
sudo: false
@ -20,6 +22,7 @@ php:
- 7.1
- 7.2
- 7.3
- 7.4
env:
- WP_VERSION=latest WP_MULTISITE=0
@ -32,27 +35,24 @@ matrix:
- name: "Coding standard check"
php: 7.4
env: WP_VERSION=latest WP_MULTISITE=0 RUN_PHPCS=1
- name: "e2e tests"
- name: "E2E tests"
php: 7.4
env: WP_VERSION=latest WP_MULTISITE=0 RUN_E2E=1
addons:
chrome: beta
apt:
packages:
- nginx
script:
- npm install
- npm run build
- docker-compose up --build -d
- bash tests/bin/run-e2e-CI.sh
after_script:
- docker-compose down -v
- name: "Unit tests code coverage"
php: 7.4
env: WP_VERSION=latest WP_MULTISITE=0 RUN_CODE_COVERAGE=1
- name: "WooCommerce unit tests using WordPress nightly"
php: 7.4
env: WP_VERSION=nightly WP_MULTISITE=0
- php: 7.4snapshot
env: WP_VERSION=nightly WP_MULTISITE=0
allow_failures:
- php: 7.4
env: WP_VERSION=latest WP_MULTISITE=0 RUN_CODE_COVERAGE=1
- php: 7.4
env: WP_VERSION=latest WP_MULTISITE=0 RUN_E2E=1
before_script:
- export PATH="$HOME/.composer/vendor/bin:$PATH"
@ -75,7 +75,6 @@ before_script:
script:
- bash tests/bin/phpunit.sh
- bash tests/bin/phpcs.sh
- travis_retry bash tests/bin/run-e2e-CI.sh
after_script:
- bash tests/bin/travis.sh after

3
Dockerfile Normal file
View File

@ -0,0 +1,3 @@
FROM wordpress:5.3
COPY . /var/www/html/wp-content/plugins/woocommerce

View File

@ -148,11 +148,29 @@ module.exports = function( grunt ) {
// Minify all .css files.
cssmin: {
minify: {
expand: true,
cwd: '<%= dirs.css %>/',
src: ['*.css'],
dest: '<%= dirs.css %>/',
ext: '.css'
files: [
{
expand: true,
cwd: '<%= dirs.css %>/',
src: ['*.css'],
dest: '<%= dirs.css %>/',
ext: '.css'
},
{
expand: true,
cwd: '<%= dirs.css %>/photoswipe/',
src: ['*.css', '!*.min.css'],
dest: '<%= dirs.css %>/photoswipe/',
ext: '.min.css'
},
{
expand: true,
cwd: '<%= dirs.css %>/photoswipe/default-skin/',
src: ['*.css', '!*.min.css'],
dest: '<%= dirs.css %>/photoswipe/default-skin/',
ext: '.min.css'
}
]
}
},
@ -229,7 +247,6 @@ module.exports = function( grunt ) {
files: {
src: [
'**/*.php', // Include all files
'!includes/libraries/**', // Exclude libraries/
'!node_modules/**', // Exclude node_modules/
'!tests/**', // Exclude tests/
'!vendor/**', // Exclude vendor/

View File

@ -2,20 +2,20 @@
* WooCommerce CSS Variables
*/
$woocommerce: #a46497;
$green: #7ad03a;
$red: #a00;
$orange: #ffba00;
$blue: #2ea2cc;
$woocommerce: #a46497 !default;
$green: #7ad03a !default;
$red: #a00 !default;
$orange: #ffba00 !default;
$blue: #2ea2cc !default;
$primary: #a46497; // Primary color for buttons (alt)
$primarytext: desaturate(lighten($primary, 50%), 18%); // Text on primary color bg
$primary: #a46497 !default; // Primary color for buttons (alt)
$primarytext: desaturate(lighten($primary, 50%), 18%) !default; // Text on primary color bg
$secondary: desaturate(lighten($primary, 40%), 21%); // Secondary buttons
$secondarytext: desaturate(darken($secondary, 60%), 21%); // Text on secondary color bg
$secondary: desaturate(lighten($primary, 40%), 21%) !default; // Secondary buttons
$secondarytext: desaturate(darken($secondary, 60%), 21%) !default; // Text on secondary color bg
$highlight: adjust-hue($primary, 150deg); // Prices, In stock labels, sales flash
$highlightext: desaturate(lighten($highlight, 50%), 18%); // Text on highlight color bg
$highlight: adjust-hue($primary, 150deg) !default; // Prices, In stock labels, sales flash
$highlightext: desaturate(lighten($highlight, 50%), 18%) !default; // Text on highlight color bg
$contentbg: #fff; // Content BG - Tabs (active state)
$subtext: #767676; // small, breadcrumbs etc
$contentbg: #fff !default; // Content BG - Tabs (active state)
$subtext: #767676 !default; // small, breadcrumbs etc

View File

@ -6818,50 +6818,47 @@ table.bar_chart {
/**
* Select2 colors for built-in admin color themes.
*/
.branch-5-3 {
.admin-color {
$wp_admin_colors: (
blue: #096484,
coffee: #c7a589,
ectoplasm: #a3b745,
midnight: #e14d43,
ocean: #9ebaa0,
sunrise: #dd823b,
light: #04a4cc
);
.admin-color {
$wp_admin_colors: (
blue: #096484,
coffee: #c7a589,
ectoplasm: #a3b745,
midnight: #e14d43,
ocean: #9ebaa0,
sunrise: #dd823b,
light: #04a4cc
);
@each $name, $color in $wp_admin_colors {
@each $name, $color in $wp_admin_colors {
&-#{$name}.branch-5-3 {
&-#{$name} {
.select2-dropdown {
border-color: $color;
}
.select2-dropdown {
border-color: $color;
}
.select2-dropdown--below {
box-shadow: 0 0 0 1px $color, 0 2px 1px rgba(0, 0, 0, 0.1);
}
.select2-dropdown--below {
box-shadow: 0 0 0 1px $color, 0 2px 1px rgba(0, 0, 0, 0.1);
}
.select2-dropdown--above {
box-shadow: 0 0 0 1px $color, 0 -2px 1px rgba(0, 0, 0, 0.1);
}
.select2-dropdown--above {
box-shadow: 0 0 0 1px $color, 0 -2px 1px rgba(0, 0, 0, 0.1);
}
.select2-selection--single .select2-selection__rendered:hover {
color: $color;
}
.select2-selection--single .select2-selection__rendered:hover {
color: $color;
}
.select2-container.select2-container--focus .select2-selection--single,
.select2-container.select2-container--open .select2-selection--single,
.select2-container.select2-container--open .select2-selection--multiple {
border-color: $color;
box-shadow: 0 0 0 1px $color;
}
.select2-container.select2-container--focus .select2-selection--single,
.select2-container.select2-container--open .select2-selection--single,
.select2-container.select2-container--open .select2-selection--multiple {
border-color: $color;
box-shadow: 0 0 0 1px $color;
}
.select2-container--default .select2-results__option--highlighted[aria-selected],
.select2-container--default .select2-results__option--highlighted[data-selected] {
background-color: $color;
}
.select2-container--default .select2-results__option--highlighted[aria-selected],
.select2-container--default .select2-results__option--highlighted[data-selected] {
background-color: $color;
}
}
}

File diff suppressed because one or more lines are too long

View File

@ -6,7 +6,7 @@ body {
padding: 0;
}
#wc-logo {
.wc-logo {
border: 0;
margin: 0 0 24px;
padding: 0;
@ -1070,6 +1070,31 @@ h3.jetpack-reasons {
}
}
.wc-setup-step__new_onboarding {
.wc-logo,
.wc-setup-steps {
display: none;
}
.wc-setup-step__new_onboarding-wrapper {
.wc-logo {
display: block;
}
p {
text-align: center;
}
.wc-setup-step__new_onboarding-welcome,
.wc-setup-step__new_onboarding-plugin-info {
color: #7c7c7c;
font-size: 12px;
}
}
}
.step {
text-align: center;
}
@ -1146,7 +1171,7 @@ h3.jetpack-reasons {
border-color: #ddd;
border-radius: 4px;
height: 30px;
width: 100%;
width: calc(100% - 8px - 8px - 2px);
padding-left: 8px;
padding-right: 8px;
font-size: 16px;
@ -1159,11 +1184,12 @@ h3.jetpack-reasons {
}
}
.branch-5-2,
.branch-5-3 {
.location-input {
margin: 0;
width: 100%;
}
}
@ -1388,6 +1414,7 @@ p.jetpack-terms {
}
}
.branch-5-2,
.branch-5-3 {
.wc-wizard-service-setting-stripe_create_account,
@ -1523,7 +1550,7 @@ p.jetpack-terms {
@media only screen and (max-width: 400px) {
#wc-logo img {
.wc-logo img {
max-width: 80%;
}

View File

@ -6,17 +6,19 @@
/**
* Imports
*/
@import 'mixins';
@import 'variables';
@import "mixins";
@import "variables";
/**
* Styling begins
*/
.woocommerce, .woocommerce-page {
.woocommerce,
.woocommerce-page {
.woocommerce-message,
.woocommerce-error,
.woocommerce-info {
.button {
float: right;
}
@ -26,6 +28,7 @@
* General layout styles
*/
.col2-set {
@include clearfix();
width: 100%;
@ -33,6 +36,7 @@
float: left;
width: 48%;
}
.col-2 {
float: right;
width: 48%;
@ -49,12 +53,14 @@
*/
div.product,
#content div.product {
div.images {
float: left;
width: 48%;
}
div.thumbnails {
@include clearfix();
a {
@ -73,6 +79,7 @@
}
&.columns-1 {
a {
width: 100%;
margin-right: 0;
@ -81,18 +88,21 @@
}
&.columns-2 {
a {
width: 48%;
}
}
&.columns-4 {
a {
width: 22.05%;
}
}
&.columns-5 {
a {
width: 16.9%;
}
@ -109,12 +119,15 @@
clear: both;
ul.tabs {
@include menu();
}
}
#reviews {
.comment {
@include mediaright();
}
}
@ -125,6 +138,7 @@
*/
ul.products {
clear: both;
@include clearfix();
li.product {
@ -146,28 +160,38 @@
}
ul.products {
&.columns-1 {
li.product {
width: 100%;
margin-right: 0;
}
}
&.columns-2 {
li.product {
width: 48%;
}
}
&.columns-3 {
li.product {
width: 30.75%;
}
}
&.columns-5 {
li.product {
width: 16.95%;
}
}
&.columns-6 {
li.product {
width: 13.5%;
}
@ -175,7 +199,9 @@
}
&.columns-1 {
ul.products {
li.product {
width: 100%;
margin-right: 0;
@ -184,7 +210,9 @@
}
&.columns-2 {
ul.products {
li.product {
width: 48%;
}
@ -192,7 +220,9 @@
}
&.columns-3 {
ul.products {
li.product {
width: 30.75%;
}
@ -200,7 +230,9 @@
}
&.columns-5 {
ul.products {
li.product {
width: 16.95%;
}
@ -208,7 +240,9 @@
}
&.columns-6 {
ul.products {
li.product {
width: 13.5%;
}
@ -218,12 +252,15 @@
.woocommerce-result-count {
float: left;
}
.woocommerce-ordering {
float: right;
}
.woocommerce-pagination {
ul.page-numbers {
@include menu();
}
}
@ -233,6 +270,7 @@
*/
table.cart,
#content table.cart {
img {
height: auto;
}
@ -255,6 +293,7 @@
}
.cart-collaterals {
@include clearfix();
width: 100%;
@ -278,11 +317,13 @@
.shipping_calculator {
width: 48%;
@include clearfix();
clear: right;
float: right;
.col2-set {
.col-1,
.col-2 {
width: 47%;
@ -301,7 +342,9 @@
*/
ul.cart_list,
ul.product_list_widget {
li {
@include mediaright();
}
}
@ -310,7 +353,9 @@
* Forms
*/
form {
.form-row {
@include clearfix();
label {
@ -352,19 +397,54 @@
.form-row-wide {
clear: both;
}
.password-input {
display: flex;
flex-direction: column;
justify-content: center;
position: relative;
input[type="password"] {
padding-right: 2.5rem;
}
/* Hide the Edge "reveal password" native button */
input::-ms-reveal {
display: none;
}
}
.show-password-input {
position: absolute;
right: 0.7em;
top: 0.7em;
cursor: pointer;
}
.show-password-input::after {
@include iconafter( "\e010" ); // Icon styles and glyph
}
.show-password-input.display-password::after {
color: #e8e8e8;
}
}
#payment {
.form-row {
select {
width: auto;
}
}
.wc-terms-and-conditions, .terms {
.wc-terms-and-conditions,
.terms {
text-align: left;
padding: 0 1em 0 0;
float:left;
float: left;
}
#place_order {
@ -374,6 +454,7 @@
.woocommerce-billing-fields,
.woocommerce-shipping-fields {
@include clearfix();
}
@ -391,6 +472,7 @@
}
.woocommerce-account {
.woocommerce-MyAccount-navigation {
float: left;
width: 30%;
@ -406,7 +488,9 @@
* Twenty Eleven specific styles
*/
.woocommerce-page {
&.left-sidebar {
#content.twentyeleven {
width: 58.4%;
margin: 0 7.6%;
@ -415,6 +499,7 @@
}
&.right-sidebar {
#content.twentyeleven {
margin: 0 7.6%;
width: 58.4%;
@ -427,6 +512,7 @@
* Twenty Fourteen specific styles
*/
.twentyfourteen {
.tfwc {
padding: 12px 10px 0;
max-width: 474px;
@ -444,7 +530,9 @@
}
@media screen and (min-width: 673px) {
.twentyfourteen {
.tfwc {
padding-right: 30px;
padding-left: 30px;
@ -453,7 +541,9 @@
}
@media screen and (min-width: 1040px) {
.twentyfourteen {
.tfwc {
padding-right: 15px;
padding-left: 15px;
@ -462,7 +552,9 @@
}
@media screen and (min-width: 1110px) {
.twentyfourteen {
.tfwc {
padding-right: 30px;
padding-left: 30px;
@ -471,13 +563,18 @@
}
@media screen and (min-width: 1218px) {
.twentyfourteen {
.tfwc {
margin-right: 54px;
}
}
.full-width {
.twentyfourteen {
.tfwc {
margin-right: auto;
}
@ -489,6 +586,7 @@
* Twenty Fifteen specific styles
*/
.twentyfifteen {
.t15wc {
padding-left: 7.6923%;
padding-right: 7.6923%;
@ -504,7 +602,9 @@
}
@media screen and (min-width: 38.75em) {
.twentyfifteen {
.t15wc {
margin-right: 7.6923%;
margin-left: 7.6923%;
@ -514,7 +614,9 @@
}
@media screen and (min-width: 59.6875em) {
.twentyfifteen {
.t15wc {
margin-left: 8.3333%;
margin-right: 8.3333%;
@ -523,7 +625,9 @@
}
.single-product {
.twentyfifteen {
.entry-summary {
padding: 0 !important;
}
@ -535,6 +639,7 @@
* Twenty Sixteen specific styles
*/
.twentysixteen {
.site-main {
margin-right: 7.6923%;
margin-left: 7.6923%;
@ -547,8 +652,11 @@
}
#content {
.twentysixteen {
div.product {
div.images,
div.summary {
width: 46.42857%;
@ -558,7 +666,9 @@
}
@media screen and (min-width: 44.375em) {
.twentysixteen {
.site-main {
margin-right: 23.0769%;
}
@ -566,7 +676,9 @@
}
@media screen and (min-width: 56.875em) {
.twentysixteen {
.site-main {
margin-right: 0;
margin-left: 0;
@ -574,7 +686,9 @@
}
.no-sidebar {
.twentysixteen {
.site-main {
margin-right: 15%;
margin-left: 15%;
@ -592,11 +706,16 @@
* RTL styles.
*/
.rtl {
.woocommerce, .woocommerce-page {
.woocommerce,
.woocommerce-page {
.col2-set {
.col-1 {
float: right;
}
.col-2 {
float: left;
}

View File

@ -383,10 +383,12 @@ jQuery( function ( $ ) {
var unit_total_tax = accounting.unformat( $line_total_tax.attr( 'data-total_tax' ), woocommerce_admin.mon_decimal_point ) / o_qty;
var $line_subtotal_tax = $( 'input.line_subtotal_tax[data-tax_id="' + tax_id + '"]', $row );
var unit_subtotal_tax = accounting.unformat( $line_subtotal_tax.attr( 'data-subtotal_tax' ), woocommerce_admin.mon_decimal_point ) / o_qty;
var round_at_subtotal = 'yes' === woocommerce_admin_meta_boxes.round_at_subtotal;
var precision = woocommerce_admin_meta_boxes[ round_at_subtotal ? 'rounding_precision' : 'currency_format_num_decimals' ];
if ( 0 < unit_total_tax ) {
$line_total_tax.val(
parseFloat( accounting.formatNumber( unit_total_tax * qty, woocommerce_admin_meta_boxes.rounding_precision, '' ) )
parseFloat( accounting.formatNumber( unit_total_tax * qty, precision, '' ) )
.toString()
.replace( '.', woocommerce_admin.mon_decimal_point )
);
@ -394,7 +396,7 @@ jQuery( function ( $ ) {
if ( 0 < unit_subtotal_tax ) {
$line_subtotal_tax.val(
parseFloat( accounting.formatNumber( unit_subtotal_tax * qty, woocommerce_admin_meta_boxes.rounding_precision, '' ) )
parseFloat( accounting.formatNumber( unit_subtotal_tax * qty, precision, '' ) )
.toString()
.replace( '.', woocommerce_admin.mon_decimal_point )
);
@ -1019,8 +1021,11 @@ jQuery( function ( $ ) {
var unit_total_tax = accounting.unformat( line_total_tax.data( 'total_tax' ), woocommerce_admin.mon_decimal_point ) / qty;
if ( 0 < unit_total_tax ) {
var round_at_subtotal = 'yes' === woocommerce_admin_meta_boxes.round_at_subtotal;
var precision = woocommerce_admin_meta_boxes[ round_at_subtotal ? 'rounding_precision' : 'currency_format_num_decimals' ];
$refund_line_total_tax.val(
parseFloat( accounting.formatNumber( unit_total_tax * refund_qty, woocommerce_admin_meta_boxes.rounding_precision, '' ) )
parseFloat( accounting.formatNumber( unit_total_tax * refund_qty, precision, '' ) )
.toString()
.replace( '.', woocommerce_admin.mon_decimal_point )
).change();

View File

@ -91,6 +91,7 @@ jQuery( function( $ ) {
action : $( this ).data( 'action' ) || 'woocommerce_json_search_products_and_variations',
security : wc_enhanced_select_params.search_products_nonce,
exclude : $( this ).data( 'exclude' ),
exclude_type : $( this ).data( 'exclude_type' ),
include : $( this ).data( 'include' ),
limit : $( this ).data( 'limit' ),
display_stock: $( this ).data( 'display_stock' )
@ -260,14 +261,16 @@ jQuery( function( $ ) {
// WooCommerce Backbone Modal
.on( 'wc_backbone_modal_before_remove', function() {
$( '.wc-enhanced-select, :input.wc-product-search, :input.wc-customer-search' ).filter( '.select2-hidden-accessible' ).selectWoo( 'close' );
$( '.wc-enhanced-select, :input.wc-product-search, :input.wc-customer-search' ).filter( '.select2-hidden-accessible' )
.selectWoo( 'close' );
})
.trigger( 'wc-enhanced-select-init' );
$( 'html' ).on( 'click', function( event ) {
if ( this === event.target ) {
$( '.wc-enhanced-select, :input.wc-product-search, :input.wc-customer-search' ).filter( '.select2-hidden-accessible' ).selectWoo( 'close' );
$( '.wc-enhanced-select, :input.wc-product-search, :input.wc-customer-search' ).filter( '.select2-hidden-accessible' )
.selectWoo( 'close' );
}
} );
} catch( err ) {

View File

@ -216,6 +216,11 @@ jQuery( function( $ ) {
waitForJetpackInstall();
} );
$( '.activate-new-onboarding' ).on( 'click', '.button-primary', function() {
// Show pending spinner while activate happens.
blockWizardUI();
} );
$( '.wc-wizard-services' ).on( 'change', 'input#stripe_create_account, input#ppec_paypal_reroute_requests', function() {
if ( $( this ).is( ':checked' ) ) {
$( this ).closest( '.wc-wizard-service-settings' )

View File

@ -61,16 +61,18 @@
})
.on( 'change', '.wc_input_price[type=text], .wc_input_decimal[type=text], .wc-order-totals #refund_amount[type=text]', function() {
var regex;
var regex, decimalRegex,
decimailPoint = woocommerce_admin.decimal_point;
if ( $( this ).is( '.wc_input_price' ) || $( this ).is( '#refund_amount' ) ) {
regex = new RegExp( '[^\-0-9\%\\' + woocommerce_admin.mon_decimal_point + ']+', 'gi' );
} else {
regex = new RegExp( '[^\-0-9\%\\' + woocommerce_admin.decimal_point + ']+', 'gi' );
decimailPoint = woocommerce_admin.mon_decimal_point;
}
regex = new RegExp( '[^\-0-9\%\\' + decimailPoint + ']+', 'gi' );
decimalRegex = new RegExp( '\\' + decimailPoint + '+', 'gi' );
var value = $( this ).val();
var newvalue = value.replace( regex, '' );
var newvalue = value.replace( regex, '' ).replace( decimalRegex, decimailPoint );
if ( value !== newvalue ) {
$( this ).val( newvalue );
@ -78,22 +80,32 @@
})
.on( 'keyup', '.wc_input_price[type=text], .wc_input_decimal[type=text], .wc_input_country_iso[type=text], .wc-order-totals #refund_amount[type=text]', function() {
var regex, error;
var regex, error, decimalRegex;
var checkDecimalNumbers = false;
if ( $( this ).is( '.wc_input_price' ) || $( this ).is( '#refund_amount' ) ) {
checkDecimalNumbers = true;
regex = new RegExp( '[^\-0-9\%\\' + woocommerce_admin.mon_decimal_point + ']+', 'gi' );
decimalRegex = new RegExp( '[^\\' + woocommerce_admin.mon_decimal_point + ']', 'gi' );
error = 'i18n_mon_decimal_error';
} else if ( $( this ).is( '.wc_input_country_iso' ) ) {
regex = new RegExp( '([^A-Z])+|(.){3,}', 'im' );
error = 'i18n_country_iso_error';
} else {
checkDecimalNumbers = true;
regex = new RegExp( '[^\-0-9\%\\' + woocommerce_admin.decimal_point + ']+', 'gi' );
decimalRegex = new RegExp( '[^\\' + woocommerce_admin.decimal_point + ']', 'gi' );
error = 'i18n_decimal_error';
}
var value = $( this ).val();
var newvalue = value.replace( regex, '' );
// Check if newvalue have more than one decimal point.
if ( checkDecimalNumbers && 1 < newvalue.replace( decimalRegex, '' ).length ) {
newvalue = newvalue.replace( decimalRegex, '' );
}
if ( value !== newvalue ) {
$( document.body ).triggerHandler( 'wc_add_error_tip', [ $( this ), error ] );
} else {

View File

@ -88,6 +88,18 @@
event.data.variationForm.$form.find( '.single_add_to_cart_button' ).removeClass( 'wc-variation-selection-needed' ).addClass( 'disabled wc-variation-is-unavailable' );
event.data.variationForm.$form.find( '.woocommerce-variation-add-to-cart' ).removeClass( 'woocommerce-variation-add-to-cart-enabled' ).addClass( 'woocommerce-variation-add-to-cart-disabled' );
}
// If present, the media element library needs initialized on the variation description.
if ( wp.mediaelement ) {
event.data.variationForm.$form.find( '.wp-audio-shortcode, .wp-video-shortcode' )
.not( '.mejs-container' )
.filter(
function () {
return ! $( this ).parent().hasClass( 'mejs-mediaelement' );
}
)
.mediaelementplayer( wp.mediaelement.settings );
}
};
/**

View File

@ -71,7 +71,7 @@ jQuery( function( $ ) {
var data = {};
$.each( $thisbutton.data(), function( key, value ) {
$.each( $thisbutton[0].dataset, function( key, value ) {
data[ key ] = value;
});

View File

@ -41,16 +41,16 @@ jQuery( function( $ ) {
this.$checkout_form.on( 'update', this.trigger_update_checkout );
// Inputs/selects which update totals
this.$checkout_form.on( 'change', 'select.shipping_method, input[name^="shipping_method"], #ship-to-different-address input, .update_totals_on_change select, .update_totals_on_change input[type="radio"], .update_totals_on_change input[type="checkbox"]', this.trigger_update_checkout );
this.$checkout_form.on( 'change', 'select.shipping_method, input[name^="shipping_method"], #ship-to-different-address input, .update_totals_on_change select, .update_totals_on_change input[type="radio"], .update_totals_on_change input[type="checkbox"]', this.trigger_update_checkout ); // eslint-disable-line max-len
this.$checkout_form.on( 'change', '.address-field select', this.input_changed );
this.$checkout_form.on( 'change', '.address-field input.input-text, .update_totals_on_change input.input-text', this.maybe_input_changed );
this.$checkout_form.on( 'keydown', '.address-field input.input-text, .update_totals_on_change input.input-text', this.queue_update_checkout );
this.$checkout_form.on( 'change', '.address-field input.input-text, .update_totals_on_change input.input-text', this.maybe_input_changed ); // eslint-disable-line max-len
this.$checkout_form.on( 'keydown', '.address-field input.input-text, .update_totals_on_change input.input-text', this.queue_update_checkout ); // eslint-disable-line max-len
// Address fields
this.$checkout_form.on( 'change', '#ship-to-different-address input', this.ship_to_different_address );
// Trigger events
this.$checkout_form.find( '#ship-to-different-address input' ).change();
this.init_ship_to_different_address();
this.init_payment_methods();
// Update on page load
@ -135,7 +135,10 @@ jQuery( function( $ ) {
}
},
init_checkout: function() {
$( document.body ).trigger( 'update_checkout' );
// Fire updated_checkout event after existing ready event handlers.
$( function() {
$( document.body ).trigger( 'updated_checkout' );
} );
},
maybe_input_changed: function( e ) {
if ( wc_checkout_form.dirtyInput ) {
@ -180,10 +183,31 @@ jQuery( function( $ ) {
wc_checkout_form.trigger_update_checkout();
}
},
init_ship_to_different_address: function() {
var $checkbox = $( '#ship-to-different-address input' );
if ( ! $checkbox.prop( 'checked' ) ) {
var $billing = $( 'div.woocommerce-billing-fields' );
// Find shipping field values that diverge from billing.
var $differentFields = $( 'div.shipping_address' ).find( 'input, select' ).filter( function() {
$( this ).attr( 'id' ).replace( 'shipping', 'billing' );
var id = $( this ).attr( 'id' ).replace( 'shipping', 'billing' );
return $( this ).val() !== $billing.find( '#' + id ).val();
} );
if ( $differentFields.length > 0 ) {
$checkbox.prop( 'checked', true );
}
}
$( 'div.shipping_address' ).toggle( $checkbox.prop( 'checked' ) );
},
ship_to_different_address: function() {
$( 'div.shipping_address' ).hide();
if ( $( this ).is( ':checked' ) ) {
$( 'div.shipping_address' ).slideDown();
} else {
$( 'div.shipping_address' ).slideUp();
}
},
reset_update_checkout_timer: function() {
@ -207,7 +231,7 @@ jQuery( function( $ ) {
event_type = e.type;
if ( 'input' === event_type ) {
$parent.removeClass( 'woocommerce-invalid woocommerce-invalid-required-field woocommerce-invalid-email woocommerce-validated' );
$parent.removeClass( 'woocommerce-invalid woocommerce-invalid-required-field woocommerce-invalid-email woocommerce-validated' ); // eslint-disable-line max-len
}
if ( 'validate' === event_type || 'change' === event_type ) {
@ -225,7 +249,7 @@ jQuery( function( $ ) {
if ( validate_email ) {
if ( $this.val() ) {
/* https://stackoverflow.com/questions/2855865/jquery-validate-e-mail-address-regex */
var pattern = new RegExp(/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i);
var pattern = new RegExp(/^([a-z\d!#$%&'*+\-\/=?^_`{|}~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+(\.[a-z\d!#$%&'*+\-\/=?^_`{|}~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+)*|"((([ \t]*\r\n)?[ \t]+)?([\x01-\x08\x0b\x0c\x0e-\x1f\x7f\x21\x23-\x5b\x5d-\x7e\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|\\[\x01-\x09\x0b\x0c\x0d-\x7f\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))*(([ \t]*\r\n)?[ \t]+)?")@(([a-z\d\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|[a-z\d\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF][a-z\d\-._~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]*[a-z\d\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])\.)+([a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|[a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF][a-z\d\-._~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]*[0-9a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])\.?$/i); // eslint-disable-line max-len
if ( ! pattern.test( $this.val() ) ) {
$parent.removeClass( 'woocommerce-validated' ).addClass( 'woocommerce-invalid woocommerce-invalid-email' );
@ -235,7 +259,7 @@ jQuery( function( $ ) {
}
if ( validated ) {
$parent.removeClass( 'woocommerce-invalid woocommerce-invalid-required-field woocommerce-invalid-email' ).addClass( 'woocommerce-validated' );
$parent.removeClass( 'woocommerce-invalid woocommerce-invalid-required-field woocommerce-invalid-email' ).addClass( 'woocommerce-validated' ); // eslint-disable-line max-len
}
}
},
@ -311,6 +335,7 @@ jQuery( function( $ ) {
if ( false !== args.update_shipping_method ) {
var shipping_methods = {};
// eslint-disable-next-line max-len
$( 'select.shipping_method, input[name^="shipping_method"][type="radio"]:checked, input[name^="shipping_method"][type="hidden"]' ).each( function() {
shipping_methods[ $( this ).data( 'index' ) ] = $( this ).val();
} );
@ -399,7 +424,7 @@ jQuery( function( $ ) {
// Add new errors returned by this event
if ( data.messages ) {
$form.prepend( '<div class="woocommerce-NoticeGroup woocommerce-NoticeGroup-updateOrderReview">' + data.messages + '</div>' );
$form.prepend( '<div class="woocommerce-NoticeGroup woocommerce-NoticeGroup-updateOrderReview">' + data.messages + '</div>' ); // eslint-disable-line max-len
} else {
$form.prepend( data );
}
@ -419,6 +444,26 @@ jQuery( function( $ ) {
});
},
handleUnloadEvent: function( e ) {
// Modern browsers have their own standard generic messages that they will display.
// Confirm, alert, prompt or custom message are not allowed during the unload event
// Browsers will display their own standard messages
// Check if the browser is Internet Explorer
if((navigator.userAgent.indexOf('MSIE') !== -1 ) || (!!document.documentMode)) {
// IE handles unload events differently than modern browsers
e.preventDefault();
return undefined;
}
return true;
},
attachUnloadEventsOnSubmit: function() {
$( window ).on('beforeunload', this.handleUnloadEvent);
},
detachUnloadEventsOnSubmit: function() {
$( window ).unbind('beforeunload', this.handleUnloadEvent);
},
blockOnSubmit: function( $form ) {
var form_data = $form.data();
@ -444,12 +489,16 @@ jQuery( function( $ ) {
}
// Trigger a handler to let gateways manipulate the checkout if needed
// eslint-disable-next-line max-len
if ( $form.triggerHandler( 'checkout_place_order' ) !== false && $form.triggerHandler( 'checkout_place_order_' + wc_checkout_form.get_payment_method() ) !== false ) {
$form.addClass( 'processing' );
wc_checkout_form.blockOnSubmit( $form );
// Attach event to block reloading the page when the form has been submitted
wc_checkout_form.attachUnloadEventsOnSubmit();
// ajaxSetup is global, but we use it to ensure JSON is valid once returned.
$.ajaxSetup( {
dataFilter: function( raw_response, dataType ) {
@ -485,6 +534,9 @@ jQuery( function( $ ) {
data: $form.serialize(),
dataType: 'json',
success: function( result ) {
// Detach the unload handler that prevents a reload / redirect
wc_checkout_form.detachUnloadEventsOnSubmit();
try {
if ( 'success' === result.result ) {
if ( -1 === result.redirect.indexOf( 'https://' ) || -1 === result.redirect.indexOf( 'http://' ) ) {
@ -513,11 +565,14 @@ jQuery( function( $ ) {
if ( result.messages ) {
wc_checkout_form.submit_error( result.messages );
} else {
wc_checkout_form.submit_error( '<div class="woocommerce-error">' + wc_checkout_params.i18n_checkout_error + '</div>' );
wc_checkout_form.submit_error( '<div class="woocommerce-error">' + wc_checkout_params.i18n_checkout_error + '</div>' ); // eslint-disable-line max-len
}
}
},
error: function( jqXHR, textStatus, errorThrown ) {
// Detach the unload handler that prevents a reload / redirect
wc_checkout_form.detachUnloadEventsOnSubmit();
wc_checkout_form.submit_error( '<div class="woocommerce-error">' + errorThrown + '</div>' );
}
});
@ -527,7 +582,7 @@ jQuery( function( $ ) {
},
submit_error: function( error_message ) {
$( '.woocommerce-NoticeGroup-checkout, .woocommerce-error, .woocommerce-message' ).remove();
wc_checkout_form.$checkout_form.prepend( '<div class="woocommerce-NoticeGroup woocommerce-NoticeGroup-checkout">' + error_message + '</div>' );
wc_checkout_form.$checkout_form.prepend( '<div class="woocommerce-NoticeGroup woocommerce-NoticeGroup-checkout">' + error_message + '</div>' ); // eslint-disable-line max-len
wc_checkout_form.$checkout_form.removeClass( 'processing' ).unblock();
wc_checkout_form.$checkout_form.find( '.input-text, select, input:checkbox' ).trigger( 'validate' ).blur();
wc_checkout_form.scroll_to_notices();

View File

@ -78,4 +78,19 @@ jQuery( function( $ ) {
}, 1000 );
}
};
// Show password visiblity hover icon on woocommerce forms
$( '.woocommerce form input[type="password"]' ).wrap( '<span class="password-input"></span>' );
$( '.password-input' ).append( '<span class="show-password-input"></span>' );
$( '.show-password-input' ).click(
function() {
$( this ).toggleClass( 'display-password' );
if ( $( this ).hasClass( 'display-password' ) ) {
$( this ).siblings( ['input[name="password"]', 'input[type="password"]'] ).prop( 'type', 'text' );
} else {
$( this ).siblings( 'input[name="password"]' ).prop( 'type', 'password' );
}
}
);
});

12
babel.config.js Normal file
View File

@ -0,0 +1,12 @@
module.exports = {
presets: [
[
'@babel/preset-env',
{
targets: {
node: 'current',
},
},
],
],
};

View File

@ -10,11 +10,11 @@
"automattic/jetpack-autoloader": "^1.2.0",
"php": ">=5.6|>=7.0",
"composer/installers": "1.7.0",
"woocommerce/woocommerce-blocks": "2.4.5",
"woocommerce/woocommerce-rest-api": "1.0.3"
"woocommerce/woocommerce-blocks": "2.5.6",
"woocommerce/woocommerce-rest-api": "1.0.5"
},
"require-dev": {
"phpunit/phpunit": "7.5.17",
"phpunit/phpunit": "7.5.18",
"woocommerce/woocommerce-sniffs": "0.0.9"
},
"config": {

136
composer.lock generated
View File

@ -4,20 +4,20 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "a5cb448a1d94f10a40207b6f0dfa1c50",
"content-hash": "42581c121025650285270f2ca34a5859",
"packages": [
{
"name": "automattic/jetpack-autoloader",
"version": "v1.2.0",
"version": "v1.3.2",
"source": {
"type": "git",
"url": "https://github.com/Automattic/jetpack-autoloader.git",
"reference": "4ad9631e68e9da8b8a764615766287becfb27f81"
"reference": "301c2fbcf070d4f0147753447616b6e982bda09e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Automattic/jetpack-autoloader/zipball/4ad9631e68e9da8b8a764615766287becfb27f81",
"reference": "4ad9631e68e9da8b8a764615766287becfb27f81",
"url": "https://api.github.com/repos/Automattic/jetpack-autoloader/zipball/301c2fbcf070d4f0147753447616b6e982bda09e",
"reference": "301c2fbcf070d4f0147753447616b6e982bda09e",
"shasum": ""
},
"require": {
@ -40,7 +40,7 @@
"GPL-2.0-or-later"
],
"description": "Creates a custom autoloader for a plugin or theme.",
"time": "2019-06-24T15:13:23+00:00"
"time": "2019-09-24T06:39:29+00:00"
},
{
"name": "composer/installers",
@ -166,25 +166,25 @@
},
{
"name": "woocommerce/woocommerce-blocks",
"version": "v2.4.5",
"version": "v2.5.6",
"source": {
"type": "git",
"url": "https://github.com/woocommerce/woocommerce-gutenberg-products-block.git",
"reference": "130bc40824f844c0870c94c0ad0aa7a6abb74f6f"
"reference": "fbf9d119c98a6fa2eead81536a7fa81c7ee4ac97"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/woocommerce/woocommerce-gutenberg-products-block/zipball/130bc40824f844c0870c94c0ad0aa7a6abb74f6f",
"reference": "130bc40824f844c0870c94c0ad0aa7a6abb74f6f",
"url": "https://api.github.com/repos/woocommerce/woocommerce-gutenberg-products-block/zipball/fbf9d119c98a6fa2eead81536a7fa81c7ee4ac97",
"reference": "fbf9d119c98a6fa2eead81536a7fa81c7ee4ac97",
"shasum": ""
},
"require": {
"automattic/jetpack-autoloader": "1.2.0",
"automattic/jetpack-autoloader": "1.3.2",
"composer/installers": "1.7.0"
},
"require-dev": {
"phpunit/phpunit": "6.5.14",
"woocommerce/woocommerce-sniffs": "0.0.6"
"woocommerce/woocommerce-sniffs": "0.0.7"
},
"type": "wordpress-plugin",
"extra": {
@ -209,28 +209,28 @@
"gutenberg",
"woocommerce"
],
"time": "2019-11-02T13:48:18+00:00"
"time": "2019-12-17T19:22:09+00:00"
},
{
"name": "woocommerce/woocommerce-rest-api",
"version": "1.0.3",
"version": "1.0.5",
"source": {
"type": "git",
"url": "https://github.com/woocommerce/woocommerce-rest-api.git",
"reference": "7d9babf1c25890c32df3edb28b8351732640f5ce"
"reference": "3be425631faefa61ab8b81011ae8a422b9bfca35"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/woocommerce/woocommerce-rest-api/zipball/7d9babf1c25890c32df3edb28b8351732640f5ce",
"reference": "7d9babf1c25890c32df3edb28b8351732640f5ce",
"url": "https://api.github.com/repos/woocommerce/woocommerce-rest-api/zipball/3be425631faefa61ab8b81011ae8a422b9bfca35",
"reference": "3be425631faefa61ab8b81011ae8a422b9bfca35",
"shasum": ""
},
"require": {
"automattic/jetpack-autoloader": "1.2.0"
"automattic/jetpack-autoloader": "^1.2.0"
},
"require-dev": {
"phpunit/phpunit": "6.5.14",
"woocommerce/woocommerce-sniffs": "0.0.6"
"woocommerce/woocommerce-sniffs": "0.0.9"
},
"type": "wordpress-plugin",
"autoload": {
@ -249,7 +249,7 @@
],
"description": "The WooCommerce core REST API.",
"homepage": "https://github.com/woocommerce/woocommerce-rest-api",
"time": "2019-07-16T14:27:40+00:00"
"time": "2019-12-18T22:20:59+00:00"
}
],
"packages-dev": [
@ -321,16 +321,16 @@
},
{
"name": "doctrine/instantiator",
"version": "1.2.0",
"version": "1.3.0",
"source": {
"type": "git",
"url": "https://github.com/doctrine/instantiator.git",
"reference": "a2c590166b2133a4633738648b6b064edae0814a"
"reference": "ae466f726242e637cebdd526a7d991b9433bacf1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/instantiator/zipball/a2c590166b2133a4633738648b6b064edae0814a",
"reference": "a2c590166b2133a4633738648b6b064edae0814a",
"url": "https://api.github.com/repos/doctrine/instantiator/zipball/ae466f726242e637cebdd526a7d991b9433bacf1",
"reference": "ae466f726242e637cebdd526a7d991b9433bacf1",
"shasum": ""
},
"require": {
@ -373,20 +373,20 @@
"constructor",
"instantiate"
],
"time": "2019-03-17T17:37:11+00:00"
"time": "2019-10-21T16:45:58+00:00"
},
{
"name": "myclabs/deep-copy",
"version": "1.9.3",
"version": "1.9.4",
"source": {
"type": "git",
"url": "https://github.com/myclabs/DeepCopy.git",
"reference": "007c053ae6f31bba39dfa19a7726f56e9763bbea"
"reference": "579bb7356d91f9456ccd505f24ca8b667966a0a7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/007c053ae6f31bba39dfa19a7726f56e9763bbea",
"reference": "007c053ae6f31bba39dfa19a7726f56e9763bbea",
"url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/579bb7356d91f9456ccd505f24ca8b667966a0a7",
"reference": "579bb7356d91f9456ccd505f24ca8b667966a0a7",
"shasum": ""
},
"require": {
@ -421,7 +421,7 @@
"object",
"object graph"
],
"time": "2019-08-09T12:45:53+00:00"
"time": "2019-12-15T19:12:40+00:00"
},
{
"name": "phar-io/manifest",
@ -837,33 +837,33 @@
},
{
"name": "phpspec/prophecy",
"version": "1.9.0",
"version": "1.10.0",
"source": {
"type": "git",
"url": "https://github.com/phpspec/prophecy.git",
"reference": "f6811d96d97bdf400077a0cc100ae56aa32b9203"
"reference": "d638ebbb58daba25a6a0dc7969e1358a0e3c6682"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpspec/prophecy/zipball/f6811d96d97bdf400077a0cc100ae56aa32b9203",
"reference": "f6811d96d97bdf400077a0cc100ae56aa32b9203",
"url": "https://api.github.com/repos/phpspec/prophecy/zipball/d638ebbb58daba25a6a0dc7969e1358a0e3c6682",
"reference": "d638ebbb58daba25a6a0dc7969e1358a0e3c6682",
"shasum": ""
},
"require": {
"doctrine/instantiator": "^1.0.2",
"php": "^5.3|^7.0",
"phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0|^5.0",
"sebastian/comparator": "^1.1|^2.0|^3.0",
"sebastian/comparator": "^1.2.3|^2.0|^3.0",
"sebastian/recursion-context": "^1.0|^2.0|^3.0"
},
"require-dev": {
"phpspec/phpspec": "^2.5|^3.2",
"phpspec/phpspec": "^2.5 || ^3.2",
"phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.8.x-dev"
"dev-master": "1.10.x-dev"
}
},
"autoload": {
@ -896,7 +896,7 @@
"spy",
"stub"
],
"time": "2019-10-03T11:07:50+00:00"
"time": "2019-12-17T16:54:23+00:00"
},
{
"name": "phpunit/php-code-coverage",
@ -1152,16 +1152,16 @@
},
{
"name": "phpunit/phpunit",
"version": "7.5.17",
"version": "7.5.18",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "4c92a15296e58191a4cd74cff3b34fc8e374174a"
"reference": "fcf6c4bfafaadc07785528b06385cce88935474d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/4c92a15296e58191a4cd74cff3b34fc8e374174a",
"reference": "4c92a15296e58191a4cd74cff3b34fc8e374174a",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/fcf6c4bfafaadc07785528b06385cce88935474d",
"reference": "fcf6c4bfafaadc07785528b06385cce88935474d",
"shasum": ""
},
"require": {
@ -1232,7 +1232,7 @@
"testing",
"xunit"
],
"time": "2019-10-28T10:37:36+00:00"
"time": "2019-12-06T05:14:37+00:00"
},
{
"name": "sebastian/code-unit-reverse-lookup",
@ -1401,16 +1401,16 @@
},
{
"name": "sebastian/environment",
"version": "4.2.2",
"version": "4.2.3",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/environment.git",
"reference": "f2a2c8e1c97c11ace607a7a667d73d47c19fe404"
"reference": "464c90d7bdf5ad4e8a6aea15c091fec0603d4368"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/f2a2c8e1c97c11ace607a7a667d73d47c19fe404",
"reference": "f2a2c8e1c97c11ace607a7a667d73d47c19fe404",
"url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/464c90d7bdf5ad4e8a6aea15c091fec0603d4368",
"reference": "464c90d7bdf5ad4e8a6aea15c091fec0603d4368",
"shasum": ""
},
"require": {
@ -1450,7 +1450,7 @@
"environment",
"hhvm"
],
"time": "2019-05-05T09:05:15+00:00"
"time": "2019-11-20T08:46:58+00:00"
},
{
"name": "sebastian/exporter",
@ -1802,16 +1802,16 @@
},
{
"name": "squizlabs/php_codesniffer",
"version": "3.5.2",
"version": "3.5.3",
"source": {
"type": "git",
"url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
"reference": "65b12cdeaaa6cd276d4c3033a95b9b88b12701e7"
"reference": "557a1fc7ac702c66b0bbfe16ab3d55839ef724cb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/65b12cdeaaa6cd276d4c3033a95b9b88b12701e7",
"reference": "65b12cdeaaa6cd276d4c3033a95b9b88b12701e7",
"url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/557a1fc7ac702c66b0bbfe16ab3d55839ef724cb",
"reference": "557a1fc7ac702c66b0bbfe16ab3d55839ef724cb",
"shasum": ""
},
"require": {
@ -1849,20 +1849,20 @@
"phpcs",
"standards"
],
"time": "2019-10-28T04:36:32+00:00"
"time": "2019-12-04T04:46:47+00:00"
},
{
"name": "symfony/polyfill-ctype",
"version": "v1.12.0",
"version": "v1.13.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
"reference": "550ebaac289296ce228a706d0867afc34687e3f4"
"reference": "f8f0b461be3385e56d6de3dbb5a0df24c0c275e3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/550ebaac289296ce228a706d0867afc34687e3f4",
"reference": "550ebaac289296ce228a706d0867afc34687e3f4",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/f8f0b461be3385e56d6de3dbb5a0df24c0c275e3",
"reference": "f8f0b461be3385e56d6de3dbb5a0df24c0c275e3",
"shasum": ""
},
"require": {
@ -1874,7 +1874,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.12-dev"
"dev-master": "1.13-dev"
}
},
"autoload": {
@ -1907,7 +1907,7 @@
"polyfill",
"portable"
],
"time": "2019-08-06T08:03:45+00:00"
"time": "2019-11-27T13:56:44+00:00"
},
{
"name": "theseer/tokenizer",
@ -1951,31 +1951,29 @@
},
{
"name": "webmozart/assert",
"version": "1.5.0",
"version": "1.6.0",
"source": {
"type": "git",
"url": "https://github.com/webmozart/assert.git",
"reference": "88e6d84706d09a236046d686bbea96f07b3a34f4"
"reference": "573381c0a64f155a0d9a23f4b0c797194805b925"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/webmozart/assert/zipball/88e6d84706d09a236046d686bbea96f07b3a34f4",
"reference": "88e6d84706d09a236046d686bbea96f07b3a34f4",
"url": "https://api.github.com/repos/webmozart/assert/zipball/573381c0a64f155a0d9a23f4b0c797194805b925",
"reference": "573381c0a64f155a0d9a23f4b0c797194805b925",
"shasum": ""
},
"require": {
"php": "^5.3.3 || ^7.0",
"symfony/polyfill-ctype": "^1.8"
},
"conflict": {
"vimeo/psalm": "<3.6.0"
},
"require-dev": {
"phpunit/phpunit": "^4.8.36 || ^7.5.13"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.3-dev"
}
},
"autoload": {
"psr-4": {
"Webmozart\\Assert\\": "src/"
@ -1997,7 +1995,7 @@
"check",
"validate"
],
"time": "2019-08-24T08:43:50+00:00"
"time": "2019-11-24T13:36:37+00:00"
},
{
"name": "woocommerce/woocommerce-sniffs",

55
docker-compose.yaml Normal file
View File

@ -0,0 +1,55 @@
version: '3.7'
services:
db:
image: mariadb:10.4
restart: on-failure
environment:
MYSQL_DATABASE: testdb
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress
MYSQL_RANDOM_ROOT_PASSWORD: 'yes'
volumes:
- db:/var/lib/mysql
wordpress-woocomerce-dev:
depends_on:
- db
build:
context: .
dockerfile: Dockerfile
ports:
- 8084:80
restart: on-failure
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_NAME: testdb
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: wordpress
WORDPRESS_TABLE_PREFIX: "wp_"
WORDPRESS_DEBUG: 1
volumes:
- wordpress:/var/www/html
wordpress-cli:
depends_on:
- db
- wordpress-woocomerce-dev
image: wordpress:cli
restart: on-failure
user: xfs
command: >
/bin/sh -c '
wp core install --url=http://localhost:8084 --title="WooCommerce Core E2E Test Suite" --admin_user=admin --admin_password=password --admin_email=admin@woocommercecoree2etestsuite.com --path=/var/www/html --skip-email;
wp plugin activate woocommerce;
wp theme install twentynineteen --activate;
wp user create customer customer@woocommercecoree2etestsuite.com --user_pass=password --role=customer --path=/var/www/html;
wp post create --post_type=page --post_status=publish --post_title='Ready' --post_content='E2E-tests.';
'
volumes:
- wordpress:/var/www/html
volumes:
db:
wordpress:

View File

@ -698,6 +698,26 @@ return array(
),
'KR' => array(),
'KW' => array(),
'LA' => array(
'AT' => __( 'Attapeu', 'woocommerce' ),
'BK' => __( 'Bokeo', 'woocommerce' ),
'BL' => __( 'Bolikhamsai', 'woocommerce' ),
'CH' => __( 'Champasak', 'woocommerce' ),
'HO' => __( 'Houaphanh', 'woocommerce' ),
'KH' => __( 'Khammouane', 'woocommerce' ),
'LM' => __( 'Luang Namtha', 'woocommerce' ),
'LP' => __( 'Luang Prabang', 'woocommerce' ),
'OU' => __( 'Oudomxay', 'woocommerce' ),
'PH' => __( 'Phongsaly', 'woocommerce' ),
'SL' => __( 'Salavan', 'woocommerce' ),
'SV' => __( 'Savannakhet', 'woocommerce' ),
'VI' => __( 'Vientiane Province', 'woocommerce' ),
'VT' => __( 'Vientiane', 'woocommerce' ),
'XA' => __( 'Sainyabuli', 'woocommerce' ),
'XE' => __( 'Sekong', 'woocommerce' ),
'XI' => __( 'Xiangkhouang', 'woocommerce' ),
'XS' => __( 'Xaisomboun', 'woocommerce' ),
),
'LB' => array(),
'LR' => array( // Liberia provinces.
'BM' => __( 'Bomi', 'woocommerce' ),

View File

@ -18,6 +18,7 @@ require_once WC_ABSPATH . 'includes/legacy/abstract-wc-legacy-order.php';
* WC_Abstract_Order class.
*/
abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order {
use WC_Item_Totals;
/**
* Order Data array. This is the core order data exposed in APIs since 3.0.0.
@ -769,6 +770,23 @@ abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order {
return apply_filters( 'woocommerce_order_get_items', $items, $this, $types );
}
/**
* Return array of values for calculations.
*
* @param string $field Field name to return.
*
* @return array Array of values.
*/
protected function get_values_for_total( $field ) {
$items = array_map(
function ( $item ) use ( $field ) {
return wc_add_number_precision( $item[ $field ], false );
},
array_values( $this->get_items() )
);
return $items;
}
/**
* Return an array of coupons within this order.
*
@ -1498,6 +1516,34 @@ abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order {
$this->save();
}
/**
* Helper function.
* If you add all items in this order in cart again, this would be the cart subtotal (assuming all other settings are same).
*
* @return float Cart subtotal.
*/
protected function get_cart_subtotal_for_order() {
return wc_remove_number_precision(
$this->get_rounded_items_total(
$this->get_values_for_total( 'subtotal' )
)
);
}
/**
* Helper function.
* If you add all items in this order in cart again, this would be the cart total (assuming all other settings are same).
*
* @return float Cart total.
*/
protected function get_cart_total_for_order() {
return wc_remove_number_precision(
$this->get_rounded_items_total(
$this->get_values_for_total( 'total' )
)
);
}
/**
* Calculate totals by looking at the contents of the order. Stores the totals and returns the orders final total.
*
@ -1508,18 +1554,13 @@ abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order {
public function calculate_totals( $and_taxes = true ) {
do_action( 'woocommerce_order_before_calculate_totals', $and_taxes, $this );
$cart_subtotal = 0;
$cart_total = 0;
$fees_total = 0;
$fees_total = 0;
$shipping_total = 0;
$cart_subtotal_tax = 0;
$cart_total_tax = 0;
// Sum line item costs.
foreach ( $this->get_items() as $item ) {
$cart_subtotal += round( $item->get_subtotal(), wc_get_price_decimals() );
$cart_total += round( $item->get_total(), wc_get_price_decimals() );
}
$cart_subtotal = $this->get_cart_subtotal_for_order();
$cart_total = $this->get_cart_total_for_order();
// Sum shipping costs.
foreach ( $this->get_shipping_methods() as $shipping ) {
@ -1740,15 +1781,16 @@ abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order {
*/
public function get_subtotal_to_display( $compound = false, $tax_display = '' ) {
$tax_display = $tax_display ? $tax_display : get_option( 'woocommerce_tax_display_cart' );
$subtotal = 0;
$subtotal = $this->get_cart_subtotal_for_order();
if ( ! $compound ) {
foreach ( $this->get_items() as $item ) {
$subtotal += $item->get_subtotal();
if ( 'incl' === $tax_display ) {
$subtotal += $item->get_subtotal_tax();
if ( 'incl' === $tax_display ) {
$subtotal_taxes = 0;
foreach ( $this->get_items() as $item ) {
$subtotal_taxes += self::round_line_tax( $item->get_subtotal_tax(), false );
}
$subtotal += wc_round_tax_total( $subtotal_taxes );
}
$subtotal = wc_price( $subtotal, array( 'currency' => $this->get_currency() ) );
@ -1761,10 +1803,6 @@ abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order {
return '';
}
foreach ( $this->get_items() as $item ) {
$subtotal += $item->get_subtotal();
}
// Add Shipping Costs.
$subtotal += $this->get_shipping_total();

View File

@ -131,6 +131,13 @@ abstract class WC_Payment_Gateway extends WC_Settings_API {
*/
public $new_method_label = '';
/**
* Pay button ID if supported.
*
* @var string
*/
public $pay_button_id = '';
/**
* Contains a users saved tokens for this gateway.
*
@ -317,6 +324,16 @@ abstract class WC_Payment_Gateway extends WC_Settings_API {
return apply_filters( 'woocommerce_gateway_icon', $icon, $this->id );
}
/**
* Return the gateway's pay button ID.
*
* @since 3.9.0
* @return string
*/
public function get_pay_button_id() {
return sanitize_html_class( $this->pay_button_id );
}
/**
* Set as current gateway.
*
@ -439,7 +456,9 @@ abstract class WC_Payment_Gateway extends WC_Settings_API {
);
wp_localize_script(
'woocommerce-tokenization-form', 'wc_tokenization_form_params', array(
'woocommerce-tokenization-form',
'wc_tokenization_form_params',
array(
'is_registration_required' => WC()->checkout()->is_registration_required(),
'is_logged_in' => is_user_logged_in(),
)
@ -521,7 +540,7 @@ abstract class WC_Payment_Gateway extends WC_Settings_API {
esc_html__( 'Save to account', 'woocommerce' )
);
echo apply_filters( 'woocommerce_payment_gateway_save_new_payment_method_option_html', $html, $this );
echo apply_filters( 'woocommerce_payment_gateway_save_new_payment_method_option_html', $html, $this ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
/**

View File

@ -1859,7 +1859,7 @@ class WC_Product extends WC_Abstract_Legacy_Product {
}
if ( ! $image && $placeholder ) {
$image = wc_placeholder_img( $size );
$image = wc_placeholder_img( $size, $attr );
}
return apply_filters( 'woocommerce_product_get_image', $image, $this, $size, $attr, $placeholder, $image );

View File

@ -78,6 +78,11 @@ abstract class WC_Widget extends WP_Widget {
* @return bool true if the widget is cached otherwise false
*/
public function get_cached_widget( $args ) {
// Don't get cache if widget_id doesn't exists.
if ( empty( $args['widget_id'] ) ) {
return false;
}
$cache = wp_cache_get( $this->get_widget_id_for_cache( $this->widget_id ), 'widget' );
if ( ! is_array( $cache ) ) {
@ -100,6 +105,11 @@ abstract class WC_Widget extends WP_Widget {
* @return string the content that was cached
*/
public function cache_widget( $args, $content ) {
// Don't set any cache if widget_id doesn't exist.
if ( empty( $args['widget_id'] ) ) {
return $content;
}
$cache = wp_cache_get( $this->get_widget_id_for_cache( $this->widget_id ), 'widget' );
if ( ! is_array( $cache ) ) {

View File

@ -488,7 +488,7 @@ class WC_Admin_Addons {
$back_admin_path = add_query_arg( array() );
return array(
'wccom-site' => site_url(),
'wccom-back' => esc_url( $back_admin_path ),
'wccom-back' => rawurlencode( $back_admin_path ),
'wccom-woo-version' => WC_VERSION,
'wccom-connect-nonce' => wp_create_nonce( 'connect' ),
);

View File

@ -169,9 +169,9 @@ if ( ! class_exists( 'WC_Admin_Assets', false ) ) :
$params = array(
/* translators: %s: decimal */
'i18n_decimal_error' => sprintf( __( 'Please enter in decimal (%s) format without thousand separators.', 'woocommerce' ), $decimal ),
'i18n_decimal_error' => sprintf( __( 'Please enter with one decimal point (%s) without thousand separators.', 'woocommerce' ), $decimal ),
/* translators: %s: price decimal separator */
'i18n_mon_decimal_error' => sprintf( __( 'Please enter in monetary decimal (%s) format without thousand separators and currency symbols.', 'woocommerce' ), wc_get_price_decimal_separator() ),
'i18n_mon_decimal_error' => sprintf( __( 'Please enter with one monetary decimal point (%s) without thousand separators and currency symbols.', 'woocommerce' ), wc_get_price_decimal_separator() ),
'i18n_country_iso_error' => __( 'Please enter in country code with two capital letters.', 'woocommerce' ),
'i18n_sale_less_than_regular_error' => __( 'Please enter in a value less than the regular price.', 'woocommerce' ),
'i18n_delete_product_notice' => __( 'This product has produced sales and may be linked to existing orders. Are you sure you want to delete it?', 'woocommerce' ),

View File

@ -1,17 +1,15 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Duplicate product functionality
*
* @author WooCommerce
* @category Admin
* @package WooCommerce/Admin
* @version 3.0.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( class_exists( 'WC_Admin_Duplicate_Product', false ) ) {
return new WC_Admin_Duplicate_Product();
}
@ -87,12 +85,10 @@ class WC_Admin_Duplicate_Product {
return;
}
if ( isset( $_GET['post'] ) ) {
$notify_url = wp_nonce_url( admin_url( 'edit.php?post_type=product&action=duplicate_product&post=' . absint( $_GET['post'] ) ), 'woocommerce-duplicate-product_' . $_GET['post'] );
?>
<div id="duplicate-action"><a class="submitduplicate duplication" href="<?php echo esc_url( $notify_url ); ?>"><?php esc_html_e( 'Copy to a new draft', 'woocommerce' ); ?></a></div>
<?php
}
$notify_url = wp_nonce_url( admin_url( 'edit.php?post_type=product&action=duplicate_product&post=' . absint( $post->ID ) ), 'woocommerce-duplicate-product_' . $post->ID );
?>
<div id="duplicate-action"><a class="submitduplicate duplication" href="<?php echo esc_url( $notify_url ); ?>"><?php esc_html_e( 'Copy to a new draft', 'woocommerce' ); ?></a></div>
<?php
}
/**
@ -111,7 +107,7 @@ class WC_Admin_Duplicate_Product {
if ( false === $product ) {
/* translators: %s: product id */
wp_die( sprintf( esc_html__( 'Product creation failed, could not find original product: %s', 'woocommerce' ), $product_id ) );
wp_die( sprintf( esc_html__( 'Product creation failed, could not find original product: %s', 'woocommerce' ), esc_html( $product_id ) ) );
}
$duplicate = $this->product_duplicate( $product );
@ -120,7 +116,7 @@ class WC_Admin_Duplicate_Product {
do_action( 'woocommerce_product_duplicate', $duplicate, $product );
wc_do_deprecated_action( 'woocommerce_duplicate_product', array( $duplicate->get_id(), $this->get_product_to_duplicate( $product_id ) ), '3.0', 'Use woocommerce_product_duplicate action instead.' );
// Redirect to the edit screen for the new draft page
// Redirect to the edit screen for the new draft page.
wp_redirect( admin_url( 'post.php?action=edit&post=' . $duplicate->get_id() ) );
exit;
}
@ -128,15 +124,20 @@ class WC_Admin_Duplicate_Product {
/**
* Function to create the duplicate of the product.
*
* @param WC_Product $product
* @return WC_Product
* @param WC_Product $product The product to duplicate.
* @return WC_Product The duplicate.
*/
public function product_duplicate( $product ) {
// Filter to allow us to unset/remove data we don't want to copy to the duplicate. @since 2.6
/**
* Filter to allow us to unset/remove data we don't want to copy to the duplicate.
*
* @since 2.6
*/
$meta_to_exclude = array_filter( apply_filters( 'woocommerce_duplicate_product_exclude_meta', array() ) );
$duplicate = clone $product;
$duplicate->set_id( 0 );
/* translators: %s contains the name of the original product. */
$duplicate->set_name( sprintf( esc_html__( '%s (Copy)', 'woocommerce' ), $duplicate->get_name() ) );
$duplicate->set_total_sales( 0 );
if ( '' !== $product->get_sku( 'edit' ) ) {
@ -153,7 +154,11 @@ class WC_Admin_Duplicate_Product {
$duplicate->delete_meta_data( $meta_key );
}
// This action can be used to modify the object further before it is created - it will be passed by reference. @since 3.0
/**
* This action can be used to modify the object further before it is created - it will be passed by reference.
*
* @since 3.0
*/
do_action( 'woocommerce_product_duplicate_before_save', $duplicate, $product );
// Save parent product.
@ -168,6 +173,12 @@ class WC_Admin_Duplicate_Product {
$child_duplicate->set_id( 0 );
$child_duplicate->set_date_created( null );
// If we wait and let the insertion generate the slug, we will see extreme performance degradation
// in the case where a product is used as a template. Every time the template is duplicated, each
// variation will query every consecutive slug until it finds an empty one. To avoid this, we can
// optimize the generation ourselves, avoiding the issue altogether.
$this->generate_unique_slug( $child_duplicate );
if ( '' !== $child->get_sku( 'edit' ) ) {
$child_duplicate->set_sku( wc_product_generate_unique_sku( 0, $child->get_sku( 'edit' ) ) );
}
@ -176,7 +187,11 @@ class WC_Admin_Duplicate_Product {
$child_duplicate->delete_meta_data( $meta_key );
}
// This action can be used to modify the object further before it is created - it will be passed by reference. @since 3.0
/**
* This action can be used to modify the object further before it is created - it will be passed by reference.
*
* @since 3.0
*/
do_action( 'woocommerce_product_duplicate_before_save', $child_duplicate, $child );
$child_duplicate->save();
@ -193,7 +208,7 @@ class WC_Admin_Duplicate_Product {
* Get a product from the database to duplicate.
*
* @deprecated 3.0.0
* @param mixed $id
* @param mixed $id The ID of the product to duplicate.
* @return object|bool
* @see duplicate_product
*/
@ -215,6 +230,44 @@ class WC_Admin_Duplicate_Product {
return $post;
}
/**
* Generates a unique slug for a given product. We do this so that we can override the
* behavior of wp_unique_post_slug(). The normal slug generation will run single
* select queries on every non-unique slug, resulting in very bad performance.
*
* @param WC_Product $product The product to generate a slug for.
* @since 3.9.0
*/
private function generate_unique_slug( $product ) {
global $wpdb;
// We want to remove the suffix from the slug so that we can find the maximum suffix using this root slug.
// This will allow us to find the next-highest suffix that is unique. While this does not support gap
// filling, this shouldn't matter for our use-case.
$root_slug = preg_replace( '/-[0-9]+$/', '', $product->get_slug() );
$results = $wpdb->get_results(
$wpdb->prepare( "SELECT post_name FROM $wpdb->posts WHERE post_name LIKE %s AND post_type IN ( 'product', 'product_variation' )", $root_slug . '%' )
);
// The slug is already unique!
if ( empty( $results ) ) {
return;
}
// Find the maximum suffix so we can ensure uniqueness.
$max_suffix = 1;
foreach ( $results as $result ) {
// Pull a numerical suffix off the slug after the last hyphen.
$suffix = intval( substr( $result->post_name, strrpos( $result->post_name, '-' ) + 1 ) );
if ( $suffix > $max_suffix ) {
$max_suffix = $suffix;
}
}
$product->set_slug( $root_slug . '-' . ( $max_suffix + 1 ) );
}
}
return new WC_Admin_Duplicate_Product();

View File

@ -115,7 +115,7 @@ class WC_Admin_Menus {
global $current_tab, $current_section;
// We should only save on the settings page.
if ( ! is_admin() || ! isset( $_GET['page'] ) || 'wc-settings' !== $_GET['page'] ) { // phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification
if ( ! is_admin() || ! isset( $_GET['page'] ) || 'wc-settings' !== $_GET['page'] ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
return;
}

View File

@ -133,7 +133,7 @@ class WC_Admin_Meta_Boxes {
add_meta_box( 'woocommerce-coupon-data', __( 'Coupon data', 'woocommerce' ), 'WC_Meta_Box_Coupon_Data::output', 'shop_coupon', 'normal', 'high' );
// Comment rating.
if ( 'comment' === $screen_id && isset( $_GET['c'] ) && metadata_exists( 'comment', wc_clean( wp_unslash( $_GET['c'] ) ), 'rating' ) ) { // phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification
if ( 'comment' === $screen_id && isset( $_GET['c'] ) && metadata_exists( 'comment', wc_clean( wp_unslash( $_GET['c'] ) ), 'rating' ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
add_meta_box( 'woocommerce-rating', __( 'Rating', 'woocommerce' ), 'WC_Meta_Box_Product_Reviews::output', 'comment', 'normal', 'high' );
}
}

View File

@ -642,6 +642,10 @@ class WC_Admin_Post_Types {
wc_update_product_stock( $product, $stock_amount, 'set', true );
break;
}
} else {
// Reset values if WooCommerce Setting - Manage Stock status is disabled.
$product->set_stock_quantity( '' );
$product->set_manage_stock( 'no' );
}
// Apply product type constraints to stock status.

View File

@ -48,6 +48,13 @@ class WC_Admin_Setup_Wizard {
'Someone give me high five, I just set up a new store with #WordPress and @WooCommerce!',
);
/**
* The version of WordPress required to run the WooCommerce Admin plugin
*
* @var string
*/
private $wc_admin_plugin_minimum_wordpress_version = '5.3';
/**
* Hook in tabs.
*/
@ -73,7 +80,7 @@ class WC_Admin_Setup_Wizard {
* @return boolean
*/
protected function should_show_theme() {
$support_woocommerce = current_theme_supports( 'woocommerce' ) && ! $this->is_default_theme();
$support_woocommerce = current_theme_supports( 'woocommerce' ) && ! wc_is_wp_default_theme_active();
return (
current_user_can( 'install_themes' ) &&
@ -83,27 +90,6 @@ class WC_Admin_Setup_Wizard {
);
}
/**
* Is the user using a default WP theme?
*
* @return boolean
*/
protected function is_default_theme() {
return wc_is_active_theme(
array(
'twentynineteen',
'twentyseventeen',
'twentysixteen',
'twentyfifteen',
'twentyfourteen',
'twentythirteen',
'twentyeleven',
'twentytwelve',
'twentyten',
)
);
}
/**
* The "automated tax" extra should only be shown if the current user can
* install plugins and the store is in a supported country.
@ -147,12 +133,36 @@ class WC_Admin_Setup_Wizard {
/**
* Should we show the WooCommerce Admin install option?
* True only if the user can install plugins,
* and up until the end date of the recommendation.
* and is running the correct version of WordPress.
*
* @see WC_Admin_Setup_Wizard::$wc_admin_plugin_minimum_wordpress_version
*
* @return boolean
*/
protected function should_show_wc_admin() {
return current_user_can( 'install_plugins' );
$wordpress_minimum_met = version_compare( get_bloginfo( 'version' ), $this->wc_admin_plugin_minimum_wordpress_version, '>=' );
return current_user_can( 'install_plugins' ) && $wordpress_minimum_met;
}
/**
* Should we show the new WooCommerce Admin onboarding experience?
*
* @return boolean
*/
protected function should_show_wc_admin_onboarding() {
if ( ! $this->should_show_wc_admin() ) {
return false;
}
$ab_test = get_option( 'woocommerce_setup_ab_wc_admin_onboarding' );
// If it doesn't exist yet, generate it for later use and save it, so we always show the same to this user.
if ( ! $ab_test ) {
$ab_test = 1 !== rand( 1, 10 ) ? 'a' : 'b'; // 10% of users. b gets the new experience.
update_option( 'woocommerce_setup_ab_wc_admin_onboarding', $ab_test );
}
return 'b' === $ab_test;
}
/**
@ -251,38 +261,48 @@ class WC_Admin_Setup_Wizard {
return;
}
$default_steps = array(
'store_setup' => array(
'name' => __( 'Store setup', 'woocommerce' ),
'view' => array( $this, 'wc_setup_store_setup' ),
'handler' => array( $this, 'wc_setup_store_setup_save' ),
'new_onboarding' => array(
'name' => '',
'view' => array( $this, 'wc_setup_new_onboarding' ),
'handler' => array( $this, 'wc_setup_new_onboarding_save' ),
),
'payment' => array(
'name' => __( 'Payment', 'woocommerce' ),
'view' => array( $this, 'wc_setup_payment' ),
'handler' => array( $this, 'wc_setup_payment_save' ),
'store_setup' => array(
'name' => __( 'Store setup', 'woocommerce' ),
'view' => array( $this, 'wc_setup_store_setup' ),
'handler' => array( $this, 'wc_setup_store_setup_save' ),
),
'shipping' => array(
'name' => __( 'Shipping', 'woocommerce' ),
'view' => array( $this, 'wc_setup_shipping' ),
'handler' => array( $this, 'wc_setup_shipping_save' ),
'payment' => array(
'name' => __( 'Payment', 'woocommerce' ),
'view' => array( $this, 'wc_setup_payment' ),
'handler' => array( $this, 'wc_setup_payment_save' ),
),
'recommended' => array(
'name' => __( 'Recommended', 'woocommerce' ),
'view' => array( $this, 'wc_setup_recommended' ),
'handler' => array( $this, 'wc_setup_recommended_save' ),
'shipping' => array(
'name' => __( 'Shipping', 'woocommerce' ),
'view' => array( $this, 'wc_setup_shipping' ),
'handler' => array( $this, 'wc_setup_shipping_save' ),
),
'activate' => array(
'name' => __( 'Activate', 'woocommerce' ),
'view' => array( $this, 'wc_setup_activate' ),
'handler' => array( $this, 'wc_setup_activate_save' ),
'recommended' => array(
'name' => __( 'Recommended', 'woocommerce' ),
'view' => array( $this, 'wc_setup_recommended' ),
'handler' => array( $this, 'wc_setup_recommended_save' ),
),
'next_steps' => array(
'name' => __( 'Ready!', 'woocommerce' ),
'view' => array( $this, 'wc_setup_ready' ),
'handler' => '',
'activate' => array(
'name' => __( 'Activate', 'woocommerce' ),
'view' => array( $this, 'wc_setup_activate' ),
'handler' => array( $this, 'wc_setup_activate_save' ),
),
'next_steps' => array(
'name' => __( 'Ready!', 'woocommerce' ),
'view' => array( $this, 'wc_setup_ready' ),
'handler' => '',
),
);
// Hide the new/improved onboarding experience screen if the user is not part of the a/b test.
if ( ! $this->should_show_wc_admin_onboarding() ) {
unset( $default_steps['new_onboarding'] );
}
// Hide recommended step if nothing is going to be shown there.
if ( ! $this->should_show_recommended_step() ) {
unset( $default_steps['recommended'] );
@ -346,6 +366,9 @@ class WC_Admin_Setup_Wizard {
* Setup Wizard Header.
*/
public function setup_wizard_header() {
// same as default WP from wp-admin/admin-header.php.
$wp_version_class = 'branch-' . str_replace( array( '.', ',' ), '-', floatval( get_bloginfo( 'version' ) ) );
set_current_screen();
?>
<!DOCTYPE html>
@ -359,8 +382,8 @@ class WC_Admin_Setup_Wizard {
<?php do_action( 'admin_print_styles' ); ?>
<?php do_action( 'admin_head' ); ?>
</head>
<body class="wc-setup wp-core-ui">
<h1 id="wc-logo"><a href="https://woocommerce.com/"><img src="<?php echo esc_url( WC()->plugin_url() ); ?>/assets/images/woocommerce_logo.png" alt="<?php esc_attr_e( 'WooCommerce', 'woocommerce' ); ?>" /></a></h1>
<body class="wc-setup wp-core-ui <?php echo esc_attr( 'wc-setup-step__' . $this->step ); ?> <?php echo esc_attr( $wp_version_class ); ?>">
<h1 class="wc-logo"><a href="https://woocommerce.com/"><img src="<?php echo esc_url( WC()->plugin_url() ); ?>/assets/images/woocommerce_logo.png" alt="<?php esc_attr_e( 'WooCommerce', 'woocommerce' ); ?>" /></a></h1>
<?php
}
@ -369,7 +392,9 @@ class WC_Admin_Setup_Wizard {
*/
public function setup_wizard_footer() {
?>
<?php if ( 'store_setup' === $this->step ) : ?>
<?php if ( 'new_onboarding' === $this->step ) : ?>
<a class="wc-setup-footer-links" href="<?php echo esc_url( $this->get_next_step_link() ); ?>"><?php esc_html_e( 'Continue with the old setup wizard', 'woocommerce' ); ?></a>
<?php elseif ( 'store_setup' === $this->step ) : ?>
<a class="wc-setup-footer-links" href="<?php echo esc_url( admin_url() ); ?>"><?php esc_html_e( 'Not right now', 'woocommerce' ); ?></a>
<?php elseif ( 'recommended' === $this->step || 'activate' === $this->step ) : ?>
<a class="wc-setup-footer-links" href="<?php echo esc_url( $this->get_next_step_link() ); ?>"><?php esc_html_e( 'Skip this step', 'woocommerce' ); ?></a>
@ -393,6 +418,8 @@ class WC_Admin_Setup_Wizard {
unset( $output_steps['activate'] );
}
unset( $output_steps['new_onboarding'] );
?>
<ol class="wc-setup-steps">
<?php
@ -431,6 +458,72 @@ class WC_Admin_Setup_Wizard {
echo '</div>';
}
/**
* Display's a prompt for users to try out the new improved WooCommerce onboarding experience in WooCommerce Admin.
*/
public function wc_setup_new_onboarding() {
?>
<div class="wc-setup-step__new_onboarding-wrapper">
<p class="wc-setup-step__new_onboarding-welcome"><?php esc_html_e( 'Welcome to', 'woocommerce' ); ?></p>
<h1 class="wc-logo"><a href="https://woocommerce.com/"><img src="<?php echo esc_url( WC()->plugin_url() ); ?>/assets/images/woocommerce_logo.png" alt="<?php esc_attr_e( 'WooCommerce', 'woocommerce' ); ?>" /></a></h1>
<p><?php esc_html_e( 'Get your store up and running more quickly with our new and improved setup experience', 'woocommerce' ); ?></p>
<form method="post" class="activate-new-onboarding">
<?php wp_nonce_field( 'wc-setup' ); ?>
<input type="hidden" name="save_step" value="new_onboarding" />
<p class="wc-setup-actions step">
<button class="button-primary button button-large" value="<?php esc_attr_e( 'Yes please', 'woocommerce' ); ?>" name="save_step"><?php esc_html_e( 'Yes please', 'woocommerce' ); ?></button>
</p>
</form>
<p class="wc-setup-step__new_onboarding-plugin-info"><?php esc_html_e( 'The "WooCommerce Admin" plugin will be installed and activated', 'woocommerce' ); ?></p>
</div>
<?php
}
/**
* Installs WooCommerce admin and redirects to the new onboarding experience.
*/
public function wc_setup_new_onboarding_save() {
check_admin_referer( 'wc-setup' );
update_option( 'wc_onboarding_opt_in', 'yes' );
if ( function_exists( 'wc_admin_url' ) ) {
$this->wc_setup_redirect_to_wc_admin_onboarding();
exit;
}
WC_Install::background_installer(
'woocommerce-admin',
array(
'name' => __( 'WooCommerce Admin', 'woocommerce' ),
'repo-slug' => 'woocommerce-admin',
)
);
// The plugin was not successfully installed, so continue with normal setup.
if ( ! function_exists( 'wc_admin_url' ) ) {
wp_safe_redirect( esc_url_raw( $this->get_next_step_link() ) );
exit;
}
$this->wc_setup_redirect_to_wc_admin_onboarding();
exit;
}
/**
* Redirects to the onboarding wizard in WooCommerce Admin.
*/
private function wc_setup_redirect_to_wc_admin_onboarding() {
// Renables the wizard.
$profile_updates = array( 'completed' => false );
$onboarding_data = get_option( 'wc_onboarding_profile', array() );
update_option( 'wc_onboarding_profile', array_merge( $onboarding_data, $profile_updates ) );
wp_safe_redirect( esc_url_raw( admin_url( 'admin.php?page=wc-admin' ) ) );
}
/**
* Initial "store setup" step.
* Location, product type, page setup, and tracking opt-in.
@ -580,7 +673,7 @@ class WC_Admin_Setup_Wizard {
printf(
wp_kses(
/* translators: %1$s: usage tracking help link */
__( 'Learn more about how usage tracking works, and how you\'ll be helping <a href="%1$s" target="_blank">here</a>.', 'woocommerce' ),
__( 'Learn more about how usage tracking works, and how you\'ll be helping in our <a href="%1$s" target="_blank">usage tracking documentation</a>.', 'woocommerce' ),
array(
'a' => array(
'href' => array(),
@ -700,7 +793,7 @@ class WC_Admin_Setup_Wizard {
public function run_deferred_actions() {
$this->close_http_connection();
foreach ( $this->deferred_actions as $action ) {
call_user_func_array( $action['func'], $action['args'] );
$action['func']( ...$action['args'] );
// Clear the background installation flag if this is a plugin.
if (

View File

@ -72,8 +72,8 @@ class WC_Admin {
}
// Setup/welcome.
if ( ! empty( $_GET['page'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification
switch ( $_GET['page'] ) { // phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification
if ( ! empty( $_GET['page'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
switch ( $_GET['page'] ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
case 'wc-setup':
include_once dirname( __FILE__ ) . '/class-wc-admin-setup-wizard.php';
break;
@ -127,7 +127,7 @@ class WC_Admin {
* For setup wizard, transient must be present, the user must have access rights, and we must ignore the network/bulk plugin updaters.
*/
public function admin_redirects() {
// phpcs:disable WordPress.Security.NonceVerification.NoNonceVerification
// phpcs:disable WordPress.Security.NonceVerification.Recommended
// Nonced plugin install redirects (whitelisted).
if ( ! empty( $_GET['wc-install-plugin-redirect'] ) ) {
$plugin_slug = wc_clean( wp_unslash( $_GET['wc-install-plugin-redirect'] ) );
@ -165,7 +165,7 @@ class WC_Admin {
exit;
}
}
// phpcs:enable WordPress.Security.NonceVerification.NoNonceVerification
// phpcs:enable WordPress.Security.NonceVerification.Recommended
}
/**

View File

@ -149,7 +149,7 @@ class WC_Product_CSV_Importer_Controller {
$this->steps = apply_filters( 'woocommerce_product_csv_importer_steps', $default_steps );
// phpcs:disable WordPress.Security.NonceVerification.NoNonceVerification
// phpcs:disable WordPress.Security.NonceVerification.Recommended
$this->step = isset( $_REQUEST['step'] ) ? sanitize_key( $_REQUEST['step'] ) : current( array_keys( $this->steps ) );
$this->file = isset( $_REQUEST['file'] ) ? wc_clean( wp_unslash( $_REQUEST['file'] ) ) : '';
$this->update_existing = isset( $_REQUEST['update_existing'] ) ? (bool) $_REQUEST['update_existing'] : false;
@ -263,7 +263,7 @@ class WC_Product_CSV_Importer_Controller {
* Dispatch current step and show correct view.
*/
public function dispatch() {
// phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification
// phpcs:ignore WordPress.Security.NonceVerification.Missing
if ( ! empty( $_POST['save_step'] ) && ! empty( $this->steps[ $this->step ]['handler'] ) ) {
call_user_func( $this->steps[ $this->step ]['handler'], $this );
}
@ -311,7 +311,7 @@ class WC_Product_CSV_Importer_Controller {
* @return string|WP_Error
*/
public function handle_upload() {
// phpcs:disable WordPress.Security.NonceVerification.NoNonceVerification -- Nonce already verified in WC_Product_CSV_Importer_Controller::upload_form_handler()
// phpcs:disable WordPress.Security.NonceVerification.Missing -- Nonce already verified in WC_Product_CSV_Importer_Controller::upload_form_handler()
$file_url = isset( $_POST['file_url'] ) ? wc_clean( wp_unslash( $_POST['file_url'] ) ) : '';
if ( empty( $file_url ) ) {

View File

@ -200,7 +200,7 @@ class WC_Tax_Rate_Importer extends WP_Importer {
* @return bool False if error uploading or invalid file, true otherwise
*/
public function handle_upload() {
$file_url = isset( $_POST['file_url'] ) ? wc_clean( wp_unslash( $_POST['file_url'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification -- Nonce already verified in WC_Tax_Rate_Importer::dispatch()
$file_url = isset( $_POST['file_url'] ) ? wc_clean( wp_unslash( $_POST['file_url'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce already verified in WC_Tax_Rate_Importer::dispatch()
if ( empty( $file_url ) ) {
$file = wp_import_handle_upload();

View File

@ -249,11 +249,11 @@ class WC_Admin_List_Table_Orders extends WC_Admin_List_Table {
}
// Check if the order was created within the last 24 hours, and not in the future.
if ( $order_timestamp > strtotime( '-1 day', current_time( 'timestamp', true ) ) && $order_timestamp <= current_time( 'timestamp', true ) ) {
if ( $order_timestamp > strtotime( '-1 day', time() ) && $order_timestamp <= time() ) {
$show_date = sprintf(
/* translators: %s: human-readable time difference */
_x( '%s ago', '%s = human-readable time difference', 'woocommerce' ),
human_time_diff( $this->object->get_date_created()->getTimestamp(), current_time( 'timestamp', true ) )
human_time_diff( $this->object->get_date_created()->getTimestamp(), time() )
);
} else {
$show_date = $this->object->get_date_created()->date_i18n( apply_filters( 'woocommerce_admin_order_date_format', __( 'M j, Y', 'woocommerce' ) ) );
@ -751,7 +751,7 @@ class WC_Admin_List_Table_Orders extends WC_Admin_List_Table {
$user_string = '';
$user_id = '';
if ( ! empty( $_GET['_customer_user'] ) ) { // phpcs:disable WordPress.Security.NonceVerification.NoNonceVerification
if ( ! empty( $_GET['_customer_user'] ) ) { // phpcs:disable WordPress.Security.NonceVerification.Recommended
$user_id = absint( $_GET['_customer_user'] ); // WPCS: input var ok, sanitization ok.
$user = get_user_by( 'id', $user_id );
@ -844,7 +844,7 @@ class WC_Admin_List_Table_Orders extends WC_Admin_List_Table {
public function search_label( $query ) {
global $pagenow, $typenow;
if ( 'edit.php' !== $pagenow || 'shop_order' !== $typenow || ! get_query_var( 'shop_order_search' ) || ! isset( $_GET['s'] ) ) { // phpcs:disable WordPress.Security.NonceVerification.NoNonceVerification
if ( 'edit.php' !== $pagenow || 'shop_order' !== $typenow || ! get_query_var( 'shop_order_search' ) || ! isset( $_GET['s'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
return $query;
}
@ -870,7 +870,7 @@ class WC_Admin_List_Table_Orders extends WC_Admin_List_Table {
public function search_custom_fields( $wp ) {
global $pagenow;
if ( 'edit.php' !== $pagenow || empty( $wp->query_vars['s'] ) || 'shop_order' !== $wp->query_vars['post_type'] || ! isset( $_GET['s'] ) ) { // phpcs:disable WordPress.Security.NonceVerification.NoNonceVerification
if ( 'edit.php' !== $pagenow || empty( $wp->query_vars['s'] ) || 'shop_order' !== $wp->query_vars['post_type'] || ! isset( $_GET['s'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
return;
}

View File

@ -479,12 +479,12 @@ class WC_Admin_List_Table_Products extends WC_Admin_List_Table {
}
// Stock status filter.
if ( ! empty( $_GET['stock_status'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification
if ( ! empty( $_GET['stock_status'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
add_filter( 'posts_clauses', array( $this, 'filter_stock_status_post_clauses' ) );
}
// Shipping class taxonomy.
if ( ! empty( $_GET['product_shipping_class'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification
if ( ! empty( $_GET['product_shipping_class'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
$query_vars['tax_query'][] = array(
'taxonomy' => 'product_shipping_class',
'field' => 'slug',
@ -614,9 +614,9 @@ class WC_Admin_List_Table_Products extends WC_Admin_List_Table {
*/
public function filter_stock_status_post_clauses( $args ) {
global $wpdb;
if ( ! empty( $_GET['stock_status'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification
if ( ! empty( $_GET['stock_status'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
$args['join'] = $this->append_product_sorting_table_join( $args['join'] );
$args['where'] .= $wpdb->prepare( ' AND wc_product_meta_lookup.stock_status=%s ', wc_clean( wp_unslash( $_GET['stock_status'] ) ) ); // phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification
$args['where'] .= $wpdb->prepare( ' AND wc_product_meta_lookup.stock_status=%s ', wc_clean( wp_unslash( $_GET['stock_status'] ) ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
}
return $args;
}

View File

@ -214,7 +214,7 @@ class WC_Meta_Box_Product_Data {
* @return array
*/
private static function prepare_children() {
return isset( $_POST['grouped_products'] ) ? array_filter( array_map( 'intval', (array) $_POST['grouped_products'] ) ) : array(); // phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification
return isset( $_POST['grouped_products'] ) ? array_filter( array_map( 'intval', (array) $_POST['grouped_products'] ) ) : array(); // phpcs:ignore WordPress.Security.NonceVerification.Missing
}
/**
@ -228,7 +228,7 @@ class WC_Meta_Box_Product_Data {
$attributes = array();
if ( ! $data ) {
$data = stripslashes_deep( $_POST ); // phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification
$data = stripslashes_deep( $_POST ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
}
if ( isset( $data['attribute_names'], $data['attribute_values'] ) ) {
@ -295,9 +295,9 @@ class WC_Meta_Box_Product_Data {
$attribute_key = sanitize_title( $attribute->get_name() );
if ( ! is_null( $index ) ) {
$value = isset( $_POST[ $key_prefix . $attribute_key ][ $index ] ) ? wp_unslash( $_POST[ $key_prefix . $attribute_key ][ $index ] ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
$value = isset( $_POST[ $key_prefix . $attribute_key ][ $index ] ) ? wp_unslash( $_POST[ $key_prefix . $attribute_key ][ $index ] ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
} else {
$value = isset( $_POST[ $key_prefix . $attribute_key ] ) ? wp_unslash( $_POST[ $key_prefix . $attribute_key ] ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
$value = isset( $_POST[ $key_prefix . $attribute_key ] ) ? wp_unslash( $_POST[ $key_prefix . $attribute_key ] ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
}
if ( $attribute->is_taxonomy() ) {
@ -322,7 +322,7 @@ class WC_Meta_Box_Product_Data {
* @param WP_Post $post Post object.
*/
public static function save( $post_id, $post ) {
// phpcs:disable WordPress.Security.NonceVerification.NoNonceVerification
// phpcs:disable WordPress.Security.NonceVerification.Missing
// Process product type first so we have the correct class to run setters.
$product_type = empty( $_POST['product-type'] ) ? WC_Product_Factory::get_product_type( $post_id ) : sanitize_title( wp_unslash( $_POST['product-type'] ) );
$classname = WC_Product_Factory::get_product_classname( $post_id, $product_type ? $product_type : 'simple' );
@ -427,7 +427,7 @@ class WC_Meta_Box_Product_Data {
}
do_action( 'woocommerce_process_product_meta_' . $product_type, $post_id );
// phpcs:enable WordPress.Security.NonceVerification.NoNonceVerification
// phpcs:enable WordPress.Security.NonceVerification.Missing
}
/**
@ -437,7 +437,7 @@ class WC_Meta_Box_Product_Data {
* @param WP_Post $post Post object.
*/
public static function save_variations( $post_id, $post ) {
// phpcs:disable WordPress.Security.NonceVerification.NoNonceVerification
// phpcs:disable WordPress.Security.NonceVerification.Missing
if ( isset( $_POST['variable_post_id'] ) ) {
$parent = wc_get_product( $post_id );
$parent->set_default_attributes( self::prepare_set_attributes( $parent->get_attributes(), 'default_attribute_' ) );
@ -453,7 +453,7 @@ class WC_Meta_Box_Product_Data {
continue;
}
$variation_id = absint( $_POST['variable_post_id'][ $i ] );
$variation = new WC_Product_Variation( $variation_id );
$variation = wc_get_product_object( 'variation', $variation_id );
$stock = null;
// Handle stock changes.
@ -527,11 +527,20 @@ class WC_Meta_Box_Product_Data {
WC_Admin_Meta_Boxes::add_error( $errors->get_error_message() );
}
/**
* Set variation props before save.
*
* @param object $variation WC_Product_Variation object.
* @param int $i
* @since 3.8.0
*/
do_action( 'woocommerce_admin_process_variation_object', $variation, $i );
$variation->save();
do_action( 'woocommerce_save_product_variation', $variation_id, $i );
}
}
// phpcs:enable WordPress.Security.NonceVerification.NoNonceVerification
// phpcs:enable WordPress.Security.NonceVerification.Missing
}
}

View File

@ -115,6 +115,10 @@ $row_class = apply_filters( 'woocommerce_admin_html_order_item_class', ! empt
$tax_item_id = $tax_item->get_rate_id();
$tax_item_total = isset( $tax_data['total'][ $tax_item_id ] ) ? $tax_data['total'][ $tax_item_id ] : '';
$tax_item_subtotal = isset( $tax_data['subtotal'][ $tax_item_id ] ) ? $tax_data['subtotal'][ $tax_item_id ] : '';
$round_at_subtotal = 'yes' === get_option( 'woocommerce_tax_round_at_subtotal' );
$tax_item_total = wc_round_tax_total( $tax_item_total, $round_at_subtotal ? wc_get_rounding_precision() : null );
$tax_item_subtotal = wc_round_tax_total( $tax_item_subtotal, $round_at_subtotal ? wc_get_rounding_precision() : null );
?>
<td class="line_tax" width="1%">
<div class="view">

View File

@ -345,7 +345,7 @@ if ( wc_tax_enabled() ) {
</thead>
<?php
$row = '
<td><select class="wc-product-search" name="item_id" data-allow_clear="true" data-display_stock="true" data-placeholder="' . esc_attr__( 'Search for a product&hellip;', 'woocommerce' ) . '"></select></td>
<td><select class="wc-product-search" name="item_id" data-allow_clear="true" data-display_stock="true" data-exclude_type="variable" data-placeholder="' . esc_attr__( 'Search for a product&hellip;', 'woocommerce' ) . '"></select></td>
<td><input type="number" step="1" min="0" max="9999" autocomplete="off" name="item_qty" placeholder="1" size="4" class="quantity" /></td>';
?>
<tbody data-row="<?php echo esc_attr( $row ); ?>">

View File

@ -587,7 +587,7 @@ class WC_Report_Sales_By_Date extends WC_Admin_Report {
'refund_amount' => '#e74c3c',
);
$current_range = ! empty( $_GET['range'] ) ? sanitize_text_field( wp_unslash( $_GET['range'] ) ) : '7day'; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated, WordPress.Security.NonceVerification.NoNonceVerification
$current_range = ! empty( $_GET['range'] ) ? sanitize_text_field( wp_unslash( $_GET['range'] ) ) : '7day'; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
if ( ! in_array( $current_range, array( 'custom', 'year', 'last_month', 'month', '7day' ), true ) ) {
$current_range = '7day';
@ -603,7 +603,7 @@ class WC_Report_Sales_By_Date extends WC_Admin_Report {
* Output an export link.
*/
public function get_export_button() {
$current_range = ! empty( $_GET['range'] ) ? sanitize_text_field( wp_unslash( $_GET['range'] ) ) : '7day'; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated, WordPress.Security.NonceVerification.NoNonceVerification
$current_range = ! empty( $_GET['range'] ) ? sanitize_text_field( wp_unslash( $_GET['range'] ) ) : '7day'; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
?>
<a
href="#"

View File

@ -150,7 +150,7 @@ class WC_Report_Sales_By_Product extends WC_Admin_Report {
'item_count' => '#d4d9dc',
);
$current_range = ! empty( $_GET['range'] ) ? sanitize_text_field( wp_unslash( $_GET['range'] ) ) : '7day'; //phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification
$current_range = ! empty( $_GET['range'] ) ? sanitize_text_field( wp_unslash( $_GET['range'] ) ) : '7day'; //phpcs:ignore WordPress.Security.NonceVerification.Recommended
if ( ! in_array( $current_range, array( 'custom', 'year', 'last_month', 'month', '7day' ), true ) ) {
$current_range = '7day';
@ -400,7 +400,7 @@ class WC_Report_Sales_By_Product extends WC_Admin_Report {
*/
public function get_export_button() {
$current_range = ! empty( $_GET['range'] ) ? sanitize_text_field( wp_unslash( $_GET['range'] ) ) : '7day'; //phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification
$current_range = ! empty( $_GET['range'] ) ? sanitize_text_field( wp_unslash( $_GET['range'] ) ) : '7day'; //phpcs:ignore WordPress.Security.NonceVerification.Recommended
?>
<a
href="#"

View File

@ -33,7 +33,11 @@ class WC_Settings_Accounts extends WC_Settings_Page {
public function get_settings() {
$erasure_text = esc_html__( 'account erasure request', 'woocommerce' );
if ( current_user_can( 'manage_privacy_options' ) ) {
$erasure_text = sprintf( '<a href="%s">%s</a>', esc_url( admin_url( 'tools.php?page=remove_personal_data' ) ), $erasure_text );
if ( version_compare( get_bloginfo( 'version' ), '5.3', '<' ) ) {
$erasure_text = sprintf( '<a href="%s">%s</a>', esc_url( admin_url( 'tools.php?page=remove_personal_data' ) ), $erasure_text );
} else {
$erasure_text = sprintf( '<a href="%s">%s</a>', esc_url( admin_url( 'erase-personal-data.php' ) ), $erasure_text );
}
}
$account_settings = array(

View File

@ -108,7 +108,7 @@ class WC_Settings_Tax extends WC_Settings_Page {
* Save settings.
*/
public function save() {
// phpcs:disable WordPress.Security.NonceVerification.NoNonceVerification
// phpcs:disable WordPress.Security.NonceVerification.Missing
global $current_section;
if ( ! $current_section ) {
@ -118,7 +118,6 @@ class WC_Settings_Tax extends WC_Settings_Page {
if ( isset( $_POST['woocommerce_tax_classes'] ) ) {
$this->save_tax_classes( wp_unslash( $_POST['woocommerce_tax_classes'] ) ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
}
} elseif ( ! empty( $_POST['tax_rate_country'] ) ) {
$this->save_tax_rates();
}
@ -128,9 +127,9 @@ class WC_Settings_Tax extends WC_Settings_Page {
}
// Invalidate caches.
WC_Cache_Helper::incr_cache_prefix( 'taxes' );
WC_Cache_Helper::invalidate_cache_group( 'taxes' );
WC_Cache_Helper::get_transient_version( 'shipping', true );
// phpcs:enable WordPress.Security.NonceVerification.NoNonceVerification
// phpcs:enable WordPress.Security.NonceVerification.Missing
}
/**
@ -188,13 +187,16 @@ class WC_Settings_Tax extends WC_Settings_Page {
'page' => 'wc-settings',
'tab' => 'tax',
'section' => $current_section,
), 'admin.php'
),
'admin.php'
)
);
// Localize and enqueue our js.
wp_localize_script(
'wc-settings-tax', 'htmlSettingsTaxLocalizeScript', array(
'wc-settings-tax',
'htmlSettingsTaxLocalizeScript',
array(
'current_class' => $current_class,
'wc_tax_nonce' => wp_create_nonce( 'wc_tax_nonce-class:' . $current_class ),
'base_url' => $base_url,

View File

@ -64,7 +64,13 @@ $exporter = new WC_Product_CSV_Exporter();
<td>
<select id="woocommerce-exporter-category" class="woocommerce-exporter-category wc-enhanced-select" style="width:100%;" multiple data-placeholder="<?php esc_attr_e( 'Export all categories', 'woocommerce' ); ?>">
<?php
foreach ( get_categories( array( 'taxonomy' => 'product_cat' ) ) as $category ) {
$categories = get_categories(
array(
'taxonomy' => 'product_cat',
'hide_empty' => false,
)
);
foreach ( $categories as $category ) {
echo '<option value="' . esc_attr( $category->slug ) . '">' . esc_html( $category->name ) . '</option>';
}
?>

View File

@ -429,6 +429,11 @@ function wc_render_action_buttons( $actions ) {
function wc_render_invalid_variation_notice( $product_object ) {
global $wpdb;
// Give ability for extensions to hide this notice.
if ( ! apply_filters( 'woocommerce_show_invalid_variations_notice', true, $product_object ) ) {
return;
}
$variation_ids = $product_object ? $product_object->get_children() : array();
if ( empty( $variation_ids ) ) {

View File

@ -74,7 +74,7 @@ class WC_AJAX {
public static function do_wc_ajax() {
global $wp_query;
// phpcs:disable WordPress.Security.NonceVerification.NoNonceVerification
// phpcs:disable WordPress.Security.NonceVerification.Recommended
if ( ! empty( $_GET['wc-ajax'] ) ) {
$wp_query->set( 'wc-ajax', sanitize_text_field( wp_unslash( $_GET['wc-ajax'] ) ) );
}
@ -396,7 +396,7 @@ class WC_AJAX {
public static function add_to_cart() {
ob_start();
// phpcs:disable WordPress.Security.NonceVerification.NoNonceVerification
// phpcs:disable WordPress.Security.NonceVerification.Missing
if ( ! isset( $_POST['product_id'] ) ) {
return;
}
@ -444,7 +444,7 @@ class WC_AJAX {
public static function remove_from_cart() {
ob_start();
// phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification
// phpcs:ignore WordPress.Security.NonceVerification.Missing
$cart_item_key = wc_clean( isset( $_POST['cart_item_key'] ) ? wp_unslash( $_POST['cart_item_key'] ) : '' );
if ( $cart_item_key && false !== WC()->cart->remove_cart_item( $cart_item_key ) ) {
@ -469,7 +469,7 @@ class WC_AJAX {
public static function get_variation() {
ob_start();
// phpcs:disable WordPress.Security.NonceVerification.NoNonceVerification
// phpcs:disable WordPress.Security.NonceVerification.Missing
if ( empty( $_POST['product_id'] ) ) {
wp_die();
}
@ -707,8 +707,8 @@ class WC_AJAX {
$product_id = intval( $_POST['post_id'] );
$post = get_post( $product_id ); // phpcs:ignore
$loop = intval( $_POST['loop'] );
$product_object = new WC_Product_Variable( $product_id ); // Forces type to variable in case product is unsaved.
$variation_object = new WC_Product_Variation();
$product_object = wc_get_product_object( 'variable', $product_id ); // Forces type to variable in case product is unsaved.
$variation_object = wc_get_product_object( 'variation' );
$variation_object->set_parent_id( $product_id );
$variation_object->set_attributes( array_fill_keys( array_map( 'sanitize_title', array_keys( $product_object->get_variation_attributes() ) ), '' ) );
$variation_id = $variation_object->save();
@ -898,6 +898,10 @@ class WC_AJAX {
if ( ! $product ) {
throw new Exception( __( 'Invalid product ID', 'woocommerce' ) . ' ' . $product_id );
}
if ( 'variable' === $product->get_type() ) {
/* translators: %s product name */
throw new Exception( sprintf( __( '%s is a variable product parent and cannot be added.', 'woocommerce' ), $product->get_name() ) );
}
$validation_error = new WP_Error();
$validation_error = apply_filters( 'woocommerce_ajax_add_order_item_validation', $validation_error, $product, $order, $qty );
@ -1144,7 +1148,7 @@ class WC_AJAX {
$order->set_billing_email( $user_email_arg );
}
$result = $order->apply_coupon( wc_format_coupon_code( wp_unslash( $_POST['coupon'] ) ) ); // phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
$result = $order->apply_coupon( wc_format_coupon_code( wp_unslash( $_POST['coupon'] ) ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
if ( is_wp_error( $result ) ) {
throw new Exception( html_entity_decode( wp_strip_all_tags( $result->get_error_message() ) ) );
@ -1196,7 +1200,7 @@ class WC_AJAX {
throw new Exception( __( 'Invalid coupon', 'woocommerce' ) );
}
$order->remove_coupon( wc_format_coupon_code( wp_unslash( $_POST['coupon'] ) ) ); // phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
$order->remove_coupon( wc_format_coupon_code( wp_unslash( $_POST['coupon'] ) ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
$order->calculate_taxes( $calculate_tax_args );
$order->calculate_totals( false );
@ -1536,6 +1540,24 @@ class WC_AJAX {
$include_ids = ! empty( $_GET['include'] ) ? array_map( 'absint', (array) wp_unslash( $_GET['include'] ) ) : array();
$exclude_ids = ! empty( $_GET['exclude'] ) ? array_map( 'absint', (array) wp_unslash( $_GET['exclude'] ) ) : array();
$exclude_types = array();
if ( ! empty( $_GET['exclude_type'] ) ) {
// Support both comma-delimited and array format inputs.
$exclude_types = wp_unslash( $_GET['exclude_type'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
if ( ! is_array( $exclude_types ) ) {
$exclude_types = explode( ',', $exclude_types );
}
// Sanitize the excluded types against valid product types.
foreach ( $exclude_types as &$exclude_type ) {
$exclude_type = strtolower( trim( $exclude_type ) );
}
$exclude_types = array_intersect(
array_merge( array( 'variation' ), array_keys( wc_get_product_types() ) ),
$exclude_types
);
}
$data_store = WC_Data_Store::load( 'product' );
$ids = $data_store->search_products( $term, '', (bool) $include_variations, false, $limit, $include_ids, $exclude_ids );
@ -1546,6 +1568,10 @@ class WC_AJAX {
$formatted_name = $product_object->get_formatted_name();
$managing_stock = $product_object->managing_stock();
if ( in_array( $product_object->get_type(), $exclude_types, true ) ) {
continue;
}
if ( $managing_stock && ! empty( $_GET['display_stock'] ) ) {
$stock_amount = $product_object->get_stock_quantity();
/* Translators: %d stock amount */
@ -1717,7 +1743,7 @@ class WC_AJAX {
* Ajax request handling for categories ordering.
*/
public static function term_ordering() {
// phpcs:disable WordPress.Security.NonceVerification.NoNonceVerification
// phpcs:disable WordPress.Security.NonceVerification.Missing
if ( ! current_user_can( 'edit_products' ) || empty( $_POST['id'] ) ) {
wp_die( -1 );
}
@ -1750,7 +1776,7 @@ class WC_AJAX {
public static function product_ordering() {
global $wpdb;
// phpcs:disable WordPress.Security.NonceVerification.NoNonceVerification
// phpcs:disable WordPress.Security.NonceVerification.Missing
if ( ! current_user_can( 'edit_products' ) || empty( $_POST['id'] ) ) {
wp_die( -1 );
}
@ -1792,6 +1818,8 @@ class WC_AJAX {
$wpdb->update( $wpdb->posts, array( 'menu_order' => $menu_orders[ $sorting_id ] ), array( 'ID' => $sorting_id ) );
WC_Post_Data::delete_product_query_transients();
do_action( 'woocommerce_after_product_ordering', $sorting_id, $menu_orders );
wp_send_json( $menu_orders );
// phpcs:enable
@ -2536,7 +2564,7 @@ class WC_AJAX {
* Handle submissions from assets/js/settings-views-html-settings-tax.js Backbone model.
*/
public static function tax_rates_save_changes() {
// phpcs:disable WordPress.Security.NonceVerification.NoNonceVerification
// phpcs:disable WordPress.Security.NonceVerification.Missing
if ( ! isset( $_POST['wc_tax_nonce'], $_POST['changes'] ) ) {
wp_send_json_error( 'missing_fields' );
wp_die();
@ -2603,7 +2631,7 @@ class WC_AJAX {
}
}
WC_Cache_Helper::incr_cache_prefix( 'taxes' );
WC_Cache_Helper::invalidate_cache_group( 'taxes' );
WC_Cache_Helper::get_transient_version( 'shipping', true );
wp_send_json_success(

View File

@ -94,7 +94,7 @@ class WC_Cache_Helper {
$prefix = wp_cache_get( 'wc_' . $group . '_cache_prefix', $group );
if ( false === $prefix ) {
$prefix = 1;
$prefix = microtime();
wp_cache_set( 'wc_' . $group . '_cache_prefix', $prefix, $group );
}
@ -107,7 +107,18 @@ class WC_Cache_Helper {
* @param string $group Group of cache to clear.
*/
public static function incr_cache_prefix( $group ) {
wp_cache_incr( 'wc_' . $group . '_cache_prefix', 1, $group );
wc_deprecated_function( 'WC_Cache_Helper::incr_cache_prefix', '3.9.0', 'WC_Cache_Helper::invalidate_cache_group' );
self::invalidate_cache_group( $group );
}
/**
* Invalidate cache group.
*
* @param string $group Group of cache to clear.
* @since 3.9.0
*/
public static function invalidate_cache_group( $group ) {
wp_cache_set( 'wc_' . $group . '_cache_prefix', microtime(), $group );
}
/**

View File

@ -23,6 +23,7 @@ if ( ! defined( 'ABSPATH' ) ) {
* @since 3.2.0
*/
final class WC_Cart_Totals {
use WC_Item_Totals;
/**
* Reference to cart object.
@ -199,15 +200,6 @@ final class WC_Cart_Totals {
);
}
/**
* Should we round at subtotal level only?
*
* @return bool
*/
protected function round_at_subtotal() {
return 'yes' === get_option( 'woocommerce_tax_round_at_subtotal' );
}
/**
* Handles a cart or order object passed in for calculation. Normalises data
* into the same format for use by this class.
@ -561,6 +553,16 @@ final class WC_Cart_Totals {
return $in_cents ? $this->totals : wc_remove_number_precision_deep( $this->totals );
}
/**
* Returns array of values for totals calculation.
*
* @param string $field Field name. Will probably be `total` or `subtotal`.
* @return array Items object
*/
protected function get_values_for_total( $field ) {
return array_values( wp_list_pluck( $this->items, $field ) );
}
/**
* Get taxes merged by type.
*
@ -598,6 +600,7 @@ final class WC_Cart_Totals {
/**
* Round merged taxes.
*
* @deprecated 3.9.0 `calculate_item_subtotals` should already appropriately round the tax values.
* @since 3.5.4
* @param array $taxes Taxes to round.
* @return array
@ -681,12 +684,8 @@ final class WC_Cart_Totals {
$this->cart->cart_contents[ $item_key ]['line_tax'] = wc_remove_number_precision( $item->total_tax );
}
$items_total = array_sum(
array_map(
array( $this, 'round_item_subtotal' ),
array_values( wp_list_pluck( $this->items, 'total' ) )
)
);
$items_total = $this->get_rounded_items_total( $this->get_values_for_total( 'total' ) );
$this->set_total( 'items_total', round( $items_total ) );
$this->set_total( 'items_total_tax', array_sum( array_values( wp_list_pluck( $this->items, 'total_tax' ) ) ) );
@ -712,11 +711,14 @@ final class WC_Cart_Totals {
protected function calculate_item_subtotals() {
$merged_subtotal_taxes = array(); // Taxes indexed by tax rate ID for storage later.
$adjust_non_base_location_prices = apply_filters( 'woocommerce_adjust_non_base_location_prices', true );
$is_customer_vat_exempt = $this->cart->get_customer()->get_is_vat_exempt();
foreach ( $this->items as $item_key => $item ) {
if ( $item->price_includes_tax ) {
if ( $this->cart->get_customer()->get_is_vat_exempt() ) {
if ( $is_customer_vat_exempt ) {
$item = $this->remove_item_base_taxes( $item );
} elseif ( apply_filters( 'woocommerce_adjust_non_base_location_prices', true ) ) {
} elseif ( $adjust_non_base_location_prices ) {
$item = $this->adjust_non_base_location_price( $item );
}
}
@ -745,12 +747,8 @@ final class WC_Cart_Totals {
$this->cart->cart_contents[ $item_key ]['line_subtotal_tax'] = wc_remove_number_precision( $item->subtotal_tax );
}
$items_subtotal = array_sum(
array_map(
array( $this, 'round_item_subtotal' ),
array_values( wp_list_pluck( $this->items, 'subtotal' ) )
)
);
$items_subtotal = $this->get_rounded_items_total( $this->get_values_for_total( 'subtotal' ) );
$this->set_total( 'items_subtotal', round( $items_subtotal ) );
$this->set_total( 'items_subtotal_tax', wc_round_tax_total( array_sum( $merged_subtotal_taxes ), 0 ) );
@ -862,7 +860,7 @@ final class WC_Cart_Totals {
* @since 3.2.0
*/
protected function calculate_totals() {
$this->set_total( 'total', round( $this->get_total( 'items_total', true ) + $this->get_total( 'fees_total', true ) + $this->get_total( 'shipping_total', true ) + array_sum( $this->get_merged_taxes( true ) ), 0 ) );
$this->set_total( 'total', round( $this->get_total( 'items_total', true ) + $this->get_total( 'fees_total', true ) + $this->get_total( 'shipping_total', true ) + wc_round_tax_total( array_sum( $this->get_merged_taxes( true ) ), 0 ), 0 ) );
$this->cart->set_total_tax( array_sum( $this->get_merged_taxes( false ) ) );
// Allow plugins to hook and alter totals before final total is calculated.
@ -873,32 +871,4 @@ final class WC_Cart_Totals {
// Allow plugins to filter the grand total, and sum the cart totals in case of modifications.
$this->cart->set_total( max( 0, apply_filters( 'woocommerce_calculated_total', $this->get_total( 'total' ), $this->cart ) ) );
}
/**
* Apply rounding to an array of taxes before summing. Rounds to store DP setting, ignoring precision.
*
* @since 3.2.6
* @param float $value Tax value.
* @return float
*/
protected function round_line_tax( $value ) {
if ( ! $this->round_at_subtotal() ) {
$value = wc_round_tax_total( $value, 0 );
}
return $value;
}
/**
* Apply rounding to item subtotal before summing.
*
* @since 3.7.0
* @param float $value Item subtotal value.
* @return float
*/
protected function round_item_subtotal( $value ) {
if ( ! $this->round_at_subtotal() ) {
$value = round( $value );
}
return $value;
}
}

View File

@ -712,11 +712,11 @@ class WC_Checkout {
switch ( $fieldset_key ) {
case 'shipping':
/* translators: %s: field name */
$field_label = sprintf( __( 'Shipping %s', 'woocommerce' ), $field_label );
$field_label = sprintf( _x( 'Shipping %s', 'checkout-validation', 'woocommerce' ), $field_label );
break;
case 'billing':
/* translators: %s: field name */
$field_label = sprintf( __( 'Billing %s', 'woocommerce' ), $field_label );
$field_label = sprintf( _x( 'Billing %s', 'checkout-validation', 'woocommerce' ), $field_label );
break;
}
@ -734,14 +734,14 @@ class WC_Checkout {
/* translators: %s: field name */
$postcode_validation_notice = sprintf( __( '%s is not a valid postcode / ZIP.', 'woocommerce' ), '<strong>' . esc_html( $field_label ) . '</strong>' );
}
$errors->add( 'validation', apply_filters( 'woocommerce_checkout_postcode_validation_notice', $postcode_validation_notice, $country, $data[ $key ] ) );
$errors->add( 'validation', apply_filters( 'woocommerce_checkout_postcode_validation_notice', $postcode_validation_notice, $country, $data[ $key ] ), array( 'id' => $key ) );
}
}
if ( in_array( 'phone', $format, true ) ) {
if ( $validate_fieldset && '' !== $data[ $key ] && ! WC_Validation::is_phone( $data[ $key ] ) ) {
/* translators: %s: phone number */
$errors->add( 'validation', sprintf( __( '%s is not a valid phone number.', 'woocommerce' ), '<strong>' . esc_html( $field_label ) . '</strong>' ) );
$errors->add( 'validation', sprintf( __( '%s is not a valid phone number.', 'woocommerce' ), '<strong>' . esc_html( $field_label ) . '</strong>' ), array( 'id' => $key ) );
}
}
@ -751,7 +751,7 @@ class WC_Checkout {
if ( $validate_fieldset && ! $email_is_valid ) {
/* translators: %s: email address */
$errors->add( 'validation', sprintf( __( '%s is not a valid email address.', 'woocommerce' ), '<strong>' . esc_html( $field_label ) . '</strong>' ) );
$errors->add( 'validation', sprintf( __( '%s is not a valid email address.', 'woocommerce' ), '<strong>' . esc_html( $field_label ) . '</strong>' ), array( 'id' => $key ) );
continue;
}
}
@ -771,14 +771,14 @@ class WC_Checkout {
if ( $validate_fieldset && ! in_array( $data[ $key ], $valid_state_values, true ) ) {
/* translators: 1: state field 2: valid states */
$errors->add( 'validation', sprintf( __( '%1$s is not valid. Please enter one of the following: %2$s', 'woocommerce' ), '<strong>' . esc_html( $field_label ) . '</strong>', implode( ', ', $valid_states ) ) );
$errors->add( 'validation', sprintf( __( '%1$s is not valid. Please enter one of the following: %2$s', 'woocommerce' ), '<strong>' . esc_html( $field_label ) . '</strong>', implode( ', ', $valid_states ) ), array( 'id' => $key ) );
}
}
}
if ( $validate_fieldset && $required && '' === $data[ $key ] ) {
/* translators: %s: field name */
$errors->add( 'required-field', apply_filters( 'woocommerce_checkout_required_field_notice', sprintf( __( '%s is a required field.', 'woocommerce' ), '<strong>' . esc_html( $field_label ) . '</strong>' ), $field_label ) );
$errors->add( 'required-field', apply_filters( 'woocommerce_checkout_required_field_notice', sprintf( __( '%s is a required field.', 'woocommerce' ), '<strong>' . esc_html( $field_label ) . '</strong>' ), $field_label ), array( 'id' => $key ) );
}
}
}
@ -1101,8 +1101,11 @@ class WC_Checkout {
// Validate posted data and cart items before proceeding.
$this->validate_checkout( $posted_data, $errors );
foreach ( $errors->get_error_messages() as $message ) {
wc_add_notice( $message, 'error' );
foreach ( $errors->errors as $code => $messages ) {
$data = $errors->get_error_data( $code );
foreach ( $messages as $message ) {
wc_add_notice( $message, 'error', $data );
}
}
if ( empty( $posted_data['woocommerce_checkout_update_totals'] ) && 0 === wc_notice_count( 'error' ) ) {

View File

@ -202,8 +202,9 @@ class WC_Data_Store {
*/
public function __call( $method, $parameters ) {
if ( is_callable( array( $this->instance, $method ) ) ) {
$object = array_shift( $parameters );
return call_user_func_array( array( $this->instance, $method ), array_merge( array( &$object ), $parameters ) );
$object = array_shift( $parameters );
$parameters = array_merge( array( &$object ), $parameters );
return $this->instance->$method( ...$parameters );
}
}
}

View File

@ -118,8 +118,10 @@ class WC_Emails {
/**
* Queues transactional email so it's not sent in current request if enabled,
* otherwise falls back to send now.
*
* @param mixed ...$args Optional arguments.
*/
public static function queue_transactional_email() {
public static function queue_transactional_email( ...$args ) {
if ( is_a( self::$background_emailer, 'WC_Background_Emailer' ) ) {
self::$background_emailer->push_to_queue(
array(
@ -128,7 +130,7 @@ class WC_Emails {
)
);
} else {
call_user_func_array( array( __CLASS__, 'send_transactional_email' ), func_get_args() ); // phpcs:ignore PHPCompatibility.FunctionUse.ArgumentFunctionsUsage.InParameterList
self::send_transactional_email( ...$args );
}
}

View File

@ -39,11 +39,11 @@ class WC_Form_Handler {
* Remove key and user ID (or user login, as a fallback) from query string, set cookie, and redirect to account page to show the form.
*/
public static function redirect_reset_password_link() {
if ( is_account_page() && isset( $_GET['key'] ) && ( isset( $_GET['id'] ) || isset( $_GET['login'] ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification
if ( is_account_page() && isset( $_GET['key'] ) && ( isset( $_GET['id'] ) || isset( $_GET['login'] ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
// If available, get $user_id from query string parameter for fallback purposes.
if ( isset( $_GET['login'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification
$user = get_user_by( 'login', sanitize_user( wp_unslash( $_GET['login'] ) ) ); // phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification
if ( isset( $_GET['login'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
$user = get_user_by( 'login', sanitize_user( wp_unslash( $_GET['login'] ) ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
$user_id = $user ? $user->ID : 0;
} else {
$user_id = absint( $_GET['id'] );
@ -113,7 +113,7 @@ class WC_Form_Handler {
// Validation: Required fields.
if ( ! empty( $field['required'] ) && empty( $value ) ) {
/* translators: %s: Field name. */
wc_add_notice( sprintf( __( '%s is a required field.', 'woocommerce' ), $field['label'] ), 'error' );
wc_add_notice( sprintf( __( '%s is a required field.', 'woocommerce' ), $field['label'] ), 'error', array( 'id' => $key ) );
}
if ( ! empty( $value ) ) {
@ -259,7 +259,7 @@ class WC_Form_Handler {
foreach ( $required_fields as $field_key => $field_name ) {
if ( empty( $_POST[ $field_key ] ) ) {
/* translators: %s: Field name. */
wc_add_notice( sprintf( __( '%s is a required field.', 'woocommerce' ), '<strong>' . esc_html( $field_name ) . '</strong>' ), 'error' );
wc_add_notice( sprintf( __( '%s is a required field.', 'woocommerce' ), '<strong>' . esc_html( $field_name ) . '</strong>' ), 'error', array( 'id' => $field_key ) );
}
}
@ -340,7 +340,7 @@ class WC_Form_Handler {
* Process the checkout form.
*/
public static function checkout_action() {
if ( isset( $_POST['woocommerce_checkout_place_order'] ) || isset( $_POST['woocommerce_checkout_update_totals'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification
if ( isset( $_POST['woocommerce_checkout_place_order'] ) || isset( $_POST['woocommerce_checkout_update_totals'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
wc_nocache_headers();
if ( WC()->cart->is_empty() ) {
@ -459,6 +459,27 @@ class WC_Form_Handler {
return;
}
// Test rate limit.
$current_user_id = get_current_user_id();
$rate_limit_id = 'add_payment_method_' . $current_user_id;
$delay = (int) apply_filters( 'woocommerce_payment_gateway_add_payment_method_delay', 20 );
if ( WC_Rate_Limiter::retried_too_soon( $rate_limit_id ) ) {
wc_add_notice(
/* translators: %d number of seconds */
_n(
'You cannot add a new payment method so soon after the previous one. Please wait for %d second.',
'You cannot add a new payment method so soon after the previous one. Please wait for %d seconds.',
$delay,
'woocommerce'
),
'error'
);
return;
}
WC_Rate_Limiter::set_rate_limit( $rate_limit_id, $delay );
ob_start();
$payment_method_id = wc_clean( wp_unslash( $_POST['payment_method'] ) );
@ -559,10 +580,10 @@ class WC_Form_Handler {
$nonce_value = wc_get_var( $_REQUEST['woocommerce-cart-nonce'], wc_get_var( $_REQUEST['_wpnonce'], '' ) ); // @codingStandardsIgnoreLine.
if ( ! empty( $_POST['apply_coupon'] ) && ! empty( $_POST['coupon_code'] ) ) {
WC()->cart->add_discount( wc_format_coupon_code( wp_unslash( $_POST['coupon_code'] ) ) ); // phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
WC()->cart->add_discount( wc_format_coupon_code( wp_unslash( $_POST['coupon_code'] ) ) ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
} elseif ( isset( $_GET['remove_coupon'] ) ) {
WC()->cart->remove_coupon( wc_format_coupon_code( urldecode( wp_unslash( $_GET['remove_coupon'] ) ) ) ); // phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
WC()->cart->remove_coupon( wc_format_coupon_code( urldecode( wp_unslash( $_GET['remove_coupon'] ) ) ) ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
} elseif ( ! empty( $_GET['remove_item'] ) && wp_verify_nonce( $nonce_value, 'woocommerce-cart' ) ) {
$cart_item_key = sanitize_text_field( wp_unslash( $_GET['remove_item'] ) );
@ -724,13 +745,13 @@ class WC_Form_Handler {
* @param bool $url (default: false) URL to redirect to.
*/
public static function add_to_cart_action( $url = false ) {
if ( ! isset( $_REQUEST['add-to-cart'] ) || ! is_numeric( wp_unslash( $_REQUEST['add-to-cart'] ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
if ( ! isset( $_REQUEST['add-to-cart'] ) || ! is_numeric( wp_unslash( $_REQUEST['add-to-cart'] ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
return;
}
wc_nocache_headers();
$product_id = apply_filters( 'woocommerce_add_to_cart_product_id', absint( wp_unslash( $_REQUEST['add-to-cart'] ) ) ); // phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification
$product_id = apply_filters( 'woocommerce_add_to_cart_product_id', absint( wp_unslash( $_REQUEST['add-to-cart'] ) ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
$was_added_to_cart = false;
$adding_to_cart = wc_get_product( $product_id );
@ -772,7 +793,7 @@ class WC_Form_Handler {
* @return bool success or not
*/
private static function add_to_cart_handler_simple( $product_id ) {
$quantity = empty( $_REQUEST['quantity'] ) ? 1 : wc_stock_amount( wp_unslash( $_REQUEST['quantity'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification
$quantity = empty( $_REQUEST['quantity'] ) ? 1 : wc_stock_amount( wp_unslash( $_REQUEST['quantity'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
$passed_validation = apply_filters( 'woocommerce_add_to_cart_validation', true, $product_id, $quantity );
if ( $passed_validation && false !== WC()->cart->add_to_cart( $product_id, $quantity ) ) {
@ -792,7 +813,7 @@ class WC_Form_Handler {
private static function add_to_cart_handler_grouped( $product_id ) {
$was_added_to_cart = false;
$added_to_cart = array();
$items = isset( $_REQUEST['quantity'] ) && is_array( $_REQUEST['quantity'] ) ? wp_unslash( $_REQUEST['quantity'] ) : array(); // phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
$items = isset( $_REQUEST['quantity'] ) && is_array( $_REQUEST['quantity'] ) ? wp_unslash( $_REQUEST['quantity'] ) : array(); // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
if ( ! empty( $items ) ) {
$quantity_set = false;
@ -841,8 +862,8 @@ class WC_Form_Handler {
*/
private static function add_to_cart_handler_variable( $product_id ) {
try {
$variation_id = empty( $_REQUEST['variation_id'] ) ? '' : absint( wp_unslash( $_REQUEST['variation_id'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification
$quantity = empty( $_REQUEST['quantity'] ) ? 1 : wc_stock_amount( wp_unslash( $_REQUEST['quantity'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification
$variation_id = empty( $_REQUEST['variation_id'] ) ? '' : absint( wp_unslash( $_REQUEST['variation_id'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
$quantity = empty( $_REQUEST['quantity'] ) ? 1 : wc_stock_amount( wp_unslash( $_REQUEST['quantity'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
$missing_attributes = array();
$variations = array();
$adding_to_cart = wc_get_product( $product_id );
@ -871,12 +892,12 @@ class WC_Form_Handler {
}
$attribute_key = 'attribute_' . sanitize_title( $attribute['name'] );
if ( isset( $_REQUEST[ $attribute_key ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification
if ( isset( $_REQUEST[ $attribute_key ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
if ( $attribute['is_taxonomy'] ) {
// Don't use wc_clean as it destroys sanitized characters.
$value = sanitize_title( wp_unslash( $_REQUEST[ $attribute_key ] ) ); // phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification
$value = sanitize_title( wp_unslash( $_REQUEST[ $attribute_key ] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
} else {
$value = html_entity_decode( wc_clean( wp_unslash( $_REQUEST[ $attribute_key ] ) ), ENT_QUOTES, get_bloginfo( 'charset' ) ); // phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification
$value = html_entity_decode( wc_clean( wp_unslash( $_REQUEST[ $attribute_key ] ) ), ENT_QUOTES, get_bloginfo( 'charset' ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
}
$posted_attributes[ $attribute_key ] = $value;
@ -1093,8 +1114,8 @@ class WC_Form_Handler {
* @throws Exception On registration error.
*/
public static function process_registration() {
$nonce_value = isset( $_POST['_wpnonce'] ) ? wp_unslash( $_POST['_wpnonce'] ) : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.NonceVerification.NoNonceVerification
$nonce_value = isset( $_POST['woocommerce-register-nonce'] ) ? wp_unslash( $_POST['woocommerce-register-nonce'] ) : $nonce_value; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.NonceVerification.NoNonceVerification
$nonce_value = isset( $_POST['_wpnonce'] ) ? wp_unslash( $_POST['_wpnonce'] ) : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
$nonce_value = isset( $_POST['woocommerce-register-nonce'] ) ? wp_unslash( $_POST['woocommerce-register-nonce'] ) : $nonce_value; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
if ( isset( $_POST['register'], $_POST['email'] ) && wp_verify_nonce( $nonce_value, 'woocommerce-register' ) ) {
$username = 'no' === get_option( 'woocommerce_registration_generate_username' ) && isset( $_POST['username'] ) ? wp_unslash( $_POST['username'] ) : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized

View File

@ -307,13 +307,13 @@ class WC_Frontend_Scripts {
private static function register_styles() {
$register_styles = array(
'photoswipe' => array(
'src' => self::get_asset_url( 'assets/css/photoswipe/photoswipe.css' ),
'src' => self::get_asset_url( 'assets/css/photoswipe/photoswipe.min.css' ),
'deps' => array(),
'version' => WC_VERSION,
'has_rtl' => false,
),
'photoswipe-default-skin' => array(
'src' => self::get_asset_url( 'assets/css/photoswipe/default-skin/default-skin.css' ),
'src' => self::get_asset_url( 'assets/css/photoswipe/default-skin/default-skin.min.css' ),
'deps' => array( 'photoswipe' ),
'version' => WC_VERSION,
'has_rtl' => false,

View File

@ -46,7 +46,7 @@ class WC_Order_Factory {
try {
return new $classname( $order_id );
} catch ( Exception $e ) {
wc_caught_exception( $e, __FUNCTION__, func_get_args() );
wc_caught_exception( $e, __FUNCTION__, array( $order_id ) );
return false;
}
}

View File

@ -113,7 +113,7 @@ class WC_Order extends WC_Abstract_Order {
$this->set_transaction_id( $transaction_id );
}
if ( ! $this->get_date_paid( 'edit' ) ) {
$this->set_date_paid( current_time( 'timestamp', true ) );
$this->set_date_paid( time() );
}
$this->set_status( apply_filters( 'woocommerce_payment_complete_order_status', $this->needs_processing() ? 'processing' : 'completed', $this->get_id(), $this ) );
$this->save();
@ -292,11 +292,11 @@ class WC_Order extends WC_Abstract_Order {
if ( $this->has_status( $payment_completed_status ) ) {
// If payment complete status is reached, set paid now.
$this->set_date_paid( current_time( 'timestamp', true ) );
$this->set_date_paid( time() );
} elseif ( 'processing' === $payment_completed_status && $this->has_status( 'completed' ) ) {
// If payment complete status was processing, but we've passed that and still have no date, set it now.
$this->set_date_paid( current_time( 'timestamp', true ) );
$this->set_date_paid( time() );
}
}
}
@ -310,7 +310,7 @@ class WC_Order extends WC_Abstract_Order {
*/
protected function maybe_set_date_completed() {
if ( $this->has_status( 'completed' ) ) {
$this->set_date_completed( current_time( 'timestamp', true ) );
$this->set_date_completed( time() );
}
}
@ -371,6 +371,21 @@ class WC_Order extends WC_Abstract_Order {
do_action( 'woocommerce_order_status_' . $status_transition['from'] . '_to_' . $status_transition['to'], $this->get_id(), $this );
do_action( 'woocommerce_order_status_changed', $this->get_id(), $status_transition['from'], $status_transition['to'], $this );
// Work out if this was for a payment, and trigger a payment_status hook instead.
if (
in_array( $status_transition['from'], apply_filters( 'woocommerce_valid_order_statuses_for_payment', array( 'pending', 'failed' ) ), true )
&& in_array( $status_transition['to'], wc_get_is_paid_statuses(), true )
) {
/**
* Fires when the order progresses from a pending payment status to a paid one.
*
* @since 3.9.0
* @param int Order ID
* @param WC_Order Order object
*/
do_action( 'woocommerce_order_payment_status_changed', $this->get_id(), $this );
}
} else {
/* translators: %s: new order status */
$transition_note = sprintf( __( 'Order status set to %s.', 'woocommerce' ), wc_get_order_status_name( $status_transition['to'] ) );

View File

@ -462,7 +462,7 @@ class WC_Post_Data {
* @param string $meta_value Meta value.
*/
public static function flush_object_meta_cache( $meta_id, $object_id, $meta_key, $meta_value ) {
WC_Cache_Helper::incr_cache_prefix( 'object_' . $object_id );
WC_Cache_Helper::invalidate_cache_group( 'object_' . $object_id );
}
/**

View File

@ -234,7 +234,7 @@ class WC_Query {
* @return bool
*/
private function is_showing_page_on_front( $q ) {
return $q->is_home() && 'page' === get_option( 'show_on_front' );
return ( $q->is_home() && ! $q->is_posts_page ) && 'page' === get_option( 'show_on_front' );
}
/**
@ -288,7 +288,7 @@ class WC_Query {
$q->is_singular = true;
}
}
} elseif ( ! empty( $_GET['orderby'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification
} elseif ( ! empty( $_GET['orderby'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
$q->set( 'page_id', (int) get_option( 'page_on_front' ) );
$q->is_page = true;
$q->is_home = false;

View File

@ -0,0 +1,79 @@
<?php
/**
* Provide basic rate limiting functionality via WP Options API.
*
* Currently only provides a simple limit by delaying action by X seconds.
*
* Example usage:
*
* When an action runs, call set_rate_limit, e.g.:
*
* WC_Rate_Limiter::set_rate_limit( "{$my_action_name}_{$user_id}", $delay );
*
* This sets a timestamp for future timestamp after which action can run again.
*
*
* Then before running the action again, check if the action is allowed to run, e.g.:
*
* if ( WC_Rate_Limiter::retried_too_soon( "{$my_action_name}_{$user_id}" ) ) {
* add_notice( 'Sorry, too soon!' );
* }
*
* @package WooCommerce/Classes
* @version 3.9.0
* @since 3.9.0
*/
defined( 'ABSPATH' ) || exit;
/**
* Rate limit class.
*/
class WC_Rate_Limiter {
/**
* Constructs Option name from action identifier.
*
* @param string $action_id Identifier of the action.
* @return string
*/
public static function storage_id( $action_id ) {
return 'woocommerce_rate_limit_' . $action_id;
}
/**
* Returns true if the action is not allowed to be run by the rate limiter yet, false otherwise.
*
* @param string $action_id Identifier of the action.
* @return bool
*/
public static function retried_too_soon( $action_id ) {
$next_try_allowed_at = get_option( self::storage_id( $action_id ) );
// No record of action running, so action is allowed to run.
if ( false === $next_try_allowed_at ) {
return false;
}
// Before the next run is allowed, retry forbidden.
if ( time() <= $next_try_allowed_at ) {
return true;
}
// After the next run is allowed, retry allowed.
return false;
}
/**
* Sets the rate limit delay in seconds for action with identifier $id.
*
* @param string $action_id Identifier of the action.
* @param int $delay Delay in seconds.
* @return bool True if the option setting was successful, false otherwise.
*/
public static function set_rate_limit( $action_id, $delay ) {
$option_name = self::storage_id( $action_id );
$next_try_allowed_at = time() + $delay;
return update_option( $option_name, $next_try_allowed_at );
}
}

View File

@ -302,7 +302,7 @@ class WC_Session_Handler extends WC_Session {
$wpdb->query( $wpdb->prepare( "DELETE FROM $this->_table WHERE session_expiry < %d", time() ) ); // @codingStandardsIgnoreLine.
if ( class_exists( 'WC_Cache_Helper' ) ) {
WC_Cache_Helper::incr_cache_prefix( WC_SESSION_CACHE_GROUP );
WC_Cache_Helper::invalidate_cache_group( WC_SESSION_CACHE_GROUP );
}
}

View File

@ -512,7 +512,7 @@ class WC_Shortcodes {
// Check if sku is a variation.
if ( isset( $atts['sku'] ) && $single_product->have_posts() && 'product_variation' === $single_product->post->post_type ) {
$variation = new WC_Product_Variation( $single_product->post->ID );
$variation = wc_get_product_object( 'variation', $single_product->post->ID );
$attributes = $variation->get_attributes();
// Set preselected id to be used by JS to provide context.

View File

@ -907,7 +907,7 @@ class WC_Tax {
}
wp_cache_delete( 'tax-rate-classes', 'taxes' );
WC_Cache_Helper::incr_cache_prefix( 'taxes' );
WC_Cache_Helper::invalidate_cache_group( 'taxes' );
return (bool) $delete;
}
@ -1025,7 +1025,7 @@ class WC_Tax {
$tax_rate_id = $wpdb->insert_id;
WC_Cache_Helper::incr_cache_prefix( 'taxes' );
WC_Cache_Helper::invalidate_cache_group( 'taxes' );
do_action( 'woocommerce_tax_rate_added', $tax_rate_id, $tax_rate );
@ -1082,7 +1082,7 @@ class WC_Tax {
)
);
WC_Cache_Helper::incr_cache_prefix( 'taxes' );
WC_Cache_Helper::invalidate_cache_group( 'taxes' );
do_action( 'woocommerce_tax_rate_updated', $tax_rate_id, $tax_rate );
}
@ -1101,7 +1101,7 @@ class WC_Tax {
$wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}woocommerce_tax_rate_locations WHERE tax_rate_id = %d;", $tax_rate_id ) );
$wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}woocommerce_tax_rates WHERE tax_rate_id = %d;", $tax_rate_id ) );
WC_Cache_Helper::incr_cache_prefix( 'taxes' );
WC_Cache_Helper::invalidate_cache_group( 'taxes' );
do_action( 'woocommerce_tax_rate_deleted', $tax_rate_id );
}
@ -1176,7 +1176,7 @@ class WC_Tax {
$wpdb->query( "INSERT INTO {$wpdb->prefix}woocommerce_tax_rate_locations ( location_code, tax_rate_id, location_type ) VALUES $sql;" ); // @codingStandardsIgnoreLine.
}
WC_Cache_Helper::incr_cache_prefix( 'taxes' );
WC_Cache_Helper::invalidate_cache_group( 'taxes' );
}
/**

View File

@ -528,8 +528,25 @@ class WC_Tracker {
$gross_total = 0;
}
$processing_gross_total = $wpdb->get_var(
"
SELECT
SUM( order_meta.meta_value ) AS 'gross_total'
FROM {$wpdb->prefix}posts AS orders
LEFT JOIN {$wpdb->prefix}postmeta AS order_meta ON order_meta.post_id = orders.ID
WHERE order_meta.meta_key = '_order_total'
AND orders.post_status = 'wc-processing'
GROUP BY order_meta.meta_key
"
);
if ( is_null( $processing_gross_total ) ) {
$processing_gross_total = 0;
}
return array(
'gross' => $gross_total,
'gross' => $gross_total,
'processing_gross' => $processing_gross_total,
);
}
@ -559,7 +576,25 @@ class WC_Tracker {
);
}
return $min_max;
$processing_min_max = $wpdb->get_row(
"
SELECT
MIN( post_date_gmt ) as 'processing_first', MAX( post_date_gmt ) as 'processing_last'
FROM {$wpdb->prefix}posts
WHERE post_type = 'shop_order'
AND post_status = 'wc-processing'
",
ARRAY_A
);
if ( is_null( $processing_min_max ) ) {
$processing_min_max = array(
'processing_first' => '-',
'processing_last' => '-',
);
}
return array_merge( $min_max, $processing_min_max );
}
}

View File

@ -96,7 +96,9 @@ class WC_Validation {
case 'NL':
$valid = (bool) preg_match( '/^([1-9][0-9]{3})(\s?)(?!SA|SD|SS)[A-Z]{2}$/i', $postcode );
break;
case 'SI':
$valid = (bool) preg_match( '/^([1-9][0-9]{3})$/', $postcode );
break;
default:
$valid = true;
break;

View File

@ -20,7 +20,7 @@ final class WooCommerce {
*
* @var string
*/
public $version = '3.8.0';
public $version = '3.9.0';
/**
* The single instance of the class.
@ -337,6 +337,11 @@ final class WooCommerce {
include_once WC_ABSPATH . 'includes/interfaces/class-wc-webhooks-data-store-interface.php';
include_once WC_ABSPATH . 'includes/interfaces/class-wc-queue-interface.php';
/**
* Core traits.
*/
include_once WC_ABSPATH . 'includes/traits/trait-wc-item-totals.php';
/**
* Abstract classes.
*/
@ -473,7 +478,7 @@ final class WooCommerce {
* @since 3.3.0
*/
private function theme_support_includes() {
if ( wc_is_active_theme( array( 'twentytwenty', 'twentynineteen', 'twentyseventeen', 'twentysixteen', 'twentyfifteen', 'twentyfourteen', 'twentythirteen', 'twentyeleven', 'twentytwelve', 'twentyten' ) ) ) {
if ( wc_is_wp_default_theme_active() ) {
switch ( get_template() ) {
case 'twentyten':
include_once WC_ABSPATH . 'includes/theme-support/class-wc-twenty-ten.php';

View File

@ -224,7 +224,6 @@ class WC_Coupon_Data_Store_CPT extends WC_Data_Store_WP implements WC_Coupon_Dat
* @since 3.0.0
*/
private function update_post_meta( &$coupon ) {
$updated_props = array();
$meta_key_to_props = array(
'discount_type' => 'discount_type',
'coupon_amount' => 'amount',
@ -278,7 +277,7 @@ class WC_Coupon_Data_Store_CPT extends WC_Data_Store_WP implements WC_Coupon_Dat
}
}
do_action( 'woocommerce_coupon_object_updated_props', $coupon, $updated_props );
do_action( 'woocommerce_coupon_object_updated_props', $coupon, $this->updated_props );
}
/**

View File

@ -842,10 +842,10 @@ class WC_Product_Data_Store_CPT extends WC_Data_Store_WP implements WC_Object_Da
wc_delete_product_transients( $product->get_id() );
if ( $product->get_parent_id( 'edit' ) ) {
wc_delete_product_transients( $product->get_parent_id( 'edit' ) );
WC_Cache_Helper::incr_cache_prefix( 'product_' . $product->get_parent_id( 'edit' ) );
WC_Cache_Helper::invalidate_cache_group( 'product_' . $product->get_parent_id( 'edit' ) );
}
WC_Cache_Helper::invalidate_attribute_count( array_keys( $product->get_attributes() ) );
WC_Cache_Helper::incr_cache_prefix( 'product_' . $product->get_id() );
WC_Cache_Helper::invalidate_cache_group( 'product_' . $product->get_id() );
}
/*
@ -1178,7 +1178,7 @@ class WC_Product_Data_Store_CPT extends WC_Data_Store_WP implements WC_Object_Da
if ( in_array( $possible_attribute, $existing_attributes ) ) { // phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict
continue;
}
$variation = new WC_Product_Variation();
$variation = wc_get_product_object( 'variation' );
$variation->set_parent_id( $product->get_id() );
$variation->set_attributes( $possible_attribute );
$variation_id = $variation->save();

View File

@ -361,7 +361,7 @@ class WC_Product_Variable_Data_Store_CPT extends WC_Product_Data_Store_CPT imple
$prices_array['price'][ $variation_id ] = wc_format_decimal( $price, wc_get_price_decimals() );
$prices_array['regular_price'][ $variation_id ] = wc_format_decimal( $regular_price, wc_get_price_decimals() );
$prices_array['sale_price'][ $variation_id ] = wc_format_decimal( $sale_price . '.00', wc_get_price_decimals() );
$prices_array['sale_price'][ $variation_id ] = wc_format_decimal( $sale_price, wc_get_price_decimals() );
$prices_array = apply_filters( 'woocommerce_variation_prices_array', $prices_array, $variation, $for_display );
}

View File

@ -48,10 +48,14 @@ class WC_Product_Variation_Data_Store_CPT extends WC_Product_Data_Store_CPT impl
$post_object = get_post( $product->get_id() );
if ( ! $post_object || ! in_array( $post_object->post_type, array( 'product', 'product_variation' ), true ) ) {
if ( ! $post_object ) {
return;
}
if ( 'product_variation' !== $post_object->post_type ) {
throw new Exception( 'Invalid product type: passed ID does not correspond to a product variation.' );
}
$product->set_props(
array(
'name' => $post_object->post_title,
@ -116,7 +120,7 @@ class WC_Product_Variation_Data_Store_CPT extends WC_Product_Data_Store_CPT impl
*/
public function create( &$product ) {
if ( ! $product->get_date_created() ) {
$product->set_date_created( current_time( 'timestamp', true ) );
$product->set_date_created( time() );
}
$new_title = $this->generate_product_title( $product );
@ -186,7 +190,7 @@ class WC_Product_Variation_Data_Store_CPT extends WC_Product_Data_Store_CPT impl
$product->save_meta_data();
if ( ! $product->get_date_created() ) {
$product->set_date_created( current_time( 'timestamp', true ) );
$product->set_date_created( time() );
}
$new_title = $this->generate_product_title( $product );

View File

@ -35,7 +35,7 @@ class WC_Shipping_Zone_Data_Store extends WC_Data_Store_WP implements WC_Shippin
$zone->save_meta_data();
$this->save_locations( $zone );
$zone->apply_changes();
WC_Cache_Helper::incr_cache_prefix( 'shipping_zones' );
WC_Cache_Helper::invalidate_cache_group( 'shipping_zones' );
WC_Cache_Helper::get_transient_version( 'shipping', true );
}
@ -60,7 +60,7 @@ class WC_Shipping_Zone_Data_Store extends WC_Data_Store_WP implements WC_Shippin
$zone->save_meta_data();
$this->save_locations( $zone );
$zone->apply_changes();
WC_Cache_Helper::incr_cache_prefix( 'shipping_zones' );
WC_Cache_Helper::invalidate_cache_group( 'shipping_zones' );
WC_Cache_Helper::get_transient_version( 'shipping', true );
}
@ -132,7 +132,7 @@ class WC_Shipping_Zone_Data_Store extends WC_Data_Store_WP implements WC_Shippin
$zone->set_id( null );
WC_Cache_Helper::incr_cache_prefix( 'shipping_zones' );
WC_Cache_Helper::invalidate_cache_group( 'shipping_zones' );
WC_Cache_Helper::get_transient_version( 'shipping', true );
do_action( 'woocommerce_delete_shipping_zone', $zone_id );

View File

@ -60,7 +60,7 @@ class WC_Webhook_Data_Store implements WC_Webhook_Data_Store_Interface {
$webhook->apply_changes();
$this->delete_transients( $webhook->get_status( 'edit' ) );
WC_Cache_Helper::incr_cache_prefix( 'webhooks' );
WC_Cache_Helper::invalidate_cache_group( 'webhooks' );
do_action( 'woocommerce_new_webhook', $webhook_id, $webhook );
}
@ -157,7 +157,7 @@ class WC_Webhook_Data_Store implements WC_Webhook_Data_Store_Interface {
$this->delete_transients( 'all' );
}
wp_cache_delete( $webhook->get_id(), 'webhooks' );
WC_Cache_Helper::incr_cache_prefix( 'webhooks' );
WC_Cache_Helper::invalidate_cache_group( 'webhooks' );
if ( 'active' === $webhook->get_status() && ( $trigger || $webhook->get_pending_delivery() ) ) {
$webhook->deliver_ping();
@ -184,7 +184,8 @@ class WC_Webhook_Data_Store implements WC_Webhook_Data_Store_Interface {
); // WPCS: cache ok, DB call ok.
$this->delete_transients( 'all' );
WC_Cache_Helper::incr_cache_prefix( 'webhooks' );
wp_cache_delete( $webhook->get_id(), 'webhooks' );
WC_Cache_Helper::invalidate_cache_group( 'webhooks' );
do_action( 'woocommerce_webhook_deleted', $webhook->get_id(), $webhook );
}

View File

@ -261,7 +261,7 @@ class WC_Email extends WC_Settings_API {
*/
public function handle_multipart( $mailer ) {
if ( $this->sending && 'multipart' === $this->get_email_type() ) {
$mailer->AltBody = wordwrap( // phpcs:ignore WordPress.NamingConventions.ValidVariableName.NotSnakeCaseMemberVar
$mailer->AltBody = wordwrap( // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
preg_replace( $this->plain_search, $this->plain_replace, wp_strip_all_tags( $this->get_content_plain() ) )
);
$this->sending = false;
@ -634,7 +634,7 @@ class WC_Email extends WC_Settings_API {
$message = apply_filters( 'woocommerce_mail_content', $this->style_inline( $message ) );
$mail_callback = apply_filters( 'woocommerce_mail_callback', 'wp_mail', $this );
$mail_callback_params = apply_filters( 'woocommerce_mail_callback_params', array( $to, $subject, $message, $headers, $attachments ), $this );
$return = call_user_func_array( $mail_callback, $mail_callback_params );
$return = $mail_callback( ...$mail_callback_params );
remove_filter( 'wp_mail_from', array( $this, 'get_from_address' ) );
remove_filter( 'wp_mail_from_name', array( $this, 'get_from_name' ) );

View File

@ -205,7 +205,7 @@ class WC_Gateway_BACS extends WC_Payment_Gateway {
$accounts = array();
// phpcs:disable WordPress.Security.NonceVerification.NoNonceVerification -- Nonce verification already handled in WC_Admin_Settings::save()
// phpcs:disable WordPress.Security.NonceVerification.Missing -- Nonce verification already handled in WC_Admin_Settings::save()
if ( isset( $_POST['bacs_account_name'] ) && isset( $_POST['bacs_account_number'] ) && isset( $_POST['bacs_bank_name'] )
&& isset( $_POST['bacs_sort_code'] ) && isset( $_POST['bacs_iban'] ) && isset( $_POST['bacs_bic'] ) ) {

View File

@ -173,13 +173,7 @@ abstract class WC_Product_Importer implements WC_Importer_Interface {
return new WP_Error( 'woocommerce_product_importer_invalid_type', __( 'Invalid product type.', 'woocommerce' ), array( 'status' => 401 ) );
}
$classname = WC_Product_Factory::get_classname_from_product_type( $data['type'] );
if ( ! class_exists( $classname ) ) {
$classname = 'WC_Product_Simple';
}
$product = new $classname( $id );
$product = wc_get_product_object( $data['type'], $id );
} elseif ( ! empty( $data['id'] ) ) {
$product = wc_get_product( $id );
@ -195,7 +189,7 @@ abstract class WC_Product_Importer implements WC_Importer_Interface {
);
}
} else {
$product = new WC_Product_Simple( $id );
$product = wc_get_product_object( 'simple', $id );
}
return apply_filters( 'woocommerce_product_import_get_product_object', $product, $data );

View File

@ -183,7 +183,7 @@ class WC_Product_CSV_Importer extends WC_Product_Importer {
// If we're not updating existing posts, we may need a placeholder product to map to.
if ( ! $this->params['update_existing'] ) {
$product = new WC_Product_Simple();
$product = wc_get_product_object( 'simple' );
$product->set_name( 'Import placeholder for ' . $id );
$product->set_status( 'importing' );
$product->add_meta_data( '_original_id', $id, true );
@ -200,7 +200,7 @@ class WC_Product_CSV_Importer extends WC_Product_Importer {
}
try {
$product = new WC_Product_Simple();
$product = wc_get_product_object( 'simple' );
$product->set_name( 'Import placeholder for ' . $value );
$product->set_status( 'importing' );
$product->set_sku( $value );
@ -254,7 +254,7 @@ class WC_Product_CSV_Importer extends WC_Product_Importer {
return $id_from_sku;
}
$product = new WC_Product_Simple();
$product = wc_get_product_object( 'simple' );
$product->set_name( 'Import placeholder for ' . $id );
$product->set_status( 'importing' );
$product->add_meta_data( '_original_id', $id, true );

View File

@ -2023,7 +2023,7 @@ class WC_API_Products extends WC_API_Resource {
// Clear transients
delete_transient( 'wc_attribute_taxonomies' );
WC_Cache_Helper::incr_cache_prefix( 'woocommerce-attributes' );
WC_Cache_Helper::invalidate_cache_group( 'woocommerce-attributes' );
$this->server->send_status( 201 );
@ -2109,7 +2109,7 @@ class WC_API_Products extends WC_API_Resource {
// Clear transients
delete_transient( 'wc_attribute_taxonomies' );
WC_Cache_Helper::incr_cache_prefix( 'woocommerce-attributes' );
WC_Cache_Helper::invalidate_cache_group( 'woocommerce-attributes' );
return $this->get_product_attribute( $id );
} catch ( WC_API_Exception $e ) {
@ -2171,7 +2171,7 @@ class WC_API_Products extends WC_API_Resource {
// Clear transients
delete_transient( 'wc_attribute_taxonomies' );
WC_Cache_Helper::incr_cache_prefix( 'woocommerce-attributes' );
WC_Cache_Helper::invalidate_cache_group( 'woocommerce-attributes' );
return array( 'message' => sprintf( __( 'Deleted %s', 'woocommerce' ), 'product_attribute' ) );
} catch ( WC_API_Exception $e ) {

View File

@ -2577,7 +2577,7 @@ class WC_API_Products extends WC_API_Resource {
// Clear transients.
wp_schedule_single_event( time(), 'woocommerce_flush_rewrite_rules' );
delete_transient( 'wc_attribute_taxonomies' );
WC_Cache_Helper::incr_cache_prefix( 'woocommerce-attributes' );
WC_Cache_Helper::invalidate_cache_group( 'woocommerce-attributes' );
$this->server->send_status( 201 );
@ -2664,7 +2664,7 @@ class WC_API_Products extends WC_API_Resource {
// Clear transients.
wp_schedule_single_event( time(), 'woocommerce_flush_rewrite_rules' );
delete_transient( 'wc_attribute_taxonomies' );
WC_Cache_Helper::incr_cache_prefix( 'woocommerce-attributes' );
WC_Cache_Helper::invalidate_cache_group( 'woocommerce-attributes' );
return $this->get_product_attribute( $id );
} catch ( WC_API_Exception $e ) {
@ -2727,7 +2727,7 @@ class WC_API_Products extends WC_API_Resource {
// Clear transients.
wp_schedule_single_event( time(), 'woocommerce_flush_rewrite_rules' );
delete_transient( 'wc_attribute_taxonomies' );
WC_Cache_Helper::incr_cache_prefix( 'woocommerce-attributes' );
WC_Cache_Helper::invalidate_cache_group( 'woocommerce-attributes' );
return array( 'message' => sprintf( __( 'Deleted %s', 'woocommerce' ), 'product_attribute' ) );
} catch ( WC_API_Exception $e ) {

View File

@ -107,7 +107,7 @@ abstract class ActionScheduler_Abstract_ListTable extends WP_List_Table {
* `_x` with some default (the package name)
*/
protected function translate( $text, $context = '' ) {
return _x( $text, $context, $this->package );
return $text;
}
/**
@ -462,7 +462,7 @@ abstract class ActionScheduler_Abstract_ListTable extends WP_List_Table {
echo '</select>';
}
submit_button( $this->translate( 'Filter' ), '', 'filter_action', false, array( 'id' => 'post-query-submit' ) );
submit_button( __( 'Filter', 'woocommerce' ), '', 'filter_action', false, array( 'id' => 'post-query-submit' ) );
echo '</div>';
}
@ -561,7 +561,8 @@ abstract class ActionScheduler_Abstract_ListTable extends WP_List_Table {
protected function display_header() {
echo '<h1 class="wp-heading-inline">' . esc_attr( $this->table_header ) . '</h1>';
if ( $this->get_request_search_query() ) {
echo '<span class="subtitle">' . esc_attr( $this->translate( sprintf( 'Search results for "%s"', $this->get_request_search_query() ) ) ) . '</span>';
/* translators: %s: search query */
echo '<span class="subtitle">' . esc_attr( sprintf( __( 'Search results for "%s"', 'woocommerce' ), $this->get_request_search_query() ) ) . '</span>';
}
echo '<hr class="wp-header-end">';
}
@ -651,6 +652,6 @@ abstract class ActionScheduler_Abstract_ListTable extends WP_List_Table {
* Get the text to display in the search box on the list table.
*/
protected function get_search_box_placeholder() {
return $this->translate( 'Search' );
return __( 'Search', 'woocommerce' );
}
}

View File

@ -19,7 +19,7 @@ class ActionScheduler_InvalidActionException extends \InvalidArgumentException i
*/
public static function from_decoding_args( $action_id ) {
$message = sprintf(
__( 'Action [%s] has invalid arguments. It cannot be JSON decoded to an array.', 'action-scheduler' ),
__( 'Action [%s] has invalid arguments. It cannot be JSON decoded to an array.', 'woocommerce' ),
$action_id
);

View File

@ -86,20 +86,20 @@ class ActionScheduler_ListTable extends ActionScheduler_Abstract_ListTable {
$this->logger = $logger;
$this->runner = $runner;
$this->table_header = __( 'Scheduled Actions', 'action-scheduler' );
$this->table_header = __( 'Scheduled Actions', 'woocommerce' );
$this->bulk_actions = array(
'delete' => __( 'Delete', 'action-scheduler' ),
'delete' => __( 'Delete', 'woocommerce' ),
);
$this->columns = array(
'hook' => __( 'Hook', 'action-scheduler' ),
'status' => __( 'Status', 'action-scheduler' ),
'args' => __( 'Arguments', 'action-scheduler' ),
'group' => __( 'Group', 'action-scheduler' ),
'recurrence' => __( 'Recurrence', 'action-scheduler' ),
'schedule' => __( 'Scheduled Date', 'action-scheduler' ),
'log_entries' => __( 'Log', 'action-scheduler' ),
'hook' => __( 'Hook', 'woocommerce' ),
'status' => __( 'Status', 'woocommerce' ),
'args' => __( 'Arguments', 'woocommerce' ),
'group' => __( 'Group', 'woocommerce' ),
'recurrence' => __( 'Recurrence', 'woocommerce' ),
'schedule' => __( 'Scheduled Date', 'woocommerce' ),
'log_entries' => __( 'Log', 'woocommerce' ),
);
$this->sort_by = array(
@ -119,19 +119,19 @@ class ActionScheduler_ListTable extends ActionScheduler_Abstract_ListTable {
if ( empty( $request_status ) ) {
$this->sort_by[] = 'status';
} elseif ( in_array( $request_status, array( 'in-progress', 'failed' ) ) ) {
$this->columns += array( 'claim_id' => __( 'Claim ID', 'action-scheduler' ) );
$this->columns += array( 'claim_id' => __( 'Claim ID', 'woocommerce' ) );
$this->sort_by[] = 'claim_id';
}
$this->row_actions = array(
'hook' => array(
'run' => array(
'name' => __( 'Run', 'action-scheduler' ),
'desc' => __( 'Process the action now as if it were run as part of a queue', 'action-scheduler' ),
'name' => __( 'Run', 'woocommerce' ),
'desc' => __( 'Process the action now as if it were run as part of a queue', 'woocommerce' ),
),
'cancel' => array(
'name' => __( 'Cancel', 'action-scheduler' ),
'desc' => __( 'Cancel the action now to avoid it being run in future', 'action-scheduler' ),
'name' => __( 'Cancel', 'woocommerce' ),
'desc' => __( 'Cancel the action now to avoid it being run in future', 'woocommerce' ),
'class' => 'cancel trash',
),
),
@ -140,31 +140,31 @@ class ActionScheduler_ListTable extends ActionScheduler_Abstract_ListTable {
self::$time_periods = array(
array(
'seconds' => YEAR_IN_SECONDS,
'names' => _n_noop( '%s year', '%s years', 'action-scheduler' ),
'names' => _n_noop( '%s year', '%s years', 'woocommerce' ),
),
array(
'seconds' => MONTH_IN_SECONDS,
'names' => _n_noop( '%s month', '%s months', 'action-scheduler' ),
'names' => _n_noop( '%s month', '%s months', 'woocommerce' ),
),
array(
'seconds' => WEEK_IN_SECONDS,
'names' => _n_noop( '%s week', '%s weeks', 'action-scheduler' ),
'names' => _n_noop( '%s week', '%s weeks', 'woocommerce' ),
),
array(
'seconds' => DAY_IN_SECONDS,
'names' => _n_noop( '%s day', '%s days', 'action-scheduler' ),
'names' => _n_noop( '%s day', '%s days', 'woocommerce' ),
),
array(
'seconds' => HOUR_IN_SECONDS,
'names' => _n_noop( '%s hour', '%s hours', 'action-scheduler' ),
'names' => _n_noop( '%s hour', '%s hours', 'woocommerce' ),
),
array(
'seconds' => MINUTE_IN_SECONDS,
'names' => _n_noop( '%s minute', '%s minutes', 'action-scheduler' ),
'names' => _n_noop( '%s minute', '%s minutes', 'woocommerce' ),
),
array(
'seconds' => 1,
'names' => _n_noop( '%s second', '%s seconds', 'action-scheduler' ),
'names' => _n_noop( '%s second', '%s seconds', 'woocommerce' ),
),
);
@ -191,7 +191,7 @@ class ActionScheduler_ListTable extends ActionScheduler_Abstract_ListTable {
private static function human_interval( $interval, $periods_to_include = 2 ) {
if ( $interval <= 0 ) {
return __( 'Now!', 'action-scheduler' );
return __( 'Now!', 'woocommerce' );
}
$output = '';
@ -204,7 +204,7 @@ class ActionScheduler_ListTable extends ActionScheduler_Abstract_ListTable {
if ( ! empty( $output ) ) {
$output .= ' ';
}
$output .= sprintf( _n( self::$time_periods[ $time_period_index ]['names'][0], self::$time_periods[ $time_period_index ]['names'][1], $periods_in_interval, 'action-scheduler' ), $periods_in_interval );
$output .= sprintf( _n( self::$time_periods[ $time_period_index ]['names'][0], self::$time_periods[ $time_period_index ]['names'][1], $periods_in_interval, 'woocommerce' ), $periods_in_interval );
$seconds_remaining -= $periods_in_interval * self::$time_periods[ $time_period_index ]['seconds'];
$periods_included++;
}
@ -224,15 +224,15 @@ class ActionScheduler_ListTable extends ActionScheduler_Abstract_ListTable {
$recurrence = $action->get_schedule();
if ( $recurrence->is_recurring() ) {
if ( method_exists( $recurrence, 'interval_in_seconds' ) ) {
return sprintf( __( 'Every %s', 'action-scheduler' ), self::human_interval( $recurrence->interval_in_seconds() ) );
return sprintf( __( 'Every %s', 'woocommerce' ), self::human_interval( $recurrence->interval_in_seconds() ) );
}
if ( method_exists( $recurrence, 'get_recurrence' ) ) {
return sprintf( __( 'Cron %s', 'action-scheduler' ), $recurrence->get_recurrence() );
return sprintf( __( 'Cron %s', 'woocommerce' ), $recurrence->get_recurrence() );
}
}
return __( 'Non-repeating', 'action-scheduler' );
return __( 'Non-repeating', 'woocommerce' );
}
/**
@ -318,7 +318,7 @@ class ActionScheduler_ListTable extends ActionScheduler_Abstract_ListTable {
if ( $this->store->get_claim_count() >= $this->runner->get_allowed_concurrent_batches() ) {
$this->admin_notices[] = array(
'class' => 'updated',
'message' => sprintf( __( 'Maximum simultaneous batches already in progress (%s queues). No actions will be processed until the current batches are complete.', 'action-scheduler' ), $this->store->get_claim_count() ),
'message' => sprintf( __( 'Maximum simultaneous batches already in progress (%s queues). No actions will be processed until the current batches are complete.', 'woocommerce' ), $this->store->get_claim_count() ),
);
}
@ -333,18 +333,18 @@ class ActionScheduler_ListTable extends ActionScheduler_Abstract_ListTable {
$class = 'updated';
switch ( $notification['row_action_type'] ) {
case 'run' :
$action_message_html = sprintf( __( 'Successfully executed action: %s', 'action-scheduler' ), $action_hook_html );
$action_message_html = sprintf( __( 'Successfully executed action: %s', 'woocommerce' ), $action_hook_html );
break;
case 'cancel' :
$action_message_html = sprintf( __( 'Successfully canceled action: %s', 'action-scheduler' ), $action_hook_html );
$action_message_html = sprintf( __( 'Successfully canceled action: %s', 'woocommerce' ), $action_hook_html );
break;
default :
$action_message_html = sprintf( __( 'Successfully processed change for action: %s', 'action-scheduler' ), $action_hook_html );
$action_message_html = sprintf( __( 'Successfully processed change for action: %s', 'woocommerce' ), $action_hook_html );
break;
}
} else {
$class = 'error';
$action_message_html = sprintf( __( 'Could not process change for action: "%s" (ID: %d). Error: %s', 'action-scheduler' ), $action_hook_html, esc_html( $notification['action_id'] ), esc_html( $notification['error_message'] ) );
$action_message_html = sprintf( __( 'Could not process change for action: "%s" (ID: %d). Error: %s', 'woocommerce' ), $action_hook_html, esc_html( $notification['action_id'] ), esc_html( $notification['error_message'] ) );
}
$action_message_html = apply_filters( 'action_scheduler_admin_notice_html', $action_message_html, $action, $notification );
@ -389,9 +389,9 @@ class ActionScheduler_ListTable extends ActionScheduler_Abstract_ListTable {
$schedule_display_string .= '<br/>';
if ( gmdate( 'U' ) > $next_timestamp ) {
$schedule_display_string .= sprintf( __( ' (%s ago)', 'action-scheduler' ), self::human_interval( gmdate( 'U' ) - $next_timestamp ) );
$schedule_display_string .= sprintf( __( ' (%s ago)', 'woocommerce' ), self::human_interval( gmdate( 'U' ) - $next_timestamp ) );
} else {
$schedule_display_string .= sprintf( __( ' (%s)', 'action-scheduler' ), self::human_interval( $next_timestamp - gmdate( 'U' ) ) );
$schedule_display_string .= sprintf( __( ' (%s)', 'woocommerce' ), self::human_interval( $next_timestamp - gmdate( 'U' ) ) );
}
return $schedule_display_string;
@ -528,6 +528,6 @@ class ActionScheduler_ListTable extends ActionScheduler_Abstract_ListTable {
* Get the text to display in the search box on the list table.
*/
protected function get_search_box_button_text() {
return __( 'Search hook, args and claim ID', 'action-scheduler' );
return __( 'Search hook, args and claim ID', 'woocommerce' );
}
}

View File

@ -59,44 +59,44 @@ abstract class ActionScheduler_Logger {
}
public function log_stored_action( $action_id ) {
$this->log( $action_id, __( 'action created', 'action-scheduler' ) );
$this->log( $action_id, __( 'action created', 'woocommerce' ) );
}
public function log_canceled_action( $action_id ) {
$this->log( $action_id, __( 'action canceled', 'action-scheduler' ) );
$this->log( $action_id, __( 'action canceled', 'woocommerce' ) );
}
public function log_started_action( $action_id ) {
$this->log( $action_id, __( 'action started', 'action-scheduler' ) );
$this->log( $action_id, __( 'action started', 'woocommerce' ) );
}
public function log_completed_action( $action_id ) {
$this->log( $action_id, __( 'action complete', 'action-scheduler' ) );
$this->log( $action_id, __( 'action complete', 'woocommerce' ) );
}
public function log_failed_action( $action_id, Exception $exception ) {
$this->log( $action_id, sprintf( __( 'action failed: %s', 'action-scheduler' ), $exception->getMessage() ) );
$this->log( $action_id, sprintf( __( 'action failed: %s', 'woocommerce' ), $exception->getMessage() ) );
}
public function log_timed_out_action( $action_id, $timeout ) {
$this->log( $action_id, sprintf( __( 'action timed out after %s seconds', 'action-scheduler' ), $timeout ) );
$this->log( $action_id, sprintf( __( 'action timed out after %s seconds', 'woocommerce' ), $timeout ) );
}
public function log_unexpected_shutdown( $action_id, $error ) {
if ( ! empty( $error ) ) {
$this->log( $action_id, sprintf( __( 'unexpected shutdown: PHP Fatal error %s in %s on line %s', 'action-scheduler' ), $error['message'], $error['file'], $error['line'] ) );
$this->log( $action_id, sprintf( __( 'unexpected shutdown: PHP Fatal error %s in %s on line %s', 'woocommerce' ), $error['message'], $error['file'], $error['line'] ) );
}
}
public function log_reset_action( $action_id ) {
$this->log( $action_id, __( 'action reset', 'action_scheduler' ) );
$this->log( $action_id, __( 'action reset', 'woocommerce' ) );
}
public function log_ignored_action( $action_id ) {
$this->log( $action_id, __( 'action ignored', 'action-scheduler' ) );
$this->log( $action_id, __( 'action ignored', 'woocommerce' ) );
}
public function log_failed_fetch_action( $action_id ) {
$this->log( $action_id, __( 'There was a failure fetching this action', 'action-scheduler' ) );
$this->log( $action_id, __( 'There was a failure fetching this action', 'woocommerce' ) );
}
}

View File

@ -107,7 +107,7 @@ class ActionScheduler_QueueRunner extends ActionScheduler_Abstract_QueueRunner {
public function add_wp_cron_schedule( $schedules ) {
$schedules['every_minute'] = array(
'interval' => 60, // in seconds
'display' => __( 'Every minute' ),
'display' => __( 'Every minute', 'woocommerce' ),
);
return $schedules;

View File

@ -149,7 +149,7 @@ abstract class ActionScheduler_Store {
protected function get_scheduled_date_string( ActionScheduler_Action $action, DateTime $scheduled_date = NULL ) {
$next = null === $scheduled_date ? $action->get_schedule()->next() : $scheduled_date;
if ( ! $next ) {
throw new InvalidArgumentException( __( 'Invalid schedule. Cannot save action.', 'action-scheduler' ) );
throw new InvalidArgumentException( __( 'Invalid schedule. Cannot save action.', 'woocommerce' ) );
}
$next->setTimezone( new DateTimeZone( 'UTC' ) );
@ -166,7 +166,7 @@ abstract class ActionScheduler_Store {
protected function get_scheduled_date_string_local( ActionScheduler_Action $action, DateTime $scheduled_date = NULL ) {
$next = null === $scheduled_date ? $action->get_schedule()->next() : $scheduled_date;
if ( ! $next ) {
throw new InvalidArgumentException( __( 'Invalid schedule. Cannot save action.', 'action-scheduler' ) );
throw new InvalidArgumentException( __( 'Invalid schedule. Cannot save action.', 'woocommerce' ) );
}
ActionScheduler_TimezoneHelper::set_local_timezone( $next );
@ -178,11 +178,11 @@ abstract class ActionScheduler_Store {
*/
public function get_status_labels() {
return array(
self::STATUS_COMPLETE => __( 'Complete', 'action-scheduler' ),
self::STATUS_PENDING => __( 'Pending', 'action-scheduler' ),
self::STATUS_RUNNING => __( 'In-progress', 'action-scheduler' ),
self::STATUS_FAILED => __( 'Failed', 'action-scheduler' ),
self::STATUS_CANCELED => __( 'Canceled', 'action-scheduler' ),
self::STATUS_COMPLETE => __( 'Complete', 'woocommerce' ),
self::STATUS_PENDING => __( 'Pending', 'woocommerce' ),
self::STATUS_RUNNING => __( 'In-progress', 'woocommerce' ),
self::STATUS_FAILED => __( 'Failed', 'woocommerce' ),
self::STATUS_CANCELED => __( 'Canceled', 'woocommerce' ),
);
}

View File

@ -28,7 +28,7 @@ class ActionScheduler_WPCLI_QueueRunner extends ActionScheduler_Abstract_QueueRu
public function __construct( ActionScheduler_Store $store = null, ActionScheduler_FatalErrorMonitor $monitor = null, ActionScheduler_QueueCleaner $cleaner = null ) {
if ( ! ( defined( 'WP_CLI' ) && WP_CLI ) ) {
/* translators: %s php class name */
throw new Exception( sprintf( __( 'The %s class can only be run within WP CLI.', 'action-scheduler' ), __CLASS__ ) );
throw new Exception( sprintf( __( 'The %s class can only be run within WP CLI.', 'woocommerce' ), __CLASS__ ) );
}
parent::__construct( $store, $monitor, $cleaner );
@ -56,9 +56,9 @@ class ActionScheduler_WPCLI_QueueRunner extends ActionScheduler_Abstract_QueueRu
$too_many = $claim_count >= $this->get_allowed_concurrent_batches();
if ( $too_many ) {
if ( $force ) {
WP_CLI::warning( __( 'There are too many concurrent batches, but the run is forced to continue.', 'action-scheduler' ) );
WP_CLI::warning( __( 'There are too many concurrent batches, but the run is forced to continue.', 'woocommerce' ) );
} else {
WP_CLI::error( __( 'There are too many concurrent batches.', 'action-scheduler' ) );
WP_CLI::error( __( 'There are too many concurrent batches.', 'woocommerce' ) );
}
}
@ -89,7 +89,7 @@ class ActionScheduler_WPCLI_QueueRunner extends ActionScheduler_Abstract_QueueRu
protected function setup_progress_bar() {
$count = count( $this->actions );
$this->progress_bar = \WP_CLI\Utils\make_progress_bar(
sprintf( _n( 'Running %d action', 'Running %d actions', $count, 'action-scheduler' ), number_format_i18n( $count ) ),
sprintf( _n( 'Running %d action', 'Running %d actions', $count, 'woocommerce' ), number_format_i18n( $count ) ),
$count
);
}
@ -106,7 +106,7 @@ class ActionScheduler_WPCLI_QueueRunner extends ActionScheduler_Abstract_QueueRu
foreach ( $this->actions as $action_id ) {
// Error if we lost the claim.
if ( ! in_array( $action_id, $this->store->find_actions_by_claim_id( $this->claim->get_id() ) ) ) {
WP_CLI::warning( __( 'The claim has been lost. Aborting current batch.', 'action-scheduler' ) );
WP_CLI::warning( __( 'The claim has been lost. Aborting current batch.', 'woocommerce' ) );
break;
}
@ -132,7 +132,7 @@ class ActionScheduler_WPCLI_QueueRunner extends ActionScheduler_Abstract_QueueRu
*/
public function before_execute( $action_id ) {
/* translators: %s refers to the action ID */
WP_CLI::log( sprintf( __( 'Started processing action %s', 'action-scheduler' ), $action_id ) );
WP_CLI::log( sprintf( __( 'Started processing action %s', 'woocommerce' ), $action_id ) );
}
/**
@ -149,7 +149,7 @@ class ActionScheduler_WPCLI_QueueRunner extends ActionScheduler_Abstract_QueueRu
$action = $this->store->fetch_action( $action_id );
}
/* translators: %s refers to the action ID */
WP_CLI::log( sprintf( __( 'Completed processing action %s with hook: %s', 'action-scheduler' ), $action_id, $action->get_hook() ) );
WP_CLI::log( sprintf( __( 'Completed processing action %s with hook: %s', 'woocommerce' ), $action_id, $action->get_hook() ) );
}
/**
@ -164,7 +164,7 @@ class ActionScheduler_WPCLI_QueueRunner extends ActionScheduler_Abstract_QueueRu
public function action_failed( $action_id, $exception ) {
WP_CLI::error(
/* translators: %1$s refers to the action ID, %2$s refers to the Exception message */
sprintf( __( 'Error processing action %1$s: %2$s', 'action-scheduler' ), $action_id, $exception->getMessage() ),
sprintf( __( 'Error processing action %1$s: %2$s', 'woocommerce' ), $action_id, $exception->getMessage() ),
false
);
}
@ -176,11 +176,12 @@ class ActionScheduler_WPCLI_QueueRunner extends ActionScheduler_Abstract_QueueRu
*/
protected function stop_the_insanity( $sleep_time = 0 ) {
if ( 0 < $sleep_time ) {
WP_CLI::warning( sprintf( 'Stopped the insanity for %d %s', $sleep_time, _n( 'second', 'seconds', $sleep_time ) ) );
/* translators: 1: sleep time 2: time unit */
WP_CLI::warning( sprintf( __( 'Stopped the insanity for %$1d %$2s', 'woocommerce' ), $sleep_time, _n( 'second', 'seconds', $sleep_time, 'woocommerce' ) ) );
sleep( $sleep_time );
}
WP_CLI::warning( __( 'Attempting to reduce used memory...', 'action-scheduler' ) );
WP_CLI::warning( __( 'Attempting to reduce used memory...', 'woocommerce' ) );
/**
* @var $wpdb \wpdb

View File

@ -84,7 +84,7 @@ class ActionScheduler_WPCLI_Scheduler_command extends WP_CLI_Command {
WP_CLI::log(
sprintf(
/* translators: %d refers to how many scheduled taks were found to run */
_n( 'Found %d scheduled task', 'Found %d scheduled tasks', $total, 'action-scheduler' ),
_n( 'Found %d scheduled task', 'Found %d scheduled tasks', $total, 'woocommerce' ),
number_format_i18n( $total )
)
);
@ -101,7 +101,7 @@ class ActionScheduler_WPCLI_Scheduler_command extends WP_CLI_Command {
WP_CLI::log(
sprintf(
/* translators: %d refers to the total number of batches executed */
_n( '%d batch executed.', '%d batches executed.', $batches_completed, 'action-scheduler' ),
_n( '%d batch executed.', '%d batches executed.', $batches_completed, 'woocommerce' ),
number_format_i18n( $batches_completed )
)
);
@ -120,7 +120,7 @@ class ActionScheduler_WPCLI_Scheduler_command extends WP_CLI_Command {
WP_CLI::error(
sprintf(
/* translators: %s refers to the exception error message. */
__( 'There was an error running the action scheduler: %s', 'action-scheduler' ),
__( 'There was an error running the action scheduler: %s', 'woocommerce' ),
$e->getMessage()
)
);
@ -137,7 +137,7 @@ class ActionScheduler_WPCLI_Scheduler_command extends WP_CLI_Command {
WP_CLI::success(
sprintf(
/* translators: %d refers to the total number of taskes completed */
_n( '%d scheduled task completed.', '%d scheduled tasks completed.', $actions_completed, 'action-scheduler' ),
_n( '%d scheduled task completed.', '%d scheduled tasks completed.', $actions_completed, 'woocommerce' ),
number_format_i18n( $actions_completed )
)
);

View File

@ -97,14 +97,14 @@ class ActionScheduler_wcSystemStatus {
<table class="wc_status_table widefat" cellspacing="0">
<thead>
<tr>
<th colspan="5" data-export-label="Action Scheduler"><h2><?php esc_html_e( 'Action Scheduler', 'action-scheduler' ); ?><?php echo wc_help_tip( esc_html__( 'This section shows scheduled action counts.', 'action-scheduler' ) ); ?></h2></th>
<th colspan="5" data-export-label="Action Scheduler"><h2><?php esc_html_e( 'Action Scheduler', 'woocommerce' ); ?><?php echo wc_help_tip( esc_html__( 'This section shows scheduled action counts.', 'woocommerce' ) ); ?></h2></th>
</tr>
<tr>
<td><strong><?php esc_html_e( 'Action Status', 'action-scheduler' ); ?></strong></td>
<td><strong><?php esc_html_e( 'Action Status', 'woocommerce' ); ?></strong></td>
<td class="help">&nbsp;</td>
<td><strong><?php esc_html_e( 'Count', 'action-scheduler' ); ?></strong></td>
<td><strong><?php esc_html_e( 'Oldest Scheduled Date', 'action-scheduler' ); ?></strong></td>
<td><strong><?php esc_html_e( 'Newest Scheduled Date', 'action-scheduler' ); ?></strong></td>
<td><strong><?php esc_html_e( 'Count', 'woocommerce' ); ?></strong></td>
<td><strong><?php esc_html_e( 'Oldest Scheduled Date', 'woocommerce' ); ?></strong></td>
<td><strong><?php esc_html_e( 'Newest Scheduled Date', 'woocommerce' ); ?></strong></td>
</tr>
</thead>
<tbody>

View File

@ -30,7 +30,7 @@ class ActionScheduler_wpPostStore extends ActionScheduler_Store {
do_action( 'action_scheduler_stored_action', $post_id );
return $post_id;
} catch ( Exception $e ) {
throw new RuntimeException( sprintf( __('Error saving action: %s', 'action-scheduler'), $e->getMessage() ), 0 );
throw new RuntimeException( sprintf( __('Error saving action: %s', 'woocommerce'), $e->getMessage() ), 0 );
}
}
@ -54,7 +54,7 @@ class ActionScheduler_wpPostStore extends ActionScheduler_Store {
remove_filter( 'pre_wp_unique_post_slug', array( $this, 'set_unique_post_slug' ), 10 );
if ( is_wp_error($post_id) || empty($post_id) ) {
throw new RuntimeException(__('Unable to save action.', 'action-scheduler'));
throw new RuntimeException(__('Unable to save action.', 'woocommerce'));
}
return $post_id;
}
@ -275,7 +275,7 @@ class ActionScheduler_wpPostStore extends ActionScheduler_Store {
protected function get_query_actions_sql( array $query, $select_or_count = 'select' ) {
if ( ! in_array( $select_or_count, array( 'select', 'count' ) ) ) {
throw new InvalidArgumentException(__('Invalid schedule. Cannot save action.', 'action-scheduler'));
throw new InvalidArgumentException(__('Invalid schedule. Cannot save action.', 'woocommerce'));
}
$query = wp_parse_args( $query, array(
@ -448,7 +448,7 @@ class ActionScheduler_wpPostStore extends ActionScheduler_Store {
public function cancel_action( $action_id ) {
$post = get_post($action_id);
if ( empty($post) || ($post->post_type != self::POST_TYPE) ) {
throw new InvalidArgumentException(sprintf(__('Unidentified action %s', 'action-scheduler'), $action_id));
throw new InvalidArgumentException(sprintf(__('Unidentified action %s', 'woocommerce'), $action_id));
}
do_action( 'action_scheduler_canceled_action', $action_id );
add_filter( 'pre_wp_unique_post_slug', array( $this, 'set_unique_post_slug' ), 10, 5 );
@ -459,7 +459,7 @@ class ActionScheduler_wpPostStore extends ActionScheduler_Store {
public function delete_action( $action_id ) {
$post = get_post($action_id);
if ( empty($post) || ($post->post_type != self::POST_TYPE) ) {
throw new InvalidArgumentException(sprintf(__('Unidentified action %s', 'action-scheduler'), $action_id));
throw new InvalidArgumentException(sprintf(__('Unidentified action %s', 'woocommerce'), $action_id));
}
do_action( 'action_scheduler_deleted_action', $action_id );
wp_delete_post($action_id, TRUE);
@ -485,7 +485,7 @@ class ActionScheduler_wpPostStore extends ActionScheduler_Store {
public function get_date_gmt( $action_id ) {
$post = get_post($action_id);
if ( empty($post) || ($post->post_type != self::POST_TYPE) ) {
throw new InvalidArgumentException(sprintf(__('Unidentified action %s', 'action-scheduler'), $action_id));
throw new InvalidArgumentException(sprintf(__('Unidentified action %s', 'woocommerce'), $action_id));
}
if ( $post->post_status == 'publish' ) {
return as_get_datetime_object($post->post_modified_gmt);
@ -597,7 +597,7 @@ class ActionScheduler_wpPostStore extends ActionScheduler_Store {
// Run the query and gather results.
$rows_affected = $wpdb->query( $wpdb->prepare( "{$update} {$where} {$order}", $params ) );
if ( $rows_affected === false ) {
throw new RuntimeException( __( 'Unable to claim actions. Database error.', 'action-scheduler' ) );
throw new RuntimeException( __( 'Unable to claim actions. Database error.', 'woocommerce' ) );
}
return (int) $rows_affected;
@ -617,7 +617,7 @@ class ActionScheduler_wpPostStore extends ActionScheduler_Store {
protected function get_actions_by_group( $group, $limit, DateTime $date ) {
// Ensure the group exists before continuing.
if ( ! term_exists( $group, self::GROUP_TAXONOMY )) {
throw new InvalidArgumentException( sprintf( __( 'The group "%s" does not exist.', 'action-scheduler' ), $group ) );
throw new InvalidArgumentException( sprintf( __( 'The group "%s" does not exist.', 'woocommerce' ), $group ) );
}
// Set up a query for post IDs to use later.
@ -678,7 +678,7 @@ class ActionScheduler_wpPostStore extends ActionScheduler_Store {
$sql = $wpdb->prepare( $sql, array( $claim->get_id() ) );
$result = $wpdb->query($sql);
if ( $result === false ) {
throw new RuntimeException( sprintf( __('Unable to unlock claim %s. Database error.', 'action-scheduler'), $claim->get_id() ) );
throw new RuntimeException( sprintf( __('Unable to unlock claim %s. Database error.', 'woocommerce'), $claim->get_id() ) );
}
}
@ -692,7 +692,7 @@ class ActionScheduler_wpPostStore extends ActionScheduler_Store {
$sql = $wpdb->prepare( $sql, $action_id, self::POST_TYPE );
$result = $wpdb->query($sql);
if ( $result === false ) {
throw new RuntimeException( sprintf( __('Unable to unlock claim on action %s. Database error.', 'action-scheduler'), $action_id ) );
throw new RuntimeException( sprintf( __('Unable to unlock claim on action %s. Database error.', 'woocommerce'), $action_id ) );
}
}
@ -703,7 +703,7 @@ class ActionScheduler_wpPostStore extends ActionScheduler_Store {
$sql = $wpdb->prepare( $sql, self::STATUS_FAILED, $action_id, self::POST_TYPE );
$result = $wpdb->query($sql);
if ( $result === false ) {
throw new RuntimeException( sprintf( __('Unable to mark failure on action %s. Database error.', 'action-scheduler'), $action_id ) );
throw new RuntimeException( sprintf( __('Unable to mark failure on action %s. Database error.', 'woocommerce'), $action_id ) );
}
}
@ -727,7 +727,7 @@ class ActionScheduler_wpPostStore extends ActionScheduler_Store {
$status = $this->get_post_column( $action_id, 'post_status' );
if ( $status === null ) {
throw new InvalidArgumentException( __( 'Invalid action ID. No status found.', 'action-scheduler' ) );
throw new InvalidArgumentException( __( 'Invalid action ID. No status found.', 'woocommerce' ) );
}
return $this->get_action_status_by_post_status( $status );
@ -755,7 +755,7 @@ class ActionScheduler_wpPostStore extends ActionScheduler_Store {
public function mark_complete( $action_id ) {
$post = get_post($action_id);
if ( empty($post) || ($post->post_type != self::POST_TYPE) ) {
throw new InvalidArgumentException(sprintf(__('Unidentified action %s', 'action-scheduler'), $action_id));
throw new InvalidArgumentException(sprintf(__('Unidentified action %s', 'woocommerce'), $action_id));
}
add_filter( 'wp_insert_post_data', array( $this, 'filter_insert_post_data' ), 10, 1 );
add_filter( 'pre_wp_unique_post_slug', array( $this, 'set_unique_post_slug' ), 10, 5 );

View File

@ -33,8 +33,8 @@ class ActionScheduler_wpPostStore_PostStatusRegistrar {
*/
protected function post_status_failed_labels() {
$labels = array(
'label' => _x( 'Failed', 'post' ),
'label_count' => _n_noop( 'Failed <span class="count">(%s)</span>', 'Failed <span class="count">(%s)</span>' ),
'label' => _x( 'Failed', 'post', 'woocommerce' ),
'label_count' => _n_noop( 'Failed <span class="count">(%s)</span>', 'Failed <span class="count">(%s)</span>', 'woocommerce' ),
);
return apply_filters( 'action_scheduler_post_status_failed_labels', $labels );
@ -47,11 +47,10 @@ class ActionScheduler_wpPostStore_PostStatusRegistrar {
*/
protected function post_status_running_labels() {
$labels = array(
'label' => _x( 'In-Progress', 'post' ),
'label_count' => _n_noop( 'In-Progress <span class="count">(%s)</span>', 'In-Progress <span class="count">(%s)</span>' ),
'label' => _x( 'In-Progress', 'post', 'woocommerce' ),
'label_count' => _n_noop( 'In-Progress <span class="count">(%s)</span>', 'In-Progress <span class="count">(%s)</span>', 'woocommerce' ),
);
return apply_filters( 'action_scheduler_post_status_running_labels', $labels );
}
}

View File

@ -30,9 +30,9 @@ class ActionScheduler_wpPostStore_PostTypeRegistrar {
'name' => __( 'Scheduled Actions', 'woocommerce' ),
'singular_name' => __( 'Scheduled Action', 'woocommerce' ),
'menu_name' => _x( 'Scheduled Actions', 'Admin menu name', 'woocommerce' ),
'add_new' => __( 'Add', 'action-scheduler' ),
'add_new' => __( 'Add', 'woocommerce' ),
'add_new_item' => __( 'Add New Scheduled Action', 'woocommerce' ),
'edit' => __( 'Edit', 'action-scheduler' ),
'edit' => __( 'Edit', 'woocommerce' ),
'edit_item' => __( 'Edit Scheduled Action', 'woocommerce' ),
'new_item' => __( 'New Scheduled Action', 'woocommerce' ),
'view' => __( 'View Action', 'woocommerce' ),
@ -47,4 +47,4 @@ class ActionScheduler_wpPostStore_PostTypeRegistrar {
return $args;
}
}

View File

@ -11,7 +11,7 @@ class ActionScheduler_wpPostStore_TaxonomyRegistrar {
protected function taxonomy_args() {
$args = array(
'label' => __('Action Group', 'action-scheduler'),
'label' => __('Action Group', 'woocommerce'),
'public' => false,
'hierarchical' => false,
'show_admin_column' => true,
@ -23,4 +23,3 @@ class ActionScheduler_wpPostStore_TaxonomyRegistrar {
return $args;
}
}

View File

@ -40,7 +40,9 @@ class WC_Shortcode_Cart {
}
if ( $address['country'] ) {
WC()->customer->set_billing_location( $address['country'], $address['state'], $address['postcode'], $address['city'] );
if ( ! WC()->customer->get_billing_first_name() ) {
WC()->customer->set_billing_location( $address['country'], $address['state'], $address['postcode'], $address['city'] );
}
WC()->customer->set_shipping_location( $address['country'], $address['state'], $address['postcode'], $address['city'] );
} else {
WC()->customer->set_billing_address_to_base();

View File

@ -153,7 +153,7 @@ class WC_Shortcode_Checkout {
$held_stock = ( $hold_stock_minutes > 0 ) ? wc_get_held_stock_quantity( $product, $order->get_id() ) : 0;
$required_stock = $quantities[ $product->get_stock_managed_by_id() ];
if ( $product->get_stock_quantity() < ( $held_stock + $required_stock ) ) {
if ( ! apply_filters( 'woocommerce_pay_order_product_has_enough_stock', ( $product->get_stock_quantity() >= ( $held_stock + $required_stock ) ), $product, $order ) ) {
/* translators: 1: product name 2: quantity in stock */
throw new Exception( sprintf( __( 'Sorry, we do not have enough "%1$s" in stock to fulfill your order (%2$s available). We apologize for any inconvenience caused.', 'woocommerce' ), $product->get_name(), wc_format_stock_quantity_for_display( $product->get_stock_quantity() - $held_stock, $product ) ) );
}

View File

@ -115,8 +115,8 @@ class WC_Shortcode_Products {
'limit' => '-1', // Results limit.
'columns' => '', // Number of columns.
'rows' => '', // Number of rows. If defined, limit will be ignored.
'orderby' => 'title', // menu_order, title, date, rand, price, popularity, rating, or id.
'order' => 'ASC', // ASC or DESC.
'orderby' => '', // menu_order, title, date, rand, price, popularity, rating, or id.
'order' => '', // ASC or DESC.
'ids' => '', // Comma separated IDs.
'skus' => '', // Comma separated SKUs.
'category' => '', // Comma separated category slugs or ids.
@ -179,7 +179,7 @@ class WC_Shortcode_Products {
'post_status' => 'publish',
'ignore_sticky_posts' => true,
'no_found_rows' => false === wc_string_to_bool( $this->attributes['paginate'] ),
'orderby' => empty( $_GET['orderby'] ) ? $this->attributes['orderby'] : wc_clean( wp_unslash( $_GET['orderby'] ) ), // phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification
'orderby' => empty( $_GET['orderby'] ) ? $this->attributes['orderby'] : wc_clean( wp_unslash( $_GET['orderby'] ) ), // phpcs:ignore WordPress.Security.NonceVerification.Recommended
);
$orderby_value = explode( '-', $query_args['orderby'] );
@ -189,7 +189,7 @@ class WC_Shortcode_Products {
$query_args['order'] = $order;
if ( wc_string_to_bool( $this->attributes['paginate'] ) ) {
$this->attributes['page'] = absint( empty( $_GET['product-page'] ) ? 1 : $_GET['product-page'] ); // WPCS: input var ok, CSRF ok.
$this->attributes['page'] = absint( empty( $_GET['product-page'] ) ? 1 : $_GET['product-page'] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
}
if ( ! empty( $this->attributes['rows'] ) ) {
@ -643,7 +643,7 @@ class WC_Shortcode_Products {
if ( wc_get_loop_prop( 'total' ) ) {
foreach ( $products->ids as $product_id ) {
$GLOBALS['post'] = get_post( $product_id ); // WPCS: override ok.
$GLOBALS['post'] = get_post( $product_id ); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
setup_postdata( $GLOBALS['post'] );
// Set custom product visibility when quering hidden products.
@ -657,7 +657,7 @@ class WC_Shortcode_Products {
}
}
$GLOBALS['post'] = $original_post; // WPCS: override ok.
$GLOBALS['post'] = $original_post; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
woocommerce_product_loop_end();
// Fire standard shop loop hooks when paginating results so we can show result counts and so on.

View File

@ -27,7 +27,7 @@ class WC_Site_Tracking {
}
// Check if tracking is actively being opted into.
$is_obw_opting_in = isset( $_POST['wc_tracker_checkbox'] ) && 'yes' === sanitize_text_field( $_POST['wc_tracker_checkbox'] ); // phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification, WordPress.Security.ValidatedSanitizedInput
$is_obw_opting_in = isset( $_POST['wc_tracker_checkbox'] ) && 'yes' === sanitize_text_field( $_POST['wc_tracker_checkbox'] ); // phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput
/**
* Don't track users who haven't opted-in to tracking or aren't in

View File

@ -41,7 +41,7 @@ class WC_Admin_Setup_Wizard_Tracking {
* @return string
*/
public function get_current_step() {
return isset( $_GET['step'] ) ? sanitize_key( $_GET['step'] ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification
return isset( $_GET['step'] ) ? sanitize_key( $_GET['step'] ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
}
/**
@ -76,7 +76,7 @@ class WC_Admin_Setup_Wizard_Tracking {
* @return void
*/
public function track_start( $option, $value ) {
if ( 'yes' !== $value || empty( $_GET['page'] ) || 'wc-setup' !== $_GET['page'] ) { // phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification
if ( 'yes' !== $value || empty( $_GET['page'] ) || 'wc-setup' !== $_GET['page'] ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
return;
}
@ -116,7 +116,7 @@ class WC_Admin_Setup_Wizard_Tracking {
add_action( 'admin_init', array( $this, 'track_next_steps' ), 1 );
}
if ( empty( $_POST['save_step'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification
if ( empty( $_POST['save_step'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
return;
}
@ -148,7 +148,7 @@ class WC_Admin_Setup_Wizard_Tracking {
* @return void
*/
public function track_store_setup() {
// phpcs:disable WordPress.Security.NonceVerification.NoNonceVerification, WordPress.Security.ValidatedSanitizedInput
// phpcs:disable WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput
$properties = array(
'country' => isset( $_POST['store_country'] ) ? sanitize_text_field( $_POST['store_country'] ) : '',
'currency_code' => isset( $_POST['currency_code'] ) ? sanitize_text_field( $_POST['currency_code'] ) : '',
@ -192,12 +192,10 @@ class WC_Admin_Setup_Wizard_Tracking {
$created_accounts[] = 'ppec_paypal';
}
// phpcs:disable WordPress.Security.NonceVerification.NoNonceVerification, WordPress.Security.ValidatedSanitizedInput
$properties = array(
'selected_gateways' => implode( ', ', $selected_gateways ),
'created_accounts' => implode( ', ', $created_accounts ),
);
// phpcs:enable
WC_Tracks::record_event( 'obw_payments', $properties );
}
@ -208,7 +206,7 @@ class WC_Admin_Setup_Wizard_Tracking {
* @return void
*/
public function track_shipping() {
// phpcs:disable WordPress.Security.NonceVerification.NoNonceVerification, WordPress.Security.ValidatedSanitizedInput
// phpcs:disable WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput
$properties = array(
'weight_unit' => isset( $_POST['weight_unit'] ) ? sanitize_text_field( wp_unslash( $_POST['weight_unit'] ) ) : '',
'dimension_unit' => isset( $_POST['dimension_unit'] ) ? sanitize_text_field( wp_unslash( $_POST['dimension_unit'] ) ) : '',
@ -226,7 +224,7 @@ class WC_Admin_Setup_Wizard_Tracking {
* @return void
*/
public function track_recommended() {
// phpcs:disable WordPress.Security.NonceVerification.NoNonceVerification
// phpcs:disable WordPress.Security.NonceVerification.Missing
$properties = array(
'setup_storefront' => isset( $_POST['setup_storefront_theme'] ) && 'yes' === $_POST['setup_storefront_theme'],
'setup_automated_tax' => isset( $_POST['setup_automated_taxes'] ) && 'yes' === $_POST['setup_automated_taxes'],

View File

@ -27,7 +27,7 @@ class WC_Extensions_Tracking {
* Send a Tracks event when an Extensions page is viewed.
*/
public function track_extensions_page() {
// phpcs:disable WordPress.Security.NonceVerification.NoNonceVerification
// phpcs:disable WordPress.Security.NonceVerification.Recommended
$event = 'extensions_view';
$properties = array(
'section' => empty( $_REQUEST['section'] ) ? '_featured' : wc_clean( wp_unslash( $_REQUEST['section'] ) ),

Some files were not shown because too many files have changed in this diff Show More