Обрезать слова, но останавливаться в конце элемента HTML, если найден - PullRequest
0 голосов
/ 06 марта 2019

Эта функция прекрасно работает, однако, если html-элемент найден, он остановится там, где не имеет значения 45-й символ, что нарушает html-элемент. Как я могу сделать исключение для этого? Я предполагаю какое-то регулярное выражение, но не уверен, что лучше в этом случае.

public function fts_custom_trim_words( $text, $num_words = 45, $more ) {
    ! empty( $num_words ) && 0 !== $num_words ? $more = __( '...' ) : '';
    $text = nl2br( $text );
    $text = strip_shortcodes( $text );
    // Add tags that you don't want stripped.
    $text        = strip_tags( $text, '<strong><br><em><i><a>' );
    $words_array = preg_split( "/[\n\r\t ]+/", $text, $num_words + 1, PREG_SPLIT_NO_EMPTY );
    $sep         = ' ';
    if ( count( $words_array ) > $num_words ) {
        array_pop( $words_array );
        $text_string = implode( $sep, $words_array );
        $text        = $text_string . $more;
    } else {
        $text = implode( $sep, $words_array );
    }

    return wpautop( $text );
}

Прямо сейчас это сломает что-то вроде этого ...

@ aeocreative и я в журнале Sarasota Magazine "Дом года"! Я сфотографировал дом для @tracee_murphy из

Ответы [ 2 ]

1 голос
/ 07 марта 2019

это может работать, не проверялось, но должно работать и делать то, что вы просили ...

это первый способ - обрезать @ количество символов

<?php

function truncate_by_characters ( $s, $l = 45, $e = '...' )
{
    $sl = strlen ( $s );

    $ns = 0;

    $cr = 0;

    $rs = '';

    preg_match_all ( '/<[^>]*>[^<]+<\/[^>]*>|<(?!\/)[^>]*>/', $s, $m, PREG_OFFSET_CAPTURE | PREG_SET_ORDER );

    foreach ( $m as $v )
    {
        if ( ( $v[0][1] - $ns ) >= $l )
        {
            break;
        }

        $ss = substr ( $s, $ns, ( $v[0][1] - $ns ) );

        $cr += strlen ( $ss );

        $rs .= $ss . $v[0][0];

        $ns = ( $v[0][1] + strlen ( $v[0][0] ) );
    }

    if ( $cr < $l )
    {
        if ( ( $ns + ( $l - $cr ) ) > $sl )
        {
            $ts = substr ( $s, $ns, ( $sl - $ns ) );
        }
        else
        {
            $ts = substr ( $s, $ns, ( $l - $cr ) );
        }

        for ( $x = ( strlen ( $ts ) - 1 ); $x >= 0; $x -= 1 )
        {
            $z = array ( "\t", "\r", "\n", " ", "\0", "\x0B" );

            if ( in_array ( $ts[$x], $z ) )
            {
                $rs .= substr ( $ts, 0, $x );

                break;
            }
        }
    }

    return $rs . $e;
}

$truncate_text = 'This <img src="" alt=""> function works great however if a <a href="http://.com/page.html?test=1">html element</a> is found it will stop where the 45th character count is no matter what, which breaks the html element. How can I make an exception for this? I\'m guessing some kind of regex but not sure what is best in this case.';

//$truncate_text = 'This function works great however if a html element is found it will stop where the 45th character count is no matter what, which breaks the html element. How can I make an exception for this? I\'m guessing some kind of regex but not sure what is best in this case.';

$truncate_characters = 45;

$truncate_ending = '...';

echo truncate_by_characters ( $truncate_text, $truncate_characters, $truncate_ending );

?>

ПРИМЕЧАНИЕ.вышеуказанная функция работает, однако нижеприведенная функция не дает никаких результатов.

этот второй - усечь @ количество слов

<?php

function truncate_by_words ( $s, $l = 45, $e = '...' )
{
    $sl = strlen ( $s );

    $ns = 0;

    $tw = 0;

    $rs = '';

    preg_match_all ( '/<[^>]*>[^<]+<\/[^>]*>|<(?!\/)[^>]*>/', $s, $m, PREG_OFFSET_CAPTURE | PREG_SET_ORDER );

    foreach ( $m as $v )
    {
        $ss = substr ( $s, $ns, ( $v[0][1] - $ns ) );

        $wf = str_word_count ( $ss, 2 );

        $wc = count ( $wf );

        if ( ( $tw + $wc ) >= $l )
        {
            $mw = 1;

            foreach ( $wf AS $wp => $wv )
            {
                if ( ( $tw + $mw++ ) == $l )
                {
                    $ss = substr ( $s, $ns, ( $wp - $ns ) );

                    $rs .= $ss . $wv;

                    $ns = ( $wp + strlen ( $wv ) );

                    $tw = $l;

                    break;
                }
            }
        }

        $tw += $wc;

        $rs .= $ss . $v[0][0];

        $ns = ( $v[0][1] + strlen ( $v[0][0] ) );
    }

    if ( $tw < $l )
    {
        $ss = substr ( $s, $ns, ( $sl - $ns ) );

        $wf = str_word_count ( $ss, 2 );

        $wc = count ( $wf );

        if ( ( $tw + $wc ) <= $l )
        {
            $rs .= $ss;
        }
        else
        {
            $mw = 1;

            foreach ( $wf AS $wp => $wv )
            {
                if ( ( $tw + $mw++ ) == $l )
                {
                    $ss = substr ( $ss, 0, $wp );

                    $rs .= $ss . $wv;

                    break;
                }
            }
        }
    }

    return $rs . $e;
}

$truncate_text = 'This <img src="" alt=""> function works great however if a <a href="http://.com/page.html?test=1">html element</a> is found it will stop where the 45th character count is no matter what, which breaks the html element. How can I make an exception for this? I\'m guessing some kind of regex but not sure what is best in this case.';

//$truncate_text = 'This function works great however if a html element is found it will stop where the 45th character count is no matter what, which breaks the html element. How can I make an exception for this? I\'m guessing some kind of regex but not sure what is best in this case.';

$truncate_words = 35;

$truncate_ending = '...';

echo truncate_by_words ( $truncate_text, $truncate_words, $truncate_ending );

?>
0 голосов
/ 06 марта 2019

У вас есть два варианта:

1) Использовать PHP stript_tags() (простой вариант) Это вернет простой текст, любые теги в строке больше не будут работать (т.е. <a>, <strong>, <li> и т. Д. Реализация будет выглядеть так:

$text = strip_tags($text);

2) Используйте предложение @Chris Harrison здесь: Текстовая строка ограничения PHP НЕ включает html-теги?

Эта опция хранит теги, но потребует, чтобы вы перестроили свою функцию, чтобы она была более сложной.

UPDATE

Возможно, это не то, что вы ищете, но я создал простое решение, которое разбивает строку на куски, а затем проверяет каждый кусок. Он не такой точный, как вариант 2, но кода для его обслуживания гораздо меньше.

function truncate($string, $maxChars) {
    // Explode input string on a character
    $stringParts = explode(' ', $string);
    $finalString = '';
    $charCount = 0;
    foreach ($stringParts as $part) {
        if ($charCount <= $maxChars) {
            $charCount += strlen(strip_tags($part));
            $finalString .= (' ' . $part);
        } else {
            return $finalString;
        }
    }
}
...