I haven’t tested this but based on memory, you are misunderstanding how shortcodes work. The “content” isn’t passed through the callback the way you seem to expect it to be. The content is extracted from the post body via a preg_*
function. That, if my memory serves, is going to give you “content” as a string no matter what you try to pass into it.
As noted below, the Codex has a line stating that is_null()
can be used to determine that the shortcode is closed. As far as I can tell, that does not work.
function baztag_func( $atts, $content = null) {
echo gettype($content);
echo '<br>';
var_dump($content);
echo '<br>';
return "content = $content";
}
add_shortcode( 'baztag', 'baztag_func' );
do_shortcode('[baztag]');
do_shortcode('[baztag]abc[/baztag]');
die;
In all cases, the shorcode content comes out as a string. If you look at how shortcodes work, you can see why:
$pattern = get_shortcode_regex();
preg_match_all("/$pattern/s",'[baztag]abc[/baztag]',$matches);
var_dump($matches);
preg_match_all("/$pattern/s",'[baztag]',$matches);
var_dump($matches);
die;
Make note of the 5th item in the resulting array. That item is a string
in both cases. That string is what is going to hit your callback as $content
.
Now, Core uses preg_replace_callback()
with the do_shortcode_tag()
callback. That callback makes it look like null
might be passed through if content isn’t set. To do that it checks the 5th element of that $matches
array with isset()
. If isset()
returns false code should push null
through, as I read it. But isset()
on empty content…
$content="";
var_dump(isset($content));
Or an array…
$content = array();
var_dump(isset($content));
Is true
. Even if this line: if ( isset( $m[5] ) ) {
in do_shortcode_tag()
is changed to if ( empty( $m[5] ) ) {
you still get a string:
function do_shortcode_tag_v2( $m ) {
global $shortcode_tags;
// allow [[foo]] syntax for escaping a tag
if ( $m[1] == '[' && $m[6] == ']' ) {
return substr($m[0], 1, -1);
}
$tag = $m[2];
$attr = shortcode_parse_atts( $m[3] );
if ( empty( $m[5] ) ) {
// enclosing tag - extra parameter
return $m[1] . call_user_func( $shortcode_tags[$tag], $attr, $m[5], $tag ) . $m[6];
} else {
// self-closing tag
return $m[1] . call_user_func( $shortcode_tags[$tag], $attr, null, $tag ) . $m[6];
}
}
var_dump(preg_replace_callback( "/$pattern/s", 'do_shortcode_tag_v2', '[baztag]' ));
Everything I can think of doing suggests that the information in the Codex is wrong on this one. That is simply not how it works.