WordPress как на ладони
wordpress jino

Меняем HTML символы (< >) на спецсимволы при комментировании

Недавно писал о том, как вставлять код в текст статьи. Сегодня хочу поделится способом удобной вставки кода в тело комментария.

Задача: в комментариях, найти теги <pre> и <code> и внутри них  заменить все символы < и > на соответствующие им спецсимволы: &lt; и&gt;.

Тут важно определится, когда делать замену. К примеру, некоторые плагины делают замену во время генерации страницы, т.е. всегда при открытии страницы к каждому комментарию применяется функция преобразования и измененный комментарий выводится на экран. Я еще не видел плагина, который бы делал замену перед записью текста в базу данных, чтобы потом просто получить текст, без преобразований. Мне кажется это лучшим подходом. В крайнем случае всегда можно обратно произвести замену, там где это нужно...

Решение задачи (новая версия кода):

add_filter('pre_comment_content', 'kama_convert_html');
/*
 * Преобразует html символы: < > внутри тегов pre|code во спецсимволы < > в тексте
 * v1.0
 */
function kama_convert_html_entities( $text, $convert_in='pre|code|var'){
	return preg_replace_callback ('!<('. $convert_in .')([^>]*)>(.*?)</\\1>!ims', '__kama_convert_html_entities_cb', $text);
}
function __kama_convert_html_entities_cb( $matches ){
	$out = str_replace( array('<','>'), array('<','>'), $matches[3] );
	$out = preg_replace( "~((?<=\n|^|\t))[ ]{4}~m", "\\1\t", $out ); // заменяем 4 пробела на табы

	return "<$matches[1]$matches[2]>$out</$matches[1]>";
}

Функцию поместите в файл functions.php вашего шаблона (вашей темы).

Что делает функция?

При публикации комментария, функция находит текст внутри тегов <pre> и/или <code> и в найденном тексте заменяет символы < и > на &lt; и &gt;.

Замена происходит перед тем, как текст комментария записывается в Базу Данных. Если нужно заменять прямо перед выводом текста на экран, то замените строку:

add_filter('pre_comment_content', 'kama_convert_html');
// на
add_filter('comment_text', 'kama_convert_html');

 

Как проверить что все работает?

После установки функции попробуйте оставить комментарий с таким текстом:

Проверка преобразования символов в комментариях. <div></div>
<code>Здесь будет код <div> </code>
Первый промежуточный текст <span></span>
<pre>Здесь будет код 2 <span> </pre>
Промежуточный текст <strong></strong>
<code>Здесь будет еще немного кода <div> </code>
Еще немного простого текста <b></b>
<pre>Здесь будет код <span> </pre>
В заключении еще немного текста <div></div>

В результате в базу данных должен записаться следующий текст:

Проверка преобразования символов в комментариях. <div></div>
<code>Здесь будет код &lt;div&gt; </code>
Первый промежуточный текст <span></span>
<pre>Здесь будет код 2 &lt;span&gt; </pre>
Промежуточный текст <strong></strong>
<code>Здесь будет еще немного кода &lt;div&gt; </code>
Еще немного простого текста <b></b>
<pre>Здесь будет код &lt;span&gt; </pre>
В заключении еще немного текста <div></div>

Сохранение любого кода в тексте статьи (поста)

Такой же трюк можно сделать и с контентом статьи. Для этого внизу функции допишите еще один фильтр:

add_filter('pre_comment_content', 'kama_convert_html');
// При обновлении поста в админке
add_filter('content_save_pre', 'kama_convert_html');

Старая версия

Старая (первая) версия кода, работает также, только код более длинный:

