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

wp-graphql / wp-graphql-woocommerce / 27386231983

12 Jun 2026 12:25AM UTC coverage: 91.791%. Remained the same
27386231983

Pull #1019

github

web-flow
Merge 46a421a18 into 01876f534
Pull Request #1019: fix: address WordPress.org plugin review (rename + prefixing + headers)

1327 of 1584 new or added lines in 200 files covered. (83.78%)

1 existing line in 1 file now uncovered.

18505 of 20160 relevant lines covered (91.79%)

151.6 hits per line

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

89.24
/includes/model/class-order.php
1
<?php
2
/**
3
 * Model - Order
4
 *
5
 * Resolves order crud object model
6
 *
7
 * @package WPGraphQL\WooCommerce\Model
8
 * @since 0.0.1
9
 */
10

11
namespace WPGraphQL\WooCommerce\Model;
12

13
use GraphQL\Error\UserError;
14
use GraphQLRelay\Relay;
15
use WPGraphQL\Model\Model;
16

17
/**
18
 * Class Order
19
 *
20
 * @property int           $ID
21
 * @property string        $id
22
 * @property int           $databaseId
23
 * @property string        $orderNumber
24
 * @property string        $orderKey
25
 * @property string        $status
26
 * @property string        $date
27
 * @property string        $modified
28
 * @property string        $datePaid
29
 * @property string        $dateCompleted
30
 * @property string        $customerNote
31
 * @property array         $billing
32
 * @property array         $shipping
33
 * @property string        $discountTotal
34
 * @property float         $discountTotalRaw
35
 * @property string        $discountTax
36
 * @property string        $discountTaxRaw
37
 * @property string        $shippingTotal
38
 * @property float         $shippingTotalRaw
39
 * @property string        $shippingTax
40
 * @property string        $shippingTaxRaw
41
 * @property string        $cartTax
42
 * @property string        $cartTaxRaw
43
 * @property string        $subtotal
44
 * @property float         $subtotalRaw
45
 * @property string        $total
46
 * @property float         $totalRaw
47
 * @property string        $totalTax
48
 * @property float         $totalTaxRaw
49
 * @property bool          $isDownloadPermitted
50
 * @property string        $shippingAddressMapUrl
51
 * @property bool          $hasBillingAddress
52
 * @property bool          $hasShippingAddress
53
 * @property bool          $needsShippingAddress
54
 * @property bool          $needsPayment
55
 * @property bool          $needsProcessing
56
 * @property bool          $hasDownloadableItem
57
 * @property array         $downloadable_items
58
 * @property int           $commentCount
59
 * @property string        $commentStatus
60
 * @property string        $currency
61
 * @property string        $paymentMethod
62
 * @property string        $paymentMethodTitle
63
 * @property string        $transactionId
64
 * @property string        $customerIpAddress
65
 * @property string        $customerUserAgent
66
 * @property string        $createdVia
67
 * @property string        $orderKey
68
 * @property bool          $pricesIncludeTax
69
 * @property string        $cartHash
70
 * @property string        $customerNote
71
 * @property string        $orderVersion
72
 *
73
 * @property string        $title
74
 * @property float         $amount
75
 * @property string        $reason
76
 * @property string        $refunded_by_id
77
 * @property string        $date
78
 *
79
 * @package WPGraphQL\WooCommerce\Model
80
 */
81
class Order extends Model {
82
        /**
83
         * Stores the incoming order data
84
         *
85
         * @var \WC_Order|\WC_Order_Refund|\WC_Abstract_Order $data
86
         */
87
        protected $data;
88

89
        /**
90
         * Hold order post type slug
91
         *
92
         * @var string $post_type
93
         */
94
        protected $post_type;
95

96
        /**
97
         * Stores the incoming post type object for the post being modeled
98
         *
99
         * @var null|\WP_Post_Type $post_type_object
100
         */
101
        protected $post_type_object;
102

103
        /**
104
         * Order constructor.
105
         *
106
         * @param int|\WC_Data $id - shop_order post-type ID.
107
         *
108
         * @throws \Exception - Failed to retrieve order data source.
109
         */
110
        public function __construct( $id ) {
111
                $data = wc_get_order( $id );
66✔
112

113
                // Check if order is valid.
114
                if ( ! $data instanceof \WC_Abstract_Order ) {
66✔
NEW
115
                        throw new \Exception( __( 'Failed to retrieve order data source', 'graphql-for-ecommerce' ) );
×
116
                }
117

118
                $this->data                = $data;
66✔
119
                $this->post_type           = $this->get_post_type();
66✔
120
                $this->post_type_object    = ! empty( $this->post_type ) ? get_post_type_object( $this->post_type ) : null;
66✔
121
                $this->current_user        = wp_get_current_user();
66✔
122
                $allowed_restricted_fields = [
66✔
123
                        'isRestricted',
66✔
124
                        'isPrivate',
66✔
125
                        'isPublic',
66✔
126
                        'id',
66✔
127
                        'databaseId',
66✔
128
                        'orderNumber',
66✔
129
                        'status',
66✔
130
                        'modified',
66✔
131
                        'datePaid',
66✔
132
                        'dateCompleted',
66✔
133
                        'paymentMethodTitle',
66✔
134
                        'customerNote',
66✔
135
                        'billing',
66✔
136
                        'shipping',
66✔
137
                        'discountTotal',
66✔
138
                        'discountTax',
66✔
139
                        'shippingTotal',
66✔
140
                        'shippingTax',
66✔
141
                        'cartTax',
66✔
142
                        'subtotal',
66✔
143
                        'total',
66✔
144
                        'totalTax',
66✔
145
                        'isDownloadPermitted',
66✔
146
                        'shippingAddressMapUrl',
66✔
147
                        'needsShippingAddress',
66✔
148
                        'needsPayment',
66✔
149
                        'needsProcessing',
66✔
150
                        'hasDownloadableItem',
66✔
151
                        'downloadable_items',
66✔
152
                        'commentCount',
66✔
153
                        'commentStatus',
66✔
154
                ];
66✔
155

156
                if ( 'shop_order_refund' === $this->get_type() ) {
66✔
157
                        $allowed_restricted_fields = array_merge(
10✔
158
                                $allowed_restricted_fields,
10✔
159
                                [
10✔
160
                                        'title',
10✔
161
                                        'amount',
10✔
162
                                        'reason',
10✔
163
                                        'refunded_by_id',
10✔
164
                                        'date',
10✔
165
                                ]
10✔
166
                        );
10✔
167
                }
168

169
                $restricted_cap = $this->get_restricted_cap();
66✔
170

171
                parent::__construct( $restricted_cap, $allowed_restricted_fields, 1 );
66✔
172
        }
173

174
        /**
175
         * Get the post type for the order
176
         *
177
         * @return string
178
         */
179
        public function get_post_type() {
180
                $object_type = $this->data->get_type();
66✔
181

182
                $post_type = null;
66✔
183
                switch ( $object_type ) {
184
                        case 'shop_order':
66✔
185
                                $post_type = 'shop_order';
60✔
186
                                break;
60✔
187
                        case 'shop_order_refund':
10✔
188
                                $post_type = 'shop_order_refund';
10✔
189
                                break;
10✔
190
                        default:
191
                                $post_type = apply_filters( 'woographql_order_model_data_post_type', $post_type, $this );
×
192
                                break;
×
193
                }
194

195
                return $post_type;
66✔
196
        }
197

198
        /**
199
         * Forwards function calls to WC_Data sub-class instance.
200
         *
201
         * @param string $method - function name.
202
         * @param array  $args  - function call arguments.
203
         *
204
         * @throws \BadMethodCallException Method not found on WC data object.
205
         *
206
         * @return mixed
207
         */
208
        public function __call( $method, $args ) {
209
                if ( \is_callable( [ $this->data, $method ] ) ) {
30✔
210
                        return $this->data->$method( ...$args );
30✔
211
                }
212

213
                $class = self::class;
×
214
                throw new \BadMethodCallException( "Call to undefined method {$method} on the {$class}" );
×
215
        }
216

217
        /**
218
         * Retrieve the cap to check if the data should be restricted for the order
219
         *
220
         * @return string
221
         */
222
        protected function get_restricted_cap() {
223
                switch ( $this->data->get_status() ) {
66✔
224
                        case 'trash':
66✔
225
                                $cap = ! empty( $this->post_type_object )
×
226
                                        ? $this->post_type_object->cap->edit_posts
×
227
                                        : 'manage_woocommerce';
×
228
                                break;
×
229
                        case 'draft':
66✔
230
                        case 'future':
66✔
231
                        case 'pending':
66✔
232
                                $cap = ! empty( $this->post_type_object )
25✔
233
                                        ? $this->post_type_object->cap->edit_others_posts
25✔
234
                                        : 'manage_woocommerce';
×
235
                                break;
25✔
236
                        default:
237
                                $cap = '';
46✔
238
                                if ( ! $this->owner_matches_current_user() ) {
46✔
239
                                        $cap = ! empty( $this->post_type_object )
20✔
240
                                                ? $this->post_type_object->cap->edit_posts
20✔
241
                                                : 'manage_woocommerce';
×
242
                                }
243
                                break;
46✔
244
                }//end switch
245

246
                return $cap;
66✔
247
        }
248

249
        /**
250
         * Return order types viewable by proven ownership.
251
         *
252
         * @return array
253
         */
254
        protected function get_viewable_order_types() {
255
                return apply_filters(
66✔
256
                        'woographql_viewable_order_types',
66✔
257
                        wc_get_order_types( 'view-orders' )
66✔
258
                );
66✔
259
        }
260

261
        /**
262
         * Returns order type.
263
         *
264
         * @return string
265
         */
266
        public function get_type() {
267
                return $this->data->get_type();
66✔
268
        }
269

270
        /**
271
         * Returns order/refund('s) parent ID
272
         *
273
         * @return int
274
         */
275
        public function get_parent_id() {
276
                return absint( $this->data->get_parent_id() );
10✔
277
        }
278

279
        /**
280
         * Whether or not the customer of the order matches the current user.
281
         *
282
         * @return bool
283
         */
284
        protected function owner_matches_current_user() {
285
                /**
286
                 * Get Order.
287
                 *
288
                 * @var \WC_Order $order
289
                 */
290
                $order = 'shop_order' !== $this->get_type() ? \wc_get_order( $this->get_parent_id() ) : $this->data;
66✔
291

292
                if ( ! is_object( $order ) ) {
66✔
293
                        return false;
×
294
                }
295

296
                // Get Customer ID.
297
                $customer_id = 0;
66✔
298
                if ( in_array( $this->post_type, $this->get_viewable_order_types(), true ) ) {
66✔
299
                        $customer_id = $order->get_customer_id();
66✔
300
                }
301

302
                // If no customer ID, check if guest order matches current user.
303
                if ( 0 === $customer_id ) {
66✔
304
                        return $this->guest_order_customer_matches_current_user();
14✔
305
                }
306

307
                // If no current user or purchasing customer ID, return false.
308
                if ( empty( $this->current_user->ID ) || empty( $customer_id ) ) {
53✔
309
                        return false;
×
310
                }
311

312
                // If customer ID matches current user, return true.
313
                return absint( $customer_id ) === absint( $this->current_user->ID );
53✔
314
        }
315

316
        /**
317
         * Whether or not the customer of the order who is a guest matches the current user.
318
         *
319
         * @return bool
320
         */
321
        public function guest_order_customer_matches_current_user() {
322
                /**
323
                 * Get Order.
324
                 *
325
                 * @var \WC_Order $order
326
                 */
327
                $order = 'shop_order' !== $this->get_type() ? \wc_get_order( $this->get_parent_id() ) : $this->data;
14✔
328

329
                // Get Customer Email.
330
                if ( in_array( $this->post_type, $this->get_viewable_order_types(), true ) ) {
14✔
331
                        $customer_email = $order->get_billing_email();
14✔
332
                }
333

334
                // If no customer email, return false.
335
                $session_customer = \WC()->customer;
14✔
336
                if ( empty( $session_customer->get_billing_email() ) || empty( $customer_email ) ) {
14✔
337
                        return false;
4✔
338
                }
339

340
                // If customer email matches current user, return true.
341
                return $customer_email === $session_customer->get_billing_email();
10✔
342
        }
343

344
        /**
345
         * Determine if the model is private
346
         *
347
         * @return bool
348
         */
349
        public function is_private() {
350
                return ! wc_is_order_status( 'wc-' . $this->data->get_status() );
66✔
351
        }
352

353
        /**
354
         * Wrapper function for deleting
355
         *
356
         * @throws \GraphQL\Error\UserError Not authorized.
357
         *
358
         * @param boolean $force_delete Should the data be deleted permanently.
359
         * @return boolean
360
         */
361
        public function delete( $force_delete = false ) {
362
                if ( ! current_user_can( ! empty( $this->post_type_object ) ? $this->post_type_object->cap->edit_posts : 'manage_woocommerce' ) ) {
×
363
                        throw new UserError(
×
364
                                __(
×
365
                                        'User does not have the capabilities necessary to delete this object.',
×
NEW
366
                                        'graphql-for-ecommerce'
×
367
                                )
×
368
                        );
×
369
                }
370

371
                return $this->data->delete( $force_delete );
×
372
        }
373

374
        /**
375
         * Returns abstract order fields shared by all child order types like Orders and Refunds.
376
         *
377
         * @return array
378
         */
379
        protected function abstract_order_fields() {
380
                return [
66✔
381
                        'ID'               => function () {
66✔
382
                                return ! empty( $this->data->get_id() ) ? $this->data->get_id() : null;
55✔
383
                        },
66✔
384
                        'id'               => function () {
66✔
385
                                return ! empty( $this->ID ) ? Relay::toGlobalId( 'order', "{$this->ID}" ) : null;
31✔
386
                        },
66✔
387
                        'databaseId'       => function () {
66✔
388
                                return $this->ID;
46✔
389
                        },
66✔
390
                        'parent_id'        => function () {
66✔
391
                                return ! empty( $this->data->get_parent_id() ) ? $this->data->get_parent_id() : null;
18✔
392
                        },
66✔
393
                        'status'           => function () {
66✔
394
                                return ! empty( $this->data->get_status() ) ? $this->data->get_status() : null;
22✔
395
                        },
66✔
396
                        'currency'         => function () {
66✔
397
                                return ! empty( $this->data->get_currency() ) ? $this->data->get_currency() : null;
18✔
398
                        },
66✔
399
                        'version'          => function () {
66✔
400
                                return ! empty( $this->data->get_version() ) ? $this->data->get_version() : null;
×
401
                        },
66✔
402
                        'pricesIncludeTax' => function () {
66✔
403
                                return ! empty( $this->data->get_prices_include_tax() ) ? $this->data->get_prices_include_tax() : null;
×
404
                        },
66✔
405
                        'dateCreated'      => function () {
66✔
406
                                return ! empty( $this->data->get_date_created() ) ? $this->data->get_date_created() : null;
×
407
                        },
66✔
408
                        'dateModified'     => function () {
66✔
409
                                return ! empty( $this->data->get_date_modified() ) ? $this->data->get_date_modified() : null;
×
410
                        },
66✔
411
                        'discountTotal'    => function () {
66✔
412
                                $price = ! is_null( $this->data->get_discount_total() ) ? $this->data->get_discount_total() : 0;
18✔
413
                                return wc_graphql_price( $price, [ 'currency' => $this->data->get_currency() ] );
18✔
414
                        },
66✔
415
                        'discountTotalRaw' => function () {
66✔
416
                                return ! empty( $this->data->get_discount_total() ) ? $this->data->get_discount_total() : 0;
×
417
                        },
66✔
418
                        'discountTax'      => function () {
66✔
419
                                $price = ! is_null( $this->data->get_discount_tax() ) ? $this->data->get_discount_tax() : 0;
18✔
420
                                return wc_graphql_price( $price, [ 'currency' => $this->data->get_currency() ] );
18✔
421
                        },
66✔
422
                        'discountTaxRaw'   => function () {
66✔
423
                                return ! empty( $this->data->get_discount_tax() ) ? $this->data->get_discount_tax() : 0;
×
424
                        },
66✔
425
                        'shippingTotal'    => function () {
66✔
426
                                $price = ! is_null( $this->data->get_shipping_total() ) ? $this->data->get_shipping_total() : 0;
20✔
427
                                return wc_graphql_price( $price, [ 'currency' => $this->data->get_currency() ] );
20✔
428
                        },
66✔
429
                        'shippingTotalRaw' => function () {
66✔
430
                                return ! empty( $this->data->get_shipping_total() ) ? $this->data->get_shipping_total() : 0;
×
431
                        },
66✔
432
                        'shippingTax'      => function () {
66✔
433
                                $price = ! is_null( $this->data->get_shipping_tax() ) ? $this->data->get_shipping_tax() : 0;
18✔
434
                                return wc_graphql_price( $price, [ 'currency' => $this->data->get_currency() ] );
18✔
435
                        },
66✔
436
                        'shippingTaxRaw'   => function () {
66✔
437
                                return ! empty( $this->data->get_shipping_tax() ) ? $this->data->get_shipping_tax() : 0;
×
438
                        },
66✔
439
                        'cartTax'          => function () {
66✔
440
                                $price = ! is_null( $this->data->get_cart_tax() ) ? $this->data->get_cart_tax() : 0;
18✔
441
                                return wc_graphql_price( $price, [ 'currency' => $this->data->get_currency() ] );
18✔
442
                        },
66✔
443
                        'cartTaxRaw'       => function () {
66✔
444
                                return ! empty( $this->data->get_cart_tax() ) ? $this->data->get_cart_tax() : 0;
×
445
                        },
66✔
446
                        'total'            => function () {
66✔
447
                                return ! is_null( $this->data->get_total() )
21✔
448
                                        ? wc_graphql_price( $this->data->get_total(), [ 'currency' => $this->data->get_currency() ] )
21✔
449
                                        : null;
21✔
450
                        },
66✔
451
                        'totalRaw'         => function () {
66✔
452
                                return ! empty( $this->data->get_total() ) ? $this->data->get_total() : 0;
2✔
453
                        },
66✔
454
                        'totalTax'         => function () {
66✔
455
                                return ! is_null( $this->data->get_total_tax() )
18✔
456
                                        ? wc_graphql_price( $this->data->get_total_tax(), [ 'currency' => $this->data->get_currency() ] )
18✔
457
                                        : null;
18✔
458
                        },
66✔
459
                        'totalTaxRaw'      => function () {
66✔
460
                                return ! empty( $this->data->get_total_tax() ) ? $this->data->get_total_tax() : 0;
×
461
                        },
66✔
462
                ];
66✔
463
        }
464

465
        /**
466
         * Returns order-only fields.
467
         *
468
         * @return array
469
         */
470
        protected function order_fields() {
471
                return [
60✔
472
                        'date'                  => function () {
60✔
473
                                return ! empty( $this->data->get_date_created() ) ? $this->data->get_date_created() : null;
22✔
474
                        },
60✔
475
                        'modified'              => function () {
60✔
476
                                return ! empty( $this->data->get_date_modified() ) ? $this->data->get_date_modified() : null;
18✔
477
                        },
60✔
478
                        'orderKey'              => function () {
60✔
479
                                $order_key = method_exists( $this->data, 'get_order_key' ) ? $this->data->get_order_key() : null;
18✔
480
                                return ! empty( $order_key ) ? $order_key : null;
18✔
481
                        },
60✔
482
                        'paymentMethod'         => function () {
60✔
483
                                $payment_method = method_exists( $this->data, 'get_payment_method' ) ? $this->data->get_payment_method() : null;
18✔
484
                                return ! empty( $payment_method ) ? $payment_method : null;
18✔
485
                        },
60✔
486
                        'paymentMethodTitle'    => function () {
60✔
487
                                $payment_method_title = method_exists( $this->data, 'get_payment_method_title' ) ? $this->data->get_payment_method_title() : null;
18✔
488
                                return ! empty( $payment_method_title ) ? $payment_method_title : null;
18✔
489
                        },
60✔
490
                        'transactionId'         => function () {
60✔
491
                                $transaction_id = method_exists( $this->data, 'get_transaction_id' ) ? $this->data->get_transaction_id() : null;
18✔
492
                                return ! empty( $transaction_id ) ? $transaction_id : null;
18✔
493
                        },
60✔
494
                        'customerIpAddress'     => function () {
60✔
495
                                $customer_ip_address = method_exists( $this->data, 'get_customer_ip_address' ) ? $this->data->get_customer_ip_address() : null;
18✔
496
                                return ! empty( $customer_ip_address ) ? $customer_ip_address : null;
18✔
497
                        },
60✔
498
                        'customerUserAgent'     => function () {
60✔
499
                                $customer_user_agent = method_exists( $this->data, 'get_customer_user_agent' ) ? $this->data->get_customer_user_agent() : null;
18✔
500
                                return ! empty( $customer_user_agent ) ? $customer_user_agent : null;
18✔
501
                        },
60✔
502
                        'createdVia'            => function () {
60✔
503
                                $created_via = method_exists( $this->data, 'get_created_via' ) ? $this->data->get_created_via() : null;
18✔
504
                                return ! empty( $created_via ) ? $created_via : null;
18✔
505
                        },
60✔
506
                        'dateCompleted'         => function () {
60✔
507
                                return ! empty( $this->data->get_date_completed() ) ? $this->data->get_date_completed() : null;
18✔
508
                        },
60✔
509
                        'datePaid'              => function () {
60✔
510
                                return ! empty( $this->data->get_date_paid() ) ? $this->data->get_date_paid() : null;
18✔
511
                        },
60✔
512
                        'subtotal'              => function () {
60✔
513
                                return ! is_null( $this->data->get_subtotal() )
18✔
514
                                        ? wc_graphql_price( $this->data->get_subtotal(), [ 'currency' => $this->data->get_currency() ] )
18✔
515
                                        : null;
18✔
516
                        },
60✔
517
                        'subtotalRaw'           => function () {
60✔
518
                                return ! empty( $this->data->get_subtotal() ) ? $this->data->get_subtotal() : 0;
×
519
                        },
60✔
520
                        'orderNumber'           => function () {
60✔
521
                                $order_number = method_exists( $this->data, 'get_order_number' ) ? $this->data->get_order_number() : null;
18✔
522
                                return ! empty( $order_number ) ? $order_number : null;
18✔
523
                        },
60✔
524
                        'orderVersion'          => function () {
60✔
525
                                return ! empty( $this->data->get_version() ) ? $this->data->get_version() : null;
18✔
526
                        },
60✔
527
                        'pricesIncludeTax'      => function () {
60✔
528
                                return ! is_null( $this->data->get_prices_include_tax() ) ? $this->data->get_prices_include_tax() : null;
18✔
529
                        },
60✔
530
                        'cartHash'              => function () {
60✔
531
                                $cart_hash = method_exists( $this->data, 'get_cart_hash' ) ? $this->data->get_cart_hash() : null;
18✔
532
                                return ! empty( $cart_hash ) ? $cart_hash : null;
18✔
533
                        },
60✔
534
                        'customerNote'          => function () {
60✔
535
                                $customer_note = method_exists( $this->data, 'get_customer_note' ) ? $this->data->get_customer_note() : null;
18✔
536
                                return ! empty( $customer_note ) ? $customer_note : null;
18✔
537
                        },
60✔
538
                        'isDownloadPermitted'   => function () {
60✔
539
                                if ( ! method_exists( $this->data, 'is_download_permitted' ) ) {
18✔
540
                                        return null;
×
541
                                }
542

543
                                return $this->data->is_download_permitted();
18✔
544
                        },
60✔
545
                        'billing'               => function () {
60✔
546
                                $billing = method_exists( $this->data, 'get_address' ) ? $this->data->get_address( 'billing' ) : null;
19✔
547
                                return ! empty( $billing ) ? $billing : null;
19✔
548
                        },
60✔
549
                        'shipping'              => function () {
60✔
550
                                $shipping = method_exists( $this->data, 'get_address' ) ? $this->data->get_address( 'shipping' ) : null;
18✔
551
                                return ! empty( $shipping ) ? $shipping : null;
18✔
552
                        },
60✔
553
                        'shippingAddressMapUrl' => function () {
60✔
554
                                $shipping_address_map_url = method_exists( $this->data, 'get_shipping_address_map_url' ) ? $this->data->get_shipping_address_map_url() : null;
18✔
555
                                return ! empty( $shipping_address_map_url ) ? $shipping_address_map_url : null;
18✔
556
                        },
60✔
557
                        'hasBillingAddress'     => function () {
60✔
558
                                if ( ! method_exists( $this->data, 'has_billing_address' ) ) {
18✔
559
                                        return null;
×
560
                                }
561

562
                                return $this->data->has_billing_address();
18✔
563
                        },
60✔
564
                        'hasShippingAddress'    => function () {
60✔
565
                                if ( ! method_exists( $this->data, 'has_shipping_address' ) ) {
18✔
566
                                        return null;
×
567
                                }
568

569
                                return $this->data->has_shipping_address();
18✔
570
                        },
60✔
571
                        'needsShippingAddress'  => function () {
60✔
572
                                if ( ! method_exists( $this->data, 'needs_shipping_address' ) ) {
18✔
573
                                        return null;
×
574
                                }
575

576
                                return $this->data->needs_shipping_address();
18✔
577
                        },
60✔
578
                        'hasDownloadableItem'   => function () {
60✔
579
                                if ( ! method_exists( $this->data, 'has_downloadable_item' ) ) {
18✔
580
                                        return null;
×
581
                                }
582

583
                                return $this->data->has_downloadable_item();
18✔
584
                        },
60✔
585
                        'needsPayment'          => function () {
60✔
586
                                if ( ! method_exists( $this->data, 'needs_payment' ) ) {
18✔
587
                                        return null;
×
588
                                }
589

590
                                return $this->data->needs_payment();
18✔
591
                        },
60✔
592
                        'needsProcessing'       => function () {
60✔
593
                                if ( ! method_exists( $this->data, 'needs_processing' ) ) {
18✔
594
                                        return null;
×
595
                                }
596

597
                                return $this->data->needs_processing();
18✔
598
                        },
60✔
599
                        /**
600
                         * Connection resolvers fields
601
                         *
602
                         * These field resolvers are used in connection resolvers to define WP_Query argument
603
                         * Note: underscore naming style is used as a quick identifier
604
                         */
605
                        'customer_id'           => function () {
60✔
606
                                $customer_id = method_exists( $this->data, 'get_customer_id' ) ? $this->data->get_customer_id() : null;
18✔
607
                                return ! empty( $customer_id ) ? $customer_id : null;
18✔
608
                        },
60✔
609
                        'downloadable_items'    => function () {
60✔
610
                                $downloadable_items = method_exists( $this->data, 'get_downloadable_items' ) ? $this->data->get_downloadable_items() : null;
22✔
611
                                return ! empty( $downloadable_items ) ? $downloadable_items : null;
22✔
612
                        },
60✔
613
                        /**
614
                         * Defines aliased fields
615
                         *
616
                         * These fields are used primarily by WPGraphQL core Node* interfaces
617
                         * and some fields act as aliases/decorator for existing fields.
618
                         */
619
                        'commentCount'          => function () {
60✔
620
                                remove_filter( 'comments_clauses', [ 'WC_Comments', 'exclude_order_comments' ] );
1✔
621

622
                                $args = [
1✔
623
                                        'post_id' => $this->ID,
1✔
624
                                        'approve' => 'approve',
1✔
625
                                        'fields'  => 'ids',
1✔
626
                                        'type'    => '',
1✔
627
                                ];
1✔
628

629
                                $is_allowed_to_edit = null !== $this->post_type_object
1✔
630
                                        ? current_user_can( $this->post_type_object->cap->edit_posts, $this->ID )
1✔
631
                                        : current_user_can( 'manage_woocommerce' );
×
632

633
                                if ( ! $is_allowed_to_edit ) {
1✔
634
                                        $args += [
1✔
635
                                                // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key
636
                                                'meta_key'   => 'is_customer_note',
1✔
637
                                                // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value
638
                                                'meta_value' => '1',
1✔
639
                                        ];
1✔
640
                                }
641

642
                                $notes = get_comments( $args );
1✔
643

644
                                add_filter( 'comments_clauses', [ 'WC_Comments', 'exclude_order_comments' ] );
1✔
645

646
                                return is_array( $notes ) ? count( $notes ) : 0;
1✔
647
                        },
60✔
648
                        'commentStatus'         => function () {
60✔
649
                                $is_allowed_to_comment = null !== $this->post_type_object
1✔
650
                                        ? current_user_can( $this->post_type_object->cap->edit_posts, $this->ID )
1✔
651
                                        : current_user_can( 'manage_woocommerce' );
×
652
                                return $is_allowed_to_comment ? 'open' : 'closed';
1✔
653
                        },
60✔
654
                ];
60✔
655
        }
656

657
        /**
658
         * Returns refund-only fields.
659
         *
660
         * @return array
661
         */
662
        protected function refund_fields() {
663
                return [
10✔
664
                        'title'          => function () {
10✔
665
                                $post_title = method_exists( $this->data, 'get_post_title' ) ? $this->data->get_post_title() : null;
2✔
666
                                return ! empty( $post_title ) ? $post_title : null;
2✔
667
                        },
10✔
668
                        'amount'         => function () {
10✔
669
                                $amount = method_exists( $this->data, 'get_amount' ) ? $this->data->get_amount() : null;
4✔
670
                                return ! empty( $amount ) ? $amount : null;
4✔
671
                        },
10✔
672
                        'reason'         => function () {
10✔
673
                                $reason = method_exists( $this->data, 'get_reason' ) ? $this->data->get_reason() : null;
3✔
674
                                return ! empty( $reason ) ? $reason : null;
3✔
675
                        },
10✔
676
                        'refunded_by_id' => [
10✔
677
                                'callback'   => function () {
10✔
678
                                        $refunded_by = method_exists( $this->data, 'get_refunded_by' ) ? $this->data->get_refunded_by() : null;
1✔
679
                                        return ! empty( $refunded_by ) ? $refunded_by : null;
1✔
680
                                },
10✔
681
                                'capability' => 'list_users',
10✔
682
                        ],
10✔
683
                        'date'           => function () {
10✔
684
                                return ! empty( $this->data->get_date_modified() ) ? $this->data->get_date_modified() : null;
1✔
685
                        },
10✔
686
                ];
10✔
687
        }
688

689
        /**
690
         * Initializes the Order field resolvers.
691
         */
692
        protected function init() {
693
                if ( empty( $this->fields ) ) {
66✔
694
                        if ( 'shop_order_refund' === $this->get_type() ) {
66✔
695
                                $this->fields = array_merge( $this->refund_fields(), $this->abstract_order_fields() );
10✔
696
                        } else {
697
                                $this->fields = array_merge( $this->abstract_order_fields(), $this->order_fields() );
60✔
698
                        }
699
                }//end if
700
        }
701
}
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