@@ -28,26 +28,303 @@ class WC_REST_Dev_Product_Variations_Controller extends WC_REST_Product_Variatio
28
28
*/
29
29
protected $ namespace = 'wc/v3 ' ;
30
30
31
+ /**
32
+ * Prepare a single variation output for response.
33
+ *
34
+ * @param WC_Data $object Object data.
35
+ * @param WP_REST_Request $request Request object.
36
+ * @return WP_REST_Response
37
+ */
38
+ public function prepare_object_for_response ( $ object , $ request ) {
39
+ $ data = array (
40
+ 'id ' => $ object ->get_id (),
41
+ 'date_created ' => wc_rest_prepare_date_response ( $ object ->get_date_created (), false ),
42
+ 'date_created_gmt ' => wc_rest_prepare_date_response ( $ object ->get_date_created () ),
43
+ 'date_modified ' => wc_rest_prepare_date_response ( $ object ->get_date_modified (), false ),
44
+ 'date_modified_gmt ' => wc_rest_prepare_date_response ( $ object ->get_date_modified () ),
45
+ 'description ' => wc_format_content ( $ object ->get_description () ),
46
+ 'permalink ' => $ object ->get_permalink (),
47
+ 'sku ' => $ object ->get_sku (),
48
+ 'price ' => $ object ->get_price (),
49
+ 'regular_price ' => $ object ->get_regular_price (),
50
+ 'sale_price ' => $ object ->get_sale_price (),
51
+ 'date_on_sale_from ' => wc_rest_prepare_date_response ( $ object ->get_date_on_sale_from (), false ),
52
+ 'date_on_sale_from_gmt ' => wc_rest_prepare_date_response ( $ object ->get_date_on_sale_from () ),
53
+ 'date_on_sale_to ' => wc_rest_prepare_date_response ( $ object ->get_date_on_sale_to (), false ),
54
+ 'date_on_sale_to_gmt ' => wc_rest_prepare_date_response ( $ object ->get_date_on_sale_to () ),
55
+ 'on_sale ' => $ object ->is_on_sale (),
56
+ 'status ' => $ object ->get_status (),
57
+ 'purchasable ' => $ object ->is_purchasable (),
58
+ 'virtual ' => $ object ->is_virtual (),
59
+ 'downloadable ' => $ object ->is_downloadable (),
60
+ 'downloads ' => $ this ->get_downloads ( $ object ),
61
+ 'download_limit ' => '' !== $ object ->get_download_limit () ? (int ) $ object ->get_download_limit () : -1 ,
62
+ 'download_expiry ' => '' !== $ object ->get_download_expiry () ? (int ) $ object ->get_download_expiry () : -1 ,
63
+ 'tax_status ' => $ object ->get_tax_status (),
64
+ 'tax_class ' => $ object ->get_tax_class (),
65
+ 'manage_stock ' => $ object ->managing_stock (),
66
+ 'stock_quantity ' => $ object ->get_stock_quantity (),
67
+ 'in_stock ' => $ object ->is_in_stock (),
68
+ 'backorders ' => $ object ->get_backorders (),
69
+ 'backorders_allowed ' => $ object ->backorders_allowed (),
70
+ 'backordered ' => $ object ->is_on_backorder (),
71
+ 'weight ' => $ object ->get_weight (),
72
+ 'dimensions ' => array (
73
+ 'length ' => $ object ->get_length (),
74
+ 'width ' => $ object ->get_width (),
75
+ 'height ' => $ object ->get_height (),
76
+ ),
77
+ 'shipping_class ' => $ object ->get_shipping_class (),
78
+ 'shipping_class_id ' => $ object ->get_shipping_class_id (),
79
+ 'image ' => $ this ->get_image ( $ object ),
80
+ 'attributes ' => $ this ->get_attributes ( $ object ),
81
+ 'menu_order ' => $ object ->get_menu_order (),
82
+ 'meta_data ' => $ object ->get_meta_data (),
83
+ );
84
+
85
+ $ context = ! empty ( $ request ['context ' ] ) ? $ request ['context ' ] : 'view ' ;
86
+ $ data = $ this ->add_additional_fields_to_object ( $ data , $ request );
87
+ $ data = $ this ->filter_response_by_context ( $ data , $ context );
88
+ $ response = rest_ensure_response ( $ data );
89
+ $ response ->add_links ( $ this ->prepare_links ( $ object , $ request ) );
90
+
91
+ /**
92
+ * Filter the data for a response.
93
+ *
94
+ * The dynamic portion of the hook name, $this->post_type,
95
+ * refers to object type being prepared for the response.
96
+ *
97
+ * @param WP_REST_Response $response The response object.
98
+ * @param WC_Data $object Object data.
99
+ * @param WP_REST_Request $request Request object.
100
+ */
101
+ return apply_filters ( "woocommerce_rest_prepare_ {$ this ->post_type }_object " , $ response , $ object , $ request );
102
+ }
103
+
104
+ /**
105
+ * Prepare a single variation for create or update.
106
+ *
107
+ * @param WP_REST_Request $request Request object.
108
+ * @param bool $creating If is creating a new object.
109
+ * @return WP_Error|WC_Data
110
+ */
111
+ protected function prepare_object_for_database ( $ request , $ creating = false ) {
112
+ if ( isset ( $ request ['id ' ] ) ) {
113
+ $ variation = wc_get_product ( absint ( $ request ['id ' ] ) );
114
+ } else {
115
+ $ variation = new WC_Product_Variation ();
116
+ }
117
+
118
+ $ variation ->set_parent_id ( absint ( $ request ['product_id ' ] ) );
119
+
120
+ // Status.
121
+ if ( isset ( $ request ['status ' ] ) ) {
122
+ $ variation ->set_status ( get_post_status_object ( $ request ['status ' ] ) ? $ request ['status ' ] : 'draft ' );
123
+ }
124
+
125
+ // SKU.
126
+ if ( isset ( $ request ['sku ' ] ) ) {
127
+ $ variation ->set_sku ( wc_clean ( $ request ['sku ' ] ) );
128
+ }
129
+
130
+ // Thumbnail.
131
+ if ( isset ( $ request ['image ' ] ) ) {
132
+ if ( is_array ( $ request ['image ' ] ) ) {
133
+ $ image = $ request ['image ' ];
134
+ $ variation = $ this ->set_product_images ( $ variation , array ( $ image ) );
135
+ } else {
136
+ $ variation ->set_image_id ( '' );
137
+ }
138
+ }
139
+
140
+ // Virtual variation.
141
+ if ( isset ( $ request ['virtual ' ] ) ) {
142
+ $ variation ->set_virtual ( $ request ['virtual ' ] );
143
+ }
144
+
145
+ // Downloadable variation.
146
+ if ( isset ( $ request ['downloadable ' ] ) ) {
147
+ $ variation ->set_downloadable ( $ request ['downloadable ' ] );
148
+ }
149
+
150
+ // Downloads.
151
+ if ( $ variation ->get_downloadable () ) {
152
+ // Downloadable files.
153
+ if ( isset ( $ request ['downloads ' ] ) && is_array ( $ request ['downloads ' ] ) ) {
154
+ $ variation = $ this ->save_downloadable_files ( $ variation , $ request ['downloads ' ] );
155
+ }
156
+
157
+ // Download limit.
158
+ if ( isset ( $ request ['download_limit ' ] ) ) {
159
+ $ variation ->set_download_limit ( $ request ['download_limit ' ] );
160
+ }
161
+
162
+ // Download expiry.
163
+ if ( isset ( $ request ['download_expiry ' ] ) ) {
164
+ $ variation ->set_download_expiry ( $ request ['download_expiry ' ] );
165
+ }
166
+ }
167
+
168
+ // Shipping data.
169
+ $ variation = $ this ->save_product_shipping_data ( $ variation , $ request );
170
+
171
+ // Stock handling.
172
+ if ( isset ( $ request ['manage_stock ' ] ) ) {
173
+ $ variation ->set_manage_stock ( $ request ['manage_stock ' ] );
174
+ }
175
+
176
+ if ( isset ( $ request ['in_stock ' ] ) ) {
177
+ $ variation ->set_stock_status ( true === $ request ['in_stock ' ] ? 'instock ' : 'outofstock ' );
178
+ }
179
+
180
+ if ( isset ( $ request ['backorders ' ] ) ) {
181
+ $ variation ->set_backorders ( $ request ['backorders ' ] );
182
+ }
183
+
184
+ if ( $ variation ->get_manage_stock () ) {
185
+ if ( isset ( $ request ['stock_quantity ' ] ) ) {
186
+ $ variation ->set_stock_quantity ( $ request ['stock_quantity ' ] );
187
+ } elseif ( isset ( $ request ['inventory_delta ' ] ) ) {
188
+ $ stock_quantity = wc_stock_amount ( $ variation ->get_stock_quantity () );
189
+ $ stock_quantity += wc_stock_amount ( $ request ['inventory_delta ' ] );
190
+ $ variation ->set_stock_quantity ( $ stock_quantity );
191
+ }
192
+ } else {
193
+ $ variation ->set_backorders ( 'no ' );
194
+ $ variation ->set_stock_quantity ( '' );
195
+ }
196
+
197
+ // Regular Price.
198
+ if ( isset ( $ request ['regular_price ' ] ) ) {
199
+ $ variation ->set_regular_price ( $ request ['regular_price ' ] );
200
+ }
201
+
202
+ // Sale Price.
203
+ if ( isset ( $ request ['sale_price ' ] ) ) {
204
+ $ variation ->set_sale_price ( $ request ['sale_price ' ] );
205
+ }
206
+
207
+ if ( isset ( $ request ['date_on_sale_from ' ] ) ) {
208
+ $ variation ->set_date_on_sale_from ( $ request ['date_on_sale_from ' ] );
209
+ }
210
+
211
+ if ( isset ( $ request ['date_on_sale_from_gmt ' ] ) ) {
212
+ $ variation ->set_date_on_sale_from ( $ request ['date_on_sale_from_gmt ' ] ? strtotime ( $ request ['date_on_sale_from_gmt ' ] ) : null );
213
+ }
214
+
215
+ if ( isset ( $ request ['date_on_sale_to ' ] ) ) {
216
+ $ variation ->set_date_on_sale_to ( $ request ['date_on_sale_to ' ] );
217
+ }
218
+
219
+ if ( isset ( $ request ['date_on_sale_to_gmt ' ] ) ) {
220
+ $ variation ->set_date_on_sale_to ( $ request ['date_on_sale_to_gmt ' ] ? strtotime ( $ request ['date_on_sale_to_gmt ' ] ) : null );
221
+ }
222
+
223
+ // Tax class.
224
+ if ( isset ( $ request ['tax_class ' ] ) ) {
225
+ $ variation ->set_tax_class ( $ request ['tax_class ' ] );
226
+ }
227
+
228
+ // Description.
229
+ if ( isset ( $ request ['description ' ] ) ) {
230
+ $ variation ->set_description ( wp_kses_post ( $ request ['description ' ] ) );
231
+ }
232
+
233
+ // Update taxonomies.
234
+ if ( isset ( $ request ['attributes ' ] ) ) {
235
+ $ attributes = array ();
236
+ $ parent = wc_get_product ( $ variation ->get_parent_id () );
237
+ $ parent_attributes = $ parent ->get_attributes ();
238
+
239
+ foreach ( $ request ['attributes ' ] as $ attribute ) {
240
+ $ attribute_id = 0 ;
241
+ $ attribute_name = '' ;
242
+
243
+ // Check ID for global attributes or name for product attributes.
244
+ if ( ! empty ( $ attribute ['id ' ] ) ) {
245
+ $ attribute_id = absint ( $ attribute ['id ' ] );
246
+ $ attribute_name = wc_attribute_taxonomy_name_by_id ( $ attribute_id );
247
+ } elseif ( ! empty ( $ attribute ['name ' ] ) ) {
248
+ $ attribute_name = sanitize_title ( $ attribute ['name ' ] );
249
+ }
250
+
251
+ if ( ! $ attribute_id && ! $ attribute_name ) {
252
+ continue ;
253
+ }
254
+
255
+ if ( ! isset ( $ parent_attributes [ $ attribute_name ] ) || ! $ parent_attributes [ $ attribute_name ]->get_variation () ) {
256
+ continue ;
257
+ }
258
+
259
+ $ attribute_key = sanitize_title ( $ parent_attributes [ $ attribute_name ]->get_name () );
260
+ $ attribute_value = isset ( $ attribute ['option ' ] ) ? wc_clean ( stripslashes ( $ attribute ['option ' ] ) ) : '' ;
261
+
262
+ if ( $ parent_attributes [ $ attribute_name ]->is_taxonomy () ) {
263
+ // If dealing with a taxonomy, we need to get the slug from the name posted to the API.
264
+ $ term = get_term_by ( 'name ' , $ attribute_value , $ attribute_name );
265
+
266
+ if ( $ term && ! is_wp_error ( $ term ) ) {
267
+ $ attribute_value = $ term ->slug ;
268
+ } else {
269
+ $ attribute_value = sanitize_title ( $ attribute_value );
270
+ }
271
+ }
272
+
273
+ $ attributes [ $ attribute_key ] = $ attribute_value ;
274
+ }
275
+
276
+ $ variation ->set_attributes ( $ attributes );
277
+ }
278
+
279
+ // Menu order.
280
+ if ( $ request ['menu_order ' ] ) {
281
+ $ variation ->set_menu_order ( $ request ['menu_order ' ] );
282
+ }
283
+
284
+ // Meta data.
285
+ if ( is_array ( $ request ['meta_data ' ] ) ) {
286
+ foreach ( $ request ['meta_data ' ] as $ meta ) {
287
+ $ variation ->update_meta_data ( $ meta ['key ' ], $ meta ['value ' ], isset ( $ meta ['id ' ] ) ? $ meta ['id ' ] : '' );
288
+ }
289
+ }
290
+
291
+ /**
292
+ * Filters an object before it is inserted via the REST API.
293
+ *
294
+ * The dynamic portion of the hook name, `$this->post_type`,
295
+ * refers to the object type slug.
296
+ *
297
+ * @param WC_Data $variation Object object.
298
+ * @param WP_REST_Request $request Request object.
299
+ * @param bool $creating If is creating a new object.
300
+ */
301
+ return apply_filters ( "woocommerce_rest_pre_insert_ {$ this ->post_type }_object " , $ variation , $ request , $ creating );
302
+ }
303
+
31
304
/**
32
305
* Get the image for a product variation.
33
306
*
34
307
* @param WC_Product_Variation $variation Variation
35
308
* @return array
36
309
*/
37
- protected function get_images ( $ variation ) {
310
+ protected function get_image ( $ variation ) {
311
+ if ( ! has_post_thumbnail ( $ variation ->get_id () ) ) {
312
+ return ;
313
+ }
314
+
38
315
$ attachment_id = $ variation ->get_image_id ();
39
316
$ attachment_post = get_post ( $ attachment_id );
40
317
if ( is_null ( $ attachment_post ) ) {
41
- $ image = array () ;
318
+ return ;
42
319
}
43
320
44
321
$ attachment = wp_get_attachment_image_src ( $ attachment_id , 'full ' );
45
322
if ( ! is_array ( $ attachment ) ) {
46
- $ image = array () ;
323
+ return ;
47
324
}
48
325
49
326
if ( ! isset ( $ image ) ) {
50
- $ image = array (
327
+ return array (
51
328
'id ' => (int ) $ attachment_id ,
52
329
'date_created ' => wc_rest_prepare_date_response ( $ attachment_post ->post_date , false ),
53
330
'date_created_gmt ' => wc_rest_prepare_date_response ( strtotime ( $ attachment_post ->post_date_gmt ) ),
@@ -59,7 +336,7 @@ protected function get_images( $variation ) {
59
336
);
60
337
}
61
338
62
- return array ( $ image ) ;
339
+ return ;
63
340
}
64
341
65
342
/**
@@ -152,10 +429,11 @@ public function get_item_schema() {
152
429
'context ' => array ( 'view ' , 'edit ' ),
153
430
'readonly ' => true ,
154
431
),
155
- 'visible ' => array (
156
- 'description ' => __ ( "Define if the attribute is visible on the \"Additional information \" tab in the product's page. " , 'woocommerce ' ),
157
- 'type ' => 'boolean ' ,
158
- 'default ' => true ,
432
+ 'status ' => array (
433
+ 'description ' => __ ( 'Variation status. ' , 'woocommerce ' ),
434
+ 'type ' => 'string ' ,
435
+ 'default ' => 'publish ' ,
436
+ 'enum ' => array_keys ( get_post_statuses () ),
159
437
'context ' => array ( 'view ' , 'edit ' ),
160
438
),
161
439
'purchasable ' => array (
0 commit comments