Product Import Export for WooCommerce - Version 1.3.8

Version Description

  • BugFix: Product not importing at 100n. n=1,2...
Download this release

Release Info

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

Code changes from version 1.3.7 to 1.3.8

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