WordPress расширение возможностей встроенного XML-RPC сервера

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

wp-xmlrpc-extended

Приветствую всех!

Тема публикации работы с движком WordPress через XML-RPC протокол обсуждается довольно часто. Пожалуй, это самый удобный способ удаленной публикации постов. Но, если вы хоть раз использовали эту возможность, то, скорее всего, заметили, что встроенный XML-RPC сервер поддерживает далеко не все возможности движка.

К тому же в последних версиях появилась возможность создавать собственные типы данных, и было бы удобно иметь возможность нормально работать с ними через XML-RPC.

Сегодня я покажу небольшой пример создания собственного XML-RPC сервера для WP.

Примечание. Если вы раньше не работали с XML-RPC, то, думаю, вам будет интересно почитать статьи Публикация постов в WordPress с помощью XML-RPC и CodeIgniter и Отложенная публикация постов в WordPress с помощью XML-RPC.

Прежде всего, сформулируем задачу.

Допустим, нам нужно создать новый тип данных под названием example_products и обеспечить возможность публикации записей этого типа через XML-RPC. Также добавим возможность организовывать записи в виде иерархической структуры.

Т.е. получается аналог страниц (Pages) WP, но для демонстрации идеи, думаю, этого будет достаточно.

Шаг 1. Создаём новый тип данных.

Для этого в файл functions.php, который находится в папке вашей темы, добавляем следующий код.

add_action( 'init', 'create_post_type' );
function create_post_type() {
	register_post_type( 'example_product',
		array(
			'labels' => array(
				'name' => __( 'Products' ),
				'singular_name' => __( 'Product' )
			),
			'public' => true,
			'hierarchical'=>true,
			'supports'=>array(
				'title',
				'editor',
				'page-attributes',
			),
		)
	);
}

Этот код практически полностью повторяет пример из кодекса.
Разница в том, что здесь включена поддержка иерархий ('hierarchical'=>true).

В результате в админке появится новый пункт Products.

Шаг 2. Разрешаем работу через XML-RPC.

В целях безопасности, по-умолчанию, эта возможность отключена. Поэтому в настройках (Settings -> Writing) отмечаем чекбокс XML-RPC.

Шаг 3. Создаём XML-RPC сервер.

В принципе, можно добавить необходимые методы в стандартный сервер WP (файл xmlrpc.php). Но этот подход мне не нравится, т.к. потом придется патчить этот файл после каждого обновления движка.

Поэтому мы будем использовать свой сервер. Создаём в корне блога файл xmlrpc-extended.php со следующим содержимым.

<?php
define('XMLRPC_REQUEST', true);

/** Include the bootstrap for setting up WordPress environment */
require_once('wp-load.php');

require_once(ABSPATH . 'wp-admin/includes/admin.php');
require_once(ABSPATH . WPINC . '/class-IXR.php');

class XMLRPCServerExtended extends IXR_Server {

	public function XMLRPCServerExtended() {
		$this->IXR_Server(array(
	        'wp_extended.create_product' => 'this:create_product',
	    ));
	}

	/**
	 * Создание страницы типа 'Product'.
	 * 
	 * @param array $args массив с данными
	 * $args[0] - имя пользователя
	 * $args[1] - пароль
	 * $args[2] - массив с данными для создания поста 
	 * (перечень полей здесь - http://codex.wordpress.org/Function_Reference/wp_insert_post)
	 * @return - сообщение о результате создания страницы
	 */
	
	public function create_product($args) {
		$username = $args[0];
		$userpass = $args[1];
		$post_data = $args[2];
		//проверяем логин/пароль
		if ( $this->login_pass_ok( $username, $userpass ) ) {
			//получаем id пользователя
			$user_data = get_userdatabylogin( $username );
			$post_data['post_type'] = 'example_product';
			$post_data['post_author'] = $user_data->ID;
			$post_data['ping_status'] = get_option( 'default_ping_status' );
			//Добавляем пост
			if ( 0 !== ( $post_id = wp_insert_post( $post_data ) ) ) {
				return 'Created post '.$post_id;
			}
			return 'Post add error';
		}
	}
	
