1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* Product Variation |
4
|
|
|
* |
5
|
|
|
* The WooCommerce product variation class handles product variation data. |
6
|
|
|
* |
7
|
|
|
* @package WooCommerce/Classes |
8
|
|
|
* @version 3.0.0 |
9
|
|
|
*/ |
10
|
|
|
|
11
|
|
|
defined( 'ABSPATH' ) || exit; |
12
|
|
|
|
13
|
|
|
/** |
14
|
|
|
* Product variation class. |
15
|
|
|
*/ |
16
|
|
|
class WC_Product_Variation extends WC_Product_Simple { |
17
|
|
|
|
18
|
|
|
/** |
19
|
|
|
* Post type. |
20
|
|
|
* |
21
|
|
|
* @var string |
22
|
|
|
*/ |
23
|
|
|
protected $post_type = 'product_variation'; |
24
|
|
|
|
25
|
|
|
/** |
26
|
|
|
* Parent data. |
27
|
|
|
* |
28
|
|
|
* @var array |
29
|
|
|
*/ |
30
|
|
|
protected $parent_data = array( |
31
|
|
|
'title' => '', |
32
|
|
|
'sku' => '', |
33
|
|
|
'manage_stock' => '', |
34
|
|
|
'backorders' => '', |
35
|
|
|
'stock_quantity' => '', |
36
|
|
|
'weight' => '', |
37
|
|
|
'length' => '', |
38
|
|
|
'width' => '', |
39
|
|
|
'height' => '', |
40
|
|
|
'tax_class' => '', |
41
|
|
|
'shipping_class_id' => '', |
42
|
|
|
'image_id' => '', |
43
|
|
|
'purchase_note' => '', |
44
|
|
|
); |
45
|
|
|
|
46
|
|
|
/** |
47
|
|
|
* Override the default constructor to set custom defaults. |
48
|
|
|
* |
49
|
|
|
* @param int|WC_Product|object $product Product to init. |
50
|
|
|
*/ |
51
|
31 |
|
public function __construct( $product = 0 ) { |
52
|
31 |
|
$this->data['tax_class'] = 'parent'; |
53
|
31 |
|
$this->data['attribute_summary'] = ''; |
54
|
31 |
|
parent::__construct( $product ); |
55
|
|
|
} |
56
|
|
|
|
57
|
|
|
/** |
58
|
|
|
* Prefix for action and filter hooks on data. |
59
|
|
|
* |
60
|
|
|
* @since 3.0.0 |
61
|
|
|
* @return string |
62
|
|
|
*/ |
63
|
31 |
|
protected function get_hook_prefix() { |
64
|
31 |
|
return 'woocommerce_product_variation_get_'; |
65
|
|
|
} |
66
|
|
|
|
67
|
|
|
/** |
68
|
|
|
* Get internal type. |
69
|
|
|
* |
70
|
|
|
* @return string |
71
|
|
|
*/ |
72
|
31 |
|
public function get_type() { |
73
|
31 |
|
return 'variation'; |
74
|
|
|
} |
75
|
|
|
|
76
|
|
|
/** |
77
|
|
|
* If the stock level comes from another product ID. |
78
|
|
|
* |
79
|
|
|
* @since 3.0.0 |
80
|
|
|
* @return int |
81
|
|
|
*/ |
82
|
|
|
public function get_stock_managed_by_id() { |
83
|
|
|
return 'parent' === $this->get_manage_stock() ? $this->get_parent_id() : $this->get_id(); |
84
|
|
|
} |
85
|
|
|
|
86
|
|
|
/** |
87
|
|
|
* Get the product's title. For variations this is the parent product name. |
88
|
|
|
* |
89
|
|
|
* @return string |
90
|
|
|
*/ |
91
|
|
|
public function get_title() { |
92
|
|
|
return apply_filters( 'woocommerce_product_title', $this->parent_data['title'], $this ); |
93
|
|
|
} |
94
|
|
|
|
95
|
|
|
/** |
96
|
|
|
* Get product name with SKU or ID. Used within admin. |
97
|
|
|
* |
98
|
|
|
* @return string Formatted product name |
99
|
|
|
*/ |
100
|
|
|
public function get_formatted_name() { |
101
|
|
|
if ( $this->get_sku() ) { |
102
|
|
|
$identifier = $this->get_sku(); |
103
|
|
|
} else { |
104
|
|
|
$identifier = '#' . $this->get_id(); |
105
|
|
|
} |
106
|
|
|
|
107
|
|
|
$formatted_variation_list = wc_get_formatted_variation( $this, true, true, true ); |
108
|
|
|
|
109
|
|
|
return sprintf( '%2$s (%1$s)', $identifier, $this->get_name() ) . '<span class="description">' . $formatted_variation_list . '</span>'; |
110
|
|
|
} |
111
|
|
|
|
112
|
|
|
/** |
113
|
|
|
* Get variation attribute values. Keys are prefixed with attribute_, as stored. |
114
|
|
|
* |
115
|
|
|
* @return array of attributes and their values for this variation |
116
|
|
|
*/ |
117
|
29 |
|
public function get_variation_attributes() { |
118
|
29 |
|
$attributes = $this->get_attributes(); |
119
|
29 |
|
$variation_attributes = array(); |
120
|
29 |
|
foreach ( $attributes as $key => $value ) { |
121
|
20 |
|
$variation_attributes[ 'attribute_' . $key ] = $value; |
122
|
|
|
} |
123
|
29 |
|
return $variation_attributes; |
124
|
|
|
} |
125
|
|
|
|
126
|
|
|
/** |
127
|
|
|
* Returns a single product attribute as a string. |
128
|
|
|
* |
129
|
|
|
* @param string $attribute to get. |
130
|
|
|
* @return string |
131
|
|
|
*/ |
132
|
|
|
public function get_attribute( $attribute ) { |
133
|
|
|
$attributes = $this->get_attributes(); |
134
|
|
|
$attribute = sanitize_title( $attribute ); |
135
|
|
|
|
136
|
|
View Code Duplication |
if ( isset( $attributes[ $attribute ] ) ) { |
137
|
|
|
$value = $attributes[ $attribute ]; |
138
|
|
|
$term = taxonomy_exists( $attribute ) ? get_term_by( 'slug', $value, $attribute ) : false; |
139
|
|
|
return ! is_wp_error( $term ) && $term ? $term->name : $value; |
140
|
|
|
} |
141
|
|
|
|
142
|
|
|
$att_str = 'pa_' . $attribute; |
143
|
|
View Code Duplication |
if ( isset( $attributes[ $att_str ] ) ) { |
144
|
|
|
$value = $attributes[ $att_str ]; |
145
|
|
|
$term = taxonomy_exists( $att_str ) ? get_term_by( 'slug', $value, $att_str ) : false; |
146
|
|
|
return ! is_wp_error( $term ) && $term ? $term->name : $value; |
147
|
|
|
} |
148
|
|
|
|
149
|
|
|
return ''; |
150
|
|
|
} |
151
|
|
|
|
152
|
|
|
/** |
153
|
|
|
* Wrapper for get_permalink. Adds this variations attributes to the URL. |
154
|
|
|
* |
155
|
|
|
* @param array|null $item_object item array If a cart or order item is passed, we can get a link containing the exact attributes selected for the variation, rather than the default attributes. |
156
|
|
|
* @return string |
157
|
|
|
*/ |
158
|
29 |
|
public function get_permalink( $item_object = null ) { |
159
|
29 |
|
$url = get_permalink( $this->get_parent_id() ); |
160
|
|
|
|
161
|
29 |
|
if ( ! empty( $item_object['variation'] ) ) { |
162
|
|
|
$data = $item_object['variation']; |
163
|
29 |
|
} elseif ( ! empty( $item_object['item_meta_array'] ) ) { |
164
|
|
|
$data_keys = array_map( 'wc_variation_attribute_name', wp_list_pluck( $item_object['item_meta_array'], 'key' ) ); |
165
|
|
|
$data_values = wp_list_pluck( $item_object['item_meta_array'], 'value' ); |
166
|
|
|
$data = array_intersect_key( array_combine( $data_keys, $data_values ), $this->get_variation_attributes() ); |
167
|
|
|
} else { |
168
|
29 |
|
$data = $this->get_variation_attributes(); |
169
|
|
|
} |
170
|
|
|
|
171
|
29 |
|
$data = array_filter( $data, 'wc_array_filter_default_attributes' ); |
172
|
|
|
|
173
|
29 |
|
if ( empty( $data ) ) { |
174
|
29 |
|
return $url; |
175
|
|
|
} |
176
|
|
|
|
177
|
|
|
// Filter and encode keys and values so this is not broken by add_query_arg. |
178
|
|
|
$data = array_map( 'urlencode', $data ); |
179
|
|
|
$keys = array_map( 'urlencode', array_keys( $data ) ); |
180
|
|
|
|
181
|
|
|
return add_query_arg( array_combine( $keys, $data ), $url ); |
182
|
|
|
} |
183
|
|
|
|
184
|
|
|
/** |
185
|
|
|
* Get the add to url used mainly in loops. |
186
|
|
|
* |
187
|
|
|
* @return string |
188
|
|
|
*/ |
189
|
|
|
public function add_to_cart_url() { |
190
|
|
|
$url = $this->is_purchasable() ? remove_query_arg( |
191
|
|
|
'added-to-cart', |
192
|
|
|
add_query_arg( |
193
|
|
|
array( |
194
|
|
|
'variation_id' => $this->get_id(), |
195
|
|
|
'add-to-cart' => $this->get_parent_id(), |
196
|
|
|
), |
197
|
|
|
$this->get_permalink() |
198
|
|
|
) |
199
|
|
|
) : $this->get_permalink(); |
200
|
|
|
return apply_filters( 'woocommerce_product_add_to_cart_url', $url, $this ); |
201
|
|
|
} |
202
|
|
|
|
203
|
|
|
/** |
204
|
|
|
* Get SKU (Stock-keeping unit) - product unique ID. |
205
|
|
|
* |
206
|
|
|
* @param string $context What the value is for. Valid values are view and edit. |
207
|
|
|
* @return string |
208
|
|
|
*/ |
209
|
31 |
|
public function get_sku( $context = 'view' ) { |
210
|
31 |
|
$value = $this->get_prop( 'sku', $context ); |
211
|
|
|
|
212
|
|
|
// Inherit value from parent. |
213
|
31 |
|
if ( 'view' === $context && empty( $value ) ) { |
214
|
|
|
$value = apply_filters( $this->get_hook_prefix() . 'sku', $this->parent_data['sku'], $this ); |
215
|
|
|
} |
216
|
31 |
|
return $value; |
217
|
|
|
} |
218
|
|
|
|
219
|
|
|
/** |
220
|
|
|
* Returns the product's weight. |
221
|
|
|
* |
222
|
|
|
* @param string $context What the value is for. Valid values are view and edit. |
223
|
|
|
* @return string |
224
|
|
|
*/ |
225
|
31 |
|
public function get_weight( $context = 'view' ) { |
226
|
31 |
|
$value = $this->get_prop( 'weight', $context ); |
227
|
|
|
|
228
|
|
|
// Inherit value from parent. |
229
|
31 |
|
if ( 'view' === $context && empty( $value ) ) { |
230
|
6 |
|
$value = apply_filters( $this->get_hook_prefix() . 'weight', $this->parent_data['weight'], $this ); |
231
|
|
|
} |
232
|
31 |
|
return $value; |
233
|
|
|
} |
234
|
|
|
|
235
|
|
|
/** |
236
|
|
|
* Returns the product length. |
237
|
|
|
* |
238
|
|
|
* @param string $context What the value is for. Valid values are view and edit. |
239
|
|
|
* @return string |
240
|
|
|
*/ |
241
|
31 |
|
public function get_length( $context = 'view' ) { |
242
|
31 |
|
$value = $this->get_prop( 'length', $context ); |
243
|
|
|
|
244
|
|
|
// Inherit value from parent. |
245
|
31 |
|
if ( 'view' === $context && empty( $value ) ) { |
246
|
6 |
|
$value = apply_filters( $this->get_hook_prefix() . 'length', $this->parent_data['length'], $this ); |
247
|
|
|
} |
248
|
31 |
|
return $value; |
249
|
|
|
} |
250
|
|
|
|
251
|
|
|
/** |
252
|
|
|
* Returns the product width. |
253
|
|
|
* |
254
|
|
|
* @param string $context What the value is for. Valid values are view and edit. |
255
|
|
|
* @return string |
256
|
|
|
*/ |
257
|
31 |
|
public function get_width( $context = 'view' ) { |
258
|
31 |
|
$value = $this->get_prop( 'width', $context ); |
259
|
|
|
|
260
|
|
|
// Inherit value from parent. |
261
|
31 |
|
if ( 'view' === $context && empty( $value ) ) { |
262
|
6 |
|
$value = apply_filters( $this->get_hook_prefix() . 'width', $this->parent_data['width'], $this ); |
263
|
|
|
} |
264
|
31 |
|
return $value; |
265
|
|
|
} |
266
|
|
|
|
267
|
|
|
/** |
268
|
|
|
* Returns the product height. |
269
|
|
|
* |
270
|
|
|
* @param string $context What the value is for. Valid values are view and edit. |
271
|
|
|
* @return string |
272
|
|
|
*/ |
273
|
31 |
|
public function get_height( $context = 'view' ) { |
274
|
31 |
|
$value = $this->get_prop( 'height', $context ); |
275
|
|
|
|
276
|
|
|
// Inherit value from parent. |
277
|
31 |
|
if ( 'view' === $context && empty( $value ) ) { |
278
|
6 |
|
$value = apply_filters( $this->get_hook_prefix() . 'height', $this->parent_data['height'], $this ); |
279
|
|
|
} |
280
|
31 |
|
return $value; |
281
|
|
|
} |
282
|
|
|
|
283
|
|
|
/** |
284
|
|
|
* Returns the tax class. |
285
|
|
|
* |
286
|
|
|
* Does not use get_prop so it can handle 'parent' Inheritance correctly. |
287
|
|
|
* |
288
|
|
|
* @param string $context view, edit, or unfiltered. |
289
|
|
|
* @return string |
290
|
|
|
*/ |
291
|
31 |
|
public function get_tax_class( $context = 'view' ) { |
292
|
31 |
|
$value = null; |
293
|
|
|
|
294
|
31 |
|
if ( array_key_exists( 'tax_class', $this->data ) ) { |
295
|
31 |
|
$value = array_key_exists( 'tax_class', $this->changes ) ? $this->changes['tax_class'] : $this->data['tax_class']; |
296
|
|
|
|
297
|
31 |
|
if ( 'edit' !== $context && 'parent' === $value ) { |
298
|
8 |
|
$value = $this->parent_data['tax_class']; |
299
|
|
|
} |
300
|
|
|
|
301
|
31 |
|
if ( 'view' === $context ) { |
302
|
8 |
|
$value = apply_filters( $this->get_hook_prefix() . 'tax_class', $value, $this ); |
303
|
|
|
} |
304
|
|
|
} |
305
|
31 |
|
return $value; |
306
|
|
|
} |
307
|
|
|
|
308
|
|
|
/** |
309
|
|
|
* Return if product manage stock. |
310
|
|
|
* |
311
|
|
|
* @since 3.0.0 |
312
|
|
|
* @param string $context What the value is for. Valid values are view and edit. |
313
|
|
|
* @return boolean|string true, false, or parent. |
314
|
|
|
*/ |
315
|
31 |
|
public function get_manage_stock( $context = 'view' ) { |
316
|
31 |
|
$value = $this->get_prop( 'manage_stock', $context ); |
317
|
|
|
|
318
|
|
|
// Inherit value from parent. |
319
|
31 |
|
if ( 'view' === $context && false === $value && true === wc_string_to_bool( $this->parent_data['manage_stock'] ) ) { |
320
|
|
|
$value = 'parent'; |
321
|
|
|
} |
322
|
31 |
|
return $value; |
323
|
|
|
} |
324
|
|
|
|
325
|
|
|
/** |
326
|
|
|
* Returns number of items available for sale. |
327
|
|
|
* |
328
|
|
|
* @param string $context What the value is for. Valid values are view and edit. |
329
|
|
|
* @return int|null |
330
|
|
|
*/ |
331
|
31 |
View Code Duplication |
public function get_stock_quantity( $context = 'view' ) { |
|
|
|
|
332
|
31 |
|
$value = $this->get_prop( 'stock_quantity', $context ); |
333
|
|
|
|
334
|
|
|
// Inherit value from parent. |
335
|
31 |
|
if ( 'view' === $context && 'parent' === $this->get_manage_stock() ) { |
336
|
|
|
$value = apply_filters( $this->get_hook_prefix() . 'stock_quantity', $this->parent_data['stock_quantity'], $this ); |
337
|
|
|
} |
338
|
31 |
|
return $value; |
339
|
|
|
} |
340
|
|
|
|
341
|
|
|
/** |
342
|
|
|
* Get backorders. |
343
|
|
|
* |
344
|
|
|
* @param string $context What the value is for. Valid values are view and edit. |
345
|
|
|
* @since 3.0.0 |
346
|
|
|
* @return string yes no or notify |
347
|
|
|
*/ |
348
|
31 |
View Code Duplication |
public function get_backorders( $context = 'view' ) { |
|
|
|
|
349
|
31 |
|
$value = $this->get_prop( 'backorders', $context ); |
350
|
|
|
|
351
|
|
|
// Inherit value from parent. |
352
|
31 |
|
if ( 'view' === $context && 'parent' === $this->get_manage_stock() ) { |
353
|
|
|
$value = apply_filters( $this->get_hook_prefix() . 'backorders', $this->parent_data['backorders'], $this ); |
354
|
|
|
} |
355
|
31 |
|
return $value; |
356
|
|
|
} |
357
|
|
|
|
358
|
|
|
/** |
359
|
|
|
* Get main image ID. |
360
|
|
|
* |
361
|
|
|
* @since 3.0.0 |
362
|
|
|
* @param string $context What the value is for. Valid values are view and edit. |
363
|
|
|
* @return string |
364
|
|
|
*/ |
365
|
31 |
|
public function get_image_id( $context = 'view' ) { |
366
|
31 |
|
$image_id = $this->get_prop( 'image_id', $context ); |
367
|
|
|
|
368
|
31 |
|
if ( 'view' === $context && ! $image_id ) { |
369
|
6 |
|
$image_id = apply_filters( $this->get_hook_prefix() . 'image_id', $this->parent_data['image_id'], $this ); |
370
|
|
|
} |
371
|
|
|
|
372
|
31 |
|
return $image_id; |
373
|
|
|
} |
374
|
|
|
|
375
|
|
|
/** |
376
|
|
|
* Get purchase note. |
377
|
|
|
* |
378
|
|
|
* @since 3.0.0 |
379
|
|
|
* @param string $context What the value is for. Valid values are view and edit. |
380
|
|
|
* @return string |
381
|
|
|
*/ |
382
|
31 |
|
public function get_purchase_note( $context = 'view' ) { |
383
|
31 |
|
$value = $this->get_prop( 'purchase_note', $context ); |
384
|
|
|
|
385
|
|
|
// Inherit value from parent. |
386
|
31 |
|
if ( 'view' === $context && empty( $value ) ) { |
387
|
|
|
$value = apply_filters( $this->get_hook_prefix() . 'purchase_note', $this->parent_data['purchase_note'], $this ); |
388
|
|
|
} |
389
|
31 |
|
return $value; |
390
|
|
|
} |
391
|
|
|
|
392
|
|
|
/** |
393
|
|
|
* Get shipping class ID. |
394
|
|
|
* |
395
|
|
|
* @since 3.0.0 |
396
|
|
|
* @param string $context What the value is for. Valid values are view and edit. |
397
|
|
|
* @return int |
398
|
|
|
*/ |
399
|
31 |
|
public function get_shipping_class_id( $context = 'view' ) { |
400
|
31 |
|
$shipping_class_id = $this->get_prop( 'shipping_class_id', $context ); |
401
|
|
|
|
402
|
31 |
|
if ( 'view' === $context && ! $shipping_class_id ) { |
403
|
4 |
|
$shipping_class_id = apply_filters( $this->get_hook_prefix() . 'shipping_class_id', $this->parent_data['shipping_class_id'], $this ); |
404
|
|
|
} |
405
|
|
|
|
406
|
31 |
|
return $shipping_class_id; |
407
|
|
|
} |
408
|
|
|
|
409
|
|
|
/** |
410
|
|
|
* Get catalog visibility. |
411
|
|
|
* |
412
|
|
|
* @param string $context What the value is for. Valid values are view and edit. |
413
|
|
|
* @return string |
414
|
|
|
*/ |
415
|
1 |
|
public function get_catalog_visibility( $context = 'view' ) { |
416
|
1 |
|
return apply_filters( $this->get_hook_prefix() . 'catalog_visibility', $this->parent_data['catalog_visibility'], $this ); |
417
|
|
|
} |
418
|
|
|
|
419
|
|
|
/** |
420
|
|
|
* Get attribute summary. |
421
|
|
|
* |
422
|
|
|
* By default, attribute summary contains comma-delimited 'attribute_name: attribute_value' pairs for all attributes. |
423
|
|
|
* |
424
|
|
|
* @param string $context What the value is for. Valid values are view and edit. |
425
|
|
|
* |
426
|
|
|
* @since 3.6.0 |
427
|
|
|
* @return string |
428
|
|
|
*/ |
429
|
31 |
|
public function get_attribute_summary( $context = 'view' ) { |
430
|
31 |
|
return $this->get_prop( 'attribute_summary', $context ); |
431
|
|
|
} |
432
|
|
|
|
433
|
|
|
|
434
|
|
|
/** |
435
|
|
|
* Set attribute summary. |
436
|
|
|
* |
437
|
|
|
* By default, attribute summary contains comma-delimited 'attribute_name: attribute_value' pairs for all attributes. |
438
|
|
|
* |
439
|
|
|
* @since 3.6.0 |
440
|
|
|
* @param string $attribute_summary Summary of attribute names and values assigned to the variation. |
441
|
|
|
*/ |
442
|
31 |
|
public function set_attribute_summary( $attribute_summary ) { |
443
|
31 |
|
$this->set_prop( 'attribute_summary', $attribute_summary ); |
444
|
|
|
} |
445
|
|
|
|
446
|
|
|
/* |
447
|
|
|
|-------------------------------------------------------------------------- |
448
|
|
|
| CRUD methods |
449
|
|
|
|-------------------------------------------------------------------------- |
450
|
|
|
*/ |
451
|
|
|
|
452
|
|
|
/** |
453
|
|
|
* Set the parent data array for this variation. |
454
|
|
|
* |
455
|
|
|
* @since 3.0.0 |
456
|
|
|
* @param array $parent_data parent data array for this variation. |
457
|
|
|
*/ |
458
|
31 |
|
public function set_parent_data( $parent_data ) { |
459
|
31 |
|
$parent_data = wp_parse_args( |
460
|
31 |
|
$parent_data, |
461
|
|
|
array( |
462
|
31 |
|
'title' => '', |
463
|
|
|
'status' => '', |
464
|
|
|
'sku' => '', |
465
|
|
|
'manage_stock' => 'no', |
466
|
|
|
'backorders' => 'no', |
467
|
|
|
'stock_quantity' => '', |
468
|
|
|
'weight' => '', |
469
|
|
|
'length' => '', |
470
|
|
|
'width' => '', |
471
|
|
|
'height' => '', |
472
|
|
|
'tax_class' => '', |
473
|
|
|
'shipping_class_id' => 0, |
474
|
|
|
'image_id' => 0, |
475
|
|
|
'purchase_note' => '', |
476
|
|
|
'catalog_visibility' => 'visible', |
477
|
|
|
) |
478
|
|
|
); |
479
|
|
|
|
480
|
|
|
// Normalize tax class. |
481
|
31 |
|
$parent_data['tax_class'] = sanitize_title( $parent_data['tax_class'] ); |
482
|
31 |
|
$parent_data['tax_class'] = 'standard' === $parent_data['tax_class'] ? '' : $parent_data['tax_class']; |
483
|
31 |
|
$valid_classes = $this->get_valid_tax_classes(); |
484
|
|
|
|
485
|
31 |
|
if ( ! in_array( $parent_data['tax_class'], $valid_classes, true ) ) { |
486
|
31 |
|
$parent_data['tax_class'] = ''; |
487
|
|
|
} |
488
|
|
|
|
489
|
31 |
|
$this->parent_data = $parent_data; |
490
|
|
|
} |
491
|
|
|
|
492
|
|
|
/** |
493
|
|
|
* Get the parent data array for this variation. |
494
|
|
|
* |
495
|
|
|
* @since 3.0.0 |
496
|
|
|
* @return array |
497
|
|
|
*/ |
498
|
|
|
public function get_parent_data() { |
499
|
|
|
return $this->parent_data; |
500
|
|
|
} |
501
|
|
|
|
502
|
|
|
/** |
503
|
|
|
* Set attributes. Unlike the parent product which uses terms, variations are assigned |
504
|
|
|
* specific attributes using name value pairs. |
505
|
|
|
* |
506
|
|
|
* @param array $raw_attributes array of raw attributes. |
507
|
|
|
*/ |
508
|
31 |
|
public function set_attributes( $raw_attributes ) { |
509
|
31 |
|
$raw_attributes = (array) $raw_attributes; |
510
|
31 |
|
$attributes = array(); |
511
|
|
|
|
512
|
31 |
|
foreach ( $raw_attributes as $key => $value ) { |
513
|
|
|
// Remove attribute prefix which meta gets stored with. |
514
|
23 |
|
if ( 0 === strpos( $key, 'attribute_' ) ) { |
515
|
19 |
|
$key = substr( $key, 10 ); |
516
|
|
|
} |
517
|
23 |
|
$attributes[ $key ] = $value; |
518
|
|
|
} |
519
|
31 |
|
$this->set_prop( 'attributes', $attributes ); |
520
|
|
|
} |
521
|
|
|
|
522
|
|
|
/** |
523
|
|
|
* Returns whether or not the product has any visible attributes. |
524
|
|
|
* |
525
|
|
|
* Variations are mapped to specific attributes unlike products, and the return |
526
|
|
|
* value of ->get_attributes differs. Therefore this returns false. |
527
|
|
|
* |
528
|
|
|
* @return boolean |
529
|
|
|
*/ |
530
|
|
|
public function has_attributes() { |
531
|
|
|
return false; |
532
|
|
|
} |
533
|
|
|
|
534
|
|
|
/* |
535
|
|
|
|-------------------------------------------------------------------------- |
536
|
|
|
| Conditionals |
537
|
|
|
|-------------------------------------------------------------------------- |
538
|
|
|
*/ |
539
|
|
|
|
540
|
|
|
/** |
541
|
|
|
* Returns false if the product cannot be bought. |
542
|
|
|
* Override abstract method so that: i) Disabled variations are not be purchasable by admins. ii) Enabled variations are not purchasable if the parent product is not purchasable. |
543
|
|
|
* |
544
|
|
|
* @return bool |
545
|
|
|
*/ |
546
|
5 |
|
public function is_purchasable() { |
547
|
5 |
|
return apply_filters( 'woocommerce_variation_is_purchasable', $this->variation_is_visible() && parent::is_purchasable() && ( 'publish' === $this->parent_data['status'] || current_user_can( 'edit_post', $this->get_parent_id() ) ), $this ); |
548
|
|
|
} |
549
|
|
|
|
550
|
|
|
/** |
551
|
|
|
* Controls whether this particular variation will appear greyed-out (inactive) or not (active). |
552
|
|
|
* Used by extensions to make incompatible variations appear greyed-out, etc. |
553
|
|
|
* Other possible uses: prevent out-of-stock variations from being selected. |
554
|
|
|
* |
555
|
|
|
* @return bool |
556
|
|
|
*/ |
557
|
5 |
|
public function variation_is_active() { |
558
|
5 |
|
return apply_filters( 'woocommerce_variation_is_active', true, $this ); |
559
|
|
|
} |
560
|
|
|
|
561
|
|
|
/** |
562
|
|
|
* Checks if this particular variation is visible. Invisible variations are enabled and can be selected, but no price / stock info is displayed. |
563
|
|
|
* Instead, a suitable 'unavailable' message is displayed. |
564
|
|
|
* Invisible by default: Disabled variations and variations with an empty price. |
565
|
|
|
* |
566
|
|
|
* @return bool |
567
|
|
|
*/ |
568
|
5 |
|
public function variation_is_visible() { |
569
|
5 |
|
return apply_filters( 'woocommerce_variation_is_visible', 'publish' === get_post_status( $this->get_id() ) && '' !== $this->get_price(), $this->get_id(), $this->get_parent_id(), $this ); |
570
|
|
|
} |
571
|
|
|
|
572
|
|
|
/** |
573
|
|
|
* Return valid tax classes. Adds 'parent' to the default list of valid tax classes. |
574
|
|
|
* |
575
|
|
|
* @return array valid tax classes |
576
|
|
|
*/ |
577
|
31 |
|
protected function get_valid_tax_classes() { |
578
|
31 |
|
$valid_classes = WC_Tax::get_tax_class_slugs(); |
579
|
31 |
|
$valid_classes[] = 'parent'; |
580
|
|
|
|
581
|
31 |
|
return $valid_classes; |
582
|
|
|
} |
583
|
|
|
} |
584
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.