@@ -28,6 +28,283 @@ class WC_REST_Dev_Product_Variations_Controller extends WC_REST_Product_Variatio
2828 */
2929 protected $ namespace = 'wc/v3 ' ;
3030
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 ' => current ( $ this ->get_images ( $ 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+ if ( is_array ( $ image ) ) {
135+ $ image ['position ' ] = 0 ;
136+ }
137+
138+ $ variation = $ this ->set_product_images ( $ variation , array ( $ image ) );
139+ } else {
140+ $ variation ->set_image_id ( '' );
141+ }
142+ }
143+
144+ // Virtual variation.
145+ if ( isset ( $ request ['virtual ' ] ) ) {
146+ $ variation ->set_virtual ( $ request ['virtual ' ] );
147+ }
148+
149+ // Downloadable variation.
150+ if ( isset ( $ request ['downloadable ' ] ) ) {
151+ $ variation ->set_downloadable ( $ request ['downloadable ' ] );
152+ }
153+
154+ // Downloads.
155+ if ( $ variation ->get_downloadable () ) {
156+ // Downloadable files.
157+ if ( isset ( $ request ['downloads ' ] ) && is_array ( $ request ['downloads ' ] ) ) {
158+ $ variation = $ this ->save_downloadable_files ( $ variation , $ request ['downloads ' ] );
159+ }
160+
161+ // Download limit.
162+ if ( isset ( $ request ['download_limit ' ] ) ) {
163+ $ variation ->set_download_limit ( $ request ['download_limit ' ] );
164+ }
165+
166+ // Download expiry.
167+ if ( isset ( $ request ['download_expiry ' ] ) ) {
168+ $ variation ->set_download_expiry ( $ request ['download_expiry ' ] );
169+ }
170+ }
171+
172+ // Shipping data.
173+ $ variation = $ this ->save_product_shipping_data ( $ variation , $ request );
174+
175+ // Stock handling.
176+ if ( isset ( $ request ['manage_stock ' ] ) ) {
177+ $ variation ->set_manage_stock ( $ request ['manage_stock ' ] );
178+ }
179+
180+ if ( isset ( $ request ['in_stock ' ] ) ) {
181+ $ variation ->set_stock_status ( true === $ request ['in_stock ' ] ? 'instock ' : 'outofstock ' );
182+ }
183+
184+ if ( isset ( $ request ['backorders ' ] ) ) {
185+ $ variation ->set_backorders ( $ request ['backorders ' ] );
186+ }
187+
188+ if ( $ variation ->get_manage_stock () ) {
189+ if ( isset ( $ request ['stock_quantity ' ] ) ) {
190+ $ variation ->set_stock_quantity ( $ request ['stock_quantity ' ] );
191+ } elseif ( isset ( $ request ['inventory_delta ' ] ) ) {
192+ $ stock_quantity = wc_stock_amount ( $ variation ->get_stock_quantity () );
193+ $ stock_quantity += wc_stock_amount ( $ request ['inventory_delta ' ] );
194+ $ variation ->set_stock_quantity ( $ stock_quantity );
195+ }
196+ } else {
197+ $ variation ->set_backorders ( 'no ' );
198+ $ variation ->set_stock_quantity ( '' );
199+ }
200+
201+ // Regular Price.
202+ if ( isset ( $ request ['regular_price ' ] ) ) {
203+ $ variation ->set_regular_price ( $ request ['regular_price ' ] );
204+ }
205+
206+ // Sale Price.
207+ if ( isset ( $ request ['sale_price ' ] ) ) {
208+ $ variation ->set_sale_price ( $ request ['sale_price ' ] );
209+ }
210+
211+ if ( isset ( $ request ['date_on_sale_from ' ] ) ) {
212+ $ variation ->set_date_on_sale_from ( $ request ['date_on_sale_from ' ] );
213+ }
214+
215+ if ( isset ( $ request ['date_on_sale_from_gmt ' ] ) ) {
216+ $ variation ->set_date_on_sale_from ( $ request ['date_on_sale_from_gmt ' ] ? strtotime ( $ request ['date_on_sale_from_gmt ' ] ) : null );
217+ }
218+
219+ if ( isset ( $ request ['date_on_sale_to ' ] ) ) {
220+ $ variation ->set_date_on_sale_to ( $ request ['date_on_sale_to ' ] );
221+ }
222+
223+ if ( isset ( $ request ['date_on_sale_to_gmt ' ] ) ) {
224+ $ variation ->set_date_on_sale_to ( $ request ['date_on_sale_to_gmt ' ] ? strtotime ( $ request ['date_on_sale_to_gmt ' ] ) : null );
225+ }
226+
227+ // Tax class.
228+ if ( isset ( $ request ['tax_class ' ] ) ) {
229+ $ variation ->set_tax_class ( $ request ['tax_class ' ] );
230+ }
231+
232+ // Description.
233+ if ( isset ( $ request ['description ' ] ) ) {
234+ $ variation ->set_description ( wp_kses_post ( $ request ['description ' ] ) );
235+ }
236+
237+ // Update taxonomies.
238+ if ( isset ( $ request ['attributes ' ] ) ) {
239+ $ attributes = array ();
240+ $ parent = wc_get_product ( $ variation ->get_parent_id () );
241+ $ parent_attributes = $ parent ->get_attributes ();
242+
243+ foreach ( $ request ['attributes ' ] as $ attribute ) {
244+ $ attribute_id = 0 ;
245+ $ attribute_name = '' ;
246+
247+ // Check ID for global attributes or name for product attributes.
248+ if ( ! empty ( $ attribute ['id ' ] ) ) {
249+ $ attribute_id = absint ( $ attribute ['id ' ] );
250+ $ attribute_name = wc_attribute_taxonomy_name_by_id ( $ attribute_id );
251+ } elseif ( ! empty ( $ attribute ['name ' ] ) ) {
252+ $ attribute_name = sanitize_title ( $ attribute ['name ' ] );
253+ }
254+
255+ if ( ! $ attribute_id && ! $ attribute_name ) {
256+ continue ;
257+ }
258+
259+ if ( ! isset ( $ parent_attributes [ $ attribute_name ] ) || ! $ parent_attributes [ $ attribute_name ]->get_variation () ) {
260+ continue ;
261+ }
262+
263+ $ attribute_key = sanitize_title ( $ parent_attributes [ $ attribute_name ]->get_name () );
264+ $ attribute_value = isset ( $ attribute ['option ' ] ) ? wc_clean ( stripslashes ( $ attribute ['option ' ] ) ) : '' ;
265+
266+ if ( $ parent_attributes [ $ attribute_name ]->is_taxonomy () ) {
267+ // If dealing with a taxonomy, we need to get the slug from the name posted to the API.
268+ $ term = get_term_by ( 'name ' , $ attribute_value , $ attribute_name );
269+
270+ if ( $ term && ! is_wp_error ( $ term ) ) {
271+ $ attribute_value = $ term ->slug ;
272+ } else {
273+ $ attribute_value = sanitize_title ( $ attribute_value );
274+ }
275+ }
276+
277+ $ attributes [ $ attribute_key ] = $ attribute_value ;
278+ }
279+
280+ $ variation ->set_attributes ( $ attributes );
281+ }
282+
283+ // Menu order.
284+ if ( $ request ['menu_order ' ] ) {
285+ $ variation ->set_menu_order ( $ request ['menu_order ' ] );
286+ }
287+
288+ // Meta data.
289+ if ( is_array ( $ request ['meta_data ' ] ) ) {
290+ foreach ( $ request ['meta_data ' ] as $ meta ) {
291+ $ variation ->update_meta_data ( $ meta ['key ' ], $ meta ['value ' ], isset ( $ meta ['id ' ] ) ? $ meta ['id ' ] : '' );
292+ }
293+ }
294+
295+ /**
296+ * Filters an object before it is inserted via the REST API.
297+ *
298+ * The dynamic portion of the hook name, `$this->post_type`,
299+ * refers to the object type slug.
300+ *
301+ * @param WC_Data $variation Object object.
302+ * @param WP_REST_Request $request Request object.
303+ * @param bool $creating If is creating a new object.
304+ */
305+ return apply_filters ( "woocommerce_rest_pre_insert_ {$ this ->post_type }_object " , $ variation , $ request , $ creating );
306+ }
307+
31308 /**
32309 * Get the image for a product variation.
33310 *
@@ -152,10 +429,11 @@ public function get_item_schema() {
152429 'context ' => array ( 'view ' , 'edit ' ),
153430 'readonly ' => true ,
154431 ),
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 () ),
159437 'context ' => array ( 'view ' , 'edit ' ),
160438 ),
161439 'purchasable ' => array (
0 commit comments