Merge branch 'master' into fix/27673
This commit is contained in:
commit
39c200bf2d
|
@ -51,4 +51,4 @@ Feature requests can be [submitted to our issue tracker](https://github.com/wooc
|
||||||
|
|
||||||
Feature request issues will remain closed until we see sufficient interest via comments and [👍 reactions](https://help.github.com/articles/about-discussions-in-issues-and-pull-requests/) from the community.
|
Feature request issues will remain closed until we see sufficient interest via comments and [👍 reactions](https://help.github.com/articles/about-discussions-in-issues-and-pull-requests/) from the community.
|
||||||
|
|
||||||
You can see a [list of current feature requests which require votes here](https://github.com/woocommerce/woocommerce/issues?q=label%3A%22votes+needed%22+label%3Aenhancement+sort%3Areactions-%2B1-desc+is%3Aclosed).
|
You can see a [list of current feature requests which require votes here](https://github.com/woocommerce/woocommerce/issues?q=is%3Aclosed+label%3A%22type%3A+enhancement%22+label%3A%22votes+needed%22+sort%3Areactions-%2B1-desc).
|
||||||
|
|
|
@ -35,9 +35,9 @@ jobs:
|
||||||
- npm install
|
- npm install
|
||||||
- composer install --no-dev
|
- composer install --no-dev
|
||||||
script:
|
script:
|
||||||
- npm run build:assets
|
- travis_retry npm run build:assets
|
||||||
- npm run docker:up
|
- travis_retry npm run docker:up
|
||||||
- npm run test:e2e
|
- travis_retry npm run test:e2e
|
||||||
after_script:
|
after_script:
|
||||||
- npm run docker:down
|
- npm run docker:down
|
||||||
- name: "WP Nightly"
|
- name: "WP Nightly"
|
||||||
|
|
|
@ -3169,6 +3169,12 @@ table.wc_input_table {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
table.wc_tax_rates {
|
||||||
|
td.country {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
table.wc_gateways,
|
table.wc_gateways,
|
||||||
table.wc_emails,
|
table.wc_emails,
|
||||||
table.wc_shipping {
|
table.wc_shipping {
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
"phpunit/phpunit": "^8.5",
|
"phpunit/phpunit": "^8.5",
|
||||||
"squizlabs/php_codesniffer": "^3.5"
|
"squizlabs/php_codesniffer": "^3.5"
|
||||||
},
|
},
|
||||||
|
"default-branch": true,
|
||||||
"bin": [
|
"bin": [
|
||||||
"bin/mozart"
|
"bin/mozart"
|
||||||
],
|
],
|
||||||
|
@ -52,6 +53,10 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "Composes all dependencies as a package inside a WordPress plugin",
|
"description": "Composes all dependencies as a package inside a WordPress plugin",
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/coenjacobs/mozart/issues",
|
||||||
|
"source": "https://github.com/coenjacobs/mozart/tree/master"
|
||||||
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"url": "https://github.com/coenjacobs",
|
"url": "https://github.com/coenjacobs",
|
||||||
|
@ -142,6 +147,10 @@
|
||||||
"sftp",
|
"sftp",
|
||||||
"storage"
|
"storage"
|
||||||
],
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/thephpleague/flysystem/issues",
|
||||||
|
"source": "https://github.com/thephpleague/flysystem/tree/1.0.70"
|
||||||
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"url": "https://offset.earth/frankdejonge",
|
"url": "https://offset.earth/frankdejonge",
|
||||||
|
@ -197,6 +206,10 @@
|
||||||
"container-interop",
|
"container-interop",
|
||||||
"psr"
|
"psr"
|
||||||
],
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/php-fig/container/issues",
|
||||||
|
"source": "https://github.com/php-fig/container/tree/master"
|
||||||
|
},
|
||||||
"time": "2017-02-14T16:28:37+00:00"
|
"time": "2017-02-14T16:28:37+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -269,6 +282,9 @@
|
||||||
],
|
],
|
||||||
"description": "Symfony Console Component",
|
"description": "Symfony Console Component",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/symfony/console/tree/v4.4.17"
|
||||||
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"url": "https://symfony.com/sponsor",
|
"url": "https://symfony.com/sponsor",
|
||||||
|
@ -327,6 +343,9 @@
|
||||||
],
|
],
|
||||||
"description": "Symfony Finder Component",
|
"description": "Symfony Finder Component",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/symfony/finder/tree/v4.4.17"
|
||||||
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"url": "https://symfony.com/sponsor",
|
"url": "https://symfony.com/sponsor",
|
||||||
|
@ -404,6 +423,9 @@
|
||||||
"portable",
|
"portable",
|
||||||
"shim"
|
"shim"
|
||||||
],
|
],
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.20.0"
|
||||||
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"url": "https://symfony.com/sponsor",
|
"url": "https://symfony.com/sponsor",
|
||||||
|
@ -480,6 +502,9 @@
|
||||||
"portable",
|
"portable",
|
||||||
"shim"
|
"shim"
|
||||||
],
|
],
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/symfony/polyfill-php73/tree/v1.20.0"
|
||||||
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"url": "https://symfony.com/sponsor",
|
"url": "https://symfony.com/sponsor",
|
||||||
|
@ -560,6 +585,9 @@
|
||||||
"portable",
|
"portable",
|
||||||
"shim"
|
"shim"
|
||||||
],
|
],
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/symfony/polyfill-php80/tree/v1.20.0"
|
||||||
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"url": "https://symfony.com/sponsor",
|
"url": "https://symfony.com/sponsor",
|
||||||
|
@ -636,6 +664,9 @@
|
||||||
"interoperability",
|
"interoperability",
|
||||||
"standards"
|
"standards"
|
||||||
],
|
],
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/symfony/service-contracts/tree/v1.1.9"
|
||||||
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"url": "https://symfony.com/sponsor",
|
"url": "https://symfony.com/sponsor",
|
||||||
|
@ -665,5 +696,5 @@
|
||||||
"platform-overrides": {
|
"platform-overrides": {
|
||||||
"php": "7.2"
|
"php": "7.2"
|
||||||
},
|
},
|
||||||
"plugin-api-version": "1.1.0"
|
"plugin-api-version": "2.0.0"
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,6 +71,10 @@
|
||||||
"stylecheck",
|
"stylecheck",
|
||||||
"tests"
|
"tests"
|
||||||
],
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/dealerdirect/phpcodesniffer-composer-installer/issues",
|
||||||
|
"source": "https://github.com/dealerdirect/phpcodesniffer-composer-installer"
|
||||||
|
},
|
||||||
"time": "2020-06-25T14:57:39+00:00"
|
"time": "2020-06-25T14:57:39+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -129,6 +133,10 @@
|
||||||
"phpcs",
|
"phpcs",
|
||||||
"standards"
|
"standards"
|
||||||
],
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/PHPCompatibility/PHPCompatibility/issues",
|
||||||
|
"source": "https://github.com/PHPCompatibility/PHPCompatibility"
|
||||||
|
},
|
||||||
"time": "2019-12-27T09:44:58+00:00"
|
"time": "2019-12-27T09:44:58+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -181,6 +189,10 @@
|
||||||
"polyfill",
|
"polyfill",
|
||||||
"standards"
|
"standards"
|
||||||
],
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie/issues",
|
||||||
|
"source": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie"
|
||||||
|
},
|
||||||
"time": "2019-11-04T15:17:54+00:00"
|
"time": "2019-11-04T15:17:54+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -231,6 +243,10 @@
|
||||||
"standards",
|
"standards",
|
||||||
"wordpress"
|
"wordpress"
|
||||||
],
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/PHPCompatibility/PHPCompatibilityWP/issues",
|
||||||
|
"source": "https://github.com/PHPCompatibility/PHPCompatibilityWP"
|
||||||
|
},
|
||||||
"time": "2019-08-28T14:22:28+00:00"
|
"time": "2019-08-28T14:22:28+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -282,6 +298,11 @@
|
||||||
"phpcs",
|
"phpcs",
|
||||||
"standards"
|
"standards"
|
||||||
],
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues",
|
||||||
|
"source": "https://github.com/squizlabs/PHP_CodeSniffer",
|
||||||
|
"wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki"
|
||||||
|
},
|
||||||
"time": "2020-10-23T02:01:07+00:00"
|
"time": "2020-10-23T02:01:07+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -322,6 +343,10 @@
|
||||||
"woocommerce",
|
"woocommerce",
|
||||||
"wordpress"
|
"wordpress"
|
||||||
],
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/woocommerce/woocommerce-sniffs/issues",
|
||||||
|
"source": "https://github.com/woocommerce/woocommerce-sniffs/tree/master"
|
||||||
|
},
|
||||||
"time": "2020-08-06T18:23:45+00:00"
|
"time": "2020-08-06T18:23:45+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -368,6 +393,11 @@
|
||||||
"standards",
|
"standards",
|
||||||
"wordpress"
|
"wordpress"
|
||||||
],
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/WordPress/WordPress-Coding-Standards/issues",
|
||||||
|
"source": "https://github.com/WordPress/WordPress-Coding-Standards",
|
||||||
|
"wiki": "https://github.com/WordPress/WordPress-Coding-Standards/wiki"
|
||||||
|
},
|
||||||
"time": "2020-05-13T23:57:56+00:00"
|
"time": "2020-05-13T23:57:56+00:00"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
@ -381,5 +411,5 @@
|
||||||
"platform-overrides": {
|
"platform-overrides": {
|
||||||
"php": "7.0"
|
"php": "7.0"
|
||||||
},
|
},
|
||||||
"plugin-api-version": "1.1.0"
|
"plugin-api-version": "2.0.0"
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,6 +59,10 @@
|
||||||
"constructor",
|
"constructor",
|
||||||
"instantiate"
|
"instantiate"
|
||||||
],
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/doctrine/instantiator/issues",
|
||||||
|
"source": "https://github.com/doctrine/instantiator/tree/master"
|
||||||
|
},
|
||||||
"time": "2015-06-14T21:17:01+00:00"
|
"time": "2015-06-14T21:17:01+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -104,6 +108,10 @@
|
||||||
"object",
|
"object",
|
||||||
"object graph"
|
"object graph"
|
||||||
],
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/myclabs/DeepCopy/issues",
|
||||||
|
"source": "https://github.com/myclabs/DeepCopy/tree/1.x"
|
||||||
|
},
|
||||||
"time": "2017-10-19T19:58:43+00:00"
|
"time": "2017-10-19T19:58:43+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -159,6 +167,10 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)",
|
"description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)",
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/phar-io/manifest/issues",
|
||||||
|
"source": "https://github.com/phar-io/manifest/tree/master"
|
||||||
|
},
|
||||||
"time": "2017-03-05T18:14:27+00:00"
|
"time": "2017-03-05T18:14:27+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -206,6 +218,10 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "Library for handling version information and constraints",
|
"description": "Library for handling version information and constraints",
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/phar-io/version/issues",
|
||||||
|
"source": "https://github.com/phar-io/version/tree/master"
|
||||||
|
},
|
||||||
"time": "2017-03-05T17:38:23+00:00"
|
"time": "2017-03-05T17:38:23+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -260,6 +276,10 @@
|
||||||
"reflection",
|
"reflection",
|
||||||
"static analysis"
|
"static analysis"
|
||||||
],
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/phpDocumentor/ReflectionCommon/issues",
|
||||||
|
"source": "https://github.com/phpDocumentor/ReflectionCommon/tree/master"
|
||||||
|
},
|
||||||
"time": "2017-09-11T18:02:19+00:00"
|
"time": "2017-09-11T18:02:19+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -312,6 +332,10 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
|
"description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues",
|
||||||
|
"source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/release/4.x"
|
||||||
|
},
|
||||||
"time": "2019-12-28T18:55:12+00:00"
|
"time": "2019-12-28T18:55:12+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -357,6 +381,10 @@
|
||||||
"email": "me@mikevanriel.com"
|
"email": "me@mikevanriel.com"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/phpDocumentor/TypeResolver/issues",
|
||||||
|
"source": "https://github.com/phpDocumentor/TypeResolver/tree/master"
|
||||||
|
},
|
||||||
"time": "2017-12-30T13:23:38+00:00"
|
"time": "2017-12-30T13:23:38+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -420,6 +448,10 @@
|
||||||
"spy",
|
"spy",
|
||||||
"stub"
|
"stub"
|
||||||
],
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/phpspec/prophecy/issues",
|
||||||
|
"source": "https://github.com/phpspec/prophecy/tree/v1.10.3"
|
||||||
|
},
|
||||||
"time": "2020-03-05T15:02:03+00:00"
|
"time": "2020-03-05T15:02:03+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -483,6 +515,10 @@
|
||||||
"testing",
|
"testing",
|
||||||
"xunit"
|
"xunit"
|
||||||
],
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
|
||||||
|
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/5.3"
|
||||||
|
},
|
||||||
"time": "2018-04-06T15:36:58+00:00"
|
"time": "2018-04-06T15:36:58+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -530,6 +566,11 @@
|
||||||
"filesystem",
|
"filesystem",
|
||||||
"iterator"
|
"iterator"
|
||||||
],
|
],
|
||||||
|
"support": {
|
||||||
|
"irc": "irc://irc.freenode.net/phpunit",
|
||||||
|
"issues": "https://github.com/sebastianbergmann/php-file-iterator/issues",
|
||||||
|
"source": "https://github.com/sebastianbergmann/php-file-iterator/tree/1.4.5"
|
||||||
|
},
|
||||||
"time": "2017-11-27T13:52:08+00:00"
|
"time": "2017-11-27T13:52:08+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -571,6 +612,10 @@
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"template"
|
"template"
|
||||||
],
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/sebastianbergmann/php-text-template/issues",
|
||||||
|
"source": "https://github.com/sebastianbergmann/php-text-template/tree/1.2.1"
|
||||||
|
},
|
||||||
"time": "2015-06-21T13:50:34+00:00"
|
"time": "2015-06-21T13:50:34+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -620,6 +665,10 @@
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"timer"
|
"timer"
|
||||||
],
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/sebastianbergmann/php-timer/issues",
|
||||||
|
"source": "https://github.com/sebastianbergmann/php-timer/tree/master"
|
||||||
|
},
|
||||||
"time": "2017-02-26T11:10:40+00:00"
|
"time": "2017-02-26T11:10:40+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -669,6 +718,10 @@
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"tokenizer"
|
"tokenizer"
|
||||||
],
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/sebastianbergmann/php-token-stream/issues",
|
||||||
|
"source": "https://github.com/sebastianbergmann/php-token-stream/tree/master"
|
||||||
|
},
|
||||||
"abandoned": true,
|
"abandoned": true,
|
||||||
"time": "2017-11-27T05:48:46+00:00"
|
"time": "2017-11-27T05:48:46+00:00"
|
||||||
},
|
},
|
||||||
|
@ -754,6 +807,10 @@
|
||||||
"testing",
|
"testing",
|
||||||
"xunit"
|
"xunit"
|
||||||
],
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
|
||||||
|
"source": "https://github.com/sebastianbergmann/phpunit/tree/6.5.14"
|
||||||
|
},
|
||||||
"time": "2019-02-01T05:22:47+00:00"
|
"time": "2019-02-01T05:22:47+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -813,6 +870,10 @@
|
||||||
"mock",
|
"mock",
|
||||||
"xunit"
|
"xunit"
|
||||||
],
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/sebastianbergmann/phpunit-mock-objects/issues",
|
||||||
|
"source": "https://github.com/sebastianbergmann/phpunit-mock-objects/tree/5.0.10"
|
||||||
|
},
|
||||||
"abandoned": true,
|
"abandoned": true,
|
||||||
"time": "2018-08-09T05:50:03+00:00"
|
"time": "2018-08-09T05:50:03+00:00"
|
||||||
},
|
},
|
||||||
|
@ -859,6 +920,10 @@
|
||||||
],
|
],
|
||||||
"description": "Looks up which function or method a line of code belongs to",
|
"description": "Looks up which function or method a line of code belongs to",
|
||||||
"homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/",
|
"homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/",
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues",
|
||||||
|
"source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/1.0.2"
|
||||||
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"url": "https://github.com/sebastianbergmann",
|
"url": "https://github.com/sebastianbergmann",
|
||||||
|
@ -929,6 +994,10 @@
|
||||||
"compare",
|
"compare",
|
||||||
"equality"
|
"equality"
|
||||||
],
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/sebastianbergmann/comparator/issues",
|
||||||
|
"source": "https://github.com/sebastianbergmann/comparator/tree/master"
|
||||||
|
},
|
||||||
"time": "2018-02-01T13:46:46+00:00"
|
"time": "2018-02-01T13:46:46+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -981,6 +1050,10 @@
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"diff"
|
"diff"
|
||||||
],
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/sebastianbergmann/diff/issues",
|
||||||
|
"source": "https://github.com/sebastianbergmann/diff/tree/master"
|
||||||
|
},
|
||||||
"time": "2017-08-03T08:09:46+00:00"
|
"time": "2017-08-03T08:09:46+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1031,6 +1104,10 @@
|
||||||
"environment",
|
"environment",
|
||||||
"hhvm"
|
"hhvm"
|
||||||
],
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/sebastianbergmann/environment/issues",
|
||||||
|
"source": "https://github.com/sebastianbergmann/environment/tree/master"
|
||||||
|
},
|
||||||
"time": "2017-07-01T08:51:00+00:00"
|
"time": "2017-07-01T08:51:00+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1098,6 +1175,10 @@
|
||||||
"export",
|
"export",
|
||||||
"exporter"
|
"exporter"
|
||||||
],
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/sebastianbergmann/exporter/issues",
|
||||||
|
"source": "https://github.com/sebastianbergmann/exporter/tree/3.1.3"
|
||||||
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"url": "https://github.com/sebastianbergmann",
|
"url": "https://github.com/sebastianbergmann",
|
||||||
|
@ -1155,6 +1236,10 @@
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"global state"
|
"global state"
|
||||||
],
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/sebastianbergmann/global-state/issues",
|
||||||
|
"source": "https://github.com/sebastianbergmann/global-state/tree/2.0.0"
|
||||||
|
},
|
||||||
"time": "2017-04-27T15:39:26+00:00"
|
"time": "2017-04-27T15:39:26+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1202,6 +1287,10 @@
|
||||||
],
|
],
|
||||||
"description": "Traverses array structures and object graphs to enumerate all referenced objects",
|
"description": "Traverses array structures and object graphs to enumerate all referenced objects",
|
||||||
"homepage": "https://github.com/sebastianbergmann/object-enumerator/",
|
"homepage": "https://github.com/sebastianbergmann/object-enumerator/",
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/sebastianbergmann/object-enumerator/issues",
|
||||||
|
"source": "https://github.com/sebastianbergmann/object-enumerator/tree/3.0.4"
|
||||||
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"url": "https://github.com/sebastianbergmann",
|
"url": "https://github.com/sebastianbergmann",
|
||||||
|
@ -1253,6 +1342,10 @@
|
||||||
],
|
],
|
||||||
"description": "Allows reflection of object attributes, including inherited and non-public ones",
|
"description": "Allows reflection of object attributes, including inherited and non-public ones",
|
||||||
"homepage": "https://github.com/sebastianbergmann/object-reflector/",
|
"homepage": "https://github.com/sebastianbergmann/object-reflector/",
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/sebastianbergmann/object-reflector/issues",
|
||||||
|
"source": "https://github.com/sebastianbergmann/object-reflector/tree/1.1.2"
|
||||||
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"url": "https://github.com/sebastianbergmann",
|
"url": "https://github.com/sebastianbergmann",
|
||||||
|
@ -1312,6 +1405,10 @@
|
||||||
],
|
],
|
||||||
"description": "Provides functionality to recursively process PHP variables",
|
"description": "Provides functionality to recursively process PHP variables",
|
||||||
"homepage": "http://www.github.com/sebastianbergmann/recursion-context",
|
"homepage": "http://www.github.com/sebastianbergmann/recursion-context",
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/sebastianbergmann/recursion-context/issues",
|
||||||
|
"source": "https://github.com/sebastianbergmann/recursion-context/tree/3.0.1"
|
||||||
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"url": "https://github.com/sebastianbergmann",
|
"url": "https://github.com/sebastianbergmann",
|
||||||
|
@ -1360,6 +1457,10 @@
|
||||||
],
|
],
|
||||||
"description": "Provides a list of PHP built-in functions that operate on resources",
|
"description": "Provides a list of PHP built-in functions that operate on resources",
|
||||||
"homepage": "https://www.github.com/sebastianbergmann/resource-operations",
|
"homepage": "https://www.github.com/sebastianbergmann/resource-operations",
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/sebastianbergmann/resource-operations/issues",
|
||||||
|
"source": "https://github.com/sebastianbergmann/resource-operations/tree/master"
|
||||||
|
},
|
||||||
"time": "2015-07-28T20:34:47+00:00"
|
"time": "2015-07-28T20:34:47+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1403,6 +1504,10 @@
|
||||||
],
|
],
|
||||||
"description": "Library that helps with managing the version number of Git-hosted PHP projects",
|
"description": "Library that helps with managing the version number of Git-hosted PHP projects",
|
||||||
"homepage": "https://github.com/sebastianbergmann/version",
|
"homepage": "https://github.com/sebastianbergmann/version",
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/sebastianbergmann/version/issues",
|
||||||
|
"source": "https://github.com/sebastianbergmann/version/tree/master"
|
||||||
|
},
|
||||||
"time": "2016-10-03T07:35:21+00:00"
|
"time": "2016-10-03T07:35:21+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1465,6 +1570,9 @@
|
||||||
"polyfill",
|
"polyfill",
|
||||||
"portable"
|
"portable"
|
||||||
],
|
],
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.19.0"
|
||||||
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"url": "https://symfony.com/sponsor",
|
"url": "https://symfony.com/sponsor",
|
||||||
|
@ -1519,6 +1627,10 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
|
"description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/theseer/tokenizer/issues",
|
||||||
|
"source": "https://github.com/theseer/tokenizer/tree/master"
|
||||||
|
},
|
||||||
"time": "2019-06-13T22:48:21+00:00"
|
"time": "2019-06-13T22:48:21+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1568,6 +1680,10 @@
|
||||||
"check",
|
"check",
|
||||||
"validate"
|
"validate"
|
||||||
],
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/webmozart/assert/issues",
|
||||||
|
"source": "https://github.com/webmozart/assert/tree/master"
|
||||||
|
},
|
||||||
"time": "2020-07-08T17:02:28+00:00"
|
"time": "2020-07-08T17:02:28+00:00"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
@ -1581,5 +1697,5 @@
|
||||||
"platform-overrides": {
|
"platform-overrides": {
|
||||||
"php": "7.0"
|
"php": "7.0"
|
||||||
},
|
},
|
||||||
"plugin-api-version": "1.1.0"
|
"plugin-api-version": "2.0.0"
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,6 +67,11 @@
|
||||||
"po",
|
"po",
|
||||||
"translation"
|
"translation"
|
||||||
],
|
],
|
||||||
|
"support": {
|
||||||
|
"email": "oom@oscarotero.com",
|
||||||
|
"issues": "https://github.com/oscarotero/Gettext/issues",
|
||||||
|
"source": "https://github.com/php-gettext/Gettext/tree/v4.8.3"
|
||||||
|
},
|
||||||
"time": "2020-11-18T22:35:49+00:00"
|
"time": "2020-11-18T22:35:49+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -128,6 +133,10 @@
|
||||||
"translations",
|
"translations",
|
||||||
"unicode"
|
"unicode"
|
||||||
],
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/php-gettext/Languages/issues",
|
||||||
|
"source": "https://github.com/php-gettext/Languages/tree/2.6.0"
|
||||||
|
},
|
||||||
"time": "2019-11-13T10:30:21+00:00"
|
"time": "2019-11-13T10:30:21+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -173,6 +182,10 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "Peast is PHP library that generates AST for JavaScript code",
|
"description": "Peast is PHP library that generates AST for JavaScript code",
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/mck89/peast/issues",
|
||||||
|
"source": "https://github.com/mck89/peast/tree/v1.11.0"
|
||||||
|
},
|
||||||
"time": "2020-10-09T15:12:13+00:00"
|
"time": "2020-10-09T15:12:13+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -219,6 +232,10 @@
|
||||||
"mustache",
|
"mustache",
|
||||||
"templating"
|
"templating"
|
||||||
],
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/bobthecow/mustache.php/issues",
|
||||||
|
"source": "https://github.com/bobthecow/mustache.php/tree/master"
|
||||||
|
},
|
||||||
"time": "2019-11-23T21:40:31+00:00"
|
"time": "2019-11-23T21:40:31+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -268,6 +285,10 @@
|
||||||
"iri",
|
"iri",
|
||||||
"sockets"
|
"sockets"
|
||||||
],
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/rmccue/Requests/issues",
|
||||||
|
"source": "https://github.com/rmccue/Requests/tree/master"
|
||||||
|
},
|
||||||
"time": "2016-10-13T00:11:37+00:00"
|
"time": "2016-10-13T00:11:37+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -317,20 +338,23 @@
|
||||||
],
|
],
|
||||||
"description": "Symfony Finder Component",
|
"description": "Symfony Finder Component",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/symfony/finder/tree/3.3"
|
||||||
|
},
|
||||||
"time": "2017-06-01T21:01:25+00:00"
|
"time": "2017-06-01T21:01:25+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "wp-cli/i18n-command",
|
"name": "wp-cli/i18n-command",
|
||||||
"version": "v2.2.5",
|
"version": "v2.2.6",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/wp-cli/i18n-command.git",
|
"url": "https://github.com/wp-cli/i18n-command.git",
|
||||||
"reference": "b02ecdc9a57f9633740c254d19749118b7411f0f"
|
"reference": "a66da3f09f6a728832381012848c3074bf1635c8"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/wp-cli/i18n-command/zipball/b02ecdc9a57f9633740c254d19749118b7411f0f",
|
"url": "https://api.github.com/repos/wp-cli/i18n-command/zipball/a66da3f09f6a728832381012848c3074bf1635c8",
|
||||||
"reference": "b02ecdc9a57f9633740c254d19749118b7411f0f",
|
"reference": "a66da3f09f6a728832381012848c3074bf1635c8",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -374,7 +398,11 @@
|
||||||
],
|
],
|
||||||
"description": "Provides internationalization tools for WordPress projects.",
|
"description": "Provides internationalization tools for WordPress projects.",
|
||||||
"homepage": "https://github.com/wp-cli/i18n-command",
|
"homepage": "https://github.com/wp-cli/i18n-command",
|
||||||
"time": "2020-07-08T15:20:38+00:00"
|
"support": {
|
||||||
|
"issues": "https://github.com/wp-cli/i18n-command/issues",
|
||||||
|
"source": "https://github.com/wp-cli/i18n-command/tree/v2.2.6"
|
||||||
|
},
|
||||||
|
"time": "2020-12-07T19:28:27+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "wp-cli/mustangostang-spyc",
|
"name": "wp-cli/mustangostang-spyc",
|
||||||
|
@ -422,6 +450,9 @@
|
||||||
],
|
],
|
||||||
"description": "A simple YAML loader/dumper class for PHP (WP-CLI fork)",
|
"description": "A simple YAML loader/dumper class for PHP (WP-CLI fork)",
|
||||||
"homepage": "https://github.com/mustangostang/spyc/",
|
"homepage": "https://github.com/mustangostang/spyc/",
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/wp-cli/spyc/tree/autoload"
|
||||||
|
},
|
||||||
"time": "2017-04-25T11:26:20+00:00"
|
"time": "2017-04-25T11:26:20+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -472,6 +503,10 @@
|
||||||
"cli",
|
"cli",
|
||||||
"console"
|
"console"
|
||||||
],
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/wp-cli/php-cli-tools/issues",
|
||||||
|
"source": "https://github.com/wp-cli/php-cli-tools/tree/master"
|
||||||
|
},
|
||||||
"time": "2018-09-04T13:28:00+00:00"
|
"time": "2018-09-04T13:28:00+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -534,6 +569,11 @@
|
||||||
"cli",
|
"cli",
|
||||||
"wordpress"
|
"wordpress"
|
||||||
],
|
],
|
||||||
|
"support": {
|
||||||
|
"docs": "https://make.wordpress.org/cli/handbook/",
|
||||||
|
"issues": "https://github.com/wp-cli/wp-cli/issues",
|
||||||
|
"source": "https://github.com/wp-cli/wp-cli"
|
||||||
|
},
|
||||||
"time": "2020-02-18T08:15:37+00:00"
|
"time": "2020-02-18T08:15:37+00:00"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
@ -547,5 +587,5 @@
|
||||||
"platform-overrides": {
|
"platform-overrides": {
|
||||||
"php": "7.0"
|
"php": "7.0"
|
||||||
},
|
},
|
||||||
"plugin-api-version": "1.1.0"
|
"plugin-api-version": "2.0.0"
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,8 +21,8 @@
|
||||||
"pelago/emogrifier": "3.1.0",
|
"pelago/emogrifier": "3.1.0",
|
||||||
"psr/container": "1.0.0",
|
"psr/container": "1.0.0",
|
||||||
"woocommerce/action-scheduler": "3.1.6",
|
"woocommerce/action-scheduler": "3.1.6",
|
||||||
"woocommerce/woocommerce-admin": "1.7.3",
|
"woocommerce/woocommerce-admin": "1.8.1",
|
||||||
"woocommerce/woocommerce-blocks": "3.8.1"
|
"woocommerce/woocommerce-blocks": "4.0.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"bamarni/composer-bin-plugin": "^1.4"
|
"bamarni/composer-bin-plugin": "^1.4"
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "77e54b85eedb5be94edbd73cf5436900",
|
"content-hash": "8b83d26cd9edae1a33b5dde164c44216",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "automattic/jetpack-autoloader",
|
"name": "automattic/jetpack-autoloader",
|
||||||
|
@ -486,16 +486,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "woocommerce/woocommerce-admin",
|
"name": "woocommerce/woocommerce-admin",
|
||||||
"version": "1.7.3",
|
"version": "1.8.1",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/woocommerce/woocommerce-admin.git",
|
"url": "https://github.com/woocommerce/woocommerce-admin.git",
|
||||||
"reference": "16de972f319e5e6fc8dbebf5024dd263234f39e0"
|
"reference": "7cbf3db2dba0fa80e66761a8955ca4cc86863877"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/woocommerce/woocommerce-admin/zipball/16de972f319e5e6fc8dbebf5024dd263234f39e0",
|
"url": "https://api.github.com/repos/woocommerce/woocommerce-admin/zipball/7cbf3db2dba0fa80e66761a8955ca4cc86863877",
|
||||||
"reference": "16de972f319e5e6fc8dbebf5024dd263234f39e0",
|
"reference": "7cbf3db2dba0fa80e66761a8955ca4cc86863877",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -527,20 +527,24 @@
|
||||||
],
|
],
|
||||||
"description": "A modern, javascript-driven WooCommerce Admin experience.",
|
"description": "A modern, javascript-driven WooCommerce Admin experience.",
|
||||||
"homepage": "https://github.com/woocommerce/woocommerce-admin",
|
"homepage": "https://github.com/woocommerce/woocommerce-admin",
|
||||||
"time": "2020-12-03T21:12:01+00:00"
|
"support": {
|
||||||
|
"issues": "https://github.com/woocommerce/woocommerce-admin/issues",
|
||||||
|
"source": "https://github.com/woocommerce/woocommerce-admin/tree/v1.8.1"
|
||||||
|
},
|
||||||
|
"time": "2020-12-15T01:30:12+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "woocommerce/woocommerce-blocks",
|
"name": "woocommerce/woocommerce-blocks",
|
||||||
"version": "v3.8.1",
|
"version": "v4.0.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/woocommerce/woocommerce-gutenberg-products-block.git",
|
"url": "https://github.com/woocommerce/woocommerce-gutenberg-products-block.git",
|
||||||
"reference": "e5aef9eddd13c5511ba673eb70ed8cb3e80d828c"
|
"reference": "f5b2485254f36f0b85fd0f30c28e17bdf44a8d1e"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/woocommerce/woocommerce-gutenberg-products-block/zipball/e5aef9eddd13c5511ba673eb70ed8cb3e80d828c",
|
"url": "https://api.github.com/repos/woocommerce/woocommerce-gutenberg-products-block/zipball/f5b2485254f36f0b85fd0f30c28e17bdf44a8d1e",
|
||||||
"reference": "e5aef9eddd13c5511ba673eb70ed8cb3e80d828c",
|
"reference": "f5b2485254f36f0b85fd0f30c28e17bdf44a8d1e",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -574,7 +578,11 @@
|
||||||
"gutenberg",
|
"gutenberg",
|
||||||
"woocommerce"
|
"woocommerce"
|
||||||
],
|
],
|
||||||
"time": "2020-11-23T20:48:39+00:00"
|
"support": {
|
||||||
|
"issues": "https://github.com/woocommerce/woocommerce-gutenberg-products-block/issues",
|
||||||
|
"source": "https://github.com/woocommerce/woocommerce-gutenberg-products-block/tree/v4.0.0"
|
||||||
|
},
|
||||||
|
"time": "2020-12-08T13:17:01+00:00"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"packages-dev": [
|
"packages-dev": [
|
||||||
|
@ -637,5 +645,5 @@
|
||||||
"platform-overrides": {
|
"platform-overrides": {
|
||||||
"php": "7.0"
|
"php": "7.0"
|
||||||
},
|
},
|
||||||
"plugin-api-version": "1.1.0"
|
"plugin-api-version": "2.0.0"
|
||||||
}
|
}
|
||||||
|
|
|
@ -358,9 +358,6 @@ class WC_Countries {
|
||||||
|
|
||||||
if ( 'eu_vat' === $type ) {
|
if ( 'eu_vat' === $type ) {
|
||||||
$countries[] = 'MC';
|
$countries[] = 'MC';
|
||||||
$countries[] = 'IM';
|
|
||||||
// The UK is still part of the EU VAT zone.
|
|
||||||
$countries[] = 'GB';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return apply_filters( 'woocommerce_european_union_countries', $countries, $type );
|
return apply_filters( 'woocommerce_european_union_countries', $countries, $type );
|
||||||
|
|
|
@ -251,16 +251,62 @@ class WC_REST_Orders_V2_Controller extends WC_REST_CRUD_Controller {
|
||||||
/**
|
/**
|
||||||
* Get formatted item data.
|
* Get formatted item data.
|
||||||
*
|
*
|
||||||
* @since 3.0.0
|
* @since 3.0.0
|
||||||
* @param WC_Data $object WC_Data instance.
|
* @param WC_Order $order WC_Data instance.
|
||||||
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
protected function get_formatted_item_data( $object ) {
|
protected function get_formatted_item_data( $order ) {
|
||||||
$data = $object->get_data();
|
$extra_fields = array( 'meta_data', 'line_items', 'tax_lines', 'shipping_lines', 'fee_lines', 'coupon_lines', 'refunds' );
|
||||||
$format_decimal = array( 'discount_total', 'discount_tax', 'shipping_total', 'shipping_tax', 'shipping_total', 'shipping_tax', 'cart_tax', 'total', 'total_tax' );
|
$format_decimal = array( 'discount_total', 'discount_tax', 'shipping_total', 'shipping_tax', 'shipping_total', 'shipping_tax', 'cart_tax', 'total', 'total_tax' );
|
||||||
$format_date = array( 'date_created', 'date_modified', 'date_completed', 'date_paid' );
|
$format_date = array( 'date_created', 'date_modified', 'date_completed', 'date_paid' );
|
||||||
$format_line_items = array( 'line_items', 'tax_lines', 'shipping_lines', 'fee_lines', 'coupon_lines' );
|
$format_line_items = array( 'line_items', 'tax_lines', 'shipping_lines', 'fee_lines', 'coupon_lines' );
|
||||||
|
|
||||||
|
// Only fetch fields that we need.
|
||||||
|
$request = func_get_arg( 1 );
|
||||||
|
if ( $request ) {
|
||||||
|
$fields = $this->get_fields_for_response( $request );
|
||||||
|
$extra_fields = array_intersect( $extra_fields, $fields );
|
||||||
|
$format_decimal = array_intersect( $format_decimal, $fields );
|
||||||
|
$format_date = array_intersect( $format_date, $fields );
|
||||||
|
$format_line_items = array_intersect( $format_line_items, $fields );
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = $order->get_base_data();
|
||||||
|
|
||||||
|
// Add extra data as necessary.
|
||||||
|
foreach ( $extra_fields as $field ) {
|
||||||
|
switch ( $field ) {
|
||||||
|
case 'meta_data':
|
||||||
|
$data['meta_data'] = $order->get_meta_data();
|
||||||
|
break;
|
||||||
|
case 'line_items':
|
||||||
|
$data['line_items'] = $order->get_items( 'line_item');
|
||||||
|
break;
|
||||||
|
case 'tax_lines':
|
||||||
|
$data['tax_lines'] = $order->get_items( 'tax' );
|
||||||
|
break;
|
||||||
|
case 'shipping_lines':
|
||||||
|
$data['shipping_lines'] = $order->get_items( 'shipping' );
|
||||||
|
break;
|
||||||
|
case 'fee_lines':
|
||||||
|
$data['fee_lines'] = $order->get_items( 'fee' );
|
||||||
|
break;
|
||||||
|
case 'coupon_lines':
|
||||||
|
$data['coupon_lines'] = $order->get_items( 'coupon' );
|
||||||
|
break;
|
||||||
|
case 'refunds':
|
||||||
|
foreach ( $order->get_refunds() as $refund ) {
|
||||||
|
$data['refunds'][] = array(
|
||||||
|
'id' => $refund->get_id(),
|
||||||
|
'reason' => $refund->get_reason() ? $refund->get_reason() : '',
|
||||||
|
'total' => '-' . wc_format_decimal( $refund->get_amount(), $this->request['dp'] ),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Format decimal values.
|
// Format decimal values.
|
||||||
foreach ( $format_decimal as $key ) {
|
foreach ( $format_decimal as $key ) {
|
||||||
$data[ $key ] = wc_format_decimal( $data[ $key ], $this->request['dp'] );
|
$data[ $key ] = wc_format_decimal( $data[ $key ], $this->request['dp'] );
|
||||||
|
@ -281,59 +327,53 @@ class WC_REST_Orders_V2_Controller extends WC_REST_CRUD_Controller {
|
||||||
$data[ $key ] = array_values( array_map( array( $this, 'get_order_item_data' ), $data[ $key ] ) );
|
$data[ $key ] = array_values( array_map( array( $this, 'get_order_item_data' ), $data[ $key ] ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Refunds.
|
$allowed_fields = array(
|
||||||
$data['refunds'] = array();
|
'id',
|
||||||
foreach ( $object->get_refunds() as $refund ) {
|
'parent_id',
|
||||||
$data['refunds'][] = array(
|
'number',
|
||||||
'id' => $refund->get_id(),
|
'order_key',
|
||||||
'reason' => $refund->get_reason() ? $refund->get_reason() : '',
|
'created_via',
|
||||||
'total' => '-' . wc_format_decimal( $refund->get_amount(), $this->request['dp'] ),
|
'version',
|
||||||
);
|
'status',
|
||||||
}
|
'currency',
|
||||||
|
'date_created',
|
||||||
return array(
|
'date_created_gmt',
|
||||||
'id' => $object->get_id(),
|
'date_modified',
|
||||||
'parent_id' => $data['parent_id'],
|
'date_modified_gmt',
|
||||||
'number' => $data['number'],
|
'discount_total',
|
||||||
'order_key' => $data['order_key'],
|
'discount_tax',
|
||||||
'created_via' => $data['created_via'],
|
'shipping_total',
|
||||||
'version' => $data['version'],
|
'shipping_tax',
|
||||||
'status' => $data['status'],
|
'cart_tax',
|
||||||
'currency' => $data['currency'],
|
'total',
|
||||||
'date_created' => $data['date_created'],
|
'total_tax',
|
||||||
'date_created_gmt' => $data['date_created_gmt'],
|
'prices_include_tax',
|
||||||
'date_modified' => $data['date_modified'],
|
'customer_id',
|
||||||
'date_modified_gmt' => $data['date_modified_gmt'],
|
'customer_ip_address',
|
||||||
'discount_total' => $data['discount_total'],
|
'customer_user_agent',
|
||||||
'discount_tax' => $data['discount_tax'],
|
'customer_note',
|
||||||
'shipping_total' => $data['shipping_total'],
|
'billing',
|
||||||
'shipping_tax' => $data['shipping_tax'],
|
'shipping',
|
||||||
'cart_tax' => $data['cart_tax'],
|
'payment_method',
|
||||||
'total' => $data['total'],
|
'payment_method_title',
|
||||||
'total_tax' => $data['total_tax'],
|
'transaction_id',
|
||||||
'prices_include_tax' => $data['prices_include_tax'],
|
'date_paid',
|
||||||
'customer_id' => $data['customer_id'],
|
'date_paid_gmt',
|
||||||
'customer_ip_address' => $data['customer_ip_address'],
|
'date_completed',
|
||||||
'customer_user_agent' => $data['customer_user_agent'],
|
'date_completed_gmt',
|
||||||
'customer_note' => $data['customer_note'],
|
'cart_hash',
|
||||||
'billing' => $data['billing'],
|
'meta_data',
|
||||||
'shipping' => $data['shipping'],
|
'line_items',
|
||||||
'payment_method' => $data['payment_method'],
|
'tax_lines',
|
||||||
'payment_method_title' => $data['payment_method_title'],
|
'shipping_lines',
|
||||||
'transaction_id' => $data['transaction_id'],
|
'fee_lines',
|
||||||
'date_paid' => $data['date_paid'],
|
'coupon_lines',
|
||||||
'date_paid_gmt' => $data['date_paid_gmt'],
|
'refunds',
|
||||||
'date_completed' => $data['date_completed'],
|
|
||||||
'date_completed_gmt' => $data['date_completed_gmt'],
|
|
||||||
'cart_hash' => $data['cart_hash'],
|
|
||||||
'meta_data' => $data['meta_data'],
|
|
||||||
'line_items' => $data['line_items'],
|
|
||||||
'tax_lines' => $data['tax_lines'],
|
|
||||||
'shipping_lines' => $data['shipping_lines'],
|
|
||||||
'fee_lines' => $data['fee_lines'],
|
|
||||||
'coupon_lines' => $data['coupon_lines'],
|
|
||||||
'refunds' => $data['refunds'],
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$data = array_intersect_key( $data, array_flip( $allowed_fields ) );
|
||||||
|
|
||||||
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -347,7 +387,7 @@ class WC_REST_Orders_V2_Controller extends WC_REST_CRUD_Controller {
|
||||||
public function prepare_object_for_response( $object, $request ) {
|
public function prepare_object_for_response( $object, $request ) {
|
||||||
$this->request = $request;
|
$this->request = $request;
|
||||||
$this->request['dp'] = is_null( $this->request['dp'] ) ? wc_get_price_decimals() : absint( $this->request['dp'] );
|
$this->request['dp'] = is_null( $this->request['dp'] ) ? wc_get_price_decimals() : absint( $this->request['dp'] );
|
||||||
$data = $this->get_formatted_item_data( $object );
|
$data = $this->get_formatted_item_data( $object, $request );
|
||||||
$context = ! empty( $request['context'] ) ? $request['context'] : 'view';
|
$context = ! empty( $request['context'] ) ? $request['context'] : 'view';
|
||||||
$data = $this->add_additional_fields_to_object( $data, $request );
|
$data = $this->add_additional_fields_to_object( $data, $request );
|
||||||
$data = $this->filter_response_by_context( $data, $context );
|
$data = $this->filter_response_by_context( $data, $context );
|
||||||
|
|
|
@ -159,7 +159,7 @@ class WC_REST_Products_V2_Controller extends WC_REST_CRUD_Controller {
|
||||||
*/
|
*/
|
||||||
public function prepare_object_for_response( $object, $request ) {
|
public function prepare_object_for_response( $object, $request ) {
|
||||||
$context = ! empty( $request['context'] ) ? $request['context'] : 'view';
|
$context = ! empty( $request['context'] ) ? $request['context'] : 'view';
|
||||||
$data = $this->get_product_data( $object, $context );
|
$data = $this->get_product_data( $object, $context, $request );
|
||||||
|
|
||||||
// Add variations to variable products.
|
// Add variations to variable products.
|
||||||
if ( $object->is_type( 'variable' ) && $object->has_child() ) {
|
if ( $object->is_type( 'variable' ) && $object->has_child() ) {
|
||||||
|
@ -589,86 +589,254 @@ class WC_REST_Products_V2_Controller extends WC_REST_CRUD_Controller {
|
||||||
return $attributes;
|
return $attributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch price HTML.
|
||||||
|
* @param WC_Product $product Product object.
|
||||||
|
* @param string $context Context of request, can be `view` or `edit`.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function api_get_price_html( $product, $context ) {
|
||||||
|
return $product->get_price_html();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch related IDs.
|
||||||
|
* @param WC_Product $product Product object.
|
||||||
|
* @param string $context Context of request, can be `view` or `edit`.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function api_get_related_ids( $product, $context ) {
|
||||||
|
return array_map( 'absint', array_values( wc_get_related_products( $product->get_id() ) ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch meta data.
|
||||||
|
* @param WC_Product $product Product object.
|
||||||
|
* @param string $context Context of request, can be `view` or `edit`.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function api_get_meta_data( $product, $context ) {
|
||||||
|
return $product->get_meta_data();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get product data.
|
* Get product data.
|
||||||
*
|
*
|
||||||
* @param WC_Product $product Product instance.
|
* @param WC_Product $product Product instance.
|
||||||
* @param string $context Request context.
|
* @param string $context Request context. Options: 'view' and 'edit'.
|
||||||
* Options: 'view' and 'edit'.
|
* @param WP_REST_Request $request Current request object. For backward compatibility, we pass this argument silently.
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
protected function get_product_data( $product, $context = 'view' ) {
|
protected function get_product_data( $product, $context = 'view' ) {
|
||||||
$data = array(
|
$fields = array();
|
||||||
'id' => $product->get_id(),
|
$request = func_get_arg( 2 );
|
||||||
'name' => $product->get_name( $context ),
|
if ( $request instanceof WP_REST_Request ) {
|
||||||
'slug' => $product->get_slug( $context ),
|
$fields = $this->get_fields_for_response( $request );
|
||||||
'permalink' => $product->get_permalink(),
|
}
|
||||||
'date_created' => wc_rest_prepare_date_response( $product->get_date_created( $context ), false ),
|
$base_data = array();
|
||||||
'date_created_gmt' => wc_rest_prepare_date_response( $product->get_date_created( $context ) ),
|
foreach ( $fields as $field ) {
|
||||||
'date_modified' => wc_rest_prepare_date_response( $product->get_date_modified( $context ), false ),
|
switch ( $field ) {
|
||||||
'date_modified_gmt' => wc_rest_prepare_date_response( $product->get_date_modified( $context ) ),
|
case 'id':
|
||||||
'type' => $product->get_type(),
|
$base_data['id'] = $product->get_id();
|
||||||
'status' => $product->get_status( $context ),
|
break;
|
||||||
'featured' => $product->is_featured(),
|
case 'name':
|
||||||
'catalog_visibility' => $product->get_catalog_visibility( $context ),
|
$base_data['name'] = $product->get_name( $context );
|
||||||
'description' => 'view' === $context ? wpautop( do_shortcode( $product->get_description() ) ) : $product->get_description( $context ),
|
break;
|
||||||
'short_description' => 'view' === $context ? apply_filters( 'woocommerce_short_description', $product->get_short_description() ) : $product->get_short_description( $context ),
|
case 'slug':
|
||||||
'sku' => $product->get_sku( $context ),
|
$base_data['slug'] = $product->get_slug( $context );
|
||||||
'price' => $product->get_price( $context ),
|
break;
|
||||||
'regular_price' => $product->get_regular_price( $context ),
|
|
||||||
'sale_price' => $product->get_sale_price( $context ) ? $product->get_sale_price( $context ) : '',
|
case 'permalink':
|
||||||
'date_on_sale_from' => wc_rest_prepare_date_response( $product->get_date_on_sale_from( $context ), false ),
|
$base_data['permalink'] = $product->get_permalink();
|
||||||
'date_on_sale_from_gmt' => wc_rest_prepare_date_response( $product->get_date_on_sale_from( $context ) ),
|
break;
|
||||||
'date_on_sale_to' => wc_rest_prepare_date_response( $product->get_date_on_sale_to( $context ), false ),
|
case 'date_created':
|
||||||
'date_on_sale_to_gmt' => wc_rest_prepare_date_response( $product->get_date_on_sale_to( $context ) ),
|
$base_data['date_created'] = wc_rest_prepare_date_response( $product->get_date_created( $context ), false );
|
||||||
'price_html' => $product->get_price_html(),
|
break;
|
||||||
'on_sale' => $product->is_on_sale( $context ),
|
case 'date_created_gmt':
|
||||||
'purchasable' => $product->is_purchasable(),
|
$base_data['date_created_gmt'] = wc_rest_prepare_date_response( $product->get_date_created( $context ) );
|
||||||
'total_sales' => $product->get_total_sales( $context ),
|
break;
|
||||||
'virtual' => $product->is_virtual(),
|
case 'date_modified':
|
||||||
'downloadable' => $product->is_downloadable(),
|
$base_data['date_modified'] = wc_rest_prepare_date_response( $product->get_date_modified( $context ), false );
|
||||||
'downloads' => $this->get_downloads( $product ),
|
break;
|
||||||
'download_limit' => $product->get_download_limit( $context ),
|
case 'date_modified_gmt':
|
||||||
'download_expiry' => $product->get_download_expiry( $context ),
|
$base_data['date_modified_gmt'] = wc_rest_prepare_date_response( $product->get_date_modified( $context ) );
|
||||||
'external_url' => $product->is_type( 'external' ) ? $product->get_product_url( $context ) : '',
|
break;
|
||||||
'button_text' => $product->is_type( 'external' ) ? $product->get_button_text( $context ) : '',
|
case 'type':
|
||||||
'tax_status' => $product->get_tax_status( $context ),
|
$base_data['type'] = $product->get_type();
|
||||||
'tax_class' => $product->get_tax_class( $context ),
|
break;
|
||||||
'manage_stock' => $product->managing_stock(),
|
case 'status':
|
||||||
'stock_quantity' => $product->get_stock_quantity( $context ),
|
$base_data['status'] = $product->get_status( $context );
|
||||||
'in_stock' => $product->is_in_stock(),
|
break;
|
||||||
'backorders' => $product->get_backorders( $context ),
|
case 'featured':
|
||||||
'backorders_allowed' => $product->backorders_allowed(),
|
$base_data['featured'] = $product->is_featured();
|
||||||
'backordered' => $product->is_on_backorder(),
|
break;
|
||||||
'sold_individually' => $product->is_sold_individually(),
|
case 'catalog_visibility':
|
||||||
'weight' => $product->get_weight( $context ),
|
$base_data['catalog_visibility'] = $product->get_catalog_visibility( $context );
|
||||||
'dimensions' => array(
|
break;
|
||||||
'length' => $product->get_length( $context ),
|
case 'description':
|
||||||
'width' => $product->get_width( $context ),
|
$base_data['description'] = 'view' === $context ? wpautop( do_shortcode( $product->get_description() ) ) : $product->get_description( $context );
|
||||||
'height' => $product->get_height( $context ),
|
break;
|
||||||
),
|
case 'short_description':
|
||||||
'shipping_required' => $product->needs_shipping(),
|
$base_data['short_description'] = 'view' === $context ? apply_filters( 'woocommerce_short_description', $product->get_short_description() ) : $product->get_short_description( $context );
|
||||||
'shipping_taxable' => $product->is_shipping_taxable(),
|
break;
|
||||||
'shipping_class' => $product->get_shipping_class(),
|
case 'sku':
|
||||||
'shipping_class_id' => $product->get_shipping_class_id( $context ),
|
$base_data['sku'] = $product->get_sku( $context );
|
||||||
'reviews_allowed' => $product->get_reviews_allowed( $context ),
|
break;
|
||||||
'average_rating' => 'view' === $context ? wc_format_decimal( $product->get_average_rating(), 2 ) : $product->get_average_rating( $context ),
|
case 'price':
|
||||||
'rating_count' => $product->get_rating_count(),
|
$base_data['price'] = $product->get_price( $context );
|
||||||
'related_ids' => array_map( 'absint', array_values( wc_get_related_products( $product->get_id() ) ) ),
|
break;
|
||||||
'upsell_ids' => array_map( 'absint', $product->get_upsell_ids( $context ) ),
|
case 'regular_price':
|
||||||
'cross_sell_ids' => array_map( 'absint', $product->get_cross_sell_ids( $context ) ),
|
$base_data['regular_price'] = $product->get_regular_price( $context );
|
||||||
'parent_id' => $product->get_parent_id( $context ),
|
break;
|
||||||
'purchase_note' => 'view' === $context ? wpautop( do_shortcode( wp_kses_post( $product->get_purchase_note() ) ) ) : $product->get_purchase_note( $context ),
|
case 'sale_price':
|
||||||
'categories' => $this->get_taxonomy_terms( $product ),
|
$base_data['sale_price'] = $product->get_sale_price( $context ) ? $product->get_sale_price( $context ) : '';
|
||||||
'tags' => $this->get_taxonomy_terms( $product, 'tag' ),
|
break;
|
||||||
'images' => $this->get_images( $product ),
|
case 'date_on_sale_from':
|
||||||
'attributes' => $this->get_attributes( $product ),
|
$base_data['date_on_sale_from'] = wc_rest_prepare_date_response( $product->get_date_on_sale_from( $context ), false );
|
||||||
'default_attributes' => $this->get_default_attributes( $product ),
|
break;
|
||||||
'variations' => array(),
|
case 'date_on_sale_from_gmt':
|
||||||
'grouped_products' => array(),
|
$base_data['date_on_sale_from_gmt'] = wc_rest_prepare_date_response( $product->get_date_on_sale_from( $context ) );
|
||||||
'menu_order' => $product->get_menu_order( $context ),
|
break;
|
||||||
'meta_data' => $product->get_meta_data(),
|
case 'date_on_sale_to':
|
||||||
|
$base_data['date_on_sale_to'] = wc_rest_prepare_date_response( $product->get_date_on_sale_to( $context ), false );
|
||||||
|
break;
|
||||||
|
case 'date_on_sale_to_gmt':
|
||||||
|
$base_data['date_on_sale_to_gmt'] = wc_rest_prepare_date_response( $product->get_date_on_sale_to( $context ) );
|
||||||
|
break;
|
||||||
|
case 'on_sale':
|
||||||
|
$base_data['on_sale'] = $product->is_on_sale( $context );
|
||||||
|
break;
|
||||||
|
case 'purchasable':
|
||||||
|
$base_data['purchasable'] = $product->is_purchasable();
|
||||||
|
break;
|
||||||
|
case 'total_sales':
|
||||||
|
$base_data['total_sales'] = $product->get_total_sales( $context );
|
||||||
|
break;
|
||||||
|
case 'virtual':
|
||||||
|
$base_data['virtual'] = $product->is_virtual();
|
||||||
|
break;
|
||||||
|
case 'downloadable':
|
||||||
|
$base_data['downloadable'] = $product->is_downloadable();
|
||||||
|
break;
|
||||||
|
case 'downloads':
|
||||||
|
$base_data['downloads'] = $this->get_downloads( $product );
|
||||||
|
break;
|
||||||
|
case 'download_limit':
|
||||||
|
$base_data['download_limit'] = $product->get_download_limit( $context );
|
||||||
|
break;
|
||||||
|
case 'download_expiry':
|
||||||
|
$base_data['download_expiry'] = $product->get_download_expiry( $context );
|
||||||
|
break;
|
||||||
|
case 'external_url':
|
||||||
|
$base_data['external_url'] = $product->is_type( 'external' ) ? $product->get_product_url( $context ) : '';
|
||||||
|
break;
|
||||||
|
case 'button_text':
|
||||||
|
$base_data['button_text'] = $product->is_type( 'external' ) ? $product->get_button_text( $context ) : '';
|
||||||
|
break;
|
||||||
|
case 'tax_status':
|
||||||
|
$base_data['tax_status'] = $product->get_tax_status( $context );
|
||||||
|
break;
|
||||||
|
case 'tax_class':
|
||||||
|
$base_data['tax_class'] = $product->get_tax_class( $context );
|
||||||
|
break;
|
||||||
|
case 'manage_stock':
|
||||||
|
$base_data['manage_stock'] = $product->managing_stock();
|
||||||
|
break;
|
||||||
|
case 'stock_quantity':
|
||||||
|
$base_data['stock_quantity'] = $product->get_stock_quantity( $context );
|
||||||
|
break;
|
||||||
|
case 'in_stock':
|
||||||
|
$base_data['in_stock'] = $product->is_in_stock();
|
||||||
|
break;
|
||||||
|
case 'backorders':
|
||||||
|
$base_data['backorders'] = $product->get_backorders( $context );
|
||||||
|
break;
|
||||||
|
case 'backorders_allowed':
|
||||||
|
$base_data['backorders_allowed'] = $product->backorders_allowed();
|
||||||
|
break;
|
||||||
|
case 'backordered':
|
||||||
|
$base_data['backordered'] = $product->is_on_backorder();
|
||||||
|
break;
|
||||||
|
case 'sold_individually':
|
||||||
|
$base_data['sold_individually'] = $product->is_sold_individually();
|
||||||
|
break;
|
||||||
|
case 'weight':
|
||||||
|
$base_data['weight'] = $product->get_weight( $context );
|
||||||
|
break;
|
||||||
|
case 'dimensions':
|
||||||
|
$base_data['dimensions'] = array(
|
||||||
|
'length' => $product->get_length( $context ),
|
||||||
|
'width' => $product->get_width( $context ),
|
||||||
|
'height' => $product->get_height( $context ),
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case 'shipping_required':
|
||||||
|
$base_data['shipping_required'] = $product->needs_shipping();
|
||||||
|
break;
|
||||||
|
case 'shipping_taxable':
|
||||||
|
$base_data['shipping_taxable'] = $product->is_shipping_taxable();
|
||||||
|
break;
|
||||||
|
case 'shipping_class':
|
||||||
|
$base_data['shipping_class'] = $product->get_shipping_class();
|
||||||
|
break;
|
||||||
|
case 'shipping_class_id':
|
||||||
|
$base_data['shipping_class_id'] = $product->get_shipping_class_id( $context );
|
||||||
|
break;
|
||||||
|
case 'reviews_allowed':
|
||||||
|
$base_data['reviews_allowed'] = $product->get_reviews_allowed( $context );
|
||||||
|
break;
|
||||||
|
case 'average_rating':
|
||||||
|
$base_data['average_rating'] = 'view' === $context ? wc_format_decimal( $product->get_average_rating(), 2 ) : $product->get_average_rating( $context );
|
||||||
|
break;
|
||||||
|
case 'rating_count':
|
||||||
|
$base_data['rating_count'] = $product->get_rating_count();
|
||||||
|
break;
|
||||||
|
case 'upsell_ids':
|
||||||
|
$base_data['upsell_ids'] = array_map( 'absint', $product->get_upsell_ids( $context ) );
|
||||||
|
break;
|
||||||
|
case 'cross_sell_ids':
|
||||||
|
$base_data['cross_sell_ids'] = array_map( 'absint', $product->get_cross_sell_ids( $context ) );
|
||||||
|
break;
|
||||||
|
case 'parent_id':
|
||||||
|
$base_data['parent_id'] = $product->get_parent_id( $context );
|
||||||
|
break;
|
||||||
|
case 'purchase_note':
|
||||||
|
$base_data['purchase_note'] = 'view' === $context ? wpautop( do_shortcode( wp_kses_post( $product->get_purchase_note() ) ) ) : $product->get_purchase_note( $context );
|
||||||
|
break;
|
||||||
|
case 'categories':
|
||||||
|
$base_data['categories'] = $this->get_taxonomy_terms( $product );
|
||||||
|
break;
|
||||||
|
case 'tags':
|
||||||
|
$base_data['tags'] = $this->get_taxonomy_terms( $product, 'tag' );
|
||||||
|
break;
|
||||||
|
case 'images':
|
||||||
|
$base_data['images'] = $this->get_images( $product );
|
||||||
|
break;
|
||||||
|
case 'attributes':
|
||||||
|
$base_data['attributes'] = $this->get_attributes( $product );
|
||||||
|
break;
|
||||||
|
case 'default_attributes':
|
||||||
|
$base_data['default_attributes'] = $this->get_default_attributes( $product );
|
||||||
|
break;
|
||||||
|
case 'variations':
|
||||||
|
$base_data['variations'] = array();
|
||||||
|
break;
|
||||||
|
case 'grouped_products':
|
||||||
|
$base_data['grouped_products'] = array();
|
||||||
|
break;
|
||||||
|
case 'menu_order':
|
||||||
|
$base_data['menu_order'] = $product->get_menu_order( $context );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = array_merge(
|
||||||
|
$base_data,
|
||||||
|
$this->fetch_fields_using_getters( $product, $context, $fields )
|
||||||
);
|
);
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
|
|
|
@ -43,6 +43,20 @@ abstract class WC_REST_Controller extends WP_REST_Controller {
|
||||||
*/
|
*/
|
||||||
protected $rest_base = '';
|
protected $rest_base = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to cache computed return fields.
|
||||||
|
*
|
||||||
|
* @var null|array
|
||||||
|
*/
|
||||||
|
private $_fields = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to verify if cached fields are for correct request object.
|
||||||
|
*
|
||||||
|
* @var null|WP_REST_Request
|
||||||
|
*/
|
||||||
|
private $_request = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add the schema from additional fields to an schema array.
|
* Add the schema from additional fields to an schema array.
|
||||||
*
|
*
|
||||||
|
@ -513,10 +527,19 @@ abstract class WC_REST_Controller extends WP_REST_Controller {
|
||||||
* @return array Fields to be included in the response.
|
* @return array Fields to be included in the response.
|
||||||
*/
|
*/
|
||||||
public function get_fields_for_response( $request ) {
|
public function get_fields_for_response( $request ) {
|
||||||
|
// From xdebug profiling, this method could take upto 25% of request time in index calls.
|
||||||
|
// Cache it and make sure _fields was cached on current request object!
|
||||||
|
// TODO: Submit this caching behavior in core.
|
||||||
|
if ( isset( $this->_fields ) && is_array( $this->_fields ) && $request === $this->_request ) {
|
||||||
|
return $this->_fields;
|
||||||
|
}
|
||||||
|
$this->_request = $request;
|
||||||
|
|
||||||
$schema = $this->get_item_schema();
|
$schema = $this->get_item_schema();
|
||||||
$properties = isset( $schema['properties'] ) ? $schema['properties'] : array();
|
$properties = isset( $schema['properties'] ) ? $schema['properties'] : array();
|
||||||
|
|
||||||
$additional_fields = $this->get_additional_fields();
|
$additional_fields = $this->get_additional_fields();
|
||||||
|
|
||||||
foreach ( $additional_fields as $field_name => $field_options ) {
|
foreach ( $additional_fields as $field_name => $field_options ) {
|
||||||
// For back-compat, include any field with an empty schema
|
// For back-compat, include any field with an empty schema
|
||||||
// because it won't be present in $this->get_item_schema().
|
// because it won't be present in $this->get_item_schema().
|
||||||
|
@ -538,10 +561,12 @@ abstract class WC_REST_Controller extends WP_REST_Controller {
|
||||||
$fields = array_keys( $properties );
|
$fields = array_keys( $properties );
|
||||||
|
|
||||||
if ( ! isset( $request['_fields'] ) ) {
|
if ( ! isset( $request['_fields'] ) ) {
|
||||||
|
$this->_fields = $fields;
|
||||||
return $fields;
|
return $fields;
|
||||||
}
|
}
|
||||||
$requested_fields = wp_parse_list( $request['_fields'] );
|
$requested_fields = wp_parse_list( $request['_fields'] );
|
||||||
if ( 0 === count( $requested_fields ) ) {
|
if ( 0 === count( $requested_fields ) ) {
|
||||||
|
$this->_fields = $fields;
|
||||||
return $fields;
|
return $fields;
|
||||||
}
|
}
|
||||||
// Trim off outside whitespace from the comma delimited list.
|
// Trim off outside whitespace from the comma delimited list.
|
||||||
|
@ -551,7 +576,7 @@ abstract class WC_REST_Controller extends WP_REST_Controller {
|
||||||
$requested_fields[] = 'id';
|
$requested_fields[] = 'id';
|
||||||
}
|
}
|
||||||
// Return the list of all requested fields which appear in the schema.
|
// Return the list of all requested fields which appear in the schema.
|
||||||
return array_reduce(
|
$this->_fields = array_reduce(
|
||||||
$requested_fields,
|
$requested_fields,
|
||||||
function( $response_fields, $field ) use ( $fields ) {
|
function( $response_fields, $field ) use ( $fields ) {
|
||||||
if ( in_array( $field, $fields, true ) ) {
|
if ( in_array( $field, $fields, true ) ) {
|
||||||
|
@ -560,8 +585,8 @@ abstract class WC_REST_Controller extends WP_REST_Controller {
|
||||||
}
|
}
|
||||||
// Check for nested fields if $field is not a direct match.
|
// Check for nested fields if $field is not a direct match.
|
||||||
$nested_fields = explode( '.', $field );
|
$nested_fields = explode( '.', $field );
|
||||||
// A nested field is included so long as its top-level property is
|
// A nested field is included so long as its top-level property
|
||||||
// present in the schema.
|
// is present in the schema.
|
||||||
if ( in_array( $nested_fields[0], $fields, true ) ) {
|
if ( in_array( $nested_fields[0], $fields, true ) ) {
|
||||||
$response_fields[] = $field;
|
$response_fields[] = $field;
|
||||||
}
|
}
|
||||||
|
@ -569,5 +594,6 @@ abstract class WC_REST_Controller extends WP_REST_Controller {
|
||||||
},
|
},
|
||||||
array()
|
array()
|
||||||
);
|
);
|
||||||
|
return $this->_fields;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -479,6 +479,24 @@ abstract class WC_REST_CRUD_Controller extends WC_REST_Posts_Controller {
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get fields for an object if getter is defined.
|
||||||
|
*
|
||||||
|
* @param object $object Object we are fetching response for.
|
||||||
|
* @param string $context Context of the request. Can be `view` or `edit`.
|
||||||
|
* @param array $fields List of fields to fetch.
|
||||||
|
* @return array Data fetched from getters.
|
||||||
|
*/
|
||||||
|
public function fetch_fields_using_getters( $object, $context, $fields ) {
|
||||||
|
$data = array();
|
||||||
|
foreach ( $fields as $field ) {
|
||||||
|
if ( method_exists( $this, "api_get_$field" ) ) {
|
||||||
|
$data[ $field ] = $this->{"api_get_$field"}( $object, $context );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepare links for the request.
|
* Prepare links for the request.
|
||||||
*
|
*
|
||||||
|
|
|
@ -25,6 +25,25 @@ class WC_REST_Orders_Controller extends WC_REST_Orders_V2_Controller {
|
||||||
*/
|
*/
|
||||||
protected $namespace = 'wc/v3';
|
protected $namespace = 'wc/v3';
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Orders.
|
||||||
|
*
|
||||||
|
* @param array $query_args Query args.
|
||||||
|
*
|
||||||
|
* @return array Products.
|
||||||
|
*/
|
||||||
|
protected function get_objects( $query_args ) {
|
||||||
|
$query_args['paginate'] = true;
|
||||||
|
$results = wc_get_orders( $query_args );
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'objects' => $results->orders,
|
||||||
|
'total' => $results->total,
|
||||||
|
'pages' => $results->max_num_pages,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate coupons.
|
* Calculate coupons.
|
||||||
*
|
*
|
||||||
|
|
|
@ -217,6 +217,25 @@ class WC_REST_Products_Controller extends WC_REST_Products_V2_Controller {
|
||||||
return $args;
|
return $args;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get products.
|
||||||
|
*
|
||||||
|
* @param array $query_args Query args.
|
||||||
|
*
|
||||||
|
* @return array Products.
|
||||||
|
*/
|
||||||
|
protected function get_objects( $query_args ) {
|
||||||
|
$query_args['paginate'] = true;
|
||||||
|
$query_args['return'] = 'objects';
|
||||||
|
$results = wc_get_products( $query_args );
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'objects' => $results->products,
|
||||||
|
'total' => $results->total,
|
||||||
|
'pages' => $results->max_num_pages,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set product images.
|
* Set product images.
|
||||||
*
|
*
|
||||||
|
@ -1326,16 +1345,22 @@ class WC_REST_Products_Controller extends WC_REST_Products_V2_Controller {
|
||||||
* @param WC_Product $product Product instance.
|
* @param WC_Product $product Product instance.
|
||||||
* @param string $context Request context.
|
* @param string $context Request context.
|
||||||
* Options: 'view' and 'edit'.
|
* Options: 'view' and 'edit'.
|
||||||
|
* @param array $fields List of fields to fetch. If empty, then all fields will be returned.
|
||||||
|
* For backward compatibility, we pass this argument silently.
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
protected function get_product_data( $product, $context = 'view' ) {
|
protected function get_product_data( $product, $context = 'view' ) {
|
||||||
$data = parent::get_product_data( $product, $context );
|
$request = func_get_arg( 2 );
|
||||||
|
$data = parent::get_product_data( $product, $context, $request );
|
||||||
|
|
||||||
// Replace in_stock with stock_status.
|
// Replace in_stock with stock_status.
|
||||||
$pos = array_search( 'in_stock', array_keys( $data ), true );
|
$pos = array_search( 'in_stock', array_keys( $data ), true );
|
||||||
$array_section_1 = array_slice( $data, 0, $pos, true );
|
if ( false !== $pos ) {
|
||||||
$array_section_2 = array_slice( $data, $pos + 1, null, true );
|
$array_section_1 = array_slice( $data, 0, $pos, true );
|
||||||
|
$array_section_2 = array_slice( $data, $pos + 1, null, true );
|
||||||
|
$data = $array_section_1 + array( 'stock_status' => $product->get_stock_status( $context ) ) + $array_section_2;
|
||||||
|
}
|
||||||
|
|
||||||
return $array_section_1 + array( 'stock_status' => $product->get_stock_status( $context ) ) + $array_section_2;
|
return $data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2748,7 +2748,7 @@ if ( ! function_exists( 'woocommerce_form_field' ) ) {
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
$field = '<select name="' . esc_attr( $key ) . '" id="' . esc_attr( $args['id'] ) . '" class="country_to_state country_select ' . esc_attr( implode( ' ', $args['input_class'] ) ) . '" ' . implode( ' ', $custom_attributes ) . '><option value="default">' . esc_html__( 'Select a country / region…', 'woocommerce' ) . '</option>';
|
$field = '<select name="' . esc_attr( $key ) . '" id="' . esc_attr( $args['id'] ) . '" class="country_to_state country_select ' . esc_attr( implode( ' ', $args['input_class'] ) ) . '" ' . implode( ' ', $custom_attributes ) . ' data-placeholder="' . esc_attr( $args['placeholder'] ? $args['placeholder'] : esc_attr__( 'Select a country / region…', 'woocommerce' ) ) . '"><option value="">' . esc_html__( 'Select a country / region…', 'woocommerce' ) . '</option>';
|
||||||
|
|
||||||
foreach ( $countries as $ckey => $cvalue ) {
|
foreach ( $countries as $ckey => $cvalue ) {
|
||||||
$field .= '<option value="' . esc_attr( $ckey ) . '" ' . selected( $value, $ckey, false ) . '>' . esc_html( $cvalue ) . '</option>';
|
$field .= '<option value="' . esc_attr( $ckey ) . '" ' . selected( $value, $ckey, false ) . '>' . esc_html( $cvalue ) . '</option>';
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
## Added
|
## Added
|
||||||
- Merchant Order Status Filter tests
|
- Merchant Order Status Filter tests
|
||||||
|
- Merchant Order Refund tests
|
||||||
|
- Merchant Apply Coupon tests
|
||||||
|
|
||||||
## Fixed
|
## Fixed
|
||||||
|
|
||||||
|
|
|
@ -53,6 +53,8 @@ The functions to access the core tests are:
|
||||||
- `runProductSettingsTest` - Merchant can update product settings
|
- `runProductSettingsTest` - Merchant can update product settings
|
||||||
- `runTaxSettingsTest` - Merchant can update tax settings
|
- `runTaxSettingsTest` - Merchant can update tax settings
|
||||||
- `runOrderStatusFilterTest` - Merchant can filter orders by order status
|
- `runOrderStatusFilterTest` - Merchant can filter orders by order status
|
||||||
|
- `runOrderRefundTest` - Merchant can refund an order
|
||||||
|
- `runOrderApplyCouponTest` - Merchant can apply a coupon to an order
|
||||||
|
|
||||||
### Shopper
|
### Shopper
|
||||||
|
|
||||||
|
|
|
@ -35,9 +35,10 @@ const runTaskListTest = () => {
|
||||||
const taskListItems = await page.$$('.woocommerce-list__item-title');
|
const taskListItems = await page.$$('.woocommerce-list__item-title');
|
||||||
expect(taskListItems).toHaveLength(6);
|
expect(taskListItems).toHaveLength(6);
|
||||||
|
|
||||||
|
const [ setupTaskListItem ] = await page.$x( '//div[contains(text(),"Set up shipping")]' );
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
// Click on "Set up shipping" task to move to the next step
|
// Click on "Set up shipping" task to move to the next step
|
||||||
taskListItems[3].click(),
|
setupTaskListItem.click(),
|
||||||
|
|
||||||
// Wait for shipping setup section to load
|
// Wait for shipping setup section to load
|
||||||
page.waitForNavigation({waitUntil: 'networkidle0'}),
|
page.waitForNavigation({waitUntil: 'networkidle0'}),
|
||||||
|
|
|
@ -22,6 +22,8 @@ const runUpdateGeneralSettingsTest = require( './merchant/wp-admin-settings-gene
|
||||||
const runProductSettingsTest = require( './merchant/wp-admin-settings-product.test' );
|
const runProductSettingsTest = require( './merchant/wp-admin-settings-product.test' );
|
||||||
const runTaxSettingsTest = require( './merchant/wp-admin-settings-tax.test' );
|
const runTaxSettingsTest = require( './merchant/wp-admin-settings-tax.test' );
|
||||||
const runOrderStatusFiltersTest = require( './merchant/wp-admin-order-status-filters.test' );
|
const runOrderStatusFiltersTest = require( './merchant/wp-admin-order-status-filters.test' );
|
||||||
|
const runOrderRefundTest = require( './merchant/wp-admin-order-refund.test' );
|
||||||
|
const runOrderApplyCouponTest = require( './merchant/wp-admin-order-apply-coupon.test' );
|
||||||
|
|
||||||
const runSetupOnboardingTests = () => {
|
const runSetupOnboardingTests = () => {
|
||||||
runActivationTest();
|
runActivationTest();
|
||||||
|
@ -46,6 +48,8 @@ const runMerchantTests = () => {
|
||||||
runProductSettingsTest();
|
runProductSettingsTest();
|
||||||
runTaxSettingsTest();
|
runTaxSettingsTest();
|
||||||
runOrderStatusFiltersTest();
|
runOrderStatusFiltersTest();
|
||||||
|
runOrderRefundTest();
|
||||||
|
runOrderApplyCouponTest();
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
@ -67,5 +71,7 @@ module.exports = {
|
||||||
runProductSettingsTest,
|
runProductSettingsTest,
|
||||||
runTaxSettingsTest,
|
runTaxSettingsTest,
|
||||||
runOrderStatusFiltersTest,
|
runOrderStatusFiltersTest,
|
||||||
|
runOrderRefundTest,
|
||||||
|
runOrderApplyCouponTest,
|
||||||
runMerchantTests,
|
runMerchantTests,
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,84 @@
|
||||||
|
/* eslint-disable jest/no-export */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal dependencies
|
||||||
|
*/
|
||||||
|
const {
|
||||||
|
StoreOwnerFlow,
|
||||||
|
createSimpleProduct,
|
||||||
|
createSimpleOrder,
|
||||||
|
createCoupon,
|
||||||
|
uiUnblocked,
|
||||||
|
addProductToOrder,
|
||||||
|
} = require( '@woocommerce/e2e-utils' );
|
||||||
|
|
||||||
|
const config = require( 'config' );
|
||||||
|
const simpleProductName = config.get( 'products.simple.name' );
|
||||||
|
|
||||||
|
const couponDialogMessage = 'Enter a coupon code to apply. Discounts are applied to line totals, before taxes.';
|
||||||
|
|
||||||
|
let couponCode;
|
||||||
|
let orderId;
|
||||||
|
|
||||||
|
const runOrderApplyCouponTest = () => {
|
||||||
|
describe('WooCommerce Orders > Apply coupon', () => {
|
||||||
|
beforeAll(async () => {
|
||||||
|
await StoreOwnerFlow.login();
|
||||||
|
await Promise.all([
|
||||||
|
await createSimpleProduct(),
|
||||||
|
couponCode = await createCoupon(),
|
||||||
|
orderId = await createSimpleOrder('Pending payment', simpleProductName),
|
||||||
|
await addProductToOrder(orderId, simpleProductName),
|
||||||
|
|
||||||
|
// We need to remove any listeners on the `dialog` event otherwise we can't catch the dialog below
|
||||||
|
page.removeAllListeners('dialog'),
|
||||||
|
]);
|
||||||
|
} );
|
||||||
|
|
||||||
|
it('can apply a coupon', async () => {
|
||||||
|
const couponDialog = await expect(page).toDisplayDialog(async () => {
|
||||||
|
await expect(page).toClick('button.add-coupon');
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(couponDialog.message()).toMatch(couponDialogMessage);
|
||||||
|
|
||||||
|
// Accept the dialog with the coupon code
|
||||||
|
await couponDialog.accept(couponCode);
|
||||||
|
|
||||||
|
await uiUnblocked();
|
||||||
|
|
||||||
|
// Verify the coupon list is showing
|
||||||
|
await page.waitForSelector('.wc-used-coupons');
|
||||||
|
await expect(page).toMatchElement('.wc_coupon_list', { text: 'Coupon(s)' });
|
||||||
|
await expect(page).toMatchElement('.wc_coupon_list li.code.editable', { text: couponCode });
|
||||||
|
|
||||||
|
// Check that the coupon has been applied
|
||||||
|
await expect(page).toMatchElement('.wc-order-item-discount', { text: '5.00' });
|
||||||
|
await expect(page).toMatchElement('.line_cost > .view > .woocommerce-Price-amount', { text: '4.99' });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can remove a coupon', async () => {
|
||||||
|
// Make sure we have a coupon on the page to use
|
||||||
|
await page.waitForSelector('.wc-used-coupons');
|
||||||
|
await expect(page).toMatchElement('.wc_coupon_list li.code.editable', { text: couponCode });
|
||||||
|
|
||||||
|
// We need to use this here as `expect(page).toClick()` was unable to find the element
|
||||||
|
// See: https://github.com/puppeteer/puppeteer/issues/1769#issuecomment-637645219
|
||||||
|
page.$eval('a.remove-coupon', elem => elem.click());
|
||||||
|
|
||||||
|
await uiUnblocked();
|
||||||
|
|
||||||
|
// Verify the coupon pricing has been removed
|
||||||
|
await expect(page).not.toMatchElement('.wc_coupon_list li.code.editable', { text: couponCode });
|
||||||
|
await expect(page).not.toMatchElement('.wc-order-item-discount', { text: '5.00' });
|
||||||
|
await expect(page).not.toMatchElement('.line-cost .view .woocommerce-Price-amount', { text: '4.99' });
|
||||||
|
|
||||||
|
// Verify the original price is the order total
|
||||||
|
await expect(page).toMatchElement('.line_cost > .view > .woocommerce-Price-amount', { text: '9.99' });
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = runOrderApplyCouponTest;
|
|
@ -0,0 +1,100 @@
|
||||||
|
/* eslint-disable jest/no-export, jest/no-disabled-tests, */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal dependencies
|
||||||
|
*/
|
||||||
|
const {
|
||||||
|
StoreOwnerFlow,
|
||||||
|
createSimpleProduct,
|
||||||
|
createSimpleOrder,
|
||||||
|
verifyCheckboxIsSet,
|
||||||
|
verifyValueOfInputField,
|
||||||
|
uiUnblocked,
|
||||||
|
addProductToOrder,
|
||||||
|
} = require( '@woocommerce/e2e-utils' );
|
||||||
|
|
||||||
|
const config = require( 'config' );
|
||||||
|
const simpleProductName = config.get( 'products.simple.name' );
|
||||||
|
|
||||||
|
let orderId;
|
||||||
|
let currencySymbol;
|
||||||
|
|
||||||
|
const runRefundOrderTest = () => {
|
||||||
|
describe('WooCommerce Orders > Refund an order', () => {
|
||||||
|
beforeAll(async () => {
|
||||||
|
await StoreOwnerFlow.login();
|
||||||
|
await createSimpleProduct();
|
||||||
|
orderId = await createSimpleOrder();
|
||||||
|
await addProductToOrder(orderId, simpleProductName);
|
||||||
|
|
||||||
|
// Get the currency symbol for the store's selected currency
|
||||||
|
await page.waitForSelector('.woocommerce-Price-currencySymbol');
|
||||||
|
let currencyElement = await page.$('.woocommerce-Price-currencySymbol');
|
||||||
|
currencySymbol = await page.evaluate(el => el.textContent, currencyElement);
|
||||||
|
|
||||||
|
// Update order status to `Completed` so we can issue a refund
|
||||||
|
await StoreOwnerFlow.updateOrderStatus(orderId, 'Completed');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can issue a refund by quantity', async () => {
|
||||||
|
// Click the Refund button
|
||||||
|
await expect(page).toClick('button.refund-items');
|
||||||
|
|
||||||
|
// Verify the refund section shows
|
||||||
|
await page.waitForSelector('div.wc-order-refund-items', { visible: true });
|
||||||
|
await verifyCheckboxIsSet('#restock_refunded_items');
|
||||||
|
|
||||||
|
// Initiate a refund
|
||||||
|
await expect(page).toFill('.refund_order_item_qty', '1');
|
||||||
|
await expect(page).toFill('#refund_reason', 'No longer wanted');
|
||||||
|
|
||||||
|
await Promise.all([
|
||||||
|
verifyValueOfInputField('.refund_line_total', '9.99'),
|
||||||
|
verifyValueOfInputField('#refund_amount', '9.99'),
|
||||||
|
expect(page).toMatchElement('.do-manual-refund', { text: `Refund ${currencySymbol}9.99 manually` }),
|
||||||
|
]);
|
||||||
|
|
||||||
|
await expect(page).toClick('.do-manual-refund');
|
||||||
|
|
||||||
|
await uiUnblocked();
|
||||||
|
|
||||||
|
await Promise.all([
|
||||||
|
// Verify the product line item shows the refunded quantity and amount
|
||||||
|
expect(page).toMatchElement('.quantity .refunded', { text: '-1' }),
|
||||||
|
expect(page).toMatchElement('.line_cost .refunded', { text: `-${currencySymbol}9.99` }),
|
||||||
|
|
||||||
|
// Verify the refund shows in the list with the amount
|
||||||
|
expect(page).toMatchElement('.refund .description', { text: 'No longer wanted' }),
|
||||||
|
expect(page).toMatchElement('.refund > .line_cost', { text: `-${currencySymbol}9.99` }),
|
||||||
|
|
||||||
|
// Verify system note was added
|
||||||
|
expect(page).toMatchElement('.system-note', { text: 'Order status changed from Completed to Refunded.' }),
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can delete an issued refund', async () => {
|
||||||
|
// We need to use this here as `expect(page).toClick()` was unable to find the element
|
||||||
|
// See: https://github.com/puppeteer/puppeteer/issues/1769#issuecomment-637645219
|
||||||
|
page.$eval('a.delete_refund', elem => elem.click());
|
||||||
|
|
||||||
|
await uiUnblocked();
|
||||||
|
|
||||||
|
// Verify the refunded row item is no longer showing
|
||||||
|
await page.waitForSelector('tr.refund', { visible: false });
|
||||||
|
|
||||||
|
await Promise.all([
|
||||||
|
// Verify the product line item shows the refunded quantity and amount
|
||||||
|
expect(page).not.toMatchElement('.quantity .refunded', { text: '-1' }),
|
||||||
|
expect(page).not.toMatchElement('.line_cost .refunded', { text: `-${currencySymbol}9.99` }),
|
||||||
|
|
||||||
|
// Verify the refund shows in the list with the amount
|
||||||
|
expect(page).not.toMatchElement('.refund .description', { text: 'No longer wanted' }),
|
||||||
|
expect(page).not.toMatchElement('.refund > .line_cost', { text: `-${currencySymbol}9.99` }),
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = runRefundOrderTest;
|
|
@ -1,5 +1,9 @@
|
||||||
# Unreleased
|
# Unreleased
|
||||||
|
|
||||||
|
## Added
|
||||||
|
|
||||||
|
- Insert a 12 hour delay in using new docker image tags
|
||||||
|
|
||||||
## Fixed
|
## Fixed
|
||||||
|
|
||||||
- Remove redundant `puppeteer` dependency
|
- Remove redundant `puppeteer` dependency
|
||||||
|
|
|
@ -36,12 +36,22 @@ async function fetchLatestTagFromPage( image, nameSearch, page ) {
|
||||||
if ( ! data.count ) {
|
if ( ! data.count ) {
|
||||||
reject( "No image '" + image + '" found' );
|
reject( "No image '" + image + '" found' );
|
||||||
} else {
|
} else {
|
||||||
|
// Implement a 12 hour delay on pulling newly released docker tags.
|
||||||
|
const delayMilliseconds = 12 * 3600 * 1000;
|
||||||
|
const currentTime = Date.now();
|
||||||
let latestTag = null;
|
let latestTag = null;
|
||||||
|
let lastUpdated = null;
|
||||||
for ( let tag of data.results ) {
|
for ( let tag of data.results ) {
|
||||||
tag.semver = tag.name.match( /^\d+\.\d+(.\d+)*$/ );
|
tag.semver = tag.name.match( /^\d+\.\d+(.\d+)*$/ );
|
||||||
if ( ! tag.semver ) {
|
if ( ! tag.semver ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lastUpdated = Date.parse( tag.last_updated );
|
||||||
|
if ( currentTime - lastUpdated < delayMilliseconds ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
tag.semver = semver.coerce( tag.semver[0] );
|
tag.semver = semver.coerce( tag.semver[0] );
|
||||||
if ( ! latestTag || semver.gt( tag.semver, latestTag.semver ) ) {
|
if ( ! latestTag || semver.gt( tag.semver, latestTag.semver ) ) {
|
||||||
latestTag = tag;
|
latestTag = tag;
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
/*
|
||||||
|
* Internal dependencies
|
||||||
|
*/
|
||||||
|
const { runOrderApplyCouponTest } = require( '@woocommerce/e2e-core-tests' );
|
||||||
|
|
||||||
|
runOrderApplyCouponTest();
|
|
@ -0,0 +1,6 @@
|
||||||
|
/*
|
||||||
|
* Internal dependencies
|
||||||
|
*/
|
||||||
|
const { runOrderRefundTest } = require( '@woocommerce/e2e-core-tests' );
|
||||||
|
|
||||||
|
runOrderRefundTest();
|
|
@ -9,6 +9,12 @@
|
||||||
- `clickFilter()` util helper method that clicks on a list page filter
|
- `clickFilter()` util helper method that clicks on a list page filter
|
||||||
- `moveAllItemsToTrash()` util helper method that checks every item in a list page and moves them to the trash
|
- `moveAllItemsToTrash()` util helper method that checks every item in a list page and moves them to the trash
|
||||||
- `createSimpleOrder( status )` component which accepts an order status string and creates a basic order with that status
|
- `createSimpleOrder( status )` component which accepts an order status string and creates a basic order with that status
|
||||||
|
- `addProductToOrder( orderId, productName )` component which adds the provided productName to the passed in orderId
|
||||||
|
- `createCoupon( couponAmount )` component which accepts a coupon amount string (it defaults to 5) and creates a basic coupon. Returns the generated coupon code.
|
||||||
|
|
||||||
|
## Changes
|
||||||
|
|
||||||
|
- `createSimpleOrder( status )` returns the ID of the order that was created
|
||||||
|
|
||||||
# 0.1.1
|
# 0.1.1
|
||||||
|
|
||||||
|
|
|
@ -38,20 +38,22 @@ describe( 'Cart page', () => {
|
||||||
|
|
||||||
### Merchant `StoreOwnerFlow`
|
### Merchant `StoreOwnerFlow`
|
||||||
|
|
||||||
| Function | Description |
|
| Function | Parameters | Description |
|
||||||
|----------|-------------|
|
|----------|-------------|------------|
|
||||||
| `login` | Log in as merchant |
|
| `login` | | Log in as merchant |
|
||||||
| `logout` | log out of merchant account |
|
| `logout` | | Log out of merchant account |
|
||||||
| `openAllOrdersView` | Go to the orders listing |
|
| `openAllOrdersView` | | Go to the orders listing |
|
||||||
| `openDashboard` | Go to the WordPress dashboard |
|
| `openDashboard` | | Go to the WordPress dashboard |
|
||||||
| `openNewCoupon` | Go to the new coupon editor |
|
| `openNewCoupon` | | Go to the new coupon editor |
|
||||||
| `openNewOrder` | Go to the new order editor |
|
| `openNewOrder` | | Go to the new order editor |
|
||||||
| `openNewProduct` | Go to the new product editor |
|
| `openNewProduct` | | Go to the new product editor |
|
||||||
| `openPermalinkSettings` | Go to Settings -> Permalinks |
|
| `openPermalinkSettings` | | Go to Settings -> Permalinks |
|
||||||
| `openPlugins` | Go to the Plugins screen |
|
| `openPlugins` | | Go to the Plugins screen |
|
||||||
| `openSettings` | Go to WooCommerce -> Settings |
|
| `openSettings` | | Go to WooCommerce -> Settings |
|
||||||
| `runSetupWizard` | Open the onboarding profiler |
|
| `runSetupWizard` | | Open the onboarding profiler |
|
||||||
|----------|-------------|
|
| `goToOrder` | `orderId` | Go to view a single order |
|
||||||
|
| `updateOrderStatus` | `orderId, status` | Update the status of an order |
|
||||||
|
|----------|-------------|-------------|
|
||||||
|
|
||||||
### Shopper `CustomerFlow`
|
### Shopper `CustomerFlow`
|
||||||
|
|
||||||
|
|
|
@ -368,6 +368,61 @@ const createSimpleOrder = async ( orderStatus = 'Pending payment' ) => {
|
||||||
|
|
||||||
// Verify
|
// Verify
|
||||||
await expect( page ).toMatchElement( '#message', { text: 'Order updated.' } );
|
await expect( page ).toMatchElement( '#message', { text: 'Order updated.' } );
|
||||||
|
|
||||||
|
const variablePostId = await page.$( '#post_ID' );
|
||||||
|
let variablePostIdValue = ( await ( await variablePostId.getProperty( 'value' ) ).jsonValue() );
|
||||||
|
return variablePostIdValue;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a product to an order in the StoreOwnerFlow.
|
||||||
|
*
|
||||||
|
* @param orderId ID of the order to add the product to.
|
||||||
|
* @param productName Name of the product being added to the order.
|
||||||
|
*/
|
||||||
|
const addProductToOrder = async ( orderId, productName ) => {
|
||||||
|
await StoreOwnerFlow.goToOrder( orderId );
|
||||||
|
|
||||||
|
// Add a product to the order
|
||||||
|
await expect( page ).toClick( 'button.add-line-item' );
|
||||||
|
await expect( page ).toClick( 'button.add-order-item' );
|
||||||
|
await page.waitForSelector( '.wc-backbone-modal-header' );
|
||||||
|
await expect( page ).toClick( '.wc-backbone-modal-content .wc-product-search' );
|
||||||
|
await expect( page ).toFill( '#wc-backbone-modal-dialog + .select2-container .select2-search__field', productName );
|
||||||
|
await expect( page ).toClick( 'li[aria-selected="true"]' );
|
||||||
|
await page.click( '.wc-backbone-modal-content #btn-ok' );
|
||||||
|
|
||||||
|
await uiUnblocked();
|
||||||
|
|
||||||
|
// Verify the product we added shows as a line item now
|
||||||
|
await expect( page ).toMatchElement( '.wc-order-item-name', { text: productName } );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a basic coupon with the provided coupon amount. Returns the coupon code.
|
||||||
|
*
|
||||||
|
* @param couponAmount Amount to be applied. Defaults to 5.
|
||||||
|
*/
|
||||||
|
const createCoupon = async ( couponAmount = '5' ) => {
|
||||||
|
await StoreOwnerFlow.openNewCoupon();
|
||||||
|
|
||||||
|
// Fill in coupon code
|
||||||
|
let couponCode = 'code-' + new Date().getTime().toString();
|
||||||
|
await expect(page).toFill( '#title', couponCode );
|
||||||
|
|
||||||
|
// Set general coupon data
|
||||||
|
await clickTab( 'General' );
|
||||||
|
await expect(page).toSelect( '#discount_type', 'Fixed cart discount' );
|
||||||
|
await expect(page).toFill( '#coupon_amount', couponAmount );
|
||||||
|
|
||||||
|
// Publish coupon
|
||||||
|
await expect( page ).toClick( '#publish' );
|
||||||
|
await page.waitForSelector( '.updated.notice' );
|
||||||
|
|
||||||
|
// Verify
|
||||||
|
await expect( page ).toMatchElement( '.updated.notice', { text: 'Coupon updated.' } );
|
||||||
|
|
||||||
|
return couponCode;
|
||||||
};
|
};
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
@ -376,4 +431,6 @@ export {
|
||||||
createVariableProduct,
|
createVariableProduct,
|
||||||
createSimpleOrder,
|
createSimpleOrder,
|
||||||
verifyAndPublish,
|
verifyAndPublish,
|
||||||
|
addProductToOrder,
|
||||||
|
createCoupon,
|
||||||
};
|
};
|
||||||
|
|
|
@ -25,6 +25,7 @@ const WP_ADMIN_NEW_ORDER = baseUrl + 'wp-admin/post-new.php?post_type=shop_order
|
||||||
const WP_ADMIN_NEW_PRODUCT = baseUrl + 'wp-admin/post-new.php?post_type=product';
|
const WP_ADMIN_NEW_PRODUCT = baseUrl + 'wp-admin/post-new.php?post_type=product';
|
||||||
const WP_ADMIN_WC_SETTINGS = baseUrl + 'wp-admin/admin.php?page=wc-settings&tab=';
|
const WP_ADMIN_WC_SETTINGS = baseUrl + 'wp-admin/admin.php?page=wc-settings&tab=';
|
||||||
const WP_ADMIN_PERMALINK_SETTINGS = baseUrl + 'wp-admin/options-permalink.php';
|
const WP_ADMIN_PERMALINK_SETTINGS = baseUrl + 'wp-admin/options-permalink.php';
|
||||||
|
const WP_ADMIN_SINGLE_CPT_VIEW = ( postId ) => baseUrl + `wp-admin/post.php?post=${ postId }&action=edit`;
|
||||||
|
|
||||||
const SHOP_PAGE = baseUrl + 'shop';
|
const SHOP_PAGE = baseUrl + 'shop';
|
||||||
const SHOP_PRODUCT_PAGE = baseUrl + '?p=';
|
const SHOP_PRODUCT_PAGE = baseUrl + '?p=';
|
||||||
|
@ -310,6 +311,23 @@ const StoreOwnerFlow = {
|
||||||
waitUntil: 'networkidle0',
|
waitUntil: 'networkidle0',
|
||||||
} );
|
} );
|
||||||
},
|
},
|
||||||
|
|
||||||
|
goToOrder: async ( orderId ) => {
|
||||||
|
await page.goto( WP_ADMIN_SINGLE_CPT_VIEW( orderId ), {
|
||||||
|
waitUntil: 'networkidle0',
|
||||||
|
} );
|
||||||
|
},
|
||||||
|
|
||||||
|
updateOrderStatus: async ( orderId, status ) => {
|
||||||
|
await page.goto( WP_ADMIN_SINGLE_CPT_VIEW( orderId ), {
|
||||||
|
waitUntil: 'networkidle0',
|
||||||
|
} );
|
||||||
|
await expect( page ).toSelect( '#order_status', status );
|
||||||
|
await page.waitFor( 2000 );
|
||||||
|
await expect( page ).toClick( 'button.save_order' );
|
||||||
|
await page.waitForSelector( '#message' );
|
||||||
|
await expect( page ).toMatchElement( '#message', { text: 'Order updated.' } );
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export { CustomerFlow, StoreOwnerFlow };
|
export { CustomerFlow, StoreOwnerFlow };
|
||||||
|
|
Loading…
Reference in New Issue