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

wp-graphql / wp-graphql-woocommerce / 6282474781

23 Sep 2023 07:50AM UTC coverage: 84.793% (+0.1%) from 84.684%
6282474781

push

github

web-flow
feat: `collectionStats` query added (#785)

* feat: collectionStats query added

* fix: `collectionStats` query completed and tested.

* chore: Linter and PHPStan compliance met

* chore: ProductTaxonomy values fixed.

* chore: CollectionStatsQueryTest tweaked for CI

563 of 563 new or added lines in 12 files covered. (100.0%)

11029 of 13007 relevant lines covered (84.79%)

58.98 hits per line

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

83.28
/includes/type/object/class-collection-stats-type.php
1
<?php
2
/**
3
 * WPObject Type - Collection_Stats_Type
4
 *
5
 * @package WPGraphQL\WooCommerce\Type\WPObject
6
 * @since   TBD
7
 */
8

9
namespace WPGraphQL\WooCommerce\Type\WPObject;
10

11
/**
12
 * Class Collection_Stats_Type
13
 */
14
class Collection_Stats_Type {
15
        /**
16
         * Register CollectionStats type to the WPGraphQL schema
17
         *
18
         * @return void
19
         */
20
        public static function register() {
21
                register_graphql_object_type(
114✔
22
                        'PriceRange',
114✔
23
                        [
114✔
24
                                'eagerlyLoadType' => true,
114✔
25
                                'description'     => __( 'Price range', 'wp-graphql-woocommerce' ),
114✔
26
                                'fields'          => [
114✔
27
                                        'minPrice' => [
114✔
28
                                                'type'        => 'String',
114✔
29
                                                'args'        => [
114✔
30
                                                        'format' => [
114✔
31
                                                                'type'        => 'PricingFieldFormatEnum',
114✔
32
                                                                'description' => __( 'Format of the price', 'wp-graphql-woocommerce' ),
114✔
33
                                                        ],
114✔
34
                                                ],
114✔
35
                                                'description' => __( 'Minimum price', 'wp-graphql-woocommerce' ),
114✔
36
                                                'resolve'     => static function ( $source, array $args ) {
114✔
37
                                                        if ( empty( $source['min_price'] ) ) {
×
38
                                                                return null;
×
39
                                                        }
40

41
                                                        if ( isset( $args['format'] ) && 'raw' === $args['format'] ) {
×
42
                                                                return $source['min_price'];
×
43
                                                        }
44
                                                        
45
                                                        return wc_graphql_price( $source['min_price'] );
×
46
                                                },
114✔
47
                                        ],
114✔
48
                                        'maxPrice' => [
114✔
49
                                                'type'        => 'String',
114✔
50
                                                'args'        => [
114✔
51
                                                        'format' => [
114✔
52
                                                                'type'        => 'PricingFieldFormatEnum',
114✔
53
                                                                'description' => __( 'Format of the price', 'wp-graphql-woocommerce' ),
114✔
54
                                                        ],
114✔
55
                                                ],
114✔
56
                                                'description' => __( 'Maximum price', 'wp-graphql-woocommerce' ),
114✔
57
                                                'resolve'     => static function ( $source, array $args ) {
114✔
58
                                                        if ( empty( $source['max_price'] ) ) {
×
59
                                                                return null;
×
60
                                                        }
61

62
                                                        if ( isset( $args['format'] ) && 'raw' === $args['format'] ) {
×
63
                                                                return $source['max_price'];
×
64
                                                        }
65
                                                        
66
                                                        return wc_graphql_price( $source['max_price'] );
×
67
                                                },
114✔
68
                                        ],
114✔
69
                                ],
114✔
70
                        ]
114✔
71
                );
114✔
72

73
                register_graphql_object_type(
114✔
74
                        'AttributeCount',
114✔
75
                        [
114✔
76
                                'eagerlyLoadType' => true,
114✔
77
                                'description'     => __( 'Product attribute terms count', 'wp-graphql-woocommerce' ),
114✔
78
                                'fields'          => [
114✔
79
                                        'slug'  => [
114✔
80
                                                'type'        => [ 'non_null' => 'ProductAttributeEnum' ],
114✔
81
                                                'description' => __( 'Attribute name', 'wp-graphql-woocommerce' ),
114✔
82
                                                'resolve'     => static function ( $source ) {
114✔
83
                                                        return $source->name;
1✔
84
                                                },
114✔
85
                                        ],
114✔
86
                                        'label' => [
114✔
87
                                                'type'        => [ 'non_null' => 'String' ],
114✔
88
                                                'description' => __( 'Attribute taxonomy', 'wp-graphql-woocommerce' ),
114✔
89
                                                'resolve'     => static function ( $source ) {
114✔
90
                                                        $taxonomy = get_taxonomy( $source->name );
1✔
91

92
                                                        if ( ! $taxonomy instanceof \WP_Taxonomy ) {
1✔
93
                                                                return null;
×
94
                                                        }
95
                                                        return $taxonomy->label;
1✔
96
                                                },
114✔
97
                                        ],
114✔
98
                                        'name'  => [
114✔
99
                                                'type'        => [ 'non_null' => 'String' ],
114✔
100
                                                'description' => __( 'Attribute name', 'wp-graphql-woocommerce' ),
114✔
101
                                                'resolve'     => static function ( $source ) {
114✔
102
                                                        $taxonomy = get_taxonomy( $source->name );
1✔
103

104
                                                        if ( ! $taxonomy instanceof \WP_Taxonomy ) {
1✔
105
                                                                return null;
×
106
                                                        }
107
                                                        return $taxonomy->labels->singular_name;
1✔
108
                                                },
114✔
109
                                        ],
114✔
110
                                        'terms' => [
114✔
111
                                                'type'        => [ 'list_of' => 'SingleAttributeCount' ],
114✔
112
                                                'description' => __( 'Attribute terms', 'wp-graphql-woocommerce' ),
114✔
113
                                        ],
114✔
114
                                ],
114✔
115
                        ]
114✔
116
                );
114✔
117

118
                register_graphql_object_type(
114✔
119
                        'SingleAttributeCount',
114✔
120
                        [
114✔
121
                                'eagerlyLoadType' => true,
114✔
122
                                'description'     => __( 'Single attribute term count', 'wp-graphql-woocommerce' ),
114✔
123
                                'fields'          => [
114✔
124
                                        'termId' => [
114✔
125
                                                'type'        => [ 'non_null' => 'ID' ],
114✔
126
                                                'description' => __( 'Term ID', 'wp-graphql-woocommerce' ),
114✔
127
                                        ],
114✔
128
                                        'count'  => [
114✔
129
                                                'type'        => 'Int',
114✔
130
                                                'description' => __( 'Number of products.', 'wp-graphql-woocommerce' ),
114✔
131
                                        ],
114✔
132
                                        'node'   => [
114✔
133
                                                'type'        => 'TermNode',
114✔
134
                                                'description' => __( 'Term object.', 'wp-graphql-woocommerce' ),
114✔
135
                                                'resolve'     => static function ( $source ) {
114✔
136
                                                        if ( empty( $source->termId ) ) { // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
1✔
137
                                                                return null;
×
138
                                                        }
139

140
                                                        /**
141
                                                         * Term object.
142
                                                         *
143
                                                         * @var \WP_Term $term
144
                                                         */
145
                                                        $term = get_term( $source->termId ); // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
1✔
146
                                                        if ( ! $term instanceof \WP_Term ) {
1✔
147
                                                                return null;
×
148
                                                        }
149
                                                        return new \WPGraphQL\Model\Term( $term );
1✔
150
                                                },
114✔
151
                                        ],
114✔
152
                                ],
114✔
153
                        ]
114✔
154
                );
114✔
155

156
                register_graphql_object_type(
114✔
157
                        'RatingCount',
114✔
158
                        [
114✔
159
                                'eagerlyLoadType' => true,
114✔
160
                                'description'     => __( 'Single rating count', 'wp-graphql-woocommerce' ),
114✔
161
                                'fields'          => [
114✔
162
                                        'rating' => [
114✔
163
                                                'type'        => [ 'non_null' => 'Int' ],
114✔
164
                                                'description' => __( 'Average rating', 'wp-graphql-woocommerce' ),
114✔
165
                                        ],
114✔
166
                                        'count'  => [
114✔
167
                                                'type'        => 'Int',
114✔
168
                                                'description' => __( 'Number of products', 'wp-graphql-woocommerce' ),
114✔
169
                                        ],
114✔
170
                                ],
114✔
171
                        ]
114✔
172
                );
114✔
173

174
                register_graphql_object_type(
114✔
175
                        'StockStatusCount',
114✔
176
                        [
114✔
177
                                'eagerlyLoadType' => true,
114✔
178
                                'description'     => __( 'Single stock status count', 'wp-graphql-woocommerce' ),
114✔
179
                                'fields'          => [
114✔
180
                                        'status' => [
114✔
181
                                                'type'        => [ 'non_null' => 'StockStatusEnum' ],
114✔
182
                                                'description' => __( 'Status', 'wp-graphql-woocommerce' ),
114✔
183
                                        ],
114✔
184
                                        'count'  => [
114✔
185
                                                'type'        => 'Int',
114✔
186
                                                'description' => __( 'Number of products.', 'wp-graphql-woocommerce' ),
114✔
187
                                        ],
114✔
188
                                ],
114✔
189
                        ]
114✔
190
                );
114✔
191

192
                register_graphql_object_type(
114✔
193
                        'CollectionStats',
114✔
194
                        [
114✔
195
                                'description' => __( 'Data about a collection of products', 'wp-graphql-woocommerce' ),
114✔
196
                                'fields'      => [
114✔
197
                                        'priceRange'        => [
114✔
198
                                                'type'        => 'PriceRange',
114✔
199
                                                'description' => __( 'Min and max prices found in collection of products, provided using the smallest unit of the currency', 'wp-graphql-woocommerce' ),
114✔
200
                                                'resolve'     => static function ( $source ) {
114✔
201
                                                        $min_price = ! empty( $source['min_price'] ) ? $source['min_price'] : null;
×
202
                                                        $max_price = ! empty( $source['max_price'] ) ? $source['max_price'] : null;
×
203
                                                        return compact( 'min_price', 'max_price' );
×
204
                                                },
114✔
205
                                        ],
114✔
206
                                        'attributeCounts'   => [
114✔
207
                                                'type'        => [ 'list_of' => 'AttributeCount' ],
114✔
208
                                                'args'        => [
114✔
209
                                                        'page'    => [
114✔
210
                                                                'type'        => 'Int',
114✔
211
                                                                'description' => __( 'Page of results to return', 'wp-graphql-woocommerce' ),
114✔
212
                                                        ],
114✔
213
                                                        'perPage' => [
114✔
214
                                                                'type'        => 'Int',
114✔
215
                                                                'description' => __( 'Number of results to return per page', 'wp-graphql-woocommerce' ),
114✔
216
                                                        ],
114✔
217
                                                ],
114✔
218
                                                'description' => __( 'Returns number of products within attribute terms', 'wp-graphql-woocommerce' ),
114✔
219
                                                'resolve'     => static function ( $source, $args ) {
114✔
220
                                                        $page             = ! empty( $args['page'] ) ? $args['page'] : 1;
1✔
221
                                                        $per_page         = ! empty( $args['perPage'] ) ? $args['perPage'] : 0;
1✔
222
                                                        $attribute_counts = ! empty( $source['attribute_counts'] ) ? $source['attribute_counts'] : [];
1✔
223
                                                        $attribute_counts = array_slice(
1✔
224
                                                                $attribute_counts,
1✔
225
                                                                ( $page - 1 ) * $per_page,
1✔
226
                                                                0 < $per_page ? $per_page : null
1✔
227
                                                        );
1✔
228
                                
229
                                                        return array_map(
1✔
230
                                                                static function ( $name, $terms ) {
1✔
231
                                                                        return (object) compact( 'name', 'terms' );
1✔
232
                                                                },
1✔
233
                                                                array_keys( $attribute_counts ),
1✔
234
                                                                array_values( $attribute_counts )
1✔
235
                                                        );
1✔
236
                                                },
114✔
237
                                        ],
114✔
238
                                        'ratingCounts'      => [
114✔
239
                                                'type'        => [ 'list_of' => 'RatingCount' ],
114✔
240
                                                'args'        => [
114✔
241
                                                        'page'    => [
114✔
242
                                                                'type'        => 'Int',
114✔
243
                                                                'description' => __( 'Page of results to return', 'wp-graphql-woocommerce' ),
114✔
244
                                                        ],
114✔
245
                                                        'perPage' => [
114✔
246
                                                                'type'        => 'Int',
114✔
247
                                                                'description' => __( 'Number of results to return per page', 'wp-graphql-woocommerce' ),
114✔
248
                                                        ],
114✔
249
                                                ],
114✔
250
                                                'description' => __( 'Returns number of products with each average rating', 'wp-graphql-woocommerce' ),
114✔
251
                                                'resolve'     => static function ( $source, $args ) {
114✔
252
                                                        $page          = ! empty( $args['page'] ) ? $args['page'] : 1;
×
253
                                                        $per_page      = ! empty( $args['perPage'] ) ? $args['perPage'] : 0;
×
254
                                                        $rating_counts = ! empty( $source['rating_counts'] ) ? $source['rating_counts'] : [];
×
255
                                                        $rating_counts = array_slice(
×
256
                                                                $rating_counts,
×
257
                                                                ( $page - 1 ) * $per_page,
×
258
                                                                0 < $per_page ? $per_page : null
×
259
                                                        );
×
260
                                
261
                                                        return $rating_counts;
×
262
                                                },
114✔
263
                                        ],
114✔
264
                                        'stockStatusCounts' => [
114✔
265
                                                'type'        => [ 'list_of' => 'StockStatusCount' ],
114✔
266
                                                'args'        => [
114✔
267
                                                        'page'    => [
114✔
268
                                                                'type'        => 'Int',
114✔
269
                                                                'description' => __( 'Page of results to return', 'wp-graphql-woocommerce' ),
114✔
270
                                                        ],
114✔
271
                                                        'perPage' => [
114✔
272
                                                                'type'        => 'Int',
114✔
273
                                                                'description' => __( 'Number of results to return per page', 'wp-graphql-woocommerce' ),
114✔
274
                                                        ],
114✔
275
                                                ],
114✔
276
                                                'description' => __( 'Returns number of products with each stock status', 'wp-graphql-woocommerce' ),
114✔
277
                                                'resolve'     => static function ( $source, $args ) {
114✔
278
                                                        $page                = ! empty( $args['page'] ) ? $args['page'] : 1;
1✔
279
                                                        $per_page            = ! empty( $args['perPage'] ) ? $args['perPage'] : 0;
1✔
280
                                                        $stock_status_counts = ! empty( $source['stock_status_counts'] ) ? $source['stock_status_counts'] : [];
1✔
281
                                                        $stock_status_counts = array_slice(
1✔
282
                                                                $stock_status_counts,
1✔
283
                                                                ( $page - 1 ) * $per_page,
1✔
284
                                                                0 < $per_page ? $per_page : null
1✔
285
                                                        );
1✔
286
                                
287
                                                        return $stock_status_counts;
1✔
288
                                                },
114✔
289
                                        ],
114✔
290
                                ],
114✔
291
                        ]
114✔
292
                );
114✔
293
        }
294

295
        /**
296
         * Prepare the WP_Rest_Request instance used for the resolution of a
297
         * statistics for a product connection.
298
         * 
299
         * @param array $where_args  Arguments used to filter the connection results.
300
         * 
301
         * @return \WP_REST_Request
302
         */
303
        public static function prepare_rest_request( array $where_args = [] ) /* @phpstan-ignore-line */ {  
304
                $request = new \WP_REST_Request();
1✔
305
                if ( empty( $where_args ) ) {
1✔
306
                        return $request;
×
307
                }
308

309
                $key_mapping = [
1✔
310
                        'slugIn'       => 'slug',
1✔
311
                        'typeIn'       => 'type',
1✔
312
                        'categoryIdIn' => 'category',
1✔
313
                        'tagIn'        => 'tag',
1✔
314
                        'onSale'       => 'on_sale',
1✔
315
                        'stockStatus'  => 'stock_status',
1✔
316
                        'visibility'   => 'catalog_visibility',
1✔
317
                        'minPrice'     => 'min_price',
1✔
318
                        'maxPrice'     => 'max_price',
1✔
319
                ];
1✔
320

321
                $needs_formatting = [ 'attributes', 'categoryIn' ];
1✔
322
                foreach ( $where_args as $key => $value ) {
1✔
323
                        if ( in_array( $key, $needs_formatting, true ) ) {
1✔
324
                                continue;
1✔
325
                        }
326

327
                        $request->set_param( $key_mapping[ $key ] ?? $key, $value );
×
328
                }
329

330
                if ( ! empty( $where_args['categoryIn'] ) ) {
1✔
331
                        $category_ids = array_map(
×
332
                                static function ( $category ) {
×
333
                                        $term = get_term_by( 'slug', $category, 'product_cat' );
×
334
                                        if ( is_object( $term ) ) {
×
335
                                                return $term->term_id;
×
336
                                        }
337
                                        return 0;
×
338
                                },
×
339
                                $where_args['categoryIn']
×
340
                        );
×
341
                        $set_category = $request->get_param( 'category' );
×
342
                        if ( ! empty( $set_category ) ) {
×
343
                                $category_ids[] = $set_category;
×
344
                                $request->set_param( 'category', $category_ids );
×
345
                        } else {
346
                                $request->set_param( 'category', $category_ids );
×
347
                        }
348
                        $request->set_param( 'category_operator', 'and' );
×
349
                }
350
                
351
                if ( ! empty( $where_args['attributes'] ) ) {
1✔
352
                        $attributes = [];
1✔
353
                        foreach ( $where_args['attributes'] as $filter ) {
1✔
354
                                if ( str_starts_with( $filter['taxonomy'], 'pa_' ) ) {
1✔
355
                                        $attribute              = [];
1✔
356
                                        $attribute['attribute'] = $filter['taxonomy'];
1✔
357
                                        if ( ! empty( $filter['terms'] ) ) {
1✔
358
                                                $attribute['slug'] = $filter['terms'];
1✔
359
                                        } elseif ( ! empty( $filter['ids'] ) ) {
×
360
                                                $attribute['term_id'] = $filter['ids'];
×
361
                                        }
362
                                        $attribute['operator'] = ! empty( $filter['operator'] ) ? strtolower( $filter['operator'] ) : 'in';
1✔
363
                                        $attributes[]          = $attribute;
1✔
364
                                } else {
365
                                        if ( ! empty( $filter['ids'] ) ) {
×
366
                                                continue;
×
367
                                        }
368
                                        $taxonomy = $filter['taxonomy'];
×
369
                                        $request->set_param( "_unstable_tax_{$taxonomy}", $filter['ids'] );
×
370
                                        $request->set_param( "_unstable_tax_{$taxonomy}_operator", strtolower( $filter['operator'] ) );
×
371
                                }
372
                        }
373
                        if ( ! empty( $attributes ) ) { 
1✔
374
                                $request->set_param( 'attributes', $attributes );
1✔
375
                        }
376
                }//end if
377

378
                return $request;
1✔
379
        }
380
}
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