Product Import Export for WooCommerce - Version 1.4.5

Version Description

  • Tested OK with WC 3.4.3
  • Image import process improved.
Download this release

Release Info

Developer mujeebur
Plugin Icon 128x128 Product Import Export for WooCommerce
Version 1.4.5
Comparing to
See all releases

Code changes from version 1.4.4 to 1.4.5

Files changed (32) hide show
  1. Product_Commercial_Sample_CSV.csv +9 -9
  2. Product_WooCommerce_Sample_CSV.csv +9 -9
  3. images/wf-ajax-loader.gif +0 -0
  4. images/wf-failed.png +0 -0
  5. images/wf-import.png +0 -0
  6. images/wf-notice.png +0 -0
  7. images/wf-success.png +0 -0
  8. includes/class-wf-prodimpexpcsv-admin-screen.php +130 -130
  9. includes/class-wf-prodimpexpcsv-ajax-handler.php +68 -68
  10. includes/class-wf-prodimpexpcsv-system-status-tools.php +102 -102
  11. includes/exporter/class-wf-prodimpexpcsv-exporter.php +527 -527
  12. includes/exporter/data/data-wf-hidden-meta-columns.php +19 -19
  13. includes/exporter/data/data-wf-post-columns.php +50 -50
  14. includes/importer/class-wf-csv-parser.php +853 -853
  15. includes/importer/class-wf-prodimpexpcsv-importer.php +40 -40
  16. includes/importer/class-wf-prodimpexpcsv-product-import.php +1564 -1488
  17. includes/importer/data/data-wf-post-defaults.php +21 -21
  18. includes/importer/data/data-wf-postmeta-allowed.php +15 -15
  19. includes/importer/data/data-wf-postmeta-defaults.php +43 -43
  20. includes/importer/data/data-wf-reserved-fields-pair.php +51 -51
  21. includes/importer/data/data-wf-reserved-fields.php +59 -59
  22. includes/importer/views/html-wf-import-greeting.php +83 -83
  23. includes/importer/views/html-wf-import-options.php +130 -130
  24. includes/settings/class-wf-prodimpexpcsv-settings.php +20 -20
  25. includes/views/export/html-wf-export-products.php +100 -100
  26. includes/views/html-wf-admin-screen.php +26 -26
  27. includes/views/import/html-wf-import-products.php +22 -22
  28. includes/views/market.php +41 -41
  29. license.txt +704 -704
  30. product-csv-import-export.php +416 -416
  31. readme.txt +240 -237
  32. styles/wf-style.css +231 -231
