diff options
author | Gábor Hojtsy <gabor@hojtsy.hu> | 2007-11-23 12:27:38 +0000 |
---|---|---|
committer | Gábor Hojtsy <gabor@hojtsy.hu> | 2007-11-23 12:27:38 +0000 |
commit | b501ff69c6edf703f5f16e8c0ed2dffd781bb793 (patch) | |
tree | 78525b15f6cf83be6159b25aed43d8df7c38cfd3 | |
parent | 5f1d0bf3430afd130ca1a3e6d1b076d5c29c519e (diff) | |
download | brdo-b501ff69c6edf703f5f16e8c0ed2dffd781bb793.tar.gz brdo-b501ff69c6edf703f5f16e8c0ed2dffd781bb793.tar.bz2 |
#180425 by Bevan, tested by gpk: teaser splitter PHP code was breaking too early, not taking break type precedence into account
-rw-r--r-- | modules/node/node.module | 65 |
1 files changed, 43 insertions, 22 deletions
diff --git a/modules/node/node.module b/modules/node/node.module index e16efee42..a1bff842f 100644 --- a/modules/node/node.module +++ b/modules/node/node.module @@ -283,36 +283,57 @@ function node_teaser($body, $format = NULL, $size = NULL) { 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. $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); - // In some cases, no delimiter has been specified. In this case, we try to - // split at paragraph boundaries. - $breakpoints = array('</p>' => 0, '<br />' => 6, '<br>' => 4, "\n" => 1); - // We use strpos on the reversed needle and haystack for speed. - foreach ($breakpoints as $point => $offset) { - $length = strpos($reversed, strrev($point)); - if ($length !== FALSE) { - $position = - $length - $offset; - return ($position == 0) ? $teaser : substr($teaser, 0, $position); + // Build an array of arrays of break points grouped by preference. + $break_points = array(); + + // A paragraph near the end of sliced teaser is most preferable. + $break_points[] = array('</p>' => 0); + + // Other line breaks often indicate a paragraph. + $break_points[] = array('<br />' => 6, '<br>' => 4, "\n" => 1); + + // 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); + } } - } - // When even the first paragraph is too long, we try to split at the end of - // the last full sentence. - $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; + // 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); } } - return ($position == 0) ? $teaser : substr($teaser, 0, $position); + + // If a break point was not found, still return a teaser. + return $teaser; } /** |