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

wp-graphql / wp-graphql-woocommerce / 11714183904

07 Nov 2024 12:23AM UTC coverage: 83.665% (-0.8%) from 84.451%
11714183904

push

github

web-flow
devops: Name officially changed to "WPGraphQL for WooCommerce" (#900)

* devops: Name officially changed to "WPGraphQL for WooCommerce"

* devops: GA workflow environment updated

* devops: GA workflow environment updated

* devops: composer-git-hooks downgraded to "2.8.5"

* devops: Unstable session manager tests skipped

* chore: cleanup applied

* devops: Docker configurations updated

* devops: Docker configurations updated

* devops: Docker configurations updated

* devops: Docker configurations updated

* devops: Docker configurations updated

2 of 8 new or added lines in 5 files covered. (25.0%)

268 existing lines in 20 files now uncovered.

12431 of 14858 relevant lines covered (83.67%)

71.79 hits per line

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

88.38
/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 );
30✔
112

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

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

156
                $restricted_cap = $this->get_restricted_cap();
30✔
157

158
                parent::__construct( $restricted_cap, $allowed_restricted_fields, 1 );
30✔
159
        }
160

161
        /**
162
         * Get the post type for the order
163
         *
164
         * @return string
165
         */
166
        public function get_post_type() {
167
                $object_type = $this->data->get_type();
30✔
168

169
                $post_type = null;
30✔
170
                switch ( $object_type ) {
171
                        case 'shop_order':
30✔
172
                                $post_type = 'shop_order';
24✔
173
                                break;
24✔
174
                        case 'shop_order_refund':
7✔
175
                                $post_type = 'shop_order_refund';
7✔
176
                                break;
7✔
177
                        default:
178
                                $post_type = apply_filters( 'woographql_order_model_data_post_type', $post_type, $this );
×
179
                                break;
×
180
                }
181

182
                return $post_type;
30✔
183
        }
184

185
        /**
186
         * Forwards function calls to WC_Data sub-class instance.
187
         *
188
         * @param string $method - function name.
189
         * @param array  $args  - function call arguments.
190
         *
191
         * @throws \BadMethodCallException Method not found on WC data object.
192
         *
193
         * @return mixed
194
         */
195
        public function __call( $method, $args ) {
196
                if ( \is_callable( [ $this->data, $method ] ) ) {
15✔
197
                        return $this->data->$method( ...$args );
15✔
198
                }
199

200
                $class = self::class;
×
201
                throw new \BadMethodCallException( "Call to undefined method {$method} on the {$class}" );
×
202
        }
203

204
        /**
205
         * Retrieve the cap to check if the data should be restricted for the order
206
         *
207
         * @return string
208
         */
209
        protected function get_restricted_cap() {
210
                switch ( $this->data->get_status() ) {
30✔
211
                        case 'trash':
30✔
212
                                $cap = ! empty( $this->post_type_object )
×
213
                                        ? $this->post_type_object->cap->edit_posts
×
214
                                        : 'manage_woocommerce';
×
215
                                break;
×
216
                        case 'draft':
30✔
217
                        case 'future':
30✔
218
                        case 'pending':
30✔
219
                                $cap = ! empty( $this->post_type_object )
16✔
220
                                        ? $this->post_type_object->cap->edit_others_posts
16✔
UNCOV
221
                                        : 'manage_woocommerce';
×
222
                                break;
16✔
223
                        default:
224
                                $cap = '';
17✔
225
                                if ( ! $this->owner_matches_current_user() ) {
17✔
226
                                        $cap = ! empty( $this->post_type_object )
7✔
227
                                                ? $this->post_type_object->cap->edit_posts
7✔
UNCOV
228
                                                : 'manage_woocommerce';
×
229
                                }
230
                                break;
17✔
231
                }//end switch
232

233
                return $cap;
30✔
234
        }
235

236
        /**
237
         * Return order types viewable by proven ownership.
238
         *
239
         * @return array
240
         */
