juust ~ php oddities

Unordered list of one element
  • rss
  • begin
  • about
    • vcard
    • WTF is BroJesus
  • php scripts
    • flickr wp widget
    • google multi key serp tool, php script
    • gwt plugin
  • php classes
    • php pagerank class
    • fibonacci class
    • robots.txt parser php class
  • serp
    • serp dashboard wordpress plugin
  • services

p2p with wordpress xml-rpc

juust | 08/02/2010

Simple fun with Wordpress xml-rpc. I want a way to return a welcome message to interested blog owners.

To get that done, I make a new plugin that adds a new method to the xml-rpc server.

The method ‘p2p.welcome’ is mapped to the plugin function ‘p2p_welcome’, which returns the “about yourself” description of the admin profile.

  1. /*
  2. Plugin Name: P2P rpc
  3. Description: RPC Peer to Peer stuff
  4. Version: 1.0.0  
  5. Author: Juust
  6. Author URI: http://www.juust.org/
  7. */
  8.  
  9. /* xmlrpc_methods hooks into IXR_Server */    
  10. add_filter( 'xmlrpc_methods', 'p2p_xmlrpc_methods' );
  11.  
  12. /* pass the $methods array and add a new one */    
  13. function p2p_xmlrpc_methods( $methods ) {
  14.      $methods['p2p.whoami'] = 'p2p_whoami';
  15.      return $methods;
  16. }
  17.  
  18. /* the function that returns the profile description of user 1 (admin) */    
  19. function p2p_whoami() {
  20.  return get_the_author_meta( 'user_description', 1 );
  21. }

I plug that into the wordpress blog.

Then I can make a small test program :

  • include class-IXR.php which has the IXR_Client class
  • extend IXR_Client as P2PClient
  • add a function P2PClient->whoareyou()
  • …that calls the new method p2p.whoami on the blog
  • echo the returned data : the admin profile description
  1. include_once('/absolute/path/to/class-IXR.php');
  2.  
  3. Class P2PClient extends IXR_Client {
  4.  
  5. var $MyPeerConnection;
  6. var $response;
  7. var $url;
  8.  
  9. function __construct($url="") {
  10.                  $this->url = $url;
  11.     if(!$this->connect($url)) return false;
  12.      }
  13.      
  14. //see if there is an xml rpc endpoint
  15. function connect($url)
  16.      {
  17.        if(!$this->MyPeerConnection = new IXR_Client($this->url)) return false;
  18.      }
  19.  
  20.  //query 'p2p.whoami', store the response
  21. function whoareyou() {
  22.   $this->MyPeerConnection->query('p2p.whoami');
  23.   $this->response = $this->MyPeerConnection->getResponse();
  24.      }
  25. }
  26.  
  27. //init the client, query, echo response
  28. $p2p = new P2PClient('http://loaneys.com/xmlrpc.php');
  29. $p2p->whoareyou();
  30. echo "resp ". $p2p->response;

That returns :

Hi I am juust, admin of loaneys.com. I worked as business economist at project control and proces automation in engineering and utilities. These days, I do some scripting as a hobby and stick to painting as job.

That is a basic way to exchange blog data by extending the xml-rpc endpoint.

         
Comments
No Comments »
Categories
wordpress, xml-rpc
Comments rss Comments rss
Trackback Trackback

metaWeblog.newPost posting to Wordpress from Word

juust | 26/10/2009

Quick and dirty : posting to Wordpress from Word with VBA. I put the text source on the server.

It works, to a point. You can take a Word document, run the PostToWordpress macro (with your own blogs settings) and it puts the content in Wordpress.

I haven’t worked with Word for a few years, you’d have to ask someone with up-to-date Word vba skills how to grab the document title, and sanitize and format the document text into proper html-output. For the tests I grabbed a snippet off the net, it does not do a perfect job but the basic idea is kosher.

metaWeblog.newPost

Most sites (including blogger) have skipped from blogger.newPost to newer formats. I prefer using the metaWeblog.newPost rpc method, it is a bit more versatile, and supported by Wordpress as well.

(ref. msdn library article on metaWeblog.newPost)

The methodcall is structured like this :

  • methodname : metaWeblog.newPost
  • blogid
  • blog user name
  • blog password
  • the post struct with it’s members
    • categories array
    • description (the doc text)
    • title
    • date created
  • publish (0=save as draft, 1=publish immediately)

So let’s build that step by step as vba routine :

  1.  
  2. Sub PostToWordpress()
  3.  
  4. 'the basic blog settings
  5.     txtURL = "http://www.blog.com/xmlrpc.php"
  6.     txtBlogId = "1"
  7.     txtUserName = "MyUserName"
  8.     txtPassWord = "MyPassword"
  9.  
  10. 'the document settings
  11.     txtTitle = "MyTitle"
  12.     'note : you can use the documents creation date here
  13.     txtDateCreated = Format(Now(), "yyyyMMdd") & "T" & Format(Now(), "hh:mm:ss")
  14.    
  15.     'Categories is an array in the post,
  16.     'you can use category names,
  17.     'and you can always use "Uncategorized"
  18.     'as all wordpress blogs have it
  19.  
  20.     Dim MyCategories(2) As String
  21.     MyCategories(1) = "Uncategorized"
  22.     MyCategories(2) = "example_category_one"
  23.  
  24.     'note: this function grabs the document text,
  25.     'replaces linebreaks with html linebreaks etc.
  26.  
  27.     'it needs a lot more work
  28.     txtDocument = getCurrentDocAsSimpleHtml()

Once I have the blog settings and the content + attributes for the new Wordpress post, I set up the XMLHttpRequest object :

  1.      
  2.     Dim objSvrHTTP As ServerXMLHTTP
  3.     Dim strT As String
  4.     Set objSvrHTTP = New ServerXMLHTTP
  5.  
  6.     objSvrHTTP.Open "POST", txtURL, False, CStr(txtUserName), _
  7.     CStr(txtPassWord)
  8.  
  9.     objSvrHTTP.setRequestHeader "Accept", "application/xml"
  10.     objSvrHTTP.setRequestHeader "Content-Type", "application/xml"

Then I start building the XML to send to Wordpress,

  1.  
  2. 'methodcall    
  3.     strT = strT & "<methodcall>"
  4.  
  5. 'methodname
  6.     strT = strT & "<methodname>metaWeblog.newPost</methodname>"
  7.  
  8. 'parameters : blog settings
  9.     strT = strT & "<params>"
  10.     strT = strT & "<param><value><string>" & txtBlogId & "</string></value></param>"
  11.     strT = strT & "<param><value><string>" & txtUserName & "</string></value></param>"
  12.     strT = strT & "<param><value><string>" & txtPassWord & "</string></value></param>"
  13.  
  14. 'parameters : the post structure
  15.     strT = strT & "<param>"
  16.         strT = strT & "<struct>"
  17.  
  18. 'parameters : post : category array
  19.             strT = strT & "<member><name>categories</name>"
  20.                 strT = strT & "<value>"
  21.                     strT = strT & "<array>"
  22.                         strT = strT & "<data>"
  23.  
  24.    For i = 1 To UBound(MyCategories)
  25.                             strT = strT & "<value>" & MyCategories(i) & "</value>"
  26.    Next i
  27.                         strT = strT & "</data>"
  28.                     strT = strT & "</array>"
  29.                 strT = strT & "</value>"
  30.             strT = strT & "</member>"
  31.  
  32. 'parameters : post : the content
  33.         strT = strT & "<member><name>description</name>"
  34.             strT = strT & "<value>< [!CDATA[" & txtDocument & "]]></value>"
  35.         strT = strT & "</member>"
  36.  
  37. 'parameters : post : title
  38.         strT = strT & "<member><name>title</name><value>" & txtTitle & "</value></member>"
  39.  
  40. 'parameters : post : date created
  41.         strT = strT & "<member><name>dateCreated</name><value><datetime .iso8601>" &  txtDateCreated & "</datetime></value></member>"
  42.         strT = strT & "</struct>"
  43.     strT = strT & "</param>"
  44.  
  45. 'parameters : post : store as draft (0) or publish immediately (1)
  46.     strT = strT & "<param><value><boolean>0</boolean></value></param>"
  47.  
  48. 'end parameters
  49.     strT = strT & "</params>"
  50.  
  51. 'end methodcall
  52.     strT = strT & "</methodcall>"
  53.  
  54. 'send it to wordpress
  55.     objSvrHTTP.send strT
  56.  
  57. 'send the response to the debug window
  58.     Debug.Print objSvrHTTP.responseText
  59.  
  60. End Sub

