mirror of
https://github.com/wp-graphql/wp-graphql-woocommerce.git
synced 2026-08-14 12:53:44 +02:00
fix: product connection resolution refactored to better work with the ProductQuery class (#880)
* fix: product connection resolution refactored to better work with the ProductQuery class * chore: Linter and PHPStan compliance met * devops: New product connection tests implemented and passing * fix: products connection pricing filters fixed * devops: CartTransactionQueueCest skipped until failing PHP version removed from CI matrix
This commit is contained in:
+2
-2
@@ -26,8 +26,8 @@
|
||||
},
|
||||
"require-dev": {
|
||||
"axepress/wp-graphql-cs": "^2.0.0-beta",
|
||||
"axepress/wp-graphql-stubs": "~1.16.0",
|
||||
"php-stubs/woocommerce-stubs": "7.9.0",
|
||||
"axepress/wp-graphql-stubs": "^1.27.1",
|
||||
"php-stubs/woocommerce-stubs": "9.1.0",
|
||||
"phpstan/extension-installer": "^1.3",
|
||||
"phpstan/phpdoc-parser": "^1.22.0",
|
||||
"phpstan/phpstan": "^1.10",
|
||||
|
||||
Generated
+64
-62
@@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "0a63256d1a0b55f5be349b050cf48c59",
|
||||
"content-hash": "fe319feb8c0b2d7478695d8dce39b020",
|
||||
"packages": [
|
||||
{
|
||||
"name": "firebase/php-jwt",
|
||||
@@ -185,16 +185,16 @@
|
||||
},
|
||||
{
|
||||
"name": "axepress/wp-graphql-stubs",
|
||||
"version": "v1.16.0+repack.1",
|
||||
"version": "v1.27.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/AxeWP/wp-graphql-stubs.git",
|
||||
"reference": "47ce4c7e0c715bea84bc84b675e274b94a8c22f4"
|
||||
"reference": "84ef51264b142d92c0ac9aa39edf2cce5f0ac3af"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/AxeWP/wp-graphql-stubs/zipball/47ce4c7e0c715bea84bc84b675e274b94a8c22f4",
|
||||
"reference": "47ce4c7e0c715bea84bc84b675e274b94a8c22f4",
|
||||
"url": "https://api.github.com/repos/AxeWP/wp-graphql-stubs/zipball/84ef51264b142d92c0ac9aa39edf2cce5f0ac3af",
|
||||
"reference": "84ef51264b142d92c0ac9aa39edf2cce5f0ac3af",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -225,7 +225,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/AxeWP/wp-graphql-stubs/issues",
|
||||
"source": "https://github.com/AxeWP/wp-graphql-stubs/tree/v1.16.0+repack.1"
|
||||
"source": "https://github.com/AxeWP/wp-graphql-stubs/tree/v1.27.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -233,7 +233,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2023-10-01T17:13:28+00:00"
|
||||
"time": "2024-07-04T12:37:29+00:00"
|
||||
},
|
||||
{
|
||||
"name": "dealerdirect/phpcodesniffer-composer-installer",
|
||||
@@ -315,16 +315,16 @@
|
||||
},
|
||||
{
|
||||
"name": "php-stubs/woocommerce-stubs",
|
||||
"version": "v7.9.0",
|
||||
"version": "v9.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-stubs/woocommerce-stubs.git",
|
||||
"reference": "3a2f522e29451490c357af550227795d2b0fc55a"
|
||||
"reference": "2c95c633362d1f4f531f69e5db63bb19399d8b58"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-stubs/woocommerce-stubs/zipball/3a2f522e29451490c357af550227795d2b0fc55a",
|
||||
"reference": "3a2f522e29451490c357af550227795d2b0fc55a",
|
||||
"url": "https://api.github.com/repos/php-stubs/woocommerce-stubs/zipball/2c95c633362d1f4f531f69e5db63bb19399d8b58",
|
||||
"reference": "2c95c633362d1f4f531f69e5db63bb19399d8b58",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -353,33 +353,34 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/php-stubs/woocommerce-stubs/issues",
|
||||
"source": "https://github.com/php-stubs/woocommerce-stubs/tree/v7.9.0"
|
||||
"source": "https://github.com/php-stubs/woocommerce-stubs/tree/v9.1.0"
|
||||
},
|
||||
"time": "2023-07-17T22:41:38+00:00"
|
||||
"time": "2024-07-11T10:55:02+00:00"
|
||||
},
|
||||
{
|
||||
"name": "php-stubs/wordpress-stubs",
|
||||
"version": "v6.5.3",
|
||||
"version": "v6.6.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-stubs/wordpress-stubs.git",
|
||||
"reference": "e611a83292d02055a25f83291a98fadd0c21e092"
|
||||
"reference": "86e8753e89d59849276dcdd91b9a7dd78bb4abe2"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-stubs/wordpress-stubs/zipball/e611a83292d02055a25f83291a98fadd0c21e092",
|
||||
"reference": "e611a83292d02055a25f83291a98fadd0c21e092",
|
||||
"url": "https://api.github.com/repos/php-stubs/wordpress-stubs/zipball/86e8753e89d59849276dcdd91b9a7dd78bb4abe2",
|
||||
"reference": "86e8753e89d59849276dcdd91b9a7dd78bb4abe2",
|
||||
"shasum": ""
|
||||
},
|
||||
"require-dev": {
|
||||
"dealerdirect/phpcodesniffer-composer-installer": "^1.0",
|
||||
"nikic/php-parser": "^4.13",
|
||||
"php": "^7.4 || ~8.0.0",
|
||||
"php": "^7.4 || ^8.0",
|
||||
"php-stubs/generator": "^0.8.3",
|
||||
"phpdocumentor/reflection-docblock": "5.3",
|
||||
"phpdocumentor/reflection-docblock": "^5.4.1",
|
||||
"phpstan/phpstan": "^1.10.49",
|
||||
"phpunit/phpunit": "^9.5",
|
||||
"szepeviktor/phpcs-psr-12-neutron-hybrid-ruleset": "^0.11"
|
||||
"szepeviktor/phpcs-psr-12-neutron-hybrid-ruleset": "^1.0",
|
||||
"wp-coding-standards/wpcs": "3.1.0 as 2.3.0"
|
||||
},
|
||||
"suggest": {
|
||||
"paragonie/sodium_compat": "Pure PHP implementation of libsodium",
|
||||
@@ -400,9 +401,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/php-stubs/wordpress-stubs/issues",
|
||||
"source": "https://github.com/php-stubs/wordpress-stubs/tree/v6.5.3"
|
||||
"source": "https://github.com/php-stubs/wordpress-stubs/tree/v6.6.0"
|
||||
},
|
||||
"time": "2024-05-08T02:12:31+00:00"
|
||||
"time": "2024-07-17T08:50:38+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpcompatibility/php-compatibility",
|
||||
@@ -776,16 +777,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpstan/extension-installer",
|
||||
"version": "1.3.1",
|
||||
"version": "1.4.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpstan/extension-installer.git",
|
||||
"reference": "f45734bfb9984c6c56c4486b71230355f066a58a"
|
||||
"reference": "f6b87faf9fc7978eab2f7919a8760bc9f58f9203"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpstan/extension-installer/zipball/f45734bfb9984c6c56c4486b71230355f066a58a",
|
||||
"reference": "f45734bfb9984c6c56c4486b71230355f066a58a",
|
||||
"url": "https://api.github.com/repos/phpstan/extension-installer/zipball/f6b87faf9fc7978eab2f7919a8760bc9f58f9203",
|
||||
"reference": "f6b87faf9fc7978eab2f7919a8760bc9f58f9203",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -814,22 +815,22 @@
|
||||
"description": "Composer plugin for automatic installation of PHPStan extensions",
|
||||
"support": {
|
||||
"issues": "https://github.com/phpstan/extension-installer/issues",
|
||||
"source": "https://github.com/phpstan/extension-installer/tree/1.3.1"
|
||||
"source": "https://github.com/phpstan/extension-installer/tree/1.4.1"
|
||||
},
|
||||
"time": "2023-05-24T08:59:17+00:00"
|
||||
"time": "2024-06-10T08:20:49+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpdoc-parser",
|
||||
"version": "1.29.0",
|
||||
"version": "1.29.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpstan/phpdoc-parser.git",
|
||||
"reference": "536889f2b340489d328f5ffb7b02bb6b183ddedc"
|
||||
"reference": "fcaefacf2d5c417e928405b71b400d4ce10daaf4"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/536889f2b340489d328f5ffb7b02bb6b183ddedc",
|
||||
"reference": "536889f2b340489d328f5ffb7b02bb6b183ddedc",
|
||||
"url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/fcaefacf2d5c417e928405b71b400d4ce10daaf4",
|
||||
"reference": "fcaefacf2d5c417e928405b71b400d4ce10daaf4",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -861,22 +862,22 @@
|
||||
"description": "PHPDoc parser with support for nullable, intersection and generic types",
|
||||
"support": {
|
||||
"issues": "https://github.com/phpstan/phpdoc-parser/issues",
|
||||
"source": "https://github.com/phpstan/phpdoc-parser/tree/1.29.0"
|
||||
"source": "https://github.com/phpstan/phpdoc-parser/tree/1.29.1"
|
||||
},
|
||||
"time": "2024-05-06T12:04:23+00:00"
|
||||
"time": "2024-05-31T08:52:43+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpstan",
|
||||
"version": "1.11.1",
|
||||
"version": "1.11.8",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpstan/phpstan.git",
|
||||
"reference": "e524358f930e41a2b4cca1320e3b04fc26b39e0b"
|
||||
"reference": "6adbd118e6c0515dd2f36b06cde1d6da40f1b8ec"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/e524358f930e41a2b4cca1320e3b04fc26b39e0b",
|
||||
"reference": "e524358f930e41a2b4cca1320e3b04fc26b39e0b",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/6adbd118e6c0515dd2f36b06cde1d6da40f1b8ec",
|
||||
"reference": "6adbd118e6c0515dd2f36b06cde1d6da40f1b8ec",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -921,20 +922,20 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2024-05-15T08:00:59+00:00"
|
||||
"time": "2024-07-24T07:01:22+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sirbrillig/phpcs-variable-analysis",
|
||||
"version": "v2.11.18",
|
||||
"version": "v2.11.19",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sirbrillig/phpcs-variable-analysis.git",
|
||||
"reference": "ca242a0b7309e0f9d1f73b236e04ecf4ca3248d0"
|
||||
"reference": "bc8d7e30e2005bce5c59018b7cdb08e9fb45c0d1"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sirbrillig/phpcs-variable-analysis/zipball/ca242a0b7309e0f9d1f73b236e04ecf4ca3248d0",
|
||||
"reference": "ca242a0b7309e0f9d1f73b236e04ecf4ca3248d0",
|
||||
"url": "https://api.github.com/repos/sirbrillig/phpcs-variable-analysis/zipball/bc8d7e30e2005bce5c59018b7cdb08e9fb45c0d1",
|
||||
"reference": "bc8d7e30e2005bce5c59018b7cdb08e9fb45c0d1",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -979,7 +980,7 @@
|
||||
"source": "https://github.com/sirbrillig/phpcs-variable-analysis",
|
||||
"wiki": "https://github.com/sirbrillig/phpcs-variable-analysis/wiki"
|
||||
},
|
||||
"time": "2024-04-13T16:42:46+00:00"
|
||||
"time": "2024-06-26T20:08:34+00:00"
|
||||
},
|
||||
{
|
||||
"name": "slevomat/coding-standard",
|
||||
@@ -1048,16 +1049,16 @@
|
||||
},
|
||||
{
|
||||
"name": "squizlabs/php_codesniffer",
|
||||
"version": "3.10.0",
|
||||
"version": "3.10.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git",
|
||||
"reference": "57e09801c2fbae2d257b8b75bebb3deeb7e9deb2"
|
||||
"reference": "86e5f5dd9a840c46810ebe5ff1885581c42a3017"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/57e09801c2fbae2d257b8b75bebb3deeb7e9deb2",
|
||||
"reference": "57e09801c2fbae2d257b8b75bebb3deeb7e9deb2",
|
||||
"url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/86e5f5dd9a840c46810ebe5ff1885581c42a3017",
|
||||
"reference": "86e5f5dd9a840c46810ebe5ff1885581c42a3017",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1124,20 +1125,20 @@
|
||||
"type": "open_collective"
|
||||
}
|
||||
],
|
||||
"time": "2024-05-20T08:11:32+00:00"
|
||||
"time": "2024-07-21T23:26:44+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php73",
|
||||
"version": "v1.29.0",
|
||||
"version": "v1.30.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-php73.git",
|
||||
"reference": "21bd091060673a1177ae842c0ef8fe30893114d2"
|
||||
"reference": "ec444d3f3f6505bb28d11afa41e75faadebc10a1"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/21bd091060673a1177ae842c0ef8fe30893114d2",
|
||||
"reference": "21bd091060673a1177ae842c0ef8fe30893114d2",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/ec444d3f3f6505bb28d11afa41e75faadebc10a1",
|
||||
"reference": "ec444d3f3f6505bb28d11afa41e75faadebc10a1",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1184,7 +1185,7 @@
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-php73/tree/v1.29.0"
|
||||
"source": "https://github.com/symfony/polyfill-php73/tree/v1.30.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -1200,20 +1201,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-01-29T20:11:03+00:00"
|
||||
"time": "2024-05-31T15:07:36+00:00"
|
||||
},
|
||||
{
|
||||
"name": "szepeviktor/phpstan-wordpress",
|
||||
"version": "v1.3.4",
|
||||
"version": "v1.3.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/szepeviktor/phpstan-wordpress.git",
|
||||
"reference": "891d0767855a32c886a439efae090408cc1fa156"
|
||||
"reference": "7f8cfe992faa96b6a33bbd75c7bace98864161e7"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/szepeviktor/phpstan-wordpress/zipball/891d0767855a32c886a439efae090408cc1fa156",
|
||||
"reference": "891d0767855a32c886a439efae090408cc1fa156",
|
||||
"url": "https://api.github.com/repos/szepeviktor/phpstan-wordpress/zipball/7f8cfe992faa96b6a33bbd75c7bace98864161e7",
|
||||
"reference": "7f8cfe992faa96b6a33bbd75c7bace98864161e7",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1228,7 +1229,8 @@
|
||||
"php-parallel-lint/php-parallel-lint": "^1.1",
|
||||
"phpstan/phpstan-strict-rules": "^1.2",
|
||||
"phpunit/phpunit": "^8.0 || ^9.0",
|
||||
"szepeviktor/phpcs-psr-12-neutron-hybrid-ruleset": "^0.8"
|
||||
"szepeviktor/phpcs-psr-12-neutron-hybrid-ruleset": "^1.0",
|
||||
"wp-coding-standards/wpcs": "3.1.0 as 2.3.0"
|
||||
},
|
||||
"suggest": {
|
||||
"swissspidy/phpstan-no-private": "Detect usage of internal core functions, classes and methods"
|
||||
@@ -1260,9 +1262,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/szepeviktor/phpstan-wordpress/issues",
|
||||
"source": "https://github.com/szepeviktor/phpstan-wordpress/tree/v1.3.4"
|
||||
"source": "https://github.com/szepeviktor/phpstan-wordpress/tree/v1.3.5"
|
||||
},
|
||||
"time": "2024-03-21T16:32:59+00:00"
|
||||
"time": "2024-06-28T22:27:19+00:00"
|
||||
},
|
||||
{
|
||||
"name": "wp-coding-standards/wpcs",
|
||||
|
||||
@@ -201,7 +201,7 @@ class Customers {
|
||||
* @return array
|
||||
*/
|
||||
public static function upgrade_models( $connection, $resolver ) {
|
||||
if ( 'customers' === $resolver->get_info()->fieldName ) { // @phpstan-ignore-line
|
||||
if ( 'customers' === $resolver->get_info()->fieldName ) {
|
||||
$nodes = [];
|
||||
$edges = [];
|
||||
foreach ( $connection['nodes'] as $node ) {
|
||||
|
||||
@@ -99,7 +99,7 @@ class Orders {
|
||||
* @param \WPGraphQL\WooCommerce\Data\Connection\Order_Connection_Resolver $resolver Connection resolver.
|
||||
* @param \WC_Customer $customer Customer object of querying user.
|
||||
*
|
||||
* @return array
|
||||
* @return array|\GraphQL\Deferred
|
||||
*/
|
||||
private static function get_customer_order_connection( $resolver, $customer ) {
|
||||
// If not "billing email" or "ID" set bail early by returning an empty connection.
|
||||
@@ -129,7 +129,7 @@ class Orders {
|
||||
* @param \WPGraphQL\WooCommerce\Data\Connection\Order_Connection_Resolver $resolver Connection resolver.
|
||||
* @param \WC_Customer $customer Customer object of querying user.
|
||||
*
|
||||
* @return array
|
||||
* @return array|\GraphQL\Deferred
|
||||
*/
|
||||
private static function get_customer_refund_connection( $resolver, $customer ) {
|
||||
$empty_results = [
|
||||
|
||||
@@ -64,10 +64,10 @@ class Cart_Item_Connection_Resolver extends AbstractConnectionResolver {
|
||||
/**
|
||||
* Filter the $query_args to allow folks to customize queries programmatically.
|
||||
*
|
||||
* @param array $query_args The args that will be passed to the WP_Query.
|
||||
* @param mixed $source The source that's passed down the GraphQL queries.
|
||||
* @param array $args The inputArgs on the field.
|
||||
* @param \WPGraphQL\AppContext $context The AppContext passed down the GraphQL tree.
|
||||
* @param array $query_args The args that will be passed to the WP_Query.
|
||||
* @param mixed $source The source that's passed down the GraphQL queries.
|
||||
* @param array<string, mixed>|null $args The inputArgs on the field.
|
||||
* @param \WPGraphQL\AppContext $context The AppContext passed down the GraphQL tree.
|
||||
* @param \GraphQL\Type\Definition\ResolveInfo $info The ResolveInfo passed down the GraphQL tree.
|
||||
*/
|
||||
$query_args = apply_filters( 'graphql_cart_item_connection_query_args', $query_args, $this->source, $this->args, $this->context, $this->info );
|
||||
|
||||
@@ -159,10 +159,10 @@ class Coupon_Connection_Resolver extends AbstractConnectionResolver {
|
||||
/**
|
||||
* Filter the $query args to allow folks to customize queries programmatically
|
||||
*
|
||||
* @param array $query_args The args that will be passed to the WP_Query
|
||||
* @param mixed $source The source that's passed down the GraphQL queries
|
||||
* @param array $args The inputArgs on the field
|
||||
* @param \WPGraphQL\AppContext $context The AppContext passed down the GraphQL tree
|
||||
* @param array $query_args The args that will be passed to the WP_Query
|
||||
* @param mixed $source The source that's passed down the GraphQL queries
|
||||
* @param array<string, mixed>|null $args The inputArgs on the field
|
||||
* @param \WPGraphQL\AppContext $context The AppContext passed down the GraphQL tree
|
||||
* @param \GraphQL\Type\Definition\ResolveInfo $info The ResolveInfo passed down the GraphQL tree
|
||||
*/
|
||||
$query_args = apply_filters( 'graphql_coupon_connection_query_args', $query_args, $this->source, $this->args, $this->context, $this->info );
|
||||
@@ -178,7 +178,9 @@ class Coupon_Connection_Resolver extends AbstractConnectionResolver {
|
||||
* @return \WP_Query
|
||||
*/
|
||||
public function get_query() {
|
||||
$query = new \WP_Query( $this->query_args );
|
||||
/** @var array $query_args */
|
||||
$query_args = $this->query_args;
|
||||
$query = new \WP_Query( $query_args );
|
||||
|
||||
if ( isset( $query->query_vars['suppress_filters'] ) && true === $query->query_vars['suppress_filters'] ) {
|
||||
throw new InvariantViolation( __( 'WP_Query has been modified by a plugin or theme to suppress_filters, which will cause issues with WPGraphQL Execution. If you need to suppress filters for a specific reason within GraphQL, consider registering a custom field to the WPGraphQL Schema with a custom resolver.', 'wp-graphql-woocommerce' ) );
|
||||
@@ -237,13 +239,13 @@ class Coupon_Connection_Resolver extends AbstractConnectionResolver {
|
||||
* This allows plugins/themes to hook in and alter what $args should be allowed to be passed
|
||||
* from a GraphQL Query to the WP_Query
|
||||
*
|
||||
* @param array $args The mapped query arguments
|
||||
* @param array $where_args Query "where" args
|
||||
* @param mixed $source The query results for a query calling this
|
||||
* @param array $all_args All of the arguments for the query (not just the "where" args)
|
||||
* @param \WPGraphQL\AppContext $context The AppContext object
|
||||
* @param array $args The mapped query arguments
|
||||
* @param array $where_args Query "where" args
|
||||
* @param mixed $source The query results for a query calling this
|
||||
* @param array<string, mixed>|null $all_args All of the arguments for the query (not just the "where" args)
|
||||
* @param \WPGraphQL\AppContext $context The AppContext object
|
||||
* @param \GraphQL\Type\Definition\ResolveInfo $info The ResolveInfo object
|
||||
* @param mixed|string|array $post_type The post type for the query
|
||||
* @param mixed|string|array $post_type The post type for the query
|
||||
*/
|
||||
$args = apply_filters(
|
||||
'graphql_map_input_fields_to_coupon_query',
|
||||
|
||||
@@ -91,10 +91,10 @@ class Downloadable_Item_Connection_Resolver extends AbstractConnectionResolver {
|
||||
/**
|
||||
* Filter the $query_args to allow folks to customize queries programmatically.
|
||||
*
|
||||
* @param array $query_args The args that will be passed to the WP_Query.
|
||||
* @param mixed $source The source that's passed down the GraphQL queries.
|
||||
* @param array $args The inputArgs on the field.
|
||||
* @param \WPGraphQL\AppContext $context The AppContext passed down the GraphQL tree.
|
||||
* @param array $query_args The args that will be passed to the WP_Query.
|
||||
* @param mixed $source The source that's passed down the GraphQL queries.
|
||||
* @param array<string, mixed>|null $args The inputArgs on the field.
|
||||
* @param \WPGraphQL\AppContext $context The AppContext passed down the GraphQL tree.
|
||||
* @param \GraphQL\Type\Definition\ResolveInfo $info The ResolveInfo passed down the GraphQL tree.
|
||||
*/
|
||||
$query_args = apply_filters( 'graphql_downloadable_item_connection_query_args', $query_args, $this->source, $this->args, $this->context, $this->info );
|
||||
|
||||
@@ -182,10 +182,10 @@ class Order_Connection_Resolver extends AbstractConnectionResolver {
|
||||
/**
|
||||
* Filter the $query args to allow folks to customize queries programmatically
|
||||
*
|
||||
* @param array $query_args The args that will be passed to the WP_Query
|
||||
* @param mixed $source The source that's passed down the GraphQL queries
|
||||
* @param array $args The inputArgs on the field
|
||||
* @param \WPGraphQL\AppContext $context The AppContext passed down the GraphQL tree
|
||||
* @param array $query_args The args that will be passed to the WP_Query
|
||||
* @param mixed $source The source that's passed down the GraphQL queries
|
||||
* @param array<string, mixed>|null $args The inputArgs on the field
|
||||
* @param \WPGraphQL\AppContext $context The AppContext passed down the GraphQL tree
|
||||
* @param \GraphQL\Type\Definition\ResolveInfo $info The ResolveInfo passed down the GraphQL tree
|
||||
*/
|
||||
$query_args = apply_filters( 'graphql_order_connection_query_args', $query_args, $this->source, $this->args, $this->context, $this->info );
|
||||
@@ -201,7 +201,9 @@ class Order_Connection_Resolver extends AbstractConnectionResolver {
|
||||
* @return \WC_Order_Query
|
||||
*/
|
||||
public function get_query() {
|
||||
$query = new \WC_Order_Query( $this->query_args );
|
||||
/** @var array<string, mixed> $query_args */
|
||||
$query_args = $this->query_args;
|
||||
$query = new \WC_Order_Query( $query_args );
|
||||
|
||||
if ( true === $query->get( 'suppress_filters', false ) ) {
|
||||
throw new InvariantViolation( __( 'WC_Order_Query has been modified by a plugin or theme to suppress_filters, which will cause issues with WPGraphQL Execution. If you need to suppress filters for a specific reason within GraphQL, consider registering a custom field to the WPGraphQL Schema with a custom resolver.', 'wp-graphql-woocommerce' ) );
|
||||
@@ -335,13 +337,13 @@ class Order_Connection_Resolver extends AbstractConnectionResolver {
|
||||
* This allows plugins/themes to hook in and alter what $args should be allowed to be passed
|
||||
* from a GraphQL Query to the WP_Query
|
||||
*
|
||||
* @param array $args The mapped query arguments
|
||||
* @param array $where_args Query "where" args
|
||||
* @param mixed $source The query results for a query calling this
|
||||
* @param array $all_args All of the arguments for the query (not just the "where" args)
|
||||
* @param \WPGraphQL\AppContext $context The AppContext object
|
||||
* @param array $args The mapped query arguments
|
||||
* @param array $where_args Query "where" args
|
||||
* @param mixed $source The query results for a query calling this
|
||||
* @param array<string, mixed>|null $all_args All of the arguments for the query (not just the "where" args)
|
||||
* @param \WPGraphQL\AppContext $context The AppContext object
|
||||
* @param \GraphQL\Type\Definition\ResolveInfo $info The ResolveInfo object
|
||||
* @param mixed|string|array $post_type The post type for the query
|
||||
* @param mixed|string|array $post_type The post type for the query
|
||||
*/
|
||||
$args = apply_filters(
|
||||
'graphql_map_input_fields_to_order_query',
|
||||
|
||||
@@ -45,10 +45,10 @@ class Order_Item_Connection_Resolver extends AbstractConnectionResolver {
|
||||
/**
|
||||
* Filter the $query_args to allow folks to customize queries programmatically.
|
||||
*
|
||||
* @param array $query_args The args that will be passed to the WP_Query.
|
||||
* @param mixed $source The source that's passed down the GraphQL queries.
|
||||
* @param array $args The inputArgs on the field.
|
||||
* @param \WPGraphQL\AppContext $context The AppContext passed down the GraphQL tree.
|
||||
* @param array $query_args The args that will be passed to the WP_Query.
|
||||
* @param mixed $source The source that's passed down the GraphQL queries.
|
||||
* @param array<string, mixed>|null $args The inputArgs on the field.
|
||||
* @param \WPGraphQL\AppContext $context The AppContext passed down the GraphQL tree.
|
||||
* @param \GraphQL\Type\Definition\ResolveInfo $info The ResolveInfo passed down the GraphQL tree.
|
||||
*/
|
||||
$query_args = apply_filters( 'graphql_order_item_connection_query_args', $query_args, $this->source, $this->args, $this->context, $this->info );
|
||||
@@ -80,10 +80,10 @@ class Order_Item_Connection_Resolver extends AbstractConnectionResolver {
|
||||
/**
|
||||
* Filter the $item_type to allow non-core item types.
|
||||
*
|
||||
* @param string $item_type Order item type.
|
||||
* @param mixed $source The source that's passed down the GraphQL queries.
|
||||
* @param array $args The inputArgs on the field.
|
||||
* @param \WPGraphQL\AppContext $context The AppContext passed down the GraphQL tree.
|
||||
* @param string $item_type Order item type.
|
||||
* @param mixed $source The source that's passed down the GraphQL queries.
|
||||
* @param array<string, mixed>|null $args The inputArgs on the field.
|
||||
* @param \WPGraphQL\AppContext $context The AppContext passed down the GraphQL tree.
|
||||
* @param \GraphQL\Type\Definition\ResolveInfo $info The ResolveInfo passed down the GraphQL tree.
|
||||
*/
|
||||
$type = apply_filters(
|
||||
@@ -143,7 +143,7 @@ class Order_Item_Connection_Resolver extends AbstractConnectionResolver {
|
||||
|
||||
// Cache items for later.
|
||||
foreach ( $items as $item ) {
|
||||
$this->loader->prime(
|
||||
$this->get_loader()->prime(
|
||||
$item->get_id(),
|
||||
new \WPGraphQL\WooCommerce\Model\Order_Item( $item, $this->source )
|
||||
);
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
namespace WPGraphQL\WooCommerce\Data\Connection;
|
||||
|
||||
use Automattic\WooCommerce\Internal\ProductAttributesLookup\Filterer;
|
||||
use Automattic\WooCommerce\StoreApi\Utilities\ProductQuery;
|
||||
use WPGraphQL\Data\Connection\AbstractConnectionResolver;
|
||||
use WPGraphQL\Utils\Utils;
|
||||
use WPGraphQL\WooCommerce\WP_GraphQL_WooCommerce;
|
||||
@@ -36,9 +36,9 @@ class Product_Connection_Resolver extends AbstractConnectionResolver {
|
||||
/**
|
||||
* The instance of the class that helps filtering with the product attributes lookup table.
|
||||
*
|
||||
* @var \Automattic\WooCommerce\Internal\ProductAttributesLookup\Filterer
|
||||
* @var \Automattic\WooCommerce\StoreApi\Utilities\ProductQuery
|
||||
*/
|
||||
private $filterer; // @phpstan-ignore-line
|
||||
private $products_query;
|
||||
|
||||
/**
|
||||
* Refund_Connection_Resolver constructor.
|
||||
@@ -52,7 +52,7 @@ class Product_Connection_Resolver extends AbstractConnectionResolver {
|
||||
// @codingStandardsIgnoreLine.
|
||||
$this->post_type = ['product'];
|
||||
|
||||
$this->filterer = wc_get_container()->get( Filterer::class ); // @phpstan-ignore-line
|
||||
$this->products_query = new ProductQuery();
|
||||
|
||||
/**
|
||||
* Call the parent construct to setup class data
|
||||
@@ -155,7 +155,7 @@ class Product_Connection_Resolver extends AbstractConnectionResolver {
|
||||
/**
|
||||
* If the query contains search default the results to
|
||||
*/
|
||||
if ( isset( $query_args['search'] ) && ! empty( $query_args['search'] ) ) {
|
||||
if ( ! empty( $query_args['search'] ) && empty( $query_args['orderby'] ) ) {
|
||||
/**
|
||||
* Don't order search results by title (causes funky issues with cursors)
|
||||
*/
|
||||
@@ -167,6 +167,54 @@ class Product_Connection_Resolver extends AbstractConnectionResolver {
|
||||
$query_args = array_merge( $query_args, \WC()->query->get_catalog_ordering_args( 'menu_order', isset( $last ) ? 'ASC' : 'DESC' ) );
|
||||
}
|
||||
|
||||
$has_offset = isset( $last ) ? $this->get_before_offset() : $this->get_after_offset();
|
||||
|
||||
$offset_product = null;
|
||||
if ( $has_offset ) {
|
||||
/** @var \WPGraphQL\WooCommerce\Model\Product|null $offset_model */
|
||||
$offset_model = $this->get_loader()->load( $has_offset );
|
||||
|
||||
/** @var \WC_Product|\WC_Product_Variable|null $offset_product */
|
||||
$offset_product = $offset_model ? $offset_model->as_WC_Data() : null;
|
||||
}
|
||||
|
||||
if ( $offset_product && 'price' === $query_args['orderby'] ) {
|
||||
/** @var array<float>|float|null $price */
|
||||
$price = is_a( $offset_product, 'WC_Product_Variable' )
|
||||
? $offset_product->get_variation_price()
|
||||
: $offset_product->get_price();
|
||||
if ( 'ASC' === $query_args['order'] ) {
|
||||
if ( is_array( $price ) ) {
|
||||
$price = reset( $price );
|
||||
}
|
||||
$query_args['graphql_cursor_compare_by_price_key'] = 'wc_product_meta_lookup.min_price';
|
||||
$query_args['graphql_cursor_compare_by_price_value'] = $price;
|
||||
} else {
|
||||
if ( is_array( $price ) ) {
|
||||
$price = end( $price );
|
||||
}
|
||||
$query_args['graphql_cursor_compare_by_price_key'] = 'wc_product_meta_lookup.max_price';
|
||||
$query_args['graphql_cursor_compare_by_price_value'] = $price;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $offset_product && 'popularity' === $query_args['orderby'] ) {
|
||||
$query_args['graphql_cursor_compare_by_popularity_value'] = $offset_product->get_total_sales();
|
||||
$query_args['graphql_cursor_compare_by_popularity_key'] = 'wc_product_meta_lookup.total_sales';
|
||||
}
|
||||
|
||||
if ( $offset_product && 'rating' === $query_args['orderby'] ) {
|
||||
$query_args['graphql_cursor_compare_by_rating_value'] = $offset_product->get_average_rating();
|
||||
$query_args['graphql_cursor_compare_by_rating_key'] = 'wc_product_meta_lookup.average_rating';
|
||||
}
|
||||
|
||||
if ( $offset_product && 'comment_count' === $query_args['orderby'] ) {
|
||||
$query_args['graphql_cursor_compare_by_comment_count_value'] = $offset_product->get_rating_count();
|
||||
$query_args['graphql_cursor_compare_by_comment_count_key'] = 'wc_product_meta_lookup.rating_count';
|
||||
$query_args['graphql_cursor_compare_by_rating_value'] = $offset_product->get_average_rating();
|
||||
$query_args['graphql_cursor_compare_by_rating_key'] = 'wc_product_meta_lookup.average_rating';
|
||||
}
|
||||
|
||||
/**
|
||||
* NOTE: Only IDs should be queried here as the Deferred resolution will handle
|
||||
* fetching the full objects, either from cache of from a follow-up query to the DB
|
||||
@@ -178,7 +226,7 @@ class Product_Connection_Resolver extends AbstractConnectionResolver {
|
||||
*
|
||||
* @param array $query_args The args that will be passed to the WP_Query
|
||||
* @param mixed $source The source that's passed down the GraphQL queries
|
||||
* @param array $args The inputArgs on the field
|
||||
* @param array<string, mixed>|null $args The inputArgs on the field
|
||||
* @param \WPGraphQL\AppContext $context The AppContext passed down the GraphQL tree
|
||||
* @param \GraphQL\Type\Definition\ResolveInfo $info The ResolveInfo passed down the GraphQL tree
|
||||
*/
|
||||
@@ -189,83 +237,19 @@ class Product_Connection_Resolver extends AbstractConnectionResolver {
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function get_query() {
|
||||
// Run query and add product query filters.
|
||||
$wp_query = new \WP_Query();
|
||||
$wp_query->query_vars = wp_parse_args( $this->query_args );
|
||||
add_filter( 'posts_clauses', [ $this, 'product_query_post_clauses' ], 10, 2 );
|
||||
add_filter( 'posts_clauses', [ $this->products_query, 'add_query_clauses' ], 10, 2 );
|
||||
|
||||
return $wp_query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter the product query and apply WC's custom clauses.
|
||||
*
|
||||
* @param array $args The query clauses.
|
||||
* @param \WP_Query $wp_query The WP_Query object.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function product_query_post_clauses( $args, $wp_query ) {
|
||||
if ( 'product_query' !== $wp_query->get( 'wc_query' ) ) {
|
||||
return $args;
|
||||
}
|
||||
|
||||
$args = $this->price_filter_post_clauses( $args, $wp_query );
|
||||
$args = $this->filterer->filter_by_attribute_post_clauses( $args, $wp_query, [] ); // @phpstan-ignore-line
|
||||
|
||||
return $args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom query used to filter products by price.
|
||||
*
|
||||
* @param array $args SQL clauses.
|
||||
* @param \WP_Query $wp_query WP_Query object.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function price_filter_post_clauses( $args, $wp_query ) {
|
||||
global $wpdb;
|
||||
|
||||
$min_price = $wp_query->get( 'min_price' );
|
||||
$max_price = $wp_query->get( 'max_price' );
|
||||
|
||||
// phpcs:disable WordPress.Security.NonceVerification.Recommended
|
||||
$current_min_price = $min_price ?: 0;
|
||||
$current_max_price = $max_price ?: PHP_INT_MAX;
|
||||
// phpcs:enable WordPress.Security.NonceVerification.Recommended
|
||||
|
||||
/**
|
||||
* Adjust if the store taxes are not displayed how they are stored.
|
||||
* Kicks in when prices excluding tax are displayed including tax.
|
||||
*/
|
||||
if ( wc_tax_enabled() && 'incl' === get_option( 'woocommerce_tax_display_shop' ) && ! wc_prices_include_tax() ) {
|
||||
$tax_class = apply_filters( 'woocommerce_price_filter_widget_tax_class', '' ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
|
||||
$tax_rates = \WC_Tax::get_rates( $tax_class );
|
||||
|
||||
if ( $tax_rates ) {
|
||||
$current_min_price -= \WC_Tax::get_tax_total( \WC_Tax::calc_inclusive_tax( $current_min_price, $tax_rates ) );
|
||||
$current_max_price -= \WC_Tax::get_tax_total( \WC_Tax::calc_inclusive_tax( $current_max_price, $tax_rates ) );
|
||||
}
|
||||
}
|
||||
|
||||
$args['join'] .= ! strstr( $args['join'], 'wc_product_meta_lookup' )
|
||||
? " LEFT JOIN {$wpdb->wc_product_meta_lookup} wc_product_meta_lookup ON $wpdb->posts.ID = wc_product_meta_lookup.product_id "
|
||||
: '';
|
||||
$args['where'] .= $wpdb->prepare(
|
||||
' AND NOT (%f<wc_product_meta_lookup.min_price OR %f>wc_product_meta_lookup.max_price ) ',
|
||||
$current_max_price,
|
||||
$current_min_price
|
||||
);
|
||||
return $args;
|
||||
return new \WP_Query();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function get_ids_from_query() {
|
||||
$ids = $this->query->get_posts();
|
||||
remove_filter( 'posts_clauses', [ $this, 'product_query_post_clauses' ], 10 );
|
||||
// Run query and get IDs.
|
||||
$ids = $this->query->query( $this->query_args );
|
||||
|
||||
remove_filter( 'posts_clauses', [ $this->products_query, 'add_query_clauses' ], 10 );
|
||||
|
||||
// If we're going backwards, we need to reverse the array.
|
||||
if ( ! empty( $this->args['last'] ) ) {
|
||||
@@ -332,9 +316,13 @@ class Product_Connection_Resolver extends AbstractConnectionResolver {
|
||||
$default_order = isset( $this->args['last'] ) ? 'ASC' : 'DESC';
|
||||
$orderby_input = current( $where_args['orderby'] );
|
||||
|
||||
$orderby = $orderby_input['field'];
|
||||
$order = ! empty( $orderby_input['order'] ) ? $orderby_input['order'] : $default_order;
|
||||
$query_args = array_merge( $query_args, \WC()->query->get_catalog_ordering_args( $orderby, $order ) );
|
||||
$orderby = $orderby_input['field'];
|
||||
$order = ! empty( $orderby_input['order'] ) ? $orderby_input['order'] : $default_order;
|
||||
// Set the order to DESC if orderby is popularity.
|
||||
if ( 'popularity' === $orderby || 'rating' === $orderby ) {
|
||||
$order = 'DESC';
|
||||
}
|
||||
$query_args = array_merge( $query_args, \wc()->query->get_catalog_ordering_args( $orderby, $order ) );
|
||||
}
|
||||
|
||||
if ( isset( $where_args['includeVariations'] ) && $where_args['includeVariations'] ) {
|
||||
@@ -669,15 +657,11 @@ class Product_Connection_Resolver extends AbstractConnectionResolver {
|
||||
];
|
||||
}
|
||||
if ( ! empty( $where_args['minPrice'] ) ) {
|
||||
$query_args['min_price'] = floatval( $where_args['minPrice'] );
|
||||
}
|
||||
|
||||
if ( ! empty( $where_args['minPrice'] ) ) {
|
||||
$query_args['min_price'] = floatval( $where_args['minPrice'] );
|
||||
$query_args['min_price'] = str_replace( '.', '', number_format( $where_args['minPrice'], 2 ) );
|
||||
}
|
||||
|
||||
if ( ! empty( $where_args['maxPrice'] ) ) {
|
||||
$query_args['max_price'] = floatval( $where_args['maxPrice'] );
|
||||
$query_args['max_price'] = str_replace( '.', '', number_format( $where_args['maxPrice'], 2 ) );
|
||||
}
|
||||
|
||||
if ( isset( $where_args['stockStatus'] ) ) {
|
||||
|
||||
@@ -64,7 +64,7 @@ class Shipping_Method_Connection_Resolver extends AbstractConnectionResolver {
|
||||
}
|
||||
|
||||
foreach ( $methods as $method ) {
|
||||
$this->loader->prime( $method->id, new Shipping_Method( $method ) );
|
||||
$this->get_loader()->prime( $method->id, new Shipping_Method( $method ) );
|
||||
}
|
||||
|
||||
// Get shipping method IDs.
|
||||
|
||||
@@ -74,7 +74,7 @@ class Tax_Class_Connection_Resolver extends AbstractConnectionResolver {
|
||||
|
||||
// Cache cart items for later.
|
||||
foreach ( $tax_classes as $tax_class ) {
|
||||
$this->loader->prime( $tax_class['slug'], $tax_class );
|
||||
$this->get_loader()->prime( $tax_class['slug'], $tax_class );
|
||||
}
|
||||
|
||||
return wp_list_pluck( $tax_classes, 'slug' );
|
||||
|
||||
@@ -95,10 +95,10 @@ class Tax_Rate_Connection_Resolver extends AbstractConnectionResolver {
|
||||
/**
|
||||
* Filter the $query args to allow folks to customize queries programmatically
|
||||
*
|
||||
* @param array $query_args The args that will be passed to the WP_Query
|
||||
* @param mixed $source The source that's passed down the GraphQL queries
|
||||
* @param array $args The inputArgs on the field
|
||||
* @param \WPGraphQL\AppContext $context The AppContext passed down the GraphQL tree
|
||||
* @param array $query_args The args that will be passed to the WP_Query
|
||||
* @param mixed $source The source that's passed down the GraphQL queries
|
||||
* @param array<string, mixed>|null $args The inputArgs on the field
|
||||
* @param \WPGraphQL\AppContext $context The AppContext passed down the GraphQL tree
|
||||
* @param \GraphQL\Type\Definition\ResolveInfo $info The ResolveInfo passed down the GraphQL tree
|
||||
*/
|
||||
$query_args = apply_filters( 'graphql_tax_rate_connection_query_args', $query_args, $this->source, $this->args, $this->context, $this->info );
|
||||
@@ -114,8 +114,11 @@ class Tax_Rate_Connection_Resolver extends AbstractConnectionResolver {
|
||||
public function get_query() {
|
||||
global $wpdb;
|
||||
|
||||
if ( ! empty( $this->query_args['where'] ) ) {
|
||||
$sql_where = $this->query_args['where'];
|
||||
/** @var array<string, mixed> $query_args */
|
||||
$query_args = $this->query_args;
|
||||
|
||||
if ( ! empty( $query_args['where'] ) ) {
|
||||
$sql_where = $query_args['where'];
|
||||
|
||||
$results = $wpdb->get_results( // @codingStandardsIgnoreStart
|
||||
$wpdb->prepare(
|
||||
@@ -126,8 +129,8 @@ class Tax_Rate_Connection_Resolver extends AbstractConnectionResolver {
|
||||
WHERE {$sql_where}
|
||||
GROUP BY rates.tax_rate_id
|
||||
ORDER BY %s %s",
|
||||
$this->query_args['orderby'],
|
||||
$this->query_args['order']
|
||||
$query_args['orderby'],
|
||||
$query_args['order']
|
||||
)
|
||||
); // @codingStandardsIgnoreEnd
|
||||
} else {
|
||||
@@ -136,8 +139,8 @@ class Tax_Rate_Connection_Resolver extends AbstractConnectionResolver {
|
||||
"SELECT tax_rate_id
|
||||
FROM {$wpdb->prefix}woocommerce_tax_rates
|
||||
ORDER BY %s %s",
|
||||
$this->query_args['orderby'],
|
||||
$this->query_args['order']
|
||||
$query_args['orderby'],
|
||||
$query_args['order']
|
||||
)
|
||||
); // @codingStandardsIgnoreEnd
|
||||
}//end if
|
||||
|
||||
@@ -74,6 +74,7 @@ class WC_CPT_Loader extends AbstractDataLoader {
|
||||
* @throws \GraphQL\Error\UserError - throws if the post-type is not a valid WooCommerce post-type.
|
||||
*/
|
||||
public function loadKeys( array $keys ) {
|
||||
/** @var array<int> $keys */
|
||||
if ( empty( $keys ) ) {
|
||||
return $keys;
|
||||
}
|
||||
@@ -177,7 +178,6 @@ class WC_CPT_Loader extends AbstractDataLoader {
|
||||
break;
|
||||
case 'product_variation':
|
||||
case 'shop_refund':
|
||||
$parent_id = $entry->post_parent;
|
||||
if ( ! empty( $entry->post_parent ) ) {
|
||||
$context->get_loader( 'wc_post' )->load_deferred( $entry->post_parent );
|
||||
}
|
||||
|
||||
@@ -172,6 +172,7 @@ class Product extends WC_Post {
|
||||
}
|
||||
|
||||
sort( $prices, SORT_NUMERIC );
|
||||
graphql_debug( implode( ', ', $prices ) );
|
||||
|
||||
if ( $raw ) {
|
||||
return implode( ', ', $prices );
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
|
||||
namespace WPGraphQL\WooCommerce\Mutation;
|
||||
|
||||
use GraphQL\Error\UserError;
|
||||
use GraphQL\Type\Definition\ResolveInfo;
|
||||
use WPGraphQL\AppContext;
|
||||
use WPGraphQL\Model\Comment;
|
||||
@@ -105,9 +104,6 @@ class Review_Write {
|
||||
$resolver = CommentCreate::mutate_and_get_payload();
|
||||
|
||||
$payload = $resolver( $input, $context, $info );
|
||||
if ( is_a( $payload, UserError::class ) ) {
|
||||
throw $payload;
|
||||
}
|
||||
|
||||
// Set product rating upon successful creation of the review.
|
||||
if ( $payload['success'] ) {
|
||||
|
||||
@@ -35,23 +35,21 @@ class Products_Orderby_Enum extends Post_Type_Orderby_Enum {
|
||||
'description' => __( 'Order by product\'s current price', 'wp-graphql-woocommerce' ),
|
||||
],
|
||||
'REGULAR_PRICE' => [
|
||||
'value' => 'regular_price',
|
||||
'description' => __( 'Order by product\'s regular price', 'wp-graphql-woocommerce' ),
|
||||
'value' => 'price',
|
||||
'description' => __( 'Order by product\'s regular price', 'wp-graphql-woocommerce' ),
|
||||
'deprecationReason' => __( 'This field is deprecated and will be removed in a future version. Use "PRICE" instead.', 'wp-graphql-woocommerce' ),
|
||||
],
|
||||
'SALE_PRICE' => [
|
||||
'value' => 'sale_price',
|
||||
'description' => __( 'Order by product\'s sale price', 'wp-graphql-woocommerce' ),
|
||||
],
|
||||
'RELEVANCE' => [
|
||||
'value' => 'relevance',
|
||||
'description' => __( 'Order by relevance', 'wp-graphql-woocommerce' ),
|
||||
'value' => 'price',
|
||||
'description' => __( 'Order by product\'s sale price', 'wp-graphql-woocommerce' ),
|
||||
'deprecationReason' => __( 'This field is deprecated and will be removed in a future version. Use "PRICE" instead.', 'wp-graphql-woocommerce' ),
|
||||
],
|
||||
'POPULARITY' => [
|
||||
'value' => 'popularity',
|
||||
'description' => __( 'Order by product popularity', 'wp-graphql-woocommerce' ),
|
||||
],
|
||||
'REVIEW_COUNT' => [
|
||||
'value' => 'popularity',
|
||||
'value' => 'comment_count',
|
||||
'description' => __( 'Order by number of reviews on product', 'wp-graphql-woocommerce' ),
|
||||
],
|
||||
'RATING' => [
|
||||
@@ -59,16 +57,19 @@ class Products_Orderby_Enum extends Post_Type_Orderby_Enum {
|
||||
'description' => __( 'Order by product average rating', 'wp-graphql-woocommerce' ),
|
||||
],
|
||||
'ON_SALE_FROM' => [
|
||||
'value' => '_sale_price_dates_from',
|
||||
'description' => __( 'Order by date product sale starts', 'wp-graphql-woocommerce' ),
|
||||
'value' => 'date',
|
||||
'description' => __( 'Order by date product sale starts', 'wp-graphql-woocommerce' ),
|
||||
'deprecationReason' => __( 'This field is deprecated and will be removed in a future version.', 'wp-graphql-woocommerce' ),
|
||||
],
|
||||
'ON_SALE_TO' => [
|
||||
'value' => '_sale_price_dates_to',
|
||||
'description' => __( 'Order by date product sale ends', 'wp-graphql-woocommerce' ),
|
||||
'value' => 'date',
|
||||
'description' => __( 'Order by date product sale ends', 'wp-graphql-woocommerce' ),
|
||||
'deprecationReason' => __( 'This field is deprecated and will be removed in a future version.', 'wp-graphql-woocommerce' ),
|
||||
],
|
||||
'TOTAL_SALES' => [
|
||||
'value' => 'total_sales',
|
||||
'description' => __( 'Order by total sales of products sold', 'wp-graphql-woocommerce' ),
|
||||
'value' => 'popularity',
|
||||
'description' => __( 'Order by total sales of products sold', 'wp-graphql-woocommerce' ),
|
||||
'deprecationReason' => __( 'This field is deprecated and will be removed in a future version. Use "POPULARITY" instead', 'wp-graphql-woocommerce' ),
|
||||
],
|
||||
]
|
||||
)
|
||||
|
||||
@@ -61,6 +61,8 @@ class Product_With_Pricing {
|
||||
// @codingStandardsIgnoreLine.
|
||||
return $source->priceRaw;
|
||||
} else {
|
||||
graphql_debug( $source->price );
|
||||
// @codingStandardsIgnoreLine.
|
||||
return $source->price;
|
||||
}
|
||||
},
|
||||
|
||||
@@ -427,7 +427,7 @@ class Order_Type {
|
||||
* @param \WPGraphQL\AppContext $context AppContext instance.
|
||||
* @param \GraphQL\Type\Definition\ResolveInfo $info ResolveInfo instance.
|
||||
*
|
||||
* @return array
|
||||
* @return \GraphQL\Deferred
|
||||
*/
|
||||
public static function resolve_item_connection( $source, array $args, AppContext $context, ResolveInfo $info ) {
|
||||
$resolver = new Order_Item_Connection_Resolver( $source, $args, $context, $info );
|
||||
|
||||
@@ -589,6 +589,7 @@ class Root_Query {
|
||||
],
|
||||
'description' => __( 'Statistics for a product taxonomy query', 'wp-graphql-woocommerce' ),
|
||||
'resolve' => static function ( $_, $args ) {
|
||||
/** @var array<string, mixed> $data */
|
||||
$data = [
|
||||
'min_price' => null,
|
||||
'max_price' => null,
|
||||
@@ -596,7 +597,7 @@ class Root_Query {
|
||||
'stock_status_counts' => null,
|
||||
'rating_counts' => null,
|
||||
];
|
||||
$filters = new ProductQueryFilters(); // @phpstan-ignore-line
|
||||
$filters = new ProductQueryFilters();
|
||||
|
||||
// Process client-side filters.
|
||||
$request = Collection_Stats_Type::prepare_rest_request( $args['where'] ?? [] );
|
||||
@@ -633,7 +634,8 @@ class Root_Query {
|
||||
$filter_request->set_param( 'min_price', null );
|
||||
$filter_request->set_param( 'max_price', null );
|
||||
|
||||
$price_results = $filters->get_filtered_price( $filter_request ); // @phpstan-ignore-line
|
||||
/** @var object{min_price: float, max_price: float} */
|
||||
$price_results = $filters->get_filtered_price( $filter_request );
|
||||
$data['min_price'] = $price_results->min_price;
|
||||
$data['max_price'] = $price_results->max_price;
|
||||
}
|
||||
@@ -645,7 +647,7 @@ class Root_Query {
|
||||
* @var \WP_REST_Request $filter_request
|
||||
*/
|
||||
$filter_request = clone $request;
|
||||
$counts = $filters->get_stock_status_counts( $filter_request ); // @phpstan-ignore-line
|
||||
$counts = $filters->get_stock_status_counts( $filter_request );
|
||||
|
||||
$data['stock_status_counts'] = [];
|
||||
|
||||
@@ -693,7 +695,7 @@ class Root_Query {
|
||||
}
|
||||
|
||||
$filter_request->set_param( 'attributes', $filter_attributes );
|
||||
$counts = $filters->get_attribute_counts( $filter_request, [ $taxonomy ] ); // @phpstan-ignore-line
|
||||
$counts = $filters->get_attribute_counts( $filter_request, [ $taxonomy ] );
|
||||
|
||||
$data['attribute_counts'][ $taxonomy ] = [];
|
||||
foreach ( $counts as $key => $value ) {
|
||||
@@ -707,7 +709,7 @@ class Root_Query {
|
||||
}
|
||||
|
||||
if ( ! empty( $taxonomy__and_queries ) ) {
|
||||
$counts = $filters->get_attribute_counts( $request, $taxonomy__and_queries ); // @phpstan-ignore-line
|
||||
$counts = $filters->get_attribute_counts( $request, $taxonomy__and_queries );
|
||||
|
||||
foreach ( $taxonomy__and_queries as $taxonomy ) {
|
||||
$data['attribute_counts'][ $taxonomy ] = [];
|
||||
@@ -729,7 +731,7 @@ class Root_Query {
|
||||
* @var \WP_REST_Request $filter_request
|
||||
*/
|
||||
$filter_request = clone $request;
|
||||
$counts = $filters->get_rating_counts( $filter_request ); // @phpstan-ignore-line
|
||||
$counts = $filters->get_rating_counts( $filter_request );
|
||||
$data['rating_counts'] = [];
|
||||
|
||||
foreach ( $counts as $key => $value ) {
|
||||
|
||||
@@ -5,7 +5,8 @@ use Tests\WPGraphQL\Logger\CodeceptLogger as Signal;
|
||||
class CartTransactionQueueCest {
|
||||
private $product_catalog;
|
||||
|
||||
public function _before( FunctionalTester $I ) {
|
||||
public function _before( FunctionalTester $I, $scenario ) {
|
||||
$scenario->skip( 'This test is unstable' );
|
||||
// Create Products
|
||||
$this->product_catalog = $I->getCatalog();
|
||||
}
|
||||
|
||||
@@ -439,479 +439,6 @@ class ProductQueriesTest extends \Tests\WPGraphQL\WooCommerce\TestCase\WooGraphQ
|
||||
$this->assertQuerySuccessful( $response, $expected );
|
||||
}
|
||||
|
||||
public function testProductsQueryAndWhereArgs() {
|
||||
$category_3 = $this->factory->product->createProductCategory( 'category-three' );
|
||||
$category_4 = $this->factory->product->createProductCategory( 'category-four' );
|
||||
$product_ids = [
|
||||
$this->factory->product->createSimple(
|
||||
[
|
||||
'slug' => 'test-product-1',
|
||||
'price' => 6000,
|
||||
'regular_price' => 6000,
|
||||
]
|
||||
),
|
||||
$this->factory->product->createSimple(
|
||||
[
|
||||
'price' => 2,
|
||||
'regular_price' => 2,
|
||||
'category_ids' => [ $category_3, $category_4 ],
|
||||
]
|
||||
),
|
||||
$this->factory->product->createSimple(
|
||||
[
|
||||
'featured' => 'true',
|
||||
'category_ids' => [ $category_3 ],
|
||||
]
|
||||
),
|
||||
$this->factory->product->createExternal(),
|
||||
$this->factory->product->createSimple(
|
||||
[
|
||||
'price' => 200,
|
||||
'regular_price' => 300,
|
||||
'sale_price' => 200,
|
||||
'date_on_sale_from' => ( new \DateTime( 'yesterday' ) )->format( 'Y-m-d H:i:s' ),
|
||||
'date_on_sale_to' => ( new \DateTime( 'tomorrow' ) )->format( 'Y-m-d H:i:s' ),
|
||||
'stock_status' => 'outofstock',
|
||||
]
|
||||
),
|
||||
];
|
||||
|
||||
$query = '
|
||||
query (
|
||||
$slugIn: [String],
|
||||
$status: String,
|
||||
$category: String,
|
||||
$categoryIn: [String],
|
||||
$categoryNotIn: [String],
|
||||
$categoryId: Int,
|
||||
$categoryIdIn: [Int]
|
||||
$categoryIdNotIn: [Int]
|
||||
$type: ProductTypesEnum,
|
||||
$typeIn: [ProductTypesEnum],
|
||||
$typeNotIn: [ProductTypesEnum],
|
||||
$featured: Boolean,
|
||||
$maxPrice: Float,
|
||||
$orderby: [ProductsOrderbyInput]
|
||||
$taxonomyFilter: ProductTaxonomyInput
|
||||
$include: [Int]
|
||||
$exclude: [Int]
|
||||
$stockStatus: [StockStatusEnum]
|
||||
) {
|
||||
products( where: {
|
||||
slugIn: $slugIn,
|
||||
status: $status,
|
||||
category: $category,
|
||||
categoryIn: $categoryIn,
|
||||
categoryNotIn: $categoryNotIn,
|
||||
categoryId: $categoryId,
|
||||
categoryIdIn: $categoryIdIn,
|
||||
categoryIdNotIn: $categoryIdNotIn,
|
||||
type: $type,
|
||||
typeIn: $typeIn,
|
||||
typeNotIn: $typeNotIn,
|
||||
featured: $featured,
|
||||
maxPrice: $maxPrice,
|
||||
orderby: $orderby,
|
||||
taxonomyFilter: $taxonomyFilter
|
||||
include: $include
|
||||
exclude: $exclude
|
||||
stockStatus: $stockStatus
|
||||
} ) {
|
||||
nodes {
|
||||
id
|
||||
... on ProductWithPricing {
|
||||
databaseId
|
||||
price
|
||||
}
|
||||
... on InventoriedProduct {
|
||||
stockStatus
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
';
|
||||
|
||||
$all_expected_product_nodes = array_map(
|
||||
function ( $product_id ) {
|
||||
return $this->expectedNode(
|
||||
'products.nodes',
|
||||
[ $this->expectedField( 'id', $this->toRelayId( 'product', $product_id ) ) ]
|
||||
);
|
||||
},
|
||||
$product_ids
|
||||
);
|
||||
|
||||
/**
|
||||
* Assertion One
|
||||
*
|
||||
* Tests query with no arguments, and expect all products to be returned.
|
||||
*/
|
||||
$response = $this->graphql( compact( 'query' ) );
|
||||
$this->assertQuerySuccessful( $response, $all_expected_product_nodes );
|
||||
|
||||
/**
|
||||
* Assertion Two
|
||||
*
|
||||
* Tests query with "slug" where argument, and expect the product with
|
||||
* the slug "test-product-1" to be returned.
|
||||
*/
|
||||
$variables = [ 'slugIn' => [ 'test-product-1' ] ];
|
||||
$response = $this->graphql( compact( 'query', 'variables' ) );
|
||||
$expected = array_filter(
|
||||
$all_expected_product_nodes,
|
||||
static function ( $node, $index ) use ( $product_ids ) {
|
||||
$product = \wc_get_product( $product_ids[ $index ] );
|
||||
return 'test-product-1' === $product->get_slug();
|
||||
},
|
||||
ARRAY_FILTER_USE_BOTH
|
||||
);
|
||||
|
||||
$this->assertQuerySuccessful( $response, $expected );
|
||||
|
||||
/**
|
||||
* Assertion Three
|
||||
*
|
||||
* Tests query with "status" where argument, and expect the products with
|
||||
* a status of "pending" to be returned, which there are none among the test
|
||||
* product with that status.
|
||||
*/
|
||||
$variables = [ 'status' => 'pending' ];
|
||||
$response = $this->graphql( compact( 'query', 'variables' ) );
|
||||
$expected = [ $this->expectedField( 'products.nodes', [] ) ];
|
||||
|
||||
$this->assertQuerySuccessful( $response, $expected );
|
||||
|
||||
/**
|
||||
* Assertion Four
|
||||
*
|
||||
* Tests query with "type" where argument, and expect only "simple" products
|
||||
* to be returned.
|
||||
*/
|
||||
$variables = [ 'type' => 'SIMPLE' ];
|
||||
$response = $this->graphql( compact( 'query', 'variables' ) );
|
||||
$expected = array_filter(
|
||||
$all_expected_product_nodes,
|
||||
static function ( $node, $index ) use ( $product_ids ) {
|
||||
$product = \wc_get_product( $product_ids[ $index ] );
|
||||
return 'simple' === $product->get_type();
|
||||
},
|
||||
ARRAY_FILTER_USE_BOTH
|
||||
);
|
||||
|
||||
$this->assertQuerySuccessful( $response, $expected );
|
||||
|
||||
/**
|
||||
* Assertion Five
|
||||
*
|
||||
* Tests query with "typeIn" where argument, and expect only "simple" products
|
||||
* to be returned.
|
||||
*/
|
||||
$variables = [ 'typeIn' => [ 'SIMPLE' ] ];
|
||||
$response = $this->graphql( compact( 'query', 'variables' ) );
|
||||
// No need to reassign the $expected for this assertion.
|
||||
|
||||
$this->assertQuerySuccessful( $response, $expected );
|
||||
|
||||
/**
|
||||
* Assertion Six
|
||||
*
|
||||
* Tests query with "typeNotIn" where argument, and expect all types of products
|
||||
* with except "simple" to be returned.
|
||||
*/
|
||||
$variables = [ 'typeNotIn' => [ 'SIMPLE' ] ];
|
||||
$response = $this->graphql( compact( 'query', 'variables' ) );
|
||||
$expected = array_filter(
|
||||
$all_expected_product_nodes,
|
||||
static function ( $node, $index ) use ( $product_ids ) {
|
||||
$product = \wc_get_product( $product_ids[ $index ] );
|
||||
return 'simple' !== $product->get_type();
|
||||
},
|
||||
ARRAY_FILTER_USE_BOTH
|
||||
);
|
||||
|
||||
$this->assertQuerySuccessful( $response, $expected );
|
||||
|
||||
/**
|
||||
* Assertion Seven
|
||||
*
|
||||
* Tests query with "featured" where argument, expect only featured products
|
||||
* to be returned.
|
||||
*/
|
||||
$variables = [ 'featured' => true ];
|
||||
$response = $this->graphql( compact( 'query', 'variables' ) );
|
||||
$expected = array_filter(
|
||||
$all_expected_product_nodes,
|
||||
static function ( $node, $index ) use ( $product_ids ) {
|
||||
$product = \wc_get_product( $product_ids[ $index ] );
|
||||
return $product->get_featured();
|
||||
},
|
||||
ARRAY_FILTER_USE_BOTH
|
||||
);
|
||||
|
||||
$this->assertQuerySuccessful( $response, $expected );
|
||||
|
||||
/**
|
||||
* Assertion Eight
|
||||
*
|
||||
* Tests query with "maxPrice" where argument, and expect all product
|
||||
* with a price of 10.00+ to be returned.
|
||||
*/
|
||||
$variables = [ 'maxPrice' => 10.00 ];
|
||||
$response = $this->graphql( compact( 'query', 'variables' ) );
|
||||
$expected = array_filter(
|
||||
$all_expected_product_nodes,
|
||||
static function ( $node, $index ) use ( $product_ids ) {
|
||||
$product = \wc_get_product( $product_ids[ $index ] );
|
||||
return 10.00 >= floatval( $product->get_price() );
|
||||
},
|
||||
ARRAY_FILTER_USE_BOTH
|
||||
);
|
||||
|
||||
$this->assertQuerySuccessful( $response, $expected );
|
||||
|
||||
/**
|
||||
* Assertion Nine
|
||||
*
|
||||
* Tests query with "orderby" where argument, and expect products to
|
||||
* be return in descending order by "price".
|
||||
*/
|
||||
$variables = [
|
||||
'orderby' => [
|
||||
[
|
||||
'field' => 'PRICE',
|
||||
'order' => 'DESC',
|
||||
],
|
||||
],
|
||||
];
|
||||
$response = $this->graphql( compact( 'query', 'variables' ) );
|
||||
|
||||
$expected = [
|
||||
$this->expectedNode(
|
||||
'products.nodes',
|
||||
[ $this->expectedField( 'id', $this->toRelayId( 'product', $product_ids[0] ) ) ],
|
||||
0
|
||||
),
|
||||
$this->expectedNode(
|
||||
'products.nodes',
|
||||
[ $this->expectedField( 'id', $this->toRelayId( 'product', $product_ids[1] ) ) ],
|
||||
4
|
||||
),
|
||||
];
|
||||
|
||||
$this->assertQuerySuccessful( $response, $expected );
|
||||
|
||||
/**
|
||||
* Assertion Ten
|
||||
*
|
||||
* Tests query with "category" where argument, and expect products in
|
||||
* the "category-three" category to be returned.
|
||||
*/
|
||||
$variables = [ 'category' => 'category-three' ];
|
||||
$response = $this->graphql( compact( 'query', 'variables' ) );
|
||||
$expected = array_filter(
|
||||
$all_expected_product_nodes,
|
||||
static function ( $node, $index ) use ( $product_ids, $category_3 ) {
|
||||
$product = \wc_get_product( $product_ids[ $index ] );
|
||||
return in_array( $category_3, $product->get_category_ids(), true );
|
||||
},
|
||||
ARRAY_FILTER_USE_BOTH
|
||||
);
|
||||
|
||||
$this->assertQuerySuccessful( $response, $expected );
|
||||
|
||||
$this->clearLoaderCache( 'wc_post' );
|
||||
|
||||
/**
|
||||
* Assertion Eleven
|
||||
*
|
||||
* Tests query with "categoryIn" where argument, and expect products in
|
||||
* the "category-three" category to be returned.
|
||||
*/
|
||||
$variables = [ 'categoryIn' => [ 'category-three' ] ];
|
||||
$response = $this->graphql( compact( 'query', 'variables' ) );
|
||||
// No need to reassign the $expected for this assertion.
|
||||
|
||||
$this->assertQuerySuccessful( $response, $expected );
|
||||
|
||||
/**
|
||||
* Assertion Twelve
|
||||
*
|
||||
* Tests query with "categoryId" where argument, and expect products in
|
||||
* the "category-three" category to be returned.
|
||||
*/
|
||||
$variables = [ 'categoryId' => $category_3 ];
|
||||
$response = $this->graphql( compact( 'query', 'variables' ) );
|
||||
// No need to reassign the $expected for this assertion either.
|
||||
|
||||
$this->assertQuerySuccessful( $response, $expected );
|
||||
|
||||
/**
|
||||
* Assertion Thirteen
|
||||
*
|
||||
* Tests query with "categoryNotIn" where argument, and expect all products
|
||||
* except products in the "category-four" category to be returned.
|
||||
*/
|
||||
$variables = [ 'categoryNotIn' => [ 'category-four' ] ];
|
||||
$response = $this->graphql( compact( 'query', 'variables' ) );
|
||||
$expected = array_filter(
|
||||
$all_expected_product_nodes,
|
||||
static function ( $node, $index ) use ( $product_ids, $category_4 ) {
|
||||
$product = \wc_get_product( $product_ids[ $index ] );
|
||||
return ! in_array( $category_4, $product->get_category_ids(), true );
|
||||
},
|
||||
ARRAY_FILTER_USE_BOTH
|
||||
);
|
||||
|
||||
$this->assertQuerySuccessful( $response, $expected );
|
||||
|
||||
/**
|
||||
* Assertion Fourteen
|
||||
*
|
||||
* Tests query with "categoryIdNotIn" where argument, and expect all products
|
||||
* except products in the "category-four" category to be returned.
|
||||
*/
|
||||
$variables = [ 'categoryIdNotIn' => [ $category_4 ] ];
|
||||
$response = $this->graphql( compact( 'query', 'variables' ) );
|
||||
// No need to reassign the $expected for this assertion.
|
||||
|
||||
$this->assertQuerySuccessful( $response, $expected );
|
||||
|
||||
/**
|
||||
* Assertion Fifteen
|
||||
*
|
||||
* Tests query with "categoryIdIn" where argument, and expect products in
|
||||
* the "category-four" category to be returned.
|
||||
*/
|
||||
$variables = [ 'categoryIdIn' => [ $category_4 ] ];
|
||||
$response = $this->graphql( compact( 'query', 'variables' ) );
|
||||
$expected = array_filter(
|
||||
$all_expected_product_nodes,
|
||||
static function ( $node, $index ) use ( $product_ids, $category_4 ) {
|
||||
$product = \wc_get_product( $product_ids[ $index ] );
|
||||
return in_array( $category_4, $product->get_category_ids(), true );
|
||||
},
|
||||
ARRAY_FILTER_USE_BOTH
|
||||
);
|
||||
|
||||
$this->assertQuerySuccessful( $response, $expected );
|
||||
|
||||
/**
|
||||
* Assertion Sixteen
|
||||
*
|
||||
* Tests "taxonomyFilter" where argument
|
||||
*/
|
||||
$variables = [
|
||||
'taxonomyFilter' => [
|
||||
'relation' => 'AND',
|
||||
'filters' => [
|
||||
[
|
||||
'taxonomy' => 'PRODUCT_CAT',
|
||||
'terms' => [ 'category-three' ],
|
||||
],
|
||||
[
|
||||
'taxonomy' => 'PRODUCT_CAT',
|
||||
'terms' => [ 'category-four' ],
|
||||
'operator' => 'NOT_IN',
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
$response = $this->graphql( compact( 'query', 'variables' ) );
|
||||
$expected = array_filter(
|
||||
$all_expected_product_nodes,
|
||||
static function ( $node, $index ) use ( $product_ids, $category_4, $category_3 ) {
|
||||
$product = \wc_get_product( $product_ids[ $index ] );
|
||||
return ! in_array( $category_4, $product->get_category_ids(), true )
|
||||
&& in_array( $category_3, $product->get_category_ids(), true );
|
||||
},
|
||||
ARRAY_FILTER_USE_BOTH
|
||||
);
|
||||
|
||||
$this->assertQuerySuccessful( $response, $expected );
|
||||
|
||||
/**
|
||||
* Assertion 17-18
|
||||
*
|
||||
* Tests "include" where argument
|
||||
*/
|
||||
$variables = [
|
||||
'include' => [ $product_ids[0] ],
|
||||
];
|
||||
$response = $this->graphql( compact( 'query', 'variables' ) );
|
||||
$expected = [
|
||||
$this->expectedNode(
|
||||
'products.nodes',
|
||||
[ $this->expectedField( 'id', $this->toRelayId( 'product', $product_ids[0] ) ) ]
|
||||
),
|
||||
];
|
||||
$this->assertQuerySuccessful( $response, $expected );
|
||||
|
||||
$variables = [
|
||||
'include' => [ 1000 ],
|
||||
];
|
||||
$response = $this->graphql( compact( 'query', 'variables' ) );
|
||||
$expected = [
|
||||
$this->expectedField(
|
||||
'products.nodes',
|
||||
self::IS_FALSY
|
||||
),
|
||||
];
|
||||
$this->assertQuerySuccessful( $response, $expected );
|
||||
|
||||
/**
|
||||
* Assertion 19-20
|
||||
*
|
||||
* Tests "exclude" where argument
|
||||
*/
|
||||
$variables = [
|
||||
'exclude' => [ $product_ids[0] ],
|
||||
];
|
||||
$response = $this->graphql( compact( 'query', 'variables' ) );
|
||||
$expected = [
|
||||
$this->not()->expectedNode(
|
||||
'products.nodes',
|
||||
[ $this->expectedField( 'id', $this->toRelayId( 'product', $product_ids[0] ) ) ]
|
||||
),
|
||||
];
|
||||
$this->assertQuerySuccessful( $response, $expected );
|
||||
|
||||
$variables = [ 'exclude' => $product_ids ];
|
||||
$response = $this->graphql( compact( 'query', 'variables' ) );
|
||||
$expected = [
|
||||
$this->expectedField(
|
||||
'products.nodes',
|
||||
self::IS_FALSY
|
||||
),
|
||||
];
|
||||
$this->assertQuerySuccessful( $response, $expected );
|
||||
|
||||
/**
|
||||
* Assertion 21-22
|
||||
*
|
||||
* Tests "stockStatus" where argument
|
||||
*/
|
||||
$variables = [ 'stockStatus' => 'IN_STOCK' ];
|
||||
$response = $this->graphql( compact( 'query', 'variables' ) );
|
||||
$expected = [
|
||||
$this->not()->expectedNode(
|
||||
'products.nodes',
|
||||
[ $this->expectedField( 'id', $this->toRelayId( 'product', $product_ids[4] ) ) ]
|
||||
),
|
||||
];
|
||||
$this->assertQuerySuccessful( $response, $expected );
|
||||
|
||||
$variables = [ 'stockStatus' => 'OUT_OF_STOCK' ];
|
||||
$response = $this->graphql( compact( 'query', 'variables' ) );
|
||||
$expected = [
|
||||
$this->expectedNode(
|
||||
'products.nodes',
|
||||
[ $this->expectedField( 'id', $this->toRelayId( 'product', $product_ids[4] ) ) ],
|
||||
0
|
||||
),
|
||||
];
|
||||
$this->assertQuerySuccessful( $response, $expected );
|
||||
}
|
||||
|
||||
public function testProductToTermConnection() {
|
||||
$test_category = $this->factory->product->createProductCategory( 'test-product-category-1' );
|
||||
$test_tag = $this->factory->product->createProductTag( 'test-product-tag-1' );
|
||||
|
||||
@@ -170,96 +170,6 @@ class ProductVariationQueriesTest extends \Tests\WPGraphQL\WooCommerce\TestCase\
|
||||
$this->assertQuerySuccessful( $response, $expected );
|
||||
}
|
||||
|
||||
public function testVariationsQueryAndWhereArgs() {
|
||||
// Create product variations.
|
||||
$products = $this->factory->product_variation->createSome(
|
||||
$this->factory->product->createVariable()
|
||||
);
|
||||
$variation_id = $products['variations'][0];
|
||||
$id = $this->toRelayId( 'product', $products['product'] );
|
||||
$product = wc_get_product( $products['product'] );
|
||||
$variations = $products['variations'];
|
||||
$prices = $product->get_variation_prices( true );
|
||||
|
||||
$query = '
|
||||
query (
|
||||
$id: ID!,
|
||||
$minPrice: Float,
|
||||
$parent: Int,
|
||||
$parentIn: [Int],
|
||||
$parentNotIn: [Int]
|
||||
) {
|
||||
product( id: $id ) {
|
||||
... on VariableProduct {
|
||||
price
|
||||
regularPrice
|
||||
salePrice
|
||||
variations( where: {
|
||||
minPrice: $minPrice,
|
||||
parent: $parent,
|
||||
parentIn: $parentIn,
|
||||
parentNotIn: $parentNotIn
|
||||
} ) {
|
||||
nodes {
|
||||
id
|
||||
price
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
';
|
||||
|
||||
/**
|
||||
* Assertion One
|
||||
*
|
||||
* Test query with no arguments
|
||||
*/
|
||||
$this->loginAsShopManager();
|
||||
$variables = [ 'id' => $id ];
|
||||
$response = $this->graphql( compact( 'query', 'variables' ) );
|
||||
$expected = [
|
||||
$this->expectedField( 'product.variations.nodes.#.id', $this->toRelayId( 'product_variation', $variations[0] ) ),
|
||||
$this->expectedField( 'product.variations.nodes.#.id', $this->toRelayId( 'product_variation', $variations[1] ) ),
|
||||
$this->expectedField( 'product.variations.nodes.#.id', $this->toRelayId( 'product_variation', $variations[2] ) ),
|
||||
$this->expectedField(
|
||||
'product.price',
|
||||
\wc_graphql_price( current( $prices['price'] ) )
|
||||
. ' - '
|
||||
. \wc_graphql_price( end( $prices['price'] ) )
|
||||
),
|
||||
$this->expectedField(
|
||||
'product.regularPrice',
|
||||
\wc_graphql_price( current( $prices['regular_price'] ) )
|
||||
. ' - '
|
||||
. \wc_graphql_price( end( $prices['regular_price'] ) )
|
||||
),
|
||||
$this->expectedField( 'product.salePrice', self::IS_NULL ),
|
||||
];
|
||||
|
||||
$this->assertQuerySuccessful( $response, $expected );
|
||||
|
||||
$this->clearLoaderCache( 'wc_post' );
|
||||
|
||||
/**
|
||||
* Assertion Two
|
||||
*
|
||||
* Test "minPrice" where argument
|
||||
*/
|
||||
$variables = [
|
||||
'id' => $id,
|
||||
'minPrice' => 15,
|
||||
];
|
||||
$response = $this->graphql( compact( 'query', 'variables' ) );
|
||||
$expected = [
|
||||
$this->not()->expectedField( 'product.variations.nodes.#.id', $this->toRelayId( 'product_variation', $variations[0] ) ),
|
||||
$this->expectedField( 'product.variations.nodes.#.id', $this->toRelayId( 'product_variation', $variations[1] ) ),
|
||||
$this->expectedField( 'product.variations.nodes.#.id', $this->toRelayId( 'product_variation', $variations[2] ) ),
|
||||
];
|
||||
|
||||
$this->assertQuerySuccessful( $response, $expected );
|
||||
}
|
||||
|
||||
public function testProductVariationToMediaItemConnections() {
|
||||
// Create product variations.
|
||||
$products = $this->factory->product_variation->createSome(
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user