This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /** |
||
3 | * Abstract Product importer |
||
4 | * |
||
5 | * @package WooCommerce/Import |
||
6 | * @version 3.1.0 |
||
7 | */ |
||
8 | |||
9 | 1 | if ( ! defined( 'ABSPATH' ) ) { |
|
10 | exit; |
||
11 | } |
||
12 | |||
13 | /** |
||
14 | * Include dependencies. |
||
15 | */ |
||
16 | 1 | if ( ! class_exists( 'WC_Importer_Interface', false ) ) { |
|
17 | 1 | include_once WC_ABSPATH . 'includes/interfaces/class-wc-importer-interface.php'; |
|
18 | } |
||
19 | |||
20 | /** |
||
21 | * WC_Product_Importer Class. |
||
22 | */ |
||
23 | abstract class WC_Product_Importer implements WC_Importer_Interface { |
||
24 | |||
25 | /** |
||
26 | * CSV file. |
||
27 | * |
||
28 | * @var string |
||
29 | */ |
||
30 | protected $file = ''; |
||
31 | |||
32 | /** |
||
33 | * The file position after the last read. |
||
34 | * |
||
35 | * @var int |
||
36 | */ |
||
37 | protected $file_position = 0; |
||
38 | |||
39 | /** |
||
40 | * Importer parameters. |
||
41 | * |
||
42 | * @var array |
||
43 | */ |
||
44 | protected $params = array(); |
||
45 | |||
46 | /** |
||
47 | * Raw keys - CSV raw headers. |
||
48 | * |
||
49 | * @var array |
||
50 | */ |
||
51 | protected $raw_keys = array(); |
||
52 | |||
53 | /** |
||
54 | * Mapped keys - CSV headers. |
||
55 | * |
||
56 | * @var array |
||
57 | */ |
||
58 | protected $mapped_keys = array(); |
||
59 | |||
60 | /** |
||
61 | * Raw data. |
||
62 | * |
||
63 | * @var array |
||
64 | */ |
||
65 | protected $raw_data = array(); |
||
66 | |||
67 | /** |
||
68 | * Raw data. |
||
69 | * |
||
70 | * @var array |
||
71 | */ |
||
72 | protected $file_positions = array(); |
||
73 | |||
74 | /** |
||
75 | * Parsed data. |
||
76 | * |
||
77 | * @var array |
||
78 | */ |
||
79 | protected $parsed_data = array(); |
||
80 | |||
81 | /** |
||
82 | * Start time of current import. |
||
83 | * |
||
84 | * (default value: 0) |
||
85 | * |
||
86 | * @var int |
||
87 | */ |
||
88 | protected $start_time = 0; |
||
89 | |||
90 | /** |
||
91 | * Get file raw headers. |
||
92 | * |
||
93 | * @return array |
||
94 | */ |
||
95 | 1 | public function get_raw_keys() { |
|
96 | 1 | return $this->raw_keys; |
|
97 | } |
||
98 | |||
99 | /** |
||
100 | * Get file mapped headers. |
||
101 | * |
||
102 | * @return array |
||
103 | */ |
||
104 | 4 | public function get_mapped_keys() { |
|
105 | 4 | return ! empty( $this->mapped_keys ) ? $this->mapped_keys : $this->raw_keys; |
|
106 | } |
||
107 | |||
108 | /** |
||
109 | * Get raw data. |
||
110 | * |
||
111 | * @return array |
||
112 | */ |
||
113 | 2 | public function get_raw_data() { |
|
114 | 2 | return $this->raw_data; |
|
115 | } |
||
116 | |||
117 | /** |
||
118 | * Get parsed data. |
||
119 | * |
||
120 | * @return array |
||
121 | */ |
||
122 | 1 | public function get_parsed_data() { |
|
123 | 1 | return apply_filters( 'woocommerce_product_importer_parsed_data', $this->parsed_data, $this->get_raw_data() ); |
|
124 | } |
||
125 | |||
126 | /** |
||
127 | * Get importer parameters. |
||
128 | * |
||
129 | * @return array |
||
130 | */ |
||
131 | public function get_params() { |
||
132 | return $this->params; |
||
133 | } |
||
134 | |||
135 | /** |
||
136 | * Get file pointer position from the last read. |
||
137 | * |
||
138 | * @return int |
||
139 | */ |
||
140 | public function get_file_position() { |
||
141 | return $this->file_position; |
||
142 | } |
||
143 | |||
144 | /** |
||
145 | * Get file pointer position as a percentage of file size. |
||
146 | * |
||
147 | * @return int |
||
148 | */ |
||
149 | public function get_percent_complete() { |
||
150 | $size = filesize( $this->file ); |
||
151 | if ( ! $size ) { |
||
152 | return 0; |
||
153 | } |
||
154 | |||
155 | return absint( min( round( ( $this->file_position / $size ) * 100 ), 100 ) ); |
||
156 | } |
||
157 | |||
158 | /** |
||
159 | * Prepare a single product for create or update. |
||
160 | * |
||
161 | * @param array $data Item data. |
||
162 | * @return WC_Product|WP_Error |
||
163 | */ |
||
164 | 2 | protected function get_product_object( $data ) { |
|
165 | 2 | $id = isset( $data['id'] ) ? absint( $data['id'] ) : 0; |
|
166 | |||
167 | // Type is the most important part here because we need to be using the correct class and methods. |
||
168 | 2 | if ( isset( $data['type'] ) ) { |
|
169 | 1 | $types = array_keys( wc_get_product_types() ); |
|
170 | 1 | $types[] = 'variation'; |
|
171 | |||
172 | 1 | View Code Duplication | if ( ! in_array( $data['type'], $types, true ) ) { |
173 | return new WP_Error( 'woocommerce_product_importer_invalid_type', __( 'Invalid product type.', 'woocommerce' ), array( 'status' => 401 ) ); |
||
174 | } |
||
175 | |||
176 | 1 | $classname = WC_Product_Factory::get_classname_from_product_type( $data['type'] ); |
|
177 | |||
178 | 1 | if ( ! class_exists( $classname ) ) { |
|
179 | $classname = 'WC_Product_Simple'; |
||
180 | } |
||
181 | |||
182 | 1 | $product = new $classname( $id ); |
|
183 | 1 | } elseif ( ! empty( $data['id'] ) ) { |
|
184 | 1 | $product = wc_get_product( $id ); |
|
185 | |||
186 | 1 | View Code Duplication | if ( ! $product ) { |
187 | return new WP_Error( |
||
188 | 'woocommerce_product_csv_importer_invalid_id', |
||
189 | /* translators: %d: product ID */ |
||
190 | sprintf( __( 'Invalid product ID %d.', 'woocommerce' ), $id ), |
||
191 | array( |
||
192 | 'id' => $id, |
||
193 | 1 | 'status' => 401, |
|
194 | ) |
||
195 | ); |
||
196 | } |
||
197 | } else { |
||
198 | $product = new WC_Product_Simple( $id ); |
||
199 | } |
||
200 | |||
201 | 2 | return apply_filters( 'woocommerce_product_import_get_product_object', $product, $data ); |
|
202 | } |
||
203 | |||
204 | /** |
||
205 | * Process a single item and save. |
||
206 | * |
||
207 | * @throws Exception If item cannot be processed. |
||
208 | * @param array $data Raw CSV data. |
||
209 | * @return array|WP_Error |
||
210 | */ |
||
211 | 2 | protected function process_item( $data ) { |
|
212 | try { |
||
213 | 2 | do_action( 'woocommerce_product_import_before_process_item', $data ); |
|
214 | 2 | $data = apply_filters( 'woocommerce_product_import_process_item_data', $data ); |
|
215 | |||
216 | // Get product ID from SKU if created during the importation. |
||
217 | 2 | if ( empty( $data['id'] ) && ! empty( $data['sku'] ) ) { |
|
218 | 2 | $product_id = wc_get_product_id_by_sku( $data['sku'] ); |
|
219 | |||
220 | 2 | if ( $product_id ) { |
|
221 | 2 | $data['id'] = $product_id; |
|
222 | } |
||
223 | } |
||
224 | |||
225 | 2 | $object = $this->get_product_object( $data ); |
|
226 | 2 | $updating = false; |
|
227 | |||
228 | 2 | if ( is_wp_error( $object ) ) { |
|
229 | return $object; |
||
230 | } |
||
231 | |||
232 | 2 | if ( $object->get_id() && 'importing' !== $object->get_status() ) { |
|
233 | 1 | $updating = true; |
|
234 | } |
||
235 | |||
236 | 2 | if ( 'external' === $object->get_type() ) { |
|
237 | 1 | unset( $data['manage_stock'], $data['stock_status'], $data['backorders'], $data['low_stock_amount'] ); |
|
238 | } |
||
239 | |||
240 | 2 | if ( 'variation' === $object->get_type() ) { |
|
241 | 1 | if ( isset( $data['status'] ) && -1 === $data['status'] ) { |
|
242 | $data['status'] = 0; // Variations cannot be drafts - set to private. |
||
243 | } |
||
244 | } |
||
245 | |||
246 | 2 | if ( 'importing' === $object->get_status() ) { |
|
247 | 1 | $object->set_status( 'publish' ); |
|
248 | 1 | $object->set_slug( '' ); |
|
249 | } |
||
250 | |||
251 | 2 | $result = $object->set_props( array_diff_key( $data, array_flip( array( 'meta_data', 'raw_image_id', 'raw_gallery_image_ids', 'raw_attributes' ) ) ) ); |
|
252 | |||
253 | 2 | if ( is_wp_error( $result ) ) { |
|
254 | throw new Exception( $result->get_error_message() ); |
||
255 | } |
||
256 | |||
257 | 2 | if ( 'variation' === $object->get_type() ) { |
|
258 | 1 | $this->set_variation_data( $object, $data ); |
|
259 | } else { |
||
260 | 2 | $this->set_product_data( $object, $data ); |
|
261 | } |
||
262 | |||
263 | 2 | $this->set_image_data( $object, $data ); |
|
264 | 2 | $this->set_meta_data( $object, $data ); |
|
265 | |||
266 | 2 | $object = apply_filters( 'woocommerce_product_import_pre_insert_product_object', $object, $data ); |
|
267 | 2 | $object->save(); |
|
268 | |||
269 | 2 | do_action( 'woocommerce_product_import_inserted_product_object', $object, $data ); |
|
270 | |||
271 | return array( |
||
272 | 2 | 'id' => $object->get_id(), |
|
273 | 2 | 'updated' => $updating, |
|
274 | ); |
||
275 | } catch ( Exception $e ) { |
||
276 | return new WP_Error( 'woocommerce_product_importer_error', $e->getMessage(), array( 'status' => $e->getCode() ) ); |
||
277 | } |
||
278 | } |
||
279 | |||
280 | /** |
||
281 | * Convert raw image URLs to IDs and set. |
||
282 | * |
||
283 | * @param WC_Product $product Product instance. |
||
284 | * @param array $data Item data. |
||
285 | */ |
||
286 | 2 | protected function set_image_data( &$product, $data ) { |
|
287 | // Image URLs need converting to IDs before inserting. |
||
288 | 2 | if ( isset( $data['raw_image_id'] ) ) { |
|
289 | 1 | $product->set_image_id( $this->get_attachment_id_from_url( $data['raw_image_id'], $product->get_id() ) ); |
|
290 | } |
||
291 | |||
292 | // Gallery image URLs need converting to IDs before inserting. |
||
293 | 2 | if ( isset( $data['raw_gallery_image_ids'] ) ) { |
|
294 | 1 | $gallery_image_ids = array(); |
|
295 | |||
296 | 1 | foreach ( $data['raw_gallery_image_ids'] as $image_id ) { |
|
297 | 1 | $gallery_image_ids[] = $this->get_attachment_id_from_url( $image_id, $product->get_id() ); |
|
298 | } |
||
299 | 1 | $product->set_gallery_image_ids( $gallery_image_ids ); |
|
300 | } |
||
301 | } |
||
302 | |||
303 | /** |
||
304 | * Append meta data. |
||
305 | * |
||
306 | * @param WC_Product $product Product instance. |
||
307 | * @param array $data Item data. |
||
308 | */ |
||
309 | 2 | protected function set_meta_data( &$product, $data ) { |
|
310 | 2 | if ( isset( $data['meta_data'] ) ) { |
|
311 | foreach ( $data['meta_data'] as $meta ) { |
||
312 | $product->update_meta_data( $meta['key'], $meta['value'] ); |
||
313 | } |
||
314 | } |
||
315 | } |
||
316 | |||
317 | /** |
||
318 | * Set product data. |
||
319 | * |
||
320 | * @param WC_Product $product Product instance. |
||
321 | * @param array $data Item data. |
||
322 | * @throws Exception If data cannot be set. |
||
323 | */ |
||
324 | 2 | protected function set_product_data( &$product, $data ) { |
|
325 | 2 | if ( isset( $data['raw_attributes'] ) ) { |
|
326 | 1 | $attributes = array(); |
|
327 | 1 | $default_attributes = array(); |
|
328 | 1 | $existing_attributes = $product->get_attributes(); |
|
329 | |||
330 | 1 | foreach ( $data['raw_attributes'] as $position => $attribute ) { |
|
331 | 1 | $attribute_id = 0; |
|
332 | |||
333 | // Get ID if is a global attribute. |
||
334 | 1 | if ( ! empty( $attribute['taxonomy'] ) ) { |
|
335 | $attribute_id = $this->get_attribute_taxonomy_id( $attribute['name'] ); |
||
336 | } |
||
337 | |||
338 | // Set attribute visibility. |
||
339 | 1 | if ( isset( $attribute['visible'] ) ) { |
|
340 | $is_visible = $attribute['visible']; |
||
341 | } else { |
||
342 | 1 | $is_visible = 1; |
|
343 | } |
||
344 | |||
345 | // Get name. |
||
346 | 1 | $attribute_name = $attribute_id ? wc_attribute_taxonomy_name_by_id( $attribute_id ) : $attribute['name']; |
|
347 | |||
348 | // Set if is a variation attribute based on existing attributes if possible so updates via CSV do not change this. |
||
349 | 1 | $is_variation = 0; |
|
350 | |||
351 | 1 | if ( $existing_attributes ) { |
|
352 | foreach ( $existing_attributes as $existing_attribute ) { |
||
353 | if ( $existing_attribute->get_name() === $attribute_name ) { |
||
354 | $is_variation = $existing_attribute->get_variation(); |
||
355 | break; |
||
356 | } |
||
357 | } |
||
358 | } |
||
359 | |||
360 | 1 | if ( $attribute_id ) { |
|
361 | if ( isset( $attribute['value'] ) ) { |
||
362 | $options = array_map( 'wc_sanitize_term_text_based', $attribute['value'] ); |
||
363 | $options = array_filter( $options, 'strlen' ); |
||
364 | } else { |
||
365 | $options = array(); |
||
366 | } |
||
367 | |||
368 | // Check for default attributes and set "is_variation". |
||
369 | if ( ! empty( $attribute['default'] ) && in_array( $attribute['default'], $options, true ) ) { |
||
370 | $default_term = get_term_by( 'name', $attribute['default'], $attribute_name ); |
||
371 | |||
372 | if ( $default_term && ! is_wp_error( $default_term ) ) { |
||
373 | $default = $default_term->slug; |
||
374 | } else { |
||
375 | $default = sanitize_title( $attribute['default'] ); |
||
376 | } |
||
377 | |||
378 | $default_attributes[ $attribute_name ] = $default; |
||
379 | $is_variation = 1; |
||
380 | } |
||
381 | |||
382 | if ( ! empty( $options ) ) { |
||
383 | $attribute_object = new WC_Product_Attribute(); |
||
384 | $attribute_object->set_id( $attribute_id ); |
||
385 | $attribute_object->set_name( $attribute_name ); |
||
386 | $attribute_object->set_options( $options ); |
||
387 | $attribute_object->set_position( $position ); |
||
388 | $attribute_object->set_visible( $is_visible ); |
||
389 | $attribute_object->set_variation( $is_variation ); |
||
390 | $attributes[] = $attribute_object; |
||
391 | } |
||
392 | 1 | } elseif ( isset( $attribute['value'] ) ) { |
|
393 | // Check for default attributes and set "is_variation". |
||
394 | 1 | if ( ! empty( $attribute['default'] ) && in_array( $attribute['default'], $attribute['value'], true ) ) { |
|
395 | 1 | $default_attributes[ sanitize_title( $attribute['name'] ) ] = $attribute['default']; |
|
396 | 1 | $is_variation = 1; |
|
397 | } |
||
398 | |||
399 | 1 | $attribute_object = new WC_Product_Attribute(); |
|
400 | 1 | $attribute_object->set_name( $attribute['name'] ); |
|
401 | 1 | $attribute_object->set_options( $attribute['value'] ); |
|
402 | 1 | $attribute_object->set_position( $position ); |
|
403 | 1 | $attribute_object->set_visible( $is_visible ); |
|
404 | 1 | $attribute_object->set_variation( $is_variation ); |
|
405 | 1 | $attributes[] = $attribute_object; |
|
406 | } |
||
407 | } |
||
408 | |||
409 | 1 | $product->set_attributes( $attributes ); |
|
410 | |||
411 | // Set variable default attributes. |
||
412 | 1 | if ( $product->is_type( 'variable' ) ) { |
|
413 | 1 | $product->set_default_attributes( $default_attributes ); |
|
414 | } |
||
415 | } |
||
416 | } |
||
417 | |||
418 | /** |
||
419 | * Set variation data. |
||
420 | * |
||
421 | * @param WC_Product $variation Product instance. |
||
422 | * @param array $data Item data. |
||
423 | * @return WC_Product|WP_Error |
||
424 | * @throws Exception If data cannot be set. |
||
425 | */ |
||
426 | 1 | protected function set_variation_data( &$variation, $data ) { |
|
427 | 1 | $parent = false; |
|
428 | |||
429 | // Check if parent exist. |
||
430 | 1 | if ( isset( $data['parent_id'] ) ) { |
|
431 | 1 | $parent = wc_get_product( $data['parent_id'] ); |
|
432 | |||
433 | 1 | if ( $parent ) { |
|
434 | 1 | $variation->set_parent_id( $parent->get_id() ); |
|
435 | } |
||
436 | } |
||
437 | |||
438 | // Stop if parent does not exists. |
||
439 | 1 | if ( ! $parent ) { |
|
440 | return new WP_Error( 'woocommerce_product_importer_missing_variation_parent_id', __( 'Variation cannot be imported: Missing parent ID or parent does not exist yet.', 'woocommerce' ), array( 'status' => 401 ) ); |
||
441 | } |
||
442 | |||
443 | // Stop if parent is a product variation. |
||
444 | 1 | if ( $parent->is_type( 'variation' ) ) { |
|
445 | return new WP_Error( 'woocommerce_product_importer_parent_set_as_variation', __( 'Variation cannot be imported: Parent product cannot be a product variation', 'woocommerce' ), array( 'status' => 401 ) ); |
||
446 | } |
||
447 | |||
448 | 1 | if ( isset( $data['raw_attributes'] ) ) { |
|
449 | 1 | $attributes = array(); |
|
450 | 1 | $parent_attributes = $this->get_variation_parent_attributes( $data['raw_attributes'], $parent ); |
|
451 | |||
452 | 1 | foreach ( $data['raw_attributes'] as $attribute ) { |
|
453 | 1 | $attribute_id = 0; |
|
454 | |||
455 | // Get ID if is a global attribute. |
||
456 | 1 | if ( ! empty( $attribute['taxonomy'] ) ) { |
|
457 | $attribute_id = $this->get_attribute_taxonomy_id( $attribute['name'] ); |
||
458 | } |
||
459 | |||
460 | 1 | if ( $attribute_id ) { |
|
461 | $attribute_name = wc_attribute_taxonomy_name_by_id( $attribute_id ); |
||
462 | } else { |
||
463 | 1 | $attribute_name = sanitize_title( $attribute['name'] ); |
|
464 | } |
||
465 | |||
466 | 1 | if ( ! isset( $parent_attributes[ $attribute_name ] ) || ! $parent_attributes[ $attribute_name ]->get_variation() ) { |
|
467 | 1 | continue; |
|
468 | } |
||
469 | |||
470 | 1 | $attribute_key = sanitize_title( $parent_attributes[ $attribute_name ]->get_name() ); |
|
471 | 1 | $attribute_value = isset( $attribute['value'] ) ? current( $attribute['value'] ) : ''; |
|
472 | |||
473 | 1 | if ( $parent_attributes[ $attribute_name ]->is_taxonomy() ) { |
|
474 | // If dealing with a taxonomy, we need to get the slug from the name posted to the API. |
||
475 | $term = get_term_by( 'name', $attribute_value, $attribute_name ); |
||
476 | |||
477 | if ( $term && ! is_wp_error( $term ) ) { |
||
478 | $attribute_value = $term->slug; |
||
479 | } else { |
||
480 | $attribute_value = sanitize_title( $attribute_value ); |
||
481 | } |
||
482 | } |
||
483 | |||
484 | 1 | $attributes[ $attribute_key ] = $attribute_value; |
|
485 | } |
||
486 | |||
487 | 1 | $variation->set_attributes( $attributes ); |
|
488 | } |
||
489 | } |
||
490 | |||
491 | /** |
||
492 | * Get variation parent attributes and set "is_variation". |
||
493 | * |
||
494 | * @param array $attributes Attributes list. |
||
495 | * @param WC_Product $parent Parent product data. |
||
496 | * @return array |
||
497 | */ |
||
498 | 1 | protected function get_variation_parent_attributes( $attributes, $parent ) { |
|
499 | 1 | $parent_attributes = $parent->get_attributes(); |
|
500 | 1 | $require_save = false; |
|
501 | |||
502 | 1 | foreach ( $attributes as $attribute ) { |
|
503 | 1 | $attribute_id = 0; |
|
504 | |||
505 | // Get ID if is a global attribute. |
||
506 | 1 | if ( ! empty( $attribute['taxonomy'] ) ) { |
|
507 | $attribute_id = $this->get_attribute_taxonomy_id( $attribute['name'] ); |
||
508 | } |
||
509 | |||
510 | 1 | if ( $attribute_id ) { |
|
511 | $attribute_name = wc_attribute_taxonomy_name_by_id( $attribute_id ); |
||
512 | } else { |
||
513 | 1 | $attribute_name = sanitize_title( $attribute['name'] ); |
|
514 | } |
||
515 | |||
516 | // Check if attribute handle variations. |
||
517 | 1 | if ( isset( $parent_attributes[ $attribute_name ] ) && ! $parent_attributes[ $attribute_name ]->get_variation() ) { |
|
518 | // Re-create the attribute to CRUD save and generate again. |
||
519 | $parent_attributes[ $attribute_name ] = clone $parent_attributes[ $attribute_name ]; |
||
520 | $parent_attributes[ $attribute_name ]->set_variation( 1 ); |
||
521 | |||
522 | $require_save = true; |
||
523 | } |
||
524 | } |
||
525 | |||
526 | // Save variation attributes. |
||
527 | 1 | if ( $require_save ) { |
|
528 | $parent->set_attributes( array_values( $parent_attributes ) ); |
||
529 | $parent->save(); |
||
530 | } |
||
531 | |||
532 | 1 | return $parent_attributes; |
|
533 | } |
||
534 | |||
535 | /** |
||
536 | * Get attachment ID. |
||
537 | * |
||
538 | * @param string $url Attachment URL. |
||
539 | * @param int $product_id Product ID. |
||
540 | * @return int |
||
541 | * @throws Exception If attachment cannot be loaded. |
||
542 | */ |
||
543 | 1 | public function get_attachment_id_from_url( $url, $product_id ) { |
|
544 | 1 | if ( empty( $url ) ) { |
|
545 | return 0; |
||
546 | } |
||
547 | |||
548 | 1 | $id = 0; |
|
549 | 1 | $upload_dir = wp_upload_dir( null, false ); |
|
550 | 1 | $base_url = $upload_dir['baseurl'] . '/'; |
|
551 | |||
552 | // Check first if attachment is inside the WordPress uploads directory, or we're given a filename only. |
||
553 | 1 | if ( false !== strpos( $url, $base_url ) || false === strpos( $url, '://' ) ) { |
|
554 | // Search for yyyy/mm/slug.extension or slug.extension - remove the base URL. |
||
555 | $file = str_replace( $base_url, '', $url ); |
||
556 | $args = array( |
||
557 | 'post_type' => 'attachment', |
||
558 | 'post_status' => 'any', |
||
559 | 'fields' => 'ids', |
||
560 | 'meta_query' => array( // @codingStandardsIgnoreLine. |
||
561 | 'relation' => 'OR', |
||
562 | array( |
||
563 | 'key' => '_wp_attached_file', |
||
564 | 'value' => '^' . $file, |
||
565 | 'compare' => 'REGEXP', |
||
566 | ), |
||
567 | array( |
||
568 | 'key' => '_wp_attached_file', |
||
569 | 'value' => '/' . $file, |
||
570 | 'compare' => 'LIKE', |
||
571 | ), |
||
572 | array( |
||
573 | 'key' => '_wc_attachment_source', |
||
574 | 'value' => '/' . $file, |
||
575 | 'compare' => 'LIKE', |
||
576 | ), |
||
577 | ), |
||
578 | ); |
||
579 | } else { |
||
580 | // This is an external URL, so compare to source. |
||
581 | $args = array( |
||
582 | 1 | 'post_type' => 'attachment', |
|
583 | 1 | 'post_status' => 'any', |
|
584 | 1 | 'fields' => 'ids', |
|
585 | 'meta_query' => array( // @codingStandardsIgnoreLine. |
||
586 | array( |
||
587 | 1 | 'value' => $url, |
|
588 | 1 | 'key' => '_wc_attachment_source', |
|
589 | ), |
||
590 | ), |
||
591 | ); |
||
592 | } |
||
593 | |||
594 | 1 | $ids = get_posts( $args ); // @codingStandardsIgnoreLine. |
|
595 | |||
596 | 1 | if ( $ids ) { |
|
597 | 1 | $id = current( $ids ); |
|
598 | } |
||
599 | |||
600 | // Upload if attachment does not exists. |
||
601 | 1 | if ( ! $id && stristr( $url, '://' ) ) { |
|
602 | 1 | $upload = wc_rest_upload_image_from_url( $url ); |
|
603 | |||
604 | 1 | if ( is_wp_error( $upload ) ) { |
|
605 | throw new Exception( $upload->get_error_message(), 400 ); |
||
606 | } |
||
607 | |||
608 | 1 | $id = wc_rest_set_uploaded_image_as_attachment( $upload, $product_id ); |
|
609 | |||
610 | 1 | if ( ! wp_attachment_is_image( $id ) ) { |
|
611 | /* translators: %s: image URL */ |
||
612 | throw new Exception( sprintf( __( 'Not able to attach "%s".', 'woocommerce' ), $url ), 400 ); |
||
613 | } |
||
614 | |||
615 | // Save attachment source for future reference. |
||
616 | 1 | update_post_meta( $id, '_wc_attachment_source', $url ); |
|
617 | } |
||
618 | |||
619 | 1 | if ( ! $id ) { |
|
620 | /* translators: %s: image URL */ |
||
621 | throw new Exception( sprintf( __( 'Unable to use image "%s".', 'woocommerce' ), $url ), 400 ); |
||
622 | } |
||
623 | |||
624 | 1 | return $id; |
|
625 | } |
||
626 | |||
627 | /** |
||
628 | * Get attribute taxonomy ID from the imported data. |
||
629 | * If does not exists register a new attribute. |
||
630 | * |
||
631 | * @param string $raw_name Attribute name. |
||
632 | * @return int |
||
633 | * @throws Exception If taxonomy cannot be loaded. |
||
634 | */ |
||
635 | public function get_attribute_taxonomy_id( $raw_name ) { |
||
636 | global $wpdb, $wc_product_attributes; |
||
637 | |||
638 | // These are exported as labels, so convert the label to a name if possible first. |
||
639 | $attribute_labels = wp_list_pluck( wc_get_attribute_taxonomies(), 'attribute_label', 'attribute_name' ); |
||
640 | $attribute_name = array_search( $raw_name, $attribute_labels, true ); |
||
641 | |||
642 | if ( ! $attribute_name ) { |
||
643 | $attribute_name = wc_sanitize_taxonomy_name( $raw_name ); |
||
644 | } |
||
645 | |||
646 | $attribute_id = wc_attribute_taxonomy_id_by_name( $attribute_name ); |
||
647 | |||
648 | // Get the ID from the name. |
||
649 | if ( $attribute_id ) { |
||
650 | return $attribute_id; |
||
651 | } |
||
652 | |||
653 | // If the attribute does not exist, create it. |
||
654 | $attribute_id = wc_create_attribute( |
||
655 | array( |
||
656 | 'name' => $raw_name, |
||
657 | 'slug' => $attribute_name, |
||
658 | 'type' => 'select', |
||
659 | 'order_by' => 'menu_order', |
||
660 | 'has_archives' => false, |
||
661 | ) |
||
662 | ); |
||
663 | |||
664 | if ( is_wp_error( $attribute_id ) ) { |
||
665 | throw new Exception( $attribute_id->get_error_message(), 400 ); |
||
666 | } |
||
667 | |||
668 | // Register as taxonomy while importing. |
||
669 | $taxonomy_name = wc_attribute_taxonomy_name( $attribute_name ); |
||
670 | register_taxonomy( |
||
671 | $taxonomy_name, |
||
672 | apply_filters( 'woocommerce_taxonomy_objects_' . $taxonomy_name, array( 'product' ) ), |
||
673 | apply_filters( |
||
674 | 'woocommerce_taxonomy_args_' . $taxonomy_name, |
||
675 | array( |
||
676 | 'labels' => array( |
||
677 | 'name' => $raw_name, |
||
678 | ), |
||
679 | 'hierarchical' => true, |
||
680 | 'show_ui' => false, |
||
681 | 'query_var' => true, |
||
682 | 'rewrite' => false, |
||
683 | ) |
||
684 | ) |
||
685 | ); |
||
686 | |||
687 | // Set product attributes global. |
||
688 | $wc_product_attributes = array(); |
||
689 | |||
690 | foreach ( wc_get_attribute_taxonomies() as $taxonomy ) { |
||
691 | $wc_product_attributes[ wc_attribute_taxonomy_name( $taxonomy->attribute_name ) ] = $taxonomy; |
||
692 | } |
||
693 | |||
694 | return $attribute_id; |
||
695 | } |
||
696 | |||
697 | /** |
||
698 | * Memory exceeded |
||
699 | * |
||
700 | * Ensures the batch process never exceeds 90% |
||
701 | * of the maximum WordPress memory. |
||
702 | * |
||
703 | * @return bool |
||
704 | */ |
||
705 | 1 | protected function memory_exceeded() { |
|
706 | 1 | $memory_limit = $this->get_memory_limit() * 0.9; // 90% of max memory |
|
707 | 1 | $current_memory = memory_get_usage( true ); |
|
708 | 1 | $return = false; |
|
709 | 1 | if ( $current_memory >= $memory_limit ) { |
|
710 | $return = true; |
||
711 | } |
||
712 | 1 | return apply_filters( 'woocommerce_product_importer_memory_exceeded', $return ); |
|
713 | } |
||
714 | |||
715 | /** |
||
716 | * Get memory limit |
||
717 | * |
||
718 | * @return int |
||
719 | */ |
||
720 | 1 | View Code Duplication | protected function get_memory_limit() { |
721 | 1 | if ( function_exists( 'ini_get' ) ) { |
|
722 | 1 | $memory_limit = ini_get( 'memory_limit' ); |
|
723 | } else { |
||
724 | // Sensible default. |
||
725 | $memory_limit = '128M'; |
||
726 | } |
||
727 | |||
728 | 1 | if ( ! $memory_limit || -1 === intval( $memory_limit ) ) { |
|
729 | // Unlimited, set to 32GB. |
||
730 | 1 | $memory_limit = '32000M'; |
|
731 | } |
||
732 | 1 | return intval( $memory_limit ) * 1024 * 1024; |
|
733 | } |
||
734 | |||
735 | /** |
||
736 | * Time exceeded. |
||
737 | * |
||
738 | * Ensures the batch never exceeds a sensible time limit. |
||
739 | * A timeout limit of 30s is common on shared hosting. |
||
740 | * |
||
741 | * @return bool |
||
742 | */ |
||
743 | 1 | protected function time_exceeded() { |
|
744 | 1 | $finish = $this->start_time + apply_filters( 'woocommerce_product_importer_default_time_limit', 20 ); // 20 seconds |
|
745 | 1 | $return = false; |
|
746 | 1 | if ( time() >= $finish ) { |
|
747 | $return = true; |
||
748 | } |
||
749 | 1 | return apply_filters( 'woocommerce_product_importer_time_exceeded', $return ); |
|
750 | } |
||
751 | |||
752 | /** |
||
753 | * Explode CSV cell values using commas by default, and handling escaped |
||
754 | * separators. |
||
755 | * |
||
756 | * @since 3.2.0 |
||
757 | * @param string $value Value to explode. |
||
758 | * @param string $separator Separator separating each value. Defaults to comma. |
||
759 | * @return array |
||
760 | */ |
||
761 | 2 | protected function explode_values( $value, $separator = ',' ) { |
|
762 | 2 | $value = str_replace( '\\,', '::separator::', $value ); |
|
763 | 2 | $values = explode( $separator, $value ); |
|
764 | 2 | $values = array_map( array( $this, 'explode_values_formatter' ), $values ); |
|
765 | |||
766 | 2 | return $values; |
|
767 | } |
||
768 | |||
769 | /** |
||
770 | * Remove formatting and trim each value. |
||
771 | * |
||
772 | * @since 3.2.0 |
||
773 | * @param string $value Value to format. |
||
774 | * @return string |
||
775 | */ |
||
776 | 2 | protected function explode_values_formatter( $value ) { |
|
777 | 2 | return trim( str_replace( '::separator::', ',', $value ) ); |
|
778 | } |
||
779 | |||
780 | /** |
||
781 | * The exporter prepends a ' to escape fields that start with =, +, - or @. |
||
782 | * Remove the prepended ' character preceding those characters. |
||
783 | * |
||
784 | * @since 3.5.2 |
||
785 | * @param string $value A string that may or may not have been escaped with '. |
||
786 | * @return string |
||
787 | */ |
||
788 | 2 | View Code Duplication | protected function unescape_data( $value ) { |
0 ignored issues
–
show
|
|||
789 | 2 | $active_content_triggers = array( "'=", "'+", "'-", "'@" ); |
|
790 | |||
791 | 2 | if ( in_array( mb_substr( $value, 0, 2 ), $active_content_triggers, true ) ) { |
|
792 | $value = mb_substr( $value, 1 ); |
||
793 | } |
||
794 | |||
795 | 2 | return $value; |
|
796 | } |
||
797 | |||
798 | } |
||
799 |
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.