<?php
/**
* Returns an excerpt from the beginning of a string. An attempt is made to
* return whole words only. However, if the beginning of the string up to the
* maximum length consists of all word characters, the string is truncated to
* the maximum length.
*
* @param string $string
* The input string. Multi-line strings are supported.
*
* @param integer $maxLength
* The maximum length of the excerpt, not including the suffix. The actual
* length of the returned string may be shorter (to avoid cutting a word) or
* longer (because of the suffix).
*
* @param integer $minLength
* The minimum length of the excerpt. Word boundaries occurring before this
* character position are ignored. Defaults to 0.
*
* @param string $suffix
* What to append to the excerpt if the input string is longer than the
* maximum length or if forced. By default, an ellipsis ("...").
*
* @param boolean $forceSuffix
* If true, the suffix is appended even if the input string is shorter than
* the maximum length. False by default.
*
* @return string
* An excerpt of the input string, or null if pattern matching failed.
* Exceptions are thrown if the function arguments are incongruent.
*/
function excerpt ($string, $maxLength, $minLength = 0, $suffix = '...', $forceSuffix = false) {
if ($maxLength < 0) {
throw new Exception('Required: $maxLength >= 0');
}
if ($minLength < 0) {
throw new Exception('Required: $minLength >= 0');
}
if ($maxLength < $minLength) {
throw new Exception('Required: $minLength <= $maxLength');
}
$strlen = strlen($string);
if ($strlen <= $maxLength) {
return $string . ($forceSuffix ? $suffix : '');
}
$pattern = sprintf('/\A(.{%1$u,%2$u}(?!\w)|.{0,%2$u})/s', $minLength, $maxLength);
preg_match($pattern, $string, $matches);
$excerpt = $matches[1];
if ($strlen > $maxLength || $forceSuffix) {
$excerpt .= $suffix;
}
return $excerpt;
}
// Usage example
$text = 'The quick brown fox jumped over the lazy dog.';
try {
var_dump(excerpt($text, 20, 10)); // string(22) "The quick brown fox..."
} catch (Exception $e) {
echo $e->getMessage();
}