Automatic Post Creation with Wordpress, PHP, and XML-RPC
Wednesday, February 11. 2009
So, for those of you who read my last blog post, you might notice that I was having issues with a script I wrote to create a new post in Wordpress when it came time to upgrade the Wordpress code. The SQL internals were modified, and I was inserting directly in to the database (yes, I know, I broke a cardinal rule). I needed an alternative way to insert information in to the database that would be much more future-proof. I remembered about XML-RPC.
It took me some time to find answers to questions I had about XML-RPC and the Wordpress’ API. Wordpress comes with the ability to use XML-RPC, and AtomPub. With regards to XML-RPC, it supports a few protocols:
- MetaWeblog
- Movable Type
- Blogger
- Wordpress’ own methods
Since there was little written documentation as to how to do this, I thought I’d share my findings. Also, although the Blogger API was very easy to figure out and use, I’m not going to cover it here mainly because it doesn’t support the creation of a title field – something for my purposes were required. (To access the blogger API, I used this class.) I’m also only going to cover what’s necessary to create a new post for my own means, nothing more – hopefully it’ll get you on your way to how you’d like to use it.
One thing to note: In order for this to work, your version of Wordpress will have to have “Remote Publishing” enabled; depending on which protocol(s) you’ll be using, you’ll want to enable either “Atom Publishing Protocol” or “XML-RPC”, or both. This can be found (as of Wordpress version 2.7) under “Settings” and then “Writing”.
Let’s get to some nitty-gritty. The following XML-RPC methods are allowable with Wordpress (again, version 2.7):
| Wordpress API:
| Blogger API:
MetaWeblog API:
MovableType API:
|
Wordpress also supports pingback, supposedly as an API. As for the AtomPub API, I don’t really understand that one yet, so if you want to find out what’s supported, you’ll want to look through the wp-app.php file found in your main Wordpress folder. The XML-RPC methods can be found in the xmlrpc.php file, also found in the main Wordpress folder.
As you can see, the Wordpress API is jam-packed with features – I believe most desktop applications that allow you to moderate your comments use the Wordpress API. Unfortunately, no “New Post” option for our needs. Dang. Because of this, and also because the Blogger API doesn’t support the creation of a title field in a new post, I decided to go with the MetaWeblog API. Technically speaking, MovableType and AtomPub are superior options to both Blogger and MetaWeblog from what I’ve been reading; regardless of that (possible) fact, I found it easy to work with the MetaWeblog API.
Let’s get to the code…
Umm…can PHP handle the transformation from data to the XML-RPC protocol of our choice automatically?
Unfortunately, no. However, the creators of Wordpress’ API features thought ahead. They packaged Wordpress with certain features and functionality (and classes) that can be utilized by us mere mortals to achieve our goals. Many of these libraries (such as the one we’ll use) were written by those not affiliated with Wordpress – so they took the legwork of finding good, well-written libraries for us.
We’ll be using the Incutio XML-RPC Library for PHP created by Simon Willison. You could download this yourself and include it in your script (note: commenter believes the official download to be corrupted), or you could just use what Wordpress already has in its folder structure, it’s the same thing with a few (pertinent) modifications and a different file name. (Wordpress uses it internally for some features since it works as a client and a server.)
The file is class-IXR.php, found in your wp-includes folder. So, to start out, we’ll create a PHP file that includes that script. We’ll also need to instantiate a new client object (to talk to the XML-RPC server – aka Wordpress). To find out what the address of your Wordpress XML-RPC server is (in order to instantiate the client), after you’ve enabled the XML-RPC remote publishing in your Wordpress settings, go to your Wordpress blog (any non-admin page) and view the source.
<link rel=”EditURI” type=”application/rsd+xml” title=”RSD” href=”http://www.example.com/xmlrpc.php?rsd />You’ll want to take the URL from the HREF property of that line of code and place it in your browser. The rendered XML of the page gives us information as to the target URI for the protocol(s) we’d be using. If you’ll be using multiple protocols that use multiple targets, you’d have to target them each individually when making client calls. So, on to the fun stuff…
This includes our XML-RPC library, allowing us to create a client connection. It then uses (defines) the target server access point for our client to access the APIs we aim to use. xmlrpc.php supports Wordpress, MovableType, MetaWeblog, and Blogger APIs all in one access point which makes it very easy if you want to use any or all four of them with the same IXR_Client object instantiation. Let’s build on that some more.
This extra code now tells our client to query our server for the Wordpress API’s “getCategories” method using the username of “admin” with a password of “password”. If any errors occur, the script will stop execution after printing the error codes and messages supplied by Wordpress’ API server. If it’s successful, the server’s response is stored in the $response variable.
Taking a step back, the getCategories method takes on 3 parameters. I left one blank simply because Wordpress (as of version 2.7) does not require the BlogID field (WPMU might, however). The 3 parameters are BlogID, Username, and Password. It will authenticate the user before allowing information to be returned.
The Wordpress API is quite easy (or at least for the getCategories method anyway), it simply returns a PHP structured array. An example print_r output from the $response variable would look like the following:
That’s pretty darn easy to break down to values we might need! Now, moving on, let’s add some code to create a new post.
This code sets up our desired blog title, the category we wish to use (in string format, do not use the ID value), the body of the blog post, and then queries the XML-RPC server. It calls the MetaWeblog API’s “New Post” method, and passes it some values. The parameters for this method are as follows:
| Parameter | Description |
| BlogID | not used (yet) |
| Username | the authenticated username that has permission to create posts via XML-RPC |
| Password | the username’s associated password |
| Content | the ARRAY of values that will be converted to XML by our XML-RPC library, and sent to Wordpress. There are a plethora of array key values that Wordpress supports for this data structure, but many of them are Wordpress specific. If you wish to remain more true to the specification, the ones I’ve shown are about all you’ve got. |
| Publish | a boolean value to tell whether or not to immediately publish the post; in this example, it will create a draft entry, requiring someone to check it before publishing. |
So we query the Wordpress XML-RPC server to create our new blog post, and if it’s successful, it returns the newly created blog posts’ ID field. The neat thing about this, is that (again, as of Wordpress version 2.7), if you wish to preview a blog post, you can use your Wordpress installation’s URL and adding a short query string to the end with this blog ID. For example, let’s assume this returned the ID of 3, the preview URL would then be:
http://www.example.com/?p=3
Pretty easy, huh? Here’s the full sample code without any breaks:
Hopefully having this documented somewhere will help someone out. I’ve used it at the work to allow librarians to upload exported XML New Item Record reports to the server, let it be processed, and then post the processed output to a Wordpress Draft where it can be reviewed for any irregularities or errors, and then posted for our public to see. The end result of that can be found here: http://www.sspl.org/newmaterials/
Trackbacks
Trackback specific URI for this entry
Comments
I have provided all of the code examples necessary to automatically post an article to a Wordpress blog via PHP. PHP also contains many useful classes and functions when dealing with XML data (SimpleXML, DOMDocument (DOM XML), XPath, expat, etc... Choosing the proper tool for your data would depend on the business requirements you have, and the structure of the XML. As there are many ways to manage this, I cannot directly help you with that, you would need to do the necessary research to decide what solution is best for your specific case.
It should not take too long if you have any PHP background. I was using this solution (automatically posting to Wordpress) for an XML data file as well. Once the data is parsed, it's quite straight forward. Parsing the data should be easy enough once you choose your parsing solution within PHP (or other language).
No, it's not very time consuming at all, which is handy. If I had direct access to our catalog's database I'd probably completely automate the process and integrate it to our website rather than use Wordpress, but alas... :P At least we can get XML exported data files!
Thank you! Thank you! and Thank you! and oh by the way did I remember to say Thank you!
As for your errors, I'll try to leave a note at the top of the article to mention that - thank you for bringing it up. I can't seem to force the blogging engine to keep my standard quotes when in code blocks. Sorry about that - but glad that once you figured out the problem it worked out for you! Thank you for your feedback!
Interesting thanks -- but do you have *any* idea how to modify the actual wordpress 'date'?
I am trying
$content['dateCreated']="2010-10-10 10:10:10";
as an example
But when I do this I get an error saying "-32700 error in xml format"...
I can figure out how to do this and am becoming exceptionally frustrated :( (Have already spent three hours on a stupid little thing and the wordpress documentation sucks)... :P sorry, just a bit annoyed... If you could help that would be awesome!
2. I will NOT (personally) help with something outside the realm of what was discussed in this article (i.e.: Java / WTK emulator).
3. "Me" - in case you're able to find an answer before me, I wanted to add a few bits of knowledge that might help. When I was researching this stuff, I *think* someone mentioned that datetime values had to be in a specific format for it to work. If it wasn't, the expected result would not be achieved. Also, I can't recall for certain, but the MetaWeblog API might not be able to specify a date different than that of when the API was called. I believe AtomPub supports different dates, but I haven't tried learning that API.
4. For any information that you can't seem to find answers for on the vast WWW, you may want to try the wp-xmlrpc mailing list: http://comox.textdrive.com/pipermail/wp-xmlrpc/
If all you did is copy my code and try to use it (without reading the whole explanation and process steps), the only thing that comes to mind off hand would be that you did not enable your "Remote Publishing" in Wordpress. It's the 4th paragraph down (skipping the list, I didn't count that as a paragraph).
FYI - for anyone else trying to leave a comment. My comments are auto-moderated after 30 days from the initial post. Sorry for no mention of this in my theme.
...a 200 HTML response means that the page was successfully found and rendered. If the error message you're seeing is "Status code was not 200", that tells me that there may be an error in the URL you are using to access your Wordpress' XMLRPC mechanism. Unfortunately I no longer have a Wordpress installation that I can test this with to see if an incorrectly given URL to the XMLRPC call will generate that error message.
If you're using the Incutio library included with Wordpress, there is a way to debug the output to check your data. After creating your new IXR_Client object, set it's debug property to 1.
$client = new IXR_Client('http://xmlrpc.example.com');
$client->debug = 1;
i'm sure i had enabled my XMLRPC functionality within Wordpress.
and i use this to post a post as a draft,it work find for me.
$client->query('metaWeblog.newPost','', 'admin',’password’, $content, false)
but when i want to post a publish post with this script,
$client->query('metaWeblog.editPost', $fm_post_id, USER, PASSWORD, $content, true)
i get an error,
An error occurred - -32301:transport error - HTTP status code was not 200
i set debug property to 1 as you told me, but the error code is too long i can't post it in comment.
As for the code...Ah, now I see the difference. You're using the editPost method, not the newPost. To be honest, I never looked at any other functions in-depth except for the single one that I needed for this project, and that was newPost. As I no longer have a test/development Wordpress install to toy with (the project is still live, but it's production, I can't mess around with it), I don't think I'll be able to be the best source of help on this issue. I would suggest checking the Wordpress community forum, some web searches, the API itself, and possibly even the mailing lists if necessary.
I'm sorry I can't be more helpful. :(
i finally find another way to work it out.
i use xmlrpc-3.0.0.beta library, and everything work fine except it's a little bit slower than using IXR library.
cheer
I used metaWeblog.getRecentPosts for each blog. Now the problem is that each blog must have XML-RPC enabled by default but that's not the case as for each blog this option is disabled by default. So is there a way to enable XML-RPC in Settings->Writings->Remote Publishing by default for each new blog that is created? Or is there any better alternative to using XML-RPC to achieve the integration purpose in our scenario?
Thanks Again!
http://mu.wordpress.org/forums/topic/15814
?
I did a test trying to display the content from a page and it works great! Here is my code for getting the description from a page with id 4682 on my blog.
if (!$client->query('wp.getPage','','4682', 'username','password')) {
die('An error occurred - '.$client->getErrorCode().":".$client->getErrorMessage());
}
$pagetest = $client->getResponse();
echo $pagetest["description"];
Go to http://codex.wordpress.org/XML-RPC_wp to find more examples on what you can pull out of wordpress using this method
The following discussion topic might shed some light on the issue though:
http://wordpress.org/support/topic/328404
Although this is most definitely possible, it would require using more than just the MetaWeblog methods - probably a lot of the Wordpress-specific methods. However, modifying records within Wordpress, especially if it's customized or using a WYSIWYG, may not be the most optimal way to manage this. It might be better to use a Wordpress plugin that creates it more of a CMS than it is, with user access controls and permissions. I don't really work with Wordpress, so I unfortunately can't really recommend a best-of-breed approach. But yes, it is possible.
I have activated XML-RPC service through wordpress admin.
I have installed Qumana web client to post content from local machine.
I entered end point as "www.xyz.com/xmlrpc.php" with username and password.
But after trying to connect my blog it shows error as below:
"Error trying to retrieve your blog information. Error decoding XML-RPC response: The processing instruction target matching "[xX][mM][][] is not allowed."
Please provide me proper solution.
This is briliant, like many posting comments here, I have been searching for information on how to do this but until now I didi not find the information or it was way too complicated for me to put together with my limited knowledge of php.
Now at last I have a solution, thanks to you.
thank you
Lee
url]http://socialmediacraze.com/[/url]
As far as a plugin to help you autopost from bulk articles, not only do I know the situation in which you are looking for an answer, but you'd probably be better off asking this type of question at the Wordpress website community discussion area: http://wordpress.org/support/
The script can be placed on any PHP enabled server, so long as it is given a PHP file extension (so the server knows to run it as PHP). The URL must point to your Wordpress installation's proper path, as explained in the article. The username and password fields must be changed to match your Wordpress username and password. The include path must point to a version of the Wordpress class-IXR.php file, so if not on the same server/account as the Wordpress installation, then you may need to download a copy of that file to include it.
Everything else should be explained within this article.
First I would like to thank you for this piece of code. I've spent the whole day trying to post on WP using XMLRPC without any result.
I can get connected and return categories for instance, but I can't publish anything with your script. I always get :
An error occurred - -32700:parse error. not well formed
I think metaWeblog.newPost is not working anymore... Could you confirm this ?
The error message sounds like it's telling you exactly what the problem is: "not well formed". Try creating a new post with a very simple message, such as "Hello World" and a title of "New". Do not include any other fields other than the title and body.
There is also a debug option (which I mention in a comment in this post, search the page for "debug" and you'll find some example code).
There are some answers to questions found within the comments on this page. :)
I found the solution puting content in a array.
Now it works fine.
$content = array(
'title'=>$title,
'description'=>$article,
'mt_allow_comments'=>$allowcomments,
'mt_allow_pings'=>$allowtrackbacks,
'post_type'=>'post',
'mt_keywords'=>$keywords,
'categories'=>array($category)
$method_name = “metaWeblog.newPost”;
$rpc_url = $rpcfile;
$blog_id = 1;
$publish = true;
$post = array(
“title” => $title,
“wp_slug” => createurl($title),
“description” => $contents,
“categories” => $cat,
“mt_keywords” => $tags,
“custom_fields” => $custom_fields
);
$rpc = new IXR_Client( $rpc_url );
$status = $rpc->query(
$method_name,
$blog_id,
$username,
$password,
$post,
$publish
);
if( !$status ) {
print “Error in RPC request\n”;
print_r( $rpc );
exit;
}
if( $rpc->getResponse( ) ){
$sql=”INSERT INTO `grab_table` (`url`) values (‘$url’)”;
if (mysql_query($sql)){
echo “Add!”;
}
}
Like what I am reading here, but have what I think is a unique Q about this process.
Q:
I have a directory on my local machine (laptop) Ex: "c:\somedir" where I have several .html content files. I want to add these as subposts to a main post (showing as tab, parentid=0 in MySQL DB). I know to do this I must be able to get the "ID" of the parent post, before the post will register under the parent and I found out, using ScribeFire that XML-RPC natively writes to home directory or parent level, then requiring manual intervention to move it as sub-post under the parent post.
My ISP, for security reasons, only allows 'localhost' transactions so I can not us host domain name or IP to gain access to the MySQL DB, so running my PHP script, which on the local machine see my directory fine, cannot see the local directory, when I post my script to the host.
Therefore that is why I am looking at the XML-RPC method as I should be able to post this way, leaving the script on my local machine.
The only problem I see is how to set up my posts so they correctly post under the parent, without requiring manual "MOVE" intervention.
I would appreciate knowing the correct extra code needed here to get this done.
Thanks!
OMR
I'd suggest asking for help at the Wordpress Support Forums as they should be able to (hopefully) provide much more superior support.
What about accessing from local script with:
OMR
The ERROR message below ............
An error occurred - 405:XML-RPC services are disabled on this blog. An admin user can enable them at http://www.articlebooth.com/wp-admin/options-writing.php
Any other php options/ideas/ways/methods/phpcode to get around this problem. Other then ubots or imacros????
Thanks James
I'm not very proficient in PHP, but as far as I can tell from your description, this code could be used to display someone's blogger posts in my Wordpress site, correct?
I used the example script in a page at http://wp.humortimes.com/&Wordpress-import-blog.php, but I get an error saying "Parse error: syntax error, unexpected T_INCLUDE in /usr/home/wheel/humortimes/wordpress/&Wordpress-import-blog.php on line 2"
What am I missing?
Also, is the password info to be included on the
if (!$client->query('wp.getCategories'
line different from the info on the
if (!$client->query('metaWeblog.newPost'
line? Is one for the Wordpress site, and the other for the blog you're importing?
Thanks for any help you can offer!
The password info should not be any different. It's the user account information you'd be using (one that has permission to create a blog post).
As for your T_INCLUDE error...it sounds like you have a syntax error somewhere. If you've doctored up your code at all, try simplifying it back down first and work your way back to more complicated code (if you're new to PHP anyway).
I managed to work out a script that uses a data feed to submit blogs to wordpress via xml-rpc. People can find more details here:
http://www.home-working.info/index.php/creating-a-wordpress-website-via-xml-rpc-using-affiliate-data-feeds/
Cheers
Raj
however i have check amny browser addon that uses the xmlrpc. but no one that works inside wysiwyg client in wordpress.
my client want to be avle to
copy and paste image to wordpress from front end and i have fixed that with nicedit but need it to also upload the image directly when clinet copy from ms word that include iamges to wordpres
any ideas?
query('wp.getCategories','', 'WHERE-I-PUT-MY-WORDPRESS-USERNAME','WHERE-I-PUT-MY-WORDPRESS-PASSWORD')) {
echo('An error occurred calling wp.getCategories - '.$client->getErrorCode().":".$client->getErrorMessage());
}
$response = $client->getResponse();
$content = array(
'title'=>$title,
'description'=>$article,
'mt_allow_comments'=>$allowcomments,
'mt_allow_pings'=>$allowtrackbacks,
'post_type'=>'post',
'mt_keywords'=>$keywords,
'categories'=>array($categories)
);
var_dump($content); // paste the output of this back to the forum for us to review.
if (!$client->query('metaWeblog.newPost','', 'WHERE-I-PUT-MY-WORDPRESS-USERNAME','WHERE-I-PUT-MY-WORDPRESS-PASSWORD', $content, false)) {
echo('An error occurred calling metaWeblog.newPost - '.$client->getErrorCode().":".$client->getErrorMessage());
}
echo $client->getResponse(); //with Wordpress, will report the ID of the new post
?>

I had created a topic discussing how to create an interface to add new posts to a Wordpress blog using PHP and XML-RPC. It was something I had needed for work. Unfortunately for many of my site visitors and readers from Google, I never had the need to edi
Tracked: May 09, 21:17