pff me respondo sacado de cakephp
Código PHP:
function truncate($text, $length = 100, $ending = '...', $exact = true, $considerHtml = false) {
164 if (is_array($ending)) {
165 extract($ending);
166 }
167 if ($considerHtml) {
168 if (mb_strlen(preg_replace('/<.*?>/', '', $text)) <= $length) {
169 return $text;
170 }
171 $totalLength = mb_strlen($ending);
172 $openTags = array();
173 $truncate = '';
174 preg_match_all('/(<\/?([\w+]+)[^>]*>)?([^<>]*)/', $text, $tags, PREG_SET_ORDER);
175 foreach ($tags as $tag) {
176 if (!preg_match('/img|br|input|hr|area|base|basefont|col|frame|isindex|link|meta|param/s', $tag[2])) {
177 if (preg_match('/<[\w]+[^>]*>/s', $tag[0])) {
178 array_unshift($openTags, $tag[2]);
179 } else if (preg_match('/<\/([\w]+)[^>]*>/s', $tag[0], $closeTag)) {
180 $pos = array_search($closeTag[1], $openTags);
181 if ($pos !== false) {
182 array_splice($openTags, $pos, 1);
183 }
184 }
185 }
186 $truncate .= $tag[1];
187
188 $contentLength = mb_strlen(preg_replace('/&[0-9a-z]{2,8};|&#[0-9]{1,7};|&#x[0-9a-f]{1,6};/i', ' ', $tag[3]));
189 if ($contentLength + $totalLength > $length) {
190 $left = $length - $totalLength;
191 $entitiesLength = 0;
192 if (preg_match_all('/&[0-9a-z]{2,8};|&#[0-9]{1,7};|&#x[0-9a-f]{1,6};/i', $tag[3], $entities, PREG_OFFSET_CAPTURE)) {
193 foreach ($entities[0] as $entity) {
194 if ($entity[1] + 1 - $entitiesLength <= $left) {
195 $left--;
196 $entitiesLength += mb_strlen($entity[0]);
197 } else {
198 break;
199 }
200 }
201 }
202
203 $truncate .= mb_substr($tag[3], 0 , $left + $entitiesLength);
204 break;
205 } else {
206 $truncate .= $tag[3];
207 $totalLength += $contentLength;
208 }
209 if ($totalLength >= $length) {
210 break;
211 }
212 }
213
214 } else {
215 if (mb_strlen($text) <= $length) {
216 return $text;
217 } else {
218 $truncate = mb_substr($text, 0, $length - strlen($ending));
219 }
220 }
221 if (!$exact) {
222 $spacepos = mb_strrpos($truncate, ' ');
223 if (isset($spacepos)) {
224 if ($considerHtml) {
225 $bits = mb_substr($truncate, $spacepos);
226 preg_match_all('/<\/([a-z]+)>/', $bits, $droppedTags, PREG_SET_ORDER);
227 if (!empty($droppedTags)) {
228 foreach ($droppedTags as $closingTag) {
229 if (!in_array($closingTag[1], $openTags)) {
230 array_unshift($openTags, $closingTag[1]);
231 }
232 }
233 }
234 }
235 $truncate = mb_substr($truncate, 0, $spacepos);
236 }
237 }
238
239 $truncate .= $ending;
240
241 if ($considerHtml) {
242 foreach ($openTags as $tag) {
243 $truncate .= '</'.$tag.'>';
244 }
245 }
246
247 return $truncate;
248 }