It was brought to my attention last week that there aren't very many good tutorials on the web regarding the use of XML-RPC in WordPress.  Sure, there are plenty that talk about how easy it is to use and how great of a tool it can be, but few examples explaining just how it can be used.

https://twitter.com/curtismchale/status/254356464154574848

I use WordPress for just about everything.  For websites, for forums, for ebook sales, for presentations, and most recently for an SMS gateway to a travel blog.  The thing is, I can't always post to WordPress the way I want to.  I will be in Haiti next week and won't have access to a computer or a laptop, but I still want to update my blog so I can communicate with friends and family at home.  XML-RPC to the rescue!

Well, not exactly.

The first part of my application is actually a custom handler for SMS messages that I set up on my server.  I won't get into that part of the system for now; instead, I'll explain how the system updates a remote blog hosted on WordPress.com using XML-RPC.

The Tools

There is just about no limit to what you can do with WordPress through XML-RPC calls.  You can add posts, edit comments, upload images, manage taxonomies, and even configure site options.  If there's something you want to do that's not exposed through the API, you can add your own calls with a simple filter.

From the receiving end of things, the XML-RPC system in WordPress is fantastic.  All of the ugly XML is converted to native PHP objects (and arrays and strings) so you can program along without needing to worry about content structs, unclosed tags, or remembering whether to use [cci][/cci] or [cci][/cci] to mark a number.

The heavier part of the API is the sending end of things.  How do you get your data into that scary-looking content struct?  How do you structure your XML so WordPress can read it?  How do you interpret errors thrown by the server?

Luckily, these questions are already answered for you.

Most systems support their own XML-RPC library - WordPress is no different.  While there is a robust server library available, there is also a robust client library available as well.  You can use this library to execute XML-RPC requests from within WordPress to interact with or consume data from any XML-RPC server you like.

The Framework

In the case of my SMS link, I need to pass a "new post" request to WordPress.com.  I could simply use an existing service like IFTTT to trigger post creation[ref]They're using an XML-RPC client under the surface as well![/ref], but their system doesn't support post formats.  I want to keep my regular posts separate from my SMS updates, so I'll be using the "status" post format for these separate updates.

Creating a post with a specified post format requires a custom call through my own, self-hosted XML-RPC client.  Luckily, I'm already using WordPress to host the SMS gateway, so I can use WordPress to push the update to the server as well.

Just include the Incutio XML-RPC library that ships with WordPress to get base functionality and WordPress' internal HTTP XML-RPC client library to get started.  The first is the workhorse that translates native PHP objects and collections back and forth into XML-RPC structures.  The second is a beautiful abstraction of the request/response process that makes live so much easier.


include_once( ABSPATH . WPINC . '/class-IXR.php' );
include_once( ABSPATH . WPINC . '/class-wp-http-ixr-client.php' );

Walking Through a Request

Every WordPress installation ships with a default XML-RPC endpoint.[ref]This will be customizable with a filter in an upcoming version of WordPress, but even when filtered the endpoint will still be available somewhere.[/ref]  In most cases, it's discoverable as well - just check for the [cci]<link rel="pingback ...>[/cci] tag in your site's header to see where it's at.  Probably something like [cci]http://yoursite.com/xmlrpc.php[/cci].

We'll start building our request by creating a new client pointed at that endpoint.


$client = new WP_HTTP_IXR_CLIENT( 'http://yoursite.com/xmlrpc.php' );

Now let's make a call.  For this specific request, we want to call [cci]wp.newPost[/cci] to create the new post.  We'll pass in an array of arguments based on the API that WordPress presents:

  • 0 - The blog ID, but it's not really used.
  • ericmann - My WordPress username for the site.
  • ..... - My WordPress password[ref]You didn't really think I'd give you my password, did you?[/ref]
  • array() - The content structure. An associative array of the fields I want set for the newly created post.


$result = $client->query( 'wp.newPost', array(
0,
"ericmann",
"....",
array(
'post_status' => 'publish',
'post_title' => 'SMS Update',
'post_content' => $_REQUEST['text'],
'post_format' => 'status',
'terms_names' => array(
'category' => array(
'Field Update'
),
'post_tag' => array(
'mobile',
'update'
)
)
)
) );

Nothing really fancy is happening here.  You could think of this as simply invoking [cci]wp_insert_post()[/cci] on a remote site.  Really, that is what you're doing.  When WordPress receives the request, it sanitizes the data (to make sure you aren't sending garbage), calls [cci]wp_insert_post()[/cci], and returns the ID of the newly created post.

Now on the client side, you check to see if the request was successful.  If it was, you'll get [cci]true[/cci].  If it wasn't, you'll get back [cci]false[/cci] as a result and can check the [cci]error[/cci] property of your client object to see what all happened.


if ( $result ) {
update_post_meta( $new_post_id, 'posted', 'Success' );
} else {
$error = $client->error->message;
update_post_meta( $new_post_id, 'posted', 'Failed: ' . $error );
}

If you absolutely need the ID back as well, you can set the [cci]debug[/cci] flag to [cci]true[/cci] on the client object and it will record both the method call and the method response.

What's Next?

Making requests is pretty simple, but if you want to get started and are worried about corrupting your database, WordPress ships with two test methods in its XML-RPC server:

  • [cci]demo.sayHello[/cci] - Returns a standard "Hello!" message.
  • [cci]demo.addTwoNumbers[/cci] - Accepts an array containing two numbers and returns the sum.

So to get started, you can merely create a request using one of these test messages:[ref]Yes, I have tested this exact code. It works just fine.[/ref]


include_once( ABSPATH . WPINC . '/class-IXR.php' );
include_once( ABSPATH . WPINC . '/class-wp-http-ixr-client.php' );

$client = new WP_HTTP_IXR_CLIENT( 'http://wordpress.com/xmlrpc.php' );
$client->debug = true;

$hello = $client->query( 'demo.sayHello' );

$addition = $client->query( 'demo.addTwoNumbers', array( 55, 17 ) );

These commands should give you these blocks of XML:




demo.sayHello




Hello!



demo.addTwoNumbers


55
17



72