conversion to html

The main practical problem is converting the Word document content to html. I grabbed two quick functions to select the current document text, convert the most common html entities and replace linebreaks with their html counterparts, but it is far from perfect.

  1. Private Function getCurrentDocAsSimpleHtml() As String
  2. '… see source text
  3. End Function
  4.  
  5. ' simple HTML entity encoder
  6. Private Function encode(ByVal s As String) As String
  7.     If s = "&" Then
  8.         encode = "&amp;"
  9.     ElseIf s = "< " Then
  10.         encode = "&lt;"
  11.     ElseIf s = ">" Then
  12.         encode = "&gt;"
  13.     ElseIf s = Chr(13) Then
  14.         encode = "<br />"
  15.     Else
  16.         encode = s
  17.     End If
  18. End Function

The Wordpress Incutio xml-parser will not pass content it cannot make sense of, which leaves you with an empty post.

using CDATA

A rather common hack I used above is using < ![CDATA[ ]]> to wrap the post content, which indicates to the wordpress xml-parser that I pass a string of raw character data as content. The parser ignores it, and Wordpress stuffs everything in the database.

Works great, but it can backfire and slip stuff in the database that wordpress cannot handle and display correctly.

I’d test without using CDATA if you want to post from Word on a regular basis, or use a more professional html-converter on the word documents first.

         
Comments
8 Comments »
Categories
wordpress, xml-rpc
Comments rss Comments rss
Trackback Trackback

RpSequel : rfc sql crud with wordpress

juust | 23/10/2009

I set out to use MsAccess with xhr/ajax to maintain tables I added to my wordpress database, from my desktop. (Because I suck at html forms backends and consider them a waste of time.)

I used a similar technique ten years ago, setting up msaccess as reporting tool for SAP R/3 with RFC dll’s and ActiveX. That remained stable for eight years without maintenance. Hey, I might get lucky with Wordpress xml-rpc and xhr/ajax.

I called the example RpSequel.

adding sql rpc functions

To sync the data sets, I will duplicate a list with sequel operations from my desktop database as rfc call to my blog’s xmlrpc-endpoint. To handle that list, I plug a sql crud method into the xml-rpc method array in Wordpress :

  1. add_filter( 'xmlrpc_methods', 'rpsequel_methods' );
  2.  
  3. function rpsequel_methods( $methods ) {
  4.     $methods['rpsequel.rpsequelInsert'] = 'rpsequelInsert';
  5.     return $methods;
  6. }
  7.  
  8. function rpsequelInsert($args) {
  9. }

The basic INSERT method itself can be simple:

  1. function rpsequelInsert($args) {
  2.         global $wpdb;
  3.  
  4. //the first parameters
  5.         $blog_id = (int) $args[0];
  6.         $username = $args[1];
  7.         $password = $args[2];
  8.         $tablename      = $args[3];
  9.  
  10. //get the structs
  11.         $structs        = $args[4];
  12.  
  13. //pick the first
  14.         $struct = $structs[0];
  15.  
  16. //compose the mysql insert statement    
  17.         foreach($struct as $key => $value){
  18.             $SqlFields .= " `".$key . "`,";
  19.             $SqlValues .= " '".$value . "',";
  20.         }
  21.  
  22.         $SqlFields=substr($SqlFields, 0, strlen($SqlFields)-1);
  23.         $SqlValues=substr($SqlValues, 0, strlen($SqlValues)-1);
  24.    
  25.         $SqlStatement .= "INSERT INTO ".$wpdb->prefix.$tablename. " (". $SqlFields .  ") VALUES (".$SqlValues . ")";
  26.        
  27. //execute the query        
  28.         $wpdb->query($wpdb->prepare($SqlStatement));
  29.  
  30. //return the record id
  31.        return $wpdb->insert_id;
  32. }

