• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

wp-graphql / wp-graphql-woocommerce / 23675172456

28 Mar 2026 02:10AM UTC coverage: 70.983% (-18.4%) from 89.424%
23675172456

Pull #1003

github

web-flow
Merge 05339093d into 6fb7b226f
Pull Request #1003: devops: WC email template tests, COT cursor HPOS fix, checkout account auth

71 of 81 new or added lines in 5 files covered. (87.65%)

3346 existing lines in 124 files now uncovered.

12576 of 17717 relevant lines covered (70.98%)

55.38 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

40.38
/includes/class-compatibility.php
1
<?php
2
/**
3
 * Compatibility integrations with third-party plugins.
4
 *
5
 * @package \WPGraphQL\WooCommerce
6
 * @since   TBD
7
 */
8

9
namespace WPGraphQL\WooCommerce;
10

11
use GraphQL\Error\UserError;
12
use WPGraphQL\WooCommerce\Model\Customer;
13

14
/**
15
 * Class Compatibility
16
 */
17
class Compatibility {
18
        /**
19
         * Register all compatibility filters.
20
         *
21
         * @return void
22
         */
23
        public static function setup() {
UNCOV
24
                self::register_wc_admin_settings();
×
UNCOV
25
                self::add_acf_filters();
×
UNCOV
26
                self::add_jwt_auth_filters();
×
UNCOV
27
                self::add_stripe_gateway_filters();
×
UNCOV
28
                self::add_swp_filters();
×
29
        }
30

31
        /**
32
         * Register WC admin settings for GraphQL requests.
33
         *
34
         * WooCommerce only registers settings groups during rest_api_init.
35
         * We need them available for GraphQL settings queries and mutations.
36
         *
37
         * @return void
38
         */
39
        private static function register_wc_admin_settings() {
UNCOV
40
                if ( method_exists( WC(), 'register_wp_admin_settings' ) ) {
×
UNCOV
41
                        WC()->register_wp_admin_settings(); // @phpstan-ignore method.private (public since WC 9.0)
×
42
                }
43
        }
44

45
        /**
46
         * Register WPGraphQL ACF compatibility filters.
47
         *
48
         * @return void
49
         */
50
        private static function add_acf_filters() {
UNCOV
51
                add_filter( 'graphql_acf_get_root_id', [ self::class, 'resolve_crud_root_id' ], 10, 2 );
×
UNCOV
52
                add_filter( 'graphql_acf_post_object_source', [ self::class, 'resolve_post_object_source' ], 10, 2 );
×
53
        }
54

55
        /**
56
         * Resolve post object ID from CRUD object Model.
57
         *
58
         * @param integer|null $id    Post object database ID.
59
         * @param mixed        $root  Root resolver.
60
         *
61
         * @return integer|null
62
         */
63
        public static function resolve_crud_root_id( $id, $root ) {
64
                if ( $root instanceof Model\WC_Post ) {
×
65
                        $id = absint( $root->ID );
×
66
                }
67

68
                return $id;
×
69
        }
70

71
        /**
72
         * Filters ACF "post_object" field type resolver to ensure that
73
         * the proper Type source is provided for WooCommerce CPTs.
74
         *
75
         * @param mixed|null $source  source of the data being provided.
76
         * @param mixed|null $value  Post ID.
77
         *
78
         * @return mixed|null
79
         */
80
        public static function resolve_post_object_source( $source, $value ) {
81
                $post = get_post( $value );
×
82
                if ( $post instanceof \WP_Post ) {
×
83
                        switch ( $post->post_type ) {
×
84
                                case 'shop_coupon':
×
85
                                        $source = new Model\Coupon( $post->ID );
×
86
                                        break;
×
87
                                case 'shop_order':
×
88
                                        $source = new Model\Order( $post->ID );
×
89
                                        break;
×
90
                                case 'product':
×
91
                                        $source = new Model\Product( $post->ID );
×
92
                                        break;
×
93
                                case 'product_variation':
×
94
                                        $source = new Model\Product_Variation( $post->ID );
×
95
                                        break;
×
96
                        }
97
                }
98

99
                return $source;
×
100
        }
101

102
        /**
103
         * Get the JWT auth class if available.
104
         *
105
         * @return string|null
106
         */
107
        public static function get_auth_class() {
108
                if ( class_exists( 'WPGraphQL\JWT_Authentication\Auth' ) ) {
8✔
109
                        return \WPGraphQL\JWT_Authentication\Auth::class;
8✔
110
                } elseif ( class_exists( 'WPGraphQL\Login\Auth\TokenManager' ) ) {
×
111
                        return \WPGraphQL\Login\Auth\TokenManager::class;
×
112
                }
113

114
                return null;
×
115
        }
116

117
        /**
118
         * Get the auth token for a user.
119
         *
120
         * @param \WP_User $user The user object.
121
         *
122
         * @throws \GraphQL\Error\UserError If the token cannot be retrieved.
123
         *
124
         * @return string|null
125
         */
126
        public static function get_auth_token( \WP_User $user ) {
127
                $auth_class = self::get_auth_class();
8✔
128

129
                if ( ! $auth_class ) {
8✔
130
                        return null;
×
131
                }
132

133
                /**
134
                 * @var \WP_Error|string|null $token
135
                 */
136
                $token = null;
8✔
137
                if ( 'WPGraphQL\JWT_Authentication\Auth' === $auth_class ) {
8✔
138
                        $token = $auth_class::get_token( $user );
8✔
139
                } elseif ( 'WPGraphQL\Login\Auth\TokenManager' === $auth_class ) {
×
140
                        $token = $auth_class::get_auth_token( $user );
×
141
                }
142

143
                if ( is_wp_error( $token ) ) {
8✔
144
                        throw new UserError( $token->get_error_message() );
×
145
                }
146

147
                return $token;
8✔
148
        }
149

150
        /**
151
         * Get the refresh token for a user.
152
         *
153
         * @param \WP_User $user The user object.
154
         *
155
         * @throws \GraphQL\Error\UserError If the token cannot be retrieved.
156
         *
157
         * @return string|null
158
         */
159
        public static function get_refresh_token( \WP_User $user ) {
160
                $auth_class = self::get_auth_class();
8✔
161

162
                if ( ! $auth_class ) {
8✔
163
                        return null;
×
164
                }
165

166
                /**
167
                 * @var \WP_Error|string|null $refresh_token
168
                 */
169
                $refresh_token = $auth_class::get_refresh_token( $user );
8✔
170

171
                if ( is_wp_error( $refresh_token ) ) {
8✔
172
                        throw new UserError( $refresh_token->get_error_message() );
×
173
                }
174

175
                return $refresh_token;
8✔
176
        }
177

178
        /**
179
         * Register WPGraphQL JWT Authentication compatibility filters.
180
         *
181
         * @return void
182
         */
183
        private static function add_jwt_auth_filters() {
UNCOV
184
                $auth_class = self::get_auth_class();
×
UNCOV
185
                if ( is_null( $auth_class ) ) {
×
186
                        return;
×
187
                }
188

UNCOV
189
                add_filter( 'graphql_jwt_user_types', [ self::class, 'add_customer_to_jwt_user_types' ], 10 );
×
UNCOV
190
                add_filter( 'graphql_registerCustomerPayload_fields', [ self::class, 'add_jwt_output_fields' ], 10, 3 );
×
UNCOV
191
                add_filter( 'graphql_updateCustomerPayload_fields', [ self::class, 'add_jwt_output_fields' ], 10, 3 );
×
UNCOV
192
                add_action( 'graphql_register_types', [ self::class, 'add_customer_to_login_payload' ], 10 );
×
193
        }
194

195
        /**
196
         * Adds Customer type to the JWT User type list.
197
         *
198
         * @param array $types JWT User types.
199
         * @return array
200
         */
201
        public static function add_customer_to_jwt_user_types( array $types ) {
202
                $types[] = 'Customer';
110✔
203

204
                return $types;
110✔
205
        }
206

207
        /**
208
         * Adds all JWT related fields to the Customer mutation output.
209
         *
210
         * @param array                             $fields         Mutation output field definitions.
211
         * @param \WPGraphQL\Type\WPInputObjectType $object_type    The WPInputObjectType the fields are be added to.
212
         * @param \WPGraphQL\Registry\TypeRegistry  $type_registry  TypeRegistry instance.
213
         *
214
         * @return array
215
         */
216
        public static function add_jwt_output_fields( $fields, $object_type, $type_registry ): array {
217
                return array_merge(
55✔
218
                        $fields,
55✔
219
                        [
55✔
220
                                'authToken'    => [
55✔
221
                                        'type'        => $type_registry->get_type( 'String' ),
55✔
222
                                        'description' => __( 'JWT Token that can be used in future requests for Authentication', 'wp-graphql-woocommerce' ),
55✔
223
                                        'resolve'     => static function ( $payload ) {
55✔
224
                                                $user = get_user_by( 'ID', $payload['id'] );
8✔
225

226
                                                if ( ! $user ) {
8✔
227
                                                        throw new UserError( __( 'User not found.', 'wp-graphql-woocommerce' ) );
×
228
                                                }
229

230
                                                return self::get_auth_token( $user );
8✔
231
                                        },
55✔
232
                                ],
55✔
233
                                'refreshToken' => [
55✔
234
                                        'type'        => $type_registry->get_type( 'String' ),
55✔
235
                                        'description' => __( 'A JWT token that can be used in future requests to get a refreshed jwtAuthToken. If the refresh token used in a request is revoked or otherwise invalid, a valid Auth token will NOT be issued in the response headers.', 'wp-graphql-woocommerce' ),
55✔
236
                                        'resolve'     => static function ( $payload ) {
55✔
237
                                                $user = get_user_by( 'ID', $payload['id'] );
8✔
238

239
                                                if ( ! $user ) {
8✔
240
                                                        throw new UserError( __( 'User not found.', 'wp-graphql-woocommerce' ) );
×
241
                                                }
242

243
                                                return self::get_refresh_token( $user );
8✔
244
                                        },
55✔
245
                                ],
55✔
246
                        ]
55✔
247
                );
55✔
248
        }
249

250
        /**
251
         * Adds "customer" field to "login" mutation payload.
252
         *
253
         * @return void
254
         */
255
        public static function add_customer_to_login_payload() {
256
                register_graphql_field(
110✔
257
                        'LoginPayload',
110✔
258
                        'customer',
110✔
259
                        [
110✔
260
                                'type'        => 'Customer',
110✔
261
                                'description' => __( 'Customer object of authenticated user.', 'wp-graphql-woocommerce' ),
110✔
262
                                'resolve'     => static function ( $payload ) {
110✔
UNCOV
263
                                        $id = $payload['id'];
×
UNCOV
264
                                        return new Customer( $id );
×
265
                                },
110✔
266
                        ]
110✔
267
                );
110✔
268

269
                if ( ! wc_graphql_is_session_handler_disabled() ) {
110✔
270
                        $token_type = woographql_setting( 'set_session_token_type', 'legacy' );
110✔
271
                        if ( in_array( $token_type, [ 'legacy', 'both' ], true ) ) {
110✔
272
                                register_graphql_field(
110✔
273
                                        'LoginPayload',
110✔
274
                                        'sessionToken',
110✔
275
                                        [
110✔
276
                                                'type'        => 'String',
110✔
277
                                                'description' => __( 'A JWT token that can be used in future requests to for WooCommerce session identification', 'wp-graphql-woocommerce' ),
110✔
278
                                                'resolve'     => static function () {
110✔
279
                                                        /** @var \WPGraphQL\WooCommerce\Utils\QL_Session_Handler $session */
UNCOV
280
                                                        $session = \WC()->session;
×
281

UNCOV
282
                                                        return apply_filters( 'graphql_customer_session_token', $session->build_token() );
×
283
                                                },
110✔
284
                                        ]
110✔
285
                                );
110✔
286
                        }
287
                        if ( in_array( $token_type, [ 'store-api', 'both' ], true ) ) {
110✔
UNCOV
288
                                register_graphql_field(
×
UNCOV
289
                                        'LoginPayload',
×
UNCOV
290
                                        'cartToken',
×
UNCOV
291
                                        [
×
UNCOV
292
                                                'type'        => 'String',
×
UNCOV
293
                                                'description' => __( 'A JWT token that can be used in future requests to for WooCommerce session identification', 'wp-graphql-woocommerce' ),
×
UNCOV
294
                                                'resolve'     => static function () {
×
295
                                                        /** @var \WPGraphQL\WooCommerce\Utils\QL_Session_Handler $session */
296
                                                        $session = \WC()->session;
×
297

298
                                                        return apply_filters( 'graphql_customer_session_token', $session->build_cart_token() );
×
UNCOV
299
                                                },
×
UNCOV
300
                                        ]
×
UNCOV
301
                                );
×
302
                        }
303
                }
304
        }
305

306
        /**
307
         * Register WooCommerce Stripe Gateway compatibility filters.
308
         *
309
         * @return void
310
         */
311
        private static function add_stripe_gateway_filters() {
UNCOV
312
                add_filter( 'graphql_stripe_process_payment_args', [ self::class, 'woocommerce_gateway_stripe_args' ], 10, 2 );
×
313
        }
314

315
        /**
316
         * Adds extra arguments to the Stripe Gateway process payment call.
317
         *
318
         * @param array  $gateway_args    Arguments to be passed to the gateway `process_payment` method.
319
         * @param string $payment_method  Payment gateway ID.
320
         *
321
         * @return array
322
         */
323
        public static function woocommerce_gateway_stripe_args( $gateway_args, $payment_method ) {
324
                /** @var false|\WC_Order|\WC_Order_Refund $order */
325
                $order = wc_get_order( $gateway_args[0] );
×
326
                if ( false === $order ) {
×
327
                        return $gateway_args;
×
328
                }
329

330
                $stripe_source_id = $order->get_meta( '_stripe_source_id' );
×
331
                if ( 'stripe' === $payment_method && ! empty( $stripe_source_id ) ) {
×
332
                        $gateway_args = [
×
333
                                $gateway_args[0],
×
334
                                true,
×
335
                                false,
×
336
                                false,
×
337
                                true,
×
338
                        ];
×
339
                }
340

341
                return $gateway_args;
×
342
        }
343

344
        /**
345
         * Register SearchWP/QL Search compatibility filters.
346
         *
347
         * @return void
348
         */
349
        private static function add_swp_filters() {
UNCOV
350
                add_filter( 'graphql_swp_result_possible_types', [ self::class, 'searchwp_result_possible_types' ] );
×
351
        }
352

353
        /**
354
         * Adds product types to QL Search SWPResult possible types.
355
         *
356
         * @param array $type_names SWPResults possible types.
357
         *
358
         * @return array
359
         */
360
        public static function searchwp_result_possible_types( array $type_names ) {
361
                if ( in_array( 'Product', $type_names, true ) ) {
×
362
                        $type_names = array_merge(
×
363
                                array_filter(
×
364
                                        $type_names,
×
365
                                        static function ( $type_name ) {
×
366
                                                return 'Product' !== $type_name;
×
367
                                        }
×
368
                                ),
×
369
                                [
×
370
                                        'SimpleProduct',
×
371
                                        'VariableProduct',
×
372
                                        'GroupProduct',
×
373
                                        'ExternalProduct',
×
374
                                ]
×
375
                        );
×
376
                }
377

378
                return $type_names;
×
379
        }
380
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc