Правильно подставлять строку, содержащую элементы «а» с PHP - PullRequest
0 голосов
/ 09 сентября 2011

В настоящее время я пишу класс, который получает каналы Facebook и Twitter, а затем объединяет их в один для показа на веб-сайте.

Однако я сталкиваюсь с одной проблемой с ограничением вывода любого введенного текста из-за элементов a, которые в итоге не будут закрыты после простой функции substr.

Итак, представьте, у меня есть эта строка:

'Check out our site at <a href="http://site.com/">site.com</a>'

И я хочу ограничить это до 50 символов. Если я просто сделаю substr($input,0,50), я получу следующее:

'Check out our site at <a href="http://site.com/">s'

Незакрытый a элемент, который превратит остальную часть моего сайта в ссылку.

Я подумал, что, возможно, используя DOMDocument, я мог бы временно заменить полный URL только частями между <a></a>, выполнить вычитание, а затем повторно применить ссылку.

Однако я не могу понять, как это сделать, и это оставляет меня с другой проблемой / выбором: что если - учитывая, что я могу временно заменить ссылку - после удаления я получаю половину ссылки:

'Check out our site at sit'

Тогда было бы трудно повторно применить ссылку, поэтому, вероятно, лучше заменить ее на что-то вроде [[id]] и просто сделать так, чтобы скрипт запомнил, как долго длился текст.

В любом случае, есть кто-нибудь, кто может мне помочь с этим?

РЕДАКТИРОВАТЬ это относится только к тегам a, поскольку я strip_tags для всего остального.

Ответы [ 3 ]

1 голос
/ 09 сентября 2011

Этот фрагмент из php.net / substr отлично подходит для этого.

Пример:

echo substrws("Check out our site at <a href=\"http://site.com/\">site.com</a>. It's really <strong>nice</strong>", 50);

Выход:

Check out our site at <a href="http://site.com/">site.com</a>.

Код:

/**
* word-sensitive substring function with html tags awareness
* @param text The text to cut
* @param len The maximum length of the cut string
* @returns string
**/
function substrws( $text, $len=180 ) {

    if( (strlen($text) > $len) ) {

        $whitespaceposition = strpos($text," ",$len)-1;

        if( $whitespaceposition > 0 )
            $text = substr($text, 0, ($whitespaceposition+1));

        // close unclosed html tags
        if( preg_match_all("|<([a-zA-Z]+)>|",$text,$aBuffer) ) {

            if( !empty($aBuffer[1]) ) {

                preg_match_all("|</([a-zA-Z]+)>|",$text,$aBuffer2);

                if( count($aBuffer[1]) != count($aBuffer2[1]) ) {

                    foreach( $aBuffer[1] as $index => $tag ) {

                        if( empty($aBuffer2[1][$index]) || $aBuffer2[1][$index] != $tag)
                            $text .= '</'.$tag.'>';
                    }
                }
            }
        }
    }

    return $text;
}
0 голосов
/ 09 сентября 2011

В конце я написал свою собственную функцию, возможно, мог бы использовать некоторые улучшения, но она работает:

private function substr_html($input,$limit){

    $original = $input;

    if(strlen($input) <= $limit)
        return $input;

    $pattern = '#<a\s+.*?href=[\'"]([^\'"]+)[\'"]\s*?.*?>((?:(?!</a>).)*)</a>#i';   

    // Match all 'a' elements
    preg_match_all($pattern,$input,$matches);

    // If no links were found, perform a simple substr()
    if(count($matches[0]) == 0)
        return substr($input,0,$limit).'...';

    $uni     = sha1(uniqid());      

    preg_replace($pattern,$uni,$input);

    $input  = explode($uni,$input);
    $tmp    = $output = '';

    // Go through the splitted input        
    foreach($input as $i){

        if(strlen($tmp.$i) < $limit){

            // If we can fit the next text value without reaching the limit, do it  
            $tmp    .= $i;
            $output .= $i;

        }else{

            // Add whatever we can fit from the last text value and break the loop
            $diff    = abs($limit - strlen($tmp));
            $output .= substr($i,0,$diff);
            break;

        }

        if(strlen($tmp) < $limit){ // Do we still have room before we reach the limit?

            $nextlink = array_shift($matches[1]);
            $nexttext = array_shift($matches[2]);

            if(strip_tags($nexttext,$this->allowed_tags) != '')
                if(strlen($tmp.$nexttext) < $limit){        

                    // Add the next link if it fits
                    $tmp    .= $nexttext;
                    $output .= '<a href="'.$nextlink.'" target="_blank">'.$nexttext.'</a>';

                }else{

                    // Add whatever we can fit from the last link and break the loop
                    $diff    = abs($limit - strlen($tmp));
                    $output .= '<a href="'.$nextlink.'" target="_blank">'.substr($nexttext,0,$diff).'</a>';
                    break;

                }

        }

    }

    // Trim string and remove linebreaks
    $output = trim(preg_replace('/((<br>|<br\/>|<br \/>){1,})/'," ",$output));

    return $output.(strip_tags($original) != strip_tags($output) ? '...' : '');

}
0 голосов
/ 09 сентября 2011

Другим решением будет strip_tags () - функция php выглядит так:

<?php
$text = '<p>Check out our site at </p><!-- other html stuff anywhere--> <a href="http://site.com/">site.com</a>';
echo strip_tags($text);
echo "\n";

// juts allow <p> and <a>
echo strip_tags($text, '<p><a>');
?>
...