note 88908 deleted from function.substr by danbrown

From: Date: Thu, 12 Feb 2009 21:22:31 +0000
Subject: note 88908 deleted from function.substr by danbrown
References: 1  Groups: php.notes 
Request: Send a blank email to php-notes+get-150591@lists.php.net to get a copy of this message
Note Submitter: alex at sirensclef dot com ---- Here's a quick and dirty function to cut text after the specified number of words, but accounts for XHTML strings. For example: echo summarize('<div><p>This is a test of the summarize function.</p></div><div>This is something else.</div>',7); gives: <div><p>This is a test of the summarize...</p></div> Obviously not something you want to overuse for performance reasons, but there's a fast path for strings that don't contain tags and therefore don't need the extra work. function summarize($str,$limit) { // summarize text up to $limit words, compatible with XHTML strings static $dom; static $limit_reached; static $word_count; if (is_scalar($str) && strpos($str,'<')===false) return sizeof(explode(' ',$str)>$limit) ? implode(' ',array_slice(explode(' ',$str),0,$limit)).'...' : $str; // if string does not contain any tags, do a regular word trim if (is_scalar($str)) { // if this is the first call $dom=new DOMDocument; // create a dom document if (!@$dom->loadXML('<root>'.$str.'</root>')) return $str; // try to load the string, returning the original string if failed $word_count=0; // init word counter $limit_reached=false; // init limited reached flag }; if (is_object($str)) {$node=$str;} // if this is a recursive call, used the passed node else $node=$dom->documentElement; // else use the root element foreach($node->childNodes as $child) if ($child->nodeType==3) { // loop through child text nodes if ($limit_reached) {$node->replaceChild($dom->createTextNode('%removed_node%'), $child);} // remove all nodes after limit reached else { // else if limit has not been reached $words=explode(' ',$child->nodeValue); // create array of words in this node $count=sizeof($words); // get number of words in this node if ($word_count+$count>$limit) { // if addition of these words passes the limit $words=implode(' ',array_slice($words,0,$limit-$word_count)); // create truncated replacement content $node->replaceChild($dom->createTextNode($words.'...'),$child); // swap in replacement content $limit_reached=true; // flag limit as reached } else $word_count+=$count; // else increment the word count and move on to the next node }; } else if ($child->hasChildNodes()) summarize($child,$limit); // else if non-text node with children met, walk it recursively $output=''; // init output if (is_scalar($str)) { // if this is the first call $xpath=new DOMXPath($dom); // create xpath object foreach($xpath->query('//*[.="%removed_node%"]') as $empty_node) $empty_node->parentNode->removeChild($empty_node); // remove all empty nodes foreach($node->childNodes as $child) $output.=$dom->saveXML($child); // add remaining content to output unset($dom); $limit_reached=false; $word_count=0; }; return $output; }

« previous php.notes (#150591) next »