nortmas
5/12/2014 - 8:17 AM

Обрезать текст сохраняя DOM

function array_remove_first_from_end($array, $exclude = '<br>') {
  $array = array_reverse($array);
  $first = FALSE;
  foreach ($array as $val) {
    if (strtolower($val) == $exclude || $first) {
      $arr[] = $val;
    }
    else {
      $first = TRUE;
    }
  }
  if (is_array($arr)) {
    $arr = array_reverse($arr);
  }
  return $arr;
}

function html_substr($html, $length) {
  $out = '';
  $arr = preg_split('/(<.+?>|&#?\\w+;)/s', $html, -1, PREG_SPLIT_DELIM_CAPTURE);
  $tagStack = array();

  for ($i = 0, $l = 0; $i < count($arr); $i++) {

    if ($i & 1) {
      if (substr($arr[$i], 0, 2) == '</' || substr($arr[$i], 0, 2) == '[/') {
        if (is_array($tagStack) && !empty($tagStack)) {
          $tagStack = array_remove_first_from_end($tagStack);
        }
      }
      elseif ($arr[$i][0] == '&') {
        $l++;
      }
      elseif (substr($arr[$i], -2) != '/>' || substr($arr[$i], -2) != '/]') {
        if (is_array($tagStack)) {
          array_push($tagStack, $arr[$i]);
        }
      }

      $out .= $arr[$i];
    }
    elseif (substr($arr[$i], -2) != '/>') {
      if (($l += strlen($arr[$i])) >= $length) {
        $out .= substr($arr[$i], 0, strpos($arr[$i], ' ', $length - $l + strlen($arr[$i])));
        break;
      }
      else {
        $out .= $arr[$i];
      }
    }
  }

  if (is_array($tagStack)) {
    while (($tag = array_pop($tagStack)) !== NULL) {
      if (strtolower($tag) != '<br>') {
        $out .= '</' . strtok(substr($tag, 1), " \t>") . '>';
      }
    }
  }
  return $out;
}