Custom excerpt function re-factoring

This may be more of a php best practices question, but here goes…

I am using a custom excerpt trim function:

Read More
function new_wp_trim_excerpt($text) { // Fakes an excerpt if needed
    global $post;
    if ( '' == $text ) {
        $text = get_the_content('');
        $text = apply_filters('the_content', $text);
        $text = str_replace(']]>', ']]>', $text);
        $text = strip_tags($text, '<p>');
        $text = preg_replace('@<script[^>]*?>.*?</script>@si', '', $text);
        $excerpt_length = 100;
        $words = explode(' ', $text, $excerpt_length + 1);
        if (count($words)> $excerpt_length) {
            $dots = '&hellip;';
            array_pop($words);
            $text = implode(' ', $words).$dots.'<p class="moarplz"><a href="'. get_permalink($post->ID) . '">Read More &raquo;</a></p';
        }
        else
        {
            $text = get_the_content();
        }
    }
    return $text;
}

remove_filter('get_the_excerpt', 'wp_trim_excerpt');
add_filter('get_the_excerpt', 'new_wp_trim_excerpt');

Basically, for posts over a hundred words, a “faked” excerpt is produced of the first 100 words, with a “Read More” link. Posts having less than 100 words are outputted in their entirety. You can see this at work here: http://www.mbird.com/

Complicating this matter is 1) that an author can choose to override the excerpt per post. Also, 2) there is a function that tries to find an image that can serve as a post thumbnail from the post attachments if none is specified.

All these things act as flags, determining the layout of the post on the index page. For example, if a full post is output, it needs to have extra padding to avoid the image wrap CSS I have in place, and it shouldn’t have a teaser thumbnail. If no teaser thumbnail can be found for a excerpt it needs to avoid the same. Etc etc.

Anyway, in order to determine what the layout out wrapper should be, I end up reusing a lot of the new_wp_trim_excerpt function in my page template to sniff if an excerpt or a full post will happen. Like so:

<?php
    while (have_posts ()) : the_post();
        global $excerpt_checkbox_mb; 
        $exmeta = $excerpt_checkbox_mb->the_meta(); //override excerpt?
        $text = get_the_content('');
        $text = apply_filters('the_content', $text);
        $text = str_replace(']]>', ']]&gt;', $text);
        $text = strip_tags($text, '<p>');
        $text = preg_replace('@<script[^>]*?>.*?</script>@si', '', $text);
        $excerpt_length = 100;
        $words = explode(' ', $text, $excerpt_length + 1);
        if (count($words) > $excerpt_length) {
            $word_count = true;
        } else {
            $word_count = false;
        }
    ?>

Then I use that to determine if an image should be hunted for:

<?php
        if (($exmeta['cb_single'] != "yes") && $word_count) { // we're printing an excerpt, get a teaser image!
            get_the_image(array(
                'meta_key' => null,
                'image_class' => 'thumb',
                'callback' => 'find_image'
            ));
        }
        ?>

And finally what the wrapper should be:

<?php $image = find_image(); ?>
        <!--if full post, add left padding to avoid image wrap-->
                    <?php if (($exmeta['cb_single'] == "yes") || !$word_count) : ?>
            <div class="post-content">    
<?php the_content();
                    elseif ($image) : ?> // we found an image, apply css psuedo-col
                <div class="post-content post-psuedo-col">     
<?php the_excerpt();
                    else : ?> // no image, reduce padding
                            <div class="post-content">             
<?php the_excerpt();
                    endif; ?>
                        </div> 

Anyway, it seems bad to reuse so much of the new_wp_trim_excerpt function to sniff, especially since I have to change $excerpt_length in two places! But I can’t really figure out an elegant way to re-factor. I was considering adding another function that both parts can call on, that would return array containing a bool regarding count($words) > $excerpt_length and optionally the text itself, but that still seems clunky.

If you’ve somehow managed to read all this, help!

Related posts

Leave a Reply

1 comment

  1. I’d simply set a flag as second input argument for the function:

    function new_wp_trim_excerpt( $text, $case = 'plain' ) 
    {
        switch ( $case ) 
        {
            default :
            case 'plain' :
                // do stuff - your function so far
                break;
    
            case 'image' :
                break;
        }
    }
    

    Notes:

    • Avoid names like class="moarplz". It’s hard to read for others and hard for yourself in a year.
    • Never count inside an if/for/while/foreach/else/elseif statement – it’s up to 5 times slower than counting it in the line before.