Merge pull request #23255 from woocommerce/shopify-column-mapping

Mapping for default Shopify fields
This commit is contained in:
Claudio Sanches 2019-07-08 18:53:57 -03:00 committed by GitHub
commit 55692cba87
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 173 additions and 9 deletions

View File

@ -157,6 +157,9 @@ class WC_Product_CSV_Importer_Controller {
$this->map_preferences = isset( $_REQUEST['map_preferences'] ) ? (bool) $_REQUEST['map_preferences'] : false; $this->map_preferences = isset( $_REQUEST['map_preferences'] ) ? (bool) $_REQUEST['map_preferences'] : false;
// phpcs:enable // phpcs:enable
// Import mappings for CSV data.
include_once dirname( __FILE__ ) . '/mappings/mappings.php';
if ( $this->map_preferences ) { if ( $this->map_preferences ) {
add_filter( 'woocommerce_csv_product_import_mapped_columns', array( $this, 'auto_map_user_preferences' ), 9999 ); add_filter( 'woocommerce_csv_product_import_mapped_columns', array( $this, 'auto_map_user_preferences' ), 9999 );
} }
@ -488,8 +491,6 @@ class WC_Product_CSV_Importer_Controller {
$weight_unit = get_option( 'woocommerce_weight_unit' ); $weight_unit = get_option( 'woocommerce_weight_unit' );
$dimension_unit = get_option( 'woocommerce_dimension_unit' ); $dimension_unit = get_option( 'woocommerce_dimension_unit' );
include dirname( __FILE__ ) . '/mappings/mappings.php';
/* /*
* @hooked wc_importer_generic_mappings - 10 * @hooked wc_importer_generic_mappings - 10
* @hooked wc_importer_wordpress_mappings - 10 * @hooked wc_importer_wordpress_mappings - 10
@ -542,7 +543,8 @@ class WC_Product_CSV_Importer_Controller {
__( 'External URL', 'woocommerce' ) => 'product_url', __( 'External URL', 'woocommerce' ) => 'product_url',
__( 'Button text', 'woocommerce' ) => 'button_text', __( 'Button text', 'woocommerce' ) => 'button_text',
__( 'Position', 'woocommerce' ) => 'menu_order', __( 'Position', 'woocommerce' ) => 'menu_order',
) ),
$raw_headers
) )
); );
@ -567,7 +569,8 @@ class WC_Product_CSV_Importer_Controller {
__( 'Download %d URL', 'woocommerce' ) => 'downloads:url', __( 'Download %d URL', 'woocommerce' ) => 'downloads:url',
/* translators: %d: Meta number */ /* translators: %d: Meta number */
__( 'Meta: %s', 'woocommerce' ) => 'meta:', __( 'Meta: %s', 'woocommerce' ) => 'meta:',
) ),
$raw_headers
) )
) )
); );
@ -697,7 +700,8 @@ class WC_Product_CSV_Importer_Controller {
), ),
), ),
'category_ids' => __( 'Categories', 'woocommerce' ), 'category_ids' => __( 'Categories', 'woocommerce' ),
'tag_ids' => __( 'Tags', 'woocommerce' ), 'tag_ids' => __( 'Tags (comma separated)', 'woocommerce' ),
'tag_ids_spaces' => __( 'Tags (space separated)', 'woocommerce' ),
'shipping_class_id' => __( 'Shipping class', 'woocommerce' ), 'shipping_class_id' => __( 'Shipping class', 'woocommerce' ),
'images' => __( 'Images', 'woocommerce' ), 'images' => __( 'Images', 'woocommerce' ),
'parent_id' => __( 'Parent', 'woocommerce' ), 'parent_id' => __( 'Parent', 'woocommerce' ),
@ -732,7 +736,7 @@ class WC_Product_CSV_Importer_Controller {
), ),
'reviews_allowed' => __( 'Allow customer reviews?', 'woocommerce' ), 'reviews_allowed' => __( 'Allow customer reviews?', 'woocommerce' ),
'purchase_note' => __( 'Purchase note', 'woocommerce' ), 'purchase_note' => __( 'Purchase note', 'woocommerce' ),
'meta:' . $meta => __( 'Import as meta', 'woocommerce' ), 'meta:' . $meta => __( 'Import as meta data', 'woocommerce' ),
'menu_order' => __( 'Position', 'woocommerce' ), 'menu_order' => __( 'Position', 'woocommerce' ),
); );

View File

