WordPress на сегодняшний день является одой из самых популярных CMS и последнее время активно развивается. Но, к сожалению, это развитие не всегда получается гармоничным.
Одной из возможностей, которая почему-то по возможностям постоянно отстаёт от остальной части движка, является XML-RPC. На сегодняшний день этот протокол является основным средством удалённой публикации постов. И, при этом, он фактически бесполезен если вы используете произвольные типы записей (custom post types) и таксономии (custom taxonomies). Ни один XML-RPC метод публикации постов в WP 3.2.1 их не поддерживает.
Конечно, можно надеятся, что в будущих версиях ситуация изменится в лучшую сторону, но ничто не мешает добавить нужные методы прямо сейчас.
Рассмотрим небольшой пример.
Допустим, нам нужно публиковать посты произвольного типа через XML-RPC и связывать их с таксономиями. При этом, таксономии могут быть как иерархическими, так и плоскими.
Примечание. Подробнее о типах постов и таксономиях рассказано в статьях: WordPress: вывод записей произвольных типов (Custom Post Types) и Управление контентом в WordPress CMS: ситуация на сегодня и ближайшая перспектива.
Немного теории
В WordPress предусмотрен фильтр (xmlrpc_methods
), позволяющий добавлять новые методы во встроенный XML-RPC сервер. Делается это следующим образом:
add_filter('xmlrpc_methods', 'add_xml_rpc_methods');
Во втором параметре фильтра указываем имя функции, которая создаст запись в глобальном массиве XML-RPC методов.
function add_xml_rpc_methods($methods) { $methods['my.my_method_name'] = 'my_method_name'; return $methods; } function my_method_name($args) { //обработка XML-RPC запроса и отправка ответа }
Чтобы создать XML-RPC метод нужно добавить новый элемент в массив $methods
. Ключ этого элемента является именем метода, а значение – именем функции, которая выполняет обработку XML-RPC запроса и формирует ответ.
Реализация: XML-RPC клиент
Начнём с кода, который отправляет XML-RPC запрос. В данном случае будем использовать библиотеку The Incutio XML-RPC Library (она же используется и в WordPress).
require_once ('IXR_Library.php'); $client = new IXR_Client('http://my_blog.com/xmlrpc.php'); $client->timeout = 60000; $requestData[0] = 0; //id блога $requestData[1] = 'admin'; //имя пользователя $requestData[2] = 'pass'; //пароль $post = array(); $post['post_title'] = 'New Post'; $post['post_excerpt'] = 'Short description'; $post['post_content'] = 'This story about ...'; $post['post_status'] = 'draft'; $post['post_type'] = 'my_custom_post_type'; //тип поста $post['post_date'] = date('Y-m-d H:i:s'); $post['post_modified'] = date('Y-m-d H:i:s'); //формируем массив с терминами таксономий $terms = array(); $terms['taxonomy_1'][] = (int)$term['term_id_1']; $terms['taxonomy_1'][] = (int)$term['term_id_2']; $terms['taxonomy_2'][] = (int)$term['term_id_3']; $terms['taxonomy_3'][] = (int)$term['term_id_4']; $post['tax_input'] = $terms; $requestData[3] = $post; if (!$client->query('my.publish_post', $requestData)) { echo 'Publish Post error: '.$client->getErrorMessage(); return; } $publishedPost = $client->getResponse();
Прежде всего, создаём объект IXR_Client
, конструктору которого передаём адрес скрипт, который выполняет обработку XML-RPC запросов (xmlrpc.php).
Затем формируем массив с данными для публикации поста. В первых трёх элементах указываем: id
блога (на данный момент не используется), логин и пароль. В четвертом элементе – массив с данными нового поста.
Чтобы сократить количество кода на стороне XML-RPC сервера, названия полей этого массива должны совпадать с полями массива, который передаётся функции wp_insert_post. Кстати, большинство ключей элементов этого массива совпадает с именами полей таблицы posts базы данных.
Обратите внимание на параметр
$post['post_type'] = 'my_custom_post_type'; //тип поста
В нём указан тип поста, который мы хотим создать. Естественно, этот тип должен быть заранее создан.
Отдельно остановимся на таксономиях.
WordPress поддерживает таксономии 2-х типов: иерархические и плоские. Чтобы связать пост с терминами таксономий нужно перечислить их в элементе tax_input массива, который передаётся функции wp_insert_post
. Например, так:
'tax_input' => array('taxonomy_1' => array('term', 'term2', 'term3'), 'taxonomy_2' => array('term1', 'term2'))
Здесь taxonomy_1
, taxonomy_2
– имена таксономий, а term
, term1
и т.д. – имена терминов.
Но здесь есть нюансы. Если публикуется «плоская» таксономия, то можно указать, либо имя термина, либо его id
. При этом, id
должен иметь тип int
, если id
сохранён в виде строки, то WordPress просто создаст новый термин. Для иерархических таксономий можно использовать только id
термина (при этом нет ограничения на тип значения, оно будет автоматически приведено к типу int
).
Т.е. универсальный вариант установки таксономий выглядит так:
$terms['taxonomy_1'][] = (int)$term['term_id_1']; $terms['taxonomy_1'][] = (int)$term['term_id_2']; $terms['taxonomy_2'][] = (int)$term['term_id_3']; $terms['taxonomy_3'][] = (int)$term['term_id_4'];
Отправка запроса выполняется с помощью метода query, а прочитать результат можно используя getResponse
.
XML-RPC сервер
На серверной стороне нужно зарегистрировать новый XML-RPC метод и написать функцию, которая будет обрабатывать запрос, и возвращать результат.
Примечание. Следующий код можно добавить в плагин или в файл functions.php темы.
add_filter('xmlrpc_methods', 'add_xml_rpc_methods' ); function add_xml_rpc_methods($methods) { $methods['my.publish_post'] = 'my_publish_post'; return $methods; } function my_publish_post($args) { $blog_id = (int) $args[0]; $username = $args[1]; $password = $args[2]; $post_data = $args[3]; if ( !get_option( 'enable_xmlrpc' ) ) { return new IXR_Error( 405, sprintf( __( 'XML-RPC services are disabled on this site. An admin user can enable them at %s'), admin_url('options-writing.php') ) ); } $user = wp_authenticate($username, $password); if (is_wp_error($user)) { return new IXR_Error(403, __('Bad login/pass combination.')); } wp_set_current_user( $user->ID ); if ( !current_user_can( 'edit_private_posts' ) ) { return new IXR_Error( 401, __( 'Sorry, you cannot edit private posts.' ) ); } if (!is_array($post_data)) { return new IXR_Error( 401, __( 'Sorry, no post data not found.' ) ); } $id = wp_insert_post( $post_data ); if ($id === 0) { return new IXR_Error( 401, __( 'Post save error.' ) ); } $post = array(); $post['id'] = $id; $post['permalink'] = get_permalink($id); return $post; }
Здесь мы регистрируем XML-RPC метод my.publish_post
и указываем, что при обращении к нему WordPress должен вызвать функцию my_publish_post
.
Большая часть кода в этой функции совпадает с большинством обработчиков стандартных XML-RPC методов WP. Собственно он оттуда и скопирован 😉 . Этот код проверяет, разрешен ли XML-RPC для данного блога (строки 14-16, кстати, не забудьте его включить в админке на странице Settings -> Writing), аутентифицирует пользователя и проверяет, достаточно ли у него прав для публикации поста.
Сама публикация выполняется с помощью всего одной функции wp_insert_post
(строка 34).
Клиенту возвращаем id
созданного поста и постоянную ссылку на него (формируем с помощью функции get_permalink).
Заключение
Как видите, принцип достаточно простой. Любую встроенную функцию WP можно вызвать через XML-RPC протокол и использовать все возможности движка при удалённой публикации постов.
Если есть вопросы или замечания, пишите, постараюсь ответить.
Успехов!
Интересные ссылки
Закажите печать фотокниг тремя способами: онлайн, в офисе или вип