#180425 by Bevan, tested by gpk: teaser splitter PHP code was breaking too early, not taking break type precedence into account
parent
5f1d0bf343
commit
b501ff69c6
|
@ -283,36 +283,57 @@ function node_teaser($body, $format = NULL, $size = NULL) {
|
||||||
return $body;
|
return $body;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the delimiter has not been specified, try to split at paragraph or
|
||||||
|
// sentence boundaries.
|
||||||
|
|
||||||
// The teaser may not be longer than maximum length specified. Initial slice.
|
// The teaser may not be longer than maximum length specified. Initial slice.
|
||||||
$teaser = truncate_utf8($body, $size);
|
$teaser = truncate_utf8($body, $size);
|
||||||
$position = 0;
|
|
||||||
// Cache the reverse of the teaser.
|
// Store the actual length of the UTF8 string -- which might not be the same
|
||||||
|
// as $size.
|
||||||
|
$max_rpos = strlen($teaser);
|
||||||
|
|
||||||
|
// How much to cut off the end of the teaser so that it doesn't end in the
|
||||||
|
// middle of a paragraph, sentence, or word.
|
||||||
|
// Initialize it to maximum in order to find the minimum.
|
||||||
|
$min_rpos = $max_rpos;
|
||||||
|
|
||||||
|
// Store the reverse of the teaser. We use strpos on the reversed needle and
|
||||||
|
// haystack for speed and convenience.
|
||||||
$reversed = strrev($teaser);
|
$reversed = strrev($teaser);
|
||||||
|
|
||||||
// In some cases, no delimiter has been specified. In this case, we try to
|
// Build an array of arrays of break points grouped by preference.
|
||||||
// split at paragraph boundaries.
|
$break_points = array();
|
||||||
$breakpoints = array('</p>' => 0, '<br />' => 6, '<br>' => 4, "\n" => 1);
|
|
||||||
// We use strpos on the reversed needle and haystack for speed.
|
// A paragraph near the end of sliced teaser is most preferable.
|
||||||
foreach ($breakpoints as $point => $offset) {
|
$break_points[] = array('</p>' => 0);
|
||||||
$length = strpos($reversed, strrev($point));
|
|
||||||
if ($length !== FALSE) {
|
// Other line breaks often indicate a paragraph.
|
||||||
$position = - $length - $offset;
|
$break_points[] = array('<br />' => 6, '<br>' => 4, "\n" => 1);
|
||||||
return ($position == 0) ? $teaser : substr($teaser, 0, $position);
|
|
||||||
|
// If the first paragraph is too long, split at the end of a sentence.
|
||||||
|
$break_points[] = array('. ' => 1, '! ' => 1, '? ' => 1, '。' => 0, '؟ ' => 1);
|
||||||
|
|
||||||
|
// Iterate over the groups of break points until a break point is found.
|
||||||
|
foreach ($break_points as $points) {
|
||||||
|
// Look for each break point, starting at the end of the teaser.
|
||||||
|
foreach ($points as $point => $offset) {
|
||||||
|
// The teaser is already reversed, but the break point isn't.
|
||||||
|
$rpos = strpos($reversed, strrev($point));
|
||||||
|
if ($rpos !== FALSE) {
|
||||||
|
$min_rpos = min($rpos + $offset, $min_rpos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If a break point was found in this group, slice and return the teaser.
|
||||||
|
if ($min_rpos !== $max_rpos) {
|
||||||
|
// Don't slice with length 0. Length must be <0 to slice from RHS.
|
||||||
|
return ($min_rpos === 0) ? $teaser : substr($teaser, 0, 0 - $min_rpos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// When even the first paragraph is too long, we try to split at the end of
|
// If a break point was not found, still return a teaser.
|
||||||
// the last full sentence.
|
return $teaser;
|
||||||
$breakpoints = array('. ' => 1, '! ' => 1, '? ' => 1, '。' => 0, '؟ ' => 1);
|
|
||||||
$min_length = strlen($reversed);
|
|
||||||
foreach ($breakpoints as $point => $offset) {
|
|
||||||
$length = strpos($reversed, strrev($point));
|
|
||||||
if ($length !== FALSE) {
|
|
||||||
$min_length = min($length, $min_length);
|
|
||||||
$position = 0 - $length - $offset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ($position == 0) ? $teaser : substr($teaser, 0, $position);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue