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

wp-graphql / wp-graphql-woocommerce / 10274605810

06 Aug 2024 10:07PM UTC coverage: 84.595% (-0.5%) from 85.048%
10274605810

push

github

web-flow
fix: product connection resolution refactored to better work with the ProductQuery class (#880)

* fix: product connection resolution refactored to better work with the ProductQuery class

* chore: Linter and PHPStan compliance met

* devops: New product connection tests implemented and passing

* fix: products connection pricing filters fixed

* devops: CartTransactionQueueCest skipped until failing PHP version removed from CI matrix

69 of 81 new or added lines in 12 files covered. (85.19%)

138 existing lines in 7 files now uncovered.

12416 of 14677 relevant lines covered (84.59%)

71.8 hits per line

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

0.0
/includes/data/cursor/class-cot-cursor.php
1
<?php
2
/**
3
 * COT Cursor
4
 *
5
 * This class generates the SQL AND operators for cursor based pagination
6
 * for the custom orders table/HPOS
7
 *
8
 * @package WPGraphQL\WooCommerce\Data\Cursor;
9
 * @since   0.14.0
10
 */
11

12
namespace WPGraphQL\WooCommerce\Data\Cursor;
13

14
use Automattic\WooCommerce\Internal\DataStores\Orders\OrdersTableDataStore;
15
use Automattic\WooCommerce\Internal\DataStores\Orders\OrdersTableMetaQuery;
16
use WPGraphQL\Data\Cursor\AbstractCursor;
17

18
/**
19
 * Class COT_Cursor
20
 */
21
class COT_Cursor extends AbstractCursor {
22
        /**
23
         * Stores the cursory order node
24
         *
25
         * @var ?\WC_Abstract_Order
26
         */
27
        public $cursor_node;
28

29
        /**
30
         * Counter for meta value joins
31
         *
32
         * @var integer
33
         */
34
        public $meta_join_alias = 0;
35

36
        /**
37
         * The query instance to use when building the SQL statement.
38
         *
39
         * @var \Automattic\WooCommerce\Internal\DataStores\Orders\OrdersTableQuery
40
         */
41
        public $query;
42

43
        /**
44
         * Names of all COT tables (orders, addresses, operational_data, meta) in the form 'table_id' => 'table name'.
45
         *
46
         * @var array
47
         */
48
        private $tables;
49

50
        /**
51
         * Undocumented variable
52
         *
53
         * @var array
54
         */
55
        private $column_mappings;
56

57
        /**
58
         * Meta query parser.
59
         *
60
         * @var \Automattic\WooCommerce\Internal\DataStores\Orders\OrdersTableMetaQuery|null
61
         */
62
        private $meta_query;
63

64
        /**
65
         * COT_Cursor constructor.
66
         *
67
         * @param array                                                               $query_vars  The query vars to use when building the SQL statement.
68
         * @param \Automattic\WooCommerce\Internal\DataStores\Orders\OrdersTableQuery $query       The query to use when building the SQL statement.
69
         * @param string|null                                                         $cursor      Whether to generate the before or after cursor. Default "after".
70
         */
71
        public function __construct( $query_vars, $query, $cursor = 'after' ) {
72
                // Initialize the class properties.
UNCOV
73
                parent::__construct( $query_vars, $cursor );
×
74

UNCOV
75
                $this->query = $query;
×
76

77
                // Get tables.
78
                /** @var \Automattic\WooCommerce\Internal\DataStores\Orders\OrdersTableDataStore $order_datastore */
UNCOV
79
                $order_datastore       = wc_get_container()->get( OrdersTableDataStore::class );
×
UNCOV
80
                $this->tables          = $order_datastore::get_all_table_names_with_id();
×
UNCOV
81
                $mappings              = $order_datastore->get_all_order_column_mappings();
×
UNCOV
82
                $this->column_mappings = [];
×
UNCOV
83
                foreach ( $mappings['orders'] as $column => $meta_value ) {
×
UNCOV
84
                        $this->column_mappings[ "{$this->tables['orders']}.{$column}" ] = $meta_value['name'];
×
85
                }
86

UNCOV
87
                if ( ! is_null( $this->get_query_var( 'meta_query' ) ) ) {
×
UNCOV
88
                        $this->meta_query = new OrdersTableMetaQuery( $this->query );
×
89
                }
90
        }
91

92
        /**
93
         * {@inheritDoc}
94
         *
95
         * @return ?\WC_Abstract_Order
96
         */
97
        public function get_cursor_node() {
98
                // If we have a bad cursor, just skip.
UNCOV
99
                if ( ! $this->cursor_offset ) {
×
100
                        return null;
×
101
                }
102

103
                // Get the order.
UNCOV
104
                $order = wc_get_order( $this->cursor_offset );
×
105

UNCOV
106
                return $order instanceof \WC_Abstract_Order ? $order : null;
×
107
        }
108

109
        /**
110
         * {@inheritDoc}
111
         */
112
        public function to_sql() {
UNCOV
113
                $orderby = isset( $this->query_vars['orderby'] ) ? $this->query_vars['orderby'] : null;
×
114

UNCOV
115
                $orderby_should_not_convert_to_sql = isset( $orderby ) && in_array(
×
UNCOV
116
                        $orderby,
×
UNCOV
117
                        [
×
UNCOV
118
                                'include',
×
UNCOV
119
                                'id',
×
UNCOV
120
                                'parent_order_id',
×
UNCOV
121
                        ],
×
UNCOV
122
                        true
×
UNCOV
123
                );
×
124

UNCOV
125
                if ( true === $orderby_should_not_convert_to_sql ) {
×
126
                        return '';
×
127
                }
128

UNCOV
129
                $sql = $this->builder->to_sql();
×
130

UNCOV
131
                if ( empty( $sql ) ) {
×
132
                        return '';
×
133
                }
134

UNCOV
135
                return ' AND ' . $sql;
×
136
        }
137

138
        /**
139
         * {@inheritDoc}
140
         */
141
        public function get_where() {
142
                // If we have a bad cursor, just skip.
UNCOV
143
                if ( ! $this->is_valid_offset_and_node() ) {
×
144
                        return '';
×
145
                }
146

UNCOV
147
                $orderby = $this->get_query_var( 'orderby' );
×
UNCOV
148
                $order   = $this->get_query_var( 'order' );
×
149

UNCOV
150
                if ( ! empty( $orderby ) && is_array( $orderby ) ) {
×
151

152
                        /**
153
                         * Loop through all order keys if it is an array
154
                         */
UNCOV
155
                        foreach ( $orderby as $by => $order ) {
×
UNCOV
156
                                $this->compare_with( $by, $order );
×
157
                        }
158
                } elseif ( ! empty( $orderby ) && is_string( $orderby ) ) {
×
159

160
                        /**
161
                         * If $orderby is just a string just compare with it directly as DESC
162
                         */
163
                        $this->compare_with( $orderby, $order );
×
164
                }
165

166
                /**
167
                 * No custom comparing. Use the default date
168
                 */
UNCOV
169
                if ( ! $this->builder->has_fields() ) {
×
170
                        $this->compare_with_date();
×
171
                }
172

UNCOV
173
                $this->builder->add_field( "{$this->tables['orders']}.id", $this->cursor_offset, 'ID', $order );
×
174

UNCOV
175
                return $this->to_sql();
×
176
        }
177

178
        /**
179
         * Get AND operator for given order by key
180
         *
181
         * @param string $by    The order by key.
182
         * @param string $order The order direction ASC or DESC.
183
         *
184
         * @return void
185
         */
186
        private function compare_with( $by, $order ) {
UNCOV
187
                if ( null === $this->cursor_node ) {
×
188
                        return;
×
189
                }
190

UNCOV
191
                $meta_orderby_keys = $this->meta_query ? $this->meta_query->get_orderby_keys() : [];
×
192

UNCOV
193
                if ( in_array( $by, $meta_orderby_keys, true ) && null !== $this->meta_query ) {
×
194
                        $orderby = $this->meta_query->get_orderby_clause_for_key( $by );
×
195
                        $value   = $this->cursor_node->get_meta( $by, true ) ?? null;
×
196
                } else {
UNCOV
197
                        $orderby     = $by;
×
UNCOV
198
                        $getter_name = $this->column_mappings[ $orderby ];
×
199

UNCOV
200
                        $method = "get_{$getter_name}";
×
UNCOV
201
                        $value  = is_callable( [ $this->cursor_node, $method ] ) ? $this->cursor_node->$method() : null;
×
202
                }
203

UNCOV
204
                if ( ! empty( $value ) && is_a( $value, '\WC_DateTime' ) ) {
×
UNCOV
205
                        $value = ( new \DateTime( $value ) )->setTimezone( new \DateTimeZone( '+00:00' ) )->format( 'Y-m-d H:i:s' );
×
UNCOV
206
                        $this->builder->add_field( $by, $value, 'DATETIME', $order );
×
UNCOV
207
                        return;
×
208
                }
209

210
                /**
211
                 * Compare by the post field if the key matches a value
212
                 */
213
                if ( ! empty( $value ) ) {
×
214
                        $this->builder->add_field( $by, $value, null, $order );
×
215
                }
216
        }
217

218
        /**
219
         * Use post date based comparison
220
         *
221
         * @return void
222
         */
223
        private function compare_with_date() {
224
                $value = null;
×
225
                if ( null !== $this->cursor_node ) {
×
226
                        $date_created = $this->cursor_node->get_date_created();
×
227
                        $value        = ! empty( $date_created ) ? ( new \DateTime( $date_created ) )->setTimezone( new \DateTimeZone( '+00:00' ) )->format( 'Y-m-d H:i:s' ) : null;
×
228
                }
229

230
                $this->builder->add_field( "{$this->tables['orders']}.date_created_gmt", $value, 'DATETIME' );
×
231
        }
232
}
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

© 2025 Coveralls, Inc