241
        protected function get_viewable_order_types() {
242
                return apply_filters(
30✔
243
                        'woographql_viewable_order_types',
30✔
244
                        wc_get_order_types( 'view-orders' )
30✔
245
                );
30✔
246
        }
247

248
        /**
249
         * Returns order type.
250
         *
251
         * @return string
252
         */
253
        public function get_type() {
254
                return $this->data->get_type();
30✔
255
        }
256

257
        /**
258
         * Returns order/refund('s) parent ID
259
         *
260
         * @return int
261
         */
262
        public function get_parent_id() {
263
                return absint( $this->data->get_parent_id() );
7✔
264
        }
265

266
        /**
267
         * Whether or not the customer of the order matches the current user.
268
         *
269
         * @return bool
270
         */
271
        protected function owner_matches_current_user() {
272
                /**
273
                 * Get Order.
274
                 *
275
                 * @var \WC_Order $order
276
                 */
277
                $order = 'shop_order' !== $this->get_type() ? \wc_get_order( $this->get_parent_id() ) : $this->data;
30✔
278

279
                if ( ! is_object( $order ) ) {
30✔
280
                        return false;
×
281
                }
282

283
                // Get Customer ID.
284
                $customer_id = 0;
30✔
285
                if ( in_array( $this->post_type, $this->get_viewable_order_types(), true ) ) {
30✔
286
                        $customer_id = $order->get_customer_id();
30✔
287
                }
288

289
                // If no customer ID, check if guest order matches current user.
290
                if ( 0 === $customer_id ) {
30✔
291
                        return $this->guest_order_customer_matches_current_user();
3✔
292
                }
293

294
                // If no current user or purchasing customer ID, return false.
295
                if ( empty( $this->current_user->ID ) || empty( $customer_id ) ) {
28✔
296
                        return false;
×
297
                }
298

299
                // If customer ID matches current user, return true.
300
                return absint( $customer_id ) === absint( $this->current_user->ID );
28✔
301
        }
302

303
        /**
304
         * Whether or not the customer of the order who is a guest matches the current user.
305
         *
306
         * @return bool
307
         */
308
        public function guest_order_customer_matches_current_user() {
309
                /**
310
                 * Get Order.
311
                 *
312
                 * @var \WC_Order $order
313
                 */
314
                $order = 'shop_order' !== $this->get_type() ? \wc_get_order( $this->get_parent_id() ) : $this->data;
3✔
315

316
                // Get Customer Email.
317
                if ( in_array( $this->post_type, $this->get_viewable_order_types(), true ) ) {
3✔
318
                        $customer_email = $order->get_billing_email();
3✔
319
                }
320

321
                // If no customer email, return false.
322
                $session_customer = \WC()->customer;
3✔
323
                if ( empty( $session_customer->get_billing_email() ) || empty( $customer_email ) ) {
3✔
324
                        return false;
×
325
                }
326

327
                // If customer email matches current user, return true.
328
                return $customer_email === $session_customer->get_billing_email();
3✔
329
        }
330

331
        /**
332
         * Determine if the model is private
333
         *
334
         * @return bool
335
         */
336
        public function is_private() {
337
                return ! wc_is_order_status( 'wc-' . $this->data->get_status() );
30✔
338
        }
339

340
        /**
341
         * Wrapper function for deleting
342
         *
343
         * @throws \GraphQL\Error\UserError Not authorized.
344
         *
345
         * @param boolean $force_delete Should the data be deleted permanently.
346
         * @return boolean
347
         */
348
        public function delete( $force_delete = false ) {
349
                if ( ! current_user_can( ! empty( $this->post_type_object ) ? $this->post_type_object->cap->edit_posts : 'manage_woocommerce' ) ) {
×
350
                        throw new UserError(
×
351
                                __(
×
352
                                        'User does not have the capabilities necessary to delete this object.',
×
353
                                        'wp-graphql-woocommerce'
×
354
                                )
×
355
                        );
×
356
                }
357

358
                return $this->data->delete( $force_delete );
×
359
        }
