Custom XML-RPC Methods in WordPress

With more and more talk around WordPress 3.0 it seems that the system is gaining even more popularity than ever before due to it’s extensibility. Today I’d like to discuss a topic that might not be of much use to bloggers and basic websites, but is generally required in larger projects – XML-RPC. It’s not limited to WordPress 3.0, but as custom post types are on their way in 3.0, we’ll probably see tonnes of new ways WordPress being used.

In general terms (and as written in the Codex), XML-RPC is simply a way of pushing in and pulling out data of a WordPress blog. Used primarily in offline blogging clients such as Windows Live Writer, a few Firefox addons and mobile clients, all of which support a set of XML-RPC blogging APIs. Okay that’s fine, but not used too much, especially in complex systems, as the standard APIs don’t support:

  • Slug corrections
  • Custom taxonomy
  • Custom post types
  • Custom fields

Which of course is easier to do via the standard WordPress admin panel, especially if meta-boxes are well-designed and implemented. So today’s use of XML RPC in WordPress is limited to blogging.

Now, suppose you have some complex system, let’s say a real estate agency website, where properties are listed, locations as taxonomies and property details as custom fields (number of beds, baths, geo location, etc). There’s no way to input this stuff via the standard XML RPC clients, nor the standard XML RPC API which comes with WordPress. Not too useful I know, since when posting properties agents should be careful to the info the input, thus it’s much wiser to use a computer than a phone or something, but..

Suppose your real estate agency has a CRM they’ve been working in for years. Wouldn’t it be nice if the CRM could insert/change property info directly into the website, without having the agents even look at the WordPress admin panel? That, my friends, could be done via custom XML RPC queries.

Basically, anything could be converted into an XML-RPC query, even the most rediculous stuff, such as changing the title of the homepage. This means that if you have enough time and patience, you could build your own (could be stand-alone) admin panel for your website, fully based on XML-RPC calls. Remember those APS.NET content management systems that are managed from standalone .NET applications? ;)

One more example of XML-RPC usage, which I actually implemented a few days ago – data replication between two websites in different languages. Let’s go back to the real estate example, say this agency has two websites – one in English (.com) and one in Russian (.ru). The English agent got all the data for a new property listing so he publishes it on the .com website. As soon as the post is published, an XML-RPC query is fired at the .ru website, where all the data, filtered through Google Translator or something, is saved as a draft. This way, the Russian agents login to the system, see that there are new drafts, open them up, correct the translations and publish. Voila! No more e-mails back and forth with 4GB of photos ;) Oh, didn’t I mention? Files could also be sent via XML-RPC if done correctly!

Alright, stop the theory, let’s talk some code! The filter used to extend the currently supported XML-RPC methods is called xmlrpc_methods and is located somewhere in xmlrpc.php in your WordPress root directory. There’s a list of all supported methods there, so feel free to disable some or add your own:

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

This will add a new XML-RPC method called myMethod, which would fire my_function. I think the callback function is supposed to be global here and could not be wrapped up into a class and passed on as an array. Not sure for what reason, but it seems that the WordPress environment is not fully initialized during XML-RPC calls, thus only the init and other top-level actions are being fired, perhaps there’s a reason behind that.

Anyways, the next step is to do something in my_function:

function my_function($args)
{
	// Parse the arguments, assuming they're in the correct order
	$username	= $args[0];
	$password	= $args[1];
	$data = $args[2];

	global $wp_xmlrpc_server;

	// Let's run a check to see if credentials are okay
	if ( !$user = $wp_xmlrpc_server->login($username, $password) ) {
		return $wp_xmlrpc_server->error;
	}

	// Let's gather the title and custom fields
	// At a later stage we'll send these via XML-RPC
	$title = $data["title"];
	$custom_fields = $data["custom_fields"];

	// Format the new post
	$new_post = array(
		'post_status' => 'draft',
		'post_title' => $title,
		'post_type' => 'property',
	);

	// Run the insert and add all meta values
	$new_post_id = wp_insert_post($new_post);
	foreach($custom_fields as $meta_key => $values)
		foreach ($values as $meta_value)
			add_post_meta($new_post_id, $meta_key, $meta_value);

	// Just output something ;)
	return "Done!";
}

