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

wp-graphql / wp-graphql-woocommerce / 27448609176

12 Jun 2026 11:18PM UTC coverage: 91.8% (+0.009%) from 91.791%
27448609176

Pull #1019

github

web-flow
Merge 6a53d4c6b into 2ce9424e1
Pull Request #1019: fix: address WordPress.org plugin review (rename + prefixing + headers)

1327 of 1579 new or added lines in 200 files covered. (84.04%)

35 existing lines in 5 files now uncovered.

18528 of 20183 relevant lines covered (91.8%)

152.68 hits per line

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

98.08
/includes/type/interface/class-product.php
1
<?php
2
/**
3
 * WPInterface Type - Product
4
 *
5
 * Registers Product interface.
6
 *
7
 * @package WPGraphQL\WooCommerce\Type\WPInterface
8
 * @since   0.3.0
9
 */
10

11
namespace WPGraphQL\WooCommerce\Type\WPInterface;
12

13
use GraphQL\Error\UserError;
14
use GraphQLRelay\Relay;
15
use WPGraphQL\AppContext;
16
use WPGraphQL\WooCommerce\Data\Factory;
17

18
/**
19
 * Class - Product
20
 */
21
class Product {
22
        /**
23
         * Registers the "Product" interface.
24
         *
25
         * @return void
26
         */
27
        public static function register_interface() {
28
                // Register the fields to the Product Interface
29
                // the product interface is defined by the post_type registration.
30
                register_graphql_field(
298✔
31
                        'RootQuery',
298✔
32
                        'product',
298✔
33
                        [
298✔
34
                                'type'        => 'Product',
298✔
35
                                'description' => static function () {
298✔
36
                                        return __( 'A product object', 'graphql-for-ecommerce' );
3✔
37
                                },
298✔
38
                                'args'        => [
298✔
39
                                        'id'     => [
298✔
40
                                                'type'        => [ 'non_null' => 'ID' ],
298✔
41
                                                'description' => static function () {
298✔
42
                                                        return __( 'The ID for identifying the product', 'graphql-for-ecommerce' );
3✔
43
                                                },
298✔
44
                                        ],
298✔
45
                                        'idType' => [
298✔
46
                                                'type'        => 'ProductIdTypeEnum',
298✔
47
                                                'description' => static function () {
298✔
48
                                                        return __( 'Type of ID being used identify product', 'graphql-for-ecommerce' );
3✔
49
                                                },
298✔
50
                                        ],
298✔
51
                                ],
298✔
52
                                'resolve'     => static function ( $source, array $args, AppContext $context ) {
298✔
53
                                        $id      = isset( $args['id'] ) ? $args['id'] : null;
35✔
54
                                        $id_type = isset( $args['idType'] ) ? $args['idType'] : 'global_id';
35✔
55

56
                                        $product_id = null;
35✔
57
                                        switch ( $id_type ) {
58
                                                case 'sku':
35✔
59
                                                        $product_id = \wc_get_product_id_by_sku( $id );
1✔
60
                                                        break;
1✔
61
                                                case 'slug':
35✔
62
                                                        $query = new \WP_Query(
2✔
63
                                                                [
2✔
64
                                                                        'name'           => $id,
2✔
65
                                                                        'post_type'      => 'product',
2✔
66
                                                                        'post_status'    => 'publish',
2✔
67
                                                                        'posts_per_page' => 1,
2✔
68
                                                                        'fields'         => 'ids',
2✔
69
                                                                ]
2✔
70
                                                        );
2✔
71
                                                        /** @var int $post_id */
72
                                                        $post_id    = ! empty( $query->posts ) ? $query->posts[0] : 0;
2✔
73
                                                        $product_id = absint( $post_id );
2✔
74
                                                        break;
2✔
75
                                                case 'database_id':
34✔
76
                                                        $product_id = absint( $id );
14✔
77
                                                        break;
14✔
78
                                                case 'global_id':
21✔
79
                                                default:
80
                                                        $id_components = Relay::fromGlobalId( $id );
21✔
81
                                                        if ( empty( $id_components['id'] ) || empty( $id_components['type'] ) ) {
21✔
NEW
82
                                                                throw new UserError( __( 'The "global ID" is invalid', 'graphql-for-ecommerce' ) );
×
83
                                                        }
84
                                                        $product_id = absint( $id_components['id'] );
21✔
85
                                                        break;
21✔
86
                                        }
87

88
                                        if ( empty( $product_id ) ) {
35✔
89
                                                /* translators: %1$s: ID type, %2$s: ID value */
NEW
90
                                                throw new UserError( sprintf( __( 'No product ID was found corresponding to the %1$s: %2$s', 'graphql-for-ecommerce' ), $id_type, $id ) );
×
91
                                        }
92
                                        $product = get_post( $product_id );
35✔
93
                                        if ( ! is_object( $product ) || 'product' !== $product->post_type ) {
35✔
94
                                                /* translators: %1$s: ID type, %2$s: ID value */
NEW
95
                                                throw new UserError( sprintf( __( 'No product exists with the %1$s: %2$s', 'graphql-for-ecommerce' ), $id_type, $id ) );
×
96
                                        }
97

98
                                        return Factory::resolve_crud_object( $product_id, $context );
35✔
99
                                },
298✔
100
                        ]
298✔
101
                );
298✔
102
        }
103

104
        /**
105
         * Defines Product fields. All child type must have these fields as well.
106
         *
107
         * @return array
108
         */
109
        public static function get_fields() {
110
                return [
298✔
111
                        'type'              => [
298✔
112
                                'type'        => 'ProductTypesEnum',
298✔
113
                                'description' => static function () {
298✔
114
                                        return __( 'Product type', 'graphql-for-ecommerce' );
3✔
115
                                },
298✔
116
                        ],
298✔
117
                        'name'              => [
298✔
118
                                'type'        => 'String',
298✔
119
                                'description' => static function () {
298✔
120
                                        return __( 'Product name', 'graphql-for-ecommerce' );
3✔
121
                                },
298✔
122
                        ],
298✔
123
                        'featured'          => [
298✔
124
                                'type'        => 'Boolean',
298✔
125
                                'description' => static function () {
298✔
126
                                        return __( 'If the product is featured', 'graphql-for-ecommerce' );
3✔
127
                                },
298✔
128
                        ],
298✔
129
                        'catalogVisibility' => [
298✔
130
                                'type'        => 'CatalogVisibilityEnum',
298✔
131
                                'description' => static function () {
298✔
132
                                        return __( 'Catalog visibility', 'graphql-for-ecommerce' );
3✔
133
                                },
298✔
134
                        ],
298✔
135
                        'description'       => [
298✔
136
                                'type'        => 'String',
298✔
137
                                'description' => static function () {
298✔
138
                                        return __( 'Product description', 'graphql-for-ecommerce' );
3✔
139
                                },
298✔
140
                                'args'        => [
298✔
141
                                        'format' => [
298✔
142
                                                'type'        => 'PostObjectFieldFormatEnum',
298✔
143
                                                'description' => static function () {
298✔
144
                                                        return __( 'Format of the field output', 'graphql-for-ecommerce' );
3✔
145
                                                },
298✔
146
                                        ],
298✔
147
                                ],
298✔
148
                                'resolve'     => static function ( $source, $args ) {
298✔
149
                                        if ( isset( $args['format'] ) && 'raw' === $args['format'] ) {
4✔
150
                                                // @codingStandardsIgnoreLine.
151
                                                return $source->descriptionRaw;
2✔
152
                                        }
153
                                        return $source->description;
4✔
154
                                },
298✔
155
                        ],
298✔
156
                        'shortDescription'  => [
298✔
157
                                'type'        => 'String',
298✔
158
                                'description' => static function () {
298✔
159
                                        return __( 'Product short description', 'graphql-for-ecommerce' );
3✔
160
                                },
298✔
161
                                'args'        => [
298✔
162
                                        'format' => [
298✔
163
                                                'type'        => 'PostObjectFieldFormatEnum',
298✔
164
                                                'description' => static function () {
298✔
165
                                                        return __( 'Format of the field output', 'graphql-for-ecommerce' );
3✔
166
                                                },
298✔
167
                                        ],
298✔
168
                                ],
298✔
169
                                'resolve'     => static function ( $source, $args ) {
298✔
170
                                        if ( isset( $args['format'] ) && 'raw' === $args['format'] ) {
2✔
171
                                                // @codingStandardsIgnoreLine.
172
                                                return $source->shortDescriptionRaw;
2✔
173
                                        }
174
                                        // @codingStandardsIgnoreLine.
175
                                        return $source->shortDescription;
2✔
176
                                },
298✔
177
                        ],
298✔
178
                        'sku'               => [
298✔
179
                                'type'        => 'String',
298✔
180
                                'description' => static function () {
298✔
181
                                        return __( 'Product SKU', 'graphql-for-ecommerce' );
3✔
182
                                },
298✔
183
                        ],
298✔
184
                        'dateOnSaleFrom'    => [
298✔
185
                                'type'        => 'String',
298✔
186
                                'description' => static function () {
298✔
187
                                        return __( 'Date on sale from', 'graphql-for-ecommerce' );
3✔
188
                                },
298✔
189
                        ],
298✔
190
                        'dateOnSaleTo'      => [
298✔
191
                                'type'        => 'String',
298✔
192
                                'description' => static function () {
298✔
193
                                        return __( 'Date on sale to', 'graphql-for-ecommerce' );
3✔
194
                                },
298✔
195
                        ],
298✔
196
                        'totalSales'        => [
298✔
197
                                'type'        => 'Int',
298✔
198
                                'description' => static function () {
298✔
199
                                        return __( 'Number total of sales', 'graphql-for-ecommerce' );
3✔
200
                                },
298✔
201
                        ],
298✔
202
                        'reviewsAllowed'    => [
298✔
203
                                'type'        => 'Boolean',
298✔
204
                                'description' => static function () {
298✔
205
                                        return __( 'If reviews are allowed', 'graphql-for-ecommerce' );
3✔
206
                                },
298✔
207
                        ],
298✔
208
                        'purchaseNote'      => [
298✔
209
                                'type'        => 'String',
298✔
210
                                'description' => static function () {
298✔
211
                                        return __( 'Purchase note', 'graphql-for-ecommerce' );
3✔
212
                                },
298✔
213
                        ],
298✔
214
                        'menuOrder'         => [
298✔
215
                                'type'        => 'Int',
298✔
216
                                'description' => static function () {
298✔
217
                                        return __( 'Menu order', 'graphql-for-ecommerce' );
3✔
218
                                },
298✔
219
                        ],
298✔
220
                        'averageRating'     => [
298✔
221
                                'type'        => 'Float',
298✔
222
                                'description' => static function () {
298✔
223
                                        return __( 'Product average count', 'graphql-for-ecommerce' );
3✔
224
                                },
298✔
225
                        ],
298✔
226
                        'reviewCount'       => [
298✔
227
                                'type'        => 'Int',
298✔
228
                                'description' => static function () {
298✔
229
                                        return __( 'Product review count', 'graphql-for-ecommerce' );
3✔
230
                                },
298✔
231
                        ],
298✔
232
                        'image'             => [
298✔
233
                                'type'        => 'MediaItem',
298✔
234
                                'description' => static function () {
298✔
235
                                        return __( 'Main image', 'graphql-for-ecommerce' );
3✔
236
                                },
298✔
237
                                'resolve'     => static function ( $source, array $args, AppContext $context ) {
298✔
238
                                        // @codingStandardsIgnoreLine.
239
                                        if ( empty( $source->image_id ) || ! absint( $source->image_id ) ) {
4✔
240
                                                return null;
×
241
                                        }
242
                                        return $context->get_loader( 'post' )->load_deferred( $source->image_id );
4✔
243
                                },
298✔
244
                        ],
298✔
245
                        'onSale'            => [
298✔
246
                                'type'        => 'Boolean',
298✔
247
                                'description' => static function () {
298✔
248
                                        return __( 'Is product on sale?', 'graphql-for-ecommerce' );
3✔
249
                                },
298✔
250
                        ],
298✔
251
                        'purchasable'       => [
298✔
252
                                'type'        => 'Boolean',
298✔
253
                                'description' => static function () {
298✔
254
                                        return __( 'Can product be purchased?', 'graphql-for-ecommerce' );
3✔
255
                                },
298✔
256
                        ],
298✔
257
                        'virtual'           => [
298✔
258
                                'type'        => 'Boolean',
298✔
259
                                'description' => static function () {
298✔
260
                                        return __( 'Is product virtual?', 'graphql-for-ecommerce' );
3✔
261
                                },
298✔
262
                        ],
298✔
263
                        'metaData'          => \WPGraphQL\WooCommerce\Type\WPObject\Meta_Data_Type::get_metadata_field_definition(),
298✔
264
                ];
298✔
265
        }
266
}
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