WordPress. Плагин для подсветки php-кода
07.07.2019
Теги: CMS • PHP • Web-разработка • WordPress • Плагин
Давайте создадим плагин, который позволит подсвечивать php-код в записях блога. Для подсветки используем нативную php-функцию highlight_string()
. Добавлять php-код в запись можно будет с помощью шорткода [php]
. Практической ценности плагин не представляет, написан исключительно с целью изучения WordPress.
Главная трудность при реализии плагина — это автоматические замены. WordPress заменяет одинарные и двойные кавычки на лапки и елочки. И заменяет двойные и одинарные переводы строк на теги <p>
и <br/>
.
Плагин для подсветки php-кода
Итак, создаем директорию highlight-php-code
, а внутри нее — файл highlight-php-code.php
:
<?php /* Plugin Name: Подсветка php-кода Plugin URI: https://tokmakov.msk.ru Description: Добавляет шорткод [php] для подсветки php-кода Version: 1.0 Author: Евгений Токмаков Author URI: https://tokmakov.msk.ru */ /* * Добавляем шорткод [php], который позволит вставлять в записи * блога php-код */ add_shortcode('php', function($atts, $content) { if (empty($content)) { return ''; } $content = trim($content); /* * При сохранении записи блога, переводы строк записываются в базу данных * как \r\n. При выводе записи блога функция highlight_string() заменяет * символ \n на тег <br/>, а вот символ \r остается. И внутри тега <pre> * добавляет лишнюю пустую строку между строк подсвеченного php-кода. Так * что удаляем символ \r, чтобы этого избежать. */ $content = str_replace("\r", '', $content); /* * При обработке шорткодов WP производит замены в $content: * 1. открывающих прямоугольных кавычек [ на [ * 2. закрывающих прямоугольных кавычкек ] на ] * Так что нам здесь надо произвести обратные замены. */ $content = str_replace(['[', ']'], ['[', ']'], $content); $content = '<pre>' . highlight_string($content, true) . '</pre>'; // убираем перевод строки, который добавляет highlight_string() $content = str_replace("\n", '', $content); return $content; }); /* * Функция wpautop заменяет переводы строк на теги <p> и <br/>. И * это ломает код внутри шорткода [php]. Это происходит потому, * что функция wpautop выполняется раньше функции do_shortcode. * Поэтому сначала отключаем функцию wpautop для контента записи, * чтобы функция do_shortcode успела обработать шорткод [php], а * потом включаем ее снова. */ remove_filter('the_content', 'wpautop'); add_filter('the_content', 'wpautop', 99); /* * Запрещаем функцию wptexturize внутри шорткода [php], которая * заменяет одинарные и двойные кавычки на лапки и елочки, чтобы * эта функция не ломала php-код. */ add_filter('no_texturize_shortcodes', function ($shortcodes) { $shortcodes[] = 'php'; return $shortcodes; });
Функция wpautop()
заменяет двойной перенос строки на теги <p>
и </p>
, а одинарный — на тег <br/>
. По умолчанию применяется к следующим фильтрам:
add_filter('term_description', 'wpautop'); add_filter('get_the_post_type_description', 'wpautop'); add_filter('the_content', 'wpautop'); add_filter('the_excerpt', 'wpautop'); add_filter('comment_text', 'wpautop', 30); add_filter('widget_text_content', 'wpautop'); add_filter('the_excerpt_embed', 'wpautop');
Если нужно отключить этот фильтр у контента записи (the_content
) или цитаты (the_excerpt
), то добавляем в functions.php
следующий код:
remove_filter('the_content', 'wpautop'); remove_filter('the_excerpt', 'wpautop');
Функция wptexturize()
изменяет некоторые символы в тексте на более правильные, читаемые и визуально привлекательные. Текст внутри HTML блоков <pre>
, <code>
, <kbd>
, <style>
, <script>
, <tt>
и в шорткоде [code]
пропускается.
Список всех фильтров, к которым по умолчанию применяется функция:
add_filter('comment_author', 'wptexturize'); add_filter('term_name', 'wptexturize'); add_filter('link_name', 'wptexturize'); add_filter('link_description', 'wptexturize'); add_filter('link_notes', 'wptexturize'); add_filter('bloginfo', 'wptexturize'); add_filter('wp_title', 'wptexturize'); add_filter('widget_title', 'wptexturize'); add_filter('single_post_title', 'wptexturize'); add_filter('single_cat_title', 'wptexturize'); add_filter('single_tag_title', 'wptexturize'); add_filter('single_month_title', 'wptexturize'); add_filter('nav_menu_attr_title', 'wptexturize'); add_filter('nav_menu_description', 'wptexturize'); add_filter('term_description', 'wptexturize'); add_filter('get_the_post_type_description', 'wptexturize'); add_filter('the_title', 'wptexturize'); add_filter('the_content', 'wptexturize'); add_filter('the_excerpt', 'wptexturize'); add_filter('the_post_thumbnail_caption', 'wptexturize'); add_filter('comment_text', 'wptexturize'); add_filter('list_cats', 'wptexturize'); add_filter('widget_text_content', 'wptexturize'); add_filter('the_excerpt_embed', 'wptexturize');
Если нужно указать html теги или шоткоды, где функция работать не должна, то можно использовать фильтры no_texturize_tags
и no_texturize_shortcodes
соответственно.
Альтернативная реализация подсветки
Без использования шорткода, просто с использованием тега <pre>
:
add_filter('the_content', function($content) { $content = preg_replace_callback( '~(<pre[^>]*>)\s*(.*?)\s*(</pre>)~s', function($match){ $code = $match[2]; $code = str_replace("\r", '', $code); $code = $match[1] . highlight_string($code, true) . $match[3]; // убираем перевод строки, который добавляет highlight_string $code = str_replace("\n", '', $code); return $code; }, $content ); return $content; });
Столкнулся с неожиданным багом — перестал корректно работать плагин галереи. Это произошло потому, что в html-коде галереи WordPress заменил переводы строк на тег <br/>
. В итоге получилось следующее:
<div class="gallery-images"> <a href="..." class="swipebox" title="..." rel="..."><br /> <img src="..." alt="..." /><br /> </a><br /> <a href="..." class="swipebox" title="..." rel="..."><br /> <img src="..." alt="..." /><br /> </a><br /> <a href="..." class="swipebox" title="..." rel="..."><br /> <img src="..." alt="..." /><br /> </a><br /> </div>
В этом виноват вот этот фрагмент кода плагина подсветки php-кода:
remove_filter('the_content', 'wpautop'); add_filter('the_content', 'wpautop', 99);
Так что пришлось добавить в плагин галереи небольшой хак, который вырезает теги <br/>
внутри html-кода галереи:
add_filter( 'the_content', function($content) { $content = preg_replace_callback( '~(<div class="gallery-images">)(.*?)(</div>)~s', function($match){ $html = $match[1].strip_tags($match[2],'<a><img>').$match[3]; return $html; }, $content ); return $content; }, 100 );
- WordPress. Установка и использование WP-CLI
- WordPress. Фильтр записей по произвольным полям. Часть 3 из 3
- WordPress. Фильтр записей по произвольным полям. Часть 2 из 3
- WordPress. Фильтр записей по произвольным полям. Часть 1 из 3
- WordPress. Добавляем мета-теги. Часть 3 из 3
- WordPress. Метабоксы. Часть 2 из 2
- WordPress. Произвольные типы записей
Поиск: PHP • Web-разработка • WordPress • Плагин • Shortcode • Шорткод • highlight_string • PHP • Подсветка кода • wpautop • wptexturize