Merge branch 'master' into fix/25561

This commit is contained in:
Claudio Sanches 2020-06-23 11:23:29 -03:00 committed by GitHub
commit 3bb7f30c01
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
351 changed files with 15473 additions and 1686 deletions

26
.distignore Normal file
View File

@ -0,0 +1,26 @@
.*
.*/
*.lock
*.md
*.zip
/bin/
/build/
/node_modules/
/tests/
babel.config.js
CHANGELOG.txt
composer.*
contributors.html
docker-compose.yaml
Dockerfile
Gruntfile.js
none
package-lock.json
package.json
packages/woocommerce-admin/docs
phpcs.xml
phpunit.xml
phpunit.xml.dist
README.md
renovate.json
webpack.config.js

View File

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

35
.eslintrc.js Normal file
View File

@ -0,0 +1,35 @@
/** @format */
const baseConfig = require( '@woocommerce/e2e-environment' ).esLintConfig;
module.exports = {
...baseConfig,
root: true,
env: {
...baseConfig.env,
browser: true,
es6: true,
node: true
},
globals: {
...baseConfig.globals,
wp: true,
wpApiSettings: true,
wcSettings: true,
es6: true
},
rules: {
camelcase: 0,
indent: 0,
'max-len': [ 2, { 'code': 140 } ],
'no-console': 1
},
parser: 'babel-eslint',
parserOptions: {
ecmaVersion: 8,
ecmaFeatures: {
modules: true,
experimentalObjectRestSpread: true,
jsx: true
}
},
};

View File

