1
votes

I have created a shortcode to display products of a specific product category (combined with a few ACF fields). All works great so use the code below for you own benefit.

The shortcode looks like this: [yl_get_products cat_id='51' order='ASC' template='1'] As you can see I've added template='1' so you can add a new layout later if you prefer.

Oke, so what's my problem: When I want to add the ADD-TO-CART button (together with my product add-ons) I need something like:

do_action( 'woocommerce_' . $product->get_type() . '_add_to_cart' ); within my shortcode.

or

do_action( 'woocommerce_single_product_summary' ); (and then remove all the not needed actions)

The result is that it indeed shows the whole add-to-cart output with add-on options etc. but it always displays on top of the page (in stead of the modal) and also any page styling is completely ignored.

I believe I have had this before and I thought it had to do something with echo return return = return .= but I can't get it right.

So my actual question is:
How can I add one to the actions above in my product loop shortcode without messing up the layout?

Here's my code:

// Get a dish category via shortcode
function yl_get_products_shortcode( $atts ) {

    $atts = shortcode_atts( array(
        'cat_id'    => '',
        'orderby'   => '',
        'order'     => '',
        'template'  => '',
    ), $atts );

    $products = new WP_Query(array(
        'post_type'         => 'product',
        'tax_query'         => array( array(
            'taxonomy'          => 'product_cat',
            'field'             => 'term_id',
            'terms'             => $atts['cat_id'],
            // 'include_children' => false // or true (optional)
        )),
        'orderby'           => $atts['orderby'],
        'order'             => $atts['order'],
        'post_status'       => 'publish',
        'posts_per_page'    => -1
    ));

    if ( $products->have_posts() ) {

        while ( $products->have_posts() ) {

            $products->the_post();

            if ($atts['template'] == '1') {

                global $product;
                $id                 = get_the_ID();
                $product            = wc_get_product( $id );

                $name               = $product->get_title();
                $short_description  = $product->get_short_description();
                $description        = $product->get_description();
                $rating_count       = $product->get_rating_count();
                $rating_average     = number_format($product->get_average_rating() * 20, 0) . '%';
                $review_count       = $product->get_review_count();
                $price              = $product->get_price();
                $image_url          = wp_get_attachment_url( $product->get_image_id() );

                $description_nl     = get_field('description_nl');
                $title_en           = get_field('title_en');
                $description_en     = get_field('description_en');
                $allergens          = get_field('allergens');
                $specifics          = get_field('specifics');

                $output .= '
                <li>
                    <div class="uk-grid-small" uk-grid>';
                        if ($product->is_in_stock()) {
                            $output .= '
                            <div class="uk-width-auto">
                                <a href="#product-' . $id . '" class="uk-button uk-button-small uk-button-primary" uk-toggle>
                                        <span uk-icon="icon: cart"></span>
                                </a>
                            </div>';
                        }
                        if (!empty($allergens)) {
                            $output .= '
                            <div class="uk-width-auto">
                                <a href="#allergens-' . $id . '" uk-toggle>
                                    <span uk-icon="icon: info"></span>
                                </a>
                            </div>';
                        }
                        $output .= '
                        <div class="uk-width-expand">
                            <p class="uk-h6 uk-margin-remove">
                                ' . $name;
                                if (!empty($specifics)) {
                                    foreach ($specifics as $specific) {
                                        $output .= '
                                        <img src="/wp-content/uploads/network/images/food-icons/icon-' . str_replace(' ', '-', $specific) . '.svg" width="16" uk-tooltip="' .  $specific . '">';
                                    }
                                }
                            $output .= '
                            </p>
                            <p class="uk-margin-remove">
                                ' . $description_nl;
                                if ($short_description) {
                                    $output .= '<br />' . $short_description;
                                }
                            $output .= '
                            </p>
                        </div>
                        <div class="uk-width-auto uk-h6">
                            € ' . $price . '
                        </div>
                    </div>';

                    if (!empty($allergens) || !empty($specifics)) {
                        $output .= '
                        <div id="allergens-' . $id . '" uk-modal="center: true">
                            <div class="uk-modal-dialog uk-modal-body">
                                <button class="uk-modal-close-default" type="button" uk-close></button>
                                <h3 class="uk-modal-title uk-margin-small uk-text-truncate">
                                    ' . $name;
                                    if (!empty($specifics)) {
                                        foreach ($specifics as $specific) {
                                            $output .= '
                                            <img src="/wp-content/uploads/network/images/food-icons/icon-' . str_replace(' ', '-', $specific) . '.svg" width="16" uk-tooltip="' . $specific . '">';
                                        }
                                    }
                                $output .= '
                                </h3>
                                <p class="uk-margin-small">' . __( 'Below you will find an overview of the allergens that are in this dish. For more information you can always contact our service staff.', 'yorlinq' ) . '</p>
                                <div uk-alert>
                                    <div class="uk-grid-small uk-child-width-1-2@s" uk-grid>';
                                        foreach ($allergens as $allergen) {
                                            $output .= '
                                            <div>
                                                <div class="uk-grid-small uk-flex-middle" uk-grid>
                                                    <div class="uk-width-1-4">
                                                        <img src="/wp-content/uploads/network/images/food-icons/icon-' . str_replace(' ', '-', $allergen) . '.svg">
                                                    </div>
                                                    <div class="uk-width-3-4">
                                                        ' . $allergen . '
                                                    </div>
                                                </div>
                                            </div>';
                                        }
                                    $output .= '
                                    </div>
                                </div>
                            </div>
                        </div>';
                    }

                    if ($product->is_in_stock()) {
                        $output .= '
                        <div id="product-' . $id . '" uk-modal="center: true">
                            <div class="uk-modal-dialog uk-modal-body">
                                <button class="uk-modal-close-default" type="button" uk-close></button>
                                <h3 class="uk-modal-title uk-margin-small uk-text-truncate">
                                    ' . $name;
                                    if (!empty($specifics)) {
                                        foreach ($specifics as $specific) {
                                            $output .= '
                                            <img src="/wp-content/uploads/network/images/food-icons/icon-' . str_replace(' ', '-', $specific) . '.svg" width="16" uk-tooltip="' . $specific . '">';
                                        }
                                    }
                                $output .= '
                                </h3>
                                ' . $description;
                        
                                // Here is where the action sould appear
                        
                            $output .= '
                            </div>
                        </div>';
                    }
                $output .= '
                </li>';

            }

        };

        return '<ul class="uk-list uk-list-divider">' . $output . '</ul>';

    }

}

add_shortcode('yl_get_products','yl_get_products_shortcode');
1

1 Answers

1
votes

I would recommend using an output buffer for storing echo output as a string. The stored content could be easily appended to the shortcode output:

function yl_get_products_shortcode( $atts ) {
//  ... your logic

    add_action( 'woocommerce_' . $product->get_type() . '_add_to_cart', function () {
//      You could remove any action you want
//      remove_action( 'xxx', 'xxx', priority );
    }, 1 );

    ob_start();
    do_action( 'woocommerce_' . $product->get_type() . '_add_to_cart' );
    $add_to_cart_content = ob_get_clean();

    return '<ul class="uk-list uk-list-divider">' . $output . '</ul>' . $add_to_cart_content;
}