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

wp-graphql / wp-graphql-woocommerce / 27452430870

13 Jun 2026 01:26AM UTC coverage: 91.8%. Remained the same
27452430870

Pull #1019

github

web-flow
Merge f03617ca3 into 2ce9424e1
Pull Request #1019: fix: address WordPress.org plugin review (rename + prefixing + headers)

1330 of 1587 new or added lines in 201 files covered. (83.81%)

1 existing line in 1 file now uncovered.

18528 of 20183 relevant lines covered (91.8%)

152.68 hits per line

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

62.05
/includes/class-compatibility.php
1
<?php
2
/**
3
 * Compatibility integrations with third-party plugins.
4
 *
5
 * @package \WPGraphQL\WooCommerce
6
 * @since   1.0.0
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() {
24
                self::register_wc_admin_settings();
33✔
25
                self::add_acf_filters();
33✔
26
                self::add_jwt_auth_filters();
33✔
27
                self::add_stripe_gateway_filters();
33✔
28
                self::add_swp_filters();
33✔
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() {
40
                if ( method_exists( WC(), 'register_wp_admin_settings' ) ) {
33✔
41
                        WC()->register_wp_admin_settings(); // @phpstan-ignore method.private (public since WC 9.0)
33✔
42
                }
43
        }
44

45
        /**
46
         * Register WPGraphQL ACF compatibility filters.
47
         *
48
         * @return void
49
         */