	/**
	 * Check user's credentials.
	 *
	 * @since 1.5.0
	 *
	 * @param string $user_login User's username.
	 * @param string $user_pass User's password.
	 * @return bool Whether authentication passed.
	 * @deprecated use wp_xmlrpc_server::login
	 * @see wp_xmlrpc_server::login
	 */
	function login_pass_ok($user_login, $user_pass) {
		if ( !get_option( 'enable_xmlrpc' ) ) {
			$this->error = 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') ) );
			return false;
		}

		if (!user_pass_ok($user_login, $user_pass)) {
			$this->error = new IXR_Error(403, __('Bad login/pass combination.'));
			return false;
		}
		return true;
	}

}

$server = new XMLRPCServerExtended();

Принцип работы сервера довольно простой. В начале мы загружаем скрипты WP для того, чтобы получить доступ к встроенным функциям, и библиотеку Incutio XML-RPC Library (она входит в дистрибутив WP).

Затем создаём сервер. Для этого наследуем класс IXR_Server. В конструкторе указываем массив с перечнем методов, которые поддерживает данный сервер. В этом примере метод только один — wp_extended.create_product.

И создаём метод create_product, который и добавляет запись. Этому методу мы передаём массив с данными для создания записи. Формат передачи данных произвольный, тут всё зависит от вас. Главное, соблюдать его при создании XML-RPC клиента.

Первыми элементами массива идут имя пользователя и пароль. Будьте внимательны, если вы забудете авторизовать пользователя, то кто угодно сможет публиковать записи.

Внутри метода create_product мы проверяем полученные логин и пароль. Для этого используется метод login_pass_ok. Я его просто скопировал из файла xmlrpc.php. В нём выполняется две проверки.

1) Разрешена ли работа через XML-RPC.
2) Проверяется логин и пароль пользователя.

Затем мы с помощью функции wp_insert_post создаём запись. При этом заполняем массив с данными. Часть этих данных (например, заголовок и текст записи) мы получаем от клиента, но некоторые поля заполняем на сервере. Сюда относятся:

1) post_type – тип записи;
2) post_author – id автора записи (для его получения используем логин пользователя);
3) ping_status – указывает, разрешены или запрещены трекбеки и пингбеки для данной записи, используем текущие настройки для всего блога.

Если запись успешно создана, отправляем клиенту сообщение, включающее её id, если нет – описание ошибки.

Обратите внимание на последнюю строчку этого скрипта. Для того, чтобы запрос был обработан, необходимо создать экземпляр нашего класса.

Шаг 4. Создаём XML-RPC клиент.

Здесь я покажу только код добавления новой записи. Для полноценной работы нужно будет создать соответствующий интерфейс.

<?php
include 'IXR_Library.php';

$client = new IXR_Client('http://sitename.domen/xmlrpc-extended.php');
$client->debug = true;

$post_data = array(
	'post_title' => 'Заголовок',
	'post_content' => 'Текст моего поста',
	'post_status' => 'publish', 
	'post_parent' => 19,
);

if (!$client->query('wp_extended.create_product', 'admin', 'password', $post_data)) {
    die('Something went wrong - '.$client->getErrorCode().' : '.$client->getErrorMessage());
}
echo $client->getResponse();

Здесь мы создаём объект IXR_Client и указываем адрес нашего XML-RPC сервера.

Затем заполняем массив с данными новой записи и отправляем запрос. При этом указываем имя метода (wp_extended.create_product), логин, пароль и массив с данными.

Если есть желание поэкспериментировать, качайте архив с этим примером.

Source

Перед использованием не забудьте добавить тип данных example_product.

Как видите через XML-RPC, можно выполнить практически любые действия с блогом. Вам будут доступны все встроенные функции WP и, если необходимо, можно выполнять запросы к БД напрямую.

Интересно почитать

Полезный блог о создании, развитии и поддержке своих сайтов. Автор публикует подробные статьи с примерами кода.

Установка плагина Disqus на wordpress