There, it’s pretty much self-explanatory. We assume that the XML-RPC query contains the username, password and an array of data where the title and custom_fields are defined. This is pretty much all XML-RPC customizing that has to be done, and the final part is actually running the call which should be a well-formated XML-RPC query. We’ll use the xmlrpc_encode_request php function for that, and the WP_Http class to actually send the request:

$post_id = 1; // Replace with post_id you need to send
$wp_query = new WP_Query("p=" . $post_id);
if ($wp_query->have_posts())
{
	$wp_query->the_post();
	$custom_fields = get_post_custom($post_id);

	// This is the data being sent as the third argument in XML-RPC
	// Could be an associative array
	$data = array(
		"title" => $this->get_the_title(),
		"custom_fields" => $custom_fields
	);

	// Format the XML RPC query params, format the request
	// We're using myMethod which we defined above
	// Assuming the username is admin and the password is 1 ;)
	$params = array("admin", "1", $data);
	$params = xmlrpc_encode_request('myMethod', $params);

	// Initiate a new HTTP carrier and fire the request, sending the parameters
	// using the POST method. We could then capture the result by reading $result
	$request = new WP_Http;
	$result = $request->request('http://domain.org/xmlrpc.php',
		array('method' => 'POST', 'body' => $params));
}

All done! The code above clearly shows how to format a simple XML-RPC request using php and you should’t have any trouble doing this in other programming languages (perhaps for standalone software). One more thing to do is enable XML-RPC support in the Writing section under Settings in the blog that’s supposed to receive the requests (though the HTTP result usually states if there are any problems).

This is only an example, perhaps not too useful, but extending it to send over images, videos, etc automatically would speed up the whole process. Writing a special mobile client for agents would also be an awesome idea. And not only real estate! All this is applicable to any kind of products or services, anything that is slightly bigger than just a post with a title and some text ;)

So, what do you use XML-RPC for? What XML-RPC clients do you prefer? And are you willing to write a standalone application based on XML-RPC as the admin panel of a WordPress blog if your clients don’t like the usual backend?

Cheers!

Extending Custom Post Types in WordPress 3.0

In a previous article about Custom Post Types in WordPress 3.0 I outlined one of the most exciting features coming up in 3.0 and I noticed that people have already started building websites upon these new features. It’s not a secret that I’m working on a project myself which involves 3.0 so just like everybody else, I can’t wait to see it being released!

Continue reading

The WP-Custom plugin. What's it all about?

You heard the news! My WP-Custom plugin got WordPress.org hosting approval a few days ago. So I finally uploaded it into their plugins repo and already got some positive feedback on Twitter and IM. Anyways, some still can’t figure out what I made the plugin for, so here’s some explenation.

I assume that you’ve read the plugin description on the wordpress.org website or the readme file in the plugin, so I thought I could just give you a few examples. As I wrote earlier it’s all about custom fields. It’s the way they look, and the way they should look. Let’s look at the Equilibrium theme for a while. There are images associated with every post and if you look closer, they’re taken from the ‘image’ custom field. If you read the installation tips you’ll figure out that you have to put the URL of the image (303×231 for big ones and 162×118 for the small ones) in the ‘image’ custom field.

Well, if I were the developer of that theme I’d use two custom fields ‘image_big’ and ‘image_small’ (you get my point…). Okay, so three days have passed and I already forgot what the dimensions of the images are and whether I should write the complete address in the custom fields or is it relative to the uploads directory. Jeez! I’d have to go look at the dimesions and open another post and check the custom fields there.

Now let’s try another way. Define two custom fields using WP-Custom with those same unique IDs: image_big and image_small. Define their captions: ‘Image 303×231 URL’ and ‘Image 162×118 URL’. Voila! You’ll never forget the dimensions again. Just think about how much time you can save with this, especially if you’re blogging in a team. So what does it require? A few plugin setup and some theme customization. It’s very simple after you get it right.

I’m also thinking about adding the feature to export and import WP-Custom settings. It’d be nice to ship those with a customized theme, making it an out-of-the-box product, right?

I’ve setup a pretty cool page with all the information you’d need about the plugin here: WP-Custom Plugin.