@@ -28,26 +28,303 @@ 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 ' => $ 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+
31304 /**
32305 * Get the image for a product variation.
33306 *
34307 * @param WC_Product_Variation $variation Variation
35308 * @return array
36309 */
37- protected function get_images ( $ variation ) {
310+ protected function get_image ( $ variation ) {
311+ if ( ! has_post_thumbnail ( $ variation ->get_id () ) ) {
312+ return ;
313+ }
314+
38315 $ attachment_id = $ variation ->get_image_id ();
39316 $ attachment_post = get_post ( $ attachment_id );
40317 if ( is_null ( $ attachment_post ) ) {
41- $ image = array () ;
318+ return ;
42319 }
43320
44321 $ attachment = wp_get_attachment_image_src ( $ attachment_id , 'full ' );
45322 if ( ! is_array ( $ attachment ) ) {
46- $ image = array () ;
323+ return ;
47324 }
48325
49326 if ( ! isset ( $ image ) ) {
50- $ image = array (
327+ return array (
51328 'id ' => (int ) $ attachment_id ,
52329 'date_created ' => wc_rest_prepare_date_response ( $ attachment_post ->post_date , false ),
53330 'date_created_gmt ' => wc_rest_prepare_date_response ( strtotime ( $ attachment_post ->post_date_gmt ) ),
@@ -59,7 +336,7 @@ protected function get_images( $variation ) {
59336 );
60337 }
61338
62- return array ( $ image ) ;
339+ return ;
63340 }
64341
65342 /**
@@ -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