@ -1,48 +1,7 @@
<!-- This form is for reporting bugs and issues specific to the WooCommerce plugin. This is not a support portal. If you need technical support from a human being, please submit a ticket via the helpdesk instead: https://woocommerce.com/contact-us/ -->
<!-- This form is for other issue types specific to the WooCommerce plugin. This is not a support portal. -->
<!-- Usage questions can also be directed to the public support forum here: https://wordpress.org/support/plugin/woocommerce, unless this is a question about a premium extension in which case you should use the helpdesk. -->
**Prerequisites (mark completed items with an [x]):**
- [ ] I have checked that my issue type is not listed here https://github.com/woocommerce/woocommerce/issues/new/choose
- [ ] My issue is not a security issue, support request, bug report, enhancement or feature request (Please use the link above if it is).
<!-- If you have a feature request, submit it to: http://ideas.woocommerce.com/forums/133476-woocommerce -->
<!-- If you are a developer who needs a new filter/hook raise a PR instead :) -->
<!-- Please be as descriptive as possible; issues lacking the below details, or for any other reason than to report a bug, may be closed without action. -->
## Prerequisites
<!-- MARK COMPLETED ITEMS WITH AN [x] -->
- [ ] I have searched for similar issues in both open and closed tickets and cannot find a duplicate
- [ ] The issue still exists against the latest `master` branch of WooCommerce on Github (this is **not** the same version as on WordPress.org!)
- [ ] I have attempted to find the simplest possible steps to reproduce the issue
- [ ] I have included a failing test as a pull request (Optional)
## Steps to reproduce the issue
<!-- We need to be able to reproduce the bug in order to fix it so please be descriptive! -->
1.
2.
3.
## Expected/actual behavior
When I follow those steps, I see...
I was expecting to see...
## Isolating the problem
<!-- MARK COMPLETED ITEMS WITH AN [x] -->
- [ ] This bug happens with only WooCommerce plugin active
- [ ] This bug happens with a default WordPress theme active, or [Storefront](https://woocommerce.com/storefront/)
- [ ] I can reproduce this bug consistently using the steps above
## WordPress Environment
<details>
```
Copy and paste the system status report from **WooCommerce > System Status** in WordPress admin here.
```
</details>
**Issue Description:**

View File

@ -1,5 +1,5 @@
---
name: "\U0001F46E Security issue"
name: "\U0001F512 Security issue"
about: Please report security issues *only* via https://www.hackerone.com
title: ''
labels: ''

View File

@ -1,10 +1,18 @@
---
name: "\U0001F47D External issues"
about: Please report WooCommerce REST API or WooCommerce Gutenberg Products Blocks issues directly to their respective repositories.
about: Please report WooCommerce REST API, WooCommerce Admin or WooCommerce Gutenberg Products Blocks issues directly to their respective repositories.
title: ''
labels: ''
assignees: ''
---
Please report WooCommerce REST API (https://github.com/woocommerce/woocommerce-rest-api) or WooCommerce Gutenberg Products Blocks (https://github.com/woocommerce/woocommerce-gutenberg-products-block) issues directly to their respective repositories.
Please report issues for the following features directly to their respective repositories.
WooCommerce REST API: https://github.com/woocommerce/woocommerce-rest-api
WooCommerce Admin: https://github.com/woocommerce/woocommerce-admin
WooCommerce Gutenberg Products Blocks: https://github.com/woocommerce/woocommerce-gutenberg-products-block
Action Scheduler: https://github.com/woocommerce/action-scheduler

View File

@ -16,10 +16,13 @@ Usage docs can be found here: https://docs.woocommerce.com/
If you have a problem, you may want to start with the self help guide here: https://docs.woocommerce.com/document/woocommerce-self-service-guide/
**Technical support for premium extensions or if you're a WooCommerce.com customer**
from a human being - submit a ticket via the helpdesk
Contact WooCommerce support by opening a ticket.
https://woocommerce.com/contact-us/
**For help with custom code**
WooCommerce Slack Community: https://woocommerce.com/community-slack/ in the `#developers` channel.
**General usage and development questions**
- WooCommerce Slack Community: https://woocommerce.com/community-slack/
- WordPress.org Forums: https://wordpress.org/support/plugin/woocommerce
- The WooCommerce Help and Share Facebook group
- The Official WooCommerce Facebook Group https://www.facebook.com/groups/advanced.woocommerce/

View File

@ -8,11 +8,30 @@ assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is. Please be as descriptive as possible; issues lacking detail, or for any other reason than to report a bug, may be closed without action.
Please provide us with the information requested in this bug report. Without these details, we won't be able to fully evaluate this issue.
Bug reports lacking detail, or for any other reason than to report a bug, may be closed without action.
**To Reproduce**
Steps to reproduce the behavior:
<!-- This template is for confirmed bugs only. If you have a support request or custom code related question please see our docs or use our forums, helpdesk, or Slack Community! https://github.com/woocommerce/woocommerce/issues/new?assignees=&labels=&template=3-Support.md&title= -->
<!-- Make sure to look through the existing issues to see whether your bug has already been submitted. Feel free to contribute to any existing issues. -->
<!-- Search tip: You can filter our issues using our component labels https://github.com/woocommerce/woocommerce/labels?q=component -->
<!-- Search tip: Make use of GitHub's search syntax to refine your search https://help.github.com/en/github/searching-for-information-on-github/searching-issues-and-pull-requests -->
**Prerequisites (mark completed items with an [x]):**
- [ ] I have have carried out troubleshooting steps and I believe I have found a bug.
- [ ] I have searched for similar bugs in both open and closed issues and cannot find a duplicate.
**Describe the bug**
A clear and concise description of what the bug is.
**Expected behavior**
A clear and concise description of what you expected to happen.
**Actual behavior**
A clear and concise description of what actually happens. Please be as descriptive as possible;
**Steps to reproduce the bug (We need to be able to reproduce the bug in order to fix it.)**
Steps to reproduce the bug:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
@ -21,8 +40,7 @@ Steps to reproduce the behavior:
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Expected behavior**
A clear and concise description of what you expected to happen.
<!-- Please try testing your site for theme and plugins conflict. To do that deactivate all plugins except for WooCommerce and switch to a default WordPress theme or [Storefront](https://en-gb.wordpress.org/themes/storefront/). Then test again. If the issue is resolved with the default theme and all plugins deactivated, it means that one of your plugins or a theme is causing the issue. You will then need to enable it one by one and test every time you do that in order to figure out which plugin is causing the issue. -->
**Isolating the problem (mark completed items with an [x]):**
- [ ] I have deactivated other plugins and confirmed this bug occurs when only WooCommerce plugin is active.
@ -30,8 +48,11 @@ A clear and concise description of what you expected to happen.
- [ ] I can reproduce this bug consistently using the steps above.
**WordPress Environment**
We use the [WooCommerce System Status Report](https://docs.woocommerce.com/document/understanding-the-woocommerce-system-status-report/) to help us evaluate the issue.
Without this report we won't be able to fully evaluate this issue.
<details>
```
Copy and paste the system status report from **WooCommerce > System Status** in WordPress admin.
The System Status Report is found in your WordPress admin under **WooCommerce > Status**.
Please select “Get system report”, then “Copy for support”, and then paste it here.
```
</details>

View File

@ -8,6 +8,10 @@ assignees: ''
---
<!-- Make sure to look through existing issues to see whether your idea is already being discussed. Feel free to contribute to any existing issues. -->
<!-- Search tip: You can filter issues using our enhancement label https://github.com/woocommerce/woocommerce/issues?q=is%3Aissue+label%3Aenhancement -->
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

View File

@ -8,6 +8,10 @@ assignees: ''
---
<!-- Make sure to look through existing issues to see whether your idea is already being discussed. Feel free to contribute to any existing issues. -->
<!-- Search tip: You can filter issues using our enhancement label https://github.com/woocommerce/woocommerce/issues?q=is%3Aissue+label%3Aenhancement -->
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

25
.github/workflows/build-release.yml vendored Normal file
View File

@ -0,0 +1,25 @@
name: Build release asset
on:
release:
types: [published]
jobs:
build:
name: Build release asset
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Build
id: build
uses: woocommerce/action-build@master
with:
generate-zip: true
- name: Upload release asset
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ github.event.release.upload_url }}
asset_path: ${{ steps.build.outputs.zip_path }}
asset_name: woocommerce.zip
asset_content_type: application/zip

15
.gitignore vendored
View File

@ -10,9 +10,10 @@ project.properties
*.sublime-project
*.sublime-workspace
.sublimelinterrc
*.swp
# Grunt
/node_modules/
node_modules/
none
# Sass
@ -42,8 +43,12 @@ tests/cli/vendor
# Unit tests
/tmp
/tests/bin/tmp
/tests/e2e-tests/config/local-*.json
/tests/e2e-tests/config/local.json
/tests/e2e/config/local-*.json
/tests/e2e/config/local.json
/tests/e2e/docker
/tests/e2e/env/docker/wp-cli/initialize.sh
/tests/e2e/env/build/
/tests/e2e/env/build-module/
# Logs
/logs
@ -51,6 +56,7 @@ tests/cli/vendor
# Composer
/vendor/
contributors.md
contributors.html
# Packages
/packages/*
@ -61,3 +67,6 @@ contributors.md
# Language files
i18n/languages/woocommerce.pot
# Build
build/

View File

@ -1,26 +0,0 @@
{
"boss": true,
"curly": true,
"eqeqeq": true,
"eqnull": true,
"es3": true,
"expr": true,
"immed": true,
"noarg": true,
"onevar": true,
"quotmark": "single",
"trailing": true,
"undef": true,
"unused": true,
"multistr": true,
"browser": true,
"globals": {
"_": false,
"Backbone": false,
"jQuery": false,
"JSON": false,
"wp": false
}
}

View File

@ -1,19 +1,18 @@
version: ~> 1.0
language: php
dist: xenial
cache:
directories:
- vendor
- $HOME/.composer/cache
# Since Xenial services are not started by default, we need to instruct it below to start.
services:
- xvfb
- mysql
- docker
- docker-compose
sudo: false
cache:
directories:
- vendor
- $HOME/.composer/cache
# Test main supported versions of PHP against latest WP.
php:
@ -28,39 +27,39 @@ env:
# Additional tests against stable PHP (min version is 7.0)
# and code coverage report.
matrix:
jobs:
fast_finish: true
include:
- name: "Coding standard check"
php: 7.4
env: WP_VERSION=latest WP_MULTISITE=0 RUN_PHPCS=1
- name: "E2E tests"
- name: "Core E2E Tests"
php: 7.4
env: WP_VERSION=latest WP_MULTISITE=0 RUN_E2E=1
script:
- composer require wp-cli/i18n-command
- npm run build
- docker-compose up --build -d
- bash tests/bin/run-e2e-CI.sh
- npm run build:packages
- npm install jest --global
- npm run docker:up
- npm run test:e2e
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"
- npm run docker:down
- name: "WP Nightly"
php: 7.4
env: WP_VERSION=nightly WP_MULTISITE=0
- name: "WP latest - 1"
- name: "WP Latest"
php: 7.2
env: WP_VERSION=5.4 WP_MULTISITE=0
- name: "WP Latest - 1"
php: 7.2
env: WP_VERSION=5.3 WP_MULTISITE=0
- name: "WP latest - 2"
- name: "WP Latest - 2"
php: 7.2
env: WP_VERSION=5.2 WP_MULTISITE=0
- name: "WP 5.1"
php: 7.2
env: WP_VERSION=5.1 WP_MULTISITE=0
- name: "WP 5.0"
php: 7.0
env: WP_VERSION=5.0 WP_MULTISITE=0
- name: "Code Standards"
php: 7.4
env: WP_VERSION=latest WP_MULTISITE=0 RUN_PHPCS=1
- name: "Code Coverage"
php: 7.4
env: WP_VERSION=latest WP_MULTISITE=0 RUN_CODE_COVERAGE=1
allow_failures:
- php: 7.4
env: WP_VERSION=latest WP_MULTISITE=0 RUN_CODE_COVERAGE=1

View File

@ -1,5 +1,128 @@
== Changelog ==
= 4.2.0 - 2020-06-02 =
**WooCommerce**
* Enhancement - Added Ghanaian regions to the state dropdown. #26273
* Enhancement - Added Mozambique provinces to the state dropdown. #26162
* Enhancement - Added support for the new group descriptions available on WordPress privacy exporters as of WP 5.3. #25575
* Fix - Fixed false positives when checking if uploads directory is public. #26600
* Fix - Introduced a new admin body class for supporting styling issues in WP 5.3+. #26251
* Fix - Removed case conversion of meta keys from CSV imports. #25517
* Fix - Allow schedule coupons via CRUD. #26387
* Fix - Password visibility toggle when password strength check fails. #26132
* Fix - Cross-sell placement when product has no description. #26334
* Fix - Display of the rate limit warning during payment method creation. #26411
* Fix - Made the shipping zone matching query's `zone_id` field more specific. #26308
* Fix - Corrected the display of RTL languages on the WooCommerce.com addons page. #26080
* Fix - Removed the postcode field for Ghana. #26272
* Fix - Made the hiding of state fields more explicit for Germany, Denmark, and Sweden. #25598
* Fix - Ensured that global attribute prefixes are passed to the `woocommerce_attribute_label` filter. #26022
* Dev - Increased WordPress minimum version to 5.2 according to policy. #26550
* Dev - Added the customer as a third argument to the `woocommerce_matched_rates` filter. #26361
* Dev - Introduced `woocommerce_menu_order_count` filter. #26044
* Dev - Introduced `should_send_ajax_request.adding_to_cart `cart event to allow short-circuiting cart addition. #25760
* Dev - Made the jQuery selector for checkout form rows less specific. #25654
* Dev - Changed the `{site_address}` placeholder to `{site_url}` for clarity. #25630
* Dev - Deprecated `.wp-policy-help` and replaced with with the `.privacy-policy-tutorial` and `.wp-suggested-text` classes added in WP 5.1. #26072
* Dev - Updated `automattic/jetpack-autoloader` to 1.7.0. #26559
* Dev - Add a way to fetch basic object data. #26025
**REST API 1.0.8**
* Enhancement - Add support for trash status for products in V2 and V3 API. #184
* Dev - Updated minimum PHP requirement to 7.0 to keep up with WooCommerce Core.
* Dev - Fixed failing unit tests. #105
**WooCommerce Admin 1.2.3**
* Enhancement - Add onboarding payments note #4157
* Enhancement - Marketing Inbox Note #4030
* Performance - Use Route based code splitting to reduce bundle size #4094
* Performance - trim down inbox note API request. #3977
* Fix - Proper display of elements in wc-admin pages when in a RTL environment. #4051
* Fix - Update UX when knowledge base articles fail to retrieve #4133
* Fix - Updated messaging after last step in OBW. #4148
* Fix - Reset profiler when visiting old OBW URL #4166.
* Fix - Dashboard flash before OBW chunk loads #4259
* Tweak - Enable the default homepage template to be filtered #4072
* Tweak - Create admin note if Jetpack or WooCommerce Services plugin doesn't get installed due to an error during OBW #3888
* Tweak - Update Email Marketing note. #4167
* Tweak - Adjust "demo products" verbiage to "Sample Products" #4184
* Tweak - Don't reschedule imports on failed imports #4263
* Tweak - Remove obsolete inbox messages #4182
* Tweak - Updates to WooCommerce Payments in Setup Checklist #4293
* Dev - Make query selector for admin alerts more specific #4289
* Dev - Guard against null themes in OBW #4244
* Dev - Update wcadmin db version after db callback #4323
* Dev - Only migrate options on version change #4324
* Dev - Use `PAGE_ROOT` constant to reduce redundant strings #4238
* Dev - Decouple Plugins DataStore from onboarding feature #4048
* Dev - Move API out of Onboarding #4093
* Dev - Add Profiler Step View Tracks #4141
* Dev - Add React Testing Library #4221
* Dev - Add List and Link components to Storybook #4219
* Dev - Cast Shipping Total to float #4042
* Dev - Dynamic Currency with Context API #4027
* Dev - Remove Duplicate array entry #4049
= 4.1.1 - 2020-05-19 =
* Enhancement - Added notice about public uploads directory. #26207
* Tweak - Disallow directory listing in woocommerce_uploads when "Redirect only" it's the selected download method. #26399
* Fix - Added correct handling of nonces to database update notice dismissal. #26500
* Dev - Updated WooCommerce admin version to 1.1.3 and Action Scheduler to 3.1.6.
* Dev - Add prop `isEnabled` and a function to dynamically enable tracks. #26493
**WooCommerce Admin**
* Tweak - Onboarding: Add Jetpack flow back to onboarding profiler. #4382
* Fix - Respect tracking opt-in before new page load. #4368
**ActionScheduler**
* Fix - Shutdown deprecated notice changed to a warning when as_* functions called without data store initialization. #546
= 4.1.0 - 2020-05-05 =
**WooCommerce**
* Enhancement - Update dependency woocommerce/woocommerce-admin to v1.1.0 #26057
* Enhancement - Updated jetpack-autoloader to 1.6 and woocommerce-blocks to 2.5.16. #26099
* Enhancement - Added option to ignore discounts from cart's total amount to enable free shipping. #24776
* Enhancement - Changed show password icon color to a darker grey hue. #25625
* Enhancement - Use new Setup Wizard for all users. #26016
* Security - Fixed unescaped meta data while duplicating products. Reported by Slavco.
* Tweak - Show notice for WP min version to WP 5.2. #26094
* Tweak - Improve the string for untested WooCommerce extensions in the system status page to avoid confusion. #25904
* Tweak - Updated KZT (₸) symbol. #25609
* Tweak - Trim whitespaces and strip slashes from MaxMind License Key. #25466
* Tweak - Updated "Help" tabs documentation. #25826
* Tweak - Update serbian currency symbol to рсд from дин. #25885
* Fix - Password visibility toggle to hide password again from text. #25627
* Fix - Undefined property error when attempting to modify the coupon post meta. #25755
* Fix - Remove some of the individual rounding logic to make sure we round at certain places only. #25800
* Fix - Order totals calculation if the order contains taxable and non-taxable products and percentage coupons. #25092
* Fix - Wording for cancelled order email. #25316
* Fix - Removed guided tour videos link on setup wizard (since current link only redirects to the docs). #25823
* Fix - Add RTL style to the onboarding wizard. #25835
* Fix - Trigger change and set val to qty on the frontend so that it properly updates event handlers. #25903
* Fix - Corrected the way percent coupons apply remainders across the order. #25943
* Fix - Clarified the error messaging for WooCommerce.com package update failures. #26034
* Fix - Enforce per user usage limit check for a coupon on guest users based on email. #26066
* Fix - Remove elements with style=display:none explicitly to address a regression causing broken email html. #26075
* Dev - Added woocommerce_can_restock_refunded_items filter. #25728
* Dev - Added woocommerce_order_get_tax_location filter. #25727
* Dev - Updated stock handling to prevent race conditions when orders come in at the same time. #25708
* Dev - Updated /myaccount/form-login.php to use consistent kebab-case class names for woocommerce-form-row. #25668
* Dev - Add filter woocommerce_product_upsells_products_heading to allow heading modification without having to override the template file. #25628
* Dev - Added woocommerce_order_get_tax_location filter. #25727
* Dev - Added the get_woocommerce_currency_symbols function to allow develops to get an array of all the currency symbol registered with WooCommerce. #25733
* Dev - Changed string typed label_class to array in checkout fields.
* Dev - Added "woocommerce_emogrifier" action before the content of the emails is "emogrified". #25801
* Dev - Add Ability to Filter Event Props. #25851
* Dev - Updated the unit test install script to support paths to MySQL sockets that contain spaces. #25923
* Dev - Made the default test source folders support the system tmp folder. #25923
* Dev - Add cart & checkout block/shortcode info to tracker data. #25932
* Dev - Make WC_Product_Data_Store_CPT::update_product_stock operations atomic. #26039
* Dev - Adds usage data for the of cart & checkout blocks (currently in development in WooCommmerce Blocks plugin) to the WC Tracker snapshot. #26084
* Dev - Implement some additional tracks for coupons, orders, and products. #26085
= 4.0.1 - 2020-03-18 =
**WooCommerce**

View File

@ -1 +1 @@
FROM wordpress:5.4.0
FROM wordpress:5.4.2

View File

@ -1,4 +1,3 @@
/* jshint node:true */
module.exports = function( grunt ) {
'use strict';
var sass = require( 'node-sass' );
@ -14,12 +13,9 @@ module.exports = function( grunt ) {
php: 'includes'
},
// JavaScript linting with JSHint.
jshint: {
options: {
jshintrc: '.jshintrc'
},
all: [
// JavaScript linting with ESLint.
eslint: {
src: [
'<%= dirs.js %>/admin/*.js',
'!<%= dirs.js %>/admin/*.min.js',
'<%= dirs.js %>/frontend/*.js',
@ -192,62 +188,13 @@ module.exports = function( grunt ) {
},
js: {
files: [
'GruntFile.js',
'<%= dirs.js %>/admin/*js',
'<%= dirs.js %>/frontend/*js',
'!<%= dirs.js %>/admin/*.min.js',
'!<%= dirs.js %>/frontend/*.min.js'
],
tasks: ['jshint', 'uglify']
}
},
// Exec shell commands.
shell: {
options: {
stdout: true,
stderr: true
},
e2e_test: {
command: 'npm run --silent test:single tests/e2e-tests/' + grunt.option( 'file' )
},
e2e_tests: {
command: 'npm run --silent test'
},
e2e_tests_grep: {
command: 'npm run --silent test:grep "' + grunt.option( 'grep' ) + '"'
},
contributors: {
command: [
'echo "Generating contributor list since <%= fromDate %>"',
'./node_modules/.bin/githubcontrib --owner woocommerce --repo woocommerce --fromDate <%= fromDate %>' +
' --authToken <%= authToken %> --cols 6 --sortBy contributions --format md --sortOrder desc' +
' --showlogin true --sha <%= sha %> --filter renovate-bot > contributors.md'
].join( '&&' )
}
},
prompt: {
contributors: {
options: {
questions: [
{
config: 'fromDate',
type: 'input',
message: 'What date (YYYY-MM-DD) should we get contributions since?'
},
{
config: 'sha',
type: 'input',
message: 'What branch should we get contributors from?'
},
{
config: 'authToken',
type: 'input',
message: '(optional) Provide a personal access token.' +
' This will allow 5000 requests per hour rather than 60 - use if nothing is generated.'
}
]
}
tasks: ['eslint','uglify']
}
},
@ -286,19 +233,17 @@ module.exports = function( grunt ) {
// Load NPM tasks to be used here.
grunt.loadNpmTasks( 'grunt-sass' );
grunt.loadNpmTasks( 'grunt-shell' );
grunt.loadNpmTasks( 'grunt-phpcs' );
grunt.loadNpmTasks( 'grunt-rtlcss' );
grunt.loadNpmTasks( 'grunt-postcss' );
grunt.loadNpmTasks( 'grunt-stylelint' );
grunt.loadNpmTasks( 'grunt-contrib-jshint' );
grunt.loadNpmTasks( 'gruntify-eslint' );
grunt.loadNpmTasks( 'grunt-contrib-uglify' );
grunt.loadNpmTasks( 'grunt-contrib-cssmin' );
grunt.loadNpmTasks( 'grunt-contrib-concat' );
grunt.loadNpmTasks( 'grunt-contrib-copy' );
grunt.loadNpmTasks( 'grunt-contrib-watch' );
grunt.loadNpmTasks( 'grunt-contrib-clean' );
grunt.loadNpmTasks( 'grunt-prompt' );
// Register tasks.
grunt.registerTask( 'default', [
@ -307,7 +252,7 @@ module.exports = function( grunt ) {
]);
grunt.registerTask( 'js', [
'jshint',
'eslint',
'uglify:admin',
'uglify:frontend'
]);
@ -332,25 +277,8 @@ module.exports = function( grunt ) {
'css'
]);
grunt.registerTask( 'contributors', [
'prompt:contributors',
'shell:contributors'
]);
// Only an alias to 'default' task.
grunt.registerTask( 'dev', [
'default'
]);
grunt.registerTask( 'e2e-tests', [
'shell:e2e_tests'
]);
grunt.registerTask( 'e2e-tests-grep', [
'shell:e2e_tests_grep'
]);
grunt.registerTask( 'e2e-test', [
'shell:e2e_test'
]);
};

View File

@ -15,7 +15,7 @@ Welcome to the WooCommerce repository on GitHub. Here you can browse the source,
If you are not a developer, please use the [WooCommerce plugin page](https://wordpress.org/plugins/woocommerce/) on WordPress.org.
## Documentation
* [WooCommerce Documentation](https://docs.woocommerce.com/documentation/plugins/woocommerce/)
* [WooCommerce Documentation](https://docs.woocommerce.com/)
* [WooCommerce Developer Documentation](https://github.com/woocommerce/woocommerce/wiki)
* [WooCommerce Code Reference](https://docs.woocommerce.com/wc-apidocs/)
* [WooCommerce REST API Docs](https://woocommerce.github.io/woocommerce-rest-api-docs/)

View File

@ -9,7 +9,10 @@
div.woocommerce-message {
overflow: hidden;
position: relative;
border-left-color: #cc99c2 !important;
&.updated {
border-left-color: #cc99c2 !important;
}
}
p.woocommerce-actions,

View File

@ -541,9 +541,12 @@
.woocommerce-message {
position: relative;
border-left-color: #cc99c2 !important;
overflow: hidden;
&.updated {
border-left-color: #cc99c2 !important;
}
a.skip,
a.docs {
text-decoration: none !important;
@ -637,7 +640,7 @@ mark.amount {
}
}
.branch-5-3 {
.wc-wp-version-gte-53 {
.woocommerce-help-tip {
font-size: 1.2em;
@ -2167,7 +2170,7 @@ ul.wc_coupon_list_block {
}
}
.branch-5-3 {
.wc-wp-version-gte-53 {
.widefat {
@ -4123,7 +4126,7 @@ img.help_tip {
}
}
.branch-5-3 {
.wc-wp-version-gte-53 {
.woocommerce {
@ -6694,7 +6697,7 @@ table.bar_chart {
min-width: 400px !important;
}
.branch-5-3 {
.wc-wp-version-gte-53 {
.select2-results {
@ -6831,7 +6834,7 @@ table.bar_chart {
@each $name, $color in $wp_admin_colors {
&-#{$name}.branch-5-3 {
&-#{$name}.wc-wp-version-gte-53 {
.select2-dropdown {
border-color: $color;

56
assets/css/privacy.scss Normal file
View File

@ -0,0 +1,56 @@
/**
* privacy.scss
* Styles applied to the Privacy Policy Guide to support WooCommerce content.
* Adds support for styling ul/ol elements.
*/
/**
* Styling begins
*/
// Support for indented bullet-lists.
.policy-text ul {
list-style: disc;
}
.policy-text ol {
list-style: decimal;
}
.policy-text ul li,
.policy-text ol li {
margin-left: 2em;
}
// Pre-5.4 support for italics.
.branch-5-2 .policy-text ul,
.branch-5-2 .policy-text ol,
.branch-5-3 .policy-text ul,
.branch-5-3 .policy-text ol {
font-style: italic;
}
// 5.4 support for white background and padding.
.branch-5-4 .policy-text ul:not(.privacy-policy-tutorial):not(.wp-policy-help),
.branch-5-4 .policy-text ol:not(.privacy-policy-tutorial):not(.wp-policy-help) {
background-color: #fff;
margin: 0;
padding: 1em;
}
.branch-5-4 .hide-privacy-policy-tutorial ul:not(.privacy-policy-tutorial):not(.wp-policy-help),
.branch-5-4 .hide-privacy-policy-tutorial ol:not(.privacy-policy-tutorial):not(.wp-policy-help) {
margin: 1em 0;
padding: 0;
}
.policy-text p:not(.privacy-policy-tutorial):not(.wp-policy-help) + ul:not(.privacy-policy-tutorial):not(.wp-policy-help),
.policy-text p:not(.privacy-policy-tutorial):not(.wp-policy-help) + ol:not(.privacy-policy-tutorial):not(.wp-policy-help),
.policy-text ul:not(.privacy-policy-tutorial):not(.wp-policy-help) + p:not(.privacy-policy-tutorial):not(.wp-policy-help),
.policy-text ul:not(.privacy-policy-tutorial):not(.wp-policy-help) + ul:not(.privacy-policy-tutorial):not(.wp-policy-help),
.policy-text ul:not(.privacy-policy-tutorial):not(.wp-policy-help) + ol:not(.privacy-policy-tutorial):not(.wp-policy-help),
.policy-text ol:not(.privacy-policy-tutorial):not(.wp-policy-help) + p:not(.privacy-policy-tutorial):not(.wp-policy-help),
.policy-text ol:not(.privacy-policy-tutorial):not(.wp-policy-help) + ul:not(.privacy-policy-tutorial):not(.wp-policy-help),
.policy-text ol:not(.privacy-policy-tutorial):not(.wp-policy-help) + ol:not(.privacy-policy-tutorial):not(.wp-policy-help) {
padding-top: 0;
}

View File

@ -170,6 +170,7 @@ a.button {
}
.wc-block-grid__products {
.wc-block-grid__product-onsale {
position: absolute;
top: 0;
@ -296,6 +297,7 @@ a.button {
}
#site-content {
.post-inner {
padding-top: 0;
}
@ -319,7 +321,7 @@ a.button {
/* Make thumbnails in the gallery affect parent's height and wrapping */
.flex-control-nav::after {
clear: both;
content: '';
content: "";
display: table;
}
@ -501,7 +503,7 @@ dl.variation,
.product_meta {
clear: both;
font-size: .7em;
font-size: 0.7em;
padding-top: 0.5em;
margin-top: 3rem;
}
@ -726,7 +728,7 @@ a.reset_variations {
margin: 4rem 0 2rem;
/* reset description tab width to full width */
#tab-description{
#tab-description {
h2,
p {
@ -836,7 +838,7 @@ a.reset_variations {
}
}
.comment-form-rating{
.comment-form-rating {
label {
max-width: 58rem;
@ -910,7 +912,7 @@ a.reset_variations {
}
.comment-form-author,
.comment-form-email{
.comment-form-email {
float: none;
margin-left: auto;
}
@ -924,6 +926,8 @@ a.reset_variations {
.related.products,
.up-sells {
clear: both;
ul.products {
display: flex;
justify-content: space-evenly;
@ -1185,6 +1189,7 @@ a.reset_variations {
}
form {
h3 {
margin-top: 0;
}
@ -1215,7 +1220,7 @@ a.reset_variations {
}
}
table.account-orders-table:not( .has-background ) {
table.account-orders-table:not(.has-background) {
tbody {
@ -1343,6 +1348,7 @@ a.reset_variations {
}
tbody {
tr {
border-top: 1px solid #eee;
}
@ -1399,7 +1405,7 @@ a.reset_variations {
width: 100%;
}
input[type='radio'].shipping_method {
input[type="radio"].shipping_method {
display: none;
& + label {
@ -1713,9 +1719,9 @@ a.reset_variations {
}
tbody::after {
content: '';
display: block;
height: 2rem;
content: "";
display: block;
height: 2rem;
}
.woocommerce-Price-amount {
@ -1723,7 +1729,7 @@ a.reset_variations {
}
.cart-subtotal,
.order-total{
.order-total {
border-top: 1px solid #ddd;
}
}
@ -1774,6 +1780,7 @@ a.reset_variations {
}
.woocommerce-form-login {
p.form-row.form-row-first,
p.form-row.form-row-last {
float: none;
@ -1836,7 +1843,7 @@ a.reset_variations {
.woocommerce-checkout-review-order-table {
input[type='radio'].shipping_method {
input[type="radio"].shipping_method {
display: none;
& + label {
@ -2134,13 +2141,15 @@ ul.wc-block-grid__products {
.wc-block-grid__product-rating {
.star-rating {
font-size: 0.7em
font-size: 0.7em;
}
}
}
@media only screen and (max-width: 600px) {
.woocommerce {
.woocommerce-ordering {
float: left;
clear: both;
@ -2265,7 +2274,7 @@ ul.wc-block-grid__products {
}
&::before {
content: '';
content: "";
}
}
}
@ -2385,8 +2394,8 @@ ul.wc-block-grid__products {
table.account-orders-table {
.button {
padding-left: .5em;
padding-right: .5em;
padding-left: 0.5em;
padding-right: 0.5em;
width: 100%;
margin: 2rem 0;
}
@ -2427,6 +2436,7 @@ ul.wc-block-grid__products {
}
.wc-block-grid__products {
.wc-block-grid__product-onsale {
font-size: 1.5rem;
padding: 1rem;
@ -2587,6 +2597,7 @@ ul.wc-block-grid__products {
}
.wc-block-grid__products {
.wc-block-grid__product-onsale {
font-size: 1.7rem;
padding: 1.5rem;

View File

@ -1185,7 +1185,7 @@ h3.jetpack-reasons {
}
.branch-5-2,
.branch-5-3 {
.wc-wp-version-gte-53 {
.location-input {
margin: 0;
@ -1415,7 +1415,7 @@ p.jetpack-terms {
}
.branch-5-2,
.branch-5-3 {
.wc-wp-version-gte-53 {
.wc-wizard-service-setting-stripe_create_account,
.wc-wizard-service-setting-ppec_paypal_reroute_requests {

View File

@ -142,7 +142,9 @@
$( '#key_permissions', self.el ).val( data.permissions );
}
} else {
$( 'h2, h3', self.el ).first().append( '<div class="wc-api-message error"><p>' + response.data.message + '</p></div>' );
$( 'h2, h3', self.el )
.first()
.append( '<div class="wc-api-message error"><p>' + response.data.message + '</p></div>' );
}
self.unblock();

View File

@ -130,7 +130,10 @@
var button = e.keyCode || e.which;
// Enter key
if ( 13 === button && ! ( e.target.tagName && ( e.target.tagName.toLowerCase() === 'input' || e.target.tagName.toLowerCase() === 'textarea' ) ) ) {
if (
13 === button &&
! ( e.target.tagName && ( e.target.tagName.toLowerCase() === 'input' || e.target.tagName.toLowerCase() === 'textarea' ) )
) {
this.addButton( e );
}

View File

@ -1,3 +1,4 @@
// eslint-disable-next-line max-len
/*global woocommerce_admin_meta_boxes, woocommerce_admin, accounting, woocommerce_admin_meta_boxes_order, wcSetClipboard, wcClearClipboard */
jQuery( function ( $ ) {
@ -11,7 +12,12 @@ jQuery( function ( $ ) {
var wc_meta_boxes_order = {
states: null,
init: function() {
if ( ! ( typeof woocommerce_admin_meta_boxes_order === 'undefined' || typeof woocommerce_admin_meta_boxes_order.countries === 'undefined' ) ) {
if (
! (
typeof woocommerce_admin_meta_boxes_order === 'undefined' ||
typeof woocommerce_admin_meta_boxes_order.countries === 'undefined'
)
) {
/* State/Country select boxes */
this.states = $.parseJSON( woocommerce_admin_meta_boxes_order.countries.replace( /&quot;/g, '"' ) );
}
@ -380,11 +386,19 @@ jQuery( function ( $ ) {
$( 'input.line_tax', $row ).each( function() {
var $line_total_tax = $( this );
var tax_id = $line_total_tax.data( 'tax_id' );
var unit_total_tax = accounting.unformat( $line_total_tax.attr( 'data-total_tax' ), woocommerce_admin.mon_decimal_point ) / o_qty;
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 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' ];
var precision = woocommerce_admin_meta_boxes[
round_at_subtotal ? 'rounding_precision' : 'currency_format_num_decimals'
];
if ( 0 < unit_total_tax ) {
$line_total_tax.val(
@ -877,7 +891,10 @@ jQuery( function ( $ ) {
$( '.refund input.refund_line_total' ).each(function( index, item ) {
if ( $( item ).closest( 'tr' ).data( 'order_item_id' ) ) {
line_item_totals[ $( item ).closest( 'tr' ).data( 'order_item_id' ) ] = accounting.unformat( item.value, woocommerce_admin.mon_decimal_point );
line_item_totals[ $( item ).closest( 'tr' ).data( 'order_item_id' ) ] = accounting.unformat(
item.value,
woocommerce_admin.mon_decimal_point
);
}
});
@ -889,7 +906,10 @@ jQuery( function ( $ ) {
line_item_tax_totals[ $( item ).closest( 'tr' ).data( 'order_item_id' ) ] = {};
}
line_item_tax_totals[ $( item ).closest( 'tr' ).data( 'order_item_id' ) ][ tax_id ] = accounting.unformat( item.value, woocommerce_admin.mon_decimal_point );
line_item_tax_totals[ $( item ).closest( 'tr' ).data( 'order_item_id' ) ][ tax_id ] = accounting.unformat(
item.value,
woocommerce_admin.mon_decimal_point
);
}
});
@ -1018,11 +1038,16 @@ jQuery( function ( $ ) {
var $refund_line_total_tax = $( this );
var tax_id = $refund_line_total_tax.data( 'tax_id' );
var line_total_tax = $( 'input.line_tax[data-tax_id="' + tax_id + '"]', $row );
var unit_total_tax = accounting.unformat( line_total_tax.data( 'total_tax' ), woocommerce_admin.mon_decimal_point ) / qty;
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' ];
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, precision, '' ) )
@ -1059,8 +1084,17 @@ jQuery( function ( $ ) {
var index = $items.find('tr').length + 1;
var $row = '<tr data-meta_id="0">' +
'<td>' +
'<input type="text" maxlength="255" placeholder="' + woocommerce_admin_meta_boxes_order.placeholder_name + '" name="meta_key[' + $item.attr( 'data-order_item_id' ) + '][new-' + index + ']" />' +
'<textarea placeholder="' + woocommerce_admin_meta_boxes_order.placeholder_value + '" name="meta_value[' + $item.attr( 'data-order_item_id' ) + '][new-' + index + ']"></textarea>' +
'<input type="text" maxlength="255" placeholder="' +
woocommerce_admin_meta_boxes_order.placeholder_name +
'" name="meta_key[' + $item.attr( 'data-order_item_id' ) +
'][new-' + index + ']" />' +
'<textarea placeholder="' +
woocommerce_admin_meta_boxes_order.placeholder_value +
'" name="meta_value[' +
$item.attr( 'data-order_item_id' ) +
'][new-' +
index +
']"></textarea>' +
'</td>' +
'<td width="1%"><button class="remove_order_item_meta button">&times;</button></td>' +
'</tr>';

View File

@ -476,7 +476,9 @@ jQuery( function( $ ) {
$( '.product_attributes .woocommerce_attribute' ).each( function( index, el ) {
if ( $( el ).css( 'display' ) !== 'none' && $( el ).is( '.taxonomy' ) ) {
$( 'select.attribute_taxonomy' ).find( 'option[value="' + $( el ).data( 'taxonomy' ) + '"]' ).prop( 'disabled', true );
$( 'select.attribute_taxonomy' )
.find( 'option[value="' + $( el ).data( 'taxonomy' ) + '"]' )
.prop( 'disabled', true );
}
});

View File

@ -38,17 +38,24 @@ jQuery( function( $ ) {
var nextpostid = ui.item.next().find( '.check-column input' ).val();
// Show Spinner
ui.item.find( '.check-column input' ).hide().after( '<img alt="processing" src="images/wpspin_light.gif" class="waiting" style="margin-left: 6px;" />' );
ui.item
.find( '.check-column input' )
.hide()
.after( '<img alt="processing" src="images/wpspin_light.gif" class="waiting" style="margin-left: 6px;" />' );
// Go do the sorting stuff via ajax
$.post( ajaxurl, { action: 'woocommerce_product_ordering', id: postid, previd: prevpostid, nextid: nextpostid }, function( response ) {
$.each( response, function( key, value ) {
$( '#inline_' + key + ' .menu_order' ).html( value );
});
ui.item.find( '.check-column input' ).show().siblings( 'img' ).remove();
$( 'table.widefat tbody th, table.widefat tbody td' ).css( 'cursor', 'move' );
$( 'table.widefat tbody' ).sortable( 'enable' );
});
$.post(
ajaxurl,
{ action: 'woocommerce_product_ordering', id: postid, previd: prevpostid, nextid: nextpostid },
function( response ) {
$.each( response, function( key, value ) {
$( '#inline_' + key + ' .menu_order' ).html( value );
});
ui.item.find( '.check-column input' ).show().siblings( 'img' ).remove();
$( 'table.widefat tbody th, table.widefat tbody td' ).css( 'cursor', 'move' );
$( 'table.widefat tbody' ).sortable( 'enable' );
}
);
// fix cell colors
$( 'table.widefat tbody tr' ).each( function() {

View File

@ -45,6 +45,7 @@ jQuery(function( $ ) {
$( 'input[name="_stock"]', '.inline-edit-row' ).val( stock );
$( 'input[name="menu_order"]', '.inline-edit-row' ).val( menu_order );
// eslint-disable-next-line max-len
$( 'select[name="_tax_status"] option, select[name="_tax_class"] option, select[name="_visibility"] option, select[name="_stock_status"] option, select[name="_backorders"] option' ).removeAttr( 'selected' );
$( 'select[name="_tax_status"] option[value="' + tax_status + '"]', '.inline-edit-row' ).attr( 'selected', 'selected' );

View File

@ -222,7 +222,13 @@ jQuery(function( $ ) {
csv_data += '"' + index + '",';
} else {
if ( groupby === 'day' ) {
csv_data += '"' + date.getUTCFullYear() + '-' + parseInt( date.getUTCMonth() + 1, 10 ) + '-' + date.getUTCDate() + '",';
csv_data += '"' +
date.getUTCFullYear() +
'-' +
parseInt( date.getUTCMonth() + 1, 10 ) +
'-' +
date.getUTCDate() +
'",';
} else {
csv_data += '"' + date.getUTCFullYear() + '-' + parseInt( date.getUTCMonth() + 1, 10 ) + '",';
}

View File

@ -165,7 +165,8 @@
minLength: 3
});
// Postcode and city don't have `name` values by default. They're only created if the contents changes, to save on database queries (I think)
// Postcode and city don't have `name` values by default.
// They're only created if the contents changes, to save on database queries (I think)
this.$el.find( 'td.postcode input, td.city input' ).change( function() {
$( this ).attr( 'name', $( this ).data( 'name' ) );
});
@ -232,7 +233,9 @@
reordered_rates = _.map( rates_to_reorder, function( rate ) {
rate.tax_rate_order++;
changes[ rate.tax_rate_id ] = _.extend( changes[ rate.tax_rate_id ] || {}, { tax_rate_order : rate.tax_rate_order } );
changes[ rate.tax_rate_id ] = _.extend(
changes[ rate.tax_rate_id ] || {}, { tax_rate_order : rate.tax_rate_order }
);
return rate;
} );
} else {

View File

@ -30,7 +30,13 @@ jQuery( function( $ ) {
};
$( document ).ajaxComplete( function( event, request, options ) {
if ( request && 4 === request.readyState && 200 === request.status && options.data && ( 0 <= options.data.indexOf( '_inline_edit' ) || 0 <= options.data.indexOf( 'add-tag' ) ) ) {
if (
request &&
4 === request.readyState &&
200 === request.status &&
options.data &&
( 0 <= options.data.indexOf( '_inline_edit' ) || 0 <= options.data.indexOf( 'add-tag' ) )
) {
$.wc_add_missing_sort_handles();
$( document.body ).trigger( 'init_tooltips' );
}
@ -80,25 +86,41 @@ jQuery( function( $ ) {
}
}
// If previous and next not at same tree level, or next not at same tree level and the previous is the parent of the next, or just moved item beneath its own children
if ( ( prevtermid === undefined && nexttermid === undefined ) || ( nexttermid === undefined && nexttermparent === prevtermid ) || ( nexttermid !== undefined && prevtermparent === termid ) ) {
// If previous and next not at same tree level, or next not at same tree level and
// the previous is the parent of the next, or just moved item beneath its own children.
if (
( prevtermid === undefined && nexttermid === undefined ) ||
( nexttermid === undefined && nexttermparent === prevtermid ) ||
( nexttermid !== undefined && prevtermparent === termid )
) {
$( table_selector ).sortable( 'cancel' );
return;
}
// Show Spinner
ui.item.find( '.check-column input' ).hide();
ui.item.find( '.check-column' ).append( '<img alt="processing" src="images/wpspin_light.gif" class="waiting" style="margin-left: 6px;" />' );
ui.item
.find( '.check-column' )
.append( '<img alt="processing" src="images/wpspin_light.gif" class="waiting" style="margin-left: 6px;" />' );
// Go do the sorting stuff via ajax
$.post( ajaxurl, { action: 'woocommerce_term_ordering', id: termid, nextid: nexttermid, thetaxonomy: woocommerce_term_ordering_params.taxonomy }, function(response){
if ( response === 'children' ) {
window.location.reload();
} else {
ui.item.find( '.check-column input' ).show();
ui.item.find( '.check-column' ).find( 'img' ).remove();
// Go do the sorting stuff via ajax.
$.post(
ajaxurl,
{
action: 'woocommerce_term_ordering',
id: termid,
nextid: nexttermid,
thetaxonomy: woocommerce_term_ordering_params.taxonomy
},
function(response) {
if ( response === 'children' ) {
window.location.reload();
} else {
ui.item.find( '.check-column input' ).show();
ui.item.find( '.check-column' ).find( 'img' ).remove();
}
}
});
);
// Fix cell colors
$( 'table.widefat tbody tr' ).each( function() {

View File

@ -58,7 +58,15 @@
$this.$form.find('.woocommerce-importer-progress').val( response.data.percentage );
if ( 'done' === response.data.position ) {
window.location = response.data.url + '&products-imported=' + parseInt( $this.imported, 10 ) + '&products-failed=' + parseInt( $this.failed, 10 ) + '&products-updated=' + parseInt( $this.updated, 10 ) + '&products-skipped=' + parseInt( $this.skipped, 10 );
window.location = response.data.url +
'&products-imported=' +
parseInt( $this.imported, 10 ) +
'&products-failed=' +
parseInt( $this.failed, 10 ) +
'&products-updated=' +
parseInt( $this.updated, 10 ) +
'&products-skipped=' +
parseInt( $this.skipped, 10 );
} else {
$this.run_import();
}

View File

@ -34,11 +34,16 @@
this.trigger( 'change:methods' );
},
save: function() {
$.post( ajaxurl + ( ajaxurl.indexOf( '?' ) > 0 ? '&' : '?' ) + 'action=woocommerce_shipping_zone_methods_save_changes', {
wc_shipping_zones_nonce : data.wc_shipping_zones_nonce,
changes : this.changes,
zone_id : data.zone_id
}, this.onSaveResponse, 'json' );
$.post(
ajaxurl + ( ajaxurl.indexOf( '?' ) > 0 ? '&' : '?' ) + 'action=woocommerce_shipping_zone_methods_save_changes',
{
wc_shipping_zones_nonce : data.wc_shipping_zones_nonce,
changes : this.changes,
zone_id : data.zone_id
},
this.onSaveResponse,
'json'
);
},
onSaveResponse: function( response, textStatus ) {
if ( 'success' === textStatus ) {
@ -46,7 +51,11 @@
if ( response.data.zone_id !== data.zone_id ) {
data.zone_id = response.data.zone_id;
if ( window.history.pushState ) {
window.history.pushState({}, '', 'admin.php?page=wc-settings&tab=shipping&zone_id=' + response.data.zone_id );
window.history.pushState(
{},
'',
'admin.php?page=wc-settings&tab=shipping&zone_id=' + response.data.zone_id
);
}
}
shippingMethod.set( 'methods', response.data.methods );
@ -72,7 +81,12 @@
$( window ).on( 'beforeunload', { view: this }, this.unloadConfirmation );
$save_button.on( 'click', { view: this }, this.onSubmit );
$( document.body ).on( 'input change', '#zone_name, #zone_locations, #zone_postcodes', { view: this }, this.onUpdateZone );
$( document.body ).on(
'input change',
'#zone_name, #zone_locations, #zone_postcodes',
{ view: this },
this.onUpdateZone
);
$( document.body ).on( 'click', '.wc-shipping-zone-method-settings', { view: this }, this.onConfigureShippingMethod );
$( document.body ).on( 'click', '.wc-shipping-zone-add-method', { view: this }, this.onAddShippingMethod );
$( document.body ).on( 'wc_backbone_modal_response', this.onConfigureShippingMethodSubmitted );
@ -128,9 +142,13 @@
// Populate $tbody with the current methods
$.each( methods, function( id, rowData ) {
if ( 'yes' === rowData.enabled ) {
rowData.enabled_icon = '<span class="woocommerce-input-toggle woocommerce-input-toggle--enabled">' + data.strings.yes + '</span>';
rowData.enabled_icon = '<span class="woocommerce-input-toggle woocommerce-input-toggle--enabled">' +
data.strings.yes +
'</span>';
} else {
rowData.enabled_icon = '<span class="woocommerce-input-toggle woocommerce-input-toggle--disabled">' + data.strings.no + '</span>';
rowData.enabled_icon = '<span class="woocommerce-input-toggle woocommerce-input-toggle--disabled">' +
data.strings.no +
'</span>';
}
view.$el.append( view.rowTemplate( rowData ) );
@ -138,7 +156,9 @@
var $tr = view.$el.find( 'tr[data-id="' + rowData.instance_id + '"]');
if ( ! rowData.has_settings ) {
$tr.find( '.wc-shipping-zone-method-title > a' ).replaceWith('<span>' + $tr.find( '.wc-shipping-zone-method-title > a' ).text() + '</span>' );
$tr
.find( '.wc-shipping-zone-method-title > a' )
.replaceWith('<span>' + $tr.find( '.wc-shipping-zone-method-title > a' ).text() + '</span>' );
var $del = $tr.find( '.wc-shipping-zone-method-delete' );
$tr.find( '.wc-shipping-zone-method-title .row-actions' ).empty().html($del);
}
@ -241,7 +261,9 @@
if ( old_position !== new_position ) {
methods[ method.instance_id ].method_order = new_position;
changes.methods = changes.methods || { methods : {} };
changes.methods[ method.instance_id ] = _.extend( changes.methods[ method.instance_id ] || {}, { method_order : new_position } );
changes.methods[ method.instance_id ] = _.extend(
changes.methods[ method.instance_id ] || {}, { method_order : new_position }
);
}
} );
@ -281,30 +303,35 @@
shippingMethodView.block();
// Save method settings via ajax call
$.post( ajaxurl + ( ajaxurl.indexOf( '?' ) > 0 ? '&' : '?' ) + 'action=woocommerce_shipping_zone_methods_save_settings', {
wc_shipping_zones_nonce : data.wc_shipping_zones_nonce,
instance_id : posted_data.instance_id,
data : posted_data
}, function( response, textStatus ) {
if ( 'success' === textStatus && response.success ) {
$( 'table.wc-shipping-zone-methods' ).parent().find( '#woocommerce_errors' ).remove();
$.post(
ajaxurl + ( ajaxurl.indexOf( '?' ) > 0 ? '&' : '?' ) + 'action=woocommerce_shipping_zone_methods_save_settings',
{
wc_shipping_zones_nonce : data.wc_shipping_zones_nonce,
instance_id : posted_data.instance_id,
data : posted_data
},
function( response, textStatus ) {
if ( 'success' === textStatus && response.success ) {
$( 'table.wc-shipping-zone-methods' ).parent().find( '#woocommerce_errors' ).remove();
// If there were errors, prepend the form.
if ( response.data.errors.length > 0 ) {
shippingMethodView.showErrors( response.data.errors );
}
// If there were errors, prepend the form.
if ( response.data.errors.length > 0 ) {
shippingMethodView.showErrors( response.data.errors );
}
// Method was saved. Re-render.
if ( _.size( shippingMethodView.model.changes ) ) {
shippingMethodView.model.save();
// Method was saved. Re-render.
if ( _.size( shippingMethodView.model.changes ) ) {
shippingMethodView.model.save();
} else {
shippingMethodView.model.onSaveResponse( response, textStatus );
}
} else {
shippingMethodView.model.onSaveResponse( response, textStatus );
window.alert( data.strings.save_failed );
shippingMethodView.unblock();
}
} else {
window.alert( data.strings.save_failed );
shippingMethodView.unblock();
}
}, 'json' );
},
'json'
);
}
},
showErrors: function( errors ) {
@ -343,7 +370,11 @@
if ( response.data.zone_id !== data.zone_id ) {
data.zone_id = response.data.zone_id;
if ( window.history.pushState ) {
window.history.pushState({}, '', 'admin.php?page=wc-settings&tab=shipping&zone_id=' + response.data.zone_id );
window.history.pushState(
{},
'',
'admin.php?page=wc-settings&tab=shipping&zone_id=' + response.data.zone_id
);
}
}
// Trigger save if there are changes, or just re-render

View File

@ -161,7 +161,9 @@
class_name = 'method_enabled';
}
$method_list.append( '<li class="wc-shipping-zone-method ' + class_name + '">' + shipping_method.title + '</li>' );
$method_list.append(
'<li class="wc-shipping-zone-method ' + class_name + '">' + shipping_method.title + '</li>'
);
} );
} else {
$method_list.append( '<li class="wc-shipping-zone-method">' + data.strings.no_shipping_methods_offered + '</li>' );

View File

@ -12,10 +12,22 @@
if ( 0 === $blankslate.length ) {
if ( woocommerce_admin.urls.export_products ) {
$title_action.after('<a href="' + woocommerce_admin.urls.export_products + '" class="page-title-action">' + woocommerce_admin.strings.export_products + '</a>');
$title_action.after(
'<a href="' +
woocommerce_admin.urls.export_products +
'" class="page-title-action">' +
woocommerce_admin.strings.export_products +
'</a>'
);
}
if ( woocommerce_admin.urls.import_products ) {
$title_action.after( '<a href="' + woocommerce_admin.urls.import_products + '" class="page-title-action">' + woocommerce_admin.strings.import_products + '</a>' );
$title_action.after(
'<a href="' +
woocommerce_admin.urls.import_products +
'" class="page-title-action">' +
woocommerce_admin.strings.import_products +
'</a>'
);
}
} else {
$title_action.hide();
@ -60,70 +72,85 @@
$( '.wc_error_tip' ).fadeOut( '100', function() { $( this ).remove(); } );
})
.on( 'change', '.wc_input_price[type=text], .wc_input_decimal[type=text], .wc-order-totals #refund_amount[type=text]', function() {
var regex, decimalRegex,
decimailPoint = woocommerce_admin.decimal_point;
.on(
'change',
'.wc_input_price[type=text], .wc_input_decimal[type=text], .wc-order-totals #refund_amount[type=text]',
function() {
var regex, decimalRegex,
decimailPoint = woocommerce_admin.decimal_point;
if ( $( this ).is( '.wc_input_price' ) || $( this ).is( '#refund_amount' ) ) {
decimailPoint = woocommerce_admin.mon_decimal_point;
if ( $( this ).is( '.wc_input_price' ) || $( this ).is( '#refund_amount' ) ) {
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, '' ).replace( decimalRegex, decimailPoint );
if ( value !== newvalue ) {
$( this ).val( newvalue );
}
}
)
regex = new RegExp( '[^\-0-9\%\\' + decimailPoint + ']+', 'gi' );
decimalRegex = new RegExp( '\\' + decimailPoint + '+', 'gi' );
.on(
'keyup',
// eslint-disable-next-line max-len
'.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, decimalRegex;
var checkDecimalNumbers = false;
var value = $( this ).val();
var newvalue = value.replace( regex, '' ).replace( decimalRegex, decimailPoint );
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';
}
if ( value !== newvalue ) {
$( this ).val( newvalue );
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 {
$( document.body ).triggerHandler( 'wc_remove_error_tip', [ $( this ), error ] );
}
}
})
.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, 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 {
$( document.body ).triggerHandler( 'wc_remove_error_tip', [ $( this ), error ] );
}
})
)
.on( 'change', '#_sale_price.wc_input_price[type=text], .wc_input_price[name^=variable_sale_price]', function() {
var sale_price_field = $( this ), regular_price_field;
if ( sale_price_field.attr( 'name' ).indexOf( 'variable' ) !== -1 ) {
regular_price_field = sale_price_field.parents( '.variable_pricing' ).find( '.wc_input_price[name^=variable_regular_price]' );
regular_price_field = sale_price_field
.parents( '.variable_pricing' )
.find( '.wc_input_price[name^=variable_regular_price]' );
} else {
regular_price_field = $( '#_regular_price' );
}
var sale_price = parseFloat( window.accounting.unformat( sale_price_field.val(), woocommerce_admin.mon_decimal_point ) );
var regular_price = parseFloat( window.accounting.unformat( regular_price_field.val(), woocommerce_admin.mon_decimal_point ) );
var sale_price = parseFloat(
window.accounting.unformat( sale_price_field.val(), woocommerce_admin.mon_decimal_point )
);
var regular_price = parseFloat(
window.accounting.unformat( regular_price_field.val(), woocommerce_admin.mon_decimal_point )
);
if ( sale_price >= regular_price ) {
$( this ).val( '' );
@ -134,13 +161,19 @@
var sale_price_field = $( this ), regular_price_field;
if ( sale_price_field.attr( 'name' ).indexOf( 'variable' ) !== -1 ) {
regular_price_field = sale_price_field.parents( '.variable_pricing' ).find( '.wc_input_price[name^=variable_regular_price]' );
regular_price_field = sale_price_field
.parents( '.variable_pricing' )
.find( '.wc_input_price[name^=variable_regular_price]' );
} else {
regular_price_field = $( '#_regular_price' );
}
var sale_price = parseFloat( window.accounting.unformat( sale_price_field.val(), woocommerce_admin.mon_decimal_point ) );
var regular_price = parseFloat( window.accounting.unformat( regular_price_field.val(), woocommerce_admin.mon_decimal_point ) );
var sale_price = parseFloat(
window.accounting.unformat( sale_price_field.val(), woocommerce_admin.mon_decimal_point )
);
var regular_price = parseFloat(
window.accounting.unformat( regular_price_field.val(), woocommerce_admin.mon_decimal_point )
);
if ( sale_price >= regular_price ) {
$( document.body ).triggerHandler( 'wc_add_error_tip', [ $(this), 'i18n_sale_less_than_regular_error' ] );
@ -236,9 +269,13 @@
if ( $( 'tr.last_selected', $this_table ).length > 0 ) {
if ( $this_row.index() > $( 'tr.last_selected', $this_table ).index() ) {
$( 'tr', $this_table ).slice( $( 'tr.last_selected', $this_table ).index(), $this_row.index() ).addClass( 'current' );
$( 'tr', $this_table )
.slice( $( 'tr.last_selected', $this_table ).index(), $this_row.index() )
.addClass( 'current' );
} else {
$( 'tr', $this_table ).slice( $this_row.index(), $( 'tr.last_selected', $this_table ).index() + 1 ).addClass( 'current' );
$( 'tr', $this_table )
.slice( $this_row.index(), $( 'tr.last_selected', $this_table ).index() + 1 )
.addClass( 'current' );
}
}
@ -260,7 +297,8 @@
});
// Additional cost and Attribute term tables
$( '.woocommerce_page_wc-settings .shippingrows tbody tr:even, table.attributes-table tbody tr:nth-child(odd)' ).addClass( 'alternate' );
$( '.woocommerce_page_wc-settings .shippingrows tbody tr:even, table.attributes-table tbody tr:nth-child(odd)' )
.addClass( 'alternate' );
// Show order items on orders page
$( document.body ).on( 'click', '.show_order_items', function() {
@ -281,9 +319,15 @@
$( '.hide_options_if_checked' ).each( function() {
$( this ).find( 'input:eq(0)' ).change( function() {
if ( $( this ).is( ':checked' ) ) {
$( this ).closest( 'fieldset, tr' ).nextUntil( '.hide_options_if_checked, .show_options_if_checked', '.hidden_option' ).hide();
$( this )
.closest( 'fieldset, tr' )
.nextUntil( '.hide_options_if_checked, .show_options_if_checked', '.hidden_option' )
.hide();
} else {
$( this ).closest( 'fieldset, tr' ).nextUntil( '.hide_options_if_checked, .show_options_if_checked', '.hidden_option' ).show();
$( this )
.closest( 'fieldset, tr' )
.nextUntil( '.hide_options_if_checked, .show_options_if_checked', '.hidden_option' )
.show();
}
}).change();
});
@ -291,9 +335,15 @@
$( '.show_options_if_checked' ).each( function() {
$( this ).find( 'input:eq(0)' ).change( function() {
if ( $( this ).is( ':checked' ) ) {
$( this ).closest( 'fieldset, tr' ).nextUntil( '.hide_options_if_checked, .show_options_if_checked', '.hidden_option' ).show();
$( this )
.closest( 'fieldset, tr' )
.nextUntil( '.hide_options_if_checked, .show_options_if_checked', '.hidden_option' )
.show();
} else {
$( this ).closest( 'fieldset, tr' ).nextUntil( '.hide_options_if_checked, .show_options_if_checked', '.hidden_option' ).hide();
$( this )
.closest( 'fieldset, tr' )
.nextUntil( '.hide_options_if_checked, .show_options_if_checked', '.hidden_option' )
.hide();
}
}).change();
});

View File

@ -43,7 +43,7 @@
// Init after gallery.
setTimeout( function() {
$form.trigger( 'check_variations' );
$form.trigger( 'wc_variation_form' );
$form.trigger( 'wc_variation_form', self );
self.loading = false;
}, 100 );
};
@ -72,8 +72,14 @@
*/
VariationForm.prototype.onHide = function( event ) {
event.preventDefault();
event.data.variationForm.$form.find( '.single_add_to_cart_button' ).removeClass( 'wc-variation-is-unavailable' ).addClass( 'disabled wc-variation-selection-needed' );
event.data.variationForm.$form.find( '.woocommerce-variation-add-to-cart' ).removeClass( 'woocommerce-variation-add-to-cart-enabled' ).addClass( 'woocommerce-variation-add-to-cart-disabled' );
event.data.variationForm.$form
.find( '.single_add_to_cart_button' )
.removeClass( 'wc-variation-is-unavailable' )
.addClass( 'disabled wc-variation-selection-needed' );
event.data.variationForm.$form
.find( '.woocommerce-variation-add-to-cart' )
.removeClass( 'woocommerce-variation-add-to-cart-enabled' )
.addClass( 'woocommerce-variation-add-to-cart-disabled' );
};
/**
@ -82,11 +88,22 @@
VariationForm.prototype.onShow = function( event, variation, purchasable ) {
event.preventDefault();
if ( purchasable ) {
event.data.variationForm.$form.find( '.single_add_to_cart_button' ).removeClass( 'disabled wc-variation-selection-needed wc-variation-is-unavailable' );
event.data.variationForm.$form.find( '.woocommerce-variation-add-to-cart' ).removeClass( 'woocommerce-variation-add-to-cart-disabled' ).addClass( 'woocommerce-variation-add-to-cart-enabled' );
event.data.variationForm.$form
.find( '.single_add_to_cart_button' )
.removeClass( 'disabled wc-variation-selection-needed wc-variation-is-unavailable' );
event.data.variationForm.$form
.find( '.woocommerce-variation-add-to-cart' )
.removeClass( 'woocommerce-variation-add-to-cart-disabled' )
.addClass( 'woocommerce-variation-add-to-cart-enabled' );
} else {
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' );
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.
@ -123,8 +140,12 @@
VariationForm.prototype.onResetDisplayedVariation = function( event ) {
var form = event.data.variationForm;
form.$product.find( '.product_meta' ).find( '.sku' ).wc_reset_content();
form.$product.find( '.product_weight, .woocommerce-product-attributes-item--weight .woocommerce-product-attributes-item__value' ).wc_reset_content();
form.$product.find( '.product_dimensions, .woocommerce-product-attributes-item--dimensions .woocommerce-product-attributes-item__value' ).wc_reset_content();
form.$product
.find( '.product_weight, .woocommerce-product-attributes-item--weight .woocommerce-product-attributes-item__value' )
.wc_reset_content();
form.$product
.find( '.product_dimensions, .woocommerce-product-attributes-item--dimensions .woocommerce-product-attributes-item__value' )
.wc_reset_content();
form.$form.trigger( 'reset_image' );
form.$singleVariation.slideUp( 200 ).trigger( 'hide_variation' );
};
@ -139,12 +160,12 @@
/**
* Looks for matching variations for current selected attributes.
*/
VariationForm.prototype.onFindVariation = function( event ) {
VariationForm.prototype.onFindVariation = function( event, chosenAttributes ) {
var form = event.data.variationForm,
attributes = form.getChosenAttributes(),
attributes = 'undefined' !== typeof chosenAttributes ? chosenAttributes : form.getChosenAttributes(),
currentAttributes = attributes.data;
if ( attributes.count === attributes.chosenCount ) {
if ( attributes.count && attributes.count === attributes.chosenCount ) {
if ( form.useAjax ) {
if ( form.xhr ) {
form.xhr.abort();
@ -164,7 +185,13 @@
attributes.chosenCount = 0;
if ( ! form.loading ) {
form.$form.find( '.single_variation' ).after( '<p class="wc-no-matching-variations woocommerce-info">' + wc_add_to_cart_variation_params.i18n_no_matching_variations_text + '</p>' );
form.$form
.find( '.single_variation' )
.after(
'<p class="wc-no-matching-variations woocommerce-info">' +
wc_add_to_cart_variation_params.i18n_no_matching_variations_text +
'</p>'
);
form.$form.find( '.wc-no-matching-variations' ).slideDown( 200 );
}
}
@ -186,7 +213,13 @@
attributes.chosenCount = 0;
if ( ! form.loading ) {
form.$form.find( '.single_variation' ).after( '<p class="wc-no-matching-variations woocommerce-info">' + wc_add_to_cart_variation_params.i18n_no_matching_variations_text + '</p>' );
form.$form
.find( '.single_variation' )
.after(
'<p class="wc-no-matching-variations woocommerce-info">' +
wc_add_to_cart_variation_params.i18n_no_matching_variations_text +
'</p>'
);
form.$form.find( '.wc-no-matching-variations' ).slideDown( 200 );
}
}
@ -206,8 +239,12 @@
VariationForm.prototype.onFoundVariation = function( event, variation ) {
var form = event.data.variationForm,
$sku = form.$product.find( '.product_meta' ).find( '.sku' ),
$weight = form.$product.find( '.product_weight, .woocommerce-product-attributes-item--weight .woocommerce-product-attributes-item__value' ),
$dimensions = form.$product.find( '.product_dimensions, .woocommerce-product-attributes-item--dimensions .woocommerce-product-attributes-item__value' ),
$weight = form.$product.find(
'.product_weight, .woocommerce-product-attributes-item--weight .woocommerce-product-attributes-item__value'
),
$dimensions = form.$product.find(
'.product_dimensions, .woocommerce-product-attributes-item--dimensions .woocommerce-product-attributes-item__value'
),
$qty = form.$singleVariationWrap.find( '.quantity' ),
purchasable = true,
variation_id = '',
@ -333,7 +370,11 @@
refSelect.find( 'option' ).removeAttr( 'disabled attached' ).removeAttr( 'selected' );
current_attr_select.data( 'attribute_options', refSelect.find( 'option' + option_gt_filter ).get() ); // Legacy data attribute.
// Legacy data attribute.
current_attr_select.data(
'attribute_options',
refSelect.find( 'option' + option_gt_filter ).get()
);
current_attr_select.data( 'attribute_html', refSelect.html() );
}
@ -597,7 +638,9 @@
$product_gallery = $product.find( '.images' ),
$gallery_nav = $product.find( '.flex-control-nav' ),
$gallery_img = $gallery_nav.find( 'li:eq(0) img' ),
$product_img_wrap = $product_gallery.find( '.woocommerce-product-gallery__image, .woocommerce-product-gallery__image--placeholder' ).eq( 0 ),
$product_img_wrap = $product_gallery
.find( '.woocommerce-product-gallery__image, .woocommerce-product-gallery__image--placeholder' )
.eq( 0 ),
$product_img = $product_img_wrap.find( '.wp-post-image' ),
$product_link = $product_img_wrap.find( 'a' ).eq( 0 );
@ -658,7 +701,9 @@
$product_gallery = $product.find( '.images' ),
$gallery_nav = $product.find( '.flex-control-nav' ),
$gallery_img = $gallery_nav.find( 'li:eq(0) img' ),
$product_img_wrap = $product_gallery.find( '.woocommerce-product-gallery__image, .woocommerce-product-gallery__image--placeholder' ).eq( 0 ),
$product_img_wrap = $product_gallery
.find( '.woocommerce-product-gallery__image, .woocommerce-product-gallery__image--placeholder' )
.eq( 0 ),
$product_img = $product_img_wrap.find( '.wp-post-image' ),
$product_link = $product_img_wrap.find( 'a' ).eq( 0 );

View File

@ -17,6 +17,7 @@ jQuery( function( $ ) {
.on( 'click', '.add_to_cart_button', { addToCartHandler: this }, this.onAddToCart )
.on( 'click', '.remove_from_cart_button', { addToCartHandler: this }, this.onRemoveFromCart )
.on( 'added_to_cart', this.updateButton )
.on( 'ajax_request_not_sent.adding_to_cart', this.updateButton )
.on( 'added_to_cart removed_from_cart', { addToCartHandler: this }, this.updateFragments );
};
@ -69,6 +70,12 @@ jQuery( function( $ ) {
$thisbutton.removeClass( 'added' );
$thisbutton.addClass( 'loading' );
// Allow 3rd parties to validate and quit early.
if ( false === $( document.body ).triggerHandler( 'should_send_ajax_request.adding_to_cart', [ $thisbutton ] ) ) {
$( document.body ).trigger( 'ajax_request_not_sent.adding_to_cart', [ false, false, $thisbutton ] );
return true;
}
var data = {};
// Fetch changes that are directly added by calling $thisbutton.data( key, value )
@ -159,10 +166,13 @@ jQuery( function( $ ) {
if ( $button ) {
$button.removeClass( 'loading' );
$button.addClass( 'added' );
if ( fragments ) {
$button.addClass( 'added' );
}
// View cart text.
if ( ! wc_add_to_cart_params.is_cart && $button.parent().find( '.added_to_cart' ).length === 0 ) {
if ( fragments && ! wc_add_to_cart_params.is_cart && $button.parent().find( '.added_to_cart' ).length === 0 ) {
$button.after( ' <a href="' + wc_add_to_cart_params.cart_url + '" class="added_to_cart wc-forward" title="' +
wc_add_to_cart_params.i18n_view_cart + '">' + wc_add_to_cart_params.i18n_view_cart + '</a>' );
}

View File

@ -105,7 +105,7 @@ jQuery( function( $ ) {
}
$( '.woocommerce-cart-form' ).replaceWith( $new_form );
$( '.woocommerce-cart-form' ).find( ':input[name="update_cart"]' ).prop( 'disabled', true );
$( '.woocommerce-cart-form' ).find( ':input[name="update_cart"]' ).prop( 'disabled', true ).attr( 'aria-disabled', true );
if ( $notices.length > 0 ) {
show_notice( $notices );
@ -134,7 +134,9 @@ jQuery( function( $ ) {
*/
var show_notice = function( html_element, $target ) {
if ( ! $target ) {
$target = $( '.woocommerce-notices-wrapper:first' ) || $( '.cart-empty' ).closest( '.woocommerce' ) || $( '.woocommerce-cart-form' );
$target = $( '.woocommerce-notices-wrapper:first' ) ||
$( '.cart-empty' ).closest( '.woocommerce' ) ||
$( '.woocommerce-cart-form' );
}
$target.prepend( html_element );
};
@ -188,6 +190,7 @@ jQuery( function( $ ) {
shipping_method_selected: function() {
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();
} );
@ -301,14 +304,14 @@ jQuery( function( $ ) {
'.woocommerce-cart-form .cart_item :input',
this.input_changed );
$( '.woocommerce-cart-form :input[name="update_cart"]' ).prop( 'disabled', true );
$( '.woocommerce-cart-form :input[name="update_cart"]' ).prop( 'disabled', true ).attr( 'aria-disabled', true );
},
/**
* After an input is changed, enable the update cart button.
*/
input_changed: function() {
$( '.woocommerce-cart-form :input[name="update_cart"]' ).prop( 'disabled', false );
$( '.woocommerce-cart-form :input[name="update_cart"]' ).prop( 'disabled', false ).attr( 'aria-disabled', false );
},
/**

View File

@ -93,7 +93,7 @@ jQuery( function( $ ) {
var country = $( this ).val(),
$statebox = $wrapper.find( '#billing_state, #shipping_state, #calc_shipping_state' ),
$parent = $statebox.closest( 'p.form-row' ),
$parent = $statebox.closest( '.form-row' ),
input_name = $statebox.attr( 'name' ),
input_id = $statebox.attr('id'),
input_classes = $statebox.attr('data-input-classes'),

View File

@ -9,7 +9,7 @@ jQuery( function( $ ) {
$( 'body' )
// Tabs
.on( 'init', '.wc-tabs-wrapper, .woocommerce-tabs', function() {
$( '.wc-tab, .woocommerce-tabs .panel:not(.panel .panel)' ).hide();
$( this ).find( '.wc-tab, .woocommerce-tabs .panel:not(.panel .panel)' ).hide();
var hash = window.location.hash;
var url = window.location.href;

View File

@ -22,7 +22,12 @@ jQuery( function( $ ) {
this.hideSaveNewCheckbox = this.hideSaveNewCheckbox.bind( this );
// When a radio button is changed, make sure to show/hide our new CC info area.
this.$target.on( 'click change', ':input.woocommerce-SavedPaymentMethods-tokenInput', { tokenizationForm: this }, this.onTokenChange );
this.$target.on(
'click change',
':input.woocommerce-SavedPaymentMethods-tokenInput',
{ tokenizationForm: this },
this.onTokenChange
);
// OR if create account is checked.
$( 'input#createaccount' ).change( { tokenizationForm: this }, this.onCreateAccountChange );

View File

@ -81,15 +81,17 @@ jQuery( function( $ ) {
// Show password visiblity hover icon on woocommerce forms
$( '.woocommerce form .woocommerce-Input[type="password"]' ).wrap( '<span class="password-input"></span>' );
// Add 'password-input' class to the password wrapper in checkout page.
$( '.woocommerce form input' ).filter(':password').parent('span').addClass('password-input');
$( '.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' );
$( this ).siblings( ['input[type="password"]'] ).prop( 'type', 'text' );
} else {
$( this ).siblings( 'input[name^="password"]' ).prop( 'type', 'password' );
$( this ).siblings( 'input[type="text"]' ).prop( 'type', 'password' );
}
}
);

View File

@ -755,6 +755,12 @@ S2.define('select2/utils',[
});
};
Utils.entityDecode = function(html) {
var txt = document.createElement("textarea");
txt.innerHTML = html;
return txt.value;
}
// Append an array of jQuery nodes to a given element.
Utils.appendMany = function ($element, $nodes) {
// jQuery 1.7.x does not support $.fn.append() with an array
@ -1611,9 +1617,9 @@ S2.define('select2/selection/single',[
var selection = data[0];
var $rendered = this.$selection.find('.select2-selection__rendered');
var formatted = this.display(selection, $rendered);
var formatted = Utils.entityDecode(this.display(selection, $rendered));
$rendered.empty().append(formatted);
$rendered.empty().text(formatted);
$rendered.prop('title', selection.title || selection.text);
};
@ -1742,12 +1748,14 @@ S2.define('select2/selection/multiple',[
var selection = data[d];
var $selection = this.selectionContainer();
var removeItemTag = $selection.html();
var formatted = this.display(selection, $selection);
if ('string' === typeof formatted) {
formatted = formatted.trim();
formatted = Utils.entityDecode(formatted.trim());
}
$selection.append(formatted);
$selection.text(formatted);
$selection.prepend(removeItemTag);
$selection.prop('title', selection.title || selection.text);
$selection.data('data', selection);
@ -1786,7 +1794,7 @@ S2.define('select2/selection/placeholder',[
Placeholder.prototype.createPlaceholder = function (decorated, placeholder) {
var $placeholder = this.selectionContainer();
$placeholder.html(this.display(placeholder));
$placeholder.text(Utils.entityDecode(this.display(placeholder)));
$placeholder.addClass('select2-selection__placeholder')
.removeClass('select2-selection__choice');

File diff suppressed because one or more lines are too long

View File

@ -755,6 +755,12 @@ S2.define('select2/utils',[
});
};
Utils.entityDecode = function(html) {
var txt = document.createElement("textarea");
txt.innerHTML = html;
return txt.value;
}
// Append an array of jQuery nodes to a given element.
Utils.appendMany = function ($element, $nodes) {
// jQuery 1.7.x does not support $.fn.append() with an array
@ -1611,9 +1617,9 @@ S2.define('select2/selection/single',[
var selection = data[0];
var $rendered = this.$selection.find('.select2-selection__rendered');
var formatted = this.display(selection, $rendered);
var formatted = Utils.entityDecode(this.display(selection, $rendered));
$rendered.empty().append(formatted);
$rendered.empty().text(formatted);
$rendered.prop('title', selection.title || selection.text);
};
@ -1742,12 +1748,14 @@ S2.define('select2/selection/multiple',[
var selection = data[d];
var $selection = this.selectionContainer();
var removeItemTag = $selection.html();
var formatted = this.display(selection, $selection);
if ('string' === typeof formatted) {
formatted = formatted.trim();
formatted = Utils.entityDecode(formatted.trim());
}
$selection.append(formatted);
$selection.text(formatted);
$selection.prepend(removeItemTag);
$selection.prop('title', selection.title || selection.text);
$selection.data('data', selection);
@ -1786,7 +1794,7 @@ S2.define('select2/selection/placeholder',[
Placeholder.prototype.createPlaceholder = function (decorated, placeholder) {
var $placeholder = this.selectionContainer();
$placeholder.html(this.display(placeholder));
$placeholder.text(Utils.entityDecode(this.display(placeholder)));
$placeholder.addClass('select2-selection__placeholder')
.removeClass('select2-selection__choice');

File diff suppressed because one or more lines are too long

View File

@ -1,12 +1,9 @@
module.exports = {
presets: [
[
'@babel/preset-env',
{
targets: {
node: 'current',
},
},
],
],
const e2eBabelConfig = require( '@woocommerce/e2e-environment' ).babelConfig;
module.exports = function( api ) {
api.cache( true );
return {
...e2eBabelConfig,
};
};

32
bin/build-zip.sh Executable file
View File

@ -0,0 +1,32 @@
#!/bin/sh
PLUGIN_SLUG="woocommerce"
PROJECT_PATH=$(pwd)
BUILD_PATH="${PROJECT_PATH}/build"
DEST_PATH="$BUILD_PATH/$PLUGIN_SLUG"
echo "Generating build directory..."
rm -rf "$BUILD_PATH"
mkdir -p "$DEST_PATH"
echo "Installing PHP and JS dependencies..."
npm install
composer install || exit "$?"
echo "Running JS Build..."
npm run build || exit "$?"
echo "Cleaning up PHP dependencies..."
composer install --no-dev || exit "$?"
echo "Syncing files..."
rsync -rc --exclude-from="$PROJECT_PATH/.distignore" "$PROJECT_PATH/" "$DEST_PATH/" --delete --delete-excluded
echo "Restoring PHP dependencies..."
composer install || exit "$?"
npm run build || exit "$?"
echo "Generating zip file..."
cd "$BUILD_PATH" || exit
zip -q -r "${PLUGIN_SLUG}.zip" "$PLUGIN_SLUG/"
echo "$BUILD_PATH/${PLUGIN_SLUG}.zip file generated!"
echo "Build done!"

32
bin/contributors.sh Executable file
View File

@ -0,0 +1,32 @@
#!/bin/bash
read -p 'What date (YYYY-MM-DD) should we get contributions since? (i.e. date of previous release): ' from_date
read -sp 'Provide a personal access token (you must): ' auth_token
ignored_users="renovate-bot,apps/renovate,renovate,renovate[bot]"
output_file="contributors.html"
common_arguments="--owner woocommerce --fromDate $from_date --authToken $auth_token --cols 6 --sortBy contributions --format html --sortOrder desc --showlogin true --filter $ignored_users"
echo ""
echo "<h2>WooCommerce core</h2>" > $output_file
echo "Generating contributor list for WC core since $from_date"
./node_modules/.bin/githubcontrib --repo woocommerce $common_arguments >> $output_file
echo "<h2>WooCommerce Admin</h2>" >> $output_file
echo "Generating contributor list for WC Admin since $from_date"
./node_modules/.bin/githubcontrib --repo woocommerce-admin $common_arguments >> $output_file
echo "<h2>WooCommerce Blocks</h2>" >> $output_file
echo "Generating contributor list for WC Blocks since $from_date"
./node_modules/.bin/githubcontrib --repo woocommerce-gutenberg-products-block $common_arguments >> $output_file
echo "<h2>Action Scheduler</h2>" >> $output_file
echo "Generating contributor list for Action Scheduler since $from_date"
./node_modules/.bin/githubcontrib --repo action-scheduler $common_arguments >> $output_file
echo "<h2>REST API</h2>" >> $output_file
echo "Generating contributor list for REST API since $from_date"
./node_modules/.bin/githubcontrib --repo woocommerce-rest-api $common_arguments >> $output_file
echo "Output generated to $output_file."

View File

@ -34,7 +34,8 @@ output 2 "Done!"
output 3 "Updating package JS textdomains..."
find ./packages/woocommerce-blocks -iname '*.js' -exec sed -i.bak -e "s/'woo-gutenberg-products-block'/'woocommerce'/g" -e "s/\"woo-gutenberg-products-block\"/'woocommerce'/g" {} \;
find ./packages/woocommerce-admin -iname '*.js' -exec sed -i.bak -e "s/, 'woocommerce-admin'/, 'woocommerce'/g" {} \;
find ./packages/woocommerce-blocks -iname '*.js' -exec sed -i.bak -e "s/'woocommerce-admin'/'woocommerce'/g" -e "s/\"woocommerce-admin\"/'woocommerce'/g" {} \;
find ./packages/woocommerce-admin -iname '*.js' -exec sed -i.bak -e "s/'woocommerce-admin'/'woocommerce'/g" -e "s/\"woocommerce-admin\"/'woocommerce'/g" {} \;
# Cleanup backup files
find ./packages -name "*.bak" -type f -delete

22
bin/pre-push.sh Executable file
View File

@ -0,0 +1,22 @@
#!/bin/sh
PROTECTED_BRANCH="master"
REMOTE_REF=$(echo "$HUSKY_GIT_STDIN" | cut -d " " -f 3)
if [ -n "$REMOTE_REF" ]; then
if [ -z "${REMOTE_REF##*$PROTECTED_BRANCH*}" ]; then
printf "%sYou're about to push to master, is that what you intended? [y/N]: %s" "$(tput setaf 3)" "$(tput sgr0)"
read -r PROCEED < /dev/tty
echo
if [ "$(echo "${PROCEED:-n}" | tr "[:upper:]" "[:lower:]")" = "y" ]; then
echo "$(tput setaf 2)Brace yourself! Pushing to the master branch...$(tput sgr0)"
echo
exit 0
fi
echo "$(tput setaf 2)Push to master cancelled!$(tput sgr0)"
echo
exit 1
fi
fi

View File

@ -8,15 +8,15 @@
"minimum-stability": "dev",
"require": {
"php": ">=7.0",
"automattic/jetpack-autoloader": "^1.6.0",
"automattic/jetpack-autoloader": "^1.7.0",
"automattic/jetpack-constants": "^1.1",
"composer/installers": "1.7.0",
"maxmind-db/reader": "1.6.0",
"pelago/emogrifier": "^3.1",
"woocommerce/action-scheduler": "3.1.5",
"woocommerce/woocommerce-blocks": "2.5.16",
"woocommerce/woocommerce-rest-api": "1.0.7",
"woocommerce/woocommerce-admin": "1.1.1"
"woocommerce/action-scheduler": "3.1.6",
"woocommerce/woocommerce-admin": "1.3.0-rc.1",
"woocommerce/woocommerce-blocks": "2.7.1",
"woocommerce/woocommerce-rest-api": "1.0.10"
},
"require-dev": {
"phpunit/phpunit": "7.5.20",
@ -43,6 +43,12 @@
"Automattic\\WooCommerce\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Automattic\\WooCommerce\\Tests\\": "tests/php/src",
"Automattic\\WooCommerce\\Testing\\Tools\\": "tests/Tools"
}
},
"scripts": {
"post-install-cmd": [
"sh ./bin/package-update.sh"
@ -63,7 +69,7 @@
"phpcbf -p"
],
"makepot-audit": [
"wp i18n make-pot . --exclude=\".github,.wordpress-org,bin,sample-data,node_modules,tests\" --slug=woocommerce"
"wp --allow-root i18n make-pot . --exclude=\".github,.wordpress-org,bin,sample-data,node_modules,tests\" --slug=woocommerce"
],
"makepot": [
"@makepot-audit --skip-audit"
@ -80,8 +86,8 @@
"test": "Run unit tests",
"phpcs": "Analyze code against the WordPress coding standards with PHP_CodeSniffer",
"phpcbf": "Fix coding standards warnings/errors automatically with PHP Code Beautifier",
"makepot-audit": "Generate i18n/langauges/woocommerce.pot file and run audit",
"makepot": "Generate i18n/langauges/woocommerce.pot file"
"makepot-audit": "Generate i18n/languages/woocommerce.pot file and run audit",
"makepot": "Generate i18n/languages/woocommerce.pot file"
}
}
}

186
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": "4f587bb7d4020e7b4987cd1dde300e48",
"content-hash": "c35209de8f965f88aa5121e3ba76fc65",
"packages": [
{
"name": "automattic/jetpack-autoloader",
"version": "v1.6.0",
"version": "v1.7.0",
"source": {
"type": "git",
"url": "https://github.com/Automattic/jetpack-autoloader.git",
"reference": "3bcbe1ae19febd6beeb181cf11af0bf0b7abe7e7"
"reference": "7c6736eeee0f9fc49fa691fe3e958725efb27ca0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Automattic/jetpack-autoloader/zipball/3bcbe1ae19febd6beeb181cf11af0bf0b7abe7e7",
"reference": "3bcbe1ae19febd6beeb181cf11af0bf0b7abe7e7",
"url": "https://api.github.com/repos/Automattic/jetpack-autoloader/zipball/7c6736eeee0f9fc49fa691fe3e958725efb27ca0",
"reference": "7c6736eeee0f9fc49fa691fe3e958725efb27ca0",
"shasum": ""
},
"require": {
@ -40,23 +40,24 @@
"GPL-2.0-or-later"
],
"description": "Creates a custom autoloader for a plugin or theme.",
"time": "2020-03-26T07:57:53+00:00"
"time": "2020-04-23T02:28:37+00:00"
},
{
"name": "automattic/jetpack-constants",
"version": "v1.1.3",
"version": "v1.2.0",
"source": {
"type": "git",
"url": "https://github.com/Automattic/jetpack-constants.git",
"reference": "5fdd94dec1151e7defd684a97e0b64fe6ff1bd3a"
"reference": "881618defb04134ddba120e7835af1a474a11edc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Automattic/jetpack-constants/zipball/5fdd94dec1151e7defd684a97e0b64fe6ff1bd3a",
"reference": "5fdd94dec1151e7defd684a97e0b64fe6ff1bd3a",
"url": "https://api.github.com/repos/Automattic/jetpack-constants/zipball/881618defb04134ddba120e7835af1a474a11edc",
"reference": "881618defb04134ddba120e7835af1a474a11edc",
"shasum": ""
},
"require-dev": {
"php-mock/php-mock": "^2.1",
"phpunit/phpunit": "^5.7 || ^6.5 || ^7.5"
},
"type": "library",
@ -70,7 +71,7 @@
"GPL-2.0-or-later"
],
"description": "A wrapper for defining constants in a more testable way.",
"time": "2019-11-08T21:16:05+00:00"
"time": "2020-04-15T18:58:53+00:00"
},
{
"name": "composer/installers",
@ -330,7 +331,7 @@
},
{
"name": "symfony/css-selector",
"version": "v3.4.39",
"version": "v3.4.42",
"source": {
"type": "git",
"url": "https://github.com/symfony/css-selector.git",
@ -379,34 +380,20 @@
],
"description": "Symfony CssSelector Component",
"homepage": "https://symfony.com",
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2020-03-16T08:31:04+00:00"
},
{
"name": "woocommerce/action-scheduler",
"version": "3.1.5",
"version": "3.1.6",
"source": {
"type": "git",
"url": "https://github.com/woocommerce/action-scheduler.git",
"reference": "84e8ecba7d4f542f85fae7663e90eede1858b41b"
"reference": "275d0ba54b1c263dfc62688de2fa9a25a373edf8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/woocommerce/action-scheduler/zipball/84e8ecba7d4f542f85fae7663e90eede1858b41b",
"reference": "84e8ecba7d4f542f85fae7663e90eede1858b41b",
"url": "https://api.github.com/repos/woocommerce/action-scheduler/zipball/275d0ba54b1c263dfc62688de2fa9a25a373edf8",
"reference": "275d0ba54b1c263dfc62688de2fa9a25a373edf8",
"shasum": ""
},
"require-dev": {
@ -428,20 +415,20 @@
],
"description": "Action Scheduler for WordPress and WooCommerce",
"homepage": "https://actionscheduler.org/",
"time": "2020-04-29T16:19:22+00:00"
"time": "2020-05-12T16:22:33+00:00"
},
{
"name": "woocommerce/woocommerce-admin",
"version": "v1.1.1",
"version": "v1.3.0-rc.1",
"source": {
"type": "git",
"url": "https://github.com/woocommerce/woocommerce-admin.git",
"reference": "79e78bb8b71fa0c0b0a77efee5474b46d62c1a76"
"reference": "12bc8bf522298a099bb725990cd50bae944e667f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/woocommerce/woocommerce-admin/zipball/79e78bb8b71fa0c0b0a77efee5474b46d62c1a76",
"reference": "79e78bb8b71fa0c0b0a77efee5474b46d62c1a76",
"url": "https://api.github.com/repos/woocommerce/woocommerce-admin/zipball/12bc8bf522298a099bb725990cd50bae944e667f",
"reference": "12bc8bf522298a099bb725990cd50bae944e667f",
"shasum": ""
},
"require": {
@ -475,20 +462,20 @@
],
"description": "A modern, javascript-driven WooCommerce Admin experience.",
"homepage": "https://github.com/woocommerce/woocommerce-admin",
"time": "2020-04-28T22:16:15+00:00"
"time": "2020-06-23T02:57:05+00:00"
},
{
"name": "woocommerce/woocommerce-blocks",
"version": "v2.5.16",
"version": "v2.7.1",
"source": {
"type": "git",
"url": "https://github.com/woocommerce/woocommerce-gutenberg-products-block.git",
"reference": "3bd91b669247000fd3f5277954701d0b148d3f1a"
"reference": "0025c5cda83892c6f566fffd05197006f230d16c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/woocommerce/woocommerce-gutenberg-products-block/zipball/3bd91b669247000fd3f5277954701d0b148d3f1a",
"reference": "3bd91b669247000fd3f5277954701d0b148d3f1a",
"url": "https://api.github.com/repos/woocommerce/woocommerce-gutenberg-products-block/zipball/0025c5cda83892c6f566fffd05197006f230d16c",
"reference": "0025c5cda83892c6f566fffd05197006f230d16c",
"shasum": ""
},
"require": {
@ -522,20 +509,20 @@
"gutenberg",
"woocommerce"
],
"time": "2020-04-07T11:47:19+00:00"
"time": "2020-06-16T13:34:29+00:00"
},
{
"name": "woocommerce/woocommerce-rest-api",
"version": "1.0.7",
"version": "1.0.10",
"source": {
"type": "git",
"url": "https://github.com/woocommerce/woocommerce-rest-api.git",
"reference": "49162ec26a25bd0c6efc0f3452b113cdfff0a823"
"reference": "fdcb116b4f5b699b942c01b46fd863c7da8b4b7c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/woocommerce/woocommerce-rest-api/zipball/49162ec26a25bd0c6efc0f3452b113cdfff0a823",
"reference": "49162ec26a25bd0c6efc0f3452b113cdfff0a823",
"url": "https://api.github.com/repos/woocommerce/woocommerce-rest-api/zipball/fdcb116b4f5b699b942c01b46fd863c7da8b4b7c",
"reference": "fdcb116b4f5b699b942c01b46fd863c7da8b4b7c",
"shasum": ""
},
"require": {
@ -562,7 +549,7 @@
],
"description": "The WooCommerce core REST API.",
"homepage": "https://github.com/woocommerce/woocommerce-rest-api",
"time": "2020-01-28T21:04:51+00:00"
"time": "2020-06-16T09:51:51+00:00"
}
],
"packages-dev": [
@ -634,20 +621,20 @@
},
{
"name": "doctrine/instantiator",
"version": "1.3.0",
"version": "1.3.1",
"source": {
"type": "git",
"url": "https://github.com/doctrine/instantiator.git",
"reference": "ae466f726242e637cebdd526a7d991b9433bacf1"
"reference": "f350df0268e904597e3bd9c4685c53e0e333feea"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/instantiator/zipball/ae466f726242e637cebdd526a7d991b9433bacf1",
"reference": "ae466f726242e637cebdd526a7d991b9433bacf1",
"url": "https://api.github.com/repos/doctrine/instantiator/zipball/f350df0268e904597e3bd9c4685c53e0e333feea",
"reference": "f350df0268e904597e3bd9c4685c53e0e333feea",
"shasum": ""
},
"require": {
"php": "^7.1"
"php": "^7.1 || ^8.0"
},
"require-dev": {
"doctrine/coding-standard": "^6.0",
@ -686,7 +673,7 @@
"constructor",
"instantiate"
],
"time": "2019-10-21T16:45:58+00:00"
"time": "2020-05-29T17:27:14+00:00"
},
{
"name": "gettext/gettext",
@ -813,16 +800,16 @@
},
{
"name": "mck89/peast",
"version": "v1.10.3",
"version": "v1.10.4",
"source": {
"type": "git",
"url": "https://github.com/mck89/peast.git",
"reference": "6d1100f39f684c9e004f808b27f6c824b083d8d8"
"reference": "e11664ef53ba2a4ca1d16d8bc73fcc317cd65d3d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/mck89/peast/zipball/6d1100f39f684c9e004f808b27f6c824b083d8d8",
"reference": "6d1100f39f684c9e004f808b27f6c824b083d8d8",
"url": "https://api.github.com/repos/mck89/peast/zipball/e11664ef53ba2a4ca1d16d8bc73fcc317cd65d3d",
"reference": "e11664ef53ba2a4ca1d16d8bc73fcc317cd65d3d",
"shasum": ""
},
"require": {
@ -834,7 +821,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.10.3-dev"
"dev-master": "1.10.4-dev"
}
},
"autoload": {
@ -854,7 +841,7 @@
}
],
"description": "Peast is PHP library that generates AST for JavaScript code",
"time": "2020-04-03T09:06:20+00:00"
"time": "2020-06-21T17:16:08+00:00"
},
{
"name": "mustache/mustache",
@ -1214,24 +1201,21 @@
},
{
"name": "phpdocumentor/reflection-common",
"version": "2.0.0",
"version": "2.1.0",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/ReflectionCommon.git",
"reference": "63a995caa1ca9e5590304cd845c15ad6d482a62a"
"reference": "6568f4687e5b41b054365f9ae03fcb1ed5f2069b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/63a995caa1ca9e5590304cd845c15ad6d482a62a",
"reference": "63a995caa1ca9e5590304cd845c15ad6d482a62a",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/6568f4687e5b41b054365f9ae03fcb1ed5f2069b",
"reference": "6568f4687e5b41b054365f9ae03fcb1ed5f2069b",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"require-dev": {
"phpunit/phpunit": "~6"
},
"type": "library",
"extra": {
"branch-alias": {
@ -1262,7 +1246,7 @@
"reflection",
"static analysis"
],
"time": "2018-08-07T13:53:10+00:00"
"time": "2020-04-27T09:25:28+00:00"
},
{
"name": "phpdocumentor/reflection-docblock",
@ -2430,7 +2414,7 @@
},
{
"name": "symfony/finder",
"version": "v3.4.39",
"version": "v3.4.42",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
@ -2475,34 +2459,20 @@
],
"description": "Symfony Finder Component",
"homepage": "https://symfony.com",
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2020-02-14T07:34:21+00:00"
},
{
"name": "symfony/polyfill-ctype",
"version": "v1.15.0",
"version": "v1.17.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
"reference": "4719fa9c18b0464d399f1a63bf624b42b6fa8d14"
"reference": "2edd75b8b35d62fd3eeabba73b26b8f1f60ce13d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/4719fa9c18b0464d399f1a63bf624b42b6fa8d14",
"reference": "4719fa9c18b0464d399f1a63bf624b42b6fa8d14",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/2edd75b8b35d62fd3eeabba73b26b8f1f60ce13d",
"reference": "2edd75b8b35d62fd3eeabba73b26b8f1f60ce13d",
"shasum": ""
},
"require": {
@ -2514,7 +2484,11 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.15-dev"
"dev-master": "1.17-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
@ -2547,21 +2521,7 @@
"polyfill",
"portable"
],
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2020-02-27T09:26:54+00:00"
"time": "2020-06-06T08:46:27+00:00"
},
{
"name": "theseer/tokenizer",
@ -2605,16 +2565,16 @@
},
{
"name": "webmozart/assert",
"version": "1.8.0",
"version": "1.9.0",
"source": {
"type": "git",
"url": "https://github.com/webmozart/assert.git",
"reference": "ab2cb0b3b559010b75981b1bdce728da3ee90ad6"
"reference": "9dc4f203e36f2b486149058bade43c851dd97451"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/webmozart/assert/zipball/ab2cb0b3b559010b75981b1bdce728da3ee90ad6",
"reference": "ab2cb0b3b559010b75981b1bdce728da3ee90ad6",
"url": "https://api.github.com/repos/webmozart/assert/zipball/9dc4f203e36f2b486149058bade43c851dd97451",
"reference": "9dc4f203e36f2b486149058bade43c851dd97451",
"shasum": ""
},
"require": {
@ -2622,6 +2582,7 @@
"symfony/polyfill-ctype": "^1.8"
},
"conflict": {
"phpstan/phpstan": "<0.12.20",
"vimeo/psalm": "<3.9.1"
},
"require-dev": {
@ -2649,7 +2610,7 @@
"check",
"validate"
],
"time": "2020-04-18T12:12:48+00:00"
"time": "2020-06-16T10:16:42+00:00"
},
{
"name": "woocommerce/woocommerce-sniffs",
@ -2693,16 +2654,16 @@
},
{
"name": "wp-cli/i18n-command",
"version": "v2.2.2",
"version": "v2.2.3",
"source": {
"type": "git",
"url": "https://github.com/wp-cli/i18n-command.git",
"reference": "2804c5246d9338da59951737b03c54d257be8e47"
"reference": "7a5d483d872dfec1b89d88d348666ecd59454d52"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/wp-cli/i18n-command/zipball/2804c5246d9338da59951737b03c54d257be8e47",
"reference": "2804c5246d9338da59951737b03c54d257be8e47",
"url": "https://api.github.com/repos/wp-cli/i18n-command/zipball/7a5d483d872dfec1b89d88d348666ecd59454d52",
"reference": "7a5d483d872dfec1b89d88d348666ecd59454d52",
"shasum": ""
},
"require": {
@ -2746,7 +2707,7 @@
],
"description": "Provides internationalization tools for WordPress projects.",
"homepage": "https://github.com/wp-cli/i18n-command",
"time": "2019-12-13T09:00:43+00:00"
"time": "2020-06-04T07:07:10+00:00"
},
{
"name": "wp-cli/mustangostang-spyc",
@ -2965,6 +2926,5 @@
"platform-dev": [],
"platform-overrides": {
"php": "7.1"
},
"plugin-api-version": "1.1.0"
}
}

View File

@ -1,57 +1,14 @@
version: '3.7'
version: '3.3'
services:
db:
image: mariadb:10.5
restart: on-failure
environment:
MYSQL_DATABASE: testdb
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress
MYSQL_RANDOM_ROOT_PASSWORD: 'yes'
wordpress-www:
volumes:
- db:/var/lib/mysql
wordpress-woocommerce-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:
- "./:/var/www/html/wp-content/plugins/woocommerce"
- wordpress:/var/www/html
# This path is relative to the first config file
# which is in tests/e2e/env or node_modules/@woocommerce/e2e-environment
- "../../../:/var/www/html/wp-content/plugins/woocommerce"
wordpress-cli:
depends_on:
- db
- wordpress-woocommerce-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:
- "./:/var/www/html/wp-content/plugins/woocommerce"
- wordpress:/var/www/html
- "../../../:/var/www/html/wp-content/plugins/woocommerce"
volumes:
db:
wordpress:

View File

@ -349,6 +349,25 @@ return array(
),
'FI' => array(),
'FR' => array(),
'GH' => array( // Ghanaian Regions.
'AF' => __( 'Ahafo', 'woocommerce' ),
'AH' => __( 'Ashanti', 'woocommerce' ),
'BA' => __( 'Brong-Ahafo', 'woocommerce' ),
'BO' => __( 'Bono', 'woocommerce' ),
'BE' => __( 'Bono East', 'woocommerce' ),
'CP' => __( 'Central', 'woocommerce' ),
'EP' => __( 'Eastern', 'woocommerce' ),
'AA' => __( 'Greater Accra', 'woocommerce' ),
'NE' => __( 'North East', 'woocommerce' ),
'NP' => __( 'Northern', 'woocommerce' ),
'OT' => __( 'Oti', 'woocommerce' ),
'SV' => __( 'Savannah', 'woocommerce' ),
'UE' => __( 'Upper East', 'woocommerce' ),
'UW' => __( 'Upper West', 'woocommerce' ),
'TV' => __( 'Volta', 'woocommerce' ),
'WP' => __( 'Western', 'woocommerce' ),
'WN' => __( 'Western North', 'woocommerce' ),
),
'GP' => array(),
'GR' => array( // Greek Regions.
'I' => __( 'Αττική', 'woocommerce' ),
@ -696,6 +715,55 @@ return array(
'JP46' => __( 'Kagoshima', 'woocommerce' ),
'JP47' => __( 'Okinawa', 'woocommerce' ),
),
'KE' => array( // Kenya counties.
'KE01' => __( 'Baringo', 'woocommerce' ),
'KE02' => __( 'Bomet', 'woocommerce' ),
'KE03' => __( 'Bungoma', 'woocommerce' ),
'KE04' => __( 'Busia', 'woocommerce' ),
'KE05' => __( 'Elgeyo-Marakwet', 'woocommerce' ),
'KE06' => __( 'Embu', 'woocommerce' ),
'KE07' => __( 'Garissa', 'woocommerce' ),
'KE08' => __( 'Homa Bay', 'woocommerce' ),
'KE09' => __( 'Isiolo', 'woocommerce' ),
'KE10' => __( 'Kajiado', 'woocommerce' ),
'KE11' => __( 'Kakamega', 'woocommerce' ),
'KE12' => __( 'Kericho', 'woocommerce' ),
'KE13' => __( 'Kiambu', 'woocommerce' ),
'KE14' => __( 'Kilifi', 'woocommerce' ),
'KE15' => __( 'Kirinyaga', 'woocommerce' ),
'KE16' => __( 'Kisii', 'woocommerce' ),
'KE17' => __( 'Kisumu', 'woocommerce' ),
'KE18' => __( 'Kitui', 'woocommerce' ),
'KE19' => __( 'Kwale', 'woocommerce' ),
'KE20' => __( 'Laikipia', 'woocommerce' ),
'KE21' => __( 'Lamu', 'woocommerce' ),
'KE22' => __( 'Machakos', 'woocommerce' ),
'KE23' => __( 'Makueni', 'woocommerce' ),
'KE24' => __( 'Mandera', 'woocommerce' ),
'KE25' => __( 'Marsabit', 'woocommerce' ),
'KE26' => __( 'Meru', 'woocommerce' ),
'KE27' => __( 'Migori', 'woocommerce' ),
'KE28' => __( 'Mombasa', 'woocommerce' ),
'KE29' => __( 'Muranga', 'woocommerce' ),
'KE30' => __( 'Nairobi County', 'woocommerce' ),
'KE31' => __( 'Nakuru', 'woocommerce' ),
'KE32' => __( 'Nandi', 'woocommerce' ),
'KE33' => __( 'Narok', 'woocommerce' ),
'KE34' => __( 'Nyamira', 'woocommerce' ),
'KE35' => __( 'Nyandarua', 'woocommerce' ),
'KE36' => __( 'Nyeri', 'woocommerce' ),
'KE37' => __( 'Samburu', 'woocommerce' ),
'KE38' => __( 'Siaya', 'woocommerce' ),
'KE39' => __( 'Taita-Taveta', 'woocommerce' ),
'KE40' => __( 'Tana River', 'woocommerce' ),
'KE41' => __( 'Tharaka-Nithi', 'woocommerce' ),
'KE42' => __( 'Trans Nzoia', 'woocommerce' ),
'KE43' => __( 'Turkana', 'woocommerce' ),
'KE44' => __( 'Uasin Gishu', 'woocommerce' ),
'KE45' => __( 'Vihiga', 'woocommerce' ),
'KE46' => __( 'Wajir', 'woocommerce' ),
'KE47' => __( 'West Pokot', 'woocommerce' ),
),
'KR' => array(),
'KW' => array(),
'LA' => array(
@ -828,6 +896,19 @@ return array(
'PJY' => __( 'Putrajaya', 'woocommerce' ),
'KUL' => __( 'Kuala Lumpur', 'woocommerce' ),
),
'MZ' => array( // Mozambique provinces.
'MZP' => __( 'Cabo Delgado', 'woocommerce' ),
'MZG' => __( 'Gaza', 'woocommerce' ),
'MZI' => __( 'Inhambane', 'woocommerce' ),
'MZB' => __( 'Manica', 'woocommerce' ),
'MZL' => __( 'Maputo Province', 'woocommerce' ),
'MZMPM' => __( 'Maputo', 'woocommerce' ),
'MZN' => __( 'Nampula', 'woocommerce' ),
'MZA' => __( 'Niassa', 'woocommerce' ),
'MZS' => __( 'Sofala', 'woocommerce' ),
'MZT' => __( 'Tete', 'woocommerce' ),
'MZQ' => __( 'Zambézia', 'woocommerce' ),
),
'NG' => array( // Nigerian provinces.
'AB' => __( 'Abia', 'woocommerce' ),
'FC' => __( 'Abuja', 'woocommerce' ),

View File

@ -437,12 +437,7 @@ abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order {
* @return float
*/
public function get_subtotal() {
$subtotal = 0;
foreach ( $this->get_items() as $item ) {
$subtotal += wc_remove_number_precision( self::round_item_subtotal( wc_add_number_precision( $item->get_subtotal() ) ) );
}
$subtotal = round( $this->get_cart_subtotal_for_order(), wc_get_price_decimals() );
return apply_filters( 'woocommerce_order_get_subtotal', (float) $subtotal, $this );
}
@ -1672,18 +1667,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;
$shipping_total = 0;
$cart_subtotal_tax = 0;
$cart_total_tax = 0;
// Sum line item costs without rounding.
foreach ( $this->get_items() as $item ) {
$cart_subtotal += $item->get_subtotal();
$cart_total += $item->get_total();
}
$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 ) {

View File

@ -708,7 +708,7 @@ abstract class WC_Settings_API {
<legend class="screen-reader-text"><span><?php echo wp_kses_post( $data['title'] ); ?></span></legend>
<select class="select <?php echo esc_attr( $data['class'] ); ?>" name="<?php echo esc_attr( $field_key ); ?>" id="<?php echo esc_attr( $field_key ); ?>" style="<?php echo esc_attr( $data['css'] ); ?>" <?php disabled( $data['disabled'], true ); ?> <?php echo $this->get_custom_attribute_html( $data ); // WPCS: XSS ok. ?>>
<?php foreach ( (array) $data['options'] as $option_key => $option_value ) : ?>
<option value="<?php echo esc_attr( $option_key ); ?>" <?php selected( (string) $option_key, esc_attr( $this->get_option( $key ) ) ); ?>><?php echo esc_attr( $option_value ); ?></option>
<option value="<?php echo esc_attr( $option_key ); ?>" <?php selected( (string) $option_key, esc_attr( $this->get_option( $key ) ) ); ?>><?php echo esc_html( $option_value ); ?></option>
<?php endforeach; ?>
</select>
<?php echo $this->get_description_html( $data ); // WPCS: XSS ok. ?>
@ -761,11 +761,11 @@ abstract class WC_Settings_API {
<?php if ( is_array( $option_value ) ) : ?>
<optgroup label="<?php echo esc_attr( $option_key ); ?>">
<?php foreach ( $option_value as $option_key_inner => $option_value_inner ) : ?>
<option value="<?php echo esc_attr( $option_key_inner ); ?>" <?php selected( in_array( (string) $option_key_inner, $value, true ), true ); ?>><?php echo esc_attr( $option_value_inner ); ?></option>
<option value="<?php echo esc_attr( $option_key_inner ); ?>" <?php selected( in_array( (string) $option_key_inner, $value, true ), true ); ?>><?php echo esc_html( $option_value_inner ); ?></option>
<?php endforeach; ?>
</optgroup>
<?php else : ?>
<option value="<?php echo esc_attr( $option_key ); ?>" <?php selected( in_array( (string) $option_key, $value, true ), true ); ?>><?php echo esc_attr( $option_value ); ?></option>
<option value="<?php echo esc_attr( $option_key ); ?>" <?php selected( in_array( (string) $option_key, $value, true ), true ); ?>><?php echo esc_html( $option_value ); ?></option>
<?php endif; ?>
<?php endforeach; ?>
</select>

View File

@ -51,13 +51,13 @@ class WC_Admin_Addons {
*/
public static function build_parameter_string( $category, $term, $country ) {
$paramters = array(
$parameters = array(
'category' => $category,
'term' => $term,
'country' => $country,
);
return '?' . http_build_query( $paramters );
return '?' . http_build_query( $parameters );
}
/**

View File

@ -44,6 +44,7 @@ if ( ! class_exists( 'WC_Admin_Assets', false ) ) :
wp_register_style( 'woocommerce_admin_dashboard_styles', WC()->plugin_url() . '/assets/css/dashboard.css', array(), $version );
wp_register_style( 'woocommerce_admin_print_reports_styles', WC()->plugin_url() . '/assets/css/reports-print.css', array(), $version, 'print' );
wp_register_style( 'woocommerce_admin_marketplace_styles', WC()->plugin_url() . '/assets/css/marketplace-suggestions.css', array(), $version );
wp_register_style( 'woocommerce_admin_privacy_styles', WC()->plugin_url() . '/assets/css/privacy.css', array(), $version );
// Add RTL support for admin styles.
wp_style_add_data( 'woocommerce_admin_menu_styles', 'rtl', 'replace' );
@ -51,6 +52,7 @@ if ( ! class_exists( 'WC_Admin_Assets', false ) ) :
wp_style_add_data( 'woocommerce_admin_dashboard_styles', 'rtl', 'replace' );
wp_style_add_data( 'woocommerce_admin_print_reports_styles', 'rtl', 'replace' );
wp_style_add_data( 'woocommerce_admin_marketplace_styles', 'rtl', 'replace' );
wp_style_add_data( 'woocommerce_admin_privacy_styles', 'rtl', 'replace' );
// Sitewide menu CSS.
wp_enqueue_style( 'woocommerce_admin_menu_styles' );
@ -70,6 +72,11 @@ if ( ! class_exists( 'WC_Admin_Assets', false ) ) :
wp_enqueue_style( 'woocommerce_admin_print_reports_styles' );
}
// Privacy Policy Guide css for back-compat.
if ( isset( $_GET['wp-privacy-policy-guide'] ) || in_array( $screen_id, array( 'privacy-policy-guide' ) ) ) {
wp_enqueue_style( 'woocommerce_admin_privacy_styles' );
}
// @deprecated 2.3.
if ( has_action( 'woocommerce_admin_css' ) ) {
do_action( 'woocommerce_admin_css' );

View File

@ -216,36 +216,61 @@ if ( ! class_exists( 'WC_Admin_Dashboard', false ) ) :
$lowinstock_count = get_transient( $transient_name );
if ( false === $lowinstock_count ) {
$lowinstock_count = (int) $wpdb->get_var(
$wpdb->prepare(
"SELECT COUNT( product_id )
FROM {$wpdb->wc_product_meta_lookup} AS lookup
INNER JOIN {$wpdb->posts} as posts ON lookup.product_id = posts.ID
WHERE stock_quantity <= %d
AND stock_quantity > %d
AND posts.post_status = 'publish'",
$stock,
$nostock
)
);
set_transient( $transient_name, $lowinstock_count, DAY_IN_SECONDS * 30 );
/**
* Status widget low in stock count pre query.
*
* @since 4.3.0
* @param null|string $low_in_stock_count Low in stock count, by default null.
* @param int $stock Low stock amount.
* @param int $nostock No stock amount
*/
$lowinstock_count = apply_filters( 'woocommerce_status_widget_low_in_stock_count_pre_query', null, $stock, $nostock );
if ( is_null( $lowinstock_count ) ) {
$lowinstock_count = $wpdb->get_var(
$wpdb->prepare(
"SELECT COUNT( product_id )
FROM {$wpdb->wc_product_meta_lookup} AS lookup
INNER JOIN {$wpdb->posts} as posts ON lookup.product_id = posts.ID
WHERE stock_quantity <= %d
AND stock_quantity > %d
AND posts.post_status = 'publish'",
$stock,
$nostock
)
);
}
set_transient( $transient_name, (int) $lowinstock_count, DAY_IN_SECONDS * 30 );
}
$transient_name = 'wc_outofstock_count';
$outofstock_count = get_transient( $transient_name );
if ( false === $outofstock_count ) {
$outofstock_count = (int) $wpdb->get_var(
$wpdb->prepare(
"SELECT COUNT( product_id )
FROM {$wpdb->wc_product_meta_lookup} AS lookup
INNER JOIN {$wpdb->posts} as posts ON lookup.product_id = posts.ID
WHERE stock_quantity <= %d
AND posts.post_status = 'publish'",
$nostock
)
);
set_transient( $transient_name, $outofstock_count, DAY_IN_SECONDS * 30 );
/**
* Status widget out of stock count pre query.
*
* @since 4.3.0
* @param null|string $outofstock_count Out of stock count, by default null.
* @param int $nostock No stock amount
*/
$outofstock_count = apply_filters( 'woocommerce_status_widget_out_of_stock_count_pre_query', null, $nostock );
if ( is_null( $outofstock_count ) ) {
$outofstock_count = (int) $wpdb->get_var(
$wpdb->prepare(
"SELECT COUNT( product_id )
FROM {$wpdb->wc_product_meta_lookup} AS lookup
INNER JOIN {$wpdb->posts} as posts ON lookup.product_id = posts.ID
WHERE stock_quantity <= %d
AND posts.post_status = 'publish'",
$nostock
)
);
}
set_transient( $transient_name, (int) $outofstock_count, DAY_IN_SECONDS * 30 );
}
?>
<li class="low-in-stock">

View File

@ -184,7 +184,7 @@ class WC_Admin_Menus {
// Add count if user has access.
if ( apply_filters( 'woocommerce_include_processing_order_count_in_menu', true ) && current_user_can( 'edit_others_shop_orders' ) ) {
$order_count = wc_processing_order_count();
$order_count = apply_filters( 'woocommerce_menu_order_count', wc_processing_order_count() );
if ( $order_count ) {
foreach ( $submenu['woocommerce'] as $key => $menu_item ) {

View File

@ -49,9 +49,9 @@ class WC_Admin_Meta_Boxes {
* Save order data - also updates status and sends out admin emails if needed. Last to show latest data.
* Save actions - sends out other emails. Last to show latest data.
*/
add_action( 'woocommerce_process_shop_order_meta', 'WC_Meta_Box_Order_Items::save', 10, 2 );
add_action( 'woocommerce_process_shop_order_meta', 'WC_Meta_Box_Order_Items::save', 10 );
add_action( 'woocommerce_process_shop_order_meta', 'WC_Meta_Box_Order_Downloads::save', 30, 2 );
add_action( 'woocommerce_process_shop_order_meta', 'WC_Meta_Box_Order_Data::save', 40, 2 );
add_action( 'woocommerce_process_shop_order_meta', 'WC_Meta_Box_Order_Data::save', 40 );
add_action( 'woocommerce_process_shop_order_meta', 'WC_Meta_Box_Order_Actions::save', 50, 2 );
// Save Product Meta Boxes.

View File

@ -28,17 +28,19 @@ class WC_Admin_Notices {
* @var array
*/
private static $core_notices = array(
'install' => 'install_notice',
'update' => 'update_notice',
'template_files' => 'template_file_check_notice',
'legacy_shipping' => 'legacy_shipping_notice',
'no_shipping_methods' => 'no_shipping_methods_notice',
'regenerating_thumbnails' => 'regenerating_thumbnails_notice',
'regenerating_lookup_table' => 'regenerating_lookup_table_notice',
'no_secure_connection' => 'secure_connection_notice',
WC_PHP_MIN_REQUIREMENTS_NOTICE => 'wp_php_min_requirements_notice',
'maxmind_license_key' => 'maxmind_missing_license_key_notice',
'redirect_download_method' => 'redirect_download_method_notice',
'install' => 'install_notice',
'update' => 'update_notice',
'template_files' => 'template_file_check_notice',
'legacy_shipping' => 'legacy_shipping_notice',
'no_shipping_methods' => 'no_shipping_methods_notice',
'regenerating_thumbnails' => 'regenerating_thumbnails_notice',
'regenerating_lookup_table' => 'regenerating_lookup_table_notice',
'no_secure_connection' => 'secure_connection_notice',
WC_PHP_MIN_REQUIREMENTS_NOTICE => 'wp_php_min_requirements_notice',
'maxmind_license_key' => 'maxmind_missing_license_key_notice',
'redirect_download_method' => 'redirect_download_method_notice',
'uploads_directory_is_unprotected' => 'uploads_directory_is_unprotected_notice',
'base_tables_missing' => 'base_tables_missing_notice',
);
/**
@ -93,6 +95,9 @@ class WC_Admin_Notices {
if ( ! self::is_ssl() ) {
self::add_notice( 'no_secure_connection' );
}
if ( ! self::is_uploads_directory_protected() ) {
self::add_notice( 'uploads_directory_is_unprotected' );
}
self::add_notice( 'template_files' );
self::add_min_version_notice();
self::add_maxmind_missing_license_key_notice();
@ -488,6 +493,35 @@ class WC_Admin_Notices {
include dirname( __FILE__ ) . '/views/html-notice-redirect-only-download.php';
}
/**
* Notice about uploads directory begin unprotected.
*
* @since 4.2.0
*/
public static function uploads_directory_is_unprotected_notice() {
if ( get_user_meta( get_current_user_id(), 'dismissed_uploads_directory_is_unprotected_notice', true ) || self::is_uploads_directory_protected() ) {
self::remove_notice( 'uploads_directory_is_unprotected' );
return;
}
include dirname( __FILE__ ) . '/views/html-notice-uploads-directory-is-unprotected.php';
}
/**
* Notice about base tables missing.
*/
public static function base_tables_missing_notice() {
$notice_dismissed = apply_filters(
'woocommerce_hide_base_tables_missing_nag',
get_user_meta( get_current_user_id(), 'dismissed_base_tables_missing_notice', true )
);
if ( $notice_dismissed ) {
self::remove_notice( 'base_tables_missing' );
}
include dirname( __FILE__ ) . '/views/html-notice-base-table-missing.php';
}
/**
* Determine if the store is running SSL.
*
@ -530,6 +564,42 @@ class WC_Admin_Notices {
public static function theme_check_notice() {
wc_deprecated_function( 'WC_Admin_Notices::theme_check_notice', '3.3.0' );
}
/**
* Check if uploads directory is protected.
*
* @since 4.2.0
* @return bool
*/
protected static function is_uploads_directory_protected() {
$cache_key = '_woocommerce_upload_directory_status';
$status = get_transient( $cache_key );
// Check for cache.
if ( false !== $status ) {
return 'protected' === $status;
}
// Get only data from the uploads directory.
$uploads = wp_get_upload_dir();
// Check for the "uploads/woocommerce_uploads" directory.
$response = wp_safe_remote_get(
esc_url_raw( $uploads['baseurl'] . '/woocommerce_uploads/' ),
array(
'redirection' => 0,
)
);
$response_code = intval( wp_remote_retrieve_response_code( $response ) );
$response_content = wp_remote_retrieve_body( $response );
// Check if returns 200 with empty content in case can open an index.html file,
// and check for non-200 codes in case the directory is protected.
$is_protected = ( 200 === $response_code && empty( $response_content ) ) || ( 200 !== $response_code );
set_transient( $cache_key, $is_protected ? 'protected' : 'unprotected', 1 * DAY_IN_SECONDS );
return $is_protected;
}
}
WC_Admin_Notices::init();

View File

@ -200,7 +200,7 @@ if ( ! class_exists( 'WC_Admin_Settings', false ) ) :
/**
* Output admin fields.
*
* Loops though the woocommerce options array and outputs each field.
* Loops through the woocommerce options array and outputs each field.
*
* @param array[] $options Opens array to output.
*/
@ -726,7 +726,7 @@ if ( ! class_exists( 'WC_Admin_Settings', false ) ) :
/**
* Save admin fields.
*
* Loops though the woocommerce options array and outputs each field.
* Loops through the woocommerce options array and outputs each field.
*
* @param array $options Options array to output.
* @param array $data Optional. Data to use for saving. Defaults to $_POST.
@ -869,25 +869,29 @@ if ( ! class_exists( 'WC_Admin_Settings', false ) ) :
* If using force or x-sendfile, this ensures the .htaccess is in place.
*/
public static function check_download_folder_protection() {
$upload_dir = wp_upload_dir();
$downloads_url = $upload_dir['basedir'] . '/woocommerce_uploads';
$upload_dir = wp_get_upload_dir();
$downloads_path = $upload_dir['basedir'] . '/woocommerce_uploads';
$download_method = get_option( 'woocommerce_file_download_method' );
$file_path = $downloads_path . '/.htaccess';
$file_content = 'redirect' === $download_method ? 'Options -Indexes' : 'deny from all';
$create = false;
if ( 'redirect' === $download_method ) {
// Redirect method - don't protect.
if ( file_exists( $downloads_url . '/.htaccess' ) ) {
unlink( $downloads_url . '/.htaccess' ); // @codingStandardsIgnoreLine
}
if ( wp_mkdir_p( $downloads_path ) && ! file_exists( $file_path ) ) {
$create = true;
} else {
$current_content = @file_get_contents( $file_path ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged, WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
// Force method - protect, add rules to the htaccess file.
if ( ! file_exists( $downloads_url . '/.htaccess' ) ) {
$file_handle = @fopen( $downloads_url . '/.htaccess', 'w' ); // @codingStandardsIgnoreLine
if ( $file_handle ) {
fwrite( $file_handle, 'deny from all' ); // @codingStandardsIgnoreLine
fclose( $file_handle ); // @codingStandardsIgnoreLine
}
if ( $current_content !== $file_content ) {
unlink( $file_path );
$create = true;
}
}
if ( $create ) {
$file_handle = @fopen( $file_path, 'wb' ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged, WordPress.WP.AlternativeFunctions.file_system_read_fopen
if ( $file_handle ) {
fwrite( $file_handle, $file_content ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_read_fwrite
fclose( $file_handle ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_read_fclose
}
}
}

View File

@ -339,6 +339,33 @@ class WC_Admin_Status {
}
}
/**
* Prints table info if a base table is not present.
*/
private static function output_tables_info() {
$missing_tables = WC_Install::verify_base_tables( false );
if ( 0 === count( $missing_tables ) ) {
return;
}
?>
<br>
<strong style="color:#a00;">
<span class="dashicons dashicons-warning"></span>
<?php
echo esc_html(
sprintf(
// translators: Comma seperated list of missing tables.
__( 'Missing base tables: %s. Some WooCommerce functionality may not work as expected.', 'woocommerce' ),
implode( ', ', $missing_tables )
)
);
?>
</strong>
<?php
}
/**
* Prints the information about plugins for the system status report.
* Used for both active and inactive plugins sections.

View File

@ -33,6 +33,9 @@ class WC_Admin {
// Disable WXR export of schedule action posts.
add_filter( 'action_scheduler_post_type_args', array( $this, 'disable_webhook_post_export' ) );
// Add body class for WP 5.3+ compatibility.
add_filter( 'admin_body_class', array( $this, 'include_admin_body_class' ) );
}
/**
@ -306,6 +309,30 @@ class WC_Admin {
$args['can_export'] = false;
return $args;
}
/**
* Include admin classes.
*
* @since 4.2.0
* @param string $classes Body classes string.
* @return string
*/
public function include_admin_body_class( $classes ) {
if ( false !== strpos( $classes, 'wc-wp-version-gte-53' ) ) {
return $classes;
}
$raw_version = get_bloginfo( 'version' );
$version_parts = explode( '-', $raw_version );
$version = count( $version_parts ) > 1 ? $version_parts[0] : $raw_version;
// Add WP 5.3+ compatibility class.
if ( $raw_version && version_compare( $version, '5.3', '>=' ) ) {
$classes .= ' wc-wp-version-gte-53';
}
return $classes;
}
}
return new WC_Admin();

View File

@ -97,10 +97,11 @@ class WC_Helper_API {
$args['headers'] = array();
}
$args['headers'] = array(
$headers = array(
'Authorization' => 'Bearer ' . $auth['access_token'],
'X-Woo-Signature' => $signature,
);
$args['headers'] = wp_parse_args( $headers, $args['headers'] );
$url = add_query_arg(
array(
@ -139,6 +140,19 @@ class WC_Helper_API {
return self::request( $endpoint, $args );
}
/**
* Wrapper for self::request().
*
* @param string $endpoint The helper API endpoint to request.
* @param array $args Arguments passed to wp_remote_request().
*
* @return array The response object from wp_safe_remote_request().
*/
public static function put( $endpoint, $args = array() ) {
$args['method'] = 'PUT';
return self::request( $endpoint, $args );
}
/**
* Using the API base, form a request URL from a given endpoint.
*

View File

@ -471,6 +471,7 @@ class WC_Helper {
if ( $wc_screen_id . '_page_wc-addons' === $screen_id && isset( $_GET['section'] ) && 'helper' === $_GET['section'] ) {
wp_enqueue_style( 'woocommerce-helper', WC()->plugin_url() . '/assets/css/helper.css', array(), Constants::get_constant( 'WC_VERSION' ) );
wp_style_add_data( 'woocommerce-helper', 'rtl', 'replace' );
}
}
@ -1149,9 +1150,18 @@ class WC_Helper {
require_once ABSPATH . 'wp-admin/includes/plugin.php';
}
// Reset plugin cache before retrieving plugin list.
wp_clean_plugins_cache();
$plugins = get_plugins();
$plugins = get_plugins();
/**
* Check if plugins have WC headers, if not then clear cache and fetch again.
* WC Headers will not be present if `wc_enable_wc_plugin_headers` hook was added after a `get_plugins` call -- for example when WC is activated/updated.
* Also, get_plugins call is expensive so we should clear this cache very conservatively.
*/
if ( ! empty( $plugins ) && ! array_key_exists( 'Woo', current( $plugins ) ) ) {
wp_clean_plugins_cache( false );
$plugins = get_plugins();
}
$woo_plugins = array();
// Backwards compatibility for woothemes_queue_update().
@ -1469,8 +1479,6 @@ class WC_Helper {
$screen = get_current_screen();
$screen_id = $screen ? $screen->id : '';
self::_prompt_helper_connect( $screen_id );
if ( 'update-core' !== $screen_id ) {
return;
}
@ -1487,56 +1495,6 @@ class WC_Helper {
}
}
/**
* Prompt a Helper connection if the user has WooCommerce.com extensions.
*
* @param string $screen_id Current screen ID.
*/
private static function _prompt_helper_connect( $screen_id ) {
if ( apply_filters( 'woocommerce_helper_suppress_connect_notice', false ) ) {
return;
}
$screens = wc_get_screen_ids();
$screens[] = 'plugins';
if ( ! in_array( $screen_id, $screens, true ) ) {
return;
}
// Don't show the notice on the Helper screens.
$screen_addons = sanitize_title( __( 'WooCommerce', 'woocommerce' ) ) . '_page_wc-addons';
if ( $screen_addons === $screen_id && ! empty( $_REQUEST['section'] ) && 'helper' === $_REQUEST['section'] ) {
return;
}
// We believe we have an active connection.
$auth = WC_Helper_Options::get( 'auth' );
if ( ! empty( $auth['access_token'] ) ) {
return;
}
$active_plugins = apply_filters( 'active_plugins', get_option( 'active_plugins' ) );
if ( empty( $active_plugins ) ) {
return;
}
$woo_plugins = self::get_local_woo_plugins();
if ( empty( $woo_plugins ) ) {
return;
}
$active_woo_plugins = array_intersect_key( $woo_plugins, array_flip( $active_plugins ) );
if ( count( $active_woo_plugins ) > 0 ) {
/* translators: %s: helper screen url */
$notice = __( '<a href="%s">Connect your store</a> to WooCommerce.com to receive extensions updates and support.', 'woocommerce' );
$notice = sprintf( $notice, admin_url( 'admin.php?page=wc-addons&section=helper' ) );
echo '<div class="updated woocommerce-message"><p>' . wp_kses_post( $notice ) . '</p></div>';
}
}
/**
* Get an update notice if one or more Woo extensions has an update available.
*

View File

@ -319,6 +319,7 @@ class WC_Product_CSV_Importer_Controller {
return new WP_Error( 'woocommerce_product_csv_importer_upload_file_empty', __( 'File is empty. Please upload something more substantial. This error could also be caused by uploads being disabled in your php.ini or by post_max_size being defined as smaller than upload_max_filesize in php.ini.', 'woocommerce' ) );
}
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated
if ( ! self::is_file_valid_csv( wc_clean( wp_unslash( $_FILES['import']['name'] ) ), false ) ) {
return new WP_Error( 'woocommerce_product_csv_importer_upload_file_invalid', __( 'Invalid file type. The importer supports CSV and TXT file formats.', 'woocommerce' ) );
}
@ -327,7 +328,7 @@ class WC_Product_CSV_Importer_Controller {
'test_form' => false,
'mimes' => self::get_valid_csv_filetypes(),
);
$import = $_FILES['import']; // WPCS: sanitization ok, input var ok.
$import = $_FILES['import']; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized,WordPress.Security.ValidatedSanitizedInput.MissingUnslash
$upload = wp_handle_upload( $import, $overrides );
if ( isset( $upload['error'] ) ) {
@ -577,14 +578,15 @@ class WC_Product_CSV_Importer_Controller {
$headers = array();
foreach ( $raw_headers as $key => $field ) {
$field = strtolower( $field );
$normalized_field = strtolower( $field );
$index = $num_indexes ? $key : $field;
$headers[ $index ] = $field;
$headers[ $index ] = $normalized_field;
if ( isset( $default_columns[ $field ] ) ) {
$headers[ $index ] = $default_columns[ $field ];
if ( isset( $default_columns[ $normalized_field ] ) ) {
$headers[ $index ] = $default_columns[ $normalized_field ];
} else {
foreach ( $special_columns as $regex => $special_key ) {
// Don't use the normalized field in the regex since meta might be case-sensitive.
if ( preg_match( $regex, $field, $matches ) ) {
$headers[ $index ] = $special_key . $matches[1];
break;
@ -619,7 +621,7 @@ class WC_Product_CSV_Importer_Controller {
* @return string
*/
protected function sanitize_special_column_name_regex( $value ) {
return '/' . str_replace( array( '%d', '%s' ), '(.*)', trim( quotemeta( $value ) ) ) . '/';
return '/' . str_replace( array( '%d', '%s' ), '(.*)', trim( quotemeta( $value ) ) ) . '/i';
}
/**

View File

@ -12,7 +12,7 @@ if ( ! defined( 'ABSPATH' ) ) {
<form class="wc-progress-form-content woocommerce-importer" enctype="multipart/form-data" method="post">
<header>
<h2><?php esc_html_e( 'Import products from a CSV file', 'woocommerce' ); ?></h2>
<p><?php esc_html_e( 'This tool allows you to import (or merge) product data to your store from a CSV file.', 'woocommerce' ); ?></p>
<p><?php esc_html_e( 'This tool allows you to import (or merge) product data to your store from a CSV or TXT file.', 'woocommerce' ); ?></p>
</header>
<section>
<table class="form-table woocommerce-importer-options">

View File

@ -351,7 +351,7 @@ class WC_Admin_List_Table_Products extends WC_Admin_List_Table {
*/
protected function render_products_type_filter() {
$current_product_type = isset( $_REQUEST['product_type'] ) ? wc_clean( wp_unslash( $_REQUEST['product_type'] ) ) : false; // WPCS: input var ok, sanitization ok.
$output = '<select name="product_type" id="dropdown_product_type"><option value="">' . __( 'Filter by product type', 'woocommerce' ) . '</option>';
$output = '<select name="product_type" id="dropdown_product_type"><option value="">' . esc_html__( 'Filter by product type', 'woocommerce' ) . '</option>';
foreach ( wc_get_product_types() as $value => $label ) {
$output .= '<option value="' . esc_attr( $value ) . '" ';
@ -362,11 +362,11 @@ class WC_Admin_List_Table_Products extends WC_Admin_List_Table {
$output .= '<option value="downloadable" ';
$output .= selected( 'downloadable', $current_product_type, false );
$output .= '> ' . ( is_rtl() ? '&larr;' : '&rarr;' ) . ' ' . __( 'Downloadable', 'woocommerce' ) . '</option>';
$output .= '> ' . ( is_rtl() ? '&larr;' : '&rarr;' ) . ' ' . esc_html__( 'Downloadable', 'woocommerce' ) . '</option>';
$output .= '<option value="virtual" ';
$output .= selected( 'virtual', $current_product_type, false );
$output .= '> ' . ( is_rtl() ? '&larr;' : '&rarr;' ) . ' ' . __( 'Virtual', 'woocommerce' ) . '</option>';
$output .= '> ' . ( is_rtl() ? '&larr;' : '&rarr;' ) . ' ' . esc_html__( 'Virtual', 'woocommerce' ) . '</option>';
}
}

View File

@ -194,7 +194,7 @@ class WC_Meta_Box_Coupon_Data {
foreach ( $product_ids as $product_id ) {
$product = wc_get_product( $product_id );
if ( is_object( $product ) ) {
echo '<option value="' . esc_attr( $product_id ) . '"' . selected( true, true, false ) . '>' . wp_kses_post( $product->get_formatted_name() ) . '</option>';
echo '<option value="' . esc_attr( $product_id ) . '"' . selected( true, true, false ) . '>' . htmlspecialchars( wp_kses_post( $product->get_formatted_name() ) ) . '</option>';
}
}
?>
@ -212,7 +212,7 @@ class WC_Meta_Box_Coupon_Data {
foreach ( $product_ids as $product_id ) {
$product = wc_get_product( $product_id );
if ( is_object( $product ) ) {
echo '<option value="' . esc_attr( $product_id ) . '"' . selected( true, true, false ) . '>' . wp_kses_post( $product->get_formatted_name() ) . '</option>';
echo '<option value="' . esc_attr( $product_id ) . '"' . selected( true, true, false ) . '>' . htmlspecialchars( wp_kses_post( $product->get_formatted_name() ) ) . '</option>';
}
}
?>

View File

@ -404,9 +404,9 @@ class WC_Meta_Box_Order_Data {
}
if ( ! $found_method && ! empty( $payment_method ) ) {
echo '<option value="' . esc_attr( $payment_method ) . '" selected="selected">' . __( 'Other', 'woocommerce' ) . '</option>';
echo '<option value="' . esc_attr( $payment_method ) . '" selected="selected">' . esc_html__( 'Other', 'woocommerce' ) . '</option>';
} else {
echo '<option value="other">' . __( 'Other', 'woocommerce' ) . '</option>';
echo '<option value="other">' . esc_html__( 'Other', 'woocommerce' ) . '</option>';
}
?>
</select>

View File

@ -244,7 +244,7 @@ class WC_Meta_Box_Product_Data {
continue;
}
$attribute_id = 0;
$attribute_name = wc_clean( $attribute_names[ $i ] );
$attribute_name = wc_clean( esc_html( $attribute_names[ $i ] ) );
if ( 'pa_' === substr( $attribute_name, 0, 3 ) ) {
$attribute_id = wc_attribute_taxonomy_id_by_name( $attribute_name );
@ -257,7 +257,7 @@ class WC_Meta_Box_Product_Data {
$options = wp_parse_id_list( $options );
} else {
// Terms or text sent in textarea.
$options = 0 < $attribute_id ? wc_sanitize_textarea( wc_sanitize_term_text_based( $options ) ) : wc_sanitize_textarea( $options );
$options = 0 < $attribute_id ? wc_sanitize_textarea( esc_html( wc_sanitize_term_text_based( $options ) ) ) : wc_sanitize_textarea( esc_html( $options ) );
$options = wc_get_text_attributes( $options );
}

View File

@ -49,7 +49,7 @@ if ( ! defined( 'ABSPATH' ) ) {
foreach ( $all_terms as $term ) {
$options = $attribute->get_options();
$options = ! empty( $options ) ? $options : array();
echo '<option value="' . esc_attr( $term->term_id ) . '"' . wc_selected( $term->term_id, $options ) . '>' . esc_attr( apply_filters( 'woocommerce_product_attribute_term_name', $term->name, $term ) ) . '</option>';
echo '<option value="' . esc_attr( $term->term_id ) . '"' . wc_selected( $term->term_id, $options ) . '>' . esc_html( apply_filters( 'woocommerce_product_attribute_term_name', $term->name, $term ) ) . '</option>';
}
}
?>

View File

@ -19,7 +19,7 @@ defined( 'ABSPATH' ) || exit;
foreach ( $product_ids as $product_id ) {
$product = wc_get_product( $product_id );
if ( is_object( $product ) ) {
echo '<option value="' . esc_attr( $product_id ) . '"' . selected( true, true, false ) . '>' . wp_kses_post( $product->get_formatted_name() ) . '</option>';
echo '<option value="' . esc_attr( $product_id ) . '"' . selected( true, true, false ) . '>' . htmlspecialchars( wp_kses_post( $product->get_formatted_name() ) ) . '</option>';
}
}
?>
@ -37,7 +37,7 @@ defined( 'ABSPATH' ) || exit;
foreach ( $product_ids as $product_id ) {
$product = wc_get_product( $product_id );
if ( is_object( $product ) ) {
echo '<option value="' . esc_attr( $product_id ) . '"' . selected( true, true, false ) . '>' . wp_kses_post( $product->get_formatted_name() ) . '</option>';
echo '<option value="' . esc_attr( $product_id ) . '"' . selected( true, true, false ) . '>' . htmlspecialchars( wp_kses_post( $product->get_formatted_name() ) ) . '</option>';
}
}
?>
@ -53,7 +53,7 @@ defined( 'ABSPATH' ) || exit;
foreach ( $product_ids as $product_id ) {
$product = wc_get_product( $product_id );
if ( is_object( $product ) ) {
echo '<option value="' . esc_attr( $product_id ) . '"' . selected( true, true, false ) . '>' . wp_kses_post( $product->get_formatted_name() ) . '</option>';
echo '<option value="' . esc_attr( $product_id ) . '"' . selected( true, true, false ) . '>' . htmlspecialchars( wp_kses_post( $product->get_formatted_name() ) ) . '</option>';
}
}
?>

View File

@ -48,12 +48,22 @@ class WC_Notes_Run_Db_Update {
} catch ( Exception $e ) {
return;
}
$note_ids = $data_store->get_notes_with_name( self::NOTE_NAME );
$note_ids = $data_store->get_notes_with_name( self::NOTE_NAME );
if ( empty( $note_ids ) ) {
return;
}
if ( count( $note_ids ) > 1 ) {
// Remove weird duplicates. Leave the first one.
$current_notice = array_shift( $note_ids );
foreach ( $note_ids as $note_id ) {
$note = new WC_Admin_Note( $note_id );
$data_store->delete( $note );
}
return $current_notice;
}
return current( $note_ids );
}
@ -79,14 +89,15 @@ class WC_Notes_Run_Db_Update {
* - actions are set up for the first 'Update database' notice, and
* - URL for note's action is equal to the given URL (to check for potential nonce update).
*
* @param WC_Admin_Note $note Note to check.
* @param string $update_url URL to check the note against.
* @param WC_Admin_Note $note Note to check.
* @param string $update_url URL to check the note against.
* @param array( string ) $current_actions List of actions to check for.
* @return bool
*/
private static function note_up_to_date( $note, $update_url ) {
private static function note_up_to_date( $note, $update_url, $current_actions ) {
$actions = $note->get_actions();
if ( 2 === count( array_intersect( wp_list_pluck( $actions, 'name' ), array( 'update-db_run', 'update-db_learn-more' ) ) )
&& in_array( $update_url, wp_list_pluck( $actions, 'query' ) ) ) {
if ( count( $current_actions ) === count( array_intersect( wp_list_pluck( $actions, 'name' ), $current_actions ) )
&& in_array( $update_url, wp_list_pluck( $actions, 'query' ), true ) ) {
return true;
}
@ -110,6 +121,23 @@ class WC_Notes_Run_Db_Update {
)
);
$note_actions = array(
array(
'name' => 'update-db_run',
'label' => __( 'Update WooCommerce Database', 'woocommerce' ),
'url' => $update_url,
'status' => 'unactioned',
'primary' => true,
),
array(
'name' => 'update-db_learn-more',
'label' => __( 'Learn more about updates', 'woocommerce' ),
'url' => 'https://docs.woocommerce.com/document/how-to-update-woocommerce/',
'status' => 'unactioned',
'primary' => false,
),
);
if ( $note_id ) {
$note = new WC_Admin_Note( $note_id );
} else {
@ -117,7 +145,7 @@ class WC_Notes_Run_Db_Update {
}
// Check if the note needs to be updated (e.g. expired nonce or different note type stored in the previous run).
if ( self::note_up_to_date( $note, $update_url ) ) {
if ( self::note_up_to_date( $note, $update_url, wp_list_pluck( $note_actions, 'name' ) ) ) {
return $note_id;
}
@ -128,7 +156,6 @@ class WC_Notes_Run_Db_Update {
. sprintf( ' ' . esc_html__( 'The database update process runs in the background and may take a little while, so please be patient. Advanced users can alternatively update via %1$sWP CLI%2$s.', 'woocommerce' ), '<a href="https://github.com/woocommerce/woocommerce/wiki/Upgrading-the-database-using-WP-CLI">', '</a>' )
);
$note->set_type( WC_Admin_Note::E_WC_ADMIN_NOTE_UPDATE );
$note->set_icon( 'info' );
$note->set_name( self::NOTE_NAME );
$note->set_content_data( (object) array() );
$note->set_source( 'woocommerce-core' );
@ -138,20 +165,9 @@ class WC_Notes_Run_Db_Update {
// Set new actions.
$note->clear_actions();
$note->add_action(
'update-db_run',
__( 'Update WooCommerce Database', 'woocommerce' ),
$update_url,
'unactioned',
true
);
$note->add_action(
'update-db_learn-more',
__( 'Learn more about updates', 'woocommerce' ),
'https://docs.woocommerce.com/document/how-to-update-woocommerce/',
'unactioned',
false
);
foreach ( $note_actions as $note_action ) {
$note->add_action( ...array_values( $note_action ) );
}
return $note->save();
}
@ -164,7 +180,7 @@ class WC_Notes_Run_Db_Update {
* @param int $note_id Note id to update.
*/
private static function update_in_progress_notice( $note_id ) {
// Same actions as in includes/admin/views/html-notice-updating.php.
// Same actions as in includes/admin/views/html-notice-updating.php. This just redirects, performs no action, so without nonce.
$pending_actions_url = admin_url( 'admin.php?page=wc-status&tab=action-scheduler&s=woocommerce_run_update&status=pending' );
$cron_disabled = Constants::is_true( 'DISABLE_WP_CRON' );
$cron_cta = $cron_disabled ? __( 'You can manually run queued updates here.', 'woocommerce' ) : __( 'View progress →', 'woocommerce' );
@ -205,89 +221,81 @@ class WC_Notes_Run_Db_Update {
)
);
$note_actions = array(
array(
'name' => 'update-db_done',
'label' => __( 'Thanks!', 'woocommerce' ),
'url' => $hide_notices_url,
'status' => 'actioned',
'primary' => true,
),
);
$note = new WC_Admin_Note( $note_id );
// Check if the note needs to be updated (e.g. expired nonce or different note type stored in the previous run).
if ( self::note_up_to_date( $note, $hide_notices_url, wp_list_pluck( $note_actions, 'name' ) ) ) {
return $note_id;
}
$note->set_title( __( 'WooCommerce database update done', 'woocommerce' ) );
$note->set_content( __( 'WooCommerce database update complete. Thank you for updating to the latest version!', 'woocommerce' ) );
$actions = $note->get_actions();
if ( ! in_array( 'update-db_done', wp_list_pluck( $actions, 'name' ) ) ) {
$note->clear_actions();
$note->add_action(
'update-db_done',
__( 'Thanks!', 'woocommerce' ),
$hide_notices_url,
'actioned',
true
);
$note->save();
}
}
/**
* Return true if db update notice should be shown, false otherwise.
*
* If the db needs an update, the notice should be always shown.
* If the db does not need an update, but the notice has *not* been actioned (i.e. after the db update, when
* store owner hasn't acknowledged the successful db update), still show the notice.
* If the db does not need an update, and the notice has been actioned, then notice should *not* be shown.
* The same is true if the db does not need an update and the notice does not exist.
*
* @return bool
*/
private static function should_show_notice() {
if ( ! \WC_Install::needs_db_update() ) {
try {
$data_store = \WC_Data_Store::load( 'admin-note' );
} catch ( Exception $e ) {
// Bail out in case of incorrect use.
return false;
}
$note_ids = $data_store->get_notes_with_name( self::NOTE_NAME );
if ( ! empty( $note_ids ) ) {
// Db update not needed && note actioned -> don't show it.
$note = new WC_Admin_Note( $note_ids[0] );
if ( $note::E_WC_ADMIN_NOTE_ACTIONED === $note->get_status() ) {
return false;
}
} else {
// Db update not needed && note does not exist -> don't show it.
return false;
}
$note->clear_actions();
foreach ( $note_actions as $note_action ) {
$note->add_action( ...array_values( $note_action ) );
}
return true;
$note->save();
}
/**
* Prepare the correct content of the db update note to be displayed by WC Admin.
*
* This one gets called on each page load, so try to bail quickly.
*
* If the db needs an update, the notice should be always shown.
* If the db does not need an update, but the notice has *not* been actioned (i.e. after the db update, when
* store owner hasn't acknowledged the successful db update), still show the Thanks notice.
* If the db does not need an update, and the notice has been actioned, then notice should *not* be shown.
* The notice should also be hidden if the db does not need an update and the notice does not exist.
*/
public static function show_reminder() {
if ( ! self::should_show_notice() ) {
return;
}
$needs_db_update = \WC_Install::needs_db_update();
$note_id = self::get_current_notice();
if ( ! $needs_db_update ) {
// Db update not needed && note does not exist -> don't show it.
if ( ! $note_id ) {
return;
}
if ( \WC_Install::needs_db_update() && empty( $note_id ) ) {
// Db needs update && no notice exists -> create one.
$note_id = self::update_needed_notice();
}
if ( \WC_Install::needs_db_update() ) {
$next_scheduled_date = WC()->queue()->get_next( 'woocommerce_run_update_callback', null, 'woocommerce-db-updates' );
if ( $next_scheduled_date || ! empty( $_GET['do_update_woocommerce'] ) ) { // WPCS: input var ok, CSRF ok.
self::update_in_progress_notice( $note_id );
$note = new WC_Admin_Note( $note_id );
if ( $note::E_WC_ADMIN_NOTE_ACTIONED === $note->get_status() ) {
// Db update not needed && note actioned -> don't show it.
return;
} else {
self::update_needed_notice( $note_id );
// Db update not needed && notice is unactioned -> Thank you note.
\WC_Install::update_db_version();
self::update_done_notice( $note_id );
return;
}
} else {
\WC_Install::update_db_version();
self::update_done_notice( $note_id );
// Db needs update &&.
if ( ! $note_id ) {
// Db needs update && no notice exists -> create one that shows Nudge to update.
$note_id = self::update_needed_notice();
}
$next_scheduled_date = WC()->queue()->get_next( 'woocommerce_run_update_callback', null, 'woocommerce-db-updates' );
if ( $next_scheduled_date || ! empty( $_GET['do_update_woocommerce'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
// Db needs update && db update is scheduled -> update note to In progress.
self::update_in_progress_notice( $note_id );
} else {
// Db needs update && db update is not scheduled -> Nudge to run the db update.
self::update_needed_notice( $note_id );
}
}
}

View File

@ -45,13 +45,6 @@ class WC_Plugin_Updates {
*/
protected $major_untested_plugins = array();
/**
* Array of plugins lacking testing with the minor version.
*
* @var array
*/
protected $minor_untested_plugins = array();
/**
* Common JS for initializing and managing thickbox-based modals.
*/
@ -103,29 +96,6 @@ class WC_Plugin_Updates {
| Methods for getting messages.
*/
/**
* Get the inline warning notice for minor version updates.
*
* @return string
*/
protected function get_extensions_inline_warning_minor() {
$upgrade_type = 'minor';
$plugins = ! empty( $this->major_untested_plugins ) ? array_diff_key( $this->minor_untested_plugins, $this->major_untested_plugins ) : $this->minor_untested_plugins;
$version_parts = explode( '.', $this->new_version );
$new_version = $version_parts[0] . '.' . $version_parts[1];
if ( empty( $plugins ) ) {
return;
}
/* translators: %s: version number */
$message = sprintf( __( "<strong>Heads up!</strong> The versions of the following plugins you're running haven't been tested with the latest version of WooCommerce (%s).", 'woocommerce' ), $new_version );
ob_start();
include 'views/html-notice-untested-extensions-inline.php';
return ob_get_clean();
}
/**
* Get the inline warning notice for major version updates.
*

View File

@ -45,7 +45,6 @@ class WC_Plugins_Screen_Updates extends WC_Plugin_Updates {
$this->new_version = $response->new_version;
$this->upgrade_notice = $this->get_upgrade_notice( $response->new_version );
$this->major_untested_plugins = $this->get_untested_plugins( $response->new_version, 'major' );
$this->minor_untested_plugins = $this->get_untested_plugins( $response->new_version, 'minor' );
$current_version_parts = explode( '.', Constants::get_constant( 'WC_VERSION' ) );
$new_version_parts = explode( '.', $this->new_version );
@ -59,10 +58,6 @@ class WC_Plugins_Screen_Updates extends WC_Plugin_Updates {
$this->upgrade_notice .= $this->get_extensions_inline_warning_major();
}
if ( ! empty( $this->minor_untested_plugins ) ) {
$this->upgrade_notice .= $this->get_extensions_inline_warning_minor();
}
if ( ! empty( $this->major_untested_plugins ) ) {
$this->upgrade_notice .= $this->get_extensions_modal_warning();
add_action( 'admin_print_footer_scripts', array( $this, 'plugin_screen_modal_js' ) );

View File

@ -42,6 +42,7 @@ class WC_Settings_Advanced extends WC_Settings_Page {
'webhooks' => __( 'Webhooks', 'woocommerce' ),
'legacy_api' => __( 'Legacy API', 'woocommerce' ),
'woocommerce_com' => __( 'WooCommerce.com', 'woocommerce' ),
'features' => __( 'Features', 'woocommerce' ),
);
return apply_filters( 'woocommerce_get_sections_' . $this->id, $sections );
@ -397,6 +398,28 @@ class WC_Settings_Advanced extends WC_Settings_Page {
),
)
);
} elseif ( 'features' === $current_section ) {
$settings = apply_filters(
'woocommerce_settings_features',
array(
array(
'title' => __( 'Features', 'woocommerce' ),
'type' => 'title',
'desc' => __( 'Start using new features that are being progressively rolled out to improve the store management experience.', 'woocommerce' ),
'id' => 'features_options',
),
array(
'title' => __( 'Home Screen', 'woocommerce' ),
'desc' => __( 'Displays analytical insights, inbox notifications, and handy shortcuts in a single screen', 'woocommerce' ),
'id' => 'woocommerce_homescreen_enabled',
'type' => 'checkbox',
),
array(
'type' => 'sectionend',
'id' => 'features_options',
),
)
);
}
return apply_filters( 'woocommerce_get_settings_' . $this->id, $settings, $current_section );

View File

@ -128,7 +128,7 @@ class WC_Settings_Emails extends WC_Settings_Page {
array(
'title' => __( 'Footer text', 'woocommerce' ),
/* translators: %s: Available placeholders for use */
'desc' => __( 'The text to appear in the footer of all WooCommerce emails.', 'woocommerce' ) . ' ' . sprintf( __( 'Available placeholders: %s', 'woocommerce' ), '{site_title} {site_address}' ),
'desc' => __( 'The text to appear in the footer of all WooCommerce emails.', 'woocommerce' ) . ' ' . sprintf( __( 'Available placeholders: %s', 'woocommerce' ), '{site_title} {site_url}' ),
'id' => 'woocommerce_email_footer_text',
'css' => 'width:400px; height: 75px;',
'placeholder' => __( 'N/A', 'woocommerce' ),

View File

@ -286,7 +286,7 @@ class WC_Settings_Shipping extends WC_Settings_Page {
* Show zones
*/
protected function zones_screen() {
$method_count = wc_get_shipping_method_count();
$method_count = wc_get_shipping_method_count( false, true );
wp_localize_script(
'wc-shipping-zones',

View File

@ -189,7 +189,7 @@ if ( ! defined( 'ABSPATH' ) ) {
if ( ! $method->supports( 'shipping-zones' ) ) {
continue;
}
echo '<option data-description="' . esc_attr( wp_kses_post( wpautop( $method->get_method_description() ) ) ) . '" value="' . esc_attr( $method->id ) . '">' . esc_attr( $method->get_method_title() ) . '</li>';
echo '<option data-description="' . esc_attr( wp_kses_post( wpautop( $method->get_method_description() ) ) ) . '" value="' . esc_attr( $method->id ) . '">' . esc_html( $method->get_method_title() ) . '</li>';
}
?>
</select>

View File

@ -108,7 +108,7 @@ if ( ! defined( 'ABSPATH' ) ) {
if ( ! $method->supports( 'shipping-zones' ) ) {
continue;
}
echo '<option data-description="' . esc_attr( wp_kses_post( wpautop( $method->get_method_description() ) ) ) . '" value="' . esc_attr( $method->id ) . '">' . esc_attr( $method->get_method_title() ) . '</li>';
echo '<option data-description="' . esc_attr( wp_kses_post( wpautop( $method->get_method_description() ) ) ) . '" value="' . esc_attr( $method->id ) . '">' . esc_html( $method->get_method_title() ) . '</li>';
}
?>
</select>

View File

@ -496,10 +496,17 @@ $untested_plugins = $plugin_updates->get_untested_plugins( WC()->version, 'min
?>
</tbody>
</table>
<table class="wc_status_table widefat" cellspacing="0">
<table id="status-database" class="wc_status_table widefat" cellspacing="0">
<thead>
<tr>
<th colspan="3" data-export-label="Database"><h2><?php esc_html_e( 'Database', 'woocommerce' ); ?></h2></th>
<th colspan="3" data-export-label="Database">
<h2>
<?php
esc_html_e( 'Database', 'woocommerce' );
self::output_tables_info();
?>
</h2>
</th>
</tr>
</thead>
<tbody>
@ -792,7 +799,7 @@ if ( 0 < count( $dropins_mu_plugins['mu_plugins'] ) ) :
</tr>
<tr>
<td data-export-label="Connected to WooCommerce.com"><?php esc_html_e( 'Connected to WooCommerce.com', 'woocommerce' ); ?>:</td>
<td class="help"><?php echo wc_help_tip( esc_html__( 'Are your site connected to WooCommerce.com?', 'woocommerce' ) ); /* phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped */ ?></td>
<td class="help"><?php echo wc_help_tip( esc_html__( 'Is your site connected to WooCommerce.com?', 'woocommerce' ) ); /* phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped */ ?></td>
<td><?php echo 'yes' === $settings['woocommerce_com_connected'] ? '<mark class="yes"><span class="dashicons dashicons-yes"></span></mark>' : '<mark class="no">&ndash;</mark>'; ?></td>
</tr>
</tbody>

View File

@ -29,7 +29,7 @@ if ( ! defined( 'ABSPATH' ) ) {
'3' => __( 'Decrease existing price by (fixed amount or %):', 'woocommerce' ),
);
foreach ( $options as $key => $value ) {
echo '<option value="' . esc_attr( $key ) . '">' . $value . '</option>';
echo '<option value="' . esc_attr( $key ) . '">' . esc_html( $value ) . '</option>';
}
?>
</select>
@ -54,7 +54,7 @@ if ( ! defined( 'ABSPATH' ) ) {
'4' => __( 'Set to regular price decreased by (fixed amount or %):', 'woocommerce' ),
);
foreach ( $options as $key => $value ) {
echo '<option value="' . esc_attr( $key ) . '">' . $value . '</option>';
echo '<option value="' . esc_attr( $key ) . '">' . esc_html( $value ) . '</option>';
}
?>
</select>
@ -78,7 +78,7 @@ if ( ! defined( 'ABSPATH' ) ) {
'none' => _x( 'None', 'Tax status', 'woocommerce' ),
);
foreach ( $options as $key => $value ) {
echo '<option value="' . esc_attr( $key ) . '">' . $value . '</option>';
echo '<option value="' . esc_attr( $key ) . '">' . esc_html( $value ) . '</option>';
}
?>
</select>
@ -104,7 +104,7 @@ if ( ! defined( 'ABSPATH' ) ) {
}
foreach ( $options as $key => $value ) {
echo '<option value="' . esc_attr( $key ) . '">' . $value . '</option>';
echo '<option value="' . esc_attr( $key ) . '">' . esc_html( $value ) . '</option>';
}
?>
</select>
@ -124,7 +124,7 @@ if ( ! defined( 'ABSPATH' ) ) {
'1' => __( 'Change to:', 'woocommerce' ),
);
foreach ( $options as $key => $value ) {
echo '<option value="' . esc_attr( $key ) . '">' . $value . '</option>';
echo '<option value="' . esc_attr( $key ) . '">' . esc_html( $value ) . '</option>';
}
?>
</select>
@ -148,7 +148,7 @@ if ( ! defined( 'ABSPATH' ) ) {
'1' => __( 'Change to:', 'woocommerce' ),
);
foreach ( $options as $key => $value ) {
echo '<option value="' . esc_attr( $key ) . '">' . $value . '</option>';
echo '<option value="' . esc_attr( $key ) . '">' . esc_html( $value ) . '</option>';
}
?>
</select>
@ -170,7 +170,7 @@ if ( ! defined( 'ABSPATH' ) ) {
<option value="_no_shipping_class"><?php _e( 'No shipping class', 'woocommerce' ); ?></option>
<?php
foreach ( $shipping_class as $key => $value ) {
echo '<option value="' . esc_attr( $value->slug ) . '">' . $value->name . '</option>';
echo '<option value="' . esc_attr( $value->slug ) . '">' . esc_html( $value->name ) . '</option>';
}
?>
</select>
@ -190,7 +190,7 @@ if ( ! defined( 'ABSPATH' ) ) {
'hidden' => __( 'Hidden', 'woocommerce' ),
);
foreach ( $options as $key => $value ) {
echo '<option value="' . esc_attr( $key ) . '">' . $value . '</option>';
echo '<option value="' . esc_attr( $key ) . '">' . esc_html( $value ) . '</option>';
}
?>
</select>
@ -207,7 +207,7 @@ if ( ! defined( 'ABSPATH' ) ) {
'no' => __( 'No', 'woocommerce' ),
);
foreach ( $options as $key => $value ) {
echo '<option value="' . esc_attr( $key ) . '">' . $value . '</option>';
echo '<option value="' . esc_attr( $key ) . '">' . esc_html( $value ) . '</option>';
}
?>
</select>
@ -222,7 +222,7 @@ if ( ! defined( 'ABSPATH' ) ) {
echo '<option value="">' . esc_html__( '— No Change —', 'woocommerce' ) . '</option>';
foreach ( wc_get_product_stock_status_options() as $key => $value ) {
echo '<option value="' . esc_attr( $key ) . '">' . $value . '</option>';
echo '<option value="' . esc_attr( $key ) . '">' . esc_html( $value ) . '</option>';
}
?>
</select>
@ -241,7 +241,7 @@ if ( ! defined( 'ABSPATH' ) ) {
'no' => __( 'No', 'woocommerce' ),
);
foreach ( $options as $key => $value ) {
echo '<option value="' . esc_attr( $key ) . '">' . $value . '</option>';
echo '<option value="' . esc_attr( $key ) . '">' . esc_html( $value ) . '</option>';
}
?>
</select>
@ -261,7 +261,7 @@ if ( ! defined( 'ABSPATH' ) ) {
'3' => __( 'Decrease existing stock by:', 'woocommerce' ),
);
foreach ( $options as $key => $value ) {
echo '<option value="' . esc_attr( $key ) . '">' . $value . '</option>';
echo '<option value="' . esc_attr( $key ) . '">' . esc_html( $value ) . '</option>';
}
?>
</select>
@ -280,7 +280,7 @@ if ( ! defined( 'ABSPATH' ) ) {
echo '<option value="">' . esc_html__( '— No Change —', 'woocommerce' ) . '</option>';
foreach ( wc_get_product_backorder_options() as $key => $value ) {
echo '<option value="' . esc_attr( $key ) . '">' . $value . '</option>';
echo '<option value="' . esc_attr( $key ) . '">' . esc_html( $value ) . '</option>';
}
?>
</select>

View File

@ -0,0 +1,43 @@
<?php
/**
* Admin View: Notice - Base table missing.
*
* @package WooCommerce\Admin
*/
defined( 'ABSPATH' ) || exit;
?>
<div class="updated woocommerce-message">
<a class="woocommerce-message-close notice-dismiss" href="<?php echo esc_url( wp_nonce_url( add_query_arg( 'wc-hide-notice', 'base_tables_missing' ), 'woocommerce_hide_notices_nonce', '_wc_notice_nonce' ) ); ?>">
<?php esc_html_e( 'Dismiss', 'woocommerce' ); ?>
</a>
<p>
<strong><?php esc_html_e( 'Database tables missing', 'woocommerce' ); ?></strong>
</p>
<p>
<?php
$verify_db_tool_available = array_key_exists( 'verify_db_tables', WC_Admin_Status::get_tools() );
$missing_tables = get_option( 'woocommerce_schema_missing_tables' );
if ( $verify_db_tool_available ) {
echo wp_kses_post(
sprintf(
/* translators: %1%s: Missing tables (seperated by ",") %2$s: Link to check again */
__( 'One or more tables required for WooCommerce to function are missing, some features may not work as expected. Missing tables: %1$s. <a href="%2$s">Check again.</a>', 'woocommerce' ),
esc_html( implode( ', ', $missing_tables ) ),
wp_nonce_url( admin_url( 'admin.php?page=wc-status&tab=tools&action=verify_db_tables' ), 'debug_action' )
)
);
} else {
echo wp_kses_post(
sprintf(
/* translators: %1%s: Missing tables (seperated by ",") */
__( 'One or more tables required for WooCommerce to function are missing, some features may not work as expected. Missing tables: %1$s.', 'woocommerce' ),
esc_html( implode( ', ', $missing_tables ) )
)
);
}
?>
</p>
</div>

View File

@ -0,0 +1,29 @@
<?php
/**
* Admin View: Notice - Uploads directory is unprotected.
*
* @package WooCommerce\Admin\Notices
* @since 4.2.0
*/
defined( 'ABSPATH' ) || exit;
$uploads = wp_get_upload_dir();
?>
<div id="message" class="error woocommerce-message">
<a class="woocommerce-message-close notice-dismiss" href="<?php echo esc_url( wp_nonce_url( add_query_arg( 'wc-hide-notice', 'uploads_directory_is_public' ), 'woocommerce_hide_notices_nonce', '_wc_notice_nonce' ) ); ?>"><?php esc_html_e( 'Dismiss', 'woocommerce' ); ?></a>
<p>
<?php
echo wp_kses_post(
sprintf(
/* translators: 1: uploads directory URL 2: documentation URL */
__( 'Your store\'s uploads directory is <a href="%1$s">browsable via the web</a>. We strongly recommend <a href="%2$s">configuring your web server to prevent directory indexing</a>.', 'woocommerce' ),
esc_url( $uploads['baseurl'] . '/woocommerce_uploads' ),
'https://docs.woocommerce.com/document/digital-downloadable-product-handling/#protecting-your-uploads-directory'
)
);
?>
</p>
</div>

View File

@ -137,7 +137,7 @@ function wc_create_page( $slug, $option = '', $page_title = '', $page_content =
/**
* Output admin fields.
*
* Loops though the woocommerce options array and outputs each field.
* Loops through the woocommerce options array and outputs each field.
*
* @param array $options Opens array to output.
*/

View File

@ -765,7 +765,6 @@ class WC_Cart extends WC_Legacy_Cart {
public function check_cart_item_stock() {
$error = new WP_Error();
$product_qty_in_cart = $this->get_cart_item_quantities();
$hold_stock_minutes = (int) get_option( 'woocommerce_hold_stock_minutes', 0 );
$current_session_order_id = isset( WC()->session->order_awaiting_payment ) ? absint( WC()->session->order_awaiting_payment ) : 0;
foreach ( $this->get_cart() as $cart_item_key => $values ) {
@ -784,7 +783,7 @@ class WC_Cart extends WC_Legacy_Cart {
}
// Check stock based on all items in the cart and consider any held stock within pending orders.
$held_stock = ( $hold_stock_minutes > 0 ) ? wc_get_held_stock_quantity( $product, $current_session_order_id ) : 0;
$held_stock = wc_get_held_stock_quantity( $product, $current_session_order_id );
$required_stock = $product_qty_in_cart[ $product->get_stock_managed_by_id() ];
if ( $product->get_stock_quantity() < ( $held_stock + $required_stock ) ) {

View File

@ -388,12 +388,30 @@ class WC_Checkout {
// Save the order.
$order_id = $order->save();
/**
* Action hook fired after an order is created used to add custom meta to the order.
*
* @since 3.0.0
*/
do_action( 'woocommerce_checkout_update_order_meta', $order_id, $data );
/**
* Action hook fired after an order is created.
*
* @since 4.3.0
*/
do_action( 'woocommerce_checkout_order_created', $order );
return $order_id;
} catch ( Exception $e ) {
if ( $order && $order instanceof WC_Order ) {
$order->get_data_store()->release_held_coupons( $order );
/**
* Action hook fired when an order is discarded due to Exception.
*
* @since 4.3.0
*/
do_action( 'woocommerce_checkout_order_exception', $order );
}
return new WP_Error( 'checkout-error', $e->getMessage() );
}
@ -748,14 +766,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 ] ), array( 'id' => $key ) );
$errors->add( $key . '_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>' ), array( 'id' => $key ) );
$errors->add( $key . '_validation', sprintf( __( '%s is not a valid phone number.', 'woocommerce' ), '<strong>' . esc_html( $field_label ) . '</strong>' ), array( 'id' => $key ) );
}
}
@ -765,7 +783,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>' ), array( 'id' => $key ) );
$errors->add( $key . '_validation', sprintf( __( '%s is not a valid email address.', 'woocommerce' ), '<strong>' . esc_html( $field_label ) . '</strong>' ), array( 'id' => $key ) );
continue;
}
}
@ -785,14 +803,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 ) ), array( 'id' => $key ) );
$errors->add( $key . '_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 ), array( 'id' => $key ) );
$errors->add( $key . '_required', 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 ) );
}
}
}

View File

@ -146,7 +146,7 @@ class WC_Comments {
*/
public static function check_comment_rating( $comment_data ) {
// If posting a comment (not trackback etc) and not logged in.
if ( ! is_admin() && isset( $_POST['comment_post_ID'], $_POST['rating'], $comment_data['comment_type'] ) && 'product' === get_post_type( absint( $_POST['comment_post_ID'] ) ) && empty( $_POST['rating'] ) && '' === $comment_data['comment_type'] && wc_review_ratings_enabled() && wc_review_ratings_required() ) { // WPCS: input var ok, CSRF ok.
if ( ! is_admin() && isset( $_POST['comment_post_ID'], $_POST['rating'], $comment_data['comment_type'] ) && 'product' === get_post_type( absint( $_POST['comment_post_ID'] ) ) && empty( $_POST['rating'] ) && self::is_default_comment_type( $comment_data['comment_type'] ) && wc_review_ratings_enabled() && wc_review_ratings_required() ) { // WPCS: input var ok, CSRF ok.
wp_die( esc_html__( 'Please rate the product.', 'woocommerce' ) );
exit;
}
@ -406,12 +406,26 @@ class WC_Comments {
* @return array
*/
public static function update_comment_type( $comment_data ) {
if ( ! is_admin() && isset( $_POST['comment_post_ID'], $comment_data['comment_type'] ) && '' === $comment_data['comment_type'] && 'product' === get_post_type( absint( $_POST['comment_post_ID'] ) ) ) { // WPCS: input var ok, CSRF ok.
if ( ! is_admin() && isset( $_POST['comment_post_ID'], $comment_data['comment_type'] ) && self::is_default_comment_type( $comment_data['comment_type'] ) && 'product' === get_post_type( absint( $_POST['comment_post_ID'] ) ) ) { // WPCS: input var ok, CSRF ok.
$comment_data['comment_type'] = 'review';
}
return $comment_data;
}
/**
* Determines if a comment is of the default type.
*
* Prior to WordPress 5.5, '' was the default comment type.
* As of 5.5, the default type is 'comment'.
*
* @since 4.3.0
* @param string $comment_type Comment type.
* @return bool
*/
private static function is_default_comment_type( $comment_type ) {
return ( '' === $comment_type || 'comment' === $comment_type );
}
}
WC_Comments::init();

View File

@ -474,7 +474,7 @@ class WC_Countries {
echo ' selected="selected"';
}
echo '>' . esc_html( $value ) . ' &mdash; ' . ( $escape ? esc_js( $state_value ) : $state_value ) . '</option>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
echo '>' . esc_html( $value ) . ' &mdash; ' . ( $escape ? esc_html( $state_value ) : $state_value ) . '</option>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
echo '</optgroup>';
@ -483,7 +483,7 @@ class WC_Countries {
if ( $selected_country === $key && '*' === $selected_state ) {
echo ' selected="selected"';
}
echo ' value="' . esc_attr( $key ) . '">' . ( $escape ? esc_js( $value ) : $value ) . '</option>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
echo ' value="' . esc_attr( $key ) . '">' . ( $escape ? esc_html( $value ) : $value ) . '</option>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
}
}
@ -910,6 +910,7 @@ class WC_Countries {
),
'state' => array(
'required' => false,
'hidden' => true,
),
),
'DK' => array(
@ -918,6 +919,7 @@ class WC_Countries {
),
'state' => array(
'required' => false,
'hidden' => true,
),
),
'EE' => array(
@ -944,6 +946,14 @@ class WC_Countries {
'required' => false,
),
),
'GH' => array(
'postcode' => array(
'required' => false,
),
'state' => array(
'label' => __( 'Region', 'woocommerce' ),
),
),
'GP' => array(
'state' => array(
'required' => false,
@ -1229,6 +1239,7 @@ class WC_Countries {
),
'state' => array(
'required' => false,
'hidden' => true,
),
),
'TR' => array(

View File

@ -290,12 +290,14 @@ class WC_Emails {
array(
'{site_title}',
'{site_address}',
'{site_url}',
'{woocommerce}',
'{WooCommerce}',
),
array(
$this->get_blogname(),
$domain,
$domain,
'<a href="https://woocommerce.com">WooCommerce</a>',
'<a href="https://woocommerce.com">WooCommerce</a>',
),

View File

@ -459,6 +459,10 @@ class WC_Form_Handler {
return;
}
if ( ! apply_filters( 'woocommerce_add_payment_method_form_is_valid', true ) ) {
return;
}
// Test rate limit.
$current_user_id = get_current_user_id();
$rate_limit_id = 'add_payment_method_' . $current_user_id;
@ -466,12 +470,15 @@ class WC_Form_Handler {
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'
sprintf(
/* 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'
),
$delay
),
'error'
);
@ -862,11 +869,12 @@ 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.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 );
$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();
$variation_attributes = array();
$adding_to_cart = wc_get_product( $product_id );
if ( ! $adding_to_cart ) {
return false;
@ -874,6 +882,9 @@ class WC_Form_Handler {
// If the $product_id was in fact a variation ID, update the variables.
if ( $adding_to_cart->is_type( 'variation' ) ) {
$variation_attributes = $adding_to_cart->get_variation_attributes();
// Filter out 'any' variations, which are empty, as they need to be explicitly specified while adding to cart.
$variation_attributes = array_filter( $variation_attributes );
$variation_id = $product_id;
$product_id = $adding_to_cart->get_parent_id();
$adding_to_cart = wc_get_product( $product_id );
@ -904,6 +915,9 @@ class WC_Form_Handler {
}
}
// Merge variation attributes and posted attributes.
$posted_and_variation_attributes = array_merge( $variation_attributes, $posted_attributes );
// If no variation ID is set, attempt to get a variation ID from posted attributes.
if ( empty( $variation_id ) ) {
$data_store = WC_Data_Store::load( 'product' );
@ -932,8 +946,8 @@ class WC_Form_Handler {
*
* If no attribute was posted, only error if the variation has an 'any' attribute which requires a value.
*/
if ( isset( $posted_attributes[ $attribute_key ] ) ) {
$value = $posted_attributes[ $attribute_key ];
if ( isset( $posted_and_variation_attributes[ $attribute_key ] ) ) {
$value = $posted_and_variation_attributes[ $attribute_key ];
// Allow if valid or show error.
if ( $valid_value === $value ) {

View File

@ -287,6 +287,7 @@ class WC_Install {
WC()->wpdb_table_fix();
self::remove_admin_notices();
self::create_tables();
self::verify_base_tables();
self::create_options();
self::create_roles();
self::setup_environment();
@ -296,6 +297,7 @@ class WC_Install {
self::maybe_enable_setup_wizard();
self::update_wc_version();
self::maybe_update_db_version();
self::maybe_enable_homescreen();
delete_transient( 'wc_installing' );
@ -303,6 +305,54 @@ class WC_Install {
do_action( 'woocommerce_installed' );
}
/**
* Check if all the base tables are present.
*
* @param bool $modify_notice Whether to modify notice based on if all tables are present.
* @param bool $execute Whether to execute get_schema queries as well.
*
* @return array List of querues.
*/
public static function verify_base_tables( $modify_notice = true, $execute = false ) {
require_once ABSPATH . 'wp-admin/includes/upgrade.php';
if ( $execute ) {
self::create_tables();
}
$queries = dbDelta( self::get_schema(), false );
$missing_tables = array();
foreach ( $queries as $table_name => $result ) {
if ( "Created table $table_name" === $result ) {
$missing_tables[] = $table_name;
}
}
if ( 0 < count( $missing_tables ) ) {
if ( $modify_notice ) {
WC_Admin_Notices::add_notice( 'base_tables_missing' );
}
update_option( 'woocommerce_schema_missing_tables', $missing_tables );
} else {
if ( $modify_notice ) {
WC_Admin_Notices::remove_notice( 'base_tables_missing' );
}
update_option( 'woocommerce_schema_version', WC()->db_version );
delete_option( 'woocommerce_schema_missing_tables' );
}
return $missing_tables;
}
/**
* Check if the homepage should be enabled and set the appropriate option if thats the case.
*
* @since 4.3.0
*/
private static function maybe_enable_homescreen() {
if ( self::is_new_install() && ! get_option( 'woocommerce_homescreen_enabled' ) ) {
add_option( 'woocommerce_homescreen_enabled', 'yes' );
}
}
/**
* Reset any notices added to admin.
*
@ -621,6 +671,11 @@ class WC_Install {
/**
* Set up the database tables which the plugin needs to function.
* WARNING: If you are modifying this method, make sure that its safe to call regardless of the state of database.
*
* This is called from `install` method and is executed in-sync when WC is installed or updated. This can also be called optionally from `verify_base_tables`.
*
* TODO: Add all crucial tables that we have created from workers in the past.
*
* Tables:
* woocommerce_attribute_taxonomies - Table for storing attribute taxonomies - these are user defined
@ -946,6 +1001,14 @@ CREATE TABLE {$wpdb->prefix}wc_tax_rate_classes (
slug varchar(200) NOT NULL DEFAULT '',
PRIMARY KEY (tax_rate_class_id),
UNIQUE KEY slug (slug($max_index_length))
) $collate;
CREATE TABLE {$wpdb->prefix}wc_reserved_stock (
`order_id` bigint(20) NOT NULL,
`product_id` bigint(20) NOT NULL,
`stock_quantity` double NOT NULL DEFAULT 0,
`timestamp` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`expires` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY (`order_id`, `product_id`)
) $collate;
";
@ -980,6 +1043,7 @@ CREATE TABLE {$wpdb->prefix}wc_tax_rate_classes (
"{$wpdb->prefix}woocommerce_shipping_zones",
"{$wpdb->prefix}woocommerce_tax_rate_locations",
"{$wpdb->prefix}woocommerce_tax_rates",
"{$wpdb->prefix}wc_reserved_stock",
);
/**
@ -1187,7 +1251,7 @@ CREATE TABLE {$wpdb->prefix}wc_tax_rate_classes (
}
// Install files and folders for uploading files and prevent hotlinking.
$upload_dir = wp_upload_dir();
$upload_dir = wp_get_upload_dir();
$download_method = get_option( 'woocommerce_file_download_method', 'force' );
$files = array(
@ -1206,19 +1270,16 @@ CREATE TABLE {$wpdb->prefix}wc_tax_rate_classes (
'file' => 'index.html',
'content' => '',
),
);
if ( 'redirect' !== $download_method ) {
$files[] = array(
array(
'base' => $upload_dir['basedir'] . '/woocommerce_uploads',
'file' => '.htaccess',
'content' => 'deny from all',
);
}
'content' => 'redirect' === $download_method ? 'Options -Indexes' : 'deny from all',
),
);
foreach ( $files as $file ) {
if ( wp_mkdir_p( $file['base'] ) && ! file_exists( trailingslashit( $file['base'] ) . $file['file'] ) ) {
$file_handle = @fopen( trailingslashit( $file['base'] ) . $file['file'], 'w' ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged, WordPress.WP.AlternativeFunctions.file_system_read_fopen
$file_handle = @fopen( trailingslashit( $file['base'] ) . $file['file'], 'wb' ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged, WordPress.WP.AlternativeFunctions.file_system_read_fopen
if ( $file_handle ) {
fwrite( $file_handle, $file['content'] ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_read_fwrite
fclose( $file_handle ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_read_fclose

View File

@ -419,6 +419,19 @@ class WC_Order extends WC_Abstract_Order {
|
*/
/**
* Get basic order data in array format.
*
* @return array
*/
public function get_base_data() {
return array_merge(
array( 'id' => $this->get_id() ),
$this->data,
array( 'number' => $this->get_order_number() )
);
}
/**
* Get all class data in array format.
*
@ -427,12 +440,8 @@ class WC_Order extends WC_Abstract_Order {
*/
public function get_data() {
return array_merge(
$this->get_base_data(),
array(
'id' => $this->get_id(),
),
$this->data,
array(
'number' => $this->get_order_number(),
'meta_data' => $this->get_meta_data(),
'line_items' => $this->get_items( 'line_item' ),
'tax_lines' => $this->get_items( 'tax' ),

View File

@ -59,6 +59,7 @@ class WC_Post_Types {
'query_var' => is_admin(),
'rewrite' => false,
'public' => false,
'label' => _x( 'Product type', 'Taxonomy name', 'woocommerce' ),
)
)
);
@ -75,6 +76,7 @@ class WC_Post_Types {
'query_var' => is_admin(),
'rewrite' => false,
'public' => false,
'label' => _x( 'Product visibility', 'Taxonomy name', 'woocommerce' ),
)
)
);

View File

@ -27,10 +27,11 @@ class WC_Privacy_Exporters {
$customer_personal_data = self::get_customer_personal_data( $user );
if ( ! empty( $customer_personal_data ) ) {
$data_to_export[] = array(
'group_id' => 'woocommerce_customer',
'group_label' => __( 'Customer Data', 'woocommerce' ),
'item_id' => 'user',
'data' => $customer_personal_data,
'group_id' => 'woocommerce_customer',
'group_label' => __( 'Customer Data', 'woocommerce' ),
'group_description' => __( 'User&#8217;s WooCommerce customer data.', 'woocommerce' ),
'item_id' => 'user',
'data' => $customer_personal_data,
);
}
}
@ -71,10 +72,11 @@ class WC_Privacy_Exporters {
if ( 0 < count( $orders ) ) {
foreach ( $orders as $order ) {
$data_to_export[] = array(
'group_id' => 'woocommerce_orders',
'group_label' => __( 'Orders', 'woocommerce' ),
'item_id' => 'order-' . $order->get_id(),
'data' => self::get_order_personal_data( $order ),
'group_id' => 'woocommerce_orders',
'group_label' => __( 'Orders', 'woocommerce' ),
'group_description' => __( 'User&#8217;s WooCommerce orders data.', 'woocommerce' ),
'item_id' => 'order-' . $order->get_id(),
'data' => self::get_order_personal_data( $order ),
);
}
$done = 10 > count( $orders );
@ -118,22 +120,24 @@ class WC_Privacy_Exporters {
if ( 0 < count( $downloads ) ) {
foreach ( $downloads as $download ) {
$data_to_export[] = array(
'group_id' => 'woocommerce_downloads',
'group_id' => 'woocommerce_downloads',
/* translators: This is the headline for a list of downloads purchased from the store for a given user. */
'group_label' => __( 'Purchased Downloads', 'woocommerce' ),
'item_id' => 'download-' . $download->get_id(),
'data' => self::get_download_personal_data( $download ),
'group_label' => __( 'Purchased Downloads', 'woocommerce' ),
'group_description' => __( 'User&#8217;s WooCommerce purchased downloads data.', 'woocommerce' ),
'item_id' => 'download-' . $download->get_id(),
'data' => self::get_download_personal_data( $download ),
);
$download_logs = $customer_download_log_data_store->get_download_logs_for_permission( $download->get_id() );
foreach ( $download_logs as $download_log ) {
$data_to_export[] = array(
'group_id' => 'woocommerce_download_logs',
'group_id' => 'woocommerce_download_logs',
/* translators: This is the headline for a list of access logs for downloads purchased from the store for a given user. */
'group_label' => __( 'Access to Purchased Downloads', 'woocommerce' ),
'item_id' => 'download-log-' . $download_log->get_id(),
'data' => array(
'group_label' => __( 'Access to Purchased Downloads', 'woocommerce' ),
'group_description' => __( 'User&#8217;s WooCommerce access to purchased downloads data.', 'woocommerce' ),
'item_id' => 'download-log-' . $download_log->get_id(),
'data' => array(
array(
'name' => __( 'Download ID', 'woocommerce' ),
'value' => $download_log->get_permission_id(),
@ -413,10 +417,11 @@ class WC_Privacy_Exporters {
if ( 0 < count( $tokens ) ) {
foreach ( $tokens as $token ) {
$data_to_export[] = array(
'group_id' => 'woocommerce_tokens',
'group_label' => __( 'Payment Tokens', 'woocommerce' ),
'item_id' => 'token-' . $token->get_id(),
'data' => array(
'group_id' => 'woocommerce_tokens',
'group_label' => __( 'Payment Tokens', 'woocommerce' ),
'group_description' => __( 'User&#8217;s WooCommerce payment tokens data.', 'woocommerce' ),
'item_id' => 'token-' . $token->get_id(),
'data' => array(
array(
'name' => __( 'Token', 'woocommerce' ),
'value' => $token->get_display_name(),

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