How about using a regular expression to find all of the whitespace, then truncate
at the the match that is largest but still less than or equal to your desired length.
function truncate($text, $length) {
$length = abs((int)$length);
$count = preg_match_all("(\s+)", $text, $matches, PREG_OFFSET_CAPTURE);
while ($count > 0) {
if ($matches[$count][0] <= $length) {
$length = $matches[$count][0];
break;
}
$count = $count - 1;
}
return substr($text, 0, $length)
}