Product_Commercial_Sample_CSV.csv CHANGED
@@ -1,12 +1,12 @@
1
- Parent SKU,SKU,Product Name,Short Description,Description,Regular Price,Sale Price,Weight,Images,Product Type,Prodcut Categories,Product Tags,meta:attribute_pa_color,attribute:pa_care-instructions,attribute_data:pa_care-instructions,attribute:pa_color,attribute_data:pa_color,attribute_default:pa_color,attribute:pa_fabric,attribute_data:pa_fabric,attribute:pa_fitting-type,attribute_data:pa_fitting-type
2
,A11,Samsung Galaxy Ace Duos,"-5 MP Primary Camera
3
-3.5 inch Capacitive Touchscreen
4
-Wi-Fi Enabled
5
- ","Having a much vaunted reputation of being one of the world’s leading budget smartphone makers, the Samsung Galaxy Ace Duos S6802 does quite well to maintain Samsung’s authority in the current market. The device comes in a bar shape and has a sleek look to it. The Ace Duos S6802 is a Smart Dual Active SIM, (GSM + GSM) device with both the inserted SIM cards being active at the same time. If you are on a call on sim 1 and you get a call on sim 2, the call would be diverted to sim 1 and the display would show it as call waiting.The same will be apply for both the Sims. So that we cannot miss out any calls on sim 1 and sim 2. This Samsung phone is run on the Android v2.3 (Gingerbread) OS with a snappy processor speed of 832 MHz. To assure the smooth running of apps, the device comes with an adequate 512 MB of RAM.",29.99,11.52,0.5,http://productimportexport.hikeforce.com/wp-content/uploads/2016/08/hikeforce-mobile.jpg | http://productimportexport.hikeforce.com/wp-content/uploads/2016/08/hikeforce-mobile-2.jpg,simple,Mobile Phone,Smart Phone,,,,,,,,,,
6
- ,A12,Formal shoe,Formal shoe leather made,"Formal shoe leather made , black color",10,8,0.5,http://productimportexport.hikeforce.com/wp-content/uploads/2016/09/hikeforce-model-shoe.png,simple,Shoes,Foot Wears,,,,,,,,,,
7
- ,A13,LED TV,LED TV 20 inches,LED TV 20 inches by samsung,30,29,1,http://productimportexport.hikeforce.com/wp-content/uploads/2016/09/hikeforce-model-tv.jpg,simple,Tele Vision,Electronics,,,,,,,,,,
8
- ,A14,Refrigerator,Double door Refrigerator,Double door Refrigerator with auto power saving,35,32,2,http://productimportexport.hikeforce.com/wp-content/uploads/2016/09/hikeforce-model-fridge.jpg,simple,Refrigerator,Electronics,,,,,,,,,,
9
- ,A15,Washing machine,Washing machine with remote control,Washing machine with remote controle and much more options,20,18,2,http://productimportexport.hikeforce.com/wp-content/uploads/2016/09/hikeforce-model-wm.jpg,simple,washing Machine,Electronics,,,,,,,,,,
10
- ,B11,Men's Cotton T-Shirt,The images represent actual product though color of the image and product may slightly differ.,Strut on the streets in comfort adorning this slim-fit T-Shirt from the house of Tinted. This unique creation is made using rayon that will highlight your torso. Work hard and play hard as you party through the night in this utterly comfortable T-Shirt.,10,,1,http://productimportexport.hikeforce.com/wp-content/uploads/2016/08/hikeforce-men-t-shirt-red.png,variable,Clothing & Accessories > Men > Tops & Tees > T-Shirts,T-Shirts,,Wash dark colors seperately,2|1|0,Blue|Red,3|0|1,red,Cotton,0|1|0,Regular Fit,1|1|0
11
- B11,B11V2,,,,24,12,,http://productimportexport.hikeforce.com/wp-content/uploads/2016/08/hikeforce-men-t-shirt-red.png,,,,red,,,,,,,,,
12
- B11,B11V1,,,,22,11,,http://productimportexport.hikeforce.com/wp-content/uploads/2016/08/hikeforce-men-t-shirt-blue.png,,,,blue,,,,,,,,,
1
+ Parent SKU,SKU,Product Name,Short Description,Description,Regular Price,Sale Price,Weight,Images,Product Type,Prodcut Categories,Product Tags,meta:attribute_pa_color,attribute:pa_care-instructions,attribute_data:pa_care-instructions,attribute:pa_color,attribute_data:pa_color,attribute_default:pa_color,attribute:pa_fabric,attribute_data:pa_fabric,attribute:pa_fitting-type,attribute_data:pa_fitting-type
2
,A11,Samsung Galaxy Ace Duos,"-5 MP Primary Camera
3
-3.5 inch Capacitive Touchscreen
4
-Wi-Fi Enabled
5
+ ","Having a much vaunted reputation of being one of the world’s leading budget smartphone makers, the Samsung Galaxy Ace Duos S6802 does quite well to maintain Samsung’s authority in the current market. The device comes in a bar shape and has a sleek look to it. The Ace Duos S6802 is a Smart Dual Active SIM, (GSM + GSM) device with both the inserted SIM cards being active at the same time. If you are on a call on sim 1 and you get a call on sim 2, the call would be diverted to sim 1 and the display would show it as call waiting.The same will be apply for both the Sims. So that we cannot miss out any calls on sim 1 and sim 2. This Samsung phone is run on the Android v2.3 (Gingerbread) OS with a snappy processor speed of 832 MHz. To assure the smooth running of apps, the device comes with an adequate 512 MB of RAM.",29.99,11.52,0.5,http://productimportexport.webtoffee.com/public_html/wp-includes/images/products/hikeforce-mobile.jpg|http://productimportexport.webtoffee.com/public_html/wp-includes/images/products/hikeforce-mobile-2.jpg,simple,Mobile Phone,Smart Phone,,,,,,,,,,
6
+ ,A12,Formal shoe,Formal shoe leather made,"Formal shoe leather made , black color",10,8,0.5,,simple,Shoes,Foot Wears,,,,,,,,,,
7
+ ,A13,LED TV,LED TV 20 inches,LED TV 20 inches by samsung,30,29,1,http://productimportexport.webtoffee.com/public_html/wp-includes/images/products/hikeforce-model-tv.jpg,simple,Tele Vision,Electronics,,,,,,,,,,
8
+ ,A14,Refrigerator,Double door Refrigerator,Double door Refrigerator with auto power saving,35,32,2,http://productimportexport.webtoffee.com/public_html/wp-includes/images/products/hikeforce-model-fridge.jpg,simple,Refrigerator,Electronics,,,,,,,,,,
9
+ ,A15,Washing machine,Washing machine with remote control,Washing machine with remote controle and much more options,20,18,2,http://productimportexport.webtoffee.com/public_html/wp-includes/images/products/hikeforce-model-wm.jpg,simple,washing Machine,Electronics,,,,,,,,,,
10
+ ,B11,Men's Cotton T-Shirt,The images represent actual product though color of the image and product may slightly differ.,Strut on the streets in comfort adorning this slim-fit T-Shirt from the house of Tinted. This unique creation is made using rayon that will highlight your torso. Work hard and play hard as you party through the night in this utterly comfortable T-Shirt.,10,,1,http://productimportexport.webtoffee.com/public_html/wp-includes/images/products/hikeforce-men-t-shirt-red.png,variable,Clothing & Accessories > Men > Tops & Tees > T-Shirts,T-Shirts,,Wash dark colors seperately,2|1|0,Blue|Red,3|0|1,red,Cotton,0|1|0,Regular Fit,1|1|0
11
+ B11,B11V2,,,,24,12,,http://productimportexport.webtoffee.com/public_html/wp-includes/images/products/hikeforce-men-t-shirt-red.png,,,,red,,,,,,,,,
12
+ B11,B11V1,,,,22,11,,http://productimportexport.webtoffee.com/public_html/wp-includes/images/products/hikeforce-men-t-shirt-blue.png,,,,blue,,,,,,,,,
Product_WooCommerce_Sample_CSV.csv CHANGED
@@ -1,12 +1,12 @@
1
- parent_sku,sku,post_title,post_excerpt,post_content,regular_price,sale_price,weight,Images,tax:product_type,tax:product_cat,tax:product_tag,meta:attribute_pa_color,attribute:pa_care-instructions,attribute_data:pa_care-instructions,attribute:pa_color,attribute_data:pa_color,attribute_default:pa_color,attribute:pa_fabric,attribute_data:pa_fabric,attribute:pa_fitting-type,attribute_data:pa_fitting-type
2
,A11,Samsung Galaxy Ace Duos,"-5 MP Primary Camera
3
-3.5 inch Capacitive Touchscreen
4
-Wi-Fi Enabled
5
- ","Having a much vaunted reputation of being one of the world’s leading budget smartphone makers, the Samsung Galaxy Ace Duos S6802 does quite well to maintain Samsung’s authority in the current market. The device comes in a bar shape and has a sleek look to it. The Ace Duos S6802 is a Smart Dual Active SIM, (GSM + GSM) device with both the inserted SIM cards being active at the same time. If you are on a call on sim 1 and you get a call on sim 2, the call would be diverted to sim 1 and the display would show it as call waiting.The same will be apply for both the Sims. So that we cannot miss out any calls on sim 1 and sim 2. This Samsung phone is run on the Android v2.3 (Gingerbread) OS with a snappy processor speed of 832 MHz. To assure the smooth running of apps, the device comes with an adequate 512 MB of RAM.",29.99,11.52,0.5,http://productimportexport.hikeforce.com/wp-content/uploads/2016/08/hikeforce-mobile.jpg | http://productimportexport.hikeforce.com/wp-content/uploads/2016/08/hikeforce-mobile-2.jpg,simple,Mobile Phone,Smart Phone,,,,,,,,,,
6
- ,A12,Formal shoe,Formal shoe leather made,"Formal shoe leather made , black color",10,8,0.5,http://productimportexport.hikeforce.com/wp-content/uploads/2016/09/hikeforce-model-shoe.png,simple,Shoes,Foot Wears,,,,,,,,,,
7
- ,A13,LED TV,LED TV 20 inches,LED TV 20 inches by samsung,30,29,1,http://productimportexport.hikeforce.com/wp-content/uploads/2016/09/hikeforce-model-tv.jpg,simple,Tele Vision,Electronics,,,,,,,,,,
8
- ,A14,Refrigerator,Double door Refrigerator,Double door Refrigerator with auto power saving,35,32,2,http://productimportexport.hikeforce.com/wp-content/uploads/2016/09/hikeforce-model-fridge.jpg,simple,Refrigerator,Electronics,,,,,,,,,,
9
- ,A15,Washing machine,Washing machine with remote control,Washing machine with remote controle and much more options,20,18,2,http://productimportexport.hikeforce.com/wp-content/uploads/2016/09/hikeforce-model-wm.jpg,simple,washing Machine,Electronics,,,,,,,,,,
10
- ,B11,Men's Cotton T-Shirt,The images represent actual product though color of the image and product may slightly differ.,Strut on the streets in comfort adorning this slim-fit T-Shirt from the house of Tinted. This unique creation is made using rayon that will highlight your torso. Work hard and play hard as you party through the night in this utterly comfortable T-Shirt.,10,,1,http://productimportexport.hikeforce.com/wp-content/uploads/2016/08/hikeforce-men-t-shirt-red.png,variable,Clothing & Accessories > Men > Tops & Tees > T-Shirts,T-Shirts,,Wash dark colors seperately,2|1|0,Blue|Red,3|0|1,red,Cotton,0|1|0,Regular Fit,1|1|0
11
- B11,B11V2,,,,24,12,,http://productimportexport.hikeforce.com/wp-content/uploads/2016/08/hikeforce-men-t-shirt-red.png,,,,red,,,,,,,,,
12
- B11,B11V1,,,,22,11,,http://productimportexport.hikeforce.com/wp-content/uploads/2016/08/hikeforce-men-t-shirt-blue.png,,,,blue,,,,,,,,,
1
+ parent_sku,sku,post_title,post_excerpt,post_content,regular_price,sale_price,weight,Images,tax:product_type,tax:product_cat,tax:product_tag,meta:attribute_pa_color,attribute:pa_care-instructions,attribute_data:pa_care-instructions,attribute:pa_color,attribute_data:pa_color,attribute_default:pa_color,attribute:pa_fabric,attribute_data:pa_fabric,attribute:pa_fitting-type,attribute_data:pa_fitting-type
2
,A11,Samsung Galaxy Ace Duos,"-5 MP Primary Camera
3
-3.5 inch Capacitive Touchscreen
4
-Wi-Fi Enabled
5
+ ","Having a much vaunted reputation of being one of the world’s leading budget smartphone makers, the Samsung Galaxy Ace Duos S6802 does quite well to maintain Samsung’s authority in the current market. The device comes in a bar shape and has a sleek look to it. The Ace Duos S6802 is a Smart Dual Active SIM, (GSM + GSM) device with both the inserted SIM cards being active at the same time. If you are on a call on sim 1 and you get a call on sim 2, the call would be diverted to sim 1 and the display would show it as call waiting.The same will be apply for both the Sims. So that we cannot miss out any calls on sim 1 and sim 2. This Samsung phone is run on the Android v2.3 (Gingerbread) OS with a snappy processor speed of 832 MHz. To assure the smooth running of apps, the device comes with an adequate 512 MB of RAM.",29.99,11.52,0.5,http://productimportexport.webtoffee.com/public_html/wp-includes/images/products/hikeforce-mobile.jpg|http://productimportexport.webtoffee.com/public_html/wp-includes/images/products/hikeforce-mobile-2.jpg,simple,Mobile Phone,Smart Phone,,,,,,,,,,
6
+ ,A12,Formal shoe,Formal shoe leather made,"Formal shoe leather made , black color",10,8,0.5,,simple,Shoes,Foot Wears,,,,,,,,,,
7
+ ,A13,LED TV,LED TV 20 inches,LED TV 20 inches by samsung,30,29,1,http://productimportexport.webtoffee.com/public_html/wp-includes/images/products/hikeforce-model-tv.jpg,simple,Tele Vision,Electronics,,,,,,,,,,
8
+ ,A14,Refrigerator,Double door Refrigerator,Double door Refrigerator with auto power saving,35,32,2,http://productimportexport.webtoffee.com/public_html/wp-includes/images/products/hikeforce-model-fridge.jpg,simple,Refrigerator,Electronics,,,,,,,,,,
9
+ ,A15,Washing machine,Washing machine with remote control,Washing machine with remote controle and much more options,20,18,2,http://productimportexport.webtoffee.com/public_html/wp-includes/images/products/hikeforce-model-wm.jpg,simple,washing Machine,Electronics,,,,,,,,,,
10
+ ,B11,Men's Cotton T-Shirt,The images represent actual product though color of the image and product may slightly differ.,Strut on the streets in comfort adorning this slim-fit T-Shirt from the house of Tinted. This unique creation is made using rayon that will highlight your torso. Work hard and play hard as you party through the night in this utterly comfortable T-Shirt.,10,,1,http://productimportexport.webtoffee.com/public_html/wp-includes/images/products/hikeforce-men-t-shirt-red.png,variable,Clothing & Accessories > Men > Tops & Tees > T-Shirts,T-Shirts,,Wash dark colors seperately,2|1|0,Blue|Red,3|0|1,red,Cotton,0|1|0,Regular Fit,1|1|0
11
+ B11,B11V2,,,,24,12,,http://productimportexport.webtoffee.com/public_html/wp-includes/images/products/hikeforce-men-t-shirt-red.png,,,,red,,,,,,,,,
12
+ B11,B11V1,,,,22,11,,http://productimportexport.webtoffee.com/public_html/wp-includes/images/products/hikeforce-men-t-shirt-blue.png,,,,blue,,,,,,,,,
images/wf-ajax-loader.gif CHANGED
File without changes
images/wf-failed.png CHANGED
File without changes
images/wf-import.png CHANGED
File without changes
images/wf-notice.png CHANGED
File without changes
images/wf-success.png CHANGED
File without changes
includes/class-wf-prodimpexpcsv-admin-screen.php CHANGED
@@ -1,131 +1,131 @@
1
- <?php
2
- if (!defined('ABSPATH')) {
3
- exit;
4
- }
5
-
6
- class WF_ProdImpExpCsv_Admin_Screen {
7
-
8
- /**
9
- * Constructor
10
- */
11
- public function __construct() {
12
-
13
- add_action('admin_menu', array($this, 'admin_menu'));
14
- add_action('admin_print_styles', array($this, 'admin_scripts'));
15
- add_action('admin_notices', array($this, 'admin_notices'));
16
-
17
- add_action('in_admin_header', array($this, 'render_review_text'), 1);
18
- add_action('wp_ajax_review_rated', array($this, 'review_rated'));
19
- }
20
-
21
- /**
22
- * Notices in admin
23
- */
24
- public function admin_notices() {
25
- if (!function_exists('mb_detect_encoding')) {
26
- echo '<div class="error"><p>' . __('Product CSV Import Export requires the function <code>mb_detect_encoding</code> to import and export CSV files. Please ask your hosting provider to enable this function.', 'wf_csv_import_export') . '</p></div>';
27
- }
28
- }
29
-
30
- /**
31
- * Admin Menu
32
- */
33
- public function admin_menu() {
34
- $page1 = add_submenu_page('edit.php?post_type=product', __('Product Im-Ex', 'wf_csv_import_export'), __('Product Im-Ex', 'wf_csv_import_export'), apply_filters('woocommerce_csv_product_role', 'manage_woocommerce'), 'wf_woocommerce_csv_im_ex', array($this, 'output'));
35
- $page = add_submenu_page('woocommerce', __('Product Import-Export', 'wf_csv_import_export'), __('Product Import-Export', 'wf_csv_import_export'), apply_filters('woocommerce_csv_product_role', 'manage_woocommerce'), 'wf_woocommerce_csv_im_ex', array($this, 'output'));
36
-
37
- }
38
-
39
- /**
40
- * Admin Scripts
41
- */
42
- public function admin_scripts() {
43
- wp_enqueue_style('woocommerce_admin_styles', WC()->plugin_url() . '/assets/css/admin.css');
44
- wp_enqueue_style('woocommerce-product-csv-importer', plugins_url(basename(plugin_dir_path(WF_ProdImpExpCsv_FILE)) . '/styles/wf-style.css', basename(__FILE__)), '', '1.4.4', 'screen');
45
- }
46
-
47
- /**
48
- * Admin Screen output
49
- */
50
- public function output() {
51
-
52
- $tab = '';
53
- if (!empty($_GET['tab'])) {
54
- if ($_GET['tab'] == 'help') {
55
- $tab = 'help';
56
- }
57
- }
58
-
59
- include( 'views/html-wf-admin-screen.php' );
60
- }
61
-
62
- /**
63
- * Admin Page for exporting
64
- */
65
- public function admin_export_page() {
66
- $post_columns = include( 'exporter/data/data-wf-post-columns.php' );
67
- include( 'views/export/html-wf-export-products.php' );
68
- }
69
-
70
- /**
71
- * Admin Page for help
72
- */
73
- public function admin_help_page() {
74
- include('views/html-wf-help-guide.php');
75
- }
76
-
77
- /**
78
- * Change the admin header text on WooCommerce admin pages.
79
- *
80
- * @since 1.4.3
81
- * @param string $header_text
82
- * @return string
83
- */
84
- public function render_review_text($header_text) {
85
-
86
- if (strtotime(get_option('xa_pipe_plugin_installed_date')) < strtotime('-7 days')) {
87
-
88
- if (!current_user_can('manage_woocommerce') || !function_exists('wc_get_screen_ids')) {
89
- return $header_text;
90
- }
91
-
92
- $current_screen = get_current_screen();
93
-
94
- $xa_pages = array('product_page_wf_woocommerce_csv_im_ex');
95
-
96
- if (isset($current_screen->id) && apply_filters('xa_display_admin_footer_text', in_array($current_screen->id, $xa_pages))) {
97
-
98
- if (!get_option('xa_pipe_plugin_review_rated')) {
99
- $header_text = sprintf(
100
- __('<div class="updated"><p>You have been using %1$s for a while. If you like the plugin please leave us a %2$s review!<p></div>', 'wf_csv_import_export'), sprintf('<strong>%s</strong>', esc_html__('Product Import Export for WooCommerce', 'wf_csv_import_export')), '<a href="https://wordpress.org/support/plugin/product-import-export-for-woo/reviews?rate=5#new-post" target="_blank" class="xa-pipe-rating-link" data-reviewed="' . esc_attr__('Thanks for the review.', 'wf_csv_import_export') . '">&#9733;&#9733;&#9733;&#9733;&#9733;</a>'
101
- );
102
- wc_enqueue_js("
103
- jQuery( 'a.xa-pipe-rating-link' ).click( function() {
104
- jQuery.post( '" . admin_url("admin-ajax.php") . "', { action: 'review_rated' } );
105
- jQuery( this ).parent().text( jQuery( this ).data( 'reviewed' ) );
106
- });
107
- ");
108
- } else {
109
- $header_text = '';
110
- }
111
- }
112
-
113
- echo $header_text;
114
- }
115
- }
116
-
117
- /**
118
- * Fired when clicking the rating header.
119
- */
120
- public function review_rated() {
121
-
122
- if (!current_user_can('manage_woocommerce')) {
123
- wp_die(-1);
124
- }
125
- update_option('xa_pipe_plugin_review_rated', 1);
126
- wp_die();
127
- }
128
-
129
- }
130
-
131
new WF_ProdImpExpCsv_Admin_Screen();
1
+ <?php
2
+ if (!defined('ABSPATH')) {
3
+ exit;
4
+ }
5
+
6
+ class WF_ProdImpExpCsv_Admin_Screen {
7
+
8
+ /**
9
+ * Constructor
10
+ */
11
+ public function __construct() {
12
+
13
+ add_action('admin_menu', array($this, 'admin_menu'));
14
+ add_action('admin_print_styles', array($this, 'admin_scripts'));
15
+ add_action('admin_notices', array($this, 'admin_notices'));
16
+
17
+ add_action('in_admin_header', array($this, 'render_review_text'), 1);
18
+ add_action('wp_ajax_review_rated', array($this, 'review_rated'));
19
+ }
20
+
21
+ /**
22
+ * Notices in admin
23
+ */
24
+ public function admin_notices() {
25
+ if (!function_exists('mb_detect_encoding')) {
26
+ echo '<div class="error"><p>' . __('Product CSV Import Export requires the function <code>mb_detect_encoding</code> to import and export CSV files. Please ask your hosting provider to enable this function.', 'wf_csv_import_export') . '</p></div>';
27
+ }
28
+ }
29
+
30
+ /**
31
+ * Admin Menu
32
+ */
33
+ public function admin_menu() {
34
+ $page1 = add_submenu_page('edit.php?post_type=product', __('Product Im-Ex', 'wf_csv_import_export'), __('Product Im-Ex', 'wf_csv_import_export'), apply_filters('woocommerce_csv_product_role', 'manage_woocommerce'), 'wf_woocommerce_csv_im_ex', array($this, 'output'));
35
+ $page = add_submenu_page('woocommerce', __('Product Import-Export', 'wf_csv_import_export'), __('Product Import-Export', 'wf_csv_import_export'), apply_filters('woocommerce_csv_product_role', 'manage_woocommerce'), 'wf_woocommerce_csv_im_ex', array($this, 'output'));
36
+
37
+ }
38
+
39
+ /**
40
+ * Admin Scripts
41
+ */
42
+ public function admin_scripts() {
43
+ wp_enqueue_style('woocommerce_admin_styles', WC()->plugin_url() . '/assets/css/admin.css');
44
+ wp_enqueue_style('woocommerce-product-csv-importer', plugins_url(basename(plugin_dir_path(WF_ProdImpExpCsv_FILE)) . '/styles/wf-style.css', basename(__FILE__)), '', '1.4.4', 'screen');
45
+ }
46
+
47
+ /**
48
+ * Admin Screen output
49
+ */
50
+ public function output() {
51
+
52
+ $tab = '';
53
+ if (!empty($_GET['tab'])) {
54
+ if ($_GET['tab'] == 'help') {
55
+ $tab = 'help';
56
+ }
57
+ }
58
+
59
+ include( 'views/html-wf-admin-screen.php' );
60
+ }
61
+
62
+ /**
63
+ * Admin Page for exporting
64
+ */
65
+ public function admin_export_page() {
66
+ $post_columns = include( 'exporter/data/data-wf-post-columns.php' );
67
+ include( 'views/export/html-wf-export-products.php' );
68
+ }
69
+
70
+ /**
71
+ * Admin Page for help
72
+ */
73
+ public function admin_help_page() {
74
+ include('views/html-wf-help-guide.php');
75
+ }
76
+
77
+ /**
78
+ * Change the admin header text on WooCommerce admin pages.
79
+ *
80
+ * @since 1.4.3
81
+ * @param string $header_text
82
+ * @return string
83
+ */
84
+ public function render_review_text($header_text) {
85
+
86
+ if (strtotime(get_option('xa_pipe_plugin_installed_date')) < strtotime('-7 days')) {
87
+
88
+ if (!current_user_can('manage_woocommerce') || !function_exists('wc_get_screen_ids')) {
89
+ return $header_text;
90
+ }
91
+
92
+ $current_screen = get_current_screen();
93
+
94
+ $xa_pages = array('product_page_wf_woocommerce_csv_im_ex');
95
+
96
+ if (isset($current_screen->id) && apply_filters('xa_display_admin_footer_text', in_array($current_screen->id, $xa_pages))) {
97
+
98
+ if (!get_option('xa_pipe_plugin_review_rated')) {
99
+ $header_text = sprintf(
100
+ __('<div class="updated"><p>You have been using %1$s for a while. If you like the plugin please leave us a %2$s review!<p></div>', 'wf_csv_import_export'), sprintf('<strong>%s</strong>', esc_html__('Product Import Export for WooCommerce', 'wf_csv_import_export')), '<a href="https://wordpress.org/support/plugin/product-import-export-for-woo/reviews?rate=5#new-post" target="_blank" class="xa-pipe-rating-link" data-reviewed="' . esc_attr__('Thanks for the review.', 'wf_csv_import_export') . '">&#9733;&#9733;&#9733;&#9733;&#9733;</a>'
101
+ );
102
+ wc_enqueue_js("
103
+ jQuery( 'a.xa-pipe-rating-link' ).click( function() {
104
+ jQuery.post( '" . admin_url("admin-ajax.php") . "', { action: 'review_rated' } );
105
+ jQuery( this ).parent().text( jQuery( this ).data( 'reviewed' ) );
106
+ });
107
+ ");
108
+ } else {
109
+ $header_text = '';
110
+ }
111
+ }
112
+
113
+ echo $header_text;
114
+ }
115
+ }
116
+
117
+ /**
118
+ * Fired when clicking the rating header.
119
+ */
120
+ public function review_rated() {
121
+
122
+ if (!current_user_can('manage_woocommerce')) {
123
+ wp_die(-1);
124
+ }
125
+ update_option('xa_pipe_plugin_review_rated', 1);
126
+ wp_die();
127
+ }
128
+
129
+ }
130
+
131
new WF_ProdImpExpCsv_Admin_Screen();
includes/class-wf-prodimpexpcsv-ajax-handler.php CHANGED
@@ -1,69 +1,69 @@
1
- <?php
2
- if ( ! defined( 'ABSPATH' ) ) {
3
- exit;
4
- }
5
-
6
- class WF_ProdImpExpCsv_AJAX_Handler {
7
-
8
- /**
9
- * Constructor
10
- */
11
- public function __construct() {
12
- add_action( 'wp_ajax_woocommerce_csv_import_request', array( $this, 'csv_import_request' ) );
13
- add_action( 'wp_ajax_woocommerce_csv_import_regenerate_thumbnail', array( $this, 'regenerate_thumbnail' ) );
14
- }
15
-
16
- /**
17
- * Ajax event for importing a CSV
18
- */
19
- public function csv_import_request() {
20
- define( 'WP_LOAD_IMPORTERS', true );
21
- WF_ProdImpExpCsv_Importer::product_importer();
22
- }
23
-
24
- /**
25
- * From regenerate thumbnails plugin
26
- */
27
- public function regenerate_thumbnail() {
28
- @error_reporting( 0 ); // Don't break the JSON result
29
-
30
- header( 'Content-type: application/json' );
31
-
32
- $id = (int) $_REQUEST['id'];
33
- $image = get_post( $id );
34
-
35
- if ( ! $image || 'attachment' != $image->post_type || 'image/' != substr( $image->post_mime_type, 0, 6 ) )
36
- die( json_encode( array( 'error' => sprintf( __( 'Failed resize: %s is an invalid image ID.', 'wf_csv_import_export' ), esc_html( $_REQUEST['id'] ) ) ) ) );
37
-
38
- if ( ! current_user_can( 'manage_woocommerce' ) )
39
- $this->die_json_error_msg( $image->ID, __( "Your user account doesn't have permission to resize images", 'wf_csv_import_export' ) );
40
-
41
- $fullsizepath = get_attached_file( $image->ID );
42
-
43
- if ( false === $fullsizepath || ! file_exists( $fullsizepath ) )
44
- $this->die_json_error_msg( $image->ID, sprintf( __( 'The originally uploaded image file cannot be found at %s', 'wf_csv_import_export' ), '<code>' . esc_html( $fullsizepath ) . '</code>' ) );
45
-
46
- @set_time_limit( 900 ); // 5 minutes per image should be PLENTY
47
-
48
- $metadata = wp_generate_attachment_metadata( $image->ID, $fullsizepath );
49
-
50
- if ( is_wp_error( $metadata ) )
51
- $this->die_json_error_msg( $image->ID, $metadata->get_error_message() );
52
- if ( empty( $metadata ) )
53
- $this->die_json_error_msg( $image->ID, __( 'Unknown failure reason.', 'wf_csv_import_export' ) );
54
-
55
- // If this fails, then it just means that nothing was changed (old value == new value)
56
- wp_update_attachment_metadata( $image->ID, $metadata );
57
-
58
- die( json_encode( array( 'success' => sprintf( __( '&quot;%1$s&quot; (ID %2$s) was successfully resized in %3$s seconds.', 'wf_csv_import_export' ), esc_html( get_the_title( $image->ID ) ), $image->ID, timer_stop() ) ) ) );
59
- }
60
-
61
- /**
62
- * Die with a JSON formatted error message
63
- */
64
- public function die_json_error_msg( $id, $message ) {
65
- die( json_encode( array( 'error' => sprintf( __( '&quot;%1$s&quot; (ID %2$s) failed to resize. The error message was: %3$s', 'regenerate-thumbnails' ), esc_html( get_the_title( $id ) ), $id, $message ) ) ) );
66
- }
67
- }
68
-
69
new WF_ProdImpExpCsv_AJAX_Handler();
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ exit;
4
+ }
5
+
6
+ class WF_ProdImpExpCsv_AJAX_Handler {
7
+
8
+ /**
9
+ * Constructor
10
+ */
11
+ public function __construct() {
12
+ add_action( 'wp_ajax_woocommerce_csv_import_request', array( $this, 'csv_import_request' ) );
13
+ add_action( 'wp_ajax_woocommerce_csv_import_regenerate_thumbnail', array( $this, 'regenerate_thumbnail' ) );
14
+ }
15
+
16
+ /**
17
+ * Ajax event for importing a CSV
18
+ */
19
+ public function csv_import_request() {
20
+ define( 'WP_LOAD_IMPORTERS', true );
21
+ WF_ProdImpExpCsv_Importer::product_importer();
22
+ }
23
+
24
+ /**
25
+ * From regenerate thumbnails plugin
26
+ */
27
+ public function regenerate_thumbnail() {
28
+ @error_reporting( 0 ); // Don't break the JSON result
29
+
30
+ header( 'Content-type: application/json' );
31
+
32
+ $id = (int) $_REQUEST['id'];
33
+ $image = get_post( $id );
34
+
35
+ if ( ! $image || 'attachment' != $image->post_type || 'image/' != substr( $image->post_mime_type, 0, 6 ) )
36
+ die( json_encode( array( 'error' => sprintf( __( 'Failed resize: %s is an invalid image ID.', 'wf_csv_import_export' ), esc_html( $_REQUEST['id'] ) ) ) ) );
37
+
38
+ if ( ! current_user_can( 'manage_woocommerce' ) )
39
+ $this->die_json_error_msg( $image->ID, __( "Your user account doesn't have permission to resize images", 'wf_csv_import_export' ) );
40
+
41
+ $fullsizepath = get_attached_file( $image->ID );
42
+
43
+ if ( false === $fullsizepath || ! file_exists( $fullsizepath ) )
44
+ $this->die_json_error_msg( $image->ID, sprintf( __( 'The originally uploaded image file cannot be found at %s', 'wf_csv_import_export' ), '<code>' . esc_html( $fullsizepath ) . '</code>' ) );
45
+
46
+ @set_time_limit( 900 ); // 5 minutes per image should be PLENTY
47
+
48
+ $metadata = wp_generate_attachment_metadata( $image->ID, $fullsizepath );
49
+
50
+ if ( is_wp_error( $metadata ) )
51
+ $this->die_json_error_msg( $image->ID, $metadata->get_error_message() );
52
+ if ( empty( $metadata ) )
53
+ $this->die_json_error_msg( $image->ID, __( 'Unknown failure reason.', 'wf_csv_import_export' ) );
54
+
55
+ // If this fails, then it just means that nothing was changed (old value == new value)
56
+ wp_update_attachment_metadata( $image->ID, $metadata );
57
+
58
+ die( json_encode( array( 'success' => sprintf( __( '&quot;%1$s&quot; (ID %2$s) was successfully resized in %3$s seconds.', 'wf_csv_import_export' ), esc_html( get_the_title( $image->ID ) ), $image->ID, timer_stop() ) ) ) );
59
+ }
60
+
61
+ /**
62
+ * Die with a JSON formatted error message
63
+ */
64
+ public function die_json_error_msg( $id, $message ) {
65
+ die( json_encode( array( 'error' => sprintf( __( '&quot;%1$s&quot; (ID %2$s) failed to resize. The error message was: %3$s', 'regenerate-thumbnails' ), esc_html( get_the_title( $id ) ), $id, $message ) ) ) );
66
+ }
67
+ }
68
+
69
new WF_ProdImpExpCsv_AJAX_Handler();
includes/class-wf-prodimpexpcsv-system-status-tools.php CHANGED
@@ -1,103 +1,103 @@
1
- <?php
2
- if ( ! defined( 'ABSPATH' ) ) {
3
- exit;
4
- }
5
-
6
- class WF_ProdImpExpCsv_System_Status_Tools {
7
-
8
- /**
9
- * Constructor
10
- */
11
- public function __construct() {
12
- add_filter( 'woocommerce_debug_tools', array( $this, 'tools' ) );
13
- }
14
-
15
- /**
16
- * Tools we add to WC
17
- * @param array $tools
18
- * @return array
19
- */
20
- public function tools( $tools ) {
21
- $tools['delete_products'] = array(
22
- 'name' => __( 'Delete Products','wf_csv_import_export'),
23
- 'button' => __( 'Delete ALL products','wf_csv_import_export' ),
24
- 'desc' => __( 'This tool will delete all products allowing you to start fresh.', 'wf_csv_import_export' ),
25
- 'callback' => array( $this, 'delete_products' )
26
- );
27
- $tools['delete_variations'] = array(
28
- 'name' => __( 'Delete Variations','wf_csv_import_export'),
29
- 'button' => __( 'Delete ALL variations','wf_csv_import_export' ),
30
- 'desc' => __( 'This tool will delete all variations allowing you to start fresh.', 'wf_csv_import_export' ),
31
- 'callback' => array( $this, 'delete_variations' )
32
- );
33
- $tools['delete_orphaned_variations'] = array(
34
- 'name' => __( 'Delete Orphans','wf_csv_import_export'),
35
- 'button' => __( 'Delete orphaned variations','wf_csv_import_export' ),
36
- 'desc' => __( 'This tool will delete variations which have no parent.', 'wf_csv_import_export' ),
37
- 'callback' => array( $this, 'delete_orphaned_variations' )
38
- );
39
- return $tools;
40
- }
41
-
42
- /**
43
- * Delete products
44
- */
45
- public function delete_products() {
46
- global $wpdb;
47
-
48
- // Delete products
49
- $result = absint( $wpdb->delete( $wpdb->posts, array( 'post_type' => 'product' ) ) );
50
- $result2 = absint( $wpdb->delete( $wpdb->posts, array( 'post_type' => 'product_variation' ) ) );
51
-
52
- // Delete meta and term relationships with no post
53
- $wpdb->query( "DELETE pm
54
- FROM {$wpdb->postmeta} pm
55
- LEFT JOIN {$wpdb->posts} wp ON wp.ID = pm.post_id
56
- WHERE wp.ID IS NULL" );
57
- $wpdb->query( "DELETE tr
58
- FROM {$wpdb->term_relationships} tr
59
- LEFT JOIN {$wpdb->posts} wp ON wp.ID = tr.object_id
60
- WHERE wp.ID IS NULL" );
61
-
62
- echo '<div class="updated"><p>' . sprintf( __( '%d Products Deleted', 'wf_csv_import_export' ), ( $result + $result2 ) ) . '</p></div>';
63
- }
64
-
65
- /**
66
- * Delete variations
67
- */
68
- public function delete_variations() {
69
- global $wpdb;
70
-
71
- // Delete products
72
- $result = absint( $wpdb->delete( $wpdb->posts, array( 'post_type' => 'product_variation' ) ) );
73
-
74
- // Delete meta and term relationships with no post
75
- $wpdb->query( "DELETE pm
76
- FROM {$wpdb->postmeta} pm
77
- LEFT JOIN {$wpdb->posts} wp ON wp.ID = pm.post_id
78
- WHERE wp.ID IS NULL" );
79
- $wpdb->query( "DELETE tr
80
- FROM {$wpdb->term_relationships} tr
81
- LEFT JOIN {$wpdb->posts} wp ON wp.ID = tr.object_id
82
- WHERE wp.ID IS NULL" );
83
-
84
- echo '<div class="updated"><p>' . sprintf( __( '%d Variations Deleted', 'wf_csv_import_export' ), $result ) . '</p></div>';
85
- }
86
-
87
- /**
88
- * Delete orphans
89
- */
90
- public function delete_orphaned_variations() {
91
- global $wpdb;
92
-
93
- // Delete meta and term relationships with no post
94
- $result = absint( $wpdb->query( "DELETE products
95
- FROM {$wpdb->posts} products
96
- LEFT JOIN {$wpdb->posts} wp ON wp.ID = products.post_parent
97
- WHERE wp.ID IS NULL AND products.post_type = 'product_variation';" ) );
98
-
99
- echo '<div class="updated"><p>' . sprintf( __( '%d Variations Deleted', 'wf_csv_import_export' ), $result ) . '</p></div>';
100
- }
101
- }
102
-
103
new WF_ProdImpExpCsv_System_Status_Tools();
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ exit;
4
+ }
5
+
6
+ class WF_ProdImpExpCsv_System_Status_Tools {
7
+
8
+ /**
9
+ * Constructor
10
+ */
11
+ public function __construct() {
12
+ add_filter( 'woocommerce_debug_tools', array( $this, 'tools' ) );
13
+ }
14
+
15
+ /**
16
+ * Tools we add to WC
17
+ * @param array $tools
18
+ * @return array
19
+ */
20
+ public function tools( $tools ) {
21
+ $tools['delete_products'] = array(
22
+ 'name' => __( 'Delete Products','wf_csv_import_export'),
23
+ 'button' => __( 'Delete ALL products','wf_csv_import_export' ),
24
+ 'desc' => __( 'This tool will delete all products allowing you to start fresh.', 'wf_csv_import_export' ),
25
+ 'callback' => array( $this, 'delete_products' )
26
+ );
27
+ $tools['delete_variations'] = array(
28
+ 'name' => __( 'Delete Variations','wf_csv_import_export'),
29
+ 'button' => __( 'Delete ALL variations','wf_csv_import_export' ),
30
+ 'desc' => __( 'This tool will delete all variations allowing you to start fresh.', 'wf_csv_import_export' ),
31
+ 'callback' => array( $this, 'delete_variations' )
32
+ );
33
+ $tools['delete_orphaned_variations'] = array(
34
+ 'name' => __( 'Delete Orphans','wf_csv_import_export'),
35
+ 'button' => __( 'Delete orphaned variations','wf_csv_import_export' ),
36
+ 'desc' => __( 'This tool will delete variations which have no parent.', 'wf_csv_import_export' ),
37
+ 'callback' => array( $this, 'delete_orphaned_variations' )
38
+ );
39
+ return $tools;
40
+ }
41
+
42
+ /**
43
+ * Delete products
44
+ */
45
+ public function delete_products() {
46
+ global $wpdb;
47
+
48
+ // Delete products
49
+ $result = absint( $wpdb->delete( $wpdb->posts, array( 'post_type' => 'product' ) ) );
50
+ $result2 = absint( $wpdb->delete( $wpdb->posts, array( 'post_type' => 'product_variation' ) ) );
51
+
52
+ // Delete meta and term relationships with no post
53
+ $wpdb->query( "DELETE pm
54
+ FROM {$wpdb->postmeta} pm
55
+ LEFT JOIN {$wpdb->posts} wp ON wp.ID = pm.post_id
56
+ WHERE wp.ID IS NULL" );
57
+ $wpdb->query( "DELETE tr
58
+ FROM {$wpdb->term_relationships} tr
59
+ LEFT JOIN {$wpdb->posts} wp ON wp.ID = tr.object_id
60
+ WHERE wp.ID IS NULL" );
61
+
62
+ echo '<div class="updated"><p>' . sprintf( __( '%d Products Deleted', 'wf_csv_import_export' ), ( $result + $result2 ) ) . '</p></div>';
63
+ }
64
+
65
+ /**
66
+ * Delete variations
67
+ */
68
+ public function delete_variations() {
69
+ global $wpdb;
70
+
71
+ // Delete products
72
+ $result = absint( $wpdb->delete( $wpdb->posts, array( 'post_type' => 'product_variation' ) ) );
73
+
74
+ // Delete meta and term relationships with no post
75
+ $wpdb->query( "DELETE pm
76
+ FROM {$wpdb->postmeta} pm
77
+ LEFT JOIN {$wpdb->posts} wp ON wp.ID = pm.post_id
78
+ WHERE wp.ID IS NULL" );
79
+ $wpdb->query( "DELETE tr
80
+ FROM {$wpdb->term_relationships} tr
81
+ LEFT JOIN {$wpdb->posts} wp ON wp.ID = tr.object_id
82
+ WHERE wp.ID IS NULL" );
83
+
84
+ echo '<div class="updated"><p>' . sprintf( __( '%d Variations Deleted', 'wf_csv_import_export' ), $result ) . '</p></div>';
85
+ }
86
+
87
+ /**
88
+ * Delete orphans
89
+ */
90
+ public function delete_orphaned_variations() {
91
+ global $wpdb;
92
+
93
+ // Delete meta and term relationships with no post
94
+ $result = absint( $wpdb->query( "DELETE products
95
+ FROM {$wpdb->posts} products
96
+ LEFT JOIN {$wpdb->posts} wp ON wp.ID = products.post_parent
97
+ WHERE wp.ID IS NULL AND products.post_type = 'product_variation';" ) );
98
+
99
+ echo '<div class="updated"><p>' . sprintf( __( '%d Variations Deleted', 'wf_csv_import_export' ), $result ) . '</p></div>';
100
+ }
101
+ }
102
+
103
new WF_ProdImpExpCsv_System_Status_Tools();
includes/exporter/class-wf-prodimpexpcsv-exporter.php CHANGED
@@ -1,527 +1,527 @@
1
- <?php
2
- if ( ! defined( 'ABSPATH' ) ) {
3
- exit;
4
- }
5
-
6
- class WF_ProdImpExpCsv_Exporter {
7
-
8
- /**
9
- * Product Exporter Tool
10
- */
11
- public static function do_export( $post_type = 'product' ) {
12
- global $wpdb;
13
-
14
- $export_limit = ! empty( $_POST['limit'] ) ? intval( $_POST['limit'] ) : 999999999;
15
- $export_count = 0;
16
- $limit = 100;
17
- $current_offset = ! empty( $_POST['offset'] ) ? intval( $_POST['offset'] ) : 0;
18
- $csv_columns = include( 'data/data-wf-post-columns.php' );
19
- $user_columns_name = ! empty( $_POST['columns_name'] ) ? $_POST['columns_name'] : $csv_columns;
20
- $product_taxonomies = get_object_taxonomies( 'product', 'name' );
21
- $export_columns = ! empty( $_POST['columns'] ) ? $_POST['columns'] : '';
22
- $include_hidden_meta = ! empty( $_POST['include_hidden_meta'] ) ? true : false;
23
- $product_limit = ! empty( $_POST['product_limit'] ) ? sanitize_text_field( $_POST['product_limit'] ) : '';
24
- $exclude_hidden_meta_columns = include( 'data/data-wf-hidden-meta-columns.php' );
25
-
26
- if ( $limit > $export_limit )
27
- $limit = $export_limit;
28
-
29
- $wpdb->hide_errors();
30
- @set_time_limit(0);
31
- if ( function_exists( 'apache_setenv' ) )
32
- @apache_setenv( 'no-gzip', 1 );
33
- @ini_set('zlib.output_compression', 0);
34
- @ob_clean();
35
-
36
-
37
- header( 'Content-Type: text/csv; charset=UTF-8' );
38
- header( 'Content-Disposition: attachment; filename=woocommerce-product-export.csv' );
39
- header( 'Pragma: no-cache' );
40
- header( 'Expires: 0' );
41
-
42
- $fp = fopen('php://output', 'w');
43
-
44
-
45
- // Headers
46
- $all_meta_keys = self::get_all_metakeys( 'product' );
47
- $found_attributes = self::get_all_product_attributes( 'product' );
48
-
49
- // Loop products and load meta data
50
- $found_product_meta = array();
51
- // Some of the values may not be usable (e.g. arrays of arrays) but the worse
52
- // that can happen is we get an empty column.
53
- foreach ( $all_meta_keys as $meta ) {
54
- if ( ! $meta ) continue;
55
- if ( ! $include_hidden_meta && ! in_array( $meta, array_keys( $csv_columns ) ) && substr( (string)$meta, 0, 1 ) == '_' )
56
- continue;
57
- if ( $include_hidden_meta && ( in_array( $meta, $exclude_hidden_meta_columns ) || in_array( $meta, array_keys( $csv_columns ) ) ) )
58
- continue;
59
- $found_product_meta[] = $meta;
60
- }
61
-
62
- $found_product_meta = array_diff( $found_product_meta, array_keys( $csv_columns ) );
63
-
64
- // Variable to hold the CSV data we're exporting
65
- $row = array();
66
-
67
- // Export header rows
68
- foreach ( $csv_columns as $column => $value ) {
69
-
70
- $temp_head = esc_attr( $user_columns_name[$column] );
71
- if (strpos($temp_head, 'yoast') === false) {
72
- $temp_head = ltrim($temp_head, '_');
73
- }
74
- if ( ! $export_columns || in_array( $column, $export_columns ) ) $row[] = $temp_head;
75
- }
76
-
77
- // Handle special fields like taxonomies
78
- if ( ! $export_columns || in_array( 'images', $export_columns ) ) {
79
- $row[] = 'images';
80
- }
81
-
82
- if ( ! $export_columns || in_array( 'file_paths', $export_columns ) ) {
83
- if ( function_exists( 'wc_get_filename_from_url' ) ) {
84
- $row[] = 'downloadable_files';
85
- } else {
86
- $row[] = 'file_paths';
87
- }
88
- }
89
-
90
- if ( ! $export_columns || in_array( 'taxonomies', $export_columns ) ) {
91
- foreach ( $product_taxonomies as $taxonomy ) {
92
- if ( strstr( $taxonomy->name, 'pa_' ) ) continue; // Skip attributes
93
-
94
- $row[] = 'tax:' . self::format_data( $taxonomy->name );
95
- }
96
- }
97
-
98
- if ( ! $export_columns || in_array( 'meta', $export_columns ) ) {
99
- foreach ( $found_product_meta as $product_meta ) {
100
- $row[] = 'meta:' . self::format_data( $product_meta );
101
- }
102
- }
103
-
104
- if ( ! $export_columns || in_array( 'attributes', $export_columns ) ) {
105
- foreach ( $found_attributes as $attribute ) {
106
- $row[] = 'attribute:' . self::format_data( $attribute );
107
- $row[] = 'attribute_data:' . self::format_data( $attribute );
108
- $row[] = 'attribute_default:' . self::format_data( $attribute );
109
- }
110
- }
111
-
112
-
113
-
114
- // WF: Adding product permalink.
115
- if ( ! $export_columns || in_array( 'product_page_url', $export_columns ) ) {
116
- $row[] = 'Product Page URL';
117
- }
118
-
119
- $row = array_map( 'WF_ProdImpExpCsv_Exporter::wrap_column', $row );
120
- fwrite( $fp, implode( ',', $row ) . "\n" );
121
- unset( $row );
122
-
123
- while ( $export_count < $export_limit ) {
124
-
125
- $product_args = apply_filters( 'woocommerce_csv_product_export_args', array(
126
- 'numberposts' => $limit,
127
- 'post_status' => array( 'publish', 'pending', 'private', 'draft' ),
128
- 'post_type' => array('product'),
129
- 'orderby' => 'ID',
130
- 'suppress_filters' => false,
131
- 'order' => 'ASC',
132
- 'offset' => $current_offset
133
- ) );
134
-
135
-
136
- if ( $product_limit ) {
137
- $parent_ids = array_map( 'intval', explode( ',', $product_limit ) );
138
- $child_ids = $wpdb->get_col( "SELECT ID FROM $wpdb->posts WHERE post_parent IN (" . implode( ',', $parent_ids ) . ");" );
139
- $product_args['post__in'] = $child_ids;
140
- }
141
-
142
- $products = get_posts( $product_args );
143
- if ( ! $products || is_wp_error( $products ) )
144
- break;
145
-
146
- // Loop products
147
- foreach ( $products as $product ) {
148
- if($product->post_parent == 0) $product->post_parent = '';
149
- $row = array();
150
-
151
- // Pre-process data
152
- $meta_data = get_post_custom( $product->ID );
153
-
154
- $product->meta = new stdClass;
155
- $product->attributes = new stdClass;
156
-
157
- // Meta data
158
- foreach ( $meta_data as $meta => $value ) {
159
- if ( ! $meta ) {
160
- continue;
161
- }
162
- if ( ! $include_hidden_meta && ! in_array( $meta, array_keys( $csv_columns ) ) && substr( $meta, 0, 1 ) == '_' ) {
163
- continue;
164
- }
165
- if ( $include_hidden_meta && in_array( $meta, $exclude_hidden_meta_columns ) ) {
166
- continue;
167
- }
168
-
169
- $meta_value = maybe_unserialize( maybe_unserialize( $value[0] ) );
170
-
171
- if ( is_array( $meta_value ) ) {
172
- $meta_value = json_encode( $meta_value );
173
- }
174
-
175
- $product->meta->$meta = self::format_export_meta( $meta_value, $meta );
176
- }
177
-
178
- // Product attributes
179
- if ( isset( $meta_data['_product_attributes'][0] ) ) {
180
-
181
- $attributes = maybe_unserialize( maybe_unserialize( $meta_data['_product_attributes'][0] ) );
182
-
183
- if ( ! empty( $attributes ) && is_array( $attributes ) ) {
184
- foreach ( $attributes as $key => $attribute ) {
185
- if ( ! $key ) {
186
- continue;
187
- }
188
-
189
- if ( $attribute['is_taxonomy'] == 1 ) {
190
- $terms = wp_get_post_terms( $product->ID, $key, array("fields" => "names") );
191
- if ( ! is_wp_error( $terms ) ) {
192
- $attribute_value = implode( '|', $terms );
193
- } else {
194
- $attribute_value = '';
195
- }
196
- } else {
197
- if ( empty( $attribute['name'] ) ) {
198
- continue;
199
- }
200
- $key = $attribute['name'];
201
- $attribute_value = $attribute['value'];
202
- }
203
-
204
- if ( ! isset( $attribute['position'] ) ) {
205
- $attribute['position'] = 0;
206
- }
207
- if ( ! isset( $attribute['is_visible'] ) ) {
208
- $attribute['is_visible'] = 0;
209
- }
210
- if ( ! isset( $attribute['is_variation'] ) ) {
211
- $attribute['is_variation'] = 0;
212
- }
213
-
214
- $attribute_data = $attribute['position'] . '|' . $attribute['is_visible'] . '|' . $attribute['is_variation'];
215
- $_default_attributes = isset( $meta_data['_default_attributes'][0] ) ? maybe_unserialize( maybe_unserialize( $meta_data['_default_attributes'][0] ) ) : '';
216
-
217
- if ( is_array( $_default_attributes ) ) {
218
- $_default_attribute = isset( $_default_attributes[ $key ] ) ? $_default_attributes[ $key ] : '';
219
- } else {
220
- $_default_attribute = '';
221
- }
222
-
223
- $product->attributes->$key = array(
224
- 'value' => $attribute_value,
225
- 'data' => $attribute_data,
226
- 'default' => $_default_attribute
227
- );
228
- }
229
- }
230
- }
231
-
232
- // GPF
233
- if ( isset( $meta_data['_woocommerce_gpf_data'][0] ) ) {
234
- $product->gpf_data = $meta_data['_woocommerce_gpf_data'][0];
235
- }
236
-
237
- // Get column values
238
- foreach ( $csv_columns as $column => $value ) {
239
- if ( ! $export_columns || in_array( $column, $export_columns ) ) {
240
-
241
- if ($column == '_regular_price' && empty( $product->meta->$column ) ) {
242
- $column = '_price';
243
- }
244
-
245
- if ( isset( $product->meta->$column ) ) {
246
- $row[] = self::format_data( $product->meta->$column );
247
- } elseif ( isset( $product->$column ) && ! is_array( $product->$column ) ) {
248
- if ( $column === 'post_title' ) {
249
- $row[] = sanitize_text_field( $product->$column );
250
- } else {
251
- $row[] = self::format_data( $product->$column );
252
- }
253
- } else {
254
- $row[] = '';
255
- }
256
- }
257
- }
258
-
259
- // Export images/gallery
260
- if ( ! $export_columns || in_array( 'images', $export_columns ) ) {
261
-
262
- $image_file_names = array();
263
-
264
- // Featured image
265
- if ( ( $featured_image_id = get_post_thumbnail_id( $product->ID ) ) && ( $image = wp_get_attachment_image_src( $featured_image_id, 'full' ) ) ) {
266
- $image_file_names[] = current( $image );
267
- }
268
-
269
- // Images
270
- $images = isset( $meta_data['_product_image_gallery'][0] ) ? explode( ',', maybe_unserialize( maybe_unserialize( $meta_data['_product_image_gallery'][0] ) ) ) : false;
271
- $results = array();
272
-
273
- if ( $images ) {
274
- foreach ( $images as $image_id ) {
275
- if ( $featured_image_id == $image_id ) {
276
- continue;
277
- }
278
- $image = wp_get_attachment_image_src( $image_id, 'full' );
279
- if ( $image ) {
280
- $image_file_names[] = current( $image );
281
- }
282
- }
283
- }
284
-
285
- $row[] = implode( ' | ', $image_file_names );
286
-
287
- }
288
-
289
- // Downloadable files
290
- if ( ! $export_columns || in_array( 'file_paths', $export_columns ) ) {
291
- if ( ! function_exists( 'wc_get_filename_from_url' ) ) {
292
- $file_paths = maybe_unserialize( maybe_unserialize( $meta_data['_file_paths'][0] ) );
293
- $file_paths_to_export = array();
294
-
295
- if ( $file_paths ) {
296
- foreach ( $file_paths as $file_path ) {
297
- $file_paths_to_export[] = $file_path;
298
- }
299
- }
300
-
301
- $file_paths_to_export = implode( ' | ', $file_paths_to_export );
302
- $row[] = self::format_data( $file_paths_to_export );
303
- } elseif ( isset( $meta_data['_downloadable_files'][0] ) ) {
304
- $file_paths = maybe_unserialize( maybe_unserialize( $meta_data['_downloadable_files'][0] ) );
305
- $file_paths_to_export = array();
306
-
307
- if ( $file_paths ) {
308
- foreach ( $file_paths as $file_path ) {
309
- $file_paths_to_export[] = ( ! empty( $file_path['name'] ) ? $file_path['name'] : wc_get_filename_from_url( $file_path['file'] ) ) . '::' . $file_path['file'];
310
- }
311
- }
312
- $file_paths_to_export = implode( ' | ', $file_paths_to_export );
313
- $row[] = self::format_data( $file_paths_to_export );
314
- } else {
315
- $row[] = '';
316
- }
317
- }
318
-
319
- // Export taxonomies
320
- if ( ! $export_columns || in_array( 'taxonomies', $export_columns ) ) {
321
- foreach ( $product_taxonomies as $taxonomy ) {
322
- if ( strstr( $taxonomy->name, 'pa_' ) ) continue; // Skip attributes
323
-
324
- if ( is_taxonomy_hierarchical( $taxonomy->name ) ) {
325
- $terms = wp_get_post_terms( $product->ID, $taxonomy->name, array( "fields" => "all" ) );
326
- $formatted_terms = array();
327
-
328
- foreach ( $terms as $term ) {
329
- $ancestors = array_reverse( get_ancestors( $term->term_id, $taxonomy->name ) );
330
- $formatted_term = array();
331
-
332
- foreach ( $ancestors as $ancestor )
333
- $formatted_term[] = get_term( $ancestor, $taxonomy->name )->name;
334
-
335
- $formatted_term[] = $term->name;
336
-
337
- $formatted_terms[] = implode( ' > ', $formatted_term );
338
- }
339
-
340
- $row[] = self::format_data( implode( '|', $formatted_terms ) );
341
- } else {
342
- $terms = wp_get_post_terms( $product->ID, $taxonomy->name, array( "fields" => "names" ) );
343
-
344
- $row[] = self::format_data( implode( '|', $terms ) );
345
- }
346
- }
347
- }
348
-
349
- // Export meta data
350
- if ( ! $export_columns || in_array( 'meta', $export_columns ) ) {
351
- foreach ( $found_product_meta as $product_meta ) {
352
- if ( isset( $product->meta->$product_meta ) ) {
353
- $row[] = self::format_data( $product->meta->$product_meta );
354
- } else {
355
- $row[] = '';
356
- }
357
- }
358
- }
359
-
360
- // Find and export attributes
361
- if ( ! $export_columns || in_array( 'attributes', $export_columns ) ) {
362
- foreach ( $found_attributes as $attribute ) {
363
- if ( isset( $product->attributes ) && isset( $product->attributes->$attribute ) ) {
364
- $values = $product->attributes->$attribute;
365
- $row[] = self::format_data( $values['value'] );
366
- $row[] = self::format_data( $values['data'] );
367
- $row[] = self::format_data( $values['default'] );
368
- } else {
369
- $row[] = '';
370
- $row[] = '';
371
- $row[] = '';
372
- }
373
- }
374
- }
375
-
376
- // Export GPF
377
- if ( function_exists( 'woocommerce_gpf_install' ) && ( ! $export_columns || in_array( 'gpf', $export_columns ) ) ) {
378
-
379
- $gpf_data = empty( $product->gpf_data ) ? '' : maybe_unserialize( $product->gpf_data );
380
-
381
- $row[] = empty( $gpf_data['availability'] ) ? '' : $gpf_data['availability'];
382
- $row[] = empty( $gpf_data['condition'] ) ? '' : $gpf_data['condition'];
383
- $row[] = empty( $gpf_data['brand'] ) ? '' : $gpf_data['brand'];
384
- $row[] = empty( $gpf_data['product_type'] ) ? '' : $gpf_data['product_type'];
385
- $row[] = empty( $gpf_data['google_product_category'] ) ? '' : $gpf_data['google_product_category'];
386
- $row[] = empty( $gpf_data['gtin'] ) ? '' : $gpf_data['gtin'];
387
- $row[] = empty( $gpf_data['mpn'] ) ? '' : $gpf_data['mpn'];
388
- $row[] = empty( $gpf_data['gender'] ) ? '' : $gpf_data['gender'];
389
- $row[] = empty( $gpf_data['age_group'] ) ? '' : $gpf_data['age_group'];
390
- $row[] = empty( $gpf_data['color'] ) ? '' : $gpf_data['color'];
391
- $row[] = empty( $gpf_data['size'] ) ? '' : $gpf_data['size'];
392
- $row[] = empty( $gpf_data['adwords_grouping'] ) ? '' : $gpf_data['adwords_grouping'];
393
- $row[] = empty( $gpf_data['adwords_labels'] ) ? '' : $gpf_data['adwords_labels'];
394
- }
395
-
396
- // WF: Adding product permalink.
397
- if ( ! $export_columns || in_array( 'product_page_url', $export_columns ) ) {
398
- $product_page_url = '';
399
- if ( $product->ID ) {
400
- $product_page_url = get_permalink( $product->ID );
401
- }
402
- if ( $product->post_parent ) {
403
- $product_page_url = get_permalink( $product->post_parent );
404
- }
405
-
406
- $row[] = $product_page_url;
407
- }
408
-
409
- // Add to csv
410
- $row = array_map( 'WF_ProdImpExpCsv_Exporter::wrap_column', $row );
411
- fwrite( $fp, implode( ',', $row ) . "\n" );
412
- unset( $row );
413
-
414
- }
415
- $current_offset += $limit;
416
- $export_count += $limit;
417
- unset( $products );
418
- }
419
-
420
- fclose( $fp );
421
- exit;
422
- }
423
-
424
- /**
425
- * Format the data if required
426
- * @param string $meta_value
427
- * @param string $meta name of meta key
428
- * @return string
429
- */
430
- public static function format_export_meta( $meta_value, $meta ) {
431
- switch ( $meta ) {
432
- case '_sale_price_dates_from' :
433
- case '_sale_price_dates_to' :
434
- return $meta_value ? date( 'Y-m-d', $meta_value ) : '';
435
- break;
436
- case '_upsell_ids' :
437
- case '_crosssell_ids' :
438
- return implode( '|', array_filter( (array) json_decode( $meta_value ) ) );
439
- break;
440
- default :
441
- return $meta_value;
442
- break;
443
- }
444
- }
445
-
446
- public static function format_data( $data ) {
447
- $enc = mb_detect_encoding( $data, 'UTF-8, ISO-8859-1', true );
448
- $data = ( $enc == 'UTF-8' ) ? $data : utf8_encode( $data );
449
- return $data;
450
- }
451
-
452
- /**
453
- * Wrap a column in quotes for the CSV
454
- * @param string data to wrap
455
- * @return string wrapped data
456
- */
457
- public static function wrap_column( $data ) {
458
- return '"' . str_replace( '"', '""', $data ) . '"';
459
- }
460
-
461
- /**
462
- * Get a list of all the meta keys for a post type. This includes all public, private,
463
- * used, no-longer used etc. They will be sorted once fetched.
464
- */
465
- public static function get_all_metakeys( $post_type = 'product' ) {
466
- global $wpdb;
467
-
468
- $meta = $wpdb->get_col( $wpdb->prepare(
469
- "SELECT DISTINCT pm.meta_key
470
- FROM {$wpdb->postmeta} AS pm
471
- LEFT JOIN {$wpdb->posts} AS p ON p.ID = pm.post_id
472
- WHERE p.post_type = %s
473
- AND p.post_status IN ( 'publish', 'pending', 'private', 'draft' )",
474
- $post_type
475
- ) );
476
-
477
- sort( $meta );
478
-
479
- return $meta;
480
- }
481
-
482
- /**
483
- * Get a list of all the product attributes for a post type.
484
- * These require a bit more digging into the values.
485
- */
486
- public static function get_all_product_attributes( $post_type = 'product' ) {
487
- global $wpdb;
488
-
489
- $results = $wpdb->get_col( $wpdb->prepare(
490
- "SELECT DISTINCT pm.meta_value
491
- FROM {$wpdb->postmeta} AS pm
492
- LEFT JOIN {$wpdb->posts} AS p ON p.ID = pm.post_id
493
- WHERE p.post_type = %s
494
- AND p.post_status IN ( 'publish', 'pending', 'private', 'draft' )
495
- AND pm.meta_key = '_product_attributes'",
496
- $post_type
497
- ) );
498
-
499
- // Go through each result, and look at the attribute keys within them.
500
- $result = array();
501
-
502
- if ( ! empty( $results ) ) {
503
- foreach( $results as $_product_attributes ) {
504
- $attributes = maybe_unserialize( maybe_unserialize( $_product_attributes ) );
505
- if ( ! empty( $attributes ) && is_array( $attributes ) ) {
506
- foreach( $attributes as $key => $attribute ) {
507
- if ( ! $key ) {
508
- continue;
509
- }
510
- if ( ! strstr( $key, 'pa_' ) ) {
511
- if ( empty( $attribute['name'] ) ) {
512
- continue;
513
- }
514
- $key = $attribute['name'];
515
- }
516
-
517
- $result[ $key ] = $key;
518
- }
519
- }
520
- }
521
- }
522
-
523
- sort( $result );
524
-
525
- return $result;
526
- }
527
- }
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ exit;
4
+ }
5
+
6
+ class WF_ProdImpExpCsv_Exporter {
7
+
8
+ /**
9
+ * Product Exporter Tool
10
+ */
11
+ public static function do_export( $post_type = 'product' ) {
12
+ global $wpdb;
13
+
14
+ $export_limit = ! empty( $_POST['limit'] ) ? intval( $_POST['limit'] ) : 999999999;
15
+ $export_count = 0;
16
+ $limit = 100;
17
+ $current_offset = ! empty( $_POST['offset'] ) ? intval( $_POST['offset'] ) : 0;
18
+ $csv_columns = include( 'data/data-wf-post-columns.php' );
19
+ $user_columns_name = ! empty( $_POST['columns_name'] ) ? $_POST['columns_name'] : $csv_columns;
20
+ $product_taxonomies = get_object_taxonomies( 'product', 'name' );
21
+ $export_columns = ! empty( $_POST['columns'] ) ? $_POST['columns'] : '';
22
+ $include_hidden_meta = ! empty( $_POST['include_hidden_meta'] ) ? true : false;
23
+ $product_limit = ! empty( $_POST['product_limit'] ) ? sanitize_text_field( $_POST['product_limit'] ) : '';
24
+ $exclude_hidden_meta_columns = include( 'data/data-wf-hidden-meta-columns.php' );
25
+
26
+ if ( $limit > $export_limit )
27
+ $limit = $export_limit;
28
+
29
+ $wpdb->hide_errors();
30
+ @set_time_limit(0);
31
+ if ( function_exists( 'apache_setenv' ) )
32
+ @apache_setenv( 'no-gzip', 1 );
33
+ @ini_set('zlib.output_compression', 0);
34
+ @ob_clean();
35
+
36
+
37
+ header( 'Content-Type: text/csv; charset=UTF-8' );
38
+ header( 'Content-Disposition: attachment; filename=woocommerce-product-export.csv' );
39
+ header( 'Pragma: no-cache' );
40
+ header( 'Expires: 0' );
41
+
42
+ $fp = fopen('php://output', 'w');
43
+
44
+
45
+ // Headers
46
+ $all_meta_keys = self::get_all_metakeys( 'product' );
47
+ $found_attributes = self::get_all_product_attributes( 'product' );
48
+
49
+ // Loop products and load meta data
50
+ $found_product_meta = array();
51
+ // Some of the values may not be usable (e.g. arrays of arrays) but the worse
52
+ // that can happen is we get an empty column.
53
+ foreach ( $all_meta_keys as $meta ) {
54
+ if ( ! $meta ) continue;
55
+ if ( ! $include_hidden_meta && ! in_array( $meta, array_keys( $csv_columns ) ) && substr( (string)$meta, 0, 1 ) == '_' )
56
+ continue;
57
+ if ( $include_hidden_meta && ( in_array( $meta, $exclude_hidden_meta_columns ) || in_array( $meta, array_keys( $csv_columns ) ) ) )
58
+ continue;
59
+ $found_product_meta[] = $meta;
60
+ }
61
+
62
+ $found_product_meta = array_diff( $found_product_meta, array_keys( $csv_columns ) );
63
+
64
+ // Variable to hold the CSV data we're exporting
65
+ $row = array();
66
+
67
+ // Export header rows
68
+ foreach ( $csv_columns as $column => $value ) {
69
+
70
+ $temp_head = esc_attr( $user_columns_name[$column] );
71
+ if (strpos($temp_head, 'yoast') === false) {
72
+ $temp_head = ltrim($temp_head, '_');
73
+ }
74
+ if ( ! $export_columns || in_array( $column, $export_columns ) ) $row[] = $temp_head;
75
+ }
76
+
77
+ // Handle special fields like taxonomies
78
+ if ( ! $export_columns || in_array( 'images', $export_columns ) ) {
79
+ $row[] = 'images';
80
+ }
81
+
82
+ if ( ! $export_columns || in_array( 'file_paths', $export_columns ) ) {
83
+ if ( function_exists( 'wc_get_filename_from_url' ) ) {
84
+ $row[] = 'downloadable_files';
85
+ } else {
86
+ $row[] = 'file_paths';
87
+ }
88
+ }
89
+
90
+ if ( ! $export_columns || in_array( 'taxonomies', $export_columns ) ) {
91
+ foreach ( $product_taxonomies as $taxonomy ) {
92
+ if ( strstr( $taxonomy->name, 'pa_' ) ) continue; // Skip attributes
93
+
94
+ $row[] = 'tax:' . self::format_data( $taxonomy->name );
95
+ }
96
+ }
97
+
98
+ if ( ! $export_columns || in_array( 'meta', $export_columns ) ) {
99
+ foreach ( $found_product_meta as $product_meta ) {
100
+ $row[] = 'meta:' . self::format_data( $product_meta );
101
+ }
102
+ }
103
+
104
+ if ( ! $export_columns || in_array( 'attributes', $export_columns ) ) {
105
+ foreach ( $found_attributes as $attribute ) {
106
+ $row[] = 'attribute:' . self::format_data( $attribute );
107
+ $row[] = 'attribute_data:' . self::format_data( $attribute );
108
+ $row[] = 'attribute_default:' . self::format_data( $attribute );
109
+ }
110
+ }
111
+
112
+
113
+
114
+ // WF: Adding product permalink.
115
+ if ( ! $export_columns || in_array( 'product_page_url', $export_columns ) ) {
116
+ $row[] = 'Product Page URL';
117
+ }
118
+
119
+ $row = array_map( 'WF_ProdImpExpCsv_Exporter::wrap_column', $row );
120
+ fwrite( $fp, implode( ',', $row ) . "\n" );
121
+ unset( $row );
122
+
123
+ while ( $export_count < $export_limit ) {
124
+
125
+ $product_args = apply_filters( 'woocommerce_csv_product_export_args', array(
126
+ 'numberposts' => $limit,
127
+ 'post_status' => array( 'publish', 'pending', 'private', 'draft' ),
128
+ 'post_type' => array('product'),
129
+ 'orderby' => 'ID',
130
+ 'suppress_filters' => false,
131
+ 'order' => 'ASC',
132
+ 'offset' => $current_offset
133
+ ) );
134
+
135
+
136
+ if ( $product_limit ) {
137
+ $parent_ids = array_map( 'intval', explode( ',', $product_limit ) );
138
+ $child_ids = $wpdb->get_col( "SELECT ID FROM $wpdb->posts WHERE post_parent IN (" . implode( ',', $parent_ids ) . ");" );
139
+ $product_args['post__in'] = $child_ids;
140
+ }
141
+
142
+ $products = get_posts( $product_args );
143
+ if ( ! $products || is_wp_error( $products ) )
144
+ break;
145
+
146
+ // Loop products
147
+ foreach ( $products as $product ) {
148
+ if($product->post_parent == 0) $product->post_parent = '';
149
+ $row = array();
150
+
151
+ // Pre-process data
152
+ $meta_data = get_post_custom( $product->ID );
153
+
154
+ $product->meta = new stdClass;
155
+ $product->attributes = new stdClass;
156
+
157
+ // Meta data
158
+ foreach ( $meta_data as $meta => $value ) {
159
+ if ( ! $meta ) {
160
+ continue;
161
+ }
162
+ if ( ! $include_hidden_meta && ! in_array( $meta, array_keys( $csv_columns ) ) && substr( $meta, 0, 1 ) == '_' ) {
163
+ continue;
164
+ }
165
+ if ( $include_hidden_meta && in_array( $meta, $exclude_hidden_meta_columns ) ) {
166
+ continue;
167
+ }
168
+
169
+ $meta_value = maybe_unserialize( maybe_unserialize( $value[0] ) );
170
+
171
+ if ( is_array( $meta_value ) ) {
172
+ $meta_value = json_encode( $meta_value );
173
+ }
174
+
175
+ $product->meta->$meta = self::format_export_meta( $meta_value, $meta );
176
+ }
177
+
178
+ // Product attributes
179
+ if ( isset( $meta_data['_product_attributes'][0] ) ) {
180
+
181
+ $attributes = maybe_unserialize( maybe_unserialize( $meta_data['_product_attributes'][0] ) );
182
+
183
+ if ( ! empty( $attributes ) && is_array( $attributes ) ) {
184
+ foreach ( $attributes as $key => $attribute ) {
185
+ if ( ! $key ) {
186
+ continue;
187
+ }
188
+
189
+ if ( $attribute['is_taxonomy'] == 1 ) {
190
+ $terms = wp_get_post_terms( $product->ID, $key, array("fields" => "names") );
191
+ if ( ! is_wp_error( $terms ) ) {
192
+ $attribute_value = implode( '|', $terms );
193
+ } else {
194
+ $attribute_value = '';
195
+ }
196
+ } else {
197
+ if ( empty( $attribute['name'] ) ) {
198
+ continue;
199
+ }
200
+ $key = $attribute['name'];
201
+ $attribute_value = $attribute['value'];
202
+ }
203
+
204
+ if ( ! isset( $attribute['position'] ) ) {
205
+ $attribute['position'] = 0;
206
+ }
207
+ if ( ! isset( $attribute['is_visible'] ) ) {
208
+ $attribute['is_visible'] = 0;
209
+ }
210
+ if ( ! isset( $attribute['is_variation'] ) ) {
211
+ $attribute['is_variation'] = 0;
212
+ }
213
+
214
+ $attribute_data = $attribute['position'] . '|' . $attribute['is_visible'] . '|' . $attribute['is_variation'];
215
+ $_default_attributes = isset( $meta_data['_default_attributes'][0] ) ? maybe_unserialize( maybe_unserialize( $meta_data['_default_attributes'][0] ) ) : '';
216
+
217
+ if ( is_array( $_default_attributes ) ) {
218
+ $_default_attribute = isset( $_default_attributes[ $key ] ) ? $_default_attributes[ $key ] : '';
219
+ } else {
220
+ $_default_attribute = '';
221
+ }
222
+
223
+ $product->attributes->$key = array(
224
+ 'value' => $attribute_value,
225
+ 'data' => $attribute_data,
226
+ 'default' => $_default_attribute
227
+ );
228
+ }
229
+ }
230
+ }
231
+
232
+ // GPF
233
+ if ( isset( $meta_data['_woocommerce_gpf_data'][0] ) ) {
234
+ $product->gpf_data = $meta_data['_woocommerce_gpf_data'][0];
235
+ }
236
+
237
+ // Get column values
238
+ foreach ( $csv_columns as $column => $value ) {
239
+ if ( ! $export_columns || in_array( $column, $export_columns ) ) {
240
+
241
+ if ($column == '_regular_price' && empty( $product->meta->$column ) ) {
242
+ $column = '_price';
243
+ }
244
+
245
+ if ( isset( $product->meta->$column ) ) {
246
+ $row[] = self::format_data( $product->meta->$column );
247
+ } elseif ( isset( $product->$column ) && ! is_array( $product->$column ) ) {
248
+ if ( $column === 'post_title' ) {
249
+ $row[] = sanitize_text_field( $product->$column );
250
+ } else {
251
+ $row[] = self::format_data( $product->$column );
252
+ }
253
+ } else {
254
+ $row[] = '';
255
+ }
256
+ }
257
+ }
258
+
259
+ // Export images/gallery
260
+ if ( ! $export_columns || in_array( 'images', $export_columns ) ) {
261
+
262
+ $image_file_names = array();
263
+
264
+ // Featured image
265
+ if ( ( $featured_image_id = get_post_thumbnail_id( $product->ID ) ) && ( $image = wp_get_attachment_image_src( $featured_image_id, 'full' ) ) ) {
266
+ $image_file_names[] = current( $image );
267
+ }
268
+
269
+ // Images
270
+ $images = isset( $meta_data['_product_image_gallery'][0] ) ? explode( ',', maybe_unserialize( maybe_unserialize( $meta_data['_product_image_gallery'][0] ) ) ) : false;
271
+ $results = array();
272
+
273
+ if ( $images ) {
274
+ foreach ( $images as $image_id ) {
275
+ if ( $featured_image_id == $image_id ) {
276
+ continue;
277
+ }
278
+ $image = wp_get_attachment_image_src( $image_id, 'full' );
279
+ if ( $image ) {
280
+ $image_file_names[] = current( $image );
281
+ }
282
+ }
283
+ }
284
+
285
+ $row[] = implode( ' | ', $image_file_names );
286
+
287
+ }
288
+
289
+ // Downloadable files
290
+ if ( ! $export_columns || in_array( 'file_paths', $export_columns ) ) {
291
+ if ( ! function_exists( 'wc_get_filename_from_url' ) ) {
292
+ $file_paths = maybe_unserialize( maybe_unserialize( $meta_data['_file_paths'][0] ) );
293
+ $file_paths_to_export = array();
294
+
295
+ if ( $file_paths ) {
296
+ foreach ( $file_paths as $file_path ) {
297
+ $file_paths_to_export[] = $file_path;
298
+ }
299
+ }
300
+
301
+ $file_paths_to_export = implode( ' | ', $file_paths_to_export );
302
+ $row[] = self::format_data( $file_paths_to_export );
303
+ } elseif ( isset( $meta_data['_downloadable_files'][0] ) ) {
304
+ $file_paths = maybe_unserialize( maybe_unserialize( $meta_data['_downloadable_files'][0] ) );
305
+ $file_paths_to_export = array();
306
+
307
+ if ( $file_paths ) {
308
+ foreach ( $file_paths as $file_path ) {
309
+ $file_paths_to_export[] = ( ! empty( $file_path['name'] ) ? $file_path['name'] : wc_get_filename_from_url( $file_path['file'] ) ) . '::' . $file_path['file'];
310
+ }
311
+ }
312
+ $file_paths_to_export = implode( ' | ', $file_paths_to_export );
313
+ $row[] = self::format_data( $file_paths_to_export );
314
+ } else {
315
+ $row[] = '';
316
+ }
317
+ }
318
+
319
+ // Export taxonomies
320
+ if ( ! $export_columns || in_array( 'taxonomies', $export_columns ) ) {
321
+ foreach ( $product_taxonomies as $taxonomy ) {
322
+ if ( strstr( $taxonomy->name, 'pa_' ) ) continue; // Skip attributes
323
+
324
+ if ( is_taxonomy_hierarchical( $taxonomy->name ) ) {
325
+ $terms = wp_get_post_terms( $product->ID, $taxonomy->name, array( "fields" => "all" ) );
326
+ $formatted_terms = array();
327
+
328
+ foreach ( $terms as $term ) {
329
+ $ancestors = array_reverse( get_ancestors( $term->term_id, $taxonomy->name ) );
330
+ $formatted_term = array();
331
+
332
+ foreach ( $ancestors as $ancestor )
333
+ $formatted_term[] = get_term( $ancestor, $taxonomy->name )->name;
334
+
335
+ $formatted_term[] = $term->name;
336
+
337
+ $formatted_terms[] = implode( ' > ', $formatted_term );
338
+ }
339
+
340
+ $row[] = self::format_data( implode( '|', $formatted_terms ) );
341
+ } else {
342
+ $terms = wp_get_post_terms( $product->ID, $taxonomy->name, array( "fields" => "names" ) );
343
+
344
+ $row[] = self::format_data( implode( '|', $terms ) );
345
+ }
346
+ }
347
+ }
348
+
349
+ // Export meta data
350
+ if ( ! $export_columns || in_array( 'meta', $export_columns ) ) {
351
+ foreach ( $found_product_meta as $product_meta ) {
352
+ if ( isset( $product->meta->$product_meta ) ) {
353
+ $row[] = self::format_data( $product->meta->$product_meta );
354
+ } else {
355
+ $row[] = '';
356
+ }
357
+ }
358
+ }
359
+
360
+ // Find and export attributes
361
+ if ( ! $export_columns || in_array( 'attributes', $export_columns ) ) {
362
+ foreach ( $found_attributes as $attribute ) {
363
+ if ( isset( $product->attributes ) && isset( $product->attributes->$attribute ) ) {
364
+ $values = $product->attributes->$attribute;
365
+ $row[] = self::format_data( $values['value'] );
366
+ $row[] = self::format_data( $values['data'] );
367
+ $row[] = self::format_data( $values['default'] );
368
+ } else {
369
+ $row[] = '';
370
+ $row[] = '';
371
+ $row[] = '';
372
+ }
373
+ }
374
+ }
375
+
376
+ // Export GPF
377
+ if ( function_exists( 'woocommerce_gpf_install' ) && ( ! $export_columns || in_array( 'gpf', $export_columns ) ) ) {
378
+
379
+ $gpf_data = empty( $product->gpf_data ) ? '' : maybe_unserialize( $product->gpf_data );
380
+
381
+ $row[] = empty( $gpf_data['availability'] ) ? '' : $gpf_data['availability'];
382
+ $row[] = empty( $gpf_data['condition'] ) ? '' : $gpf_data['condition'];
383
+ $row[] = empty( $gpf_data['brand'] ) ? '' : $gpf_data['brand'];
384
+ $row[] = empty( $gpf_data['product_type'] ) ? '' : $gpf_data['product_type'];
385
+ $row[] = empty( $gpf_data['google_product_category'] ) ? '' : $gpf_data['google_product_category'];
386
+ $row[] = empty( $gpf_data['gtin'] ) ? '' : $gpf_data['gtin'];
387
+ $row[] = empty( $gpf_data['mpn'] ) ? '' : $gpf_data['mpn'];
388
+ $row[] = empty( $gpf_data['gender'] ) ? '' : $gpf_data['gender'];
389
+ $row[] = empty( $gpf_data['age_group'] ) ? '' : $gpf_data['age_group'];
390
+ $row[] = empty( $gpf_data['color'] ) ? '' : $gpf_data['color'];
391
+ $row[] = empty( $gpf_data['size'] ) ? '' : $gpf_data['size'];
392
+ $row[] = empty( $gpf_data['adwords_grouping'] ) ? '' : $gpf_data['adwords_grouping'];
393
+ $row[] = empty( $gpf_data['adwords_labels'] ) ? '' : $gpf_data['adwords_labels'];
394
+ }
395
+
396
+ // WF: Adding product permalink.
397
+ if ( ! $export_columns || in_array( 'product_page_url', $export_columns ) ) {
398
+ $product_page_url = '';
399
+ if ( $product->ID ) {
400
+ $product_page_url = get_permalink( $product->ID );
401
+ }
402
+ if ( $product->post_parent ) {
403
+ $product_page_url = get_permalink( $product->post_parent );
404
+ }
405
+
406
+ $row[] = $product_page_url;
407
+ }
408
+
409
+ // Add to csv
410
+ $row = array_map( 'WF_ProdImpExpCsv_Exporter::wrap_column', $row );
411
+ fwrite( $fp, implode( ',', $row ) . "\n" );
412
+ unset( $row );
413
+
414
+ }
415
+ $current_offset += $limit;
416
+ $export_count += $limit;
417
+ unset( $products );
418
+ }
419
+
420
+ fclose( $fp );
421
+ exit;
422
+ }
423
+
424
+ /**
425
+ * Format the data if required
426
+ * @param string $meta_value
427
+ * @param string $meta name of meta key
428
+ * @return string
429
+ */
430
+ public static function format_export_meta( $meta_value, $meta ) {
431
+ switch ( $meta ) {
432
+ case '_sale_price_dates_from' :
433
+ case '_sale_price_dates_to' :
434
+ return $meta_value ? date( 'Y-m-d', $meta_value ) : '';
435
+ break;
436
+ case '_upsell_ids' :
437
+ case '_crosssell_ids' :
438
+ return implode( '|', array_filter( (array) json_decode( $meta_value ) ) );
439
+ break;
440
+ default :
441
+ return $meta_value;
442
+ break;
443
+ }
444
+ }
445
+
446
+ public static function format_data( $data ) {
447
+ $enc = mb_detect_encoding( $data, 'UTF-8, ISO-8859-1', true );
448
+ $data = ( $enc == 'UTF-8' ) ? $data : utf8_encode( $data );
449
+ return $data;
450
+ }
451
+
452
+ /**
453
+ * Wrap a column in quotes for the CSV
454
+ * @param string data to wrap
455
+ * @return string wrapped data
456
+ */
457
+ public static function wrap_column( $data ) {
458
+ return '"' . str_replace( '"', '""', $data ) . '"';
459
+ }
460
+
461
+ /**
462
+ * Get a list of all the meta keys for a post type. This includes all public, private,
463
+ * used, no-longer used etc. They will be sorted once fetched.
464
+ */
465
+ public static function get_all_metakeys( $post_type = 'product' ) {
466
+ global $wpdb;
467
+
468
+ $meta = $wpdb->get_col( $wpdb->prepare(
469
+ "SELECT DISTINCT pm.meta_key
470
+ FROM {$wpdb->postmeta} AS pm
471
+ LEFT JOIN {$wpdb->posts} AS p ON p.ID = pm.post_id
472
+ WHERE p.post_type = %s
473
+ AND p.post_status IN ( 'publish', 'pending', 'private', 'draft' )",
474
+ $post_type
475
+ ) );
476
+
477
+ sort( $meta );
478
+
479
+ return $meta;
480
+ }
481
+
482
+ /**
483
+ * Get a list of all the product attributes for a post type.
484
+ * These require a bit more digging into the values.
485
+ */
486
+ public static function get_all_product_attributes( $post_type = 'product' ) {
487
+ global $wpdb;
488
+
489
+ $results = $wpdb->get_col( $wpdb->prepare(
490
+ "SELECT DISTINCT pm.meta_value
491
+ FROM {$wpdb->postmeta} AS pm
492
+ LEFT JOIN {$wpdb->posts} AS p ON p.ID = pm.post_id
493
+ WHERE p.post_type = %s
494
+ AND p.post_status IN ( 'publish', 'pending', 'private', 'draft' )
495
+ AND pm.meta_key = '_product_attributes'",
496
+ $post_type
497
+ ) );
498
+
499
+ // Go through each result, and look at the attribute keys within them.
500
+ $result = array();
501
+
502
+ if ( ! empty( $results ) ) {
503
+ foreach( $results as $_product_attributes ) {
504
+ $attributes = maybe_unserialize( maybe_unserialize( $_product_attributes ) );
505
+ if ( ! empty( $attributes ) && is_array( $attributes ) ) {
506
+ foreach( $attributes as $key => $attribute ) {
507
+ if ( ! $key ) {
508
+ continue;
509
+ }
510
+ if ( ! strstr( $key, 'pa_' ) ) {
511
+ if ( empty( $attribute['name'] ) ) {
512
+ continue;
513
+ }
514
+ $key = $attribute['name'];
515
+ }
516
+
517
+ $result[ $key ] = $key;
518
+ }
519
+ }
520
+ }
521
+ }
522
+
523
+ sort( $result );
524
+
525
+ return $result;
526
+ }
527
+ }
includes/exporter/data/data-wf-hidden-meta-columns.php CHANGED
@@ -1,20 +1,20 @@
1
- <?php
2
-
3
- // Exclude columns handled specifically
4
- return array(
5
- '_product_attributes',
6
- '_file_paths',
7
- '_woocommerce_gpf_data',
8
- '_price',
9
- '_default_attributes',
10
- '_edit_last',
11
- '_edit_lock',
12
- '_wp_old_slug',
13
- '_product_image_gallery',
14
- '_max_variation_price',
15
- '_max_variation_regular_price',
16
- '_max_variation_sale_price',
17
- '_min_variation_price',
18
- '_min_variation_regular_price',
19
- '_min_variation_sale_price',
20
);
1
+ <?php
2
+
3
+ // Exclude columns handled specifically
4
+ return array(
5
+ '_product_attributes',
6
+ '_file_paths',
7
+ '_woocommerce_gpf_data',
8
+ '_price',
9
+ '_default_attributes',
10
+ '_edit_last',
11
+ '_edit_lock',
12
+ '_wp_old_slug',
13
+ '_product_image_gallery',
14
+ '_max_variation_price',
15
+ '_max_variation_regular_price',
16
+ '_max_variation_sale_price',
17
+ '_min_variation_price',
18
+ '_min_variation_regular_price',
19
+ '_min_variation_sale_price',
20
);
includes/exporter/data/data-wf-post-columns.php CHANGED
@@ -1,51 +1,51 @@
1
- <?php
2
- if ( ! defined( 'ABSPATH' ) ) {
3
- exit;
4
- }
5
-
6
- return apply_filters('woocommerce_csv_product_post_columns', array(
7
- 'post_title' => 'post_title',
8
- 'post_name' => 'post_name',
9
- 'ID' => 'ID',
10
- 'post_excerpt' => 'post_excerpt',
11
- 'post_content' => 'post_content',
12
- 'post_status' => 'post_status',
13
- 'menu_order' => 'menu_order',
14
- 'post_date' => 'post_date',
15
- 'post_author' => 'post_author',
16
- 'comment_status' => 'comment_status',
17
-
18
- // Meta
19
- '_sku' => 'sku',
20
- '_downloadable' => 'downloadable',
21
- '_virtual' => 'virtual',
22
- '_stock' => 'stock',
23
- '_regular_price' => 'regular_price',
24
- '_sale_price' => 'sale_price',
25
- '_weight' => 'weight',
26
- '_length' => 'length',
27
- '_width' => 'width',
28
- '_height' => 'height',
29
- '_tax_class' => 'tax_class',
30
-
31
- '_visibility' => 'visibility',
32
- '_stock_status' => 'stock_status',
33
- '_backorders' => 'backorders',
34
- '_manage_stock' => 'manage_stock',
35
- '_tax_status' => 'tax_status',
36
- '_upsell_ids' => 'upsell_ids',
37
- '_crosssell_ids' => 'crosssell_ids',
38
- '_featured' => 'featured',
39
-
40
- '_sale_price_dates_from' => 'sale_price_dates_from',
41
- '_sale_price_dates_to' => 'sale_price_dates_to',
42
-
43
- // Downloadable products
44
- '_download_limit' => 'download_limit',
45
- '_download_expiry' => 'download_expiry',
46
-
47
- // Virtual products
48
- '_product_url' => 'product_url',
49
- '_button_text' => 'button_text',
50
-
51
) );
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ exit;
4
+ }
5
+
6
+ return apply_filters('woocommerce_csv_product_post_columns', array(
7
+ 'post_title' => 'post_title',
8
+ 'post_name' => 'post_name',
9
+ 'ID' => 'ID',
10
+ 'post_excerpt' => 'post_excerpt',
11
+ 'post_content' => 'post_content',
12
+ 'post_status' => 'post_status',
13
+ 'menu_order' => 'menu_order',
14
+ 'post_date' => 'post_date',
15
+ 'post_author' => 'post_author',
16
+ 'comment_status' => 'comment_status',
17
+
18
+ // Meta
19
+ '_sku' => 'sku',
20
+ '_downloadable' => 'downloadable',
21
+ '_virtual' => 'virtual',
22
+ '_stock' => 'stock',
23
+ '_regular_price' => 'regular_price',
24
+ '_sale_price' => 'sale_price',
25
+ '_weight' => 'weight',
26
+ '_length' => 'length',
27
+ '_width' => 'width',
28
+ '_height' => 'height',
29
+ '_tax_class' => 'tax_class',
30
+
31
+ '_visibility' => 'visibility',
32
+ '_stock_status' => 'stock_status',
33
+ '_backorders' => 'backorders',
34
+ '_manage_stock' => 'manage_stock',
35
+ '_tax_status' => 'tax_status',
36
+ '_upsell_ids' => 'upsell_ids',
37
+ '_crosssell_ids' => 'crosssell_ids',
38
+ '_featured' => 'featured',
39
+
40
+ '_sale_price_dates_from' => 'sale_price_dates_from',
41
+ '_sale_price_dates_to' => 'sale_price_dates_to',
42
+
43
+ // Downloadable products
44
+ '_download_limit' => 'download_limit',
45
+ '_download_expiry' => 'download_expiry',
46
+
47
+ // Virtual products
48
+ '_product_url' => 'product_url',
49
+ '_button_text' => 'button_text',
50
+
51
) );
includes/importer/class-wf-csv-parser.php CHANGED
@@ -1,853 +1,853 @@
1
- <?php
2
- /**
3
- * WooCommerce CSV Importer class for managing parsing of CSV files.
4
- */
5
- class WF_CSV_Parser {
6
-
7
- var $row;
8
- var $post_type;
9
- var $reserved_fields; // Fields we map/handle (not custom fields)
10
- var $post_defaults; // Default post data
11
- var $postmeta_defaults; // default post meta
12
- var $postmeta_allowed; // post meta validation
13
- var $allowed_product_types; // Allowed product types
14
-
15
- /**
16
- * Constructor
17
- */
18
- public function __construct( $post_type = 'product' ) {
19
-
20
- $this->post_type = $post_type;
21
- $this->reserved_fields = include( 'data/data-wf-reserved-fields.php' );
22
- $this->post_defaults = include( 'data/data-wf-post-defaults.php' );
23
- $this->postmeta_defaults = include( 'data/data-wf-postmeta-defaults.php' );
24
- $this->postmeta_allowed = include( 'data/data-wf-postmeta-allowed.php' );
25
-
26
- $simple_term = get_term_by( 'slug', 'simple', 'product_type' );
27
- $variable_term = get_term_by( 'slug', 'variable', 'product_type' );
28
- $grouped_term = get_term_by( 'slug', 'grouped', 'product_type' );
29
- $external_term = get_term_by( 'slug', 'external', 'product_type' );
30
-
31
- $this->allowed_product_types = array(
32
- 'simple' => $simple_term->term_id,
33
- 'variable' => $variable_term->term_id,
34
- 'grouped' => $grouped_term->term_id,
35
- 'external' => $external_term->term_id
36
- );
37
-
38
- }
39
-
40
- /**
41
- * Format data from the csv file
42
- * @param string $data
43
- * @param string $enc
44
- * @return string
45
- */
46
- public function format_data_from_csv( $data, $enc ) {
47
- return ( $enc == 'UTF-8' ) ? $data : utf8_encode( $data );
48
- }
49
-
50
- /**
51
- * Parse the data
52
- * @param string $file [description]
53
- * @param string $delimiter [description]
54
- * @param array $mapping [description]
55
- * @param integer $start_pos [description]
56
- * @param integer $end_pos [description]
57
- * @return array
58
- */
59
- public function parse_data( $file, $delimiter, $mapping, $start_pos = 0, $end_pos = null, $eval_field ) {
60
- // Set locale
61
- $enc = mb_detect_encoding( $file, 'UTF-8, ISO-8859-1', true );
62
- if ( $enc )
63
- setlocale( LC_ALL, 'en_US.' . $enc );
64
- @ini_set( 'auto_detect_line_endings', true );
65
-
66
- $parsed_data = array();
67
- $raw_headers = array();
68
-
69
- // Put all CSV data into an associative array
70
- if ( ( $handle = fopen( $file, "r" ) ) !== FALSE ) {
71
-
72
- $header = fgetcsv( $handle, 0, $delimiter );
73
- if ( $start_pos != 0 )
74
- fseek( $handle, $start_pos );
75
-
76
- while ( ( $postmeta = fgetcsv( $handle, 0, $delimiter ) ) !== FALSE ) {
77
- $row = array();
78
-
79
- foreach ( $header as $key => $heading ) {
80
- // Heading is the lowercase version of the column name
81
- $s_heading = strtolower( $heading );
82
-
83
- // Check if this heading is being mapped to a different field
84
- if ( isset( $mapping[$s_heading] ) ) {
85
- if ( $mapping[$s_heading] == 'import_as_meta' ) {
86
-
87
- $s_heading = 'meta:' . $s_heading;
88
-
89
- } elseif ( $mapping[$s_heading] == 'import_as_images' ) {
90
-
91
- $s_heading = 'images';
92
-
93
- } else {
94
- $s_heading = esc_attr( $mapping[$s_heading] );
95
- }
96
- }
97
- if( !empty($mapping) )
98
- {
99
- foreach ($mapping as $mkey => $mvalue) {
100
- if(trim($mvalue) === trim($heading)){
101
- $s_heading = $mkey;
102
- }
103
- }
104
- }
105
-
106
- if ( $s_heading == '' )
107
- continue;
108
-
109
- // Add the heading to the parsed data
110
- $row[$s_heading] = ( isset( $postmeta[$key] ) ) ? $this->format_data_from_csv( $postmeta[$key], $enc ) : '';
111
-
112
- if(!empty($eval_field[strtolower( $heading )]))
113
- $row[$s_heading] = $this->evaluate_field($row[$s_heading], $eval_field[strtolower( $heading )]);
114
-
115
- // Raw Headers stores the actual column name in the CSV
116
- $raw_headers[ $s_heading ] = $heading;
117
- }
118
- $parsed_data[] = $row;
119
-
120
- unset( $postmeta, $row );
121
-
122
- $position = ftell( $handle );
123
-
124
- if ( $end_pos && $position >= $end_pos )
125
- break;
126
- }
127
- fclose( $handle );
128
- }
129
- return array( $parsed_data, $raw_headers, $position );
130
- }
131
-
132
- private function evaluate_field($value, $evaluation_field){
133
-
134
- $processed_value = $value;
135
- if(!empty($evaluation_field)){
136
- $operator = substr($evaluation_field, 0, 1);
137
- if(in_array($operator, array('=', '+', '-', '*', '/', '&'))){
138
- $eval_val = substr($evaluation_field, 1);
139
-
140
- switch($operator){
141
- case '=':
142
- $processed_value = trim($eval_val);
143
- break;
144
- case '+':
145
- $processed_value = $value + $eval_val;
146
- break;
147
- case '-':
148
- $processed_value = $value - $eval_val;
149
- break;
150
- case '*':
151
- $processed_value = $value * $eval_val;
152
- break;
153
- case '/':
154
- $processed_value = $value / $eval_val;
155
- break;
156
- case '&':
157
- if (strpos($eval_val, '[VAL]') !== false) {
158
- $processed_value = str_replace('[VAL]',$value,$eval_val);
159
- }
160
- else{
161
- $processed_value = $value . $eval_val;
162
- }
163
- break;
164
- }
165
- }
166
- }
167
- return $processed_value;
168
- }
169
-
170
- /**
171
- * Parse product
172
- * @param array $item
173
- * @param integer $merge_empty_cells
174
- * @return array
175
- */
176
- public function parse_product( $item, $merge_empty_cells = 0 ) {
177
-
178
- global $WF_CSV_Product_Import, $wpdb;
179
- $this->row++;
180
-
181
- $terms_array = $postmeta = $product = array();
182
- $attributes = $default_attributes = $gpf_data = null;
183
-
184
- // Merging
185
- $merging = ( ! empty( $_GET['merge'] ) && $_GET['merge'] ) ? 1 : 0;
186
- //if($item['post_parent']!== '' && $item['parent_sku'] !== ''){
187
-
188
- $this->post_defaults['post_type'] = 'product';
189
- $this->post_type = 'product';
190
- // Post ID field mapping
191
- $post_id = ( ! empty( $item['id'] ) ) ? $item['id'] : 0;
192
- $post_id = ( ! empty( $item['post_id'] ) ) ? $item['post_id'] : $post_id;
193
- if ( $merging ) {
194
-
195
- $product['merging'] = true;
196
-
197
-
198
- $WF_CSV_Product_Import->hf_log_data_change( 'csv-import', sprintf( __('> Row %s - preparing for merge.', 'wf_csv_import_export'), $this->row ) );
199
-
200
- // Required fields
201
- if ( ! $post_id && empty( $item['sku'] ) ) {
202
-
203
- $WF_CSV_Product_Import->hf_log_data_change( 'csv-import', __( '> > Cannot merge without id or sku. Importing instead.', 'wf_csv_import_export') );
204
-
205
- $merging = false;
206
- } else {
207
-
208
- // Check product exists
209
- if ( ! $post_id ) {
210
- // Check product to merge exists
211
- $db_query = $wpdb->prepare("
212
- SELECT $wpdb->posts.ID
213
- FROM $wpdb->posts
214
- LEFT JOIN $wpdb->postmeta ON ($wpdb->posts.ID = $wpdb->postmeta.post_id)
215
- WHERE $wpdb->posts.post_type = 'product'
216
- AND $wpdb->posts.post_status IN ( 'publish', 'private', 'draft', 'pending', 'future' )
217
- AND $wpdb->postmeta.meta_key = '_sku' AND $wpdb->postmeta.meta_value = '%s'
218
- ", $item['sku']);
219
- $found_product_id = $wpdb->get_var($db_query);
220
- if ( ! $found_product_id ) {
221
- $WF_CSV_Product_Import->hf_log_data_change( 'csv-import', sprintf(__( '> > Skipped. Cannot find product with sku %s. Importing instead.', 'wf_csv_import_export'), $item['sku']) );
222
- $merging = false;
223
-
224
- } else {
225
-
226
- $post_id = $found_product_id;
227
-
228
- $WF_CSV_Product_Import->hf_log_data_change( 'csv-import', sprintf(__( '> > Found product with ID %s.', 'wf_csv_import_export'), $post_id) );
229
-
230
- }
231
- }
232
-
233
- }
234
- }
235
-
236
- if ( ! $merging ) {
237
-
238
- $product['merging'] = false;
239
- $WF_CSV_Product_Import->hf_log_data_change( 'csv-import', sprintf( __('> Row %s - preparing for import.', 'wf_csv_import_export'), $this->row ) );
240
-
241
- // Required fields
242
- if ( isset($item['post_parent']) && $item['post_parent']=== '' && $item['post_title']=== '') {
243
- $WF_CSV_Product_Import->hf_log_data_change( 'csv-import', __( '> > Skipped. No post_title set for new product.', 'wf_csv_import_export') );
244
- return new WP_Error( 'parse-error', __( 'No post_title set for new product.', 'wf_csv_import_export' ) );
245
- }
246
- if ( !empty($item['post_parent']) && $item['post_parent']!== '' && $item['post_parent']!== null && $item['parent_sku'] === '' ) {
247
- $WF_CSV_Product_Import->hf_log_data_change( 'csv-import', __( '> > Skipped. No parent set for new variation product.', 'wf_csv_import_export') );
248
- //return new WP_Error( 'parse-error', __( 'No post_title set for new product.', 'wf_csv_import_export' ) );
249
- return new WP_Error( 'parse-error', __( 'No parent set for new variation product.', 'wf_csv_import_export' ) );
250
- }
251
-
252
- }
253
-
254
- $product['post_id'] = $post_id;
255
-
256
-
257
- // Get post fields
258
- foreach ( $this->post_defaults as $column => $default ) {
259
- if ( isset( $item[ $column ] ) ) $product[ $column ] = $item[ $column ];
260
- }
261
-
262
- // Get custom fields
263
- foreach ( $this->postmeta_defaults as $column => $default ) {
264
- if ( isset( $item[$column] ) )
265
- $postmeta[$column] = (string) $item[$column];
266
- elseif ( isset( $item['_' . $column] ) )
267
- $postmeta[$column] = (string) $item['_' . $column];
268
-
269
- // Check custom fields are valid
270
- if ( isset( $postmeta[$column] ) && isset( $this->postmeta_allowed[$column] ) && ! in_array( $postmeta[$column], $this->postmeta_allowed[$column] ) ) {
271
- $postmeta[$column] = $this->postmeta_defaults[$column];
272
- }
273
- }
274
-
275
- if ( ! $merging ) {
276
- // Merge post meta with defaults
277
- $product = wp_parse_args( $product, $this->post_defaults );
278
- $postmeta = wp_parse_args( $postmeta, $this->postmeta_defaults );
279
- }
280
-
281
- // Handle special meta fields
282
- // price
283
- if ( $merging ) {
284
- if ( ! isset( $postmeta['regular_price'] ) )
285
- $postmeta['regular_price'] = get_post_meta( $post_id, '_regular_price', true );
286
- $postmeta['regular_price'] = $this->hf_currency_formatter($postmeta['regular_price']);
287
- if ( ! isset( $postmeta['sale_price'] ) )
288
- $postmeta['sale_price'] = get_post_meta( $post_id, '_sale_price', true );
289
- $postmeta['sale_price'] = $this->hf_currency_formatter($postmeta['sale_price']);
290
- }
291
-
292
- if ( isset( $postmeta['regular_price'] ) && isset( $postmeta['sale_price'] ) && $postmeta['sale_price'] !== '' ) {
293
- $postmeta['sale_price'] = $this->hf_currency_formatter($postmeta['sale_price']);
294
- $postmeta['regular_price'] = $this->hf_currency_formatter($postmeta['regular_price']);
295
- $price = min( $postmeta['sale_price'], $postmeta['regular_price']);
296
- $postmeta['price'] = $price;
297
- } elseif ( isset( $postmeta['regular_price'] ) ) {
298
- $postmeta['price'] = $this->hf_currency_formatter($postmeta['regular_price']);
299
- }
300
-
301
- // Reset dynamically generated meta
302
- if ( !isset($item['post_parent']) ) {
303
- $postmeta['min_variation_price'] = $postmeta['max_variation_price'] = $postmeta['min_variation_regular_price'] =$postmeta['max_variation_regular_price'] = $postmeta['min_variation_sale_price'] = $postmeta['max_variation_sale_price'] = '';
304
- }
305
-
306
- // upsells
307
- if ( isset( $postmeta['upsell_ids'] ) && ! is_array( $postmeta['upsell_ids'] ) ) {
308
- $ids = array_filter( array_map( 'trim', explode( '|', $postmeta['upsell_ids'] ) ) );
309
- $postmeta['upsell_ids'] = $ids;
310
- }
311
-
312
- // crosssells
313
- if ( isset( $postmeta['crosssell_ids'] ) && ! is_array( $postmeta['crosssell_ids'] ) ) {
314
- $ids = array_filter( array_map( 'trim', explode( '|', $postmeta['crosssell_ids'] ) ) );
315
- $postmeta['crosssell_ids'] = $ids;
316
- }
317
-
318
- // Sale dates
319
- if ( isset( $postmeta['sale_price_dates_from'] ) ) {
320
- $postmeta['sale_price_dates_from'] = empty( $postmeta['sale_price_dates_from'] ) ? '' : strtotime( $postmeta['sale_price_dates_from'] );
321
- }
322
-
323
- if ( isset( $postmeta['sale_price_dates_to'] ) ) {
324
- $postmeta['sale_price_dates_to'] = empty( $postmeta['sale_price_dates_to'] ) ? '' : strtotime( $postmeta['sale_price_dates_to'] );
325
- }
326
-
327
- // Relative stock updates
328
- if ( $merging ) {
329
- if ( isset( $postmeta['stock'] ) ) {
330
-
331
- $postmeta['stock'] = trim( $postmeta['stock'] );
332
-
333
- $mode = substr( $postmeta['stock'], 0, 3 );
334
-
335
- if ( $mode == '(+)' ) {
336
- $old_stock = absint( get_post_meta( $post_id, '_stock', true ) );
337
- $amount = absint( substr( $postmeta['stock'], 3 ) );
338
- $new_stock = $old_stock + $amount;
339
- $postmeta['stock'] = $new_stock;
340
- }
341
-
342
- if ( $mode == '(-)' ) {
343
- $old_stock = absint( get_post_meta( $post_id, '_stock', true ) );
344
- $amount = absint( substr( $postmeta['stock'], 3 ) );
345
- $new_stock = $old_stock - $amount;
346
- $postmeta['stock'] = $new_stock;
347
- }
348
- }
349
- }
350
-
351
- // Format post status
352
- if ( ! empty( $product['post_status'] ) ) {
353
- $product['post_status'] = strtolower( $product['post_status'] );
354
-
355
- if ( empty($item['post_parent']) ) {
356
- if ( ! in_array( $product['post_status'], array( 'publish', 'private', 'draft', 'pending', 'future', 'inherit', 'trash' ) ) ) {
357
- $product['post_status'] = 'publish';
358
- }
359
- } else {
360
- if ( ! in_array( $product['post_status'], array( 'private', 'publish' ) ) ) {
361
- $product['post_status'] = 'publish';
362
- }
363
- }
364
- }
365
-
366
- // Put set core product postmeta into product array
367
- foreach ( $postmeta as $key => $value ) {
368
- $product['postmeta'][] = array( 'key' => '_' . esc_attr($key), 'value' => $value );
369
- }
370
-
371
- /**
372
- * Handle other columns
373
- */
374
- foreach ( $item as $key => $value ) {
375
-
376
- if ( empty($item['post_parent']) && ! $merge_empty_cells && $value == "" )
377
- continue;
378
-
379
- /**
380
- * File path handling
381
- */
382
- if ( $key == 'file_paths' || $key == 'downloadable_files' ) {
383
-
384
- $file_paths = explode( '|', $value );
385
- $_file_paths = array();
386
- foreach ( $file_paths as $file_path ) {
387
- // 2.1
388
- if ( function_exists( 'wc_get_filename_from_url' ) ) {
389
- $file_path = array_map( 'trim', explode( '::', $file_path ) );
390
- if ( sizeof( $file_path ) === 2 ) {
391
- $file_name = $file_path[0];
392
- $file_path = $file_path[1];
393
- } else {
394
- $file_name = wc_get_filename_from_url( $file_path[0] );
395
- $file_path = $file_path[0];
396
- }
397
- $_file_paths[ md5( $file_path ) ] = array(
398
- 'name' => $file_name,
399
- 'file' => $file_path
400
- );
401
- } else {
402
- $file_path = trim( $file_path );
403
- $_file_paths[ md5( $file_path ) ] = $file_path;
404
- }
405
- }
406
- $value = $_file_paths;
407
-
408
- $product['postmeta'][] = array( 'key' => '_' . esc_attr( $key ), 'value' => $value );
409
- }
410
-
411
- elseif ( strstr( $key, 'tax:' ) ) {
412
-
413
- // Get taxonomy
414
- $taxonomy = trim( str_replace( 'tax:', '', $key ) );
415
-
416
- // Exists?
417
- if ( ! taxonomy_exists( $taxonomy ) ) {
418
- $WF_CSV_Product_Import->hf_log_data_change( 'csv-import', sprintf( __('> > Skipping taxonomy "%s" - it does not exist.', 'wf_csv_import_export'), $taxonomy ) );
419
- continue;
420
- }
421
-
422
- // Product type check
423
- if ( $taxonomy == 'product_type' ) {
424
- $term = strtolower( $value );
425
-
426
- if ( ! array_key_exists( $term, $this->allowed_product_types ) ) {
427
- $WF_CSV_Product_Import->hf_log_data_change( 'csv-import', sprintf( __('> > > Product type "%s" not allowed - using simple.', 'wf_csv_import_export'), $term ) );
428
- $term_id = $this->allowed_product_types['simple'];
429
- } else {
430
- $term_id = $this->allowed_product_types[ $term ];
431
- }
432
-
433
- // Add to array
434
- $terms_array[] = array(
435
- 'taxonomy' => $taxonomy,
436
- 'terms' => array( $term_id )
437
- );
438
-
439
- continue;
440
- }
441
-
442
- // Get terms - ID => parent
443
- $terms = array();
444
- $raw_terms = explode( '|', $value );
445
- $raw_terms = array_map( 'trim', $raw_terms );
446
-
447
- // Handle term hierachy (>)
448
- foreach ( $raw_terms as $raw_term ) {
449
-
450
- if ( strstr( $raw_term, '>' ) ) {
451
-
452
- $raw_term = explode( '>', $raw_term );
453
- $raw_term = array_map( 'trim', $raw_term );
454
-
455
- if(WC()->version < '2.7.0')
456
- {
457
- $raw_term = array_map( 'wp_specialchars', $raw_term );
458
- $raw_term = array_filter( $raw_term );
459
-
460
- }
461
- else
462
- {
463
- $raw_term = array_map( 'esc_html', $raw_term );
464
- $raw_term = array_filter( $raw_term );
465
-
466
- }
467
-
468
- $parent = 0;
469
- $loop = 0;
470
-
471
- foreach ( $raw_term as $term ) {
472
- $loop ++;
473
- $term_id = '';
474
-
475
- if ( isset( $this->inserted_terms[ $taxonomy ][ $parent ][ $term ] ) ) {
476
- $term_id = $this->inserted_terms[ $taxonomy ][ $parent ][ $term ];
477
- } elseif ( $term ) {
478
-
479
- /**
480
- * Check term existance
481
- */
482
- $term_may_exist = term_exists( $term, $taxonomy, absint( $parent ) );
483
-
484
- $WF_CSV_Product_Import->hf_log_data_change( 'CSV-Import', sprintf( __( '> > (' . __LINE__ . ') Term %s (%s) exists? %s', 'wf_csv_import_export' ), sanitize_text_field( $term ), esc_html( $taxonomy ), $term_may_exist ? print_r( $term_may_exist, true ) : '-' ) );
485
-
486
- if ( is_array( $term_may_exist ) ) {
487
- $possible_term = get_term( $term_may_exist['term_id'], 'product_cat' );
488
-
489
- if ( $possible_term->parent == $parent ) {
490
- $term_id = $term_may_exist['term_id'];
491
- }
492
- }
493
-
494
- if ( ! $term_id ) {
495
-
496
- // Create appropriate slug
497
- $slug = array();
498
-
499
- for ( $i = 0; $i < $loop; $i ++ )
500
- $slug[] = $raw_term[ $i ];
501
-
502
- $slug = sanitize_title( implode( '-', $slug ) );
503
-
504
- $t = wp_insert_term( $term, $taxonomy, array( 'parent' => $parent, 'slug' => $slug ) );
505
-
506
- if ( ! is_wp_error( $t ) ) {
507
- $term_id = $t['term_id'];
508
- } else {
509
- $WF_CSV_Product_Import->hf_log_data_change( 'CSV-Import', sprintf( __( '> > (' . __LINE__ . ') Failed to import term %s, parent %s - %s', 'wf_csv_import_export' ), sanitize_text_field( $term ), sanitize_text_field( $parent ), sanitize_text_field( $taxonomy ) ) );
510
- break;
511
- }
512
- }
513
-
514
- $this->inserted_terms[$taxonomy][$parent][$term] = $term_id;
515
-
516
- }
517
-
518
- if ( ! $term_id )
519
- break;
520
-
521
- // Add to product terms, ready to set if this is the final term
522
- if ( sizeof( $raw_term ) == $loop )
523
- $terms[] = $term_id;
524
-
525
- $parent = $term_id;
526
- }
527
-
528
- } else {
529
-
530
- $term_id = '';
531
- $raw_term = (WC()->version < '2.7.0') ? wp_specialchars( $raw_term ) : esc_html( $raw_term );
532
-
533
- if ( isset( $this->inserted_terms[$taxonomy][0][$raw_term] ) ) {
534
-
535
- $term_id = $this->inserted_terms[$taxonomy][0][$raw_term];
536
-
537
- } elseif ( $raw_term ) {
538
-
539
- // Check term existance
540
- $term_exists = term_exists( $raw_term, $taxonomy, 0 );
541
- $term_id = is_array( $term_exists ) ? $term_exists['term_id'] : 0;
542
-
543
- if ( ! $term_id ) {
544
- $t = wp_insert_term( trim( $raw_term ), $taxonomy, array( 'parent' => 0 ) );
545
-
546
- if ( ! is_wp_error( $t ) ) {
547
- $term_id = $t['term_id'];
548
- } else {
549
- $WF_CSV_Product_Import->hf_log_data_change( 'csv-import', sprintf( __( '> > Failed to import term %s %s', 'wf_csv_import_export' ), esc_html($raw_term), esc_html($taxonomy) ) );
550
- break;
551
- }
552
- }
553
-
554
- $this->inserted_terms[$taxonomy][0][$raw_term] = $term_id;
555
-
556
- }
557
-
558
- // Store terms for later insertion
559
- if ( $term_id )
560
- $terms[] = $term_id;
561
-
562
- }
563
-
564
- }
565
-
566
- // Any defined?
567
- if ( sizeof( $terms ) == 0 )
568
- continue;
569
-
570
- // Add to array
571
- $terms_array[] = array(
572
- 'taxonomy' => $taxonomy,
573
- 'terms' => $terms
574
- );
575
- }
576
-
577
- /**
578
- * Handle Attributes
579
- */
580
- elseif ( strstr( $key, 'attribute:' ) ) {
581
-
582
- $attribute_key = sanitize_title( trim( str_replace( 'attribute:', '', $key ) ) );
583
- $attribute_name = str_replace( 'attribute:', '', $WF_CSV_Product_Import->raw_headers[ $key ] );
584
-
585
- if ( ! $attribute_key )
586
- continue;
587
-
588
- // Taxonomy
589
- if ( substr( $attribute_key, 0, 3 ) == 'pa_' ) {
590
-
591
- $taxonomy = $attribute_key;
592
-
593
- // Exists?
594
- if ( ! taxonomy_exists( $taxonomy ) ) {
595
-
596
- $nicename = strtolower( sanitize_title( str_replace( 'pa_', '', $taxonomy ) ) );
597
-
598
- $WF_CSV_Product_Import->hf_log_data_change( 'csv-import', sprintf( __('> > Attribute taxonomy "%s" does not exist. Adding it. Nicename: %s', 'wf_csv_import_export'), $taxonomy, $nicename ) );
599
-
600
- $exists_in_db = $wpdb->get_var( "SELECT attribute_id FROM " . $wpdb->prefix . "woocommerce_attribute_taxonomies WHERE attribute_name = '" . $nicename . "';" );
601
-
602
- if ( ! $exists_in_db ) {
603
- // Create the taxonomy
604
- $wpdb->insert( $wpdb->prefix . "woocommerce_attribute_taxonomies", array( 'attribute_name' => $nicename, 'attribute_label' => $nicename, 'attribute_type' => 'select', 'attribute_orderby' => 'menu_order' ) );
605
- } else {
606
- $WF_CSV_Product_Import->hf_log_data_change( 'csv-import', sprintf( __('> > Attribute taxonomy %s already exists in DB.', 'wf_csv_import_export'), $taxonomy ) );
607
- }
608
-
609
- // Register the taxonomy now so that the import works!
610
- register_taxonomy( $taxonomy,
611
- array( 'product', 'product_variation' ),
612
- array(
613
- 'hierarchical' => true,
614
- 'show_ui' => false,
615
- 'query_var' => true,
616
- 'rewrite' => false,
617
- )
618
- );
619
- }
620
-
621
- // Get terms
622
- $terms = array();
623
- $raw_terms = explode( '|', $value );
624
- if(WC()->version < '2.7.0')
625
- {
626
- $raw_terms = array_map( 'wp_specialchars', $raw_terms );
627
- $raw_terms = array_map( 'trim', $raw_terms );
628
-
629
- }else{
630
-
631
- $raw_terms = array_map( 'esc_html', $raw_terms );
632
- $raw_terms = array_map( 'trim', $raw_terms );
633
-
634
- }
635
-
636
- if ( sizeof( $raw_terms ) > 0 ) {
637
-
638
- foreach ( $raw_terms as $raw_term ) {
639
-
640
- if ( empty( $raw_term ) && 0 != $raw_term ) {
641
- continue;
642
- }
643
-
644
- // Check term existance
645
- $term_exists = term_exists( $raw_term, $taxonomy, 0 );
646
- $term_id = is_array( $term_exists ) ? $term_exists['term_id'] : 0;
647
-
648
- if ( ! $term_id ) {
649
- $t = wp_insert_term( trim( $raw_term ), $taxonomy );
650
-
651
- if ( ! is_wp_error( $t ) ) {
652
- $term_id = $t['term_id'];
653
-
654
- $WF_CSV_Product_Import->hf_log_data_change( 'csv-import', sprintf( __( '> > Inserted Raw Term %s ID = %s', 'wf_csv_import_export' ), esc_html( $raw_term ), $term_id ) );
655
- } else {
656
- $WF_CSV_Product_Import->hf_log_data_change( 'csv-import', sprintf( __( '> > Failed to import term %s %s', 'wf_csv_import_export' ), esc_html($raw_term), esc_html($taxonomy) ) );
657
- break;
658
- }
659
- } else {
660
- $WF_CSV_Product_Import->hf_log_data_change( 'csv-import', sprintf( __( '> > Raw Term %s ID = %s', 'wf_csv_import_export' ), esc_html( $raw_term ), $term_id ) );
661
- }
662
-
663
- if ( $term_id ) {
664
- $terms[] = $term_id;
665
- }
666
- }
667
-
668
- }
669
-
670
- // Add to array
671
- $terms_array[] = array(
672
- 'taxonomy' => $taxonomy,
673
- 'terms' => $terms
674
- );
675
-
676
- // Ensure we have original attributes
677
- if ( is_null( $attributes ) && $merging ) {
678
- $attributes = array_filter( (array) maybe_unserialize( get_post_meta( $post_id, '_product_attributes', true ) ) );
679
- } elseif ( is_null( $attributes ) ) {
680
- $attributes = array();
681
- }
682
-
683
- // Set attribute
684
- if ( ! isset( $attributes[$taxonomy] ) )
685
- $attributes[$taxonomy] = array();
686
-
687
- $attributes[$taxonomy]['name'] = $taxonomy;
688
- $attributes[$taxonomy]['value'] = null;
689
- $attributes[$taxonomy]['is_taxonomy'] = 1;
690
-
691
- if ( ! isset( $attributes[$taxonomy]['position'] ) )
692
- $attributes[$taxonomy]['position'] = 0;
693
- if ( ! isset( $attributes[$taxonomy]['is_visible'] ) )
694
- $attributes[$taxonomy]['is_visible'] = 1;
695
- if ( ! isset( $attributes[$taxonomy]['is_variation'] ) )
696
- $attributes[$taxonomy]['is_variation'] = 0;
697
-
698
- } else {
699
-
700
- if ( ! $value || ! $attribute_key ) continue;
701
-
702
- // Set attribute
703
- if ( ! isset( $attributes[$attribute_key] ) )
704
- $attributes[$attribute_key] = array();
705
-
706
- $attributes[$attribute_key]['name'] = $attribute_name;
707
- $attributes[$attribute_key]['value'] = $value;
708
- $attributes[$attribute_key]['is_taxonomy'] = 0;
709
-
710
- if ( ! isset( $attributes[$attribute_key]['position'] ) )
711
- $attributes[$attribute_key]['position'] = 0;
712
- if ( ! isset( $attributes[$attribute_key]['is_visible'] ) )
713
- $attributes[$attribute_key]['is_visible'] = 1;
714
- if ( ! isset( $attributes[$attribute_key]['is_variation'] ) )
715
- $attributes[$attribute_key]['is_variation'] = 0;
716
- }
717
-
718
- }
719
-
720
- /**
721
- * Handle Attributes Data - position|is_visible|is_variation
722
- */
723
- elseif ( strstr( $key, 'attribute_data:' ) ) {
724
-
725
- $attribute_key = sanitize_title( trim( str_replace( 'attribute_data:', '', $key ) ) );
726
-
727
- if ( ! $attribute_key ) {
728
- continue;
729
- }
730
-
731
- $values = explode( '|', $value );
732
- $position = isset( $values[0] ) ? (int) $values[0] : 0;
733
- $visible = isset( $values[1] ) ? (int) $values[1] : 1;
734
- $variation = isset( $values[2] ) ? (int) $values[2] : 0;
735
-
736
- // Ensure we have original attributes
737
- if ( ! isset( $attributes[ $attribute_key ] ) ) {
738
- if ( $merging ) {
739
- $existing_attributes = array_filter( (array) maybe_unserialize( get_post_meta( $post_id, '_product_attributes', true ) ) );
740
- $attributes[ $attribute_key ] = isset( $existing_attributes[ $attribute_key ] ) ? $existing_attributes[ $attribute_key ] : array();
741
- } else {
742
- $attributes[ $attribute_key ] = array();
743
- }
744
- }
745
-
746
- $attributes[ $attribute_key ]['position'] = $position;
747
- $attributes[ $attribute_key ]['is_visible'] = $visible;
748
- $attributes[ $attribute_key ]['is_variation'] = $variation;
749
- }
750
-
751
- /**
752
- * Handle Attributes Default Values
753
- */
754
- elseif ( strstr( $key, 'attribute_default:' ) ) {
755
-
756
- $attribute_key = sanitize_title( trim( str_replace( 'attribute_default:', '', $key ) ) );
757
-
758
- if ( ! $attribute_key ) continue;
759
-
760
- // Ensure we have original attributes
761
- if ( is_null( $default_attributes ) && $merging ) {
762
- $default_attributes = array_filter( (array) maybe_unserialize( get_post_meta( $post_id, '_default_attributes', true ) ) );
763
- } elseif ( is_null( $default_attributes ) ) {
764
- $default_attributes = array();
765
- }
766
-
767
- $default_attributes[ $attribute_key ] = $value;
768
- }
769
-
770
- /**
771
- * Handle gpf: google product feed columns
772
- */
773
- elseif ( strstr( $key, 'gpf:' ) ) {
774
-
775
- $gpf_key = trim( str_replace( 'gpf:', '', $key ) );
776
-
777
- // Get original values
778
- if ( is_null( $gpf_data ) && $merging ) {
779
- $gpf_data = array_filter( (array) maybe_unserialize( get_post_meta( $post_id, '_woocommerce_gpf_data', true ) ) );
780
- } elseif ( is_null( $gpf_data ) ) {
781
- $gpf_data = array(
782
- 'availability' => '',
783
- 'condition' => '',
784
- 'brand' => '',
785
- 'product_type' => '',
786
- 'google_product_category' => '',
787
- 'gtin' => '',
788
- 'mpn' => '',
789
- 'gender' => '',
790
- 'age_group' => '',
791
- 'color' => '',
792
- 'size' => ''
793
- );
794
- }
795
-
796
- $gpf_data[$gpf_key] = $value;
797
-
798
- }
799
-
800
- /**
801
- * Handle upsell SKUs which we cannot assign until we get IDs later on
802
- */
803
- elseif ( strstr( $key, 'upsell_skus' ) ) {
804
- if ( $value ) {
805
- $skus = array_filter( array_map( 'trim', explode( '|', $value ) ) );
806
- $product['upsell_skus'] = $skus;
807
- }
808
- }
809
-
810
- /**
811
- * Handle crosssells SKUs which we cannot assign until we get IDs later on
812
- */
813
- elseif ( strstr( $key, 'crosssell_skus' ) ) {
814
- if ( $value ) {
815
- $skus = array_filter( array_map( 'trim', explode( '|', $value ) ) );
816
- $product['crosssell_skus'] = $skus;
817
- }
818
- }
819
-
820
- }
821
-
822
- // Remove empty attribues
823
- if(!empty($attributes))
824
- foreach ( $attributes as $key => $value ) {
825
- if ( ! isset($value['name']) ) unset( $attributes[$key] );
826
- }
827
-
828
- /**
829
- * Handle images
830
- */
831
- if ( ! empty( $item['images'] ) ) {
832
- $images = array_map( 'trim', explode( '|', $item['images'] ) );
833
- } else {
834
- $images = '';
835
- }
836
-
837
- $product['postmeta'][] = array( 'key' => '_default_attributes', 'value' => $default_attributes );
838
- $product['attributes'] = $attributes;
839
- $product['gpf_data'] = $gpf_data;
840
- $product['images'] = $images;
841
- $product['terms'] = $terms_array;
842
- $product['sku'] = ( ! empty( $item['sku'] ) ) ? $item['sku'] : '';
843
- $product['post_title'] = ( ! empty( $item['post_title'] ) ) ? $item['post_title'] : '';
844
- $product['post_type'] = $this->post_type;
845
- unset( $item, $terms_array, $postmeta, $attributes, $gpf_data, $images );
846
- return $product;
847
- }
848
- public function hf_currency_formatter($price){
849
-
850
- $decimal_seperator = wc_get_price_decimal_separator();
851
- return preg_replace("[^0-9\\'.$decimal_seperator.']", "", $price);
852
- }
853
- }
1
+ <?php
2
+ /**
3
+ * WooCommerce CSV Importer class for managing parsing of CSV files.
4
+ */
5
+ class WF_CSV_Parser {
6
+
7
+ var $row;
8
+ var $post_type;
9
+ var $reserved_fields; // Fields we map/handle (not custom fields)
10
+ var $post_defaults; // Default post data
11
+ var $postmeta_defaults; // default post meta
12
+ var $postmeta_allowed; // post meta validation
13
+ var $allowed_product_types; // Allowed product types
14
+
15
+ /**
16
+ * Constructor
17
+ */
18
+ public function __construct( $post_type = 'product' ) {
19
+
20
+ $this->post_type = $post_type;
21
+ $this->reserved_fields = include( 'data/data-wf-reserved-fields.php' );
22
+ $this->post_defaults = include( 'data/data-wf-post-defaults.php' );
23
+ $this->postmeta_defaults = include( 'data/data-wf-postmeta-defaults.php' );
24
+ $this->postmeta_allowed = include( 'data/data-wf-postmeta-allowed.php' );
25
+
26
+ $simple_term = get_term_by( 'slug', 'simple', 'product_type' );
27
+ $variable_term = get_term_by( 'slug', 'variable', 'product_type' );
28
+ $grouped_term = get_term_by( 'slug', 'grouped', 'product_type' );
29
+ $external_term = get_term_by( 'slug', 'external', 'product_type' );
30
+
31
+ $this->allowed_product_types = array(
32
+ 'simple' => $simple_term->term_id,
33
+ 'variable' => $variable_term->term_id,
34
+ 'grouped' => $grouped_term->term_id,
35
+ 'external' => $external_term->term_id
36
+ );
37
+
38
+ }
39
+
40
+ /**
41
+ * Format data from the csv file
42
+ * @param string $data
43
+ * @param string $enc
44
+ * @return string
45
+ */
46
+ public function format_data_from_csv( $data, $enc ) {
47
+ return ( $enc == 'UTF-8' ) ? $data : utf8_encode( $data );
48
+ }
49
+
50
+ /**
51
+ * Parse the data
52
+ * @param string $file [description]
53
+ * @param string $delimiter [description]
54
+ * @param array $mapping [description]
55
+ * @param integer $start_pos [description]
56
+ * @param integer $end_pos [description]
57
+ * @return array
58
+ */
59
+ public function parse_data( $file, $delimiter, $mapping, $start_pos = 0, $end_pos = null, $eval_field ) {
60
+ // Set locale
61
+ $enc = mb_detect_encoding( $file, 'UTF-8, ISO-8859-1', true );
62
+ if ( $enc )
63
+ setlocale( LC_ALL, 'en_US.' . $enc );
64
+ @ini_set( 'auto_detect_line_endings', true );
65
+
66
+ $parsed_data = array();
67
+ $raw_headers = array();
68
+
69
+ // Put all CSV data into an associative array
70
+ if ( ( $handle = fopen( $file, "r" ) ) !== FALSE ) {
71
+
72
+ $header = fgetcsv( $handle, 0, $delimiter );
73
+ if ( $start_pos != 0 )
74
+ fseek( $handle, $start_pos );
75
+
76
+ while ( ( $postmeta = fgetcsv( $handle, 0, $delimiter ) ) !== FALSE ) {
77
+ $row = array();
78
+
79
+ foreach ( $header as $key => $heading ) {
80
+ // Heading is the lowercase version of the column name
81
+ $s_heading = strtolower( $heading );
82
+
83
+ // Check if this heading is being mapped to a different field
84
+ if ( isset( $mapping[$s_heading] ) ) {
85
+ if ( $mapping[$s_heading] == 'import_as_meta' ) {
86
+
87
+ $s_heading = 'meta:' . $s_heading;
88
+
89
+ } elseif ( $mapping[$s_heading] == 'import_as_images' ) {
90
+
91
+ $s_heading = 'images';
92
+
93
+ } else {
94
+ $s_heading = esc_attr( $mapping[$s_heading] );
95
+ }
96
+ }
97
+ if( !empty($mapping) )
98
+ {
99
+ foreach ($mapping as $mkey => $mvalue) {
100
+ if(trim($mvalue) === trim($heading)){
101
+ $s_heading = $mkey;
102
+ }
103
+ }
104
+ }
105
+
106
+ if ( $s_heading == '' )
107
+ continue;
108
+
109
+ // Add the heading to the parsed data
110
+ $row[$s_heading] = ( isset( $postmeta[$key] ) ) ? $this->format_data_from_csv( $postmeta[$key], $enc ) : '';
111
+
112
+ if(!empty($eval_field[strtolower( $heading )]))
113
+ $row[$s_heading] = $this->evaluate_field($row[$s_heading], $eval_field[strtolower( $heading )]);
114
+
115
+ // Raw Headers stores the actual column name in the CSV
116
+ $raw_headers[ $s_heading ] = $heading;
117
+ }
118
+ $parsed_data[] = $row;
119
+
120
+ unset( $postmeta, $row );
121
+
122
+ $position = ftell( $handle );
123
+
124
+ if ( $end_pos && $position >= $end_pos )
125
+ break;
126
+ }
127
+ fclose( $handle );
128
+ }
129
+ return array( $parsed_data, $raw_headers, $position );
130
+ }
131
+
132
+ private function evaluate_field($value, $evaluation_field){
133
+
134
+ $processed_value = $value;
135
+ if(!empty($evaluation_field)){
136
+ $operator = substr($evaluation_field, 0, 1);
137
+ if(in_array($operator, array('=', '+', '-', '*', '/', '&'))){
138
+ $eval_val = substr($evaluation_field, 1);
139
+
140
+ switch($operator){
141
+ case '=':
142
+ $processed_value = trim($eval_val);
143
+ break;
144
+ case '+':
145
+ $processed_value = $value + $eval_val;
146
+ break;
147
+ case '-':
148
+ $processed_value = $value - $eval_val;
149
+ break;
150
+ case '*':
151
+ $processed_value = $value * $eval_val;
152
+ break;
153
+ case '/':
154
+ $processed_value = $value / $eval_val;
155
+ break;
156
+ case '&':
157
+ if (strpos($eval_val, '[VAL]') !== false) {
158
+ $processed_value = str_replace('[VAL]',$value,$eval_val);
159
+ }
160
+ else{
161
+ $processed_value = $value . $eval_val;
162
+ }
163
+ break;
164
+ }
165
+ }
166
+ }
167
+ return $processed_value;
168
+ }
169
+
170
+ /**
171
+ * Parse product
172
+ * @param array $item
173
+ * @param integer $merge_empty_cells
174
+ * @return array
175
+ */
176
+ public function parse_product( $item, $merge_empty_cells = 0 ) {
177
+
178
+ global $WF_CSV_Product_Import, $wpdb;
179
+ $this->row++;
180
+
181
+ $terms_array = $postmeta = $product = array();
182
+ $attributes = $default_attributes = $gpf_data = null;
183
+
184
+ // Merging
185
+ $merging = ( ! empty( $_GET['merge'] ) && $_GET['merge'] ) ? 1 : 0;
186
+ //if($item['post_parent']!== '' && $item['parent_sku'] !== ''){
187
+
188
+ $this->post_defaults['post_type'] = 'product';
189
+ $this->post_type = 'product';
190
+ // Post ID field mapping
191
+ $post_id = ( ! empty( $item['id'] ) ) ? $item['id'] : 0;
192
+ $post_id = ( ! empty( $item['post_id'] ) ) ? $item['post_id'] : $post_id;
193
+ if ( $merging ) {
194
+
195
+ $product['merging'] = true;
196
+
197
+
198
+ $WF_CSV_Product_Import->hf_log_data_change( 'csv-import', sprintf( __('> Row %s - preparing for merge.', 'wf_csv_import_export'), $this->row ) );
199
+
200
+ // Required fields
201
+ if ( ! $post_id && empty( $item['sku'] ) ) {
202
+
203
+ $WF_CSV_Product_Import->hf_log_data_change( 'csv-import', __( '> > Cannot merge without id or sku. Importing instead.', 'wf_csv_import_export') );
204
+
205
+ $merging = false;
206
+ } else {
207
+
208
+ // Check product exists
209
+ if ( ! $post_id ) {
210
+ // Check product to merge exists
211
+ $db_query = $wpdb->prepare("
212
+ SELECT $wpdb->posts.ID
213
+ FROM $wpdb->posts
214
+ LEFT JOIN $wpdb->postmeta ON ($wpdb->posts.ID = $wpdb->postmeta.post_id)
215
+ WHERE $wpdb->posts.post_type = 'product'
216
+ AND $wpdb->posts.post_status IN ( 'publish', 'private', 'draft', 'pending', 'future' )
217
+ AND $wpdb->postmeta.meta_key = '_sku' AND $wpdb->postmeta.meta_value = '%s'
218
+ ", $item['sku']);
219
+ $found_product_id = $wpdb->get_var($db_query);
220
+ if ( ! $found_product_id ) {
221
+ $WF_CSV_Product_Import->hf_log_data_change( 'csv-import', sprintf(__( '> > Skipped. Cannot find product with sku %s. Importing instead.', 'wf_csv_import_export'), $item['sku']) );
222
+ $merging = false;
223
+
224
+ } else {
225
+
226
+ $post_id = $found_product_id;
227
+
228
+ $WF_CSV_Product_Import->hf_log_data_change( 'csv-import', sprintf(__( '> > Found product with ID %s.', 'wf_csv_import_export'), $post_id) );
229
+
230
+ }
231
+ }
232
+
233
+ }
234
+ }
235
+
236
+ if ( ! $merging ) {
237
+
238
+ $product['merging'] = false;
239
+ $WF_CSV_Product_Import->hf_log_data_change( 'csv-import', sprintf( __('> Row %s - preparing for import.', 'wf_csv_import_export'), $this->row ) );
240
+
241
+ // Required fields
242
+ if ( isset($item['post_parent']) && $item['post_parent']=== '' && $item['post_title']=== '') {
243
+ $WF_CSV_Product_Import->hf_log_data_change( 'csv-import', __( '> > Skipped. No post_title set for new product.', 'wf_csv_import_export') );
244
+ return new WP_Error( 'parse-error', __( 'No post_title set for new product.', 'wf_csv_i