TinyButStrong - the PHP Template Engine
Categories > Your tips & tricks >

Shorten HTML text and close open tags

The forum is closed. Please use Stack Overflow for submitting new questions. Use tags: tinybutstrong , opentbs

By: Rudy
Date: 2011-09-11
Time: 23:30

Shorten HTML text and close open tags

Hi,

I'd like to share what I use to shorten html text with TBS. This format function shortens the text to the "snippet_length" and closes open (allowed) html tags (p, strong, em, blockquote), after operation (something I wish "ope=max:n;maxhtml" would do :)).

usage:
[myblock.longhtmldescription;onformat=fmt_html_snippet;snippet_length=200]
Also accepts the optional parameters add_if_cut and add_not_cut, both of which can hold text or markup to be added to the shortened (or not shortened) html text. These are not the "...", those are added by default if needed.

  function fmt_html_snippet($fieldname, & $html, & $params) {
    $html = strip_tags(($html), '<p><strong><em><br><blockquote>'); //allowed html elements
    $length = isset($params['snippet_length']) ? (int)$params['snippet_length'] : 0; //how long should the snippet be
    $add_if_cut = isset($params['add_if_cut']) ? $params['add_if_cut'] : ''; //to add if cut (e.g. "(more..)" or a link
    $add_not_cut = isset($params['add_not_cut']) ? $params['add_not_cut'] : ''; //to add if text was short enough and has not been cut
    if ($length > 0 && mb_strlen(strip_tags($html)) > $length) {
      $text_length = $html_length = 0;
      $lt = mb_strpos($html, '<');
      if ($lt !== false) {
        $gt = mb_strpos($html, '>');
        $text_length = $lt;
        $html_length = $gt - $lt + 1;
        while ($gt > $lt && $lt !== false) {
          $lt = mb_strpos($html, '<', $gt);
          $text_length += $lt - $gt - 1;
          if ($text_length >= $length) {
            break;
          }
          $gt = mb_strpos($html, '>', $lt);
          $html_length += $gt - $lt + 1;
        }
        $charcount = $html_length + $length;
      } else {
        $charcount = $length;
      }
      $html = mb_substr($html, 0, $charcount-1).'...';
      preg_match_all("#<([a-z]+)( .*)?(?!/)>#iU", $html, $result);
      $openedtags= $result[1];
      preg_match_all("#</([a-z]+)>#iU", $html, $result);
      $closedtags = array_reverse($result[1]);
      foreach($closedtags as $ckey => $closedtag) {
        foreach($openedtags as $okey => $openedtag) {
          if ($openedtag == $closedtag) {
            unset($openedtags[$okey]);
            break;
          }
        }
      }
      $openedtags = array_reverse($openedtags);
      foreach($openedtags as $tag) {
        if ($tag != 'br') {
          $html .= '</'.$tag.'>';
        }
      }
      $html = $html . $add_if_cut;
    } else {
      $html = $html. $add_not_cut;
    }
  }

Hope this is useful to someone.

Bye
Rudy