Total Complexity | 140 |
Total Lines | 1384 |
Duplicated Lines | 0 % |
Changes | 0 |
Complex classes like ProductSchema often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use ProductSchema, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
15 | class ProductSchema { |
||
16 | |||
17 | /** |
||
18 | * Return schema for products. |
||
19 | * |
||
20 | * @return array |
||
21 | */ |
||
22 | public static function get_schema() { |
||
23 | $weight_unit = get_option( 'woocommerce_weight_unit' ); |
||
24 | $dimension_unit = get_option( 'woocommerce_dimension_unit' ); |
||
25 | $schema = array( |
||
26 | '$schema' => 'http://json-schema.org/draft-04/schema#', |
||
27 | 'title' => 'product', |
||
28 | 'type' => 'object', |
||
29 | 'properties' => array( |
||
30 | 'id' => array( |
||
31 | 'description' => __( 'Unique identifier for the resource.', 'woocommerce' ), |
||
32 | 'type' => 'integer', |
||
33 | 'context' => array( 'view', 'edit', 'embed' ), |
||
34 | 'readonly' => true, |
||
35 | ), |
||
36 | 'name' => array( |
||
37 | 'description' => __( 'Product name.', 'woocommerce' ), |
||
38 | 'type' => 'string', |
||
39 | 'context' => array( 'view', 'edit', 'embed' ), |
||
40 | 'arg_options' => array( |
||
41 | 'sanitize_callback' => 'wp_filter_post_kses', |
||
42 | ), |
||
43 | ), |
||
44 | 'slug' => array( |
||
45 | 'description' => __( 'Product slug.', 'woocommerce' ), |
||
46 | 'type' => 'string', |
||
47 | 'context' => array( 'view', 'edit', 'embed' ), |
||
48 | ), |
||
49 | 'permalink' => array( |
||
50 | 'description' => __( 'Product URL.', 'woocommerce' ), |
||
51 | 'type' => 'string', |
||
52 | 'format' => 'uri', |
||
53 | 'context' => array( 'view', 'edit', 'embed' ), |
||
54 | 'readonly' => true, |
||
55 | ), |
||
56 | 'date_created' => array( |
||
57 | 'description' => __( "The date the product was created, in the site's timezone.", 'woocommerce' ), |
||
58 | 'type' => 'date-time', |
||
59 | 'context' => array( 'view', 'edit' ), |
||
60 | ), |
||
61 | 'date_created_gmt' => array( |
||
62 | 'description' => __( 'The date the product was created, as GMT.', 'woocommerce' ), |
||
63 | 'type' => 'date-time', |
||
64 | 'context' => array( 'view', 'edit' ), |
||
65 | ), |
||
66 | 'date_modified' => array( |
||
67 | 'description' => __( "The date the product was last modified, in the site's timezone.", 'woocommerce' ), |
||
68 | 'type' => 'date-time', |
||
69 | 'context' => array( 'view', 'edit' ), |
||
70 | 'readonly' => true, |
||
71 | ), |
||
72 | 'date_modified_gmt' => array( |
||
73 | 'description' => __( 'The date the product was last modified, as GMT.', 'woocommerce' ), |
||
74 | 'type' => 'date-time', |
||
75 | 'context' => array( 'view', 'edit' ), |
||
76 | 'readonly' => true, |
||
77 | ), |
||
78 | 'type' => array( |
||
79 | 'description' => __( 'Product type.', 'woocommerce' ), |
||
80 | 'type' => 'string', |
||
81 | 'default' => 'simple', |
||
82 | 'enum' => array_keys( wc_get_product_types() ), |
||
83 | 'context' => array( 'view', 'edit' ), |
||
84 | ), |
||
85 | 'status' => array( |
||
86 | 'description' => __( 'Product status (post status).', 'woocommerce' ), |
||
87 | 'type' => 'string', |
||
88 | 'default' => 'publish', |
||
89 | 'enum' => array_merge( array_keys( get_post_statuses() ), array( 'future' ) ), |
||
90 | 'context' => array( 'view', 'edit' ), |
||
91 | ), |
||
92 | 'featured' => array( |
||
93 | 'description' => __( 'Featured product.', 'woocommerce' ), |
||
94 | 'type' => 'boolean', |
||
95 | 'default' => false, |
||
96 | 'context' => array( 'view', 'edit' ), |
||
97 | ), |
||
98 | 'catalog_visibility' => array( |
||
99 | 'description' => __( 'Catalog visibility.', 'woocommerce' ), |
||
100 | 'type' => 'string', |
||
101 | 'default' => 'visible', |
||
102 | 'enum' => array( 'visible', 'catalog', 'search', 'hidden' ), |
||
103 | 'context' => array( 'view', 'edit' ), |
||
104 | ), |
||
105 | 'description' => array( |
||
106 | 'description' => __( 'Product description.', 'woocommerce' ), |
||
107 | 'type' => 'string', |
||
108 | 'context' => array( 'view', 'edit', 'embed' ), |
||
109 | 'arg_options' => array( |
||
110 | 'sanitize_callback' => 'wp_filter_post_kses', |
||
111 | ), |
||
112 | ), |
||
113 | 'short_description' => array( |
||
114 | 'description' => __( 'Product short description.', 'woocommerce' ), |
||
115 | 'type' => 'string', |
||
116 | 'context' => array( 'view', 'edit', 'embed' ), |
||
117 | 'arg_options' => array( |
||
118 | 'sanitize_callback' => 'wp_filter_post_kses', |
||
119 | ), |
||
120 | ), |
||
121 | 'sku' => array( |
||
122 | 'description' => __( 'Unique identifier.', 'woocommerce' ), |
||
123 | 'type' => 'string', |
||
124 | 'context' => array( 'view', 'edit' ), |
||
125 | 'arg_options' => array( |
||
126 | 'sanitize_callback' => 'wc_clean', |
||
127 | ), |
||
128 | ), |
||
129 | 'price' => array( |
||
130 | 'description' => __( 'Current product price.', 'woocommerce' ), |
||
131 | 'type' => 'string', |
||
132 | 'context' => array( 'view', 'edit' ), |
||
133 | 'readonly' => true, |
||
134 | ), |
||
135 | 'regular_price' => array( |
||
136 | 'description' => __( 'Product regular price.', 'woocommerce' ), |
||
137 | 'type' => 'string', |
||
138 | 'context' => array( 'view', 'edit' ), |
||
139 | ), |
||
140 | 'sale_price' => array( |
||
141 | 'description' => __( 'Product sale price.', 'woocommerce' ), |
||
142 | 'type' => 'string', |
||
143 | 'context' => array( 'view', 'edit' ), |
||
144 | ), |
||
145 | 'date_on_sale_from' => array( |
||
146 | 'description' => __( "Start date of sale price, in the site's timezone.", 'woocommerce' ), |
||
147 | 'type' => 'date-time', |
||
148 | 'context' => array( 'view', 'edit' ), |
||
149 | ), |
||
150 | 'date_on_sale_from_gmt' => array( |
||
151 | 'description' => __( 'Start date of sale price, as GMT.', 'woocommerce' ), |
||
152 | 'type' => 'date-time', |
||
153 | 'context' => array( 'view', 'edit' ), |
||
154 | ), |
||
155 | 'date_on_sale_to' => array( |
||
156 | 'description' => __( "End date of sale price, in the site's timezone.", 'woocommerce' ), |
||
157 | 'type' => 'date-time', |
||
158 | 'context' => array( 'view', 'edit' ), |
||
159 | ), |
||
160 | 'date_on_sale_to_gmt' => array( |
||
161 | 'description' => __( "End date of sale price, in the site's timezone.", 'woocommerce' ), |
||
162 | 'type' => 'date-time', |
||
163 | 'context' => array( 'view', 'edit' ), |
||
164 | ), |
||
165 | 'price_html' => array( |
||
166 | 'description' => __( 'Price formatted in HTML.', 'woocommerce' ), |
||
167 | 'type' => 'string', |
||
168 | 'context' => array( 'view', 'edit' ), |
||
169 | 'readonly' => true, |
||
170 | ), |
||
171 | 'on_sale' => array( |
||
172 | 'description' => __( 'Shows if the product is on sale.', 'woocommerce' ), |
||
173 | 'type' => 'boolean', |
||
174 | 'context' => array( 'view', 'edit' ), |
||
175 | 'readonly' => true, |
||
176 | ), |
||
177 | 'purchasable' => array( |
||
178 | 'description' => __( 'Shows if the product can be bought.', 'woocommerce' ), |
||
179 | 'type' => 'boolean', |
||
180 | 'context' => array( 'view', 'edit' ), |
||
181 | 'readonly' => true, |
||
182 | ), |
||
183 | 'total_sales' => array( |
||
184 | 'description' => __( 'Amount of sales.', 'woocommerce' ), |
||
185 | 'type' => 'integer', |
||
186 | 'context' => array( 'view', 'edit' ), |
||
187 | 'readonly' => true, |
||
188 | ), |
||
189 | 'virtual' => array( |
||
190 | 'description' => __( 'If the product is virtual.', 'woocommerce' ), |
||
191 | 'type' => 'boolean', |
||
192 | 'default' => false, |
||
193 | 'context' => array( 'view', 'edit' ), |
||
194 | ), |
||
195 | 'downloadable' => array( |
||
196 | 'description' => __( 'If the product is downloadable.', 'woocommerce' ), |
||
197 | 'type' => 'boolean', |
||
198 | 'default' => false, |
||
199 | 'context' => array( 'view', 'edit' ), |
||
200 | ), |
||
201 | 'downloads' => array( |
||
202 | 'description' => __( 'List of downloadable files.', 'woocommerce' ), |
||
203 | 'type' => 'array', |
||
204 | 'context' => array( 'view', 'edit' ), |
||
205 | 'items' => array( |
||
206 | 'type' => 'object', |
||
207 | 'properties' => array( |
||
208 | 'id' => array( |
||
209 | 'description' => __( 'File ID.', 'woocommerce' ), |
||
210 | 'type' => 'string', |
||
211 | 'context' => array( 'view', 'edit' ), |
||
212 | ), |
||
213 | 'name' => array( |
||
214 | 'description' => __( 'File name.', 'woocommerce' ), |
||
215 | 'type' => 'string', |
||
216 | 'context' => array( 'view', 'edit' ), |
||
217 | ), |
||
218 | 'file' => array( |
||
219 | 'description' => __( 'File URL.', 'woocommerce' ), |
||
220 | 'type' => 'string', |
||
221 | 'context' => array( 'view', 'edit' ), |
||
222 | ), |
||
223 | ), |
||
224 | ), |
||
225 | ), |
||
226 | 'download_limit' => array( |
||
227 | 'description' => __( 'Number of times downloadable files can be downloaded after purchase.', 'woocommerce' ), |
||
228 | 'type' => 'integer', |
||
229 | 'default' => -1, |
||
230 | 'context' => array( 'view', 'edit' ), |
||
231 | ), |
||
232 | 'download_expiry' => array( |
||
233 | 'description' => __( 'Number of days until access to downloadable files expires.', 'woocommerce' ), |
||
234 | 'type' => 'integer', |
||
235 | 'default' => -1, |
||
236 | 'context' => array( 'view', 'edit' ), |
||
237 | ), |
||
238 | 'external_url' => array( |
||
239 | 'description' => __( 'Product external URL. Only for external products.', 'woocommerce' ), |
||
240 | 'type' => 'string', |
||
241 | 'format' => 'uri', |
||
242 | 'context' => array( 'view', 'edit' ), |
||
243 | ), |
||
244 | 'button_text' => array( |
||
245 | 'description' => __( 'Product external button text. Only for external products.', 'woocommerce' ), |
||
246 | 'type' => 'string', |
||
247 | 'context' => array( 'view', 'edit' ), |
||
248 | ), |
||
249 | 'tax_status' => array( |
||
250 | 'description' => __( 'Tax status.', 'woocommerce' ), |
||
251 | 'type' => 'string', |
||
252 | 'default' => 'taxable', |
||
253 | 'enum' => array( 'taxable', 'shipping', 'none' ), |
||
254 | 'context' => array( 'view', 'edit' ), |
||
255 | ), |
||
256 | 'tax_class' => array( |
||
257 | 'description' => __( 'Tax class.', 'woocommerce' ), |
||
258 | 'type' => 'string', |
||
259 | 'context' => array( 'view', 'edit' ), |
||
260 | ), |
||
261 | 'manage_stock' => array( |
||
262 | 'description' => __( 'Stock management at product level.', 'woocommerce' ), |
||
263 | 'type' => 'boolean', |
||
264 | 'default' => false, |
||
265 | 'context' => array( 'view', 'edit' ), |
||
266 | ), |
||
267 | 'stock_quantity' => array( |
||
268 | 'description' => __( 'Stock quantity.', 'woocommerce' ), |
||
269 | 'type' => 'integer', |
||
270 | 'context' => array( 'view', 'edit' ), |
||
271 | ), |
||
272 | 'stock_status' => array( |
||
273 | 'description' => __( 'Controls the stock status of the product.', 'woocommerce' ), |
||
274 | 'type' => 'string', |
||
275 | 'default' => 'instock', |
||
276 | 'enum' => array_keys( wc_get_product_stock_status_options() ), |
||
277 | 'context' => array( 'view', 'edit' ), |
||
278 | ), |
||
279 | 'backorders' => array( |
||
280 | 'description' => __( 'If managing stock, this controls if backorders are allowed.', 'woocommerce' ), |
||
281 | 'type' => 'string', |
||
282 | 'default' => 'no', |
||
283 | 'enum' => array( 'no', 'notify', 'yes' ), |
||
284 | 'context' => array( 'view', 'edit' ), |
||
285 | ), |
||
286 | 'backorders_allowed' => array( |
||
287 | 'description' => __( 'Shows if backorders are allowed.', 'woocommerce' ), |
||
288 | 'type' => 'boolean', |
||
289 | 'context' => array( 'view', 'edit' ), |
||
290 | 'readonly' => true, |
||
291 | ), |
||
292 | 'backordered' => array( |
||
293 | 'description' => __( 'Shows if the product is on backordered.', 'woocommerce' ), |
||
294 | 'type' => 'boolean', |
||
295 | 'context' => array( 'view', 'edit' ), |
||
296 | 'readonly' => true, |
||
297 | ), |
||
298 | 'sold_individually' => array( |
||
299 | 'description' => __( 'Allow one item to be bought in a single order.', 'woocommerce' ), |
||
300 | 'type' => 'boolean', |
||
301 | 'default' => false, |
||
302 | 'context' => array( 'view', 'edit' ), |
||
303 | ), |
||
304 | 'weight' => array( |
||
305 | /* translators: %s: weight unit */ |
||
306 | 'description' => sprintf( __( 'Product weight (%s).', 'woocommerce' ), $weight_unit ), |
||
|
|||
307 | 'type' => 'string', |
||
308 | 'context' => array( 'view', 'edit' ), |
||
309 | ), |
||
310 | 'dimensions' => array( |
||
311 | 'description' => __( 'Product dimensions.', 'woocommerce' ), |
||
312 | 'type' => 'object', |
||
313 | 'context' => array( 'view', 'edit' ), |
||
314 | 'properties' => array( |
||
315 | 'length' => array( |
||
316 | /* translators: %s: dimension unit */ |
||
317 | 'description' => sprintf( __( 'Product length (%s).', 'woocommerce' ), $dimension_unit ), |
||
318 | 'type' => 'string', |
||
319 | 'context' => array( 'view', 'edit' ), |
||
320 | ), |
||
321 | 'width' => array( |
||
322 | /* translators: %s: dimension unit */ |
||
323 | 'description' => sprintf( __( 'Product width (%s).', 'woocommerce' ), $dimension_unit ), |
||
324 | 'type' => 'string', |
||
325 | 'context' => array( 'view', 'edit' ), |
||
326 | ), |
||
327 | 'height' => array( |
||
328 | /* translators: %s: dimension unit */ |
||
329 | 'description' => sprintf( __( 'Product height (%s).', 'woocommerce' ), $dimension_unit ), |
||
330 | 'type' => 'string', |
||
331 | 'context' => array( 'view', 'edit' ), |
||
332 | ), |
||
333 | ), |
||
334 | ), |
||
335 | 'shipping_required' => array( |
||
336 | 'description' => __( 'Shows if the product need to be shipped.', 'woocommerce' ), |
||
337 | 'type' => 'boolean', |
||
338 | 'context' => array( 'view', 'edit' ), |
||
339 | 'readonly' => true, |
||
340 | ), |
||
341 | 'shipping_taxable' => array( |
||
342 | 'description' => __( 'Shows whether or not the product shipping is taxable.', 'woocommerce' ), |
||
343 | 'type' => 'boolean', |
||
344 | 'context' => array( 'view', 'edit' ), |
||
345 | 'readonly' => true, |
||
346 | ), |
||
347 | 'shipping_class' => array( |
||
348 | 'description' => __( 'Shipping class slug.', 'woocommerce' ), |
||
349 | 'type' => 'string', |
||
350 | 'context' => array( 'view', 'edit' ), |
||
351 | ), |
||
352 | 'shipping_class_id' => array( |
||
353 | 'description' => __( 'Shipping class ID.', 'woocommerce' ), |
||
354 | 'type' => 'string', |
||
355 | 'context' => array( 'view', 'edit' ), |
||
356 | 'readonly' => true, |
||
357 | ), |
||
358 | 'reviews_allowed' => array( |
||
359 | 'description' => __( 'Allow reviews.', 'woocommerce' ), |
||
360 | 'type' => 'boolean', |
||
361 | 'default' => true, |
||
362 | 'context' => array( 'view', 'edit' ), |
||
363 | ), |
||
364 | 'average_rating' => array( |
||
365 | 'description' => __( 'Reviews average rating.', 'woocommerce' ), |
||
366 | 'type' => 'string', |
||
367 | 'context' => array( 'view', 'edit' ), |
||
368 | 'readonly' => true, |
||
369 | ), |
||
370 | 'rating_count' => array( |
||
371 | 'description' => __( 'Amount of reviews that the product have.', 'woocommerce' ), |
||
372 | 'type' => 'integer', |
||
373 | 'context' => array( 'view', 'edit' ), |
||
374 | 'readonly' => true, |
||
375 | ), |
||
376 | 'related_ids' => array( |
||
377 | 'description' => __( 'List of related products IDs.', 'woocommerce' ), |
||
378 | 'type' => 'array', |
||
379 | 'items' => array( |
||
380 | 'type' => 'integer', |
||
381 | ), |
||
382 | 'context' => array( 'view', 'edit' ), |
||
383 | 'readonly' => true, |
||
384 | ), |
||
385 | 'upsell_ids' => array( |
||
386 | 'description' => __( 'List of up-sell products IDs.', 'woocommerce' ), |
||
387 | 'type' => 'array', |
||
388 | 'items' => array( |
||
389 | 'type' => 'integer', |
||
390 | ), |
||
391 | 'context' => array( 'view', 'edit' ), |
||
392 | ), |
||
393 | 'cross_sell_ids' => array( |
||
394 | 'description' => __( 'List of cross-sell products IDs.', 'woocommerce' ), |
||
395 | 'type' => 'array', |
||
396 | 'items' => array( |
||
397 | 'type' => 'integer', |
||
398 | ), |
||
399 | 'context' => array( 'view', 'edit' ), |
||
400 | ), |
||
401 | 'parent_id' => array( |
||
402 | 'description' => __( 'Product parent ID.', 'woocommerce' ), |
||
403 | 'type' => 'integer', |
||
404 | 'context' => array( 'view', 'edit' ), |
||
405 | ), |
||
406 | 'purchase_note' => array( |
||
407 | 'description' => __( 'Optional note to send the customer after purchase.', 'woocommerce' ), |
||
408 | 'type' => 'string', |
||
409 | 'context' => array( 'view', 'edit' ), |
||
410 | 'arg_options' => array( |
||
411 | 'sanitize_callback' => 'wp_kses_post', |
||
412 | ), |
||
413 | ), |
||
414 | 'categories' => array( |
||
415 | 'description' => __( 'List of categories.', 'woocommerce' ), |
||
416 | 'type' => 'array', |
||
417 | 'context' => array( 'view', 'edit' ), |
||
418 | 'items' => array( |
||
419 | 'type' => 'object', |
||
420 | 'properties' => array( |
||
421 | 'id' => array( |
||
422 | 'description' => __( 'Category ID.', 'woocommerce' ), |
||
423 | 'type' => 'integer', |
||
424 | 'context' => array( 'view', 'edit' ), |
||
425 | ), |
||
426 | 'name' => array( |
||
427 | 'description' => __( 'Category name.', 'woocommerce' ), |
||
428 | 'type' => 'string', |
||
429 | 'context' => array( 'view', 'edit' ), |
||
430 | 'readonly' => true, |
||
431 | ), |
||
432 | 'slug' => array( |
||
433 | 'description' => __( 'Category slug.', 'woocommerce' ), |
||
434 | 'type' => 'string', |
||
435 | 'context' => array( 'view', 'edit' ), |
||
436 | 'readonly' => true, |
||
437 | ), |
||
438 | ), |
||
439 | ), |
||
440 | ), |
||
441 | 'tags' => array( |
||
442 | 'description' => __( 'List of tags.', 'woocommerce' ), |
||
443 | 'type' => 'array', |
||
444 | 'context' => array( 'view', 'edit' ), |
||
445 | 'items' => array( |
||
446 | 'type' => 'object', |
||
447 | 'properties' => array( |
||
448 | 'id' => array( |
||
449 | 'description' => __( 'Tag ID.', 'woocommerce' ), |
||
450 | 'type' => 'integer', |
||
451 | 'context' => array( 'view', 'edit' ), |
||
452 | ), |
||
453 | 'name' => array( |
||
454 | 'description' => __( 'Tag name.', 'woocommerce' ), |
||
455 | 'type' => 'string', |
||
456 | 'context' => array( 'view', 'edit' ), |
||
457 | 'readonly' => true, |
||
458 | ), |
||
459 | 'slug' => array( |
||
460 | 'description' => __( 'Tag slug.', 'woocommerce' ), |
||
461 | 'type' => 'string', |
||
462 | 'context' => array( 'view', 'edit' ), |
||
463 | 'readonly' => true, |
||
464 | ), |
||
465 | ), |
||
466 | ), |
||
467 | ), |
||
468 | 'images' => array( |
||
469 | 'description' => __( 'List of images.', 'woocommerce' ), |
||
470 | 'type' => 'object', |
||
471 | 'context' => array( 'view', 'edit', 'embed' ), |
||
472 | 'items' => array( |
||
473 | 'type' => 'object', |
||
474 | 'properties' => array( |
||
475 | 'id' => array( |
||
476 | 'description' => __( 'Image ID.', 'woocommerce' ), |
||
477 | 'type' => 'integer', |
||
478 | 'context' => array( 'view', 'edit' ), |
||
479 | ), |
||
480 | 'date_created' => array( |
||
481 | 'description' => __( "The date the image was created, in the site's timezone.", 'woocommerce' ), |
||
482 | 'type' => 'date-time', |
||
483 | 'context' => array( 'view', 'edit' ), |
||
484 | 'readonly' => true, |
||
485 | ), |
||
486 | 'date_created_gmt' => array( |
||
487 | 'description' => __( 'The date the image was created, as GMT.', 'woocommerce' ), |
||
488 | 'type' => 'date-time', |
||
489 | 'context' => array( 'view', 'edit' ), |
||
490 | 'readonly' => true, |
||
491 | ), |
||
492 | 'date_modified' => array( |
||
493 | 'description' => __( "The date the image was last modified, in the site's timezone.", 'woocommerce' ), |
||
494 | 'type' => 'date-time', |
||
495 | 'context' => array( 'view', 'edit' ), |
||
496 | 'readonly' => true, |
||
497 | ), |
||
498 | 'date_modified_gmt' => array( |
||
499 | 'description' => __( 'The date the image was last modified, as GMT.', 'woocommerce' ), |
||
500 | 'type' => 'date-time', |
||
501 | 'context' => array( 'view', 'edit' ), |
||
502 | 'readonly' => true, |
||
503 | ), |
||
504 | 'src' => array( |
||
505 | 'description' => __( 'Image URL.', 'woocommerce' ), |
||
506 | 'type' => 'string', |
||
507 | 'format' => 'uri', |
||
508 | 'context' => array( 'view', 'edit' ), |
||
509 | ), |
||
510 | 'name' => array( |
||
511 | 'description' => __( 'Image name.', 'woocommerce' ), |
||
512 | 'type' => 'string', |
||
513 | 'context' => array( 'view', 'edit' ), |
||
514 | ), |
||
515 | 'alt' => array( |
||
516 | 'description' => __( 'Image alternative text.', 'woocommerce' ), |
||
517 | 'type' => 'string', |
||
518 | 'context' => array( 'view', 'edit' ), |
||
519 | ), |
||
520 | ), |
||
521 | ), |
||
522 | ), |
||
523 | 'attributes' => array( |
||
524 | 'description' => __( 'List of attributes.', 'woocommerce' ), |
||
525 | 'type' => 'array', |
||
526 | 'context' => array( 'view', 'edit' ), |
||
527 | 'items' => array( |
||
528 | 'type' => 'object', |
||
529 | 'properties' => array( |
||
530 | 'id' => array( |
||
531 | 'description' => __( 'Attribute ID.', 'woocommerce' ), |
||
532 | 'type' => 'integer', |
||
533 | 'context' => array( 'view', 'edit' ), |
||
534 | ), |
||
535 | 'name' => array( |
||
536 | 'description' => __( 'Attribute name.', 'woocommerce' ), |
||
537 | 'type' => 'string', |
||
538 | 'context' => array( 'view', 'edit' ), |
||
539 | ), |
||
540 | 'position' => array( |
||
541 | 'description' => __( 'Attribute position.', 'woocommerce' ), |
||
542 | 'type' => 'integer', |
||
543 | 'context' => array( 'view', 'edit' ), |
||
544 | ), |
||
545 | 'visible' => array( |
||
546 | 'description' => __( "Define if the attribute is visible on the \"Additional information\" tab in the product's page.", 'woocommerce' ), |
||
547 | 'type' => 'boolean', |
||
548 | 'default' => false, |
||
549 | 'context' => array( 'view', 'edit' ), |
||
550 | ), |
||
551 | 'variation' => array( |
||
552 | 'description' => __( 'Define if the attribute can be used as variation.', 'woocommerce' ), |
||
553 | 'type' => 'boolean', |
||
554 | 'default' => false, |
||
555 | 'context' => array( 'view', 'edit' ), |
||
556 | ), |
||
557 | 'options' => array( |
||
558 | 'description' => __( 'List of available term names of the attribute.', 'woocommerce' ), |
||
559 | 'type' => 'array', |
||
560 | 'items' => array( |
||
561 | 'type' => 'string', |
||
562 | ), |
||
563 | 'context' => array( 'view', 'edit' ), |
||
564 | ), |
||
565 | ), |
||
566 | ), |
||
567 | ), |
||
568 | 'default_attributes' => array( |
||
569 | 'description' => __( 'Defaults variation attributes.', 'woocommerce' ), |
||
570 | 'type' => 'array', |
||
571 | 'context' => array( 'view', 'edit' ), |
||
572 | 'items' => array( |
||
573 | 'type' => 'object', |
||
574 | 'properties' => array( |
||
575 | 'id' => array( |
||
576 | 'description' => __( 'Attribute ID.', 'woocommerce' ), |
||
577 | 'type' => 'integer', |
||
578 | 'context' => array( 'view', 'edit' ), |
||
579 | ), |
||
580 | 'name' => array( |
||
581 | 'description' => __( 'Attribute name.', 'woocommerce' ), |
||
582 | 'type' => 'string', |
||
583 | 'context' => array( 'view', 'edit' ), |
||
584 | ), |
||
585 | 'option' => array( |
||
586 | 'description' => __( 'Selected attribute term name.', 'woocommerce' ), |
||
587 | 'type' => 'string', |
||
588 | 'context' => array( 'view', 'edit' ), |
||
589 | ), |
||
590 | ), |
||
591 | ), |
||
592 | ), |
||
593 | 'variations' => array( |
||
594 | 'description' => __( 'List of variations IDs.', 'woocommerce' ), |
||
595 | 'type' => 'array', |
||
596 | 'context' => array( 'view', 'edit' ), |
||
597 | 'items' => array( |
||
598 | 'type' => 'integer', |
||
599 | ), |
||
600 | 'readonly' => true, |
||
601 | ), |
||
602 | 'grouped_products' => array( |
||
603 | 'description' => __( 'List of grouped products ID.', 'woocommerce' ), |
||
604 | 'type' => 'array', |
||
605 | 'items' => array( |
||
606 | 'type' => 'integer', |
||
607 | ), |
||
608 | 'context' => array( 'view', 'edit' ), |
||
609 | 'readonly' => true, |
||
610 | ), |
||
611 | 'menu_order' => array( |
||
612 | 'description' => __( 'Menu order, used to custom sort products.', 'woocommerce' ), |
||
613 | 'type' => 'integer', |
||
614 | 'context' => array( 'view', 'edit' ), |
||
615 | ), |
||
616 | 'meta_data' => array( |
||
617 | 'description' => __( 'Meta data.', 'woocommerce' ), |
||
618 | 'type' => 'array', |
||
619 | 'context' => array( 'view', 'edit' ), |
||
620 | 'items' => array( |
||
621 | 'type' => 'object', |
||
622 | 'properties' => array( |
||
623 | 'id' => array( |
||
624 | 'description' => __( 'Meta ID.', 'woocommerce' ), |
||
625 | 'type' => 'integer', |
||
626 | 'context' => array( 'view', 'edit' ), |
||
627 | 'readonly' => true, |
||
628 | ), |
||
629 | 'key' => array( |
||
630 | 'description' => __( 'Meta key.', 'woocommerce' ), |
||
631 | 'type' => 'string', |
||
632 | 'context' => array( 'view', 'edit' ), |
||
633 | ), |
||
634 | 'value' => array( |
||
635 | 'description' => __( 'Meta value.', 'woocommerce' ), |
||
636 | 'type' => 'mixed', |
||
637 | 'context' => array( 'view', 'edit' ), |
||
638 | ), |
||
639 | ), |
||
640 | ), |
||
641 | ), |
||
642 | ), |
||
643 | ); |
||
644 | return $schema; |
||
645 | } |
||
646 | |||
647 | /** |
||
648 | * Convert object to match data in the schema. |
||
649 | * |
||
650 | * @param \WC_Product $object Product instance. |
||
651 | * @param string $context Request context. Options: 'view' and 'edit'. |
||
652 | * @return array |
||
653 | */ |
||
654 | public static function object_to_schema( $object, $context ) { |
||
655 | $data = array( |
||
656 | 'id' => $object->get_id(), |
||
657 | 'name' => $object->get_name( $context ), |
||
658 | 'slug' => $object->get_slug( $context ), |
||
659 | 'permalink' => $object->get_permalink(), |
||
660 | 'date_created' => wc_rest_prepare_date_response( $object->get_date_created( $context ), false ), |
||
661 | 'date_created_gmt' => wc_rest_prepare_date_response( $object->get_date_created( $context ) ), |
||
662 | 'date_modified' => wc_rest_prepare_date_response( $object->get_date_modified( $context ), false ), |
||
663 | 'date_modified_gmt' => wc_rest_prepare_date_response( $object->get_date_modified( $context ) ), |
||
664 | 'type' => $object->get_type(), |
||
665 | 'status' => $object->get_status( $context ), |
||
666 | 'featured' => $object->is_featured(), |
||
667 | 'catalog_visibility' => $object->get_catalog_visibility( $context ), |
||
668 | 'description' => 'view' === $context ? wpautop( do_shortcode( $object->get_description() ) ) : $object->get_description( $context ), |
||
669 | 'short_description' => 'view' === $context ? apply_filters( 'woocommerce_short_description', $object->get_short_description() ) : $object->get_short_description( $context ), |
||
670 | 'sku' => $object->get_sku( $context ), |
||
671 | 'price' => $object->get_price( $context ), |
||
672 | 'regular_price' => $object->get_regular_price( $context ), |
||
673 | 'sale_price' => $object->get_sale_price( $context ) ? $object->get_sale_price( $context ) : '', |
||
674 | 'date_on_sale_from' => wc_rest_prepare_date_response( $object->get_date_on_sale_from( $context ), false ), |
||
675 | 'date_on_sale_from_gmt' => wc_rest_prepare_date_response( $object->get_date_on_sale_from( $context ) ), |
||
676 | 'date_on_sale_to' => wc_rest_prepare_date_response( $object->get_date_on_sale_to( $context ), false ), |
||
677 | 'date_on_sale_to_gmt' => wc_rest_prepare_date_response( $object->get_date_on_sale_to( $context ) ), |
||
678 | 'price_html' => $object->get_price_html(), |
||
679 | 'on_sale' => $object->is_on_sale( $context ), |
||
680 | 'purchasable' => $object->is_purchasable(), |
||
681 | 'total_sales' => $object->get_total_sales( $context ), |
||
682 | 'virtual' => $object->is_virtual(), |
||
683 | 'downloadable' => $object->is_downloadable(), |
||
684 | 'downloads' => self::get_downloads( $object ), |
||
685 | 'download_limit' => $object->get_download_limit( $context ), |
||
686 | 'download_expiry' => $object->get_download_expiry( $context ), |
||
687 | 'external_url' => $object->is_type( 'external' ) ? $object->get_product_url( $context ) : '', |
||
688 | 'button_text' => $object->is_type( 'external' ) ? $object->get_button_text( $context ) : '', |
||
689 | 'tax_status' => $object->get_tax_status( $context ), |
||
690 | 'tax_class' => $object->get_tax_class( $context ), |
||
691 | 'manage_stock' => $object->managing_stock(), |
||
692 | 'stock_quantity' => $object->get_stock_quantity( $context ), |
||
693 | 'stock_status' => $object->get_stock_status( $context ), |
||
694 | 'backorders' => $object->get_backorders( $context ), |
||
695 | 'backorders_allowed' => $object->backorders_allowed(), |
||
696 | 'backordered' => $object->is_on_backorder(), |
||
697 | 'sold_individually' => $object->is_sold_individually(), |
||
698 | 'weight' => $object->get_weight( $context ), |
||
699 | 'dimensions' => array( |
||
700 | 'length' => $object->get_length( $context ), |
||
701 | 'width' => $object->get_width( $context ), |
||
702 | 'height' => $object->get_height( $context ), |
||
703 | ), |
||
704 | 'shipping_required' => $object->needs_shipping(), |
||
705 | 'shipping_taxable' => $object->is_shipping_taxable(), |
||
706 | 'shipping_class' => $object->get_shipping_class(), |
||
707 | 'shipping_class_id' => $object->get_shipping_class_id( $context ), |
||
708 | 'reviews_allowed' => $object->get_reviews_allowed( $context ), |
||
709 | 'average_rating' => 'view' === $context ? wc_format_decimal( $object->get_average_rating(), 2 ) : $object->get_average_rating( $context ), |
||
710 | 'rating_count' => $object->get_rating_count(), |
||
711 | 'related_ids' => array_map( 'absint', array_values( wc_get_related_products( $object->get_id() ) ) ), |
||
712 | 'upsell_ids' => array_map( 'absint', $object->get_upsell_ids( $context ) ), |
||
713 | 'cross_sell_ids' => array_map( 'absint', $object->get_cross_sell_ids( $context ) ), |
||
714 | 'parent_id' => $object->get_parent_id( $context ), |
||
715 | 'purchase_note' => 'view' === $context ? wpautop( do_shortcode( wp_kses_post( $object->get_purchase_note() ) ) ) : $object->get_purchase_note( $context ), |
||
716 | 'categories' => self::get_taxonomy_terms( $object ), |
||
717 | 'tags' => self::get_taxonomy_terms( $object, 'tag' ), |
||
718 | 'images' => self::get_images( $object ), |
||
719 | 'attributes' => self::get_attributes( $object ), |
||
720 | 'default_attributes' => self::get_default_attributes( $object ), |
||
721 | 'variations' => array(), |
||
722 | 'grouped_products' => array(), |
||
723 | 'menu_order' => $object->get_menu_order( $context ), |
||
724 | 'meta_data' => $object->get_meta_data(), |
||
725 | ); |
||
726 | |||
727 | // Add variations to variable products. |
||
728 | if ( $object->is_type( 'variable' ) && $object->has_child() ) { |
||
729 | $data['variations'] = $object->get_children(); |
||
730 | } |
||
731 | |||
732 | // Add grouped products data. |
||
733 | if ( $object->is_type( 'grouped' ) && $object->has_child() ) { |
||
734 | $data['grouped_products'] = $object->get_children(); |
||
735 | } |
||
736 | |||
737 | return $data; |
||
738 | } |
||
739 | |||
740 | /** |
||
741 | * Take data in the format of the schema and convert to a product object. |
||
742 | * |
||
743 | * @param \WP_REST_Request $request Request object. |
||
744 | * @return \WP_Error|\WC_Product |
||
745 | */ |
||
746 | public static function schema_to_object( $request ) { |
||
747 | $id = isset( $request['id'] ) ? (int) $request['id'] : 0; |
||
748 | |||
749 | if ( isset( $request['type'] ) ) { |
||
750 | $classname = '\\' . \WC_Product_Factory::get_classname_from_product_type( $request['type'] ); |
||
751 | |||
752 | if ( ! class_exists( $classname ) ) { |
||
753 | $classname = '\\WC_Product_Simple'; |
||
754 | } |
||
755 | |||
756 | $object = new $classname( $id ); |
||
757 | } elseif ( isset( $request['id'] ) ) { |
||
758 | $object = wc_get_product( $id ); |
||
759 | } else { |
||
760 | $object = new \WC_Product_Simple(); |
||
761 | } |
||
762 | |||
763 | if ( $object->is_type( 'variation' ) ) { |
||
764 | return new \WP_Error( |
||
765 | 'woocommerce_rest_invalid_product_id', |
||
766 | __( 'To manipulate product variations you should use the /products/<product_id>/variations/<id> endpoint.', 'woocommerce' ), |
||
767 | array( |
||
768 | 'status' => 404, |
||
769 | ) |
||
770 | ); |
||
771 | } |
||
772 | |||
773 | self::set_object_data( $object, $request ); |
||
774 | |||
775 | return $object; |
||
776 | } |
||
777 | |||
778 | /** |
||
779 | * Set object data from a request. |
||
780 | * |
||
781 | * @param \WC_Product $object Product object. |
||
782 | * @param \WP_REST_Request $request Request object. |
||
783 | */ |
||
784 | protected static function set_object_data( &$object, $request ) { |
||
785 | $props_to_set = [ |
||
786 | 'name', |
||
787 | 'sku', |
||
788 | 'description', |
||
789 | 'short_description', |
||
790 | 'slug', |
||
791 | 'menu_order', |
||
792 | 'reviews_allowed', |
||
793 | 'virtual', |
||
794 | 'tax_status', |
||
795 | 'tax_class', |
||
796 | 'catalog_visibility', |
||
797 | 'purchase_note', |
||
798 | 'status', |
||
799 | 'featured', |
||
800 | 'regular_price', |
||
801 | 'sale_price', |
||
802 | 'date_on_sale_from', |
||
803 | 'date_on_sale_from_gmt', |
||
804 | 'date_on_sale_to', |
||
805 | 'date_on_sale_to_gmt', |
||
806 | 'parent_id', |
||
807 | 'sold_individually', |
||
808 | 'manage_stock', |
||
809 | 'backorders', |
||
810 | 'stock_status', |
||
811 | 'stock_quantity', |
||
812 | 'downloadable', |
||
813 | 'button_text', |
||
814 | 'download_limit', |
||
815 | 'download_expiry', |
||
816 | ]; |
||
817 | |||
818 | foreach ( $props_to_set as $prop ) { |
||
819 | if ( isset( $request[ $prop ] ) && is_callable( array( $object, "set_$prop" ) ) ) { |
||
820 | $object->{"set_$prop"}( $request[ $prop ] ); |
||
821 | } |
||
822 | } |
||
823 | |||
824 | if ( isset( $request['external_url'] ) && is_callable( array( $object, 'set_product_url' ) ) ) { |
||
825 | $object->set_product_url( $request['external_url'] ); |
||
826 | } |
||
827 | |||
828 | if ( ! empty( $request['date_created'] ) ) { |
||
829 | $date = rest_parse_date( $request['date_created'] ); |
||
830 | |||
831 | if ( $date ) { |
||
832 | $object->set_date_created( $date ); |
||
833 | } |
||
834 | } |
||
835 | |||
836 | if ( ! empty( $request['date_created_gmt'] ) ) { |
||
837 | $date = rest_parse_date( $request['date_created_gmt'], true ); |
||
838 | |||
839 | if ( $date ) { |
||
840 | $object->set_date_created( $date ); |
||
841 | } |
||
842 | } |
||
843 | |||
844 | if ( isset( $request['upsell_ids'] ) ) { |
||
845 | $object->set_upsell_ids( wp_parse_id_list( $request['upsell_ids'] ) ); |
||
846 | } |
||
847 | |||
848 | if ( isset( $request['cross_sell_ids'] ) ) { |
||
849 | $object->set_cross_sell_ids( wp_parse_id_list( $request['cross_sell_ids'] ) ); |
||
850 | } |
||
851 | |||
852 | // Set children for a grouped product. |
||
853 | if ( $object->is_type( 'grouped' ) && isset( $request['grouped_products'] ) ) { |
||
854 | $object->set_children( $request['grouped_products'] ); |
||
855 | } |
||
856 | |||
857 | // Allow set meta_data. |
||
858 | if ( isset( $request['meta_data'] ) ) { |
||
859 | foreach ( $request['meta_data'] as $meta ) { |
||
860 | $object->update_meta_data( $meta['key'], $meta['value'], isset( $meta['id'] ) ? $meta['id'] : '' ); |
||
861 | } |
||
862 | } |
||
863 | |||
864 | // Save default attributes for variable products. |
||
865 | if ( $object->is_type( 'variable' ) && isset( $request['default_attributes'] ) ) { |
||
866 | self::set_default_attributes( $object, $request['default_attributes'] ); |
||
867 | } |
||
868 | |||
869 | // Check for featured/gallery images, upload it and set it. |
||
870 | if ( isset( $request['images'] ) ) { |
||
871 | self::set_images( $object, $request['images'] ); |
||
872 | } |
||
873 | |||
874 | // Product categories. |
||
875 | if ( isset( $request['categories'] ) ) { |
||
876 | self::set_taxonomy_terms( $object, $request['categories'] ); |
||
877 | } |
||
878 | |||
879 | // Product tags. |
||
880 | if ( isset( $request['tags'] ) ) { |
||
881 | self::set_taxonomy_terms( $object, $request['tags'], 'tag' ); |
||
882 | } |
||
883 | |||
884 | // Downloadable files. |
||
885 | if ( isset( $request['downloads'] ) && is_array( $request['downloads'] ) ) { |
||
886 | self::set_downloadable_files( $object, $request['downloads'] ); |
||
887 | } |
||
888 | |||
889 | if ( isset( $request['attributes'] ) ) { |
||
890 | self::set_attributes( $object, $request['attributes'] ); |
||
891 | } |
||
892 | |||
893 | self::set_shipping_data( $object, $request ); |
||
894 | |||
895 | return $object; |
||
896 | } |
||
897 | |||
898 | /** |
||
899 | * Get the downloads for a product or product variation. |
||
900 | * |
||
901 | * @param \WC_Product|\WC_Product_Variation $object Product instance. |
||
902 | * |
||
903 | * @return array |
||
904 | */ |
||
905 | protected static function get_downloads( $object ) { |
||
906 | $downloads = array(); |
||
907 | |||
908 | if ( $object->is_downloadable() ) { |
||
909 | foreach ( $object->get_downloads() as $file_id => $file ) { |
||
910 | $downloads[] = array( |
||
911 | 'id' => $file_id, // MD5 hash. |
||
912 | 'name' => $file['name'], |
||
913 | 'file' => $file['file'], |
||
914 | ); |
||
915 | } |
||
916 | } |
||
917 | |||
918 | return $downloads; |
||
919 | } |
||
920 | |||
921 | /** |
||
922 | * Get taxonomy terms. |
||
923 | * |
||
924 | * @param \WC_Product $object Product instance. |
||
925 | * @param string $taxonomy Taxonomy slug. |
||
926 | * |
||
927 | * @return array |
||
928 | */ |
||
929 | protected static function get_taxonomy_terms( $object, $taxonomy = 'cat' ) { |
||
930 | $terms = array(); |
||
931 | |||
932 | foreach ( wc_get_object_terms( $object->get_id(), 'product_' . $taxonomy ) as $term ) { |
||
933 | $terms[] = array( |
||
934 | 'id' => $term->term_id, |
||
935 | 'name' => $term->name, |
||
936 | 'slug' => $term->slug, |
||
937 | ); |
||
938 | } |
||
939 | |||
940 | return $terms; |
||
941 | } |
||
942 | |||
943 | /** |
||
944 | * Get the images for a product or product variation. |
||
945 | * |
||
946 | * @param \WC_Product|\WC_Product_Variation $object Product instance. |
||
947 | * @return array |
||
948 | */ |
||
949 | protected static function get_images( $object ) { |
||
950 | $images = array(); |
||
951 | $attachment_ids = array(); |
||
952 | |||
953 | // Add featured image. |
||
954 | if ( $object->get_image_id() ) { |
||
955 | $attachment_ids[] = $object->get_image_id(); |
||
956 | } |
||
957 | |||
958 | // Add gallery images. |
||
959 | $attachment_ids = array_merge( $attachment_ids, $object->get_gallery_image_ids() ); |
||
960 | |||
961 | // Build image data. |
||
962 | foreach ( $attachment_ids as $attachment_id ) { |
||
963 | $attachment_post = get_post( $attachment_id ); |
||
964 | if ( is_null( $attachment_post ) ) { |
||
965 | continue; |
||
966 | } |
||
967 | |||
968 | $attachment = wp_get_attachment_image_src( $attachment_id, 'full' ); |
||
969 | if ( ! is_array( $attachment ) ) { |
||
970 | continue; |
||
971 | } |
||
972 | |||
973 | $images[] = array( |
||
974 | 'id' => (int) $attachment_id, |
||
975 | 'date_created' => wc_rest_prepare_date_response( $attachment_post->post_date, false ), |
||
976 | 'date_created_gmt' => wc_rest_prepare_date_response( strtotime( $attachment_post->post_date_gmt ) ), |
||
977 | 'date_modified' => wc_rest_prepare_date_response( $attachment_post->post_modified, false ), |
||
978 | 'date_modified_gmt' => wc_rest_prepare_date_response( strtotime( $attachment_post->post_modified_gmt ) ), |
||
979 | 'src' => current( $attachment ), |
||
980 | 'name' => get_the_title( $attachment_id ), |
||
981 | 'alt' => get_post_meta( $attachment_id, '_wp_attachment_image_alt', true ), |
||
982 | ); |
||
983 | } |
||
984 | |||
985 | return $images; |
||
986 | } |
||
987 | |||
988 | /** |
||
989 | * Get product attribute taxonomy name. |
||
990 | * |
||
991 | * @param string $slug Taxonomy name. |
||
992 | * @param \WC_Product $object Product data. |
||
993 | * |
||
994 | * @since 3.0.0 |
||
995 | * @return string |
||
996 | */ |
||
997 | protected static function get_attribute_taxonomy_name( $slug, $object ) { |
||
998 | // Format slug so it matches attributes of the product. |
||
999 | $slug = wc_attribute_taxonomy_slug( $slug ); |
||
1000 | $attributes = $object->get_attributes(); |
||
1001 | $attribute = false; |
||
1002 | |||
1003 | // pa_ attributes. |
||
1004 | if ( isset( $attributes[ wc_attribute_taxonomy_name( $slug ) ] ) ) { |
||
1005 | $attribute = $attributes[ wc_attribute_taxonomy_name( $slug ) ]; |
||
1006 | } elseif ( isset( $attributes[ $slug ] ) ) { |
||
1007 | $attribute = $attributes[ $slug ]; |
||
1008 | } |
||
1009 | |||
1010 | if ( ! $attribute ) { |
||
1011 | return $slug; |
||
1012 | } |
||
1013 | |||
1014 | // Taxonomy attribute name. |
||
1015 | if ( $attribute->is_taxonomy() ) { |
||
1016 | $taxonomy = $attribute->get_taxonomy_object(); |
||
1017 | return $taxonomy->attribute_label; |
||
1018 | } |
||
1019 | |||
1020 | // Custom product attribute name. |
||
1021 | return $attribute->get_name(); |
||
1022 | } |
||
1023 | |||
1024 | /** |
||
1025 | * Get default attributes. |
||
1026 | * |
||
1027 | * @param \WC_Product $object Product instance. |
||
1028 | * |
||
1029 | * @return array |
||
1030 | */ |
||
1031 | protected static function get_default_attributes( $object ) { |
||
1032 | $default = array(); |
||
1033 | |||
1034 | if ( $object->is_type( 'variable' ) ) { |
||
1035 | foreach ( array_filter( (array) $object->get_default_attributes(), 'strlen' ) as $key => $value ) { |
||
1036 | if ( 0 === strpos( $key, 'pa_' ) ) { |
||
1037 | $default[] = array( |
||
1038 | 'id' => wc_attribute_taxonomy_id_by_name( $key ), |
||
1039 | 'name' => self::get_attribute_taxonomy_name( $key, $object ), |
||
1040 | 'option' => $value, |
||
1041 | ); |
||
1042 | } else { |
||
1043 | $default[] = array( |
||
1044 | 'id' => 0, |
||
1045 | 'name' => self::get_attribute_taxonomy_name( $key, $object ), |
||
1046 | 'option' => $value, |
||
1047 | ); |
||
1048 | } |
||
1049 | } |
||
1050 | } |
||
1051 | |||
1052 | return $default; |
||
1053 | } |
||
1054 | |||
1055 | /** |
||
1056 | * Get attribute options. |
||
1057 | * |
||
1058 | * @param int $object_id Product ID. |
||
1059 | * @param array $attribute Attribute data. |
||
1060 | * |
||
1061 | * @return array |
||
1062 | */ |
||
1063 | protected static function get_attribute_options( $object_id, $attribute ) { |
||
1064 | if ( isset( $attribute['is_taxonomy'] ) && $attribute['is_taxonomy'] ) { |
||
1065 | return wc_get_product_terms( |
||
1066 | $object_id, |
||
1067 | $attribute['name'], |
||
1068 | array( |
||
1069 | 'fields' => 'names', |
||
1070 | ) |
||
1071 | ); |
||
1072 | } elseif ( isset( $attribute['value'] ) ) { |
||
1073 | return array_map( 'trim', explode( '|', $attribute['value'] ) ); |
||
1074 | } |
||
1075 | |||
1076 | return array(); |
||
1077 | } |
||
1078 | |||
1079 | /** |
||
1080 | * Get the attributes for a product or product variation. |
||
1081 | * |
||
1082 | * @param \WC_Product|\WC_Product_Variation $object Product instance. |
||
1083 | * |
||
1084 | * @return array |
||
1085 | */ |
||
1086 | protected static function get_attributes( $object ) { |
||
1087 | $attributes = array(); |
||
1088 | |||
1089 | if ( $object->is_type( 'variation' ) ) { |
||
1090 | $_product = wc_get_product( $object->get_parent_id() ); |
||
1091 | foreach ( $object->get_variation_attributes() as $attribute_name => $attribute ) { |
||
1092 | $name = str_replace( 'attribute_', '', $attribute_name ); |
||
1093 | |||
1094 | if ( empty( $attribute ) && '0' !== $attribute ) { |
||
1095 | continue; |
||
1096 | } |
||
1097 | |||
1098 | // Taxonomy-based attributes are prefixed with `pa_`, otherwise simply `attribute_`. |
||
1099 | if ( 0 === strpos( $attribute_name, 'attribute_pa_' ) ) { |
||
1100 | $option_term = get_term_by( 'slug', $attribute, $name ); |
||
1101 | $attributes[] = array( |
||
1102 | 'id' => wc_attribute_taxonomy_id_by_name( $name ), |
||
1103 | 'name' => self::get_attribute_taxonomy_name( $name, $_product ), |
||
1104 | 'option' => $option_term && ! is_wp_error( $option_term ) ? $option_term->name : $attribute, |
||
1105 | ); |
||
1106 | } else { |
||
1107 | $attributes[] = array( |
||
1108 | 'id' => 0, |
||
1109 | 'name' => self::get_attribute_taxonomy_name( $name, $_product ), |
||
1110 | 'option' => $attribute, |
||
1111 | ); |
||
1112 | } |
||
1113 | } |
||
1114 | } else { |
||
1115 | foreach ( $object->get_attributes() as $attribute ) { |
||
1116 | $attributes[] = array( |
||
1117 | 'id' => $attribute['is_taxonomy'] ? wc_attribute_taxonomy_id_by_name( $attribute['name'] ) : 0, |
||
1118 | 'name' => self::get_attribute_taxonomy_name( $attribute['name'], $object ), |
||
1119 | 'position' => (int) $attribute['position'], |
||
1120 | 'visible' => (bool) $attribute['is_visible'], |
||
1121 | 'variation' => (bool) $attribute['is_variation'], |
||
1122 | 'options' => self::get_attribute_options( $object->get_id(), $attribute ), |
||
1123 | ); |
||
1124 | } |
||
1125 | } |
||
1126 | |||
1127 | return $attributes; |
||
1128 | } |
||
1129 | |||
1130 | /** |
||
1131 | * Set product object's attributes. |
||
1132 | * |
||
1133 | * @param \WC_Product $object Product object. |
||
1134 | * @param array $raw_attributes Attribute data from request. |
||
1135 | */ |
||
1136 | protected static function set_attributes( &$object, $raw_attributes ) { |
||
1199 | } |
||
1200 | |||
1201 | /** |
||
1202 | * Set product images. |
||
1203 | * |
||
1204 | * @throws \WC_REST_Exception REST API exceptions. |
||
1205 | * |
||
1206 | * @param \WC_Product $object Product instance. |
||
1207 | * @param array $images Images data. |
||
1208 | */ |
||
1209 | protected static function set_images( &$object, $images ) { |
||
1210 | $images = is_array( $images ) ? array_filter( $images ) : array(); |
||
1211 | |||
1212 | if ( ! empty( $images ) ) { |
||
1213 | $gallery = array(); |
||
1214 | |||
1215 | foreach ( $images as $index => $image ) { |
||
1216 | $attachment_id = isset( $image['id'] ) ? absint( $image['id'] ) : 0; |
||
1217 | |||
1218 | if ( 0 === $attachment_id && isset( $image['src'] ) ) { |
||
1219 | $upload = wc_rest_upload_image_from_url( esc_url_raw( $image['src'] ) ); |
||
1220 | |||
1221 | if ( is_wp_error( $upload ) ) { |
||
1222 | if ( ! apply_filters( 'woocommerce_rest_suppress_image_upload_error', false, $upload, $object->get_id(), $images ) ) { |
||
1223 | throw new \WC_REST_Exception( 'woocommerce_product_image_upload_error', $upload->get_error_message(), 400 ); |
||
1224 | } else { |
||
1225 | continue; |
||
1226 | } |
||
1227 | } |
||
1228 | |||
1229 | $attachment_id = wc_rest_set_uploaded_image_as_attachment( $upload, $object->get_id() ); |
||
1230 | } |
||
1231 | |||
1232 | if ( ! wp_attachment_is_image( $attachment_id ) ) { |
||
1233 | /* translators: %s: image ID */ |
||
1234 | throw new \WC_REST_Exception( 'woocommerce_product_invalid_image_id', sprintf( __( '#%s is an invalid image ID.', 'woocommerce' ), $attachment_id ), 400 ); |
||
1235 | } |
||
1236 | |||
1237 | $featured_image = $object->get_image_id(); |
||
1238 | |||
1239 | if ( 0 === $index ) { |
||
1240 | $object->set_image_id( $attachment_id ); |
||
1241 | } else { |
||
1242 | $gallery[] = $attachment_id; |
||
1243 | } |
||
1244 | |||
1245 | // Set the image alt if present. |
||
1246 | if ( ! empty( $image['alt'] ) ) { |
||
1247 | update_post_meta( $attachment_id, '_wp_attachment_image_alt', wc_clean( $image['alt'] ) ); |
||
1248 | } |
||
1249 | |||
1250 | // Set the image name if present. |
||
1251 | if ( ! empty( $image['name'] ) ) { |
||
1252 | wp_update_post( |
||
1253 | array( |
||
1254 | 'ID' => $attachment_id, |
||
1255 | 'post_title' => $image['name'], |
||
1256 | ) |
||
1257 | ); |
||
1258 | } |
||
1259 | } |
||
1260 | |||
1261 | $object->set_gallery_image_ids( $gallery ); |
||
1262 | } else { |
||
1263 | $object->set_image_id( '' ); |
||
1264 | $object->set_gallery_image_ids( array() ); |
||
1265 | } |
||
1266 | } |
||
1267 | |||
1268 | /** |
||
1269 | * Set product shipping data. |
||
1270 | * |
||
1271 | * @param \WC_Product $object Product instance. |
||
1272 | * @param array $data Shipping data. |
||
1273 | */ |
||
1274 | protected static function set_shipping_data( &$object, $data ) { |
||
1275 | if ( $object->get_virtual() ) { |
||
1276 | $object->set_weight( '' ); |
||
1277 | $object->set_height( '' ); |
||
1278 | $object->set_length( '' ); |
||
1279 | $object->set_width( '' ); |
||
1280 | } else { |
||
1281 | if ( isset( $data['weight'] ) ) { |
||
1282 | $object->set_weight( $data['weight'] ); |
||
1283 | } |
||
1284 | |||
1285 | // Height. |
||
1286 | if ( isset( $data['dimensions']['height'] ) ) { |
||
1287 | $object->set_height( $data['dimensions']['height'] ); |
||
1288 | } |
||
1289 | |||
1290 | // Width. |
||
1291 | if ( isset( $data['dimensions']['width'] ) ) { |
||
1292 | $object->set_width( $data['dimensions']['width'] ); |
||
1293 | } |
||
1294 | |||
1295 | // Length. |
||
1296 | if ( isset( $data['dimensions']['length'] ) ) { |
||
1297 | $object->set_length( $data['dimensions']['length'] ); |
||
1298 | } |
||
1299 | } |
||
1300 | |||
1301 | // Shipping class. |
||
1302 | if ( isset( $data['shipping_class'] ) ) { |
||
1303 | $data_store = $object->get_data_store(); |
||
1304 | $shipping_class_id = $data_store->get_shipping_class_id_by_slug( wc_clean( $data['shipping_class'] ) ); |
||
1305 | $object->set_shipping_class_id( $shipping_class_id ); |
||
1306 | } |
||
1307 | } |
||
1308 | |||
1309 | /** |
||
1310 | * Save downloadable files. |
||
1311 | * |
||
1312 | * @param \WC_Product $object Product instance. |
||
1313 | * @param array $downloads Downloads data. |
||
1314 | */ |
||
1315 | protected static function set_downloadable_files( &$object, $downloads ) { |
||
1329 | } |
||
1330 | |||
1331 | /** |
||
1332 | * Save taxonomy terms. |
||
1333 | * |
||
1334 | * @param \WC_Product $object Product instance. |
||
1335 | * @param array $terms Terms data. |
||
1336 | * @param string $taxonomy Taxonomy name. |
||
1337 | */ |
||
1338 | protected static function set_taxonomy_terms( &$object, $terms, $taxonomy = 'cat' ) { |
||
1339 | $term_ids = wp_list_pluck( $terms, 'id' ); |
||
1340 | |||
1341 | if ( 'cat' === $taxonomy ) { |
||
1342 | $object->set_category_ids( $term_ids ); |
||
1343 | } elseif ( 'tag' === $taxonomy ) { |
||
1344 | $object->set_tag_ids( $term_ids ); |
||
1345 | } |
||
1346 | } |
||
1347 | |||
1348 | /** |
||
1349 | * Save default attributes. |
||
1350 | * |
||
1351 | * @param \WC_Product $object Product instance. |
||
1352 | * @param array $raw_default_attributes Default attributes. |
||
1353 | */ |
||
1354 | protected static function set_default_attributes( &$object, $raw_default_attributes ) { |
||
1399 | } |
||
1400 | } |
||
1401 |