0

This function is supposed to trim down a string to the given number of characters or the given number of words, what ever is shorter. And if it truncates the string, append a "..." to it.

It works except when I run it with a URL like string, then it just returns the "..." by itself.

For example:

truncate('https://accounts.google.com/SignUp?service=youtube&continue=http%3A%2F%2Fwww.youtube.com%2Fsignin%3Faction_handle_signin%3Dtrue%26feature%3Dplaylist%26hl%3Den_US%26next%3D%252Faccount_recovery%26nomobiletemp%3D1', 1, 85);

Here is the function:

function truncate($input, $maxWords, $maxChars){
$words = preg_split('/\s+/', $input);
$words = array_slice($words, 0, $maxWords);
$words = array_reverse($words);

$chars = 0;
$truncated = array();

while(count($words) > 0)
{
    $fragment = trim(array_pop($words));
    $chars += strlen($fragment);

    if($chars > $maxChars) break;

    $truncated[] = $fragment;
}

    $result = implode($truncated, ' ');

    return $result . ($input == $result ? '' : '...');
}

What am I doing wrong? Why does it return "..." in this case, but in multi-word sentences it works fine?

irfan mir
  • 373
  • 2
  • 4
  • 10

1 Answers1

0

The problem is that the only word in your example string is too long and therefore you don't add it to the $truncated array.

You could consider this:

  if ($chars > $maxChars) {
       if (!$truncated) { // no captured words yet, add as much as possible
           $truncated[] = substr($fragment, 0, $maxChars - $chars);
       }
       break;
  }

It copies the word until it fills up exactly $maxChars if you don't have any captured words yet. Output:

https://accounts.google.com/SignUp?service=youtube&continue=http%3A%2F%2Fwww.youtube....

Proof

Ja͢ck
  • 170,779
  • 38
  • 263
  • 309
  • Ah, I see. But that gives the whole thing plus the "..." How can I give just what it is in the character limit and the "..." – irfan mir May 30 '13 at 02:17
  • For example, `truncate('https://accounts.google.com/ServiceLogin?hl=en_US&continue=http%3A%2F%2Fwww.youtube.com%2Fsignin%3Faction_handle_signin%3Dtrue%26feature%3Dsign_in_promo%26hl%3Den_US%26next%3D%252Fchannels%26nomobiletemp%3D1&passive=true&service=youtube&uilel=3', 1, 85);` returns `'https://accounts.google.com/ServiceLogin?hl=en_US&continue=http%3A%2F%2Fwww.youtube.com%2Fsignin%3Faction_handle_signin%3Dtrue%26feature%3Dsign_in_promo%26hl%3Den_US%26next%3D%252Fchannels%26nomobiletemp%3D1&passive=true&service=youtube&uilel=3'...` – irfan mir May 30 '13 at 02:18
  • @irfanmir No it doesn't. It truncates it to 85 characters; have you even tried the code? – Ja͢ck May 30 '13 at 02:24
  • @irfanmir I've updated my answer with the output I get after applying the proposed code change. – Ja͢ck May 30 '13 at 02:32