50
        private static function add_acf_filters() {
51
                add_filter( 'graphql_acf_get_root_id', [ self::class, 'resolve_crud_root_id' ], 10, 2 );
33✔
52
                add_filter( 'graphql_acf_post_object_source', [ self::class, 'resolve_post_object_source' ], 10, 2 );
33✔
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' ) ) {
41✔
109
                        return \WPGraphQL\JWT_Authentication\Auth::class;
41✔
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() {
184
                $auth_class = self::get_auth_class();
33✔
185
                if ( is_null( $auth_class ) ) {
33✔
186
                        return;
×
187
                }
188

189
                add_filter( 'graphql_jwt_user_types', [ self::class, 'add_customer_to_jwt_user_types' ], 10 );
33✔
190
                add_filter( 'graphql_registerCustomerPayload_fields', [ self::class, 'add_jwt_output_fields' ], 10, 3 );
33✔
191
                add_filter( 'graphql_updateCustomerPayload_fields', [ self::class, 'add_jwt_output_fields' ], 10, 3 );
33✔
192
                add_action( 'graphql_register_types', [ self::class, 'add_customer_to_login_payload' ], 10 );
33✔
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';
298✔
203

204
                return $types;
298✔
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(
151✔
218
                        $fields,
151✔
219
                        [
151✔
220
                                'authToken'    => [
151✔
221
                                        'type'        => $type_registry->get_type( 'String' ),
151✔
222
                                        'description' => static function () {
151✔
223
                                                return __( 'JWT Token that can be used in future requests for Authentication', 'graphql-for-ecommerce' );
2✔
224
                                        },
151✔
225
                                        'resolve'     => static function ( $payload ) {
151✔
226
                                                $user = get_user_by( 'ID', $payload['id'] );
8✔
227

228
                                                if ( ! $user ) {
8✔
NEW
229
                                                        throw new UserError( __( 'User not found.', 'graphql-for-ecommerce' ) );
×
230
                                                }
231

232
                                                return self::get_auth_token( $user );
8✔
233
                                        },
151✔
234
                                ],
151✔
235
                                'refreshToken' => [
151✔
236
                                        'type'        => $type_registry->get_type( 'String' ),
151✔
237
                                        'description' => static function () {
151✔
238
                                                return __( '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.', 'graphql-for-ecommerce' );
2✔
239
                                        },
151✔
240
                                        'resolve'     => static function ( $payload ) {
151✔
241
                                                $user = get_user_by( 'ID', $payload['id'] );
8✔
242

243
                                                if ( ! $user ) {
8✔
NEW
244
                                                        throw new UserError( __( 'User not found.', 'graphql-for-ecommerce' ) );
×
245
                                                }
246

247
                                                return self::get_refresh_token( $user );
8✔
248
                                        },
151✔
249
                                ],
151✔
250
                        ]
151✔
251
                );
151✔
252
        }
253

254
        /**
255
         * Adds "customer" field to "login" mutation payload.
256
         *
257
         * @return void
258
         */
259
        public static function add_customer_to_login_payload() {
260
                register_graphql_field(
298✔
261
                        'LoginPayload',
298✔
262
                        'customer',
298✔
263
                        [
298✔
264
                                'type'        => 'Customer',
298✔
265
                                'description' => static function () {
298✔
266
                                        return __( 'Customer object of authenticated user.', 'graphql-for-ecommerce' );
2✔
267
                                },
298✔
268
                                'resolve'     => static function ( $payload ) {
298✔
269
                                        $id = $payload['id'];
15✔
270
                                        return new Customer( $id );
15✔
271
                                },
298✔
272
                        ]
298✔
273
                );
298✔
274

275
                if ( ! wc_graphql_is_session_handler_disabled() ) {
298✔
276
                        $token_type = woographql_setting( 'set_session_token_type', 'legacy' );
298✔
277
                        if ( in_array( $token_type, [ 'legacy', 'both' ], true ) ) {
298✔
278
                                register_graphql_field(
297✔
279
                                        'LoginPayload',
297✔
280
                                        'sessionToken',
297✔
281
                                        [
297✔
282
                                                'type'        => 'String',
297✔
283
                                                'description' => static function () {
297✔
284
                                                        return __( 'A JWT token that can be used in future requests to for WooCommerce session identification', 'graphql-for-ecommerce' );
2✔
285
                                                },
297✔
286
                                                'resolve'     => static function () {
297✔
287
                                                        /** @var \WPGraphQL\WooCommerce\Utils\QL_Session_Handler $session */
288
                                                        $session = \WC()->session;
15✔
289

290
                                                        return apply_filters( 'graphql_customer_session_token', $session->build_token() );
15✔
291
                                                },
297✔
292
                                        ]
297✔
293
                                );
297✔
294
                        }
295
                        if ( in_array( $token_type, [ 'store-api', 'both' ], true ) ) {
298✔
296
                                register_graphql_field(
2✔
297
                                        'LoginPayload',
2✔
298
                                        'cartToken',
2✔
299
                                        [
2✔
300
                                                'type'        => 'String',
2✔
301
                                                'description' => static function () {
2✔
NEW
302
                                                        return __( 'A JWT token that can be used in future requests to for WooCommerce session identification', 'graphql-for-ecommerce' );
×
303
                                                },
2✔
304
                                                'resolve'     => static function () {
2✔
305
                                                        /** @var \WPGraphQL\WooCommerce\Utils\QL_Session_Handler $session */
306
                                                        $session = \WC()->session;
×
307

308
                                                        return apply_filters( 'graphql_customer_session_token', $session->build_cart_token() );
×
309
                                                },
2✔
310
                                        ]
2✔
311
                                );
2✔
312
                        }
313
                }
314
        }
315

316
        /**
317
         * Register WooCommerce Stripe Gateway compatibility filters.
318
         *
319
         * @return void
320
         */
321
        private static function add_stripe_gateway_filters() {
322
                add_filter( 'graphql_stripe_process_payment_args', [ self::class, 'woocommerce_gateway_stripe_args' ], 10, 2 );
33✔
323
        }
324

325
        /**
326
         * Adds extra arguments to the Stripe Gateway process payment call.
327
         *
328
         * @param array  $gateway_args    Arguments to be passed to the gateway `process_payment` method.
329
         * @param string $payment_method  Payment gateway ID.
330
         *
331
         * @return array
332
         */
333
        public static function woocommerce_gateway_stripe_args( $gateway_args, $payment_method ) {
334
                /** @var false|\WC_Order|\WC_Order_Refund $order */
335
                $order = wc_get_order( $gateway_args[0] );
×
336
                if ( false === $order ) {
×
337
                        return $gateway_args;
×
338
                }
339

340
                $stripe_source_id = $order->get_meta( '_stripe_source_id' );
×
341
                if ( 'stripe' === $payment_method && ! empty( $stripe_source_id ) ) {
×
342
                        $gateway_args = [
×
343
                                $gateway_args[0],
×
344
                                true,
×
345
                                false,
×
346
                                false,
×
347
                                true,
×
348
                        ];
×
349
                }
350

351
                return $gateway_args;
×
352
        }
353

354
        /**
355
         * Register SearchWP/QL Search compatibility filters.
356
         *
357
         * @return void
358
         */
359
        private static function add_swp_filters() {
360
                add_filter( 'graphql_swp_result_possible_types', [ self::class, 'searchwp_result_possible_types' ] );
33✔
361
        }
362

363
        /**
364
         * Adds product types to QL Search SWPResult possible types.
365
         *
366
         * @param array $type_names SWPResults possible types.
367
         *
368
         * @return array
369
         */
370
        public static function searchwp_result_possible_types( array $type_names ) {
371
                if ( in_array( 'Product', $type_names, true ) ) {
×
372
                        $type_names = array_merge(
×
373
                                array_filter(
×
374
                                        $type_names,
×
375
                                        static function ( $type_name ) {
×
376
                                                return 'Product' !== $type_name;
×
377
                                        }
×
378
                                ),
×
379
                                [
×
380
                                        'SimpleProduct',
×
381
                                        'VariableProduct',
×
382
                                        'GroupProduct',
×
383
                                        'ExternalProduct',
×
384
                                ]
×
385
                        );
×
386
                }
387

388
                return $type_names;
×
389
        }
390
}
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