Getting the count of a shortcode that is nested

Let’s say I have nested shortcode where the outmost shortcode is just HTML but the inner one is the one who displays the data.

[outer_shortcode][inner_code url="#" title="Hello"][/outer_shortcode]

In this case, the count of inner items is one. In the following one:

Read More
[outer_shortcode][inner_code url="#" title="Hello"][inner_code url="#2" title="Hello2"][/outer_shortcode]

The inner count is two.

How can I determine this on the functions that I work with?

I currently have (outer shortcode that calls the inner):

return '<section id="recipes"><nav><ul>'.do_shortcode($content).'</ul></nav></section>';

And as inner:

        $the_stuff .= '<li>';     
        $the_stuff .= '<a href="' .$url. '" rel="external">'.$title.'</a>';
        $the_stuff .= '</li>';

        return $the_stuff;

That’s what I want. To count the list items. How can I accomplish this?

Related posts

Leave a Reply

1 comment

  1. Here is very, very rough code that should get you started:

    add_shortcode('outer_shortcode',function($attts,$content){return 1;});
    add_shortcode('inner_code',function($attts,$content){return 1;});
    $str = '[outer_shortcode][inner_code url="#" title="Hello"][inner_code url="#2" title="Hello2"][/outer_shortcode]';
    $reg = get_shortcode_regex();
    preg_match_all('~'.$reg.'~',$str,$matches);
    var_dump($matches);
    preg_match_all('~'.$reg.'~',$matches[5][0],$matches2);
    var_dump($matches2);
    

    What is happening is that you are parsing the string which matches and “pulls apart” the outer shortcode. You then need to parse that shortcode’s content (array element 5) to parse the two inner shortcodes. count($matches[0][0]) should be 2. Simple is principle but there are a lot of ways it could go wrong. You’d want to do a lot of error checking and may want to iterate over the arrays rather than assuming the first match, $matches[5][0], as I did.

    If you look at the source for get_shortcode_regex you can see what the different parts of that complicated array mean:

    199  * 1 - An extra [ to allow for escaping shortcodes with double [[]]
    200  * 2 - The shortcode name
    201  * 3 - The shortcode argument list
    202  * 4 - The self closing /
    203  * 5 - The content of a shortcode when it wraps some content.
    204  * 6 - An extra ] to allow for escaping shortcodes with double [[]]
    

    If you are doing what I think you are doing, you probably want something like this:

    add_shortcode(
      'outer_shortcode',
      function($atts,$content){
        $reg = get_shortcode_regex();
        preg_match_all('~'.$reg.'~',$content,$matches);
        echo count($matches[0]);
        return do_shortcode($content);
      }
    );
    
    add_shortcode(
      'inner_code',
      function($atts,$content){
        $the_stuff = '<li>';     
          $the_stuff .= '<a href="' .$atts['url']. '" rel="external">'.$atts['title'].'</a>';
        $the_stuff .= '</li>';
        return $the_stuff;
      }
    );
    
    // now test it
    $str = '[outer_shortcode][inner_code url="#" title="Hello"][inner_code url="#2" title="Hello2"][/outer_shortcode]';
    echo do_shortcode($str);
    

    I think you can fill in the rest of the markup.