Patching WordPress xmlrpc to filter post using categories
I´m building an application to integrate data between some blog apps (WordPress and Blogger for example) and then faced a problem when I was trying to filter some posts using a specific category.
My app is AppEngine based and I´m algo using xmlrpclib and wordpress-library to make web calls. After playing a while with wordpress-library, I got some things missing and started to patch to make it work for me.
Basically I´ve added some stuff like post status, custom fields and filter posts by categories. I dont know why WordPress don´t give a simple wrapper function inside xmlrpc.php to make things generic, allowing other users to extend functionalities. Anyway, I did it and will suggest to add support for it, because makes easier to give some maitenance.
To make the patch, you must understand the get_post function, exposed on wp-includes/post.php. Looking inside, the function body is:
function get_posts($args = null) {
$defaults = array(
'numberposts' => 5, 'offset' => 0,
'category' => 0, 'orderby' => 'post_date',
'order' => 'DESC', 'include' => '',
'exclude' => '', 'meta_key' => '',
'meta_value' =>'', 'post_type' => 'post',
'suppress_filters' => true
);
…. continue
Based on that function, it becomes easier to make your on function on xmlrpc.php:
First: Include your function entrypoint on $this->methods array. My implementation is ‘wp.getPostsByCategory’ => ‘this:wp_getPostsByCategory’. I decided to use this name, because it´s a specific function for wordpress, not a MetaWebLog structure.
Second: Change mw_wp_get_recent_posts to receive other args and change the call wp_get_recent_posts($num_posts) to use get_posts . You´ll also need to change the ways that arrays are accessed, because get_posts function returns an Object, instead of array. Example: $entry['ID'] becomes $entry->ID.
After that, just make your call to wp.getPostsByCategory, passing username, password and categoryId. Like magic
Just to finish, a simple python example using xmlrpclib to call a server method:
import xmlrpclib
server = xmlrpclib.ServerProxy("http://www.mywebsite.com/xmlrpc.php")
posts = server.wp.getPostsByCategory(categoryId, 'user', 'password')
for post in posts:
print post['post_title']
.
Piece of cake ! If you have any doubt, leave a comment here.
Popularity: 18%








Hi Robson,
I’m trying to employ some of what you’ve written in order to do the same thing, but for a flash project
in terms of the xmlrpc.php -
I’m not sure if I’ve totally understood the steps…
1 in xmlrpc.php I followed your step and added ‘wp.getPostsByCategory’ => ‘this:wp_getPostsByCategory’,
to the $this-methods array
but,
2 is where im not sure if im following you.
i copy/pasted the mw_getRecentPosts function, renamed my new function wp_getPostsByCategory, and amended the first few lines to use
function wp_getPostsByCategory($args) {
$this->escape($args);
$blog_ID = (int) $args[0];
$user_login = $args[1];
$user_pass = $args[2];
$num_posts = (int) $args[3];
$cat = (int) $args[4];
if (!$this->login_pass_ok($user_login, $user_pass)) {
return $this->error;
}
do_action(‘xmlrpc_call’, ‘wp.getPostsByCategory’);
$posts_list = get_posts( “post_type=post&post_status=all&numberposts={$num_posts}&category={$cat}” );
after which, everything is the same as the original mw_getRecentPosts function
while my call to:
metaWeblog.getRecentPosts
worked succssfully calling my:
wp.getPostsByCategory
doesnt work
have i misunderstood what you wrote?
thanks!
Apparently, you´ve done everything correctly. By the way, I´m copying my function here and then you can copy, paste and test.
Anyway, if you have a public url, I can make a call and test to see if it´s ok.
Cheers
function wp_getPostsByCategory($args){
$this->escape($args);
$catid = (int) $args[0];
$username = $args[1];
$password = $args[2];
if ( !$this->login_pass_ok( $username, $password ) )
return $this->error;
do_action('xmlrpc_call', 'wp.getPostsByCategory');
//$posts_list = get_posts('category='.$catid);
$posts_list = get_posts('category='.$catid);
if (!$posts_list) {
return array( );
}
set_current_user( 0, $user_login );
$i=0;
foreach ($posts_list as $entry) {
setup_postdata($entry);
//if( !current_user_can( 'edit_post', $entry->ID ) )
// continue;
$post_date = mysql2date('Ymd\TH:i:s', $entry->post_date);
$post_date_gmt = mysql2date('Ymd\TH:i:s', $entry->post_date_gmt);
$tagnames = array();
$tags = wp_get_post_tags( $entry->ID );
if ( !empty( $tags ) ) {
foreach ( $tags as $tag ) {
$tagnames[] = $tag->name;
}
$tagnames = implode( ', ', $tagnames );
} else {
$tagnames = '';
}
$post = get_extended($entry->post_content);
$link = post_permalink($entry->ID);
$allow_comments = ('open' == $entry->comment_status) ? 1 : 0;
$allow_pings = ('open' == $entry->ping_status) ? 1 : 0;
// Consider future posts as published
if( $entry->post_status === 'future' ) {
$entry->post_status = 'publish';
}
$struct[] = array(
'dateCreated' => new IXR_Date($post_date),
'userid' => $entry->post_author,
'postid' => $entry->ID,
// usando content
'description' => $post['main'],
'title' => $entry->post_title,
'link' => $link,
'permaLink' => $link,
// commented out because no other tool seems to use this
//'content' => $entry->post_content,
'categories' => '',
'mt_excerpt' => $entry->post_excerpt,
'mt_text_more' => $post->extended,
'mt_allow_comments' => $allow_comments,
'mt_allow_pings' => $allow_pings,
'mt_keywords' => $tagnames,
'wp_slug' => $entry->post_name,
'wp_password' => $entry->post_password,
'wp_author_id' => '',
'wp_author_display_name' => $author->display_name,
'date_created_gmt' => new IXR_Date($post_date_gmt),
'post_status' => $entry->post_status,
'custom_fields' => $this->get_custom_fields($entry->ID)
);
}
$recent_posts = array();
for ($j=0; $j<count($struct); $j++) {
array_push($recent_posts, $struct[$j]);
}
//print_r($struct);
return $recent_posts;
}
you know what, i hadn’t changed everything from array elements to object properties of $entry as you had specified, so my fault! it works perfectly!
very grateful for this!
Fantastic, it worked straight away. Thank you, you saved me lots of work.