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

wp-graphql / wp-graphql-woocommerce / 23675172456

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

Pull #1003

github

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

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

3346 existing lines in 124 files now uncovered.

12576 of 17717 relevant lines covered (70.98%)

55.38 hits per line

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

92.16
/includes/data/class-db-hooks.php
1
<?php
2
/**
3
 * Register hooks for the filtering DB queries.
4
 *
5
 * @package WPGraphQL\WooCommerce\Data
6
 * @since 0.14.0
7
 */
8

9
namespace WPGraphQL\WooCommerce\Data;
10

11
use Automattic\WooCommerce\Internal\DataStores\Orders\OrdersTableDataStore;
12

13
/**
14
 * Class DB_Hooks
15
 */
16
class DB_Hooks {
17
        /**
18
         * DB_Hooks constructor.
19
         */
20
        public function __construct() {
NEW
21
                add_filter( 'woocommerce_order_query_args', [ $this, 'clean_query_vars' ] );
×
UNCOV
22
                add_filter( 'woocommerce_orders_table_query_clauses', [ $this, 'add_cursor' ], 10, 3 );
×
23
        }
24

25
        /**
26
         * Meta key to COT column mapping for orderby translation.
27
         *
28
         * @var array
29
         */
30
        private static $meta_to_column = [
31
                '_order_total'    => 'total',
32
                '_order_tax'      => 'tax_amount',
33
                '_cart_discount'  => 'discount_total_amount',
34
                '_date_paid'      => 'date_paid',
35
                '_date_completed' => 'date_completed',
36
                '_order_key'      => 'payment_method',
37
        ];
38

39
        /**
40
         * Translate legacy meta_key orderby to COT column orderby in query vars.
41
         *
42
         * When HPOS is active, meta keys like _order_total are stored as columns
43
         * in the orders table, not in the meta table. This replaces meta_value_num
44
         * orderby with the direct column name so WC's OrdersTableQuery doesn't
45
         * generate an invalid meta join.
46
         *
47
         * @param array $query_vars The query vars.
48
         *
49
         * @return array
50
         */
51
        public function clean_query_vars( $query_vars ) {
52
                if ( true !== is_graphql_request() ) {
32✔
53
                        return $query_vars;
20✔
54
                }
55

56
                if ( ! \Automattic\WooCommerce\Utilities\OrderUtil::custom_orders_table_usage_is_enabled() ) {
31✔
NEW
57
                        return $query_vars;
×
58
                }
59

60
                // Map post_* orderby fields to COT-compatible equivalents.
61
                $post_field_map = [
31✔
62
                        'post_date'     => 'date',
31✔
63
                        'post_modified' => 'date_modified',
31✔
64
                        'post_parent'   => 'parent',
31✔
65
                ];
31✔
66

67
                $orderby = $query_vars['orderby'] ?? [];
31✔
68
                if ( is_array( $orderby ) ) {
31✔
69
                        foreach ( $post_field_map as $post_field => $cot_field ) {
19✔
70
                                if ( isset( $orderby[ $post_field ] ) ) {
19✔
71
                                        $orderby[ $cot_field ] = $orderby[ $post_field ];
3✔
72
                                        unset( $orderby[ $post_field ] );
3✔
73
                                }
74
                        }
75
                        $query_vars['orderby'] = $orderby;
19✔
76
                }
77

78
                // Map meta_key orderby to COT column orderby.
79
                $meta_key = $query_vars['meta_key'] ?? '';
31✔
80
                if ( empty( $meta_key ) || ! isset( self::$meta_to_column[ $meta_key ] ) ) {
31✔
81
                        return $query_vars;
28✔
82
                }
83

84
                $column        = self::$meta_to_column[ $meta_key ];
3✔
85
                $default_order = isset( $query_vars['graphql_cursor_compare'] ) && '>' === $query_vars['graphql_cursor_compare']
3✔
NEW
86
                        ? 'DESC'
×
87
                        : 'ASC';
3✔
88

89
                $orderby = $query_vars['orderby'] ?? [];
3✔
90
                if ( is_array( $orderby ) ) {
3✔
91
                        $order = $orderby['meta_value_num'] ?? ( $orderby['meta_value'] ?? $default_order );
3✔
92
                        unset( $orderby['meta_value_num'], $orderby['meta_value'] );
3✔
93
                        $orderby[ $column ] = $order;
3✔
94
                        $query_vars['orderby'] = $orderby;
3✔
95
                }
96

97
                unset( $query_vars['meta_key'] );
3✔
98

99
                return $query_vars;
3✔
100
        }
101

102
        /**
103
         * Add the cursor to the WHERE clause of the query.
104
         *
105
         * @param string[]                                                            $clauses {
106
         *                                                        Associative array of the clauses for the query.
107
         *
108
         *     @type string $fields  The SELECT clause of the query.
109
         *     @type string $join    The JOIN clause of the query.
110
         *     @type string $where   The WHERE clause of the query.
111
         *     @type string $groupby The GROUP BY clause of the query.
112
         *     @type string $orderby The ORDER BY clause of the query.
113
         *     @type string $limits  The LIMIT clause of the query.
114
         * }
115
         * @param \Automattic\WooCommerce\Internal\DataStores\Orders\OrdersTableQuery $query The OrdersTableQuery instance (passed by reference).
116
         * @param array                                                               $args  Query args.
117
         *
118
         * @return string[]
119
         */
120
        public function add_cursor( $clauses, $query, $args ) {
121
                if ( true !== is_graphql_request() ) {
32✔
122
                        return $clauses;
20✔
123
                }
124

125
                /** @var \Automattic\WooCommerce\Internal\DataStores\Orders\OrdersTableDataStore $order_datastore */
126
                $order_datastore = wc_get_container()->get( OrdersTableDataStore::class );
31✔
127
                $tables          = $order_datastore::get_all_table_names_with_id();
31✔
128

129

130
                // apply the after cursor to the query.
131
                if ( ! empty( $args['graphql_after_cursor'] ) ) {
31✔
132
                        $after_cursor      = new Cursor\COT_Cursor( $args, $query, 'after' );
8✔
133
                        $clauses['where'] .= $after_cursor->get_where();
8✔
134
                }
135

136
                // apply the before cursor to the query.
137
                if ( ! empty( $args['graphql_before_cursor'] ) ) {
31✔
138
                        $before_cursor     = new Cursor\COT_Cursor( $args, $query, 'before' );
3✔
139
                        $clauses['where'] .= $before_cursor->get_where();
3✔
140
                }
141

142
                // If the cursor "graphql_cursor_compare" arg is not in the query,
143
                // default to using ID DESC as the stabilizer.
144
                $orderby = ! empty( $clauses['orderby'] ) && is_string( $clauses['orderby'] )
31✔
145
                        ? $clauses['orderby'] . ','
30✔
146
                        : '';
1✔
147

148
                if ( ! isset( $args['graphql_cursor_compare'] ) ) {
31✔
149
                        $clauses['orderby'] = "{$orderby} {$tables['orders']}.id DESC ";
15✔
150
                } else {
151
                        // Check the cursor compare order.
152
                        $order = '>' === $args['graphql_cursor_compare'] ? 'ASC' : 'DESC';
19✔
153

154
                        $clauses['orderby'] = "{$orderby} {$tables['orders']}.id {$order} ";
19✔
155
                }
156

157
                return $clauses;
31✔
158
        }
159
}
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