This may be more of a php best practices question, but here goes…
I am using a custom excerpt trim function:
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 = '…';
array_pop($words);
$text = implode(' ', $words).$dots.'<p class="moarplz"><a href="'. get_permalink($post->ID) . '">Read More »</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(']]>', ']]>', $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!
I’d simply set a flag as second input argument for the function:
Notes:
class="moarplz"
. It’s hard to read for others and hard for yourself in a year.count
inside anif/for/while/foreach/else/elseif
statement – it’s up to 5 times slower than counting it in the line before.