Search code examples
wordpresswoocommercee-commercehook-woocommercewpallimport

Woocommerce Product Bundle import via WP All Import


Trying to figure out how to import the woocommerce bundled products into Wordpress via WP ALL Import (http://www.wpallimport.com).

There is no native support when it comes to wpallimport for bundled products, only grouped products.

I have been reading over the API and functions documents for wp all import and feel I maybe able to do it via the import functions after saving a bundle.

I cant see any documentation on how to 1. using the feed data in the functions, wanted to confirm if that is possible 2. is it possible to reference the woocommerce functions, ie add_bundled_item_meta, and if so what would be the best method? https://docs.woocommerce.com/document/bundles/bundles-functions-reference/#add_bundled_item_meta 3. best methods to link up the feature image of one of the bundled products to the bundled product being updated

My coding is novice level, I learn by reverse engineering something. Excuse my lack of php knowledge

Woocommerce changed the way they handled bundles, so its no longer just an import field, but a separate table, found this stackoverflow thread but was as per the old functionality. https://docs.woocommerce.com/document/bundles/bundles-v5-0-whats-new/ Bulk import Product Bundles – WooCommerce?

Developer reference material https://docs.woocommerce.com/document/bundles/#developer-resources https://docs.woocommerce.com/document/bundles/bundles-functions-reference/#add_bundled_item_meta https://docs.woocommerce.com/document/bundles/bundles-rest-api-reference/

There is another dedicated Woocommerce bundle import plugin but its not wpallimport

https://www.webtoffee.com/woocommerce-import-and-export-of-bundle-products/

My thinking is to do something like this in the import function



add_action('pmxi_saved_post', 'update_bundle', 10, 1);

if ({product_type[1]} == 'product bundle'){
function update_bundle($id) 
{
// is it a product bundle test?
if ({product_type[1]} == 'product bundle'){

// Get products from import file (not sure if this is correct, but guessing it will be something like this)
$Bundle_product_1 = {Bundle_product_1[1]};
$Bundle_product_2 = {Bundle_product_2[1]};

// Get all bundled ids against product currently
$bundled_ids = WC_PB_DB::query_bundled_items( array(
    'return'     => 'id=>bundle_id',
    'product_id' => array( $id )
) );

if (in_array($Bundle_product_1, $bundled_ids->product_id))
{
echo "";
}else{
$item_id = $Bundle_product_1;
$meta_key = ;
$meta_value  = ;

$result = WC_PB_DB::add_bundled_item_meta( $item_id, $meta_key, $meta_value );
}    
}
}

Solution

  • Thought I would share my learnings for the community

    This function runs after the product has imported, then assigns the child product to the bundled product package. I have also assigned the meta of a description field for easier lookup later and make it easier to use the wc functions https://docs.woocommerce.com/document/bundles/bundles-functions-reference/

    With my import, I only import the highlevel attributes for the product filters The second piece of code is a more direct lookup, where I have set a method of pulling the meta data (including custom fields). The idea is to reduce data duplication and keep the meta tables lean Still looking at a method to make the query more efficient, but at the moment it does what I need it to do

    lastly, and most prob wont care about this but I have added in a function to assign all products and assets to have the same author id

    /**
     * ==================================
     * Action: pmxi_saved_post
     * ==================================
     *
     * Called after a post is created/updated by WP All Import.
     *
     * @param $post_id int               - The id of the post just created/updated
     * @param $xml_node SimpleXMLElement - An object holding values for the current record
     * @param $is_update             - Boolean showing whether the post is created or updated
     *
     */
    function apyc_product_bundle_saved_post($post_id, $xml_node, $is_update)
    {
        /*
         * Here you can use standard WordPress functions like get_post_meta() and get_post() to
         * retrieve data, make changes and then save them with update_post() and/or update_post_meta()
         *
         * There are two ways to access the data from the current record in your import file:
         *
         * 1) Custom fields. For example, you could import a value to a custom field called "_temp" and
         *  then retrieve it here. Since it's only temporary, you'd probably want to delete it immediately:
         *
         *     $my_value = get_post_meta($post_id, "_temp", true);
         *     delete_post_meta($post_id,"_temp");
         *
         * 2) The $xml param (a SimpleXMLElement object). This can be complex to work with if you're not
         * used to iterators and/or xpath syntax. It's usually easiest to convert it a nested array using:
         *
         *     $record = json_decode(json_encode((array) $xml_node), 1);
         */
        /*
         * You can also conditionally run your code based on the import ID:
         *
         *     $import_id = ( isset( $_GET['id'] ) ? $_GET['id'] : ( isset( $_GET['import_id'] ) ? $_GET['import_id'] : 'new' ) );
         *     if ( $import_id == '8' ) {
         *        // run code
         *     }
         */
             /**
             * The product_id must exists in the database, if not it wont bundle.
             * Also the product type must be simple, variable or simple/variable subs.
             **/
             if( $xml_node->product_type == 'Product bundle'){
                    if(isset($xml_node->child2_id)){
                        $data = [
                            'product_id' => (int)$xml_node->child2_id,
                            'bundle_id' => $post_id,
                            'menu_order' => 0,
                            'meta_data' => [
                                'description' => 'child2_title'
                            ],
                        ];
                        WC_PB_DB::add_bundled_item( $data );
                    }
                    if(isset($xml_node->child1_id)){
                        $data = [
                            'product_id' => (int)$xml_node->child1_id,
                            'bundle_id' => $post_id,
                            'menu_order' => 0,
                            'meta_data' => [
                                'description' => 'child1_title'
                            ],
                        ];
                        WC_PB_DB::add_bundled_item( $data );
                    }
             }
             image_author($post_id);
             wp_publish_post($post_id);
    }
    add_action('pmxi_saved_post', 'apyc_product_bundle_saved_post', 10, 3);
    function image_author($id)
    {
    
        $user_id = get_post_field ('post_author', $id);
    
    
        $args = array(
        'post_parent' => $id,
        'post_type' => 'attachment'
        //,
        // 'post_mime_type' => 'image'
        );
    
        $attachments = get_posts($args);
        if($attachments) :
            foreach ($attachments as $attachment) : setup_postdata($attachment);
               $the_post = array();
               $the_post['ID'] = $attachment->ID;
               $the_post['post_author'] = $user_id;
    
               wp_update_post( $the_post );
    
           endforeach;
        endif;
    
    }
    

    New short code to pull the metadata on woocommerce child bundle item

    // Bundled Child Products meta fields shortcode
    // Usage
    // id is a required parameter
    // Will return text wraped in a span matching the meta field
    // [child_products_meta_fields id="custom-field-1" childcategory="category-x"]
    // Adding output="url" Will return the URL of the meta attached file 
    // [child_products_meta_fields id="custom-field-1" childcategory="category-x"] output="url"]
    function child_products_meta_fields_shortcode( $atts ) {
        global $wpdb;
        $atts = extract( shortcode_atts( array(
            'id' => '',
            'childcategory' => '',
            'output' => ''
        ), $atts ) );
        $packageid = get_the_ID();
         $childcategory = " AND wp_terms.slug = '".$childcategory."'";
        // $output ='';
    
                $propertyid =   $wpdb->get_results("SELECT
                wp_woocommerce_bundled_items.product_id
                FROM
                wp_woocommerce_bundled_items
                INNER JOIN wp_term_relationships ON wp_woocommerce_bundled_items.product_id = wp_term_relationships.object_id
                INNER JOIN wp_term_taxonomy ON wp_term_relationships.term_taxonomy_id = wp_term_taxonomy.term_taxonomy_id
                INNER JOIN wp_terms ON wp_term_taxonomy.term_id = wp_terms.term_id
                WHERE
                wp_woocommerce_bundled_items.bundle_id = ".$packageid."
                 ".$childcategory."
                Limit 1");
    
                ob_start();
        foreach( $propertyid as $propertyid ){
        $propertyid = $propertyid->product_id ;
         }
    
        if ( ! $id ) return;    
        $data = get_post_meta( $propertyid, $id, true );
        if ( $data && $output == "") {
            return '<span class="id-'. $id .'">'. $data .'</span>';
        }
        if ( $data && $output == "url") {
            return wp_get_attachment_url( $data );
        }
         return ob_get_clean();
    }
    add_shortcode( 'child_products_meta_fields', 'child_products_meta_fields_shortcode' );