Nested Shortcode Inside [caption] Doesn’t Process

Captions in wordpress do not support nested shortcodes at the moment (v3.6). So, If I do write

<img src=""> I love my [city]

Where city is suppose to be processed but it does not. How do I fix this?

Read More

Ticket: #24990

Related posts

3 comments

  1. 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);
    
  2. 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);
    
  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!

Comments are closed.