That in itself is not very exciting, it stuffs records in the host’s database. Which is fine, however, I want the blog to respond to individual operations.

I can write rpc-functions for every single function I want the blog to perform, that means truckloads of rpc-functions, on both client and server end. I am incredibly lazy, so I ain’t gonna go there.

adding hooks to sql rpc functions

Lucky for me, Wordpress has hooks, hooks are cool.

Adding action hooks (before_insert and after_insert) to the crud method makes it more powerful. Two hooks are enough to separate the business logic of the desktop database from the blogs reporting logic.

  1. function rpsequelInsert($args) {
  2.         global $wpdb;
  3.  
  4. //the first parameters
  5.         $blog_id = (int) $args[0];
  6.         $username = $args[1];
  7.         $password = $args[2];
  8.         $tablename      = $args[3];
  9.  
  10. //get the structs
  11.         $structs        = $args[4];
  12.  
  13. //here is the first action hook,
  14. //it hands the tablename and the records over to any
  15. //function that 'listens' on the action hook
  16.  
  17. do_action('rpsequel_before_insert',  $tablename, $structs);
  18.  
  19. //the rest of the rather dull method
  20.  
  21.         $struct = $structs[0];
  22. //….
  23. //execute the query        
  24.         $wpdb->query($wpdb->prepare($SqlStatement));
  25.  
  26. //here is the second action hook,
  27. //it hands the table name with the new record id
  28. //to any function that 'listens' on the action hook
  29.  
  30. do_action('rpsequel_after_insert',  $tablename, $wpdb->insert_id);
  31.  
  32. //return the record id
  33.        return $wpdb->insert_id;
  34. }

Now it is more exciting.

  • I can send a list of records and a rfc insert-method to the blogs xmlrpc endpoint
  • the rfc crud-plugin can process the records one by one
  • Before and after each insert operation, the method triggers an action.
  • Before inserting, it exposes the record data.
  • After inserting, it exposes the record id.

And the last two, was exactly what I wanted.

adding functionality with plugins

Now I can add tiny plugins, that ‘listen’ on the action hooks in the rfc-methods. If there is an INSERT into the database, my plugins read which table it affects. They can perform actions, either before the insert, with the new record data, or after the insert, with the new record id.

  1. add_action ( 'rpsequel_before_insert', 'before_insert_logic', 10, 2);
  2. add_action ( 'rpsequel_after_insert', 'after_insert_logic', 10, 2);
  3.  
  4. function before_insert_logic($rpc_tablename, $rpc_array) {
  5.    if($rpc_tablename=="ships") {
  6. //do some stuff before inserting incoming records
  7.    }
  8. }
  9.  
  10. function after_insert_logic($rpc_tablename, $rpc_insert_id) {
  11.    if($rpc_tablename=="ships") {
  12. //do some stuff after inserting incoming records
  13.    }
  14. }

That’s basically all it takes. As technique, it has it’s limitations, but it can come in handy sometimes.

         
Comments
1 Comment »
Categories
php, wordpress, xml-rpc
Tags
xml-rpc
Comments rss Comments rss
Trackback Trackback

« Previous Entries

Recent Posts

  • p2p with wordpress xml-rpc
  • Tweets on Google’s frontpage
  • happy new year
  • metaWeblog.newPost posting to Wordpress from Word
  • IE is retarded

click me!
rss
Comments rss
Blog Directory
Web Developement Blogs - BlogCatalog Blog Directory
Listed in LS Blogs the Blog Directory and Blog Search Engine
Blog Flux Directory
joopita.com free web directory and search engine
design by jide
sitemap
8085 confirmed spam kills