How to have shortcode autofilling the content if the attribution is specified?

The first two could happen if you mixed self-closing and enclosing shortcodes for the same tag/shortcode, e.g. you put the shortcodes in question into the same post content like so:

1) Self-closing: [test content="foo" ] and 2) Enclosing: [test]blabla[/test]

.. in which case WordPress’ shortcode parser would treat those two shortcodes as only one shortcode, i.e. it begins at [test content="foo" ] and ends at the [/test], whereby the $content value would be and 2) Enclosing: [test]blabla.

So try creating a brand new post and add only one of the above shortcodes, e.g. just the [test]blabla[/test], and then you’d get the expected output, i.e. AblablaB.

See https://codex.wordpress.org/Shortcode_API#Enclosing_vs_self-closing_shortcodes for more details.

And if you want to use your shortcode in both the self-closing and enclosing forms, then you can avoid the parsing issue by using / as in [test /] (or [test/]), which functions just like the / in self-closing HTML tags like <br />, <hr />, <img ... />, etc.

So for example, (note the /])

1) Self-closing: [test content="foo" /] and 2) Enclosing: [test]blabla[/test]

.. and with that, you’d get the correct output — 1) Self-closing: AbarB and 2) Enclosing: AblablaB.


As for the [test /] (or just [test] when not mixed with the enclosing form), or [test][/test] (the enclosing form), the correct output based on your code is actually AB and not ANot loadingB.

Because the shortcode was used without any content where “content” here refers to the content in between the opening and closing tags, e.g. [test]this is the CONTENT[/test].

And secondly, the shortcodes didn’t have the content attribute/parameter (e.g. as in [test content="foo"]), hence the $content remained empty, which then outputs AB.

So if you actually wanted Not loading to always be the $content value when the content and content attribute are both empty or not specified, then you could do something like..

$content = $content ? $content : 'Not loading'; // add this line
return 'A' . $content . 'B';

That way, [test /] and [test][/test] would give you ANot loadingB.