WordPress nested Shortcodes doesn’t work even with do_shortcode() function

So another nested shortcodes problem.
I have two shortcodes : [slide] and [prg]. They’re both enclosing shortcodes. [prg] is nested into [slide]. But [prg] isn’t interpreted.
The two shortcodes work well separately.
I know the do_shortcode() function but it seems not working, I don’t know why.

Here’s the code I’ve write :

Read More
add_action( 'init', 'register_shortcodes');

function make_slide($atts, $content = null) {
    extract(shortcode_atts(array(
      'num' => 1,
   ), $atts));

    $post_title = get_the_title($post->ID);
    $wrap = '<div class="slide slide-'.$num.'"><h1 class="h2-like projet_title">'.$post_title.'</h1>'.$content.'</div>';
    return $wrap;
}

function wrap_paragraph($atts, $content = null)
{
    $content = do_shortcode($content); //I've tried several solutions but none've worked.
    return '<p>'.$content.'</p>';
}

function register_shortcodes(){
    add_shortcode('slide', 'make_slide');
    add_shortcode('prg', 'wrap_paragraph');
}

And here’s the content of my post (a custom post type) in the html editor :

[slide num="1"]<img title="4a6c2a605946a_1080x733" src="http://localhost:8888/labs/noway/wordpress_1/wp-content/uploads/2012/09/4a6c2a605946a_1080x733-460x312.jpg" alt="4a6c2a605946a_1080x733" width="460" height="312" />

[prg]Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nam cursus. Morbi ut mi. Nullam enim leo, egestas id, condimentum at, laoreet mattis, massa.[/prg][/slide]

I’ve read several posts on this site and other ones such as sitepoint.com and speckyboy.com, as well as the wordpress codex but the answers doesn’t work for me.
Perhaps it’s just because i’m not implementing shortcodes the right way in my function.php file?

If anybody can help me ? I really want to understand what makes it not working. Thanks a lot in advance.
Sorry for my bad english, I hope I’m understandable.

EDIT
I’ve stupidely validated my comment before finishing it, so there it is :

Hi @maiorano and thanks a lot for your help, it worked perfectly.
However even if your code is really good, I can’t use it as it is because I need to get the pictures directly from the media library, with as less as possible human intervention in the MCE editor. But it has made me learn a godd way to go.

Also I’ve tested to use do_shortcode into the top-level shortcode, but it produced a weird result : my < p > was deported outside of the < div > so I was confused.

So it appears that what was blocking me was a combination of that top-level do_shortcode-ish and perhaps the fact that my add_shortcode() were declared after the shortcodes.

Related posts

Leave a Reply

1 comment

  1. The problem is that your top-level shortocde “[slide]” is not executing do_shortcode() on its content. A few pointers:

    I would advise including your image attributes as shortcode attributes, as it reduces the amount of markup and provides you the ability to define defaults.

    You also don’t need to define your shortcodes within an ‘init’ callback. It can be done in global scope:

    add_shortcode('slide', 'make_slide');
    add_shortcode('prg', 'wrap_paragraph');
    function make_slide($atts, $content = null)
    {
        extract(shortcode_atts(array(
          'num' => 1,
          'title' => false,
          'src' => get_bloginfo('stylesheet_directory').'/images/notfound.jpg', //Default image if none provided
          'alt' => false,
          'width' => false,
          'height' => false,
       ), $atts));
    
        $title = $title ? " title="$title"" : '';
        $alt = $alt ? " alt="$alt"" : '';
        $width = $width ? " width="$width"" : '';
        $height = $height ? " height="$height"" : '';
    
        $img = "<img src="$src"".$title.$alt.$width.$height." />";
    
        $post_title = get_the_title($post->ID);
        $wrap = '<div class="slide slide-'.$num.'"><h1 class="h2-like projet_title">'.$post_title.'</h1>'.$img.do_shortcode($content).'</div>';
        return $wrap;
    }
    
    function wrap_paragraph($atts, $content = null)
    {
        $content = do_shortcode($content); //This is fine if you plan on nesting shortcode within this callback
        return '<p>'.$content.'</p>';
    }
    

    Using this, I was able to add the content:

    [slide num="1" title="4a6c2a605946a_1080x733" src="http://localhost:8888/labs/noway/wordpress_1/wp-content/uploads/2012/09/4a6c2a605946a_1080x733-460x312.jpg" alt="4a6c2a605946a_1080x733" width="460" height="312"][prg]Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nam cursus. Morbi ut mi. Nullam enim leo, egestas id, condimentum at, laoreet mattis, massa.[/prg][/slide]
    

    And get:

    <div class="slide slide-1"><h1 class="h2-like projet_title">Hello world!</h1><img width="460" height="312" alt="4a6c2a605946a_1080x733" title="4a6c2a605946a_1080x733" src="http://localhost:8888/labs/noway/wordpress_1/wp-content/uploads/2012/09/4a6c2a605946a_1080x733-460x312.jpg"><p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nam cursus. Morbi ut mi. Nullam enim leo, egestas id, condimentum at, laoreet mattis, massa.</p></div>