Wrap HTML around each shortcode with do_shortcode()

I have a page that has multiple shortcodes on it. I would like to have the content from each shortcode wrapped with an HTML tag. I have the following code that almost works but it wraps all of the shortcodes in one div.

<?php $sidebarBlocks = get_post_meta($post->ID, "page_sidebarhubspot", true); ?>
<?php echo do_shortcode('<div>'.$sidebarBlocks.'</div>'); ?>

This outputs..

Read More
<div>
   <p>Content from shortcode1</p>
   <p>Content from shortcode2</p>
   <p>Content from shortcode3</p>
</div>

What I want is this..

<div>
   <p>Content from shortcode1</p>
</div>

<div>
   <p>Content from shortcode2</p>
</div>

<div>
   <p>Content from shortcode3</p>
</div>

How can I accomplish this? Thanks!

Related posts

Leave a Reply

2 comments

  1. That’s a good question – I don’t think it’s currently possible without hacking around. Here’s my go at that:

    <?php 
    function my_override_shortcodes() {
        global $shortcode_tags, $_shortcode_tags;
    
        // Let's make a back-up of the shortcodes
        $_shortcode_tags = $shortcode_tags;
    
        // Add any shortcode tags that we shouldn't touch here
        $disabled_tags = array( 'gallery' );
    
        foreach ( $shortcode_tags as $tag => $cb ) {
            if ( in_array( $tag, $disabled_tags ) ) {
                continue;
            }
            // Overwrite the callback function
            $shortcode_tags[ $tag ] = 'my_wrap_shortcode_in_div';
        }
    }
    add_action( 'init', 'my_override_shortcodes', 9999 );
    
    // Wrap the output of a shortcode in a div with class "i-wrap-you"
    // The original callback is called from the $_shortcode_tags array
    function my_wrap_shortcode_in_div( $attr, $content = null, $tag ) {
        global $_shortcode_tags;
        return '<div class="i-wrap-you">' . call_user_func( $_shortcode_tags[ $tag ], $attr, $content, $tag ) . '</div>';
    }
    

    So what happens here is that on init we copy all of the registered shortcodes and overwrite their callback function with our own function.

    That function on the other hands when called returns an opening div tag, followed by the output of the original callback function and then a closing div tag.

    If you want to override the shortcodes just for that do_shortcode call, you can do something like this:

    function my_restore_shortcodes() {
        global $shortcode_tags, $_shortcode_tags;
    
        // Restore the original callbacks
        if ( isset( $_shortcode_tags ) ) {
            $shortcode_tags = $_shortcode_tags;
        }
    }
    

    And in your code do this:

    $sidebarBlocks = get_post_meta( $post->ID, "page_sidebarhubspot", true );
    
    my_override_shortcodes();
    
    echo do_shortcode('<div>'.$sidebarBlocks.'</div>');
    
    my_restore_shortcodes();
    

    Of course if you use the second method, don’t forget to remove the line

    add_action( 'init', 'my_override_shortcodes', 10 );
    

    As a bonus in the my_override_shortcodes() function you can specify shortcodes that will not be overwritten(the $disabled_tags array).

  2. You can try like this [You can remove the htmlentities(), I have used it for illustration purposes , just use plain echo ]

    <?php $sidebarBlocks = get_post_meta($post->ID, "page_sidebarhubspot", true); ?>
    <?php 
    $sidebarBlocks=str_replace("<p>","<div><p>",$sidebarBlocks);
    $sidebarBlocks=str_replace("</p>","</p></div>",$sidebarBlocks);
    echo htmlentities($str);
    ?>
    

    OUTPUT :

    <div><p>Content from shortcode1</p></div>
    <div><p>Content from shortcode2</p></div>
    <div><p>Content from shortcode3</p></div>