on Tutorials

Extending the WordPress XML RPC API

0 comments
Codeforest
Tweet about this on TwitterShare on FacebookShare on Google+Share on LinkedInShare on RedditShare on StumbleUpon

XML-RPC is a remote procedure call (RPC) protocol which uses XML for data handling and HTTP as a data transport mechanism.

XML-RPC also refers generically to the use of XML for remote procedure call, independently of the specific protocol.

Basically, client uses XML to encode parameters for remote calling, send that XML through HTTP request to XML-RPC server, which executes remote method and return XML encoded response back to the client.

WordPress uses XML-RPC interface and currently support the Blogger API, metaWeblog API, Movable Type API, and the Pingback API.

Original idea behind this interface was to allow people to easily exchange content between popular blogging platforms and WordPress platform.  But it is even more powerful, allowing developers to write their own methods.

XML-RPC is simply a way of pushing in and pulling out data of a WordPress blog. Used primarily in desktop blogging clients such as Windows Live Writer, browser add-ons and mobile clients.

Enabling XML-RPC support in WordPress

XML-RPC support is turned off by default, as many average WordPress users don’t need it. To turn it on, you must go to your Settings — Writing page inside WordPress admin interface, check Enable the WordPress, Movable Type, MetaWeblog and Blogger XML-RPC publishing protocols and save changes.

How to use it?

The best way to show you how to use it is by example. WordPress has a nifty demo methods built for testing the API, so let’s create some.

First, let’s build a helper method for encoding our request and sending it through HTTP. We will use this method all through this article:

define('RPC_URL', 'http://wordpress.url/xmlrpc.php');
function sendRequest($methodName, $parameters)
{
	$request = xmlrpc_encode_request($methodName, $parameters);
	$ch = curl_init();
	curl_setopt($ch, CURLOPT_POSTFIELDS, $request);
	curl_setopt($ch, CURLOPT_URL, RPC_URL);
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
	curl_setopt($ch, CURLOPT_TIMEOUT, 1);
	$results = curl_exec($ch);
	$results = xml_decode($results);
	curl_close($ch);
	return $results;
}

First, I defined a constant RPC_URL which is the URL to which we are sending all our requests. Notice that in the first line of our method, request is XML-RPC encoded as well as parameters sent as method arguments.

I prefer cURL because it is very easy to implement and allows custom headers to be sent, so I can do some things in my methods only if they are called through XML-RPC.

Now, lets try to call demo.sayHello method which has no parameters and its whole purpose is to test if everything is working fine:

$parameters = array();
$response = sendRequest('demo.sayHello', $parameters);

This was easy, first parameters is name of the method we are calling (demo is a namespace) and sending an empty array of parameters. If everything is working $response should be: Hello!

To see a list of all methods open up your /wp-includes/class-wp-xmlrpc-server.php and check the constructor. Only sky is the limit.

All built-in XML-RPC methods use the action xmlrpc_call, with a parameter equal to the method’s name (e.g., wp.newPost). The action is performed after the user has been authenticated but before the rest of the method logic begins.

But there is a catch. Those methods are great, but does not give you enough freedom to tailor everything by your needs.

Extending the API

“There is a filter for that”. Sure there is, called xmlrpc_methods. You basicaly just add your custom method names and that’s it. They are immediately available (example from WordPress Codex):

function mynamespace_subtractTwoNumbers( $args ) {
    $number1 = (int) $args[0];
    $number2 = (int) $args[1];
    return $number1 - $number2;
}

function mynamespace_new_xmlrpc_methods( $methods ) {
    $methods['mynamespace.subtractTwoNumbers'] = 'mynamespace_subtractTwoNumbers';
    return $methods;
}
add_filter( 'xmlrpc_methods', 'mynamespace_new_xmlrpc_methods');

This is really basic and works without an authentication. In real life, you should really authenticate XML-RPC calls, especially if your altering something in the database.

It is pretty easy:

function getSecureData($args)
	{
	    global $wp_xmlrpc_server;
	    $wp_xmlrpc_server->escape($args);

	    $someId  = $args[0];
	    $username = $args[1];
	    $password = $args[2];

	    if (!$user = $wp_xmlrpc_server->login($username, $password))
	        return $wp_xmlrpc_server->error;

	    // .. do something secret here
	}

Please, notice the escaping arguments part. ALWAYS escape method arguments in this way, as you can never trust some data that is coming through the internet.

Now, practical example. You have two web sites in different languages. As soon as you Publish the post on one site, you want to publish it on the other (as draft), so that translators can do their jobs.

First, add our future method to array of XML-RPC methods:

add_filter('xmlrpc_methods', 'my_xmlrpc_methods');
function my_xmlrpc_methods($methods)
{
	$methods['myCopyPost'] = 'myMethod';
	return $methods;
}

And this is the method that deals with inserting the post:

function myMethod($args)
{
	//Parse and escape parameters
	global $wp_xmlrpc_server;
	$wp_xmlrpc_server->escape($args);

	$username	= $args[0];
	$password	= $args[1];
	$content	= $args[2];

	//Authenticated?
	if ( !$user = $wp_xmlrpc_server->login($username, $password) ) {
		return $wp_xmlrpc_server->error;
	}

	$title 			= $content['title'];
	$postContent 	= $content['content'];

	$postData = array(
		'post_status' 	=> 'draft',
		'post_title' 	=> $title,
		'post_type' 	=> 'post',
		'post_content' 	=> $postContent
	);

	$postId = wp_insert_post($postData);

	return 'Post inserted successfully';
}

All that is left to see is the client side method for retrieving post data, encoding it and sending:

// after post is saved we have its id
$wpQuery = new WP_Query("p=" . $postId);

if ($wpQuery->have_posts()) {
    $wpQuery->the_post();

    $content = array(
       'title'   => get_the_title(),
       'content' => get_the_content()
    );

    $parameters = array('username', 'password', $content);

    sendRequest('myCopyPost', $parameters);
}

Basically, you can put this code in edit_post filter. It gets the post data, encodes it and send to receiving end. This way you can send whatever you want (custom post types, all posts, posts in chunks, post by tag, images, attachments, you name it) and are not limited by anything.

I hope that this little article will help you to better understand the possibilities of XML-RPC WordPress API calls.

Please tell me if you ever used this great feature in the comments below.

Tweet about this on TwitterShare on FacebookShare on Google+Share on LinkedInShare on RedditShare on StumbleUpon



Comments are closed.