From b4b85d1348c7d7a1b2280511ae7157cfc84cba2a Mon Sep 17 00:00:00 2001 From: James Collings Date: Thu, 16 Feb 2023 22:54:36 +0000 Subject: [PATCH] Release 2.2.0 --- README.md | 8 +- class/Exporter/Mapper/ProductMapper.php | 201 ++++++++++++++++++++++++ exporter.php | 31 ++++ samples/products.csv | 9 ++ woocommerce.php | 3 +- 5 files changed, 249 insertions(+), 3 deletions(-) create mode 100644 class/Exporter/Mapper/ProductMapper.php create mode 100644 exporter.php create mode 100644 samples/products.csv diff --git a/README.md b/README.md index d9671bc..501dcfe 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Requires Import WP: 2.5.0 -**Version: 2.1.2** +**Version: 2.2.0** ![WooCommerce Product Importer](./assets/iwp-addon-woocommerce.png) @@ -52,6 +52,10 @@ The WooCommerce Product Importer Addon can currently only be installed by downlo ## Changelog +### 2.2.0 + +- FIX - Update exporter to work with Import WP 2.7.0 + ### 2.1.2 -* Add - New Attribute "Used for variations" field. \ No newline at end of file +- Add - New Attribute "Used for variations" field. diff --git a/class/Exporter/Mapper/ProductMapper.php b/class/Exporter/Mapper/ProductMapper.php new file mode 100644 index 0000000..b3b89ff --- /dev/null +++ b/class/Exporter/Mapper/ProductMapper.php @@ -0,0 +1,201 @@ +post_type = $post_type; + } + + public function get_fields() + { + /** + * @var \WPDB $wpdb + */ + global $wpdb; + + $fields = parent::get_fields(); + + // Add sku to core field list + $fields['fields'][] = 'sku'; + + // product fields + $fields['children']['woocommerce'] = [ + 'key' => 'woocommerce', + 'label' => 'WooCommerce Product', + 'loop' => false, + 'fields' => [ + 'product_type' + ], + 'children' => [] + ]; + + // extra parent fields + $fields['children']['parent']['fields'][] = 'sku'; + + // TODO: Fetch all custom attributes + $custom_attribute_rows = $wpdb->get_col("SELECT DISTINCT meta_value FROM {$wpdb->postmeta} WHERE meta_key='_product_attributes' AND meta_value LIKE '%\"is_taxonomy\";i:0;%'"); + + $tmp = []; + if (!empty($custom_attribute_rows)) { + foreach ($custom_attribute_rows as $row) { + $data = maybe_unserialize($row); + foreach ($data as $attribute_id => $attribute_data) { + if ($attribute_data['is_taxonomy'] == 0 && !in_array($attribute_id, $tmp)) { + $tmp[] = $attribute_id; + } + } + } + } + + $fields['children']['product_attributes'] = [ + 'key' => 'product_attributes', + 'label' => 'Product Attributes', + 'loop' => false, + 'fields' => $tmp, + 'children' => [] + ]; + + // Linked Products + $fields['children']['linked_products'] = [ + 'key' => 'linked_products', + 'label' => 'Linked Products', + 'loop' => false, + 'fields' => [ + 'grouped::id', + 'grouped::name', + 'grouped::slug', + 'grouped::sku', + 'upsells::id', + 'upsells::name', + 'upsells::slug', + 'upsells::sku', + 'crosssells::id', + 'crosssells::name', + 'crosssells::slug', + 'crosssells::sku', + ], + 'children' => [] + ]; + + // Product Gallery + $fields['children']['product_gallery'] = [ + 'key' => 'product_gallery', + 'label' => 'Product Gallery', + 'loop' => false, + 'fields' => [ + 'id', 'url', 'title', 'alt', 'caption', 'description' + ], + 'children' => [] + ]; + + return $fields; + } + + + public function setup($i) + { + $is_setup = parent::setup($i); + + $product = wc_get_product($this->record['ID']); + + // product fields + $this->record['woocommerce'] = [ + 'product_type' => $product->get_type() + ]; + + // core product sku, added here to show in unique identifier field + $this->record['sku'] = $product->get_sku(); + + // extra parent fields + $this->record['parent']['sku'] = get_post_meta($this->record['parent']['id'], '_sku', true); + + // Product attributes + $this->record['product_attributes'] = []; + $attributes = $product->get_attributes(); + foreach ($attributes as $attribute_id => $attribute_data) { + + /** + * @var \WC_Product_Attribute|string $attribute_data + */ + + if ($attribute_data instanceof \WC_Product_Attribute) { + $this->record['product_attributes'][$attribute_id] = $attribute_data->get_options(); + } else { + $this->record['product_attributes'][$attribute_id] = $attribute_data; + } + } + + // Linked Products + $this->record['linked_products'] = []; + + if ($product->is_type('grouped')) { + $this->record['linked_products'] = array_merge( + $this->record['linked_products'], + $this->get_linked_product_data($product->get_children(), 'grouped') + ); + } + + $this->record['linked_products'] = array_merge( + $this->record['linked_products'], + $this->get_linked_product_data($product->get_upsell_ids(), 'upsells') + ); + + $this->record['linked_products'] = array_merge( + $this->record['linked_products'], + $this->get_linked_product_data($product->get_cross_sell_ids(), 'crosssells') + ); + + // Product Gallery + $gallery = $product->get_gallery_image_ids(); + $this->record['product_gallery'] = []; + + foreach ($gallery as $thumbnail_id) { + + $attachment = get_post($thumbnail_id, ARRAY_A); + $alt = get_post_meta($thumbnail_id, '_wp_attachment_image_alt', true); + + $this->record['product_gallery'][] = [ + 'id' => $thumbnail_id, + 'url' => wp_get_attachment_url($thumbnail_id), + 'title' => $attachment['post_title'], + 'alt' => $alt, + 'caption' => $attachment['post_excerpt'], + 'description' => $attachment['post_content'] + ]; + } + + return $is_setup; + } + + public function get_linked_product_data($ids, $prefix) + { + $tmp = [ + "{$prefix}::id" => [], + "{$prefix}::name" => [], + "{$prefix}::slug" => [], + "{$prefix}::sku" => [], + ]; + + if (!empty($ids)) { + foreach ($ids as $child_id) { + + $child = wc_get_product($child_id); + if (!$child) { + continue; + } + + $tmp["{$prefix}::id"][] = $child->get_id(); + $tmp["{$prefix}::name"][] = $child->get_name(); + $tmp["{$prefix}::slug"][] = $child->get_slug(); + $tmp["{$prefix}::sku"][] = $child->get_sku(); + } + } + + return $tmp; + } +} diff --git a/exporter.php b/exporter.php new file mode 100644 index 0000000..7dff63c --- /dev/null +++ b/exporter.php @@ -0,0 +1,31 @@ + 'woocommerce_product', + 'label' => 'WooCommerce Products', + 'fields' => $mapper->get_fields() + ]); + + return $fields; +}); + +/** + * Load ProductMapper when exporting data with the id: woocommerce_product. + */ +add_filter('iwp/exporter/load_mapper', function ($result, $type) { + + if ($type === 'woocommerce_product') { + return new ProductMapper(['product', 'product_variation']); + } + + return $result; +}, 10, 2); diff --git a/samples/products.csv b/samples/products.csv new file mode 100644 index 0000000..a7ed6f1 --- /dev/null +++ b/samples/products.csv @@ -0,0 +1,9 @@ +"Name"," Price"," SKU"," Product Type"," Grouped Products","Product Url","Parent","Colour",Images,Image Title,Tag,Categories +"Simple Product 1"," 10.99","simple-one","simple",,,,,"https://picsum.photos/id/1/550/500.webp, https://picsum.photos/id/9/550/500.webp","Image Title 1, Image Title 9",Simple,Products > Simple +"Simple Product 2","12.99","simple-two","simple",,,,,https://picsum.photos/id/2/550/500.webp,Image Title 2,Simple,Products > Simple +"Simple Product 3","14.99","simple-three","simple",,,,,https://picsum.photos/id/3/550/500.webp,Image Title 3,Simple,Products > Simple +"Grouped Product 1",,"group-one","grouped","simple-one, simple-two",,,,https://picsum.photos/id/4/550/500.webp,Image Title 4,Grouped,Products > Grouped +"External product 1","10.99","external-one","external",,"https://www.importwp.com/integrations/import-export-woocommerce-plugin/",,,https://picsum.photos/id/5/550/500.webp,Image Title 5,External,Products > External +"Variable Product 1",,"variable-one","variable",,,,"red,blue",https://picsum.photos/id/6/550/500.webp,Image Title 6,Variable,Products > Variable +"Product Variation 1","10.99","variation-one","variation",,,"variable-one","red",https://picsum.photos/id/7/550/500.webp,Image Title 7,, +"Product Variation 2","12.99","variation-two","variation",,,"variable-one","blue",https://picsum.photos/id/8/550/500.webp,Image Title 8,, \ No newline at end of file diff --git a/woocommerce.php b/woocommerce.php index 4b1d582..d12ccb2 100644 --- a/woocommerce.php +++ b/woocommerce.php @@ -5,7 +5,7 @@ * Plugin URI: https://www.importwp.com * Description: Allow Import WP to import WooCommerce Products. * Author: James Collings - * Version: 2.1.2 + * Version: 2.2.0 * Author URI: https://www.importwp.com * Network: True */ @@ -45,6 +45,7 @@ function iwp_woocommerce_setup() require_once $base_path . '/class/autoload.php'; require_once $base_path . '/setup.php'; + require_once $base_path . '/exporter.php'; // Install updater if (file_exists($base_path . '/updater.php') && !class_exists('IWP_Updater')) {