Cannot strip JW Player shortcode?

On the WordPress archive template I am using a custom excerpt function that includes a reference to strip_shortcodes(). For some reason, shortcodes are being rendered and displayed in the archive.

Example: http://arisehub.org/blog/page/2/

Read More

Scroll down to “Sing a New Song with Joshua Cunningham”

Notice the script code showing up. That’s a shortcode reference to JW Player, showing up rendered.

Here’s the code I’m using for the custom excerpt function.

function custom_excerpt($length, $more_text) { 
    global $post;     
    $text = get_the_content(); 
    $text = strip_shortcodes( $text );    
    $text = apply_filters('the_content', $text);  
    $text = str_replace(']]>', ']]>', $text);  
    $text = strip_tags($text, '<a>, <p>, <strong>, <em>, <b>');


    if(!empty($length)){
        $excerpt_length = apply_filters('excerpt_length', $length); 
    } else {
        $excerpt_length = apply_filters('excerpt_length', 180); 
    }

    if(!empty($more_text)){
        $excerpt_more = apply_filters('excerpt_more', ' ' . '&hellip; <br /><a href="'.get_permalink($post->id).'" class="more-link">'.$more_text.'</a>');
    } else { 
        $excerpt_more = apply_filters('excerpt_more', ' ' . '&hellip;<a href="'.get_permalink($post->id).'" class="more-link">+ more</a>');
    }

    $words = preg_split('/(<a.*?a>)|n|r|t|s/', $text, $excerpt_length + 1, PREG_SPLIT_NO_EMPTY|PREG_SPLIT_DELIM_CAPTURE );  
    if ( count($words) > $excerpt_length ) {  
        array_pop($words);  
        $text = implode(' ', $words);  
        $text = $text . $excerpt_more;  
    } else {  
        $text = implode(' ', $words);  
    }  
    $output = '<p>'.$text.'</p>';
    echo $output;  
} 

Any ideas?

Related posts

Leave a Reply

5 comments

  1. JW Player Plugin for WordPress does not register its shortcode like all other shortcodes, so strip_shortcodes() will not know about it and not strip it. In the code there is a note that this is because it uses argument names with a . in it, and WordPress does not support this.

    There are probably multiple ways to solve this, but I would copy the relevant line from strip_shortcodes() and integrate the regex from the plugin:

    function custom_excerpt( $length, $more_text ) {
        global $post;
        $text = get_the_content();
        $text = strip_shortcodes( $text );
        // Strip JW Player shortcode too
        $text = preg_replace( '/(.?)[(jwplayer)b(.*?)(?:(/))?](?:(.+?)[/2])?(.?)/s', '$1$6', $text );
        $text = apply_filters('the_content', $text);
        // Continue with the rest of your function ...
    
  2. There’s a function on the Codex page for strip_shortcodes that does what you need:

    function remove_shortcode_from_index($content) {
      if ( is_home() ) {
        $content = strip_shortcodes( $content );
      }
      return $content;
    }
    add_filter('the_content', 'remove_shortcode_from_index');
    

    In your case, you would apply it to your archives page or wherever else you want.

  3. Try the code below. It will only add the filter to strip shortcodes when your custom_excerpt function is called. The rest of your site will be unaffected. I am not sure how your get_the_content function fetches the content. So this filter will also take care of it.

    function my_strip_jwplayer( $content ) {
        $content = strip_shortcodes( $content );
        return $content;
    }
    
    function custom_excerpt($length, $more_text) { 
    global $post;     
    
    // add a custom filter
    add_filter('the_content', 'my_strip_jwplayer', 10);
    
    
    $text = get_the_content(); 
    $text = apply_filters('the_content', $text);  
    $text = str_replace(']]>', ']]>', $text);  
    $text = strip_tags($text, '<a>, <p>, <strong>, <em>, <b>');
    
    
    if(!empty($length)){
        $excerpt_length = apply_filters('excerpt_length', $length); 
    } else {
        $excerpt_length = apply_filters('excerpt_length', 180); 
    }
    
    if(!empty($more_text)){
        $excerpt_more = apply_filters('excerpt_more', ' ' . '&hellip; <br /><a href="'.get_permalink($post->id).'" class="more-link">'.$more_text.'</a>');
    } else { 
        $excerpt_more = apply_filters('excerpt_more', ' ' . '&hellip;<a href="'.get_permalink($post->id).'" class="more-link">+ more</a>');
    }
    
    $words = preg_split('/(<a.*?a>)|n|r|t|s/', $text, $excerpt_length + 1, PREG_SPLIT_NO_EMPTY|PREG_SPLIT_DELIM_CAPTURE );  
    if ( count($words) > $excerpt_length ) {  
        array_pop($words);  
        $text = implode(' ', $words);  
        $text = $text . $excerpt_more;  
    } else {  
        $text = implode(' ', $words);  
    }  
    $output = '<p>'.$text.'</p>';
    echo $output;  
    
    } 
    
  4. Just going to take a shot in the dark here, but after looking at your code it seems like you might want to try to swap the order of the following 2 lines:

    $text = strip_shortcodes( $text );    
    $text = apply_filters('the_content', $text);
    

    As far as I know, do_shortcode() is applied to the ‘the_content’ filter at 11. You are removing it and then adding it right back again. Doing this instead:

    $text = apply_filters('the_content', $text);    
    $text = strip_shortcodes( $text );    
    

    may help.

  5. I did some digging and tried to re-create this scenario.

    The only answer I can come up with that might help you is that your JWPlayer shortcode is added to the shortcodes list in a filter on the_content.

    strip_shortcodes only works when a shortcode is previously added to the shortcode list.. so my suspicion is that the JWPlayer shortcode is not added when you call that, but added in the filter.

    There are two ways to go about solving this problem.

    1. add your own shortcode with the same name before you do strip_shortcodes to the list, adding the capability for the strip_shortcodes to remove it, however that will remove your JWPlayer from ALL exceprts (may or may not be what you want)
    2. Modify the JWPlayer location of where it adds the shortcode so that it is available before the_content filter gets called.

    Edit Note for #1: After you do the strip_shortcodes, I would remove the shortcode you added, just incase the JWPlayer needs to be called somewhere else (outside of an excerpt) on the same page, it might conflict having two shortcodes added, depending on load order.

    Solution for #1:

    function nullfunc(){
      return '';
    }
    // put that function outside, it's the placeholder function just so the shortcode registers properly, if the callback isn't a valid function - it won't register.
    
    // do your get_the_content() here
    add_shortcode('<replace_with_shortcode_for_JWPlayer','nullfunc');
    // do your strip shortcodes here
    remove_shortcode('<rplace_with_shortcode_for_JWPlayer');
    
    // continue on with the rest of your code.
    

    These are just based on what I could recreate myself, and I’m not 100% sure they will help you, though I can’t think of any other reason why strip_shortcodes would fail, and this is the only scenario that makes sense to me.