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

wp-graphql / wp-graphql-woocommerce / 23228201207

18 Mar 2026 03:49AM UTC coverage: 83.184% (-0.4%) from 83.59%
23228201207

push

github

web-flow
fix: inverted logic in pop_transaction_id() causes cart session corruption (#971)

* fix: resolve REQUEST_URI fatal error and JWT key length issues in CI

QLSessionHandlerTest::tearDown() was calling unset($_SERVER) which
destroyed the entire superglobal. WordPress cron.php then fataled on
shutdown when accessing $_SERVER['REQUEST_URI']. Changed to only unset
the specific HTTP_WOOCOMMERCE_SESSION key.

Also updated JWT secret keys to meet firebase/php-jwt v7's minimum
32-byte requirement for HS256 in both test config and Docker entrypoint.

* fix: the rest of the files added

* devops: php7.4 removed from matrix

* chore: Linter compliances met

* devops: More broken test updated

* devops: Tests updated for CI

* fix: QLSessionHandlerCest fixed

* fix: QLSessionHandlerCest fixed

* devops: CI fixed

3 of 59 new or added lines in 2 files covered. (5.08%)

526 existing lines in 17 files now uncovered.

12594 of 15140 relevant lines covered (83.18%)

75.9 hits per line

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

98.7
/includes/model/class-customer.php
1
<?php
2
/**
3
 * Model - Customer
4
 *
5
 * Models WooCommerce post-type data
6
 *
7
 * @package WPGraphQL\WooCommerce\Model
8
 * @since 0.0.1
9
 */
10

11
namespace WPGraphQL\WooCommerce\Model;
12

13
use GraphQLRelay\Relay;
14
use WC_Customer;
15
use WPGraphQL\Model\Model;
16

17
/**
18
 * Class Customer
19
 *
20
 * @property int $ID
21
 * @property string $id
22
 * @property int $databaseId
23
 * @property bool $isVatExempt
24
 * @property bool $hasCalculatedShipping
25
 * @property bool $calculatedShipping
26
 * @property int $orderCount
27
 * @property float $totalSpent
28
 * @property string $username
29
 * @property string $email
30
 * @property string $firstName
31
 * @property string $lastName
32
 * @property string $displayName
33
 * @property string $role
34
 * @property string $date
35
 * @property string $modified
36
 * @property array $billing
37
 * @property array $shipping
38
 * @property bool $isPayingCustomer
39
 * @property int $last_order_id
40
 *
41
 * @package WPGraphQL\WooCommerce\Model
42
 */
43
class Customer extends Model {
44
        /**
45
         * Customer constructor
46
         *
47
         * @param \WC_Customer|int|string $id - User ID.
48
         * @param bool                    $is_session - Whether the customer is a session.
49
         */
50
        public function __construct( $id = 'session', $is_session = false ) {
51
                $this->data                = 'session' === $id ? \WC()->customer : new WC_Customer( absint( $id ), $is_session );
33✔
52
                $allowed_restricted_fields = [
33✔
53
                        'isRestricted',
33✔
54
                        'isPrivate',
33✔
55
                        'isPublic',
33✔
56
                        'id',
33✔
57
                        'customerId',
33✔
58
                ];
33✔
59

60
                // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
61
                $restricted_cap = apply_filters( 'customer_restricted_cap', 'session' === $id ? '' : 'list_users' );
33✔
62

63
                parent::__construct( $restricted_cap, $allowed_restricted_fields, $this->data->get_id() );
33✔
64
        }
65

66
        /**
67
         * Forwards function calls to WC_Data sub-class instance.
68
         *
69
         * @param string $method - function name.
70
         * @param array  $args  - function call arguments.
71
         * @return mixed
72
         */
73
        public function __call( $method, $args ) {
74
                return $this->data->$method( ...$args );
2✔
75
        }
76

77
        /**
78
         * Initializes the Customer field resolvers.
79
         */
80
        protected function init() {
81
                if ( empty( $this->fields ) ) {
33✔
82
                        $this->fields = [
33✔
83
                                'ID'                    => function () {
33✔
84
                                        return ( ! empty( $this->data->get_id() ) ) ? $this->data->get_id() : \WC()->session->get_customer_id();
23✔
85
                                },
33✔
86
                                'id'                    => function () {
33✔
87
                                        return ! empty( $this->data->get_id() )
16✔
88
                                                ? Relay::toGlobalId( 'user', $this->data->get_id() )
13✔
89
                                                : 'guest';
16✔
90
                                },
33✔
91
                                'databaseId'            => function () {
33✔
UNCOV
92
                                        return ! empty( $this->ID ) ? $this->ID : null;
×
93
                                },
33✔
94
                                'isVatExempt'           => function () {
33✔
95
                                        return ! is_null( $this->data->get_is_vat_exempt() ) ? $this->data->get_is_vat_exempt() : null;
1✔
96
                                },
33✔
97
                                'hasCalculatedShipping' => function () {
33✔
98
                                        return ! is_null( $this->data->has_calculated_shipping() ) ? $this->data->has_calculated_shipping() : null;
1✔
99
                                },
33✔
100
                                'calculatedShipping'    => function () {
33✔
101
                                        return ! is_null( $this->data->get_calculated_shipping() ) ? $this->data->get_calculated_shipping() : null;
1✔
102
                                },
33✔
103
                                'orderCount'            => function () {
33✔
104
                                        return ! is_null( $this->data->get_order_count() ) ? $this->data->get_order_count() : null;
1✔
105
                                },
33✔
106
                                'totalSpent'            => function () {
33✔
107
                                        return ! is_null( $this->data->get_total_spent() ) ? $this->data->get_total_spent() : null;
1✔
108
                                },
33✔
109
                                'username'              => function () {
33✔
110
                                        return ( ! empty( $this->data->get_username() ) ) ? $this->data->get_username() : null;
10✔
111
                                },
33✔
112
                                'email'                 => function () {
33✔
113
                                        return ( ! empty( $this->data->get_email() ) ) ? $this->data->get_email() : null;
11✔
114
                                },
33✔
115
                                'firstName'             => function () {
33✔
116
                                        return ( ! empty( $this->data->get_first_name() ) ) ? $this->data->get_first_name() : null;
9✔
117
                                },
33✔
118
                                'lastName'              => function () {
33✔
119
                                        return ( ! empty( $this->data->get_last_name() ) ) ? $this->data->get_last_name() : null;
9✔
120
                                },
33✔
121
                                'displayName'           => function () {
33✔
122
                                        return ( ! empty( $this->data->get_display_name() ) ) ? $this->data->get_display_name() : null;
1✔
123
                                },
33✔
124
                                'role'                  => function () {
33✔
125
                                        return ( ! empty( $this->data->get_role() ) ) ? $this->data->get_role() : null;
1✔
126
                                },
33✔
127
                                'date'                  => function () {
33✔
128
                                        return ( ! empty( $this->data->get_date_created() ) ) ? $this->data->get_date_created() : null;
1✔
129
                                },
33✔
130
                                'modified'              => function () {
33✔
131
                                        return ( ! empty( $this->data->get_date_modified() ) ) ? $this->data->get_date_modified() : null;
1✔
132
                                },
33✔
133
                                'billing'               => function () {
33✔
134
                                        return ( ! empty( $this->data->get_billing() ) ) ? $this->data->get_billing() : null;
17✔
135
                                },
33✔
136
                                'shipping'              => function () {
33✔
137
                                        return ( ! empty( $this->data->get_shipping() ) ) ? $this->data->get_shipping() : null;
9✔
138
                                },
33✔
139
                                'isPayingCustomer'      => function () {
33✔
140
                                        return ( ! is_null( $this->data->get_is_paying_customer() ) ) ? $this->data->get_is_paying_customer() : null;
1✔
141
                                },
33✔
142
                                /**
143
                                 * Connection resolvers fields
144
                                 *
145
                                 * These field resolvers are used in connection resolvers to define WP_Query argument
146
                                 * Note: underscore naming style is used as a quick identifier
147
                                 */
148
                                'last_order_id'         => function () {
33✔
149
                                        return ( ! empty( $this->data->get_last_order() ) ) ? $this->data->get_last_order()->get_id() : null;
1✔
150
                                },
33✔
151
                        ];
33✔
152
                }//end if
153

154
                parent::prepare_fields();
33✔
155
        }
156
}
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