@ -11,4 +11,5 @@ if ( ! defined( 'ABSPATH' ) ) {
require dirname( __FILE__ ) . '/default.php'; require dirname( __FILE__ ) . '/default.php';
require dirname( __FILE__ ) . '/generic.php'; require dirname( __FILE__ ) . '/generic.php';
require dirname( __FILE__ ) . '/shopify.php';
require dirname( __FILE__ ) . '/wordpress.php'; require dirname( __FILE__ ) . '/wordpress.php';

View File

@ -0,0 +1,90 @@
<?php
/**
* Shopify mappings
*
* @package WooCommerce\Admin\Importers
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Add Shopify mappings.
*
* @since 3.7.0
* @param array $mappings Importer columns mappings.
* @param array $raw_headers Raw headers from CSV being imported.
* @return array
*/
function wc_importer_shopify_mappings( $mappings, $raw_headers ) {
// Only map if this is looks like a Shopify export.
if ( 0 !== count( array_diff( array( 'Title', 'Body (HTML)', 'Type', 'Variant SKU' ), $raw_headers ) ) ) {
return $mappings;
}
$shopify_mappings = array(
'Variant SKU' => 'sku',
'Title' => 'name',
'Body (HTML)' => 'description',
'Quantity' => 'stock_quantity',
'Variant Inventory Qty' => 'stock_quantity',
'Image Src' => 'images',
'Variant Image' => 'images',
'Variant SKU' => 'sku',
'Variant Price' => 'sale_price',
'Variant Compare At Price' => 'regular_price',
'Type' => 'category_ids',
'Tags' => 'tag_ids_spaces',
'Variant Grams' => 'weight',
'Variant Requires Shipping' => 'meta:shopify_requires_shipping',
'Variant Taxable' => 'tax_status',
);
return array_merge( $mappings, $shopify_mappings );
}
add_filter( 'woocommerce_csv_product_import_mapping_default_columns', 'wc_importer_shopify_mappings', 10, 2 );
/**
* Add special wildcard Shopify mappings.
*
* @since 3.7.0
* @param array $mappings Importer columns mappings.
* @param array $raw_headers Raw headers from CSV being imported.
* @return array
*/
function wc_importer_shopify_special_mappings( $mappings, $raw_headers ) {
// Only map if this is looks like a Shopify export.
if ( 0 !== count( array_diff( array( 'Title', 'Body (HTML)', 'Type', 'Variant SKU' ), $raw_headers ) ) ) {
return $mappings;
}
$shopify_mappings = array(
'Option%d Name' => 'attributes:name',
'Option%d Value' => 'attributes:value',
);
return array_merge( $mappings, $shopify_mappings );
}
add_filter( 'woocommerce_csv_product_import_mapping_special_columns', 'wc_importer_shopify_special_mappings', 10, 2 );
/**
* Expand special Shopify columns to WC format.
*
* @since 3.7.0
* @param array $data Array of data.
* @return array Expanded data.
*/
function wc_importer_shopify_expand_data( $data ) {
if ( isset( $data['meta:shopify_requires_shipping'] ) ) {
$requires_shipping = wc_string_to_bool( $data['meta:shopify_requires_shipping'] );
if ( ! $requires_shipping ) {
if ( isset( $data['type'] ) ) {
$data['type'][] = 'virtual';
} else {
$data['type'] = array( 'virtual' );
}
}
unset( $data['meta:shopify_requires_shipping'] );
}
return $data;
}
add_filter( 'woocommerce_product_importer_pre_expand_data', 'wc_importer_shopify_expand_data' );

View File

@ -754,11 +754,12 @@ abstract class WC_Product_Importer implements WC_Importer_Interface {
* *
* @since 3.2.0 * @since 3.2.0
* @param string $value Value to explode. * @param string $value Value to explode.
* @param string $separator Separator separating each value. Defaults to comma.
* @return array * @return array
*/ */
protected function explode_values( $value ) { protected function explode_values( $value, $separator = ',' ) {
$value = str_replace( '\\,', '::separator::', $value ); $value = str_replace( '\\,', '::separator::', $value );
$values = explode( ',', $value ); $values = explode( $separator, $value );
$values = array_map( array( $this, 'explode_values_formatter' ), $values ); $values = array_map( array( $this, 'explode_values_formatter' ), $values );
return $values; return $values;

View File

@ -60,6 +60,9 @@ class WC_Product_CSV_Importer extends WC_Product_Importer {
$this->params['mapping'] = array_combine( $this->params['mapping']['from'], $this->params['mapping']['to'] ); $this->params['mapping'] = array_combine( $this->params['mapping']['from'], $this->params['mapping']['to'] );
} }
// Import mappings for CSV data.
include_once dirname( dirname( __FILE__ ) ) . '/admin/importers/mappings/mappings.php';
$this->read_file(); $this->read_file();
} }
@ -353,6 +356,28 @@ class WC_Product_CSV_Importer extends WC_Product_Importer {
return wc_stock_amount( $value ); return wc_stock_amount( $value );
} }
/**
* Parse the tax status field.
*
* @param string $value Field value.
*
* @return string
*/
public function parse_tax_status_field( $value ) {
if ( '' === $value ) {
return $value;
}
// Remove the ' prepended to fields that start with - if needed.
$value = $this->unescape_data( $value );
if ( 'true' === strtolower( $value ) || 'false' === strtolower( $value ) ) {
$value = wc_string_to_bool( $value ) ? 'taxable' : 'none';
}
return wc_clean( $value );
}
/** /**
* Parse a category field from a CSV. * Parse a category field from a CSV.
* Categories are separated by commas and subcategories are "parent > subcategory". * Categories are separated by commas and subcategories are "parent > subcategory".
@ -437,6 +462,37 @@ class WC_Product_CSV_Importer extends WC_Product_Importer {
return $tags; return $tags;
} }
/**
* Parse a tag field from a CSV with space separators.
*
* @param string $value Field value.
*
* @return array
*/
public function parse_tags_spaces_field( $value ) {
if ( empty( $value ) ) {
return array();
}
$value = $this->unescape_data( $value );
$names = $this->explode_values( $value, ' ' );
$tags = array();
foreach ( $names as $name ) {
$term = get_term_by( 'name', $name, 'product_tag' );
if ( ! $term || is_wp_error( $term ) ) {
$term = (object) wp_insert_term( $name, 'product_tag' );
}
if ( ! is_wp_error( $term ) ) {
$tags[] = $term->term_id;
}
}
return $tags;
}
/** /**
* Parse a shipping class field from a CSV. * Parse a shipping class field from a CSV.
* *
@ -653,6 +709,7 @@ class WC_Product_CSV_Importer extends WC_Product_Importer {
'stock_quantity' => array( $this, 'parse_stock_quantity_field' ), 'stock_quantity' => array( $this, 'parse_stock_quantity_field' ),
'category_ids' => array( $this, 'parse_categories_field' ), 'category_ids' => array( $this, 'parse_categories_field' ),
'tag_ids' => array( $this, 'parse_tags_field' ), 'tag_ids' => array( $this, 'parse_tags_field' ),
'tag_ids_spaces' => array( $this, 'parse_tags_spaces_field' ),
'shipping_class_id' => array( $this, 'parse_shipping_class_field' ), 'shipping_class_id' => array( $this, 'parse_shipping_class_field' ),
'images' => array( $this, 'parse_images_field' ), 'images' => array( $this, 'parse_images_field' ),
'parent_id' => array( $this, 'parse_relative_field' ), 'parent_id' => array( $this, 'parse_relative_field' ),
@ -663,6 +720,7 @@ class WC_Product_CSV_Importer extends WC_Product_Importer {
'download_expiry' => array( $this, 'parse_int_field' ), 'download_expiry' => array( $this, 'parse_int_field' ),
'product_url' => 'esc_url_raw', 'product_url' => 'esc_url_raw',
'menu_order' => 'intval', 'menu_order' => 'intval',
'tax_status' => array( $this, 'parse_tax_status_field' ),
); );
/** /**
@ -740,6 +798,10 @@ class WC_Product_CSV_Importer extends WC_Product_Importer {
// Convert type to string. // Convert type to string.
$data['type'] = current( array_diff( $data['type'], array( 'virtual', 'downloadable' ) ) ); $data['type'] = current( array_diff( $data['type'], array( 'virtual', 'downloadable' ) ) );
if ( ! $data['type'] ) {
$data['type'] = 'simple';
}
} }
// Status is mapped from a special published field. // Status is mapped from a special published field.
@ -778,6 +840,12 @@ class WC_Product_CSV_Importer extends WC_Product_Importer {
unset( $data['grouped_products'] ); unset( $data['grouped_products'] );
} }
// Tag ids.
if ( isset( $data['tag_ids_spaces'] ) ) {
$data['tag_ids'] = $data['tag_ids_spaces'];
unset( $data['tag_ids_spaces'] );
}
// Handle special column names which span multiple columns. // Handle special column names which span multiple columns.
$attributes = array(); $attributes = array();
$downloads = array(); $downloads = array();