360

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

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

530
                                return $this->data->is_download_permitted();
9✔
531
                        },
24✔
532
                        'billing'               => function () {
24✔
533
                                $billing = method_exists( $this->data, 'get_address' ) ? $this->data->get_address( 'billing' ) : null;
10✔
534
                                return ! empty( $billing ) ? $billing : null;
10✔
535
                        },
24✔
536
                        'shipping'              => function () {
24✔
537
                                $shipping = method_exists( $this->data, 'get_address' ) ? $this->data->get_address( 'shipping' ) : null;
9✔
538
                                return ! empty( $shipping ) ? $shipping : null;
9✔
539
                        },
24✔
540
                        'shippingAddressMapUrl' => function () {
24✔
541
                                $shipping_address_map_url = method_exists( $this->data, 'get_shipping_address_map_url' ) ? $this->data->get_shipping_address_map_url() : null;
9✔
542
                                return ! empty( $shipping_address_map_url ) ? $shipping_address_map_url : null;
9✔
543
                        },
24✔
544
                        'hasBillingAddress'     => function () {
24✔
545
                                if ( ! method_exists( $this->data, 'has_billing_address' ) ) {
9✔
546
                                        return null;
×
547
                                }
548

549
                                return $this->data->has_billing_address();
9✔
550
                        },
24✔
551
                        'hasShippingAddress'    => function () {
24✔
552
                                if ( ! method_exists( $this->data, 'has_shipping_address' ) ) {
9✔
553
                                        return null;
×
554
                                }
555

556
                                return $this->data->has_shipping_address();
9✔
557
                        },
24✔
558
                        'needsShippingAddress'  => function () {
24✔
559
                                if ( ! method_exists( $this->data, 'needs_shipping_address' ) ) {
9✔
560
                                        return null;
×
561
                                }
562

563
                                return $this->data->needs_shipping_address();
9✔
564
                        },
24✔
565
                        'hasDownloadableItem'   => function () {
24✔
566
                                if ( ! method_exists( $this->data, 'has_downloadable_item' ) ) {
9✔
567
                                        return null;
×
568
                                }
569

570
                                return $this->data->has_downloadable_item();
9✔
571
                        },
24✔
572
                        'needsPayment'          => function () {
24✔
573
                                if ( ! method_exists( $this->data, 'needs_payment' ) ) {
9✔
574
                                        return null;
×
575
                                }
576

577
                                return $this->data->needs_payment();
9✔
578
                        },
24✔
579
                        'needsProcessing'       => function () {
24✔
580
                                if ( ! method_exists( $this->data, 'needs_processing' ) ) {
9✔
581
                                        return null;
×
582
                                }
583

584
                                return $this->data->needs_processing();
9✔
585
                        },
24✔
586
                        /**
587
                         * Connection resolvers fields
588
                         *
589
                         * These field resolvers are used in connection resolvers to define WP_Query argument
590
                         * Note: underscore naming style is used as a quick identifier
591
                         */
592
                        'customer_id'           => function () {
24✔
593
                                $customer_id = method_exists( $this->data, 'get_customer_id' ) ? $this->data->get_customer_id() : null;
9✔
594
                                return ! empty( $customer_id ) ? $customer_id : null;
9✔
595
                        },
24✔
596
                        'downloadable_items'    => function () {
24✔
597
                                $downloadable_items = method_exists( $this->data, 'get_downloadable_items' ) ? $this->data->get_downloadable_items() : null;
12✔
598
                                return ! empty( $downloadable_items ) ? $downloadable_items : null;
12✔
599
                        },
24✔
600
                        /**
601
                         * Defines aliased fields
602
                         *
603
                         * These fields are used primarily by WPGraphQL core Node* interfaces
604
                         * and some fields act as aliases/decorator for existing fields.
605
                         */
