registrieren registriertes Mitglied


Anzeige

Anzeige

Teaser aus einem langem Text erstellen

Stell hier Deine Frage zu: HTML, CSS, PHP, MySQL, htaccess, robots.txt, Javascript usw
marc77
PostRank 9
PostRank 9
Beiträge: 983
Registriert: 22.05.2007, 22:41

Beitrag marc77 » 06.02.2016, 17:16 Teaser aus einem langem Text erstellen

Hallo,

ich hab bereits alles versucht um eine Lösung zu finden. Auch bei Stackoverflow konnte niemand helfen.

- Ich stehe mit regex auf Kriegsfuss
- Ich möchte nicht strip_tags verwenden
- html Tags müssen beibehalten werden
- ich kann kein DOM verwenden.

Um den Teaser zu bekommen, muss zuerst der lange Text gekürzt werden. Sofern das kürzen richtig funktioniert, ist der Rest einfach.

Das Problem ist, wenn an der Stelle wo gekürzt wird ein HTML Tag mit Text ist z. B. <b>, <u>, <strong>, <a> etc. dann wird der Text innerhalb dieses Tags ebenfalls gekürzt. Das soll aber nicht sein.

hier die funktion:

Code: Alles auswählen

function truncate&#40;$text, $length = 540, $options = array&#40;&#41;&#41; &#123;
    $default = array&#40;
        'ending' => '...', 'exact' => true, 'html' => true
    &#41;;
    $options = array_merge&#40;$default, $options&#41;;
    extract&#40;$options&#41;;

    if &#40;$html&#41; &#123;
        if &#40;mb_strlen&#40;preg_replace&#40;'/<.*?>/', '', $text&#41;&#41; <= $length&#41; &#123;
            return $text;
        &#125;
        $totalLength = mb_strlen&#40;strip_tags&#40;$ending&#41;&#41;;
        $openTags = array&#40;&#41;;
        $truncate = '';

        preg_match_all&#40;'/&#40;<\/?&#40;&#91;\w+&#93;+&#41;&#91;^>&#93;*>&#41;?&#40;&#91;^<>&#93;*&#41;/', $text, $tags, PREG_SET_ORDER&#41;;
        
        foreach &#40;$tags as $tag&#41; &#123;
            if &#40;!preg_match&#40;'/img|br|input|hr|area|base|basefont|col|frame|isindex|link|meta|param/s', $tag&#91;2&#93;&#41;&#41; &#123;
                if &#40;preg_match&#40;'/<&#91;\w&#93;+&#91;^>&#93;*>/s', $tag&#91;0&#93;&#41;&#41; &#123;
                    array_unshift&#40;$openTags, $tag&#91;2&#93;&#41;;
                &#125; else if &#40;preg_match&#40;'/<\/&#40;&#91;\w&#93;+&#41;&#91;^>&#93;*>/s', $tag&#91;0&#93;, $closeTag&#41;&#41; &#123;
                    $pos = array_search&#40;$closeTag&#91;1&#93;, $openTags&#41;;
                    if &#40;$pos !== false&#41; &#123;
                        array_splice&#40;$openTags, $pos, 1&#41;;
                    &#125;
                &#125;
            &#125;
            $truncate .= $tag&#91;1&#93;;

            $contentLength = mb_strlen&#40;preg_replace&#40;'/&&#91;0-9a-z&#93;&#123;2,8&#125;;|&#&#91;0-9&#93;&#123;1,7&#125;;|&#x&#91;0-9a-f&#93;&#123;1,6&#125;;/i', ' ', $tag&#91;3&#93;&#41;&#41;;
            if &#40;$contentLength + $totalLength > $length&#41; &#123;
                $left = $length - $totalLength;
                $entitiesLength = 0;
                if &#40;preg_match_all&#40;'/&&#91;0-9a-z&#93;&#123;2,8&#125;;|&#&#91;0-9&#93;&#123;1,7&#125;;|&#x&#91;0-9a-f&#93;&#123;1,6&#125;;/i', $tag&#91;3&#93;, $entities, PREG_OFFSET_CAPTURE&#41;&#41; &#123;
                    foreach &#40;$entities&#91;0&#93; as $entity&#41; &#123;
                        if &#40;$entity&#91;1&#93; + 1 - $entitiesLength <= $left&#41; &#123;
                            $left--;
                            $entitiesLength += mb_strlen&#40;$entity&#91;0&#93;&#41;;
                        &#125; else &#123;
                            break;
                        &#125;
                    &#125;
                &#125;

                $truncate .= mb_substr&#40;$tag&#91;3&#93;, 0 , $left + $entitiesLength&#41;;
                break;
            &#125; else &#123;
                $truncate .= $tag&#91;3&#93;;
                $totalLength += $contentLength;
            &#125;
            if &#40;$totalLength >= $length&#41; &#123;
                break;
            &#125;
        &#125;
    &#125; else &#123;
        if &#40;mb_strlen&#40;$text&#41; <= $length&#41; &#123;
            return $text;
        &#125; else &#123;
            $truncate = mb_substr&#40;$text, 0, $length - mb_strlen&#40;$ending&#41;&#41;;
        &#125;
    &#125;
    if &#40;!$exact&#41; &#123;
        $spacepos = mb_strrpos&#40;$truncate, ' '&#41;;
        if &#40;isset&#40;$spacepos&#41;&#41; &#123;
            if &#40;$html&#41; &#123;
                $bits = mb_substr&#40;$truncate, $spacepos&#41;;
                preg_match_all&#40;'/<\/&#40;&#91;a-z&#93;+&#41;>/', $bits, $droppedTags, PREG_SET_ORDER&#41;;
                if &#40;!empty&#40;$droppedTags&#41;&#41; &#123;
                    foreach &#40;$droppedTags as $closingTag&#41; &#123;
                        if &#40;!in_array&#40;$closingTag&#91;1&#93;, $openTags&#41;&#41; &#123;
                            array_unshift&#40;$openTags, $closingTag&#91;1&#93;&#41;;
                        &#125;
                    &#125;
                &#125;
            &#125;
            $truncate = mb_substr&#40;$truncate, 0, $spacepos&#41;;
        &#125;
    &#125;
    $truncate .= $ending;

    if &#40;$html&#41; &#123;
        foreach &#40;$openTags as $tag&#41; &#123;
            $truncate .= '</'.$tag.'>';
        &#125;
    &#125;

    return $truncate;
&#125;
Wie kann das regex in der Funktion so verändert werden, dass html Tags bestehen bleiben aber Text innerhalb der Tags nicht als Wörter interpretiert und somit gekürzt werden?

Anzeige von: