Самое важное в движке, претендующем на универсальность, — расширяемость и масштабируемость. Рассматривая же любые CMS этот момент как-то упоминают вскользь или замалчивают вовсе — а ведь отрицать, что тот же ВП стал популярным именно из-за этих свойств, никто не будет.
Стоит только посмотреть, как по всему коду раскиданы хуки, на которые можно навешивать свои действия практически в любой стадии выполнения скриптов и расширять функционал блога в любой части фронтенда и админки (к сожалению, это не до конца так — есть некоторое количество узких мест, ограничивающих фантазию разработчика). И сказать спасибо разработчикам хоть за это.
Не удивительно, что, используя популярнейшую реализацию визуального редактора (который сам по себе обладает scalability&extensibility в полной мере) Вордпресс дает плагинам непосредственный доступ и к нему.
Именно это я и использовал, чтобы упростить вставку шорткода в моем исправлении популярного плагина Livejournal Crossposter (текст внутри такого шорткода теперь не отдается в кросспост) — соответствующие кнопки добавляются в оба редактора ВП. И многим другим плагинам такая фича тоже не помешает.
Но сначала посмотрим, как это делается в не-визуальной версии.
У нас есть подключаемый quicktags.js, внутри — массив подключаемых кнопок и сам функционал обработки. Задача простая — не изменяя сам этот файл, добавить в массив еще одно значение, соответствующее новой кнопке.
Подключаем нашу функцию к экшну в хеде админки.
add_action('admin_head','add_button');
function add_button(){
Естественно, делаем свои изменения надо только на определенных страницах — создание/редактирование записи/страницы (можно еще добавить дэшборд для новых версий). Я использовал preg_match
для того, что одновременно определить страницы post.php и post-new.php (т.е. проверка только на страницу создания и редактирования только постов), но можно делать и по-другому.
if(preg_match('~post(-new)?.php~',$_SERVER['REQUEST_URI']))
{
Маленький нюанс — сам скрипт quicktags.js подключается до вызова основной функции, выводящей тулбар с этими кнопками, но на странице создания новой записи находится не в хедере. Поэтому его нужно определить раньше — в ВП, как и положено, есть специальная функция, которая следит за тем, чтобы скрипты не подключались по нескольку раз:
wp_print_scripts( 'quicktags' );
Ну а после этого нам надо вывести короткий скрипт, который добавит в массив новое значение с соответствующими значениями. Вот, например, как «выглядит» кнопка ката:
edButtons[edButtons.length] = new edButton('ed_more', 'more', '<!--more-->', '', 't', -1);
где по порядку: id
(уникальное имя кнопки), display
(то, что на ней будет написано), tagStart
(тег в начале), tagEnd
(тег в конце — может быть пустой строкой), access
(кнопка, по которой доступна с клавиатуры), open
(либо параметр пропускается, либо равен -1
— если не требуется закрывающий тег).
Ну а для того, чтобы на всех конфигурациях скрипта наши изменения были сделаны гарантированы правильно, выводим этот кусок через эхо, вручную добавляя символы перевода строки и табуляции, а также экранируем js-код. Заканчиваем наш код вот так (пример из ljxp remix):
echo "<script type=\"text/javascript\">"."\n";
echo "/* <![CDATA[ */"."\n";
echo "edButtons[edButtons.length] = new edButton"."\n";
echo "\t('ed_nocross',"."\n";
echo "\t'NOCROSS'"."\n";
echo "\t,''"."\n";
echo "\t,''"."\n";
echo "\t,'n'"."\n";
echo "\t);"."\n";
echo "/* ]]> */"."\n";
echo "</script>"."\n";
}
}
Все, в простой HTML-редактор добавлена полноценная кнопка, уже готовая к исполнению своих обязанностей.
Но этого недостаточно — ведь не все сидят в простом редакторе, предпочитая ему wysiwyg-вариант. Поэтому нам надо заглянуть в ВП Кодекс, чтобы узнать, что подключение кнопок в TinyMCE с версии 2.7 изменилось, и нам придется предусматривать все варианты.
Для начала, будем предполагать, что рабочий TinyMCE-плагин кнопки у нас лежит внутри папки ВП-плагина. В последнем нам потребуется 4 рабочих функции на каждый хук:
Во-первых, это регистрация самой кнопки в скрипте инициализации — нам надо добавить в существующий массив название кнопок, плюс, возможно разделители (separator
или |
).
function &tinymce_registerbutton(&$buttons) {
array_push($buttons, 'separator', '%button_name%');
return $buttons;
}
Далее для 2.7 мы сразу указываем и название плагина, и путь до него (с названием файла плагина) — путь внутри %plugins_url%
используем относительный.
function &tinymce_addplugin(&$plugin_array) {
$plugin_array['plugin_name'] = '%plugin_path%/editor_plugin.js';
return $plugin_array;
}
Чтобы облегчить указание пути можно воспользоваться php-функцией plugins_url ('название_плагина/дальнейший путь'), которая возвратит абсолютный путь, добавив нужную строку. Но в старых версиях такой функции просто нет, поэтому надо это учесть (заменяется первая строка):
if (function_exists (plugins_url) )
$plugin_array['nocross'] = plugins_url('livejournal-crossposter-remix/tinymce/plugins/ljxp/editor_plugin.js');
else
$plugin_array['ljusers'] = get_option('siteurl') . '/wp-content/plugins/livejournal-crossposter-remix/tinymce/plugins/ljxp/editor_plugin.js';
Для более старых версий ВП (а значит — и для более старой TinyMCE) нужно опять же в массив добавить плагин по названию, поставив перед ним дефис (это сигнализирует скрипту, что плагин внешний).
function &tinymce_old_addplugin(&$plugins) {
array_push($plugins, '-%plugin_name%');
return $plugins;
}
Для версий ВП старее 2.5 надо также будет указать, где именно располагается внешний плагин — здесь plugin_path
— путь абсолютный и только до папки, где уже лежит editor_plugin.js (без файла).
function tinymce_old_load() {
echo "tinyMCE.loadPlugin('%plugin_name%', '%plugin_path%');\n";
}
Осталось только правильно подключить эти функции к соответствующим хукам. Делать это будем при инициализации, проверяя — находимся ли мы на соответствующей странице, имеет ли право текущий пользователь на редактирование, а также — включено ли визуальное редактирование.
add_action('init', 'ljxp_add_shortcode_mce');
function ljxp_add_shortcode_mce() {
if(!preg_match('~post(-new)?.php~',$_SERVER['REQUEST_URI'])
&& !current_user_can('edit_posts')
&& ! current_user_can('edit_pages')) {
return;
}
if('true' == get_user_option('rich_editing')) {
add_filter("mce_external_plugins", "tinymce_addplugin");
add_filter("mce_buttons", "tinymce_registerbutton");
add_filter("mce_plugins", "tinymce_old_addplugin");
add_action("tinymce_before_init", "tinymce_old_load");
}
}
Не ошибитесь названием экшна tinymce_before_init
— в более новых версиях есть также tiny_mce_before_init
, но фильтр, а не экшн, и используется он в других целях.
Ну вот, с подключением внешних плагинов к визуальному редактору мы определились, но — как же их создавать? Я не буду заострять внимание на вопросе по многим причинам — это требует хоть какого-то знания js, разные напильники для разных решений, и еще много нюансов. Начать разбираться можно с вики TinyMCE.
Хотя вообще, все просто — в editor_plugin.js мы определяем кнопки, навешиваем на них действия, добавляем картинки и, если нужно, мультиязычные файлы (кстати, последние в новых ВП подключаются не скопом, а вываливаются прямо в хтмл).
Самое сложное — это обработка действия по нажатию кнопки (список команд в вики).
Особенно это касается вставки нестандартных тегов — mceReplaceContent
даже в новых версиях работает неправильно, стирая все оформление в выделенном контенте. Приведенный код «правильного использования» работать отказывается вообще. Если же использовать вставку ссылки со временным id и потом превращать все такие элементы в нужный нам тег, то это может быть только инлайновый элемент, или же придется проводить дополнительную чистку.
Если же что-то непонятно или не получается — всегда можно поискать в гуглояндексах или чужом коде.
Меню сайта
![]() Как вставить кнопки в редактор WordPress |