Allowing shortcodes inside attributes

I want to do a Wikipedia-like infobox for some articles on a WP site. I guess the most logical thing to do it is to use a custom shortcode—one that returns a table-like markup with a fixed order of fields, each with more markup at custom along some conditional stuff for showing or not fields if they are not set, somewhat emulating something like this:

 <!--MediaWiki markup-->
 {{infobox-cd
 |name=Abbey Road"
 |cover=[[File:laserdisc.jpg]]
 |artist=[[The Bombay Beach Boys]]
 |country={{flag id=mx}} Argentina<br />{{flag id=dk}} Vanuatu (post-production)
 |rating={{stars no=3}}
 |prev=[[The Wall]]
 |next=[[Born in the U.S.A.]]
 }}

Yet I have been blocked from using them in a more literal approach for years due to shortcodes breaking while having brackets inside attributes. It theoretically should work, but doesn’t because the shortcode regex stops with the first occurrence of a closing bracket (]) in a shortcode, so in this:

Read More
[foo bar="[baz /]"]content[/foo]

it “outputs”:

[foo bar="[baz /]

I’m not sure how else I can get this markup working or something else with the same goal.

Related posts

1 comment

  1. Sorry, brackets are still not allowed within shortcodes, as you can see in the Shortcode API. However it’s possible to use enclosing shortcodes which will allow to use brackets. Let me demonstrate this:

    Shortcode: [foo bar="No brackets here!"]...use [brackets] here[/foo]

    You can add this kind of shortcode in your functions.php like this:

    add_shortcode( 'foo', 'foo_shortcode' );
    function foo_shortcode( $atts, $content = null ) {
    extract( shortcode_atts(
        array(
          'bar' => '',
        ), $atts )
      );
      return '<p>' . $bar . ' ' . $content . '</p>';
    }
    

    It’s also possible to execute the content within the brackets as another shortcode:

    Shortcode: [foo bar="No shortcodes here!"]...use [shortcodes] here[/foo]

    add_shortcode( 'foo', 'execute_foo_shortcode' );
    function execute_foo_shortcode( $atts, $content = null ) {
    extract( shortcode_atts(
        array(
          'bar' => '',
        ), $atts )
      );
      return '<p>' . $bar . ' ' . do_shortcode($content) . '</p>';
    }
    

    But let’s keep it simple. Why not adding the brackets within the shortcode itself?

    Shortcode: [foo bar="shortcode"]

    And within your functions.php

    add_shortcode( 'foo', 'build_foo_shortcode' );
    function build_foo_shortcode( $atts ) {
      extract( shortcode_atts(
        array(
          'bar' => '',
        ), $atts )
      );
    
      if ( isset( $bar ) ) :
        return '<p>' . do_shortcode( '[' . $bar . ']' ) . '</p>';
      endif;
    }
    

    If you want to stay with your kind of shortcode, you can go around the brackets and add something similar, to recognize and replace it via regex:

    Shortcode: [foo bar="Use your ___shortcode___ here"]

    Within your functions.php you can replace ___shortcode___ with [shortcode] and again execute it via do_shortcode()

    add_shortcode( 'foo', 'regex_foo_shortcode' );
    function regex_foo_shortcode( $atts ) {
      extract( shortcode_atts(
        array(
          'bar' => '',
        ), $atts )
      );
    
      if ( isset( $bar ) ) :
        $foo_bar = preg_replace_callback("/(.*)_{3}(.*)_{3}(.*)/", function($m) {
            return $m[1] . do_shortcode('[' . $m[2] . ']') . $m[3];
        }, $bar);
        return '<p>' . $foo_bar . '</p>';
      endif;
    }
    

    Okay, it’s a bit complicated now, isn’t it? Another approach (if you don’t want to keep doing it via shortcodes) would be custom fields. Custom fields are available per default and can be toggled via the Screen Options.

    You can use the_meta() or get it via get_post_meta() function to output them easily within your theme. Moreover it’s easier (compared to shortcodes) to handle the in- and output and nobody of the editors has to remember all of those available shortcodes.

    You can also generate advanced custom fields easily via the interface of a plugin or build and style them on your own. Anyway you will have nice input fields below or beside your text editor without limitations (even file upload, datepicker…). It will look something like this:

    enter image description here

Comments are closed.