606
                        'commentCount'          => function () {
24✔
607
                                remove_filter( 'comments_clauses', [ 'WC_Comments', 'exclude_order_comments' ] );
1✔
608

609
                                $args = [
1✔
610
                                        'post_id' => $this->ID,
1✔
611
                                        'approve' => 'approve',
1✔
612
                                        'fields'  => 'ids',
1✔
613
                                        'type'    => '',
1✔
614
                                ];
1✔
615

616
                                $is_allowed_to_edit = null !== $this->post_type_object
1✔
617
                                        ? current_user_can( $this->post_type_object->cap->edit_posts, $this->ID )
1✔
UNCOV
618
                                        : current_user_can( 'manage_woocommerce' );
×
619

620
                                if ( ! $is_allowed_to_edit ) {
1✔
621
                                        $args += [
1✔
622
                                                // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key
623
                                                'meta_key'   => 'is_customer_note',
1✔
624
                                                // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value
625
                                                'meta_value' => '1',
1✔
626
                                        ];
1✔
627
                                }
628

629
                                $notes = get_comments( $args );
1✔
630

631
                                add_filter( 'comments_clauses', [ 'WC_Comments', 'exclude_order_comments' ] );
1✔
632

633
                                return is_array( $notes ) ? count( $notes ) : 0;
1✔
634
                        },
24✔
635
                        'commentStatus'         => function () {
24✔
636
                                $is_allowed_to_comment = null !== $this->post_type_object
1✔
637
                                        ? current_user_can( $this->post_type_object->cap->edit_posts, $this->ID )
1✔
UNCOV
638
                                        : current_user_can( 'manage_woocommerce' );
×
639
                                return $is_allowed_to_comment ? 'open' : 'closed';
1✔
640
                        },
24✔
641
                ];
24✔
642
        }
643

644
        /**
645
         * Returns refund-only fields.
646
         *
647
         * @return array
648
         */
649
        protected function refund_fields() {
650
                return [
7✔
651
                        'title'          => function () {
7✔
652
                                $post_title = method_exists( $this->data, 'get_post_title' ) ? $this->data->get_post_title() : null;
1✔
653
                                return ! empty( $post_title ) ? $post_title : null;
1✔
654
                        },
7✔
655
                        'amount'         => function () {
7✔
656
                                $amount = method_exists( $this->data, 'get_amount' ) ? $this->data->get_amount() : null;
1✔
657
                                return ! empty( $amount ) ? $amount : null;
1✔
658
                        },
7✔
659
                        'reason'         => function () {
7✔
660
                                $reason = method_exists( $this->data, 'get_reason' ) ? $this->data->get_reason() : null;
1✔
661
                                return ! empty( $reason ) ? $reason : null;
1✔
662
                        },
7✔
663
                        'refunded_by_id' => [
7✔
664
                                'callback'   => function () {
7✔
665
                                        $refunded_by = method_exists( $this->data, 'get_refunded_by' ) ? $this->data->get_refunded_by() : null;
1✔
666
                                        return ! empty( $refunded_by ) ? $refunded_by : null;
1✔
667
                                },
7✔
668
                                'capability' => 'list_users',
7✔
669
                        ],
7✔
670
                        'date'           => function () {
7✔
671
                                return ! empty( $this->data->get_date_modified() ) ? $this->data->get_date_modified() : null;
1✔
672
                        },
7✔
673
                ];
7✔
674
        }
675

676
        /**
677
         * Initializes the Order field resolvers.
678
         */
679
        protected function init() {
680
                if ( empty( $this->fields ) ) {
30✔
681
                        if ( 'shop_order_refund' === $this->get_type() ) {
30✔
682
                                $this->fields = array_merge( $this->refund_fields(), $this->abstract_order_fields() );
7✔
683
                        } else {
684
                                $this->fields = array_merge( $this->abstract_order_fields(), $this->order_fields() );
24✔
685
                        }
686
                }//end if
687
        }
688
}
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