Skip to content

Commit 32f8ba2

Browse files
authored
fix: ID resolution made consistent across all edit and delete node mu… (#902)
* fix: ID resolution made consistent across all edit and delete node mutations * chore: linter compliances met
1 parent b801133 commit 32f8ba2

12 files changed

+127
-102
lines changed

includes/data/mutation/class-order-mutation.php

Lines changed: 50 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
namespace WPGraphQL\WooCommerce\Data\Mutation;
1010

1111
use GraphQL\Error\UserError;
12+
use WPGraphQL\Utils\Utils;
1213

1314

1415
/**
@@ -22,8 +23,9 @@ class Order_Mutation {
2223
* @param \WPGraphQL\AppContext $context AppContext instance.
2324
* @param \GraphQL\Type\Definition\ResolveInfo $info ResolveInfo instance.
2425
* @param string $mutation Mutation being executed.
25-
* @param integer|null $order_id Order ID.
26-
*
26+
* @param integer|null|false $order_id Order ID.
27+
* @throws \GraphQL\Error\UserError Error locating order.
28+
*
2729
* @return boolean
2830
*/
2931
public static function authorized( $input, $context, $info, $mutation = 'create', $order_id = null ) {
@@ -34,18 +36,38 @@ public static function authorized( $input, $context, $info, $mutation = 'create'
3436
*/
3537
$post_type_object = get_post_type_object( 'shop_order' );
3638

37-
return apply_filters(
38-
"graphql_woocommerce_authorized_to_{$mutation}_orders",
39-
current_user_can(
40-
'delete' === $mutation
41-
? $post_type_object->cap->delete_posts
42-
: $post_type_object->cap->edit_posts
43-
),
44-
$order_id,
45-
$input,
46-
$context,
47-
$info
48-
);
39+
if ( ! $order_id ) {
40+
return apply_filters(
41+
"graphql_woocommerce_authorized_to_{$mutation}_orders",
42+
current_user_can( $post_type_object->cap->edit_posts ),
43+
$order_id,
44+
$input,
45+
$context,
46+
$info
47+
);
48+
}
49+
50+
/** @var false|\WC_Order $order */
51+
$order = \wc_get_order( $order_id );
52+
if ( false === $order ) {
53+
throw new UserError(
54+
sprintf(
55+
/* translators: %d: Order ID */
56+
__( 'Failed to find order with ID of %d.', 'wp-graphql-woocommerce' ),
57+
$order_id
58+
)
59+
);
60+
}
61+
62+
$post_type = get_post_type( $order_id );
63+
if ( false === $post_type ) {
64+
throw new UserError( __( 'Failed to identify the post type of the order.', 'wp-graphql-woocommerce' ) );
65+
}
66+
67+
// Return true if user is owner or admin.
68+
$is_owner = 0 !== get_current_user_id() && $order->get_customer_id() === get_current_user_id();
69+
$is_admin = \wc_rest_check_post_permissions( $post_type, 'edit', $order_id );
70+
return $is_owner || $is_admin;
4971
}
5072

5173
/**
@@ -565,25 +587,26 @@ public static function apply_coupons( $order_id, $coupons ) {
565587
/**
566588
* Validates order customer
567589
*
568-
* @param array $input Input data describing order.
590+
* @param string $customer_id ID of customer for order.
569591
*
570592
* @return bool
571593
*/
572-
public static function validate_customer( $input ) {
573-
if ( ! empty( $input['customerId'] ) ) {
574-
// Make sure customer exists.
575-
if ( false === get_user_by( 'id', $input['customerId'] ) ) {
576-
return false;
577-
}
578-
// Make sure customer is part of blog.
579-
if ( is_multisite() && ! is_user_member_of_blog( $input['customerId'] ) ) {
580-
add_user_to_blog( get_current_blog_id(), $input['customerId'], 'customer' );
581-
}
594+
public static function validate_customer( $customer_id ) {
595+
$id = Utils::get_database_id_from_id( $customer_id );
596+
if ( ! $id ) {
597+
return false;
598+
}
582599

583-
return true;
600+
if ( false === get_user_by( 'id', $id ) ) {
601+
return false;
584602
}
585603

586-
return false;
604+
// Make sure customer is part of blog.
605+
if ( is_multisite() && ! is_user_member_of_blog( $id ) ) {
606+
add_user_to_blog( get_current_blog_id(), $id, 'customer' );
607+
}
608+
609+
return true;
587610
}
588611

589612
/**

includes/mutation/class-coupon-create.php

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212

1313
use GraphQL\Error\UserError;
1414
use GraphQL\Type\Definition\ResolveInfo;
15-
use GraphQLRelay\Relay;
1615
use WPGraphQL\AppContext;
16+
use WPGraphQL\Utils\Utils;
1717
use WPGraphQL\WooCommerce\Data\Mutation\Coupon_Mutation;
1818
use WPGraphQL\WooCommerce\Model\Coupon;
1919

@@ -163,16 +163,14 @@ public static function get_output_fields() {
163163
*/
164164
public static function mutate_and_get_payload( $input, AppContext $context, ResolveInfo $info ) {
165165
// Retrieve order ID.
166-
$coupon_id = 0;
167-
if ( ! empty( $input['id'] ) && is_numeric( $input['id'] ) ) {
168-
$coupon_id = absint( $input['id'] );
169-
} elseif ( ! empty( $input['id'] ) ) {
170-
$id_components = Relay::fromGlobalId( $input['id'] );
171-
if ( empty( $id_components['id'] ) || empty( $id_components['type'] ) ) {
172-
throw new UserError( __( 'The "id" provided is invalid', 'wp-graphql-woocommerce' ) );
173-
}
166+
if ( ! empty( $input['id'] ) ) {
167+
$coupon_id = Utils::get_database_id_from_id( $input['id'] );
168+
} else {
169+
$coupon_id = 0;
170+
}
174171

175-
$coupon_id = absint( $id_components['id'] );
172+
if ( false === $coupon_id ) {
173+
throw new UserError( __( 'Coupon ID provided is invalid. Please check input and try again.', 'wp-graphql-woocommerce' ) );
176174
}
177175

178176
$coupon = new \WC_Coupon( $coupon_id );

includes/mutation/class-coupon-delete.php

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212

1313
use GraphQL\Error\UserError;
1414
use GraphQL\Type\Definition\ResolveInfo;
15-
use GraphQLRelay\Relay;
1615
use WPGraphQL\AppContext;
16+
use WPGraphQL\Utils\Utils;
1717
use WPGraphQL\WooCommerce\Model\Coupon;
1818

1919
/**
@@ -87,17 +87,11 @@ public static function get_output_fields() {
8787
*/
8888
public static function mutate_and_get_payload( $input, AppContext $context, ResolveInfo $info ) {
8989
// Retrieve order ID.
90-
$coupon_id = 0;
91-
if ( ! empty( $input['id'] ) && is_numeric( $input['id'] ) ) {
92-
$coupon_id = absint( $input['id'] );
93-
} elseif ( ! empty( $input['id'] ) ) {
94-
$id_components = Relay::fromGlobalId( $input['id'] );
95-
if ( empty( $id_components['id'] ) || empty( $id_components['type'] ) ) {
96-
throw new UserError( __( 'The "id" provided is invalid', 'wp-graphql-woocommerce' ) );
97-
}
98-
99-
$coupon_id = absint( $id_components['id'] );
90+
$coupon_id = Utils::get_database_id_from_id( $input['id'] );
91+
if ( empty( $coupon_id ) ) {
92+
throw new UserError( __( 'Coupon ID provided is missing or invalid. Please check input and try again.', 'wp-graphql-woocommerce' ) );
10093
}
94+
10195
$coupon = new Coupon( $coupon_id );
10296

10397
if ( ! $coupon->ID ) {

includes/mutation/class-order-create.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ public static function mutate_and_get_payload() {
167167
WC()->payment_gateways();
168168

169169
// Validate customer ID, if set.
170-
if ( ! empty( $input['customerId'] ) && ! Order_Mutation::validate_customer( $input ) ) {
170+
if ( ! empty( $input['customerId'] ) && ! Order_Mutation::validate_customer( $input['customerId'] ) ) {
171171
throw new UserError( __( 'Customer ID is invalid.', 'wp-graphql-woocommerce' ) );
172172
}
173173

includes/mutation/class-order-delete-items.php

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212

1313
use GraphQL\Error\UserError;
1414
use GraphQL\Type\Definition\ResolveInfo;
15-
use GraphQLRelay\Relay;
1615
use WPGraphQL\AppContext;
16+
use WPGraphQL\Utils\Utils;
1717
use WPGraphQL\WooCommerce\Data\Mutation\Order_Mutation;
1818
use WPGraphQL\WooCommerce\Model\Order;
1919

@@ -47,11 +47,12 @@ public static function get_input_fields() {
4747
[
4848
'id' => [
4949
'type' => 'ID',
50-
'description' => __( 'Order global ID', 'wp-graphql-woocommerce' ),
50+
'description' => __( 'Database ID or global ID of the order', 'wp-graphql-woocommerce' ),
5151
],
5252
'orderId' => [
53-
'type' => 'Int',
54-
'description' => __( 'Order WP ID', 'wp-graphql-woocommerce' ),
53+
'type' => 'Int',
54+
'description' => __( 'Order WP ID', 'wp-graphql-woocommerce' ),
55+
'deprecationReason' => __( 'Use "id" field instead.', 'wp-graphql-woocommerce' ),
5556
],
5657
'itemIds' => [
5758
'type' => [ 'list_of' => 'Int' ],
@@ -87,20 +88,20 @@ public static function mutate_and_get_payload() {
8788
// Retrieve order ID.
8889
$order_id = null;
8990
if ( ! empty( $input['id'] ) ) {
90-
$id_components = Relay::fromGlobalId( $input['id'] );
91-
if ( empty( $id_components['id'] ) || empty( $id_components['type'] ) ) {
92-
throw new UserError( __( 'The "id" provided is invalid', 'wp-graphql-woocommerce' ) );
93-
}
94-
$order_id = absint( $id_components['id'] );
91+
$order_id = Utils::get_database_id_from_id( $input['id'] );
9592
} elseif ( ! empty( $input['orderId'] ) ) {
9693
$order_id = absint( $input['orderId'] );
9794
} else {
98-
throw new UserError( __( 'No order ID provided.', 'wp-graphql-woocommerce' ) );
95+
throw new UserError( __( 'Order ID provided is missing or invalid. Please check input and try again.', 'wp-graphql-woocommerce' ) );
96+
}
97+
98+
if ( ! $order_id ) {
99+
throw new UserError( __( 'Order ID provided is invalid. Please check input and try again.', 'wp-graphql-woocommerce' ) );
99100
}
100101

101102
// Check if authorized to delete items on this order.
102103
if ( ! Order_Mutation::authorized( $input, $context, $info, 'delete-items', $order_id ) ) {
103-
throw new UserError( __( 'User does not have the capabilities necessary to delete an order.', 'wp-graphql-woocommerce' ) );
104+
throw new UserError( __( 'User does not have the capabilities necessary to delete order items.', 'wp-graphql-woocommerce' ) );
104105
}
105106

106107
// Confirm item IDs.

includes/mutation/class-order-delete.php

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@
1212

1313
use GraphQL\Error\UserError;
1414
use GraphQL\Type\Definition\ResolveInfo;
15-
use GraphQLRelay\Relay;
1615
use WC_Order_Factory;
1716
use WPGraphQL\AppContext;
17+
use WPGraphQL\Utils\Utils;
1818
use WPGraphQL\WooCommerce\Data\Mutation\Order_Mutation;
1919
use WPGraphQL\WooCommerce\Model\Order;
2020

@@ -48,11 +48,12 @@ public static function get_input_fields() {
4848
[
4949
'id' => [
5050
'type' => 'ID',
51-
'description' => __( 'Order global ID', 'wp-graphql-woocommerce' ),
51+
'description' => __( 'Database ID or global ID of the order', 'wp-graphql-woocommerce' ),
5252
],
5353
'orderId' => [
54-
'type' => 'Int',
55-
'description' => __( 'Order WP ID', 'wp-graphql-woocommerce' ),
54+
'type' => 'Int',
55+
'description' => __( 'Order WP ID', 'wp-graphql-woocommerce' ),
56+
'deprecationReason' => __( 'Use "id" field instead.', 'wp-graphql-woocommerce' ),
5657
],
5758
'forceDelete' => [
5859
'type' => 'Boolean',
@@ -86,17 +87,17 @@ public static function get_output_fields() {
8687
public static function mutate_and_get_payload() {
8788
return static function ( $input, AppContext $context, ResolveInfo $info ) {
8889
// Retrieve order ID.
89-
$order_id = null;
90+
$order_id = false;
9091
if ( ! empty( $input['id'] ) ) {
91-
$id_components = Relay::fromGlobalId( $input['id'] );
92-
if ( empty( $id_components['id'] ) || empty( $id_components['type'] ) ) {
93-
throw new UserError( __( 'The "id" provided is invalid', 'wp-graphql-woocommerce' ) );
94-
}
95-
$order_id = absint( $id_components['id'] );
92+
$order_id = Utils::get_database_id_from_id( $input['id'] );
9693
} elseif ( ! empty( $input['orderId'] ) ) {
9794
$order_id = absint( $input['orderId'] );
9895
} else {
99-
throw new UserError( __( 'No order ID provided.', 'wp-graphql-woocommerce' ) );
96+
throw new UserError( __( 'Order ID provided is missing or invalid. Please check input and try again.', 'wp-graphql-woocommerce' ) );
97+
}
98+
99+
if ( ! $order_id ) {
100+
throw new UserError( __( 'Order ID provided is invalid. Please check input and try again.', 'wp-graphql-woocommerce' ) );
100101
}
101102

102103
// Check if authorized to delete this order.

includes/mutation/class-order-update.php

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@
1212

1313
use GraphQL\Error\UserError;
1414
use GraphQL\Type\Definition\ResolveInfo;
15-
use GraphQLRelay\Relay;
1615
use WC_Order_Factory;
1716
use WPGraphQL\AppContext;
17+
use WPGraphQL\Utils\Utils;
1818
use WPGraphQL\WooCommerce\Data\Mutation\Order_Mutation;
1919
use WPGraphQL\WooCommerce\Model\Order;
2020

@@ -49,15 +49,16 @@ public static function get_input_fields() {
4949
[
5050
'id' => [
5151
'type' => 'ID',
52-
'description' => __( 'Order global ID', 'wp-graphql-woocommerce' ),
52+
'description' => __( 'Database ID or global ID of the order', 'wp-graphql-woocommerce' ),
5353
],
5454
'orderId' => [
55-
'type' => 'Int',
56-
'description' => __( 'Order WP ID', 'wp-graphql-woocommerce' ),
55+
'type' => 'Int',
56+
'description' => __( 'Order WP ID', 'wp-graphql-woocommerce' ),
57+
'deprecationReason' => __( 'Use "id" field instead.', 'wp-graphql-woocommerce' ),
5758
],
5859
'customerId' => [
59-
'type' => 'Int',
60-
'description' => __( 'Order customer ID', 'wp-graphql-woocommerce' ),
60+
'type' => 'ID',
61+
'description' => __( 'Database ID or global ID of the customer for the order', 'wp-graphql-woocommerce' ),
6162
],
6263
]
6364
);
@@ -89,15 +90,15 @@ public static function mutate_and_get_payload() {
8990
// Retrieve order ID.
9091
$order_id = null;
9192
if ( ! empty( $input['id'] ) ) {
92-
$id_components = Relay::fromGlobalId( $input['id'] );
93-
if ( empty( $id_components['id'] ) || empty( $id_components['type'] ) ) {
94-
throw new UserError( __( 'The "id" provided is invalid', 'wp-graphql-woocommerce' ) );
95-
}
96-
$order_id = absint( $id_components['id'] );
93+
$order_id = Utils::get_database_id_from_id( $input['id'] );
9794
} elseif ( ! empty( $input['orderId'] ) ) {
9895
$order_id = absint( $input['orderId'] );
9996
} else {
100-
throw new UserError( __( 'No order ID provided.', 'wp-graphql-woocommerce' ) );
97+
throw new UserError( __( 'Order ID provided is missing or invalid. Please check input and try again.', 'wp-graphql-woocommerce' ) );
98+
}
99+
100+
if ( ! $order_id ) {
101+
throw new UserError( __( 'Order ID provided is invalid. Please check input and try again.', 'wp-graphql-woocommerce' ) );
101102
}
102103

103104
// Check if authorized to update this order.
@@ -133,7 +134,7 @@ public static function mutate_and_get_payload() {
133134
\WC()->payment_gateways();
134135

135136
// Validate customer ID.
136-
if ( ! empty( $input['customerId'] ) && ! Order_Mutation::validate_customer( $input ) ) {
137+
if ( ! empty( $input['customerId'] ) && ! Order_Mutation::validate_customer( $input['customerId'] ) ) {
137138
throw new UserError( __( 'New customer ID is invalid.', 'wp-graphql-woocommerce' ) );
138139
}
139140

@@ -147,7 +148,7 @@ public static function mutate_and_get_payload() {
147148
}
148149

149150
// Actions for after the order is saved.
150-
if ( true === $input['isPaid'] ) {
151+
if ( isset( $input['isPaid'] ) && true === $input['isPaid'] ) {
151152
$order->payment_complete(
152153
! empty( $input['transactionId'] )
153154
? $input['transactionId']

includes/mutation/class-review-delete-restore.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use GraphQL\Type\Definition\ResolveInfo;
1515
use GraphQLRelay\Relay;
1616
use WPGraphQL\AppContext;
17+
use WPGraphQL\Utils\Utils;
1718

1819
/**
1920
* Class Review_Delete_Restore
@@ -130,12 +131,12 @@ public static function get_output_fields( $restore = false ) {
130131
public static function mutate_and_get_payload() {
131132
return static function ( $input, AppContext $context, ResolveInfo $info ) {
132133
// Retrieve the product review rating for the payload.
133-
$id_parts = Relay::fromGlobalId( $input['id'] );
134-
if ( empty( $id_parts['id'] ) ) {
134+
$id = Utils::get_database_id_from_id( $input['id'] );
135+
if ( ! $id ) {
135136
throw new UserError( __( 'Invalid Product Review ID provided', 'wp-graphql-woocommerce' ) );
136137
}
137138

138-
$rating = get_comment_meta( absint( $id_parts['id'] ), 'rating' );
139+
$rating = get_comment_meta( absint( $id ), 'rating' );
139140

140141
// @codingStandardsIgnoreLine
141142
switch ( $info->fieldName ) {

0 commit comments

Comments
 (0)