/* Преобразуем хтмл символы  < > в спецсимволы при отправке комментария */
function kama_html_replace_char_pre( $matches ){
	$out = str_replace (array ('<'   ,'>'),   array ('&lt;','&gt;'),  $matches[2] );
	return "<pre{$matches[1]}>".$out."</pre>";
}
function kama_html_replace_char_code ($matches){
	$out = str_replace (array ('<'   ,'>'),   array ('&lt;','&gt;'),  $matches[2] );
	return "<code{$matches[1]}>".$out."</code>";
}
function kama_convert_html ($comment_text){ // подготавливает контент комментатора
	$comment_text = preg_replace_callback ('!<pre([^>]*)>(?:\r\n|\n|\r|)(.*?)(?:\r\n|\n|\r|)</pre>!ims', 'kama_html_replace_char_pre', $comment_text);
	$comment_text = preg_replace_callback ('!<code([^>]*)>(?:\r\n|\n|\r|)(.*?)(?:\r\n|\n|\r|)</code>!ims', 'kama_html_replace_char_code', $comment_text);
	return $comment_text;
}
add_filter ('pre_comment_content','kama_convert_html');
Меняем HTML символы (< >) на спецсимволы при комментировании 13 комментариев
Полезные 1 Все
  • Ctrogo @

    А как вы заменили стандартные XHTML: Вы можете использовать следующие теги: <a href="" title="" rel="nofollow"> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> на кнопочки? Есть ли плагин для этого?

    Ответить6.5 лет назад #
  • Kverde cайт: kverde.ru

    у меня заработала только когда сделал так:

    <?php  
    	/* Преобразуем хтмл символы  < > в спецсимволы при отправке комментария */  
    	function kama_html_replace_char_code_pre ($matches){  
    		$out = str_replace (array ('<'   ,'>'),   array ('<','>'),  $matches[3] );  
    		return "<{$matches[1]}{$matches[2]}>".$out."</{$matches[1]}>";  
    	}  
    	function kama_convert_html ($comment_text){ // подготавливает контент комментатора  
    		$comment_text = preg_replace_callback ('!<(pre|code)([^>]*)>(?:\r\n|\n|\r|)(.*?)(?:\r\n|\n|\r|)</\\1>!ims', 'kama_html_replace_char_code_pre', $comment_text);  
    		return $comment_text;  
    	}  
    
    	add_filter ('pre_comment_content','kama_convert_html'); 
    //Скопировал эту строку еще раз. 
    	add_filter ('pre_comment_content','kama_convert_html');  
    	 ?>

    И еще уже второй день думаю почему так?

    str_replace (array ('<'   ,'>'),   array ('<','>'),  $matches[3]);

    вроде как заменять на & lt; & gt; нужно (пробелы добавил чтобы не преобразовывалось), а так ведь строка не должна изменятся.

    Ответить6.2 лет назад #
    • Kverde cайт: kverde.ru

      Поспешил, ничего не заработало smile

      Если делаю так:

      function kama_html_replace_char_code_pre ($matches){
      	$out = str_replace (array ('<'   ,'>'),   array ('& lt;','& gt;'),    $matches[3] ); // без пробелов.
      	return "<{$matches[1]}{$matches[2]}>".$out."</{$matches[1]}>";
      }
      function kama_convert_html ($comment_text){ // подготавливает контент комментатора
      	$comment_text = preg_replace_callback ('!<(pre|code)([^>]*)>(?:\r\n|\n|\r|)(.*?)(?:\r\n|\n|\r|)</\\1>!ims', 'kama_html_replace_char_code_pre', $comment_text);
      	return $comment_text;
      }
      add_filter ('pre_comment_content','kama_convert_html');

      то сохраняется так & amp;lt; (без пробела). Думаю где-то ампресанд заменяется..

      Ответить6.2 лет назад #
    • Kama4639

      Ага, у меня в коде была ошибка, поправил. Спасибо что указали на нее.

      Строка должна выглядеть так:

      $out = str_replace (array ('<'   ,'>'),   array ('&lt;','&gt;'),  $matches[3] );
      Ответить6.2 лет назад #
      • Kverde cайт: kverde.ru

        Но у меня почему-то все равно не работает.

        Без функции так:

        админ. - кавычки преобразованы в &lt; (и все отображается как нужно)
        посетитель - теги вырезаются.

        с функцией:

        у админа и посетителя кавычки преобразуются в &amp;lt;, соотвественно в комментариях выводится &lt; вместо кавычек.

        Уже по всякому пробовал, ничего не получилось пока sad

        Ответить6.2 лет назад #
        • Kama4639

          У вас видимо есть еще какой-то плагин, который конфликтует в этим кодом. Т.е. мой код заменяет кавычки, а тот плагин затем преобразует & в &amp;

          Ответить6.2 лет назад #
  • Master @

    Привет, Тимур! С наступающим Новым Годом!
    У меня вопрос по SyntaxHighlighter Evolved. Проблема такая, что при выводе кода на странице заменяются символы и другие на спец. символы. Я не хочу, чтобы они заменялись, а выводились в XHTML. Как это реализовать? Не силен в этом вопросе, к сожалению. Не поможете разобраться?
    Заранее спасибо. Надеюсь на скорый ответ, желательно на e-mail.

    Ответить5.8 лет назад #
  • Дмитрий cайт: artcafe-jw.ru @

    День добрый!
    Спасибо за толковые статьи! smile
    А разве функции htmlentities и htmlspecialchars не решают данную проблему, вместо того, чтобы регулярки гонять?

    Ответить5.3 лет назад #
    • Kama4639

      У меня там регулярка для замены только внутри pre|code, если вы не заметили. И htmlentities и htmlspecialchars такое не умеют, к тому же у них будет двойное преобразование для амперсанда, например, для такого в коде: &amp;, получим &amp;amp;!

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

      Ответить5.3 лет назад #
  • parmactep cайт: blog.brainf.net

    Почему авторы плагинов не используют этот подход мне не понятно

    Разработчикиплагинов так не делают потому что перед записью в базу теги экранируются...

    Ответить4.9 года назад #
    • Kama4639

      А при извлечении экранирование снимается. И что? Не понял. У меня есть своя версия этого "почему" и она никак не связана с экранированием, а связана со здравым смыслом: оставляя все как есть, разработчики дают возможность налету изменять данные, как нужно для каждого конкретного сайта.

      Ответить4.9 года назад #
  • Есть еще одна неувязочка.. закрывающий тэг 'pre' в тэге 'pre'))

    ... wp_qwerty(); .

    . wp_qwerty(); ...

    ...
    придется знак '<' тэга pre в тэге pre править вручную... вставлять html символ '&lt ;'

    ... wp_qwerty(); . </pre> . wp_qwerty(); ...

    laugh

    Ответить2.3 года назад #

Здравствуйте, !

Ваш комментарий