WordPress: публикация постов с помощью XML-RPC с поддержкой таксономий

Владимир | | PHP, Web разработка, WordPress.

wordpress xml-rpc publish

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 протокол и использовать все возможности движка при удалённой публикации постов.

Если есть вопросы или замечания, пишите, постараюсь ответить.

Успехов!

Интересные ссылки

Закажите печать фотокниг тремя способами: онлайн, в офисе или вип