Captions in wordpress do not support nested shortcodes at the moment (v3.6
). So, If I do write
[caption]<img src=""> I love my [city][/caption]
Where city is suppose to be processed but it does not. How do I fix this?
Ticket: #24990
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It only takes a minute to sign up.
Sign up to join this communityCaptions in wordpress do not support nested shortcodes at the moment (v3.6
). So, If I do write
[caption]<img src=""> I love my [city][/caption]
Where city is suppose to be processed but it does not. How do I fix this?
Ticket: #24990
There is a hook inside the caption shortcode that will allow you to hijack the whole thing. Most of the following is copied from the Core img_caption_shortcode
function.
function nested_img_caption_shortcode($nada, $attr, $content = null) {
extract(
shortcode_atts(
array(
'id' => '',
'align' => 'alignnone',
'width' => '',
'caption' => ''
),
$attr,
'caption'
)
);
$caption = do_shortcode($caption); // process nested shortcodes
if ( 1 > (int) $width || empty($caption) )
return $content;
if ( $id ) $id = 'id="' . esc_attr($id) . '" ';
return '<div ' . $id . 'class="wp-caption ' . esc_attr($align) . '" style="width: ' . (10 + (int) $width) . 'px">'
. do_shortcode( $content ) . '<p class="wp-caption-text">' . $caption . '</p></div>';
}
add_filter('img_caption_shortcode', 'nested_img_caption_shortcode', 1, 3);
The latest versions of WP have really improved the filterability of caption arguments, so I think this new answer will have the smallest footprint and safest operation.
What we need to do is directly filter $atts['caption']
during shortcode_atts()
for the [caption]
shortcode. We can do this with the shortcode_atts_caption
filter which only affects the caption shortcode.
As a bonus I added a commented-out line that will test the caption for a specific shortcode before running do_shortcode()
. This is useful if you only want to enable a particular shortcode in captions (I use it to enable only the Shortcode Shortcode). Careful though: do_shortcode()
will process all shortcodes, not just the one you tested for.
/**
* Filter Caption shortcode attributes to enable the [shortcode] shortcode inside caption text
*
* WP doesn't run do_shortcode on the 'caption' text value parsed out of [caption], which means
* the [shortcode] shortcode doesn't work.
*
* @param array $out atts array as determined by WP to be returned after filtering
* @param array $pairs
* @param array $atts
* @return filtered $out atts
*/
function wpse_113416_filter_shortcode_atts_caption($out, $pairs, $atts) {
// OPTIONAL: Look for a specific shortcode before running do_shortcode
// if (has_shortcode($out['caption'], 'shortcode_to_look_for'))
$out['caption'] = do_shortcode($out['caption']);
return $out;
}
add_filter('shortcode_atts_caption', 'wpse_113416_filter_shortcode_atts_caption', 10, 3);
Using latest function has_shortcode()
introduced on v3.6
add_filter( 'the_content', 'process_wp_caption_shortcodes' ); // hook it late
function process_wp_caption_shortcodes( $content ){
if( !function_exists ( 'has_shortcode' ) ) // no luck for user using older versions :)
return $content;
if( has_shortcode( get_the_content(), 'caption' ) ){ // check with raw content
// caption exists on the current post
$content = do_shortcode( $content );
}
return $content;
}
This solution can be used on any third party shotcode that didn't implemented nested shortcode support.
Any better solution welcomed!
has_shortcode
function can be defined coping code from v3.6 wrapping it with if (! function_exists('has_shortcode') ) {