Product Import Export for WooCommerce - Version 1.4.0

Version Description

  • Updates: Tested OK with WP 4.9
Download this release

Release Info

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

Code changes from version 1.3.9 to 1.4.0

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,81 +1,81 @@
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
- add_action( 'admin_menu', array( $this, 'admin_menu' ) );
13
- add_action( 'admin_print_styles', array( $this, 'admin_scripts' ) );
14
- add_action( 'admin_notices', array( $this, 'admin_notices' ) );
15
- }
16
-
17
- /**
18
- * Notices in admin
19
- */
20
- public function admin_notices() {
21
- if ( ! function_exists( 'mb_detect_encoding' ) ) {
22
- 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>';
23
- }
24
- }
25
-
26
- /**
27
- * Admin Menu
28
- */
29
- public function admin_menu() {
30
- $page = add_submenu_page( 'woocommerce', __( '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' ) );
31
- }
32
-
33
- /**
34
- * Admin Scripts
35
- */
36
- public function admin_scripts() {
37
- wp_enqueue_style( 'woocommerce_admin_styles', WC()->plugin_url() . '/assets/css/admin.css' );
38
- wp_enqueue_style( 'woocommerce-product-csv-importer', plugins_url( basename( plugin_dir_path( WF_ProdImpExpCsv_FILE ) ) . '/styles/wf-style.css', basename( __FILE__ ) ), '', '1.0.0', 'screen' );
39
- }
40
-
41
- /**
42
- * Admin Screen output
43
- */
44
- public function output() {
45
- $tab = 'import';
46
- if( ! empty( $_GET['tab'] ) ) {
47
- if( $_GET['tab'] == 'export' ) {
48
- $tab = 'export';
49
- }
50
- else if ( $_GET['tab'] == 'settings' ) {
51
- $tab = 'settings';
52
- }
53
- }
54
- include( 'views/html-wf-admin-screen.php' );
55
- }
56
-
57
- /**
58
- * Admin page for importing
59
- */
60
- public function admin_import_page() {
61
- include( 'views/import/html-wf-import-products.php' );
62
- $post_columns = include( 'exporter/data/data-wf-post-columns.php' );
63
- include( 'views/export/html-wf-export-products.php' );
64
- }
65
-
66
- /**
67
- * Admin Page for exporting
68
- */
69
- public function admin_export_page() {
70
- $post_columns = include( 'exporter/data/data-wf-post-columns.php' );
71
- include( 'views/export/html-wf-export-products.php' );
72
- }
73
-
74
- /**
75
- * Admin Page for settings
76
- */
77
- public function admin_settings_page() {
78
- }
79
- }
80
-
81
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
+ add_action( 'admin_menu', array( $this, 'admin_menu' ) );
13
+ add_action( 'admin_print_styles', array( $this, 'admin_scripts' ) );
14
+ add_action( 'admin_notices', array( $this, 'admin_notices' ) );
15
+ }
16
+
17
+ /**
18
+ * Notices in admin
19
+ */
20
+ public function admin_notices() {
21
+ if ( ! function_exists( 'mb_detect_encoding' ) ) {
22
+ 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>';
23
+ }
24
+ }
25
+
26
+ /**
27
+ * Admin Menu
28
+ */
29
+ public function admin_menu() {
30
+ $page = add_submenu_page( 'woocommerce', __( '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' ) );
31
+ }
32
+
33
+ /**
34
+ * Admin Scripts
35
+ */
36
+ public function admin_scripts() {
37
+ wp_enqueue_style( 'woocommerce_admin_styles', WC()->plugin_url() . '/assets/css/admin.css' );
38
+ wp_enqueue_style( 'woocommerce-product-csv-importer', plugins_url( basename( plugin_dir_path( WF_ProdImpExpCsv_FILE ) ) . '/styles/wf-style.css', basename( __FILE__ ) ), '', '1.0.0', 'screen' );
39
+ }
40
+
41
+ /**
42
+ * Admin Screen output
43
+ */
44
+ public function output() {
45
+ $tab = 'import';
46
+ if( ! empty( $_GET['tab'] ) ) {
47
+ if( $_GET['tab'] == 'export' ) {
48
+ $tab = 'export';
49
+ }
50
+ else if ( $_GET['tab'] == 'settings' ) {
51
+ $tab = 'settings';
52
+ }
53
+ }
54
+ include( 'views/html-wf-admin-screen.php' );
55
+ }
56
+
57
+ /**
58
+ * Admin page for importing
59
+ */
60
+ public function admin_import_page() {
61
+ include( 'views/import/html-wf-import-products.php' );
62
+ $post_columns = include( 'exporter/data/data-wf-post-columns.php' );
63
+ include( 'views/export/html-wf-export-products.php' );
64
+ }
65
+
66
+ /**
67
+ * Admin Page for exporting
68
+ */
69
+ public function admin_export_page() {
70
+ $post_columns = include( 'exporter/data/data-wf-post-columns.php' );
71
+ include( 'views/export/html-wf-export-products.php' );
72
+ }
73
+
74
+ /**
75
+ * Admin Page for settings
76
+ */
77
+ public function admin_settings_page() {
78
+ }
79
+ }
80
+
81
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,873 +1,873 @@
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
- $this->post_type = $post_type;
20
- $this->reserved_fields = include( 'data/data-wf-reserved-fields.php' );
21
- $this->post_defaults = include( 'data/data-wf-post-defaults.php' );
22
- $this->postmeta_defaults = include( 'data/data-wf-postmeta-defaults.php' );
23
- $this->postmeta_allowed = include( 'data/data-wf-postmeta-allowed.php' );
24
-
25
- $simple_term = get_term_by( 'slug', 'simple', 'product_type' );
26
- $variable_term = get_term_by( 'slug', 'variable', 'product_type' );
27
- $grouped_term = get_term_by( 'slug', 'grouped', 'product_type' );
28
- $external_term = get_term_by( 'slug', 'external', 'product_type' );
29
-
30
- $this->allowed_product_types = array(
31
- 'simple' => $simple_term->term_id,
32
- 'variable' => $variable_term->term_id,
33
- 'grouped' => $grouped_term->term_id,
34
- 'external' => $external_term->term_id
35
- );
36
-
37
- }
38
-
39
- /**
40
- * Format data from the csv file
41
- * @param string $data
42
- * @param string $enc
43
- * @return string
44
- */
45
- public function format_data_from_csv( $data, $enc ) {
46
- return ( $enc == 'UTF-8' ) ? $data : utf8_encode( $data );
47
- }
48
-
49
- /**
50
- * Parse the data
51
- * @param string $file [description]
52
- * @param string $delimiter [description]
53
- * @param array $mapping [description]
54
- * @param integer $start_pos [description]
55
- * @param integer $end_pos [description]
56
- * @return array
57
- */
58
- public function parse_data( $file, $delimiter, $mapping, $start_pos = 0, $end_pos = null, $eval_field ) {
59
- // Set locale
60
- $enc = mb_detect_encoding( $file, 'UTF-8, ISO-8859-1', true );
61
- if ( $enc )
62
- setlocale( LC_ALL, 'en_US.' . $enc );
63
- @ini_set( 'auto_detect_line_endings', true );
64
-
65
- $parsed_data = array();
66
- $raw_headers = array();
67
-
68
- // Put all CSV data into an associative array
69
- if ( ( $handle = fopen( $file, "r" ) ) !== FALSE ) {
70
-
71
- $header = fgetcsv( $handle, 0, $delimiter );
72
- if ( $start_pos != 0 )
73
- fseek( $handle, $start_pos );
74
-
75
- while ( ( $postmeta = fgetcsv( $handle, 0, $delimiter ) ) !== FALSE ) {
76
- $row = array();
77
-
78
- foreach ( $header as $key => $heading ) {
79
- // Heading is the lowercase version of the column name
80
- $s_heading = strtolower( $heading );
81
-
82
- // Check if this heading is being mapped to a different field
83
- if ( isset( $mapping[$s_heading] ) ) {
84
- if ( $mapping[$s_heading] == 'import_as_meta' ) {
85
-
86
- $s_heading = 'meta:' . $s_heading;
87
-
88
- } elseif ( $mapping[$s_heading] == 'import_as_images' ) {
89
-
90
- $s_heading = 'images';
91
-
92
- } else {
93
- $s_heading = esc_attr( $mapping[$s_heading] );
94
- }
95
- }
96
- if( !empty($mapping) )
97
- {
98
- foreach ($mapping as $mkey => $mvalue) {
99
- if(trim($mvalue) === trim($heading)){
100
- $s_heading = $mkey;
101
- }
102
- }
103
- }
104
-
105
- if ( $s_heading == '' )
106
- continue;
107
-
108
- // Add the heading to the parsed data
109
- $row[$s_heading] = ( isset( $postmeta[$key] ) ) ? $this->format_data_from_csv( $postmeta[$key], $enc ) : '';
110
-
111
- if(!empty($eval_field[strtolower( $heading )]))
112
- $row[$s_heading] = $this->evaluate_field($row[$s_heading], $eval_field[strtolower( $heading )]);
113
-
114
- // Raw Headers stores the actual column name in the CSV
115
- $raw_headers[ $s_heading ] = $heading;
116
- }
117
- $parsed_data[] = $row;
118
-
119
- unset( $postmeta, $row );
120
-
121
- $position = ftell( $handle );
122
-
123
- if ( $end_pos && $position >= $end_pos )
124
- break;
125
- }
126
- fclose( $handle );
127
- }
128
- return array( $parsed_data, $raw_headers, $position );
129
- }
130
-
131
- private function evaluate_field($value, $evaluation_field){
132
- //echo "value:$value, $evaluation_field </br>";
133
- $processed_value = $value;
134
- if(!empty($evaluation_field)){
135
- $operator = substr($evaluation_field, 0, 1);
136
- if(in_array($operator, array('=', '+', '-', '*', '/', '&'))){
137
- $eval_val = substr($evaluation_field, 1);
138
- //echo "operator:$operator";
139
- switch($operator){
140
- case '=':
141
- $processed_value = trim($eval_val);
142
- break;
143
- case '+':
144
- $processed_value = $value + $eval_val;
145
- break;
146
- case '-':
147
- $processed_value = $value - $eval_val;
148
- break;
149
- case '*':
150
- $processed_value = $value * $eval_val;
151
- break;
152
- case '/':
153
- $processed_value = $value / $eval_val;
154
- break;
155
- case '&':
156
- if (strpos($eval_val, '[VAL]') !== false) {
157
- $processed_value = str_replace('[VAL]',$value,$eval_val);
158
- }
159
- else{
160
- $processed_value = $value . $eval_val;
161
- }
162
- break;
163
- }
164
- }
165
- }
166
- return $processed_value;
167
- }
168
-
169
- /**
170
- * Parse product
171
- * @param array $item
172
- * @param integer $merge_empty_cells
173
- * @return array
174
- */
175
- public function parse_product( $item, $merge_empty_cells = 0 ) {
176
- global $WF_CSV_Product_Import, $wpdb;
177
- $this->row++;
178
-
179
- $terms_array = $postmeta = $product = array();
180
- $attributes = $default_attributes = $gpf_data = null;
181
-
182
- // Merging
183
- $merging = ( ! empty( $_GET['merge'] ) && $_GET['merge'] ) ? true : false;
184
- //if($item['post_parent']!== '' && $item['parent_sku'] !== ''){
185
-
186
- $this->post_defaults['post_type'] = 'product';
187
- $this->post_type = 'product';
188
- // Post ID field mapping
189
- $post_id = ( ! empty( $item['id'] ) ) ? $item['id'] : 0;
190
- $post_id = ( ! empty( $item['post_id'] ) ) ? $item['post_id'] : $post_id;
191
- if ( $merging ) {
192
-
193
- $product['merging'] = true;
194
-
195
-
196
- $WF_CSV_Product_Import->hf_log_data_change( 'csv-import', sprintf( __('> Row %s - preparing for merge.', 'wf_csv_import_export'), $this->row ) );
197
-
198
- // Required fields
199
- if ( ! $post_id && empty( $item['sku'] ) ) {
200
-
201
- $WF_CSV_Product_Import->hf_log_data_change( 'csv-import', __( '> > Cannot merge without id or sku. Importing instead.', 'wf_csv_import_export') );
202
-
203
- $merging = false;
204
- } else {
205
-
206
- // Check product exists
207
- if ( ! $post_id ) {
208
- // Check product to merge exists
209
- $db_query = $wpdb->prepare("
210
- SELECT $wpdb->posts.ID
211
- FROM $wpdb->posts
212
- LEFT JOIN $wpdb->postmeta ON ($wpdb->posts.ID = $wpdb->postmeta.post_id)
213
- WHERE $wpdb->posts.post_type = 'product'
214
- AND $wpdb->posts.post_status IN ( 'publish', 'private', 'draft', 'pending', 'future' )
215
- AND $wpdb->postmeta.meta_key = '_sku' AND $wpdb->postmeta.meta_value = '%s'
216
- ", $item['sku']);
217
- $found_product_id = $wpdb->get_var($db_query);
218
- if ( ! $found_product_id ) {
219
- $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']) );
220
- $merging = false;
221
-
222
- } else {
223
-
224
- $post_id = $found_product_id;
225
-
226
- $WF_CSV_Product_Import->hf_log_data_change( 'csv-import', sprintf(__( '> > Found product with ID %s.', 'wf_csv_import_export'), $post_id) );
227
-
228
- }
229
- }
230
- $product['merging'] = true;
231
- }
232
- }
233
-
234
- if ( ! $merging ) {
235
-
236
- $product['merging'] = false;
237
- $WF_CSV_Product_Import->hf_log_data_change( 'csv-import', sprintf( __('> Row %s - preparing for import.', 'wf_csv_import_export'), $this->row ) );
238
-
239
- // Required fields
240
- if ( isset($item['post_parent']) && $item['post_parent']=== '' && $item['post_title']=== '') {
241
- $WF_CSV_Product_Import->hf_log_data_change( 'csv-import', __( '> > Skipped. No post_title set for new product.', 'wf_csv_import_export') );
242
- return new WP_Error( 'parse-error', __( 'No post_title set for new product.', 'wf_csv_import_export' ) );
243
- }
244
- if ( !empty($item['post_parent']) && $item['post_parent']!== '' && $item['post_parent']!== null && $item['parent_sku'] === '' ) {
245
- $WF_CSV_Product_Import->hf_log_data_change( 'csv-import', __( '> > Skipped. No parent set for new variation product.', 'wf_csv_import_export') );
246
- //return new WP_Error( 'parse-error', __( 'No post_title set for new product.', 'wf_csv_import_export' ) );
247
- return new WP_Error( 'parse-error', __( 'No parent set for new variation product.', 'wf_csv_import_export' ) );
248
- }
249
-
250
- }
251
-
252
- $product['post_id'] = $post_id;
253
-
254
-
255
- // Get post fields
256
- foreach ( $this->post_defaults as $column => $default ) {
257
- if ( isset( $item[ $column ] ) ) $product[ $column ] = $item[ $column ];
258
- }
259
-
260
- // Get custom fields
261
- foreach ( $this->postmeta_defaults as $column => $default ) {
262
- if ( isset( $item[$column] ) )
263
- $postmeta[$column] = (string) $item[$column];
264
- elseif ( isset( $item['_' . $column] ) )
265
- $postmeta[$column] = (string) $item['_' . $column];
266
-
267
- // Check custom fields are valid
268
- if ( isset( $postmeta[$column] ) && isset( $this->postmeta_allowed[$column] ) && ! in_array( $postmeta[$column], $this->postmeta_allowed[$column] ) ) {
269
- $postmeta[$column] = $this->postmeta_defaults[$column];
270
- }
271
- }
272
-
273
- if ( ! $merging ) {
274
- // Merge post meta with defaults
275
- $product = wp_parse_args( $product, $this->post_defaults );
276
- $postmeta = wp_parse_args( $postmeta, $this->postmeta_defaults );
277
- }
278
-
279
- // Handle special meta fields
280
- if ( isset($item['post_parent']) ) {
281
-
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
- } else {
302
-
303
- // price
304
- if ( $merging ) {
305
- if ( ! isset( $postmeta['regular_price'] ) )
306
- $postmeta['regular_price'] = get_post_meta( $post_id, '_regular_price', true );
307
- $postmeta['regular_price'] = $this->hf_currency_formatter($postmeta['regular_price']);
308
- if ( ! isset( $postmeta['sale_price'] ) )
309
- $postmeta['sale_price'] = get_post_meta( $post_id, '_sale_price', true );
310
- $postmeta['sale_price'] = $this->hf_currency_formatter($postmeta['sale_price']);
311
- }
312
-
313
- if ( isset( $postmeta['regular_price'] ) && isset( $postmeta['sale_price'] ) && $postmeta['sale_price'] !== '' ) {
314
- $postmeta['sale_price'] = $this->hf_currency_formatter($postmeta['sale_price']);
315
- $postmeta['regular_price'] = $this->hf_currency_formatter($postmeta['regular_price']);
316
- $price = min( $postmeta['sale_price'], $postmeta['regular_price']);
317
- $postmeta['price'] = $price;
318
- } elseif ( isset( $postmeta['regular_price'] ) ) {
319
- $postmeta['price'] = $this->hf_currency_formatter($postmeta['regular_price']);
320
- }
321
-
322
- // Reset dynamically generated meta
323
- $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'] = '';
324
- }
325
-
326
- // upsells
327
- if ( isset( $postmeta['upsell_ids'] ) && ! is_array( $postmeta['upsell_ids'] ) ) {
328
- $ids = array_filter( array_map( 'trim', explode( '|', $postmeta['upsell_ids'] ) ) );
329
- $postmeta['upsell_ids'] = $ids;
330
- }
331
-
332
- // crosssells
333
- if ( isset( $postmeta['crosssell_ids'] ) && ! is_array( $postmeta['crosssell_ids'] ) ) {
334
- $ids = array_filter( array_map( 'trim', explode( '|', $postmeta['crosssell_ids'] ) ) );
335
- $postmeta['crosssell_ids'] = $ids;
336
- }
337
-
338
- // Sale dates
339
- if ( isset( $postmeta['sale_price_dates_from'] ) ) {
340
- $postmeta['sale_price_dates_from'] = empty( $postmeta['sale_price_dates_from'] ) ? '' : strtotime( $postmeta['sale_price_dates_from'] );
341
- }
342
-
343
- if ( isset( $postmeta['sale_price_dates_to'] ) ) {
344
- $postmeta['sale_price_dates_to'] = empty( $postmeta['sale_price_dates_to'] ) ? '' : strtotime( $postmeta['sale_price_dates_to'] );
345
- }
346
-
347
- // Relative stock updates
348
- if ( $merging ) {
349
- if ( isset( $postmeta['stock'] ) ) {
350
-
351
- $postmeta['stock'] = trim( $postmeta['stock'] );
352
-
353
- $mode = substr( $postmeta['stock'], 0, 3 );
354
-
355
- if ( $mode == '(+)' ) {
356
- $old_stock = absint( get_post_meta( $post_id, '_stock', true ) );
357
- $amount = absint( substr( $postmeta['stock'], 3 ) );
358
- $new_stock = $old_stock + $amount;
359
- $postmeta['stock'] = $new_stock;
360
- }
361
-
362
- if ( $mode == '(-)' ) {
363
- $old_stock = absint( get_post_meta( $post_id, '_stock', true ) );
364
- $amount = absint( substr( $postmeta['stock'], 3 ) );
365
- $new_stock = $old_stock - $amount;
366
- $postmeta['stock'] = $new_stock;
367
- }
368
- }
369
- }
370
-
371
- // Format post status
372
- if ( ! empty( $product['post_status'] ) ) {
373
- $product['post_status'] = strtolower( $product['post_status'] );
374
-
375
- if ( empty($item['post_parent']) ) {
376
- if ( ! in_array( $product['post_status'], array( 'publish', 'private', 'draft', 'pending', 'future', 'inherit', 'trash' ) ) ) {
377
- $product['post_status'] = 'publish';
378
- }
379
- } else {
380
- if ( ! in_array( $product['post_status'], array( 'private', 'publish' ) ) ) {
381
- $product['post_status'] = 'publish';
382
- }
383
- }
384
- }
385
-
386
- // Put set core product postmeta into product array
387
- foreach ( $postmeta as $key => $value ) {
388
- $product['postmeta'][] = array( 'key' => '_' . esc_attr($key), 'value' => $value );
389
- }
390
-
391
- /**
392
- * Handle other columns
393
- */
394
- foreach ( $item as $key => $value ) {
395
-
396
- if ( empty($item['post_parent']) && ! $merge_empty_cells && $value == "" )
397
- continue;
398
-
399
- /**
400
- * File path handling
401
- */
402
- if ( $key == 'file_paths' || $key == 'downloadable_files' ) {
403
-
404
- $file_paths = explode( '|', $value );
405
- $_file_paths = array();
406
- foreach ( $file_paths as $file_path ) {
407
- // 2.1
408
- if ( function_exists( 'wc_get_filename_from_url' ) ) {
409
- $file_path = array_map( 'trim', explode( '::', $file_path ) );
410
- if ( sizeof( $file_path ) === 2 ) {
411
- $file_name = $file_path[0];
412
- $file_path = $file_path[1];
413
- } else {
414
- $file_name = wc_get_filename_from_url( $file_path[0] );
415
- $file_path = $file_path[0];
416
- }
417
- $_file_paths[ md5( $file_path ) ] = array(
418
- 'name' => $file_name,
419
- 'file' => $file_path
420
- );
421
- } else {
422
- $file_path = trim( $file_path );
423
- $_file_paths[ md5( $file_path ) ] = $file_path;
424
- }
425
- }
426
- $value = $_file_paths;
427
-
428
- $product['postmeta'][] = array( 'key' => '_' . esc_attr( $key ), 'value' => $value );
429
- }
430
-
431
- elseif ( strstr( $key, 'tax:' ) ) {
432
-
433
- // Get taxonomy
434
- $taxonomy = trim( str_replace( 'tax:', '', $key ) );
435
-
436
- // Exists?
437
- if ( ! taxonomy_exists( $taxonomy ) ) {
438
- $WF_CSV_Product_Import->hf_log_data_change( 'csv-import', sprintf( __('> > Skipping taxonomy "%s" - it does not exist.', 'wf_csv_import_export'), $taxonomy ) );
439
- continue;
440
- }
441
-
442
- // Product type check
443
- if ( $taxonomy == 'product_type' ) {
444
- $term = strtolower( $value );
445
-
446
- if ( ! array_key_exists( $term, $this->allowed_product_types ) ) {
447
- $WF_CSV_Product_Import->hf_log_data_change( 'csv-import', sprintf( __('> > > Product type "%s" not allowed - using simple.', 'wf_csv_import_export'), $term ) );
448
- $term_id = $this->allowed_product_types['simple'];
449
- } else {
450
- $term_id = $this->allowed_product_types[ $term ];
451
- }
452
-
453
- // Add to array
454
- $terms_array[] = array(
455
- 'taxonomy' => $taxonomy,
456
- 'terms' => array( $term_id )
457
- );
458
-
459
- continue;
460
- }
461
-
462
- // Get terms - ID => parent
463
- $terms = array();
464
- $raw_terms = explode( '|', $value );
465
- $raw_terms = array_map( 'trim', $raw_terms );
466
-
467
- // Handle term hierachy (>)
468
- foreach ( $raw_terms as $raw_term ) {
469
-
470
- if ( strstr( $raw_term, '>' ) ) {
471
-
472
- $raw_term = explode( '>', $raw_term );
473
- $raw_term = array_map( 'trim', $raw_term );
474
-
475
- if(WC()->version < '2.7.0')
476
- {
477
- $raw_term = array_map( 'wp_specialchars', $raw_term );
478
- $raw_term = array_filter( $raw_term );
479
-
480
- }
481
- else
482
- {
483
- $raw_term = array_map( 'esc_html', $raw_term );
484
- $raw_term = array_filter( $raw_term );
485
-
486
- }
487
-
488
- $parent = 0;
489
- $loop = 0;
490
-
491
- foreach ( $raw_term as $term ) {
492
- $loop ++;
493
- $term_id = '';
494
-
495
- if ( isset( $this->inserted_terms[ $taxonomy ][ $parent ][ $term ] ) ) {
496
- $term_id = $this->inserted_terms[ $taxonomy ][ $parent ][ $term ];
497
- } elseif ( $term ) {
498
-
499
- /**
500
- * Check term existance
501
- */
502
- $term_may_exist = term_exists( $term, $taxonomy, absint( $parent ) );
503
-
504
- $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 ) : '-' ) );
505
-
506
- if ( is_array( $term_may_exist ) ) {
507
- $possible_term = get_term( $term_may_exist['term_id'], 'product_cat' );
508
-
509
- if ( $possible_term->parent == $parent ) {
510
- $term_id = $term_may_exist['term_id'];
511
- }
512
- }
513
-
514
- if ( ! $term_id ) {
515
-
516
- // Create appropriate slug
517
- $slug = array();
518
-
519
- for ( $i = 0; $i < $loop; $i ++ )
520
- $slug[] = $raw_term[ $i ];
521
-
522
- $slug = sanitize_title( implode( '-', $slug ) );
523
-
524
- $t = wp_insert_term( $term, $taxonomy, array( 'parent' => $parent, 'slug' => $slug ) );
525
-
526
- if ( ! is_wp_error( $t ) ) {
527
- $term_id = $t['term_id'];
528
- } else {
529
- $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 ) ) );
530
- break;
531
- }
532
- }
533
-
534
- $this->inserted_terms[$taxonomy][$parent][$term] = $term_id;
535
-
536
- }
537
-
538
- if ( ! $term_id )
539
- break;
540
-
541
- // Add to product terms, ready to set if this is the final term
542
- if ( sizeof( $raw_term ) == $loop )
543
- $terms[] = $term_id;
544
-
545
- $parent = $term_id;
546
- }
547
-
548
- } else {
549
-
550
- $term_id = '';
551
- $raw_term = (WC()->version < '2.7.0') ? wp_specialchars( $raw_term ) : esc_html( $raw_term );
552
-
553
- if ( isset( $this->inserted_terms[$taxonomy][0][$raw_term] ) ) {
554
-
555
- $term_id = $this->inserted_terms[$taxonomy][0][$raw_term];
556
-
557
- } elseif ( $raw_term ) {
558
-
559
- // Check term existance
560
- $term_exists = term_exists( $raw_term, $taxonomy, 0 );
561
- $term_id = is_array( $term_exists ) ? $term_exists['term_id'] : 0;
562
-
563
- if ( ! $term_id ) {
564
- $t = wp_insert_term( trim( $raw_term ), $taxonomy, array( 'parent' => 0 ) );
565
-
566
- if ( ! is_wp_error( $t ) ) {
567
- $term_id = $t['term_id'];
568
- } else {
569
- $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) ) );
570
- break;
571
- }
572
- }
573
-
574
- $this->inserted_terms[$taxonomy][0][$raw_term] = $term_id;
575
-
576
- }
577
-
578
- // Store terms for later insertion
579
- if ( $term_id )
580
- $terms[] = $term_id;
581
-
582
- }
583
-
584
- }
585
-
586
- // Any defined?
587
- if ( sizeof( $terms ) == 0 )
588
- continue;
589
-
590
- // Add to array
591
- $terms_array[] = array(
592
- 'taxonomy' => $taxonomy,
593
- 'terms' => $terms
594
- );
595
- }
596
-
597
- /**
598
- * Handle Attributes
599
- */
600
- elseif ( strstr( $key, 'attribute:' ) ) {
601
-
602
- $attribute_key = sanitize_title( trim( str_replace( 'attribute:', '', $key ) ) );
603
- $attribute_name = str_replace( 'attribute:', '', $WF_CSV_Product_Import->raw_headers[ $key ] );
604
-
605
- if ( ! $attribute_key )
606
- continue;
607
-
608
- // Taxonomy
609
- if ( substr( $attribute_key, 0, 3 ) == 'pa_' ) {
610
-
611
- $taxonomy = $attribute_key;
612
-
613
- // Exists?
614
- if ( ! taxonomy_exists( $taxonomy ) ) {
615
-
616
- $nicename = strtolower( sanitize_title( str_replace( 'pa_', '', $taxonomy ) ) );
617
-
618
- $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 ) );
619
-
620
- $exists_in_db = $wpdb->get_var( "SELECT attribute_id FROM " . $wpdb->prefix . "woocommerce_attribute_taxonomies WHERE attribute_name = '" . $nicename . "';" );
621
-
622
- if ( ! $exists_in_db ) {
623
- // Create the taxonomy
624
- $wpdb->insert( $wpdb->prefix . "woocommerce_attribute_taxonomies", array( 'attribute_name' => $nicename, 'attribute_label' => $nicename, 'attribute_type' => 'select', 'attribute_orderby' => 'menu_order' ) );
625
- } else {
626
- $WF_CSV_Product_Import->hf_log_data_change( 'csv-import', sprintf( __('> > Attribute taxonomy %s already exists in DB.', 'wf_csv_import_export'), $taxonomy ) );
627
- }
628
-
629
- // Register the taxonomy now so that the import works!
630
- register_taxonomy( $taxonomy,
631
- array( 'product', 'product_variation' ),
632
- array(
633
- 'hierarchical' => true,
634
- 'show_ui' => false,
635
- 'query_var' => true,
636
- 'rewrite' => false,
637
- )
638
- );
639
- }
640
-
641
- // Get terms
642
- $terms = array();
643
- $raw_terms = explode( '|', $value );
644
- if(WC()->version < '2.7.0')
645
- {
646
- $raw_terms = array_map( 'wp_specialchars', $raw_terms );
647
- $raw_terms = array_map( 'trim', $raw_terms );
648
-
649
- }else{
650
-
651
- $raw_terms = array_map( 'esc_html', $raw_terms );
652
- $raw_terms = array_map( 'trim', $raw_terms );
653
-
654
- }
655
-
656
- if ( sizeof( $raw_terms ) > 0 ) {
657
-
658
- foreach ( $raw_terms as $raw_term ) {
659
-
660
- if ( empty( $raw_term ) && 0 != $raw_term ) {
661
- continue;
662
- }
663
-
664
- // Check term existance
665
- $term_exists = term_exists( $raw_term, $taxonomy, 0 );
666
- $term_id = is_array( $term_exists ) ? $term_exists['term_id'] : 0;
667
-
668
- if ( ! $term_id ) {
669
- $t = wp_insert_term( trim( $raw_term ), $taxonomy );
670
-
671
- if ( ! is_wp_error( $t ) ) {
672
- $term_id = $t['term_id'];
673
-
674
- $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 ) );
675
- } else {
676
- $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) ) );
677
- break;
678
- }
679
- } else {
680
- $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 ) );
681
- }
682
-
683
- if ( $term_id ) {
684
- $terms[] = $term_id;
685
- }
686
- }
687
-
688
- }
689
-
690
- // Add to array
691
- $terms_array[] = array(
692
- 'taxonomy' => $taxonomy,
693
- 'terms' => $terms
694
- );
695
-
696
- // Ensure we have original attributes
697
- if ( is_null( $attributes ) && $merging ) {
698
- $attributes = array_filter( (array) maybe_unserialize( get_post_meta( $post_id, '_product_attributes', true ) ) );
699
- } elseif ( is_null( $attributes ) ) {
700
- $attributes = array();
701
- }
702
-
703
- // Set attribute
704
- if ( ! isset( $attributes[$taxonomy] ) )
705
- $attributes[$taxonomy] = array();
706
-
707
- $attributes[$taxonomy]['name'] = $taxonomy;
708
- $attributes[$taxonomy]['value'] = null;
709
- $attributes[$taxonomy]['is_taxonomy'] = 1;
710
-
711
- if ( ! isset( $attributes[$taxonomy]['position'] ) )
712
- $attributes[$taxonomy]['position'] = 0;
713
- if ( ! isset( $attributes[$taxonomy]['is_visible'] ) )
714
- $attributes[$taxonomy]['is_visible'] = 1;
715
- if ( ! isset( $attributes[$taxonomy]['is_variation'] ) )
716
- $attributes[$taxonomy]['is_variation'] = 0;
717
-
718
- } else {
719
-
720
- if ( ! $value || ! $attribute_key ) continue;
721
-
722
- // Set attribute
723
- if ( ! isset( $attributes[$attribute_key] ) )
724
- $attributes[$attribute_key] = array();
725
-
726
- $attributes[$attribute_key]['name'] = $attribute_name;
727
- $attributes[$attribute_key]['value'] = $value;
728
- $attributes[$attribute_key]['is_taxonomy'] = 0;
729
-
730
- if ( ! isset( $attributes[$attribute_key]['position'] ) )
731
- $attributes[$attribute_key]['position'] = 0;
732
- if ( ! isset( $attributes[$attribute_key]['is_visible'] ) )
733
- $attributes[$attribute_key]['is_visible'] = 1;
734
- if ( ! isset( $attributes[$attribute_key]['is_variation'] ) )
735
- $attributes[$attribute_key]['is_variation'] = 0;
736
- }
737
-
738
- }
739
-
740
- /**
741
- * Handle Attributes Data - position|is_visible|is_variation
742
- */
743
- elseif ( strstr( $key, 'attribute_data:' ) ) {
744
-
745
- $attribute_key = sanitize_title( trim( str_replace( 'attribute_data:', '', $key ) ) );
746
-
747
- if ( ! $attribute_key ) {
748
- continue;
749
- }
750
-
751
- $values = explode( '|', $value );
752
- $position = isset( $values[0] ) ? (int) $values[0] : 0;
753
- $visible = isset( $values[1] ) ? (int) $values[1] : 1;
754
- $variation = isset( $values[2] ) ? (int) $values[2] : 0;
755
-
756
- // Ensure we have original attributes
757
- if ( ! isset( $attributes[ $attribute_key ] ) ) {
758
- if ( $merging ) {
759
- $existing_attributes = array_filter( (array) maybe_unserialize( get_post_meta( $post_id, '_product_attributes', true ) ) );
760
- $attributes[ $attribute_key ] = isset( $existing_attributes[ $attribute_key ] ) ? $existing_attributes[ $attribute_key ] : array();
761
- } else {
762
- $attributes[ $attribute_key ] = array();
763
- }
764
- }
765
-
766
- $attributes[ $attribute_key ]['position'] = $position;
767
- $attributes[ $attribute_key ]['is_visible'] = $visible;
768
- $attributes[ $attribute_key ]['is_variation'] = $variation;
769
- }
770
-
771
- /**
772
- * Handle Attributes Default Values
773
- */
774
- elseif ( strstr( $key, 'attribute_default:' ) ) {
775
-
776
- $attribute_key = sanitize_title( trim( str_replace( 'attribute_default:', '', $key ) ) );
777
-
778
- if ( ! $attribute_key ) continue;
779
-
780
- // Ensure we have original attributes
781
- if ( is_null( $default_attributes ) && $merging ) {
782
- $default_attributes = array_filter( (array) maybe_unserialize( get_post_meta( $post_id, '_default_attributes', true ) ) );
783
- } elseif ( is_null( $default_attributes ) ) {
784
- $default_attributes = array();
785
- }
786
-
787
- $default_attributes[ $attribute_key ] = $value;
788
- }
789
-
790
- /**
791
- * Handle gpf: google product feed columns
792
- */
793
- elseif ( strstr( $key, 'gpf:' ) ) {
794
-
795
- $gpf_key = trim( str_replace( 'gpf:', '', $key ) );
796
-
797
- // Get original values
798
- if ( is_null( $gpf_data ) && $merging ) {
799
- $gpf_data = array_filter( (array) maybe_unserialize( get_post_meta( $post_id, '_woocommerce_gpf_data', true ) ) );
800
- } elseif ( is_null( $gpf_data ) ) {
801
- $gpf_data = array(
802
- 'availability' => '',
803
- 'condition' => '',
804
- 'brand' => '',
805
- 'product_type' => '',
806
- 'google_product_category' => '',
807
- 'gtin' => '',
808
- 'mpn' => '',
809
- 'gender' => '',
810
- 'age_group' => '',
811
- 'color' => '',
812
- 'size' => ''
813
- );
814
- }
815
-
816
- $gpf_data[$gpf_key] = $value;
817
-
818
- }
819
-
820
- /**
821
- * Handle upsell SKUs which we cannot assign until we get IDs later on
822
- */
823
- elseif ( strstr( $key, 'upsell_skus' ) ) {
824
- if ( $value ) {
825
- $skus = array_filter( array_map( 'trim', explode( '|', $value ) ) );
826
- $product['upsell_skus'] = $skus;
827
- }
828
- }
829
-
830
- /**
831
- * Handle crosssells SKUs which we cannot assign until we get IDs later on
832
- */
833
- elseif ( strstr( $key, 'crosssell_skus' ) ) {
834
- if ( $value ) {
835
- $skus = array_filter( array_map( 'trim', explode( '|', $value ) ) );
836
- $product['crosssell_skus'] = $skus;
837
- }
838
- }
839
-
840
- }
841
-
842
- // Remove empty attribues
843
- if(!empty($attributes))
844
- foreach ( $attributes as $key => $value ) {
845
- if ( ! isset($value['name']) ) unset( $attributes[$key] );
846
- }
847
-
848
- /**
849
- * Handle images
850
- */
851
- if ( ! empty( $item['images'] ) ) {
852
- $images = array_map( 'trim', explode( '|', $item['images'] ) );
853
- } else {
854
- $images = '';
855
- }
856
-
857
- $product['postmeta'][] = array( 'key' => '_default_attributes', 'value' => $default_attributes );
858
- $product['attributes'] = $attributes;
859
- $product['gpf_data'] = $gpf_data;
860
- $product['images'] = $images;
861
- $product['terms'] = $terms_array;
862
- $product['sku'] = ( ! empty( $item['sku'] ) ) ? $item['sku'] : '';
863
- $product['post_title'] = ( ! empty( $item['post_title'] ) ) ? $item['post_title'] : '';
864
- $product['post_type'] = $this->post_type;
865
- unset( $item, $terms_array, $postmeta, $attributes, $gpf_data, $images );
866
- return $product;
867
- }
868
- function hf_currency_formatter($price){
869
- $decimal_seperator = wc_get_price_decimal_separator();
870
- //return ereg_replace("[^0-9\\'.$decimal_seperator.']", "", $price);
871
- return preg_replace("[^0-9\\'.$decimal_seperator.']", "", $price);
872
- }
873
- }
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
+ $this->post_type = $post_type;
20
+ $this->reserved_fields = include( 'data/data-wf-reserved-fields.php' );
21
+ $this->post_defaults = include( 'data/data-wf-post-defaults.php' );
22
+ $this->postmeta_defaults = include( 'data/data-wf-postmeta-defaults.php' );
23
+ $this->postmeta_allowed = include( 'data/data-wf-postmeta-allowed.php' );
24
+
25
+ $simple_term = get_term_by( 'slug', 'simple', 'product_type' );
26
+ $variable_term = get_term_by( 'slug', 'variable', 'product_type' );
27
+ $grouped_term = get_term_by( 'slug', 'grouped', 'product_type' );
28
+ $external_term = get_term_by( 'slug', 'external', 'product_type' );
29
+
30
+ $this->allowed_product_types = array(
31
+ 'simple' => $simple_term->term_id,
32
+ 'variable' => $variable_term->term_id,
33
+ 'grouped' => $grouped_term->term_id,
34
+ 'external' => $external_term->term_id
35
+ );
36
+
37
+ }
38
+
39
+ /**
40
+ * Format data from the csv file
41
+ * @param string $data
42
+ * @param string $enc
43
+ * @return string
44
+ */
45
+ public function format_data_from_csv( $data, $enc ) {
46
+ return ( $enc == 'UTF-8' ) ? $data : utf8_encode( $data );
47
+ }
48
+
49
+ /**
50
+ * Parse the data
51
+ * @param string $file [description]
52
+ * @param string $delimiter [description]
53
+ * @param array $mapping [description]
54
+ * @param integer $start_pos [description]
55
+ * @param integer $end_pos [description]
56
+ * @return array
57
+ */
58
+ public function parse_data( $file, $delimiter, $mapping, $start_pos = 0, $end_pos = null, $eval_field ) {
59
+ // Set locale
60
+ $enc = mb_detect_encoding( $file, 'UTF-8, ISO-8859-1', true );
61
+ if ( $enc )
62
+ setlocale( LC_ALL, 'en_US.' . $enc );
63
+ @ini_set( 'auto_detect_line_endings', true );
64
+
65
+ $parsed_data = array();
66
+ $raw_headers = array();
67
+
68
+ // Put all CSV data into an associative array
69
+ if ( ( $handle = fopen( $file, "r" ) ) !== FALSE ) {
70
+
71
+ $header = fgetcsv( $handle, 0, $delimiter );
72
+ if ( $start_pos != 0 )
73
+ fseek( $handle, $start_pos );
74
+
75
+ while ( ( $postmeta = fgetcsv( $handle, 0, $delimiter ) ) !== FALSE ) {
76
+ $row = array();
77
+
78
+ foreach ( $header as $key => $heading ) {
79
+ // Heading is the lowercase version of the column name
80
+ $s_heading = strtolower( $heading );
81
+
82
+ // Check if this heading is being mapped to a different field
83
+ if ( isset( $mapping[$s_heading] ) ) {
84
+ if ( $mapping[$s_heading] == 'import_as_meta' ) {
85
+
86
+ $s_heading = 'meta:' . $s_heading;
87
+
88
+ } elseif ( $mapping[$s_heading] == 'import_as_images' ) {
89
+
90
+ $s_heading = 'images';
91
+
92
+ } else {
93
+ $s_heading = esc_attr( $mapping[$s_heading] );
94
+ }
95
+ }
96
+ if( !empty($mapping) )
97
+ {
98
+ foreach ($mapping as $mkey => $mvalue) {
99
+ if(trim($mvalue) === trim($heading)){
100
+ $s_heading = $mkey;
101
+ }
102
+ }
103
+ }
104
+
105
+ if ( $s_heading == '' )
106
+ continue;
107
+
108
+ // Add the heading to the parsed data
109
+ $row[$s_heading] = ( isset( $postmeta[$key] ) ) ? $this->format_data_from_csv( $postmeta[$key], $enc ) : '';
110
+
111
+ if(!empty($eval_field[strtolower( $heading )]))
112
+ $row[$s_heading] = $this->evaluate_field($row[$s_heading], $eval_field[strtolower( $heading )]);
113
+
114
+ // Raw Headers stores the actual column name in the CSV
115
+ $raw_headers[ $s_heading ] = $heading;
116
+ }
117
+ $parsed_data[] = $row;
118
+
119
+ unset( $postmeta, $row );
120
+
121
+ $position = ftell( $handle );
122
+
123
+ if ( $end_pos && $position >= $end_pos )
124
+ break;
125
+ }
126
+ fclose( $handle );
127
+ }
128
+ return array( $parsed_data, $raw_headers, $position );
129
+ }
130
+
131
+ private function evaluate_field($value, $evaluation_field){
132
+ //echo "value:$value, $evaluation_field </br>";
133
+ $processed_value = $value;
134
+ if(!empty($evaluation_field)){
135
+ $operator = substr($evaluation_field, 0, 1);
136
+ if(in_array($operator, array('=', '+', '-', '*', '/', '&'))){
137
+ $eval_val = substr($evaluation_field, 1);
138
+ //echo "operator:$operator";
139
+ switch($operator){
140
+ case '=':
141
+ $processed_value = trim($eval_val);
142
+ break;
143
+ case '+':
144
+ $processed_value = $value + $eval_val;
145
+ break;
146
+ case '-':
147
+ $processed_value = $value - $eval_val;
148
+ break;
149
+ case '*':
150
+ $processed_value = $value * $eval_val;
151
+ break;
152
+ case '/':
153
+ $processed_value = $value / $eval_val;
154
+ break;
155
+ case '&':
156
+ if (strpos($eval_val, '[VAL]') !== false) {
157
+ $processed_value = str_replace('[VAL]',$value,$eval_val);
158
+ }
159
+ else{
160
+ $processed_value = $value . $eval_val;
161
+ }
162
+ break;
163
+ }
164
+ }
165
+ }
166
+ return $processed_value;
167
+ }
168
+
169
+ /**
170
+ * Parse product
171
+ * @param array $item
172
+ * @param integer $merge_empty_cells
173
+ * @return array
174
+ */
175
+ public function parse_product( $item, $merge_empty_cells = 0 ) {
176
+ global $WF_CSV_Product_Import, $wpdb;
177
+ $this->row++;
178
+
179
+ $terms_array = $postmeta = $product = array();
180
+ $attributes = $default_attributes = $gpf_data = null;
181
+
182
+ // Merging
183
+ $merging = ( ! empty( $_GET['merge'] ) && $_GET['merge'] ) ? true : false;
184
+ //if($item['post_parent']!== '' && $item['parent_sku'] !== ''){
185
+
186
+ $this->post_defaults['post_type'] = 'product';
187
+ $this->post_type = 'product';
188
+ // Post ID field mapping
189
+ $post_id = ( ! empty( $item['id'] ) ) ? $item['id'] : 0;
190
+ $post_id = ( ! empty( $item['post_id'] ) ) ? $item['post_id'] : $post_id;
191
+ if ( $merging ) {
192
+
193
+ $product['merging'] = true;
194
+
195
+
196
+ $WF_CSV_Product_Import->hf_log_data_change( 'csv-import', sprintf( __('> Row %s - preparing for merge.', 'wf_csv_import_export'), $this->row ) );
197
+
198
+ // Required fields
199
+ if ( ! $post_id && empty( $item['sku'] ) ) {
200
+
201
+ $WF_CSV_Product_Import->hf_log_data_change( 'csv-import', __( '> > Cannot merge without id or sku. Importing instead.', 'wf_csv_import_export') );
202
+
203
+ $merging = false;
204
+ } else {
205
+
206
+ // Check product exists
207
+ if ( ! $post_id ) {
208
+ // Check product to merge exists
209
+ $db_query = $wpdb->prepare("
210
+ SELECT $wpdb->posts.ID
211
+ FROM $wpdb->posts
212
+ LEFT JOIN $wpdb->postmeta ON ($wpdb->posts.ID = $wpdb->postmeta.post_id)
213
+ WHERE $wpdb->posts.post_type = 'product'
214
+ AND $wpdb->posts.post_status IN ( 'publish', 'private', 'draft', 'pending', 'future' )
215
+ AND $wpdb->postmeta.meta_key = '_sku' AND $wpdb->postmeta.meta_value = '%s'
216
+ ", $item['sku']);
217
+ $found_product_id = $wpdb->get_var($db_query);
218
+ if ( ! $found_product_id ) {
219
+ $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']) );
220
+ $merging = false;
221
+
222
+ } else {
223
+
224
+ $post_id = $found_product_id;
225
+
226
+ $WF_CSV_Product_Import->hf_log_data_change( 'csv-import', sprintf(__( '> > Found product with ID %s.', 'wf_csv_import_export'), $post_id) );
227
+
228
+ }
229
+ }
230
+ $product['merging'] = true;
231
+ }
232
+ }
233
+
234
+ if ( ! $merging ) {
235
+
236
+ $product['merging'] = false;
237
+ $WF_CSV_Product_Import->hf_log_data_change( 'csv-import', sprintf( __('> Row %s - preparing for import.', 'wf_csv_import_export'), $this->row ) );
238
+
239
+ // Required fields
240
+ if ( isset($item['post_parent']) && $item['post_parent']=== '' && $item['post_title']=== '') {
241
+ $WF_CSV_Product_Import->hf_log_data_change( 'csv-import', __( '> > Skipped. No post_title set for new product.', 'wf_csv_import_export') );
242
+ return new WP_Error( 'parse-error', __( 'No post_title set for new product.', 'wf_csv_import_export' ) );
243
+ }
244
+ if ( !empty($item['post_parent']) && $item['post_parent']!== '' && $item['post_parent']!== null && $item['parent_sku'] === '' ) {
245
+ $WF_CSV_Product_Import->hf_log_data_change( 'csv-import', __( '> > Skipped. No parent set for new variation product.', 'wf_csv_import_export') );
246
+ //return new WP_Error( 'parse-error', __( 'No post_title set for new product.', 'wf_csv_import_export' ) );
247
+ return new WP_Error( 'parse-error', __( 'No parent set for new variation product.', 'wf_csv_import_export' ) );
248
+ }
249
+
250
+ }
251
+
252
+ $product['post_id'] = $post_id;
253
+
254
+
255
+ // Get post fields
256
+ foreach ( $this->post_defaults as $column => $default ) {
257
+ if ( isset( $item[ $column ] ) ) $product[ $column ] = $item[ $column ];
258
+ }
259
+
260
+ // Get custom fields
261
+ foreach ( $this->postmeta_defaults as $column => $default ) {
262
+ if ( isset( $item[$column] ) )
263
+ $postmeta[$column] = (string) $item[$column];
264
+ elseif ( isset( $item['_' . $column] ) )
265
+ $postmeta[$column] = (string) $item['_' . $column];
266
+
267
+ // Check custom fields are valid
268
+ if ( isset( $postmeta[$column] ) && isset( $this->postmeta_allowed[$column] ) && ! in_array( $postmeta[$column], $this->postmeta_allowed[$column] ) ) {
269
+ $postmeta[$column] = $this->postmeta_defaults[$column];
270
+ }
271
+ }
272
+
273
+ if ( ! $merging ) {
274
+ // Merge post meta with defaults
275
+ $product = wp_parse_args( $product, $this->post_defaults );
276
+ $postmeta = wp_parse_args( $postmeta, $this->postmeta_defaults );
277
+ }
278
+
279
+ // Handle special meta fields
280
+ if ( isset($item['post_parent']) ) {
281
+
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
+ } else {
302
+
303
+ // price
304
+ if ( $merging ) {
305
+ if ( ! isset( $postmeta['regular_price'] ) )
306
+ $postmeta['regular_price'] = get_post_meta( $post_id, '_regular_price', true );
307
+ $postmeta['regular_price'] = $this->hf_currency_formatter($postmeta['regular_price']);
308
+ if ( ! isset( $postmeta['sale_price'] ) )
309
+ $postmeta['sale_price'] = get_post_meta( $post_id, '_sale_price', true );
310
+ $postmeta['sale_price'] = $this->hf_currency_formatter($postmeta['sale_price']);
311
+ }
312
+
313
+ if ( isset( $postmeta['regular_price'] ) && isset( $postmeta['sale_price'] ) && $postmeta['sale_price'] !== '' ) {
314
+ $postmeta['sale_price'] = $this->hf_currency_formatter($postmeta['sale_price']);
315
+ $postmeta['regular_price'] = $this->hf_currency_formatter($postmeta['regular_price']);
316
+ $price = min( $postmeta['sale_price'], $postmeta['regular_price']);
317
+ $postmeta['price'] = $price;
318
+ } elseif ( isset( $postmeta['regular_price'] ) ) {
319
+ $postmeta['price'] = $this->hf_currency_formatter($postmeta['regular_price']);
320
+ }
321
+
322
+ // Reset dynamically generated meta
323
+ $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'] = '';
324
+ }
325
+
326
+ // upsells
327
+ if ( isset( $postmeta['upsell_ids'] ) && ! is_array( $postmeta['upsell_ids'] ) ) {
328
+ $ids = array_filter( array_map( 'trim', explode( '|', $postmeta['upsell_ids'] ) ) );
329
+ $postmeta['upsell_ids'] = $ids;
330
+ }
331
+
332
+ // crosssells
333
+ if ( isset( $postmeta['crosssell_ids'] ) && ! is_array( $postmeta['crosssell_ids'] ) ) {
334
+ $ids = array_filter( array_map( 'trim', explode( '|', $postmeta['crosssell_ids'] ) ) );
335
+ $postmeta['crosssell_ids'] = $ids;
336
+ }
337
+
338
+ // Sale dates
339
+ if ( isset( $postmeta['sale_price_dates_from'] ) ) {
340
+ $postmeta['sale_price_dates_from'] = empty( $postmeta['sale_price_dates_from'] ) ? '' : strtotime( $postmeta['sale_price_dates_from'] );
341
+ }
342
+
343
+ if ( isset( $postmeta['sale_price_dates_to'] ) ) {
344
+ $postmeta['sale_price_dates_to'] = empty( $postmeta['sale_price_dates_to'] ) ? '' : strtotime( $postmeta['sale_price_dates_to'] );
345
+ }
346
+
347
+ // Relative stock updates
348
+ if ( $merging ) {
349
+ if ( isset( $postmeta['stock'] ) ) {
350
+
351
+ $postmeta['stock'] = trim( $postmeta['stock'] );
352
+
353
+ $mode = substr( $postmeta['stock'], 0, 3 );
354
+
355
+ if ( $mode == '(+)' ) {
356
+ $old_stock = absint( get_post_meta( $post_id, '_stock', true ) );
357
+ $amount = absint( substr( $postmeta['stock'], 3 ) );
358
+ $new_stock = $old_stock + $amount;
359
+ $postmeta['stock'] = $new_stock;
360
+ }
361
+
362
+ if ( $mode == '(-)' ) {
363
+ $old_stock = absint( get_post_meta( $post_id, '_stock', true ) );
364
+ $amount = absint( substr( $postmeta['stock'], 3 ) );
365
+ $new_stock = $old_stock - $amount;
366
+ $postmeta['stock'] = $new_stock;
367
+ }
368
+ }
369
+ }
370
+
371
+ // Format post status
372
+ if ( ! empty( $product['post_status'] ) ) {
373
+ $product['post_status'] = strtolower( $product['post_status'] );
374
+
375
+ if ( empty($item['post_parent']) ) {
376
+ if ( ! in_array( $product['post_status'], array( 'publish', 'private', 'draft', 'pending', 'future', 'inherit', 'trash' ) ) ) {
377
+ $product['post_status'] = 'publish';
378
+ }
379
+ } else {
380
+ if ( ! in_array( $product['post_status'], array( 'private', 'publish' ) ) ) {
381
+ $product['post_status'] = 'publish';
382
+ }
383
+ }
384
+ }
385
+
386
+ // Put set core product postmeta into product array
387
+ foreach ( $postmeta as $key => $value ) {
388
+ $product['postmeta'][] = array( 'key' => '_' . esc_attr($key), 'value' => $value );
389
+ }
390
+
391
+ /**
392
+ * Handle other columns
393
+ */
394
+ foreach ( $item as $key => $value ) {
395
+
396
+ if ( empty($item['post_parent']) && ! $merge_empty_cells && $value == "" )
397
+ continue;
398
+
399
+ /**
400
+ * File path handling
401
+ */
402
+ if ( $key == 'file_paths' || $key == 'downloadable_files' ) {
403
+
404
+ $file_paths = explode( '|', $value );
405
+ $_file_paths = array();
406
+ foreach ( $file_paths as $file_path ) {
407
+ // 2.1
408
+ if ( function_exists( 'wc_get_filename_from_url' ) ) {
409
+ $file_path = array_map( 'trim', explode( '::', $file_path ) );
410
+ if ( sizeof( $file_path ) === 2 ) {
411
+ $file_name = $file_path[0];
412
+ $file_path = $file_path[1];
413
+ } else {
414
+ $file_name = wc_get_filename_from_url( $file_path[0] );
415
+ $file_path = $file_path[0];
416
+ }
417
+ $_file_paths[ md5( $file_path ) ] = array(
418
+ 'name' => $file_name,
419
+ 'file' => $file_path
420
+ );
421
+ } else {
422
+ $file_path = trim( $file_path );
423
+ $_file_paths[ md5( $file_path ) ] = $file_path;<