Jaunder

Post by mdorman

M
Michael Alan Dorman@mdorman

The gateway to the server

The machinery of interacting with WordPress

Although I don't have any immediate plans to implement a back-end for anything other than WordPress, I want to make sure it's possible, so I have created a list of operations I want to be able to do on posts (well, OK, I haven't actually written it down or anything, but it's in my head. Somewhere). Each back-end needs to implement each call (even if it's just a no-op).

If that was the only abstraction, though, we would end up with a lot of boilerplate code---or we would define some macros, which I'm not yet familiar with---because each operation would have to take care of pulling out whatever information it needed from the arguments it was handed---which will always include a blog structure as the first item.

Instead, I opted for a level of indirection. Instead of calling a back-end function directly, any time the back-end-agnostic code wants to perform an operation on an article, it goes through org-blog-call. org-blog-call figures out what engine the blog structure is using, constructs the name of the operation for the back-end associated with the blog, and then invokes it.

So it's really pretty short---pulling out a single bit of info and checking for a function's existence.

(defun org-blog-call (blog call &rest args)
  "Make the specified call to the appropriate blog engine.

This allows us to maintain multiple engines, with a set of
operations common to all, and call the appropriate function based
on the engine specification in the entry in `org-blog-alist'."
  (let ((entry (intern (concat "org-blog-" (cdr (assq :engine blog)) "-call"))))
    (if (fboundp entry)
        (apply entry blog call args)
      (error (format  "Can't find function %s" entry)))))

What this is invoking, in the case of a WordPress blog, is org-blog-wp-call. It doesn't do whole heck of a lot, either, other than pull out the parameters that are common to each XML-RPC request, and invoking the actual function (whose name it has constructed, much like org-blog-call).

(defun org-blog-wp-call (blog call &rest args)
  "Easy calls to WordPress API functions.

This routine will take whatever information a user has available,
fill in the rest (if the user is willing to cooperate) and then
call the specified function and return the results."
  (let ((blog-id (cdr (assq :blog-id blog)))
        (func (intern (concat "org-blog-wp-" call)))
        (password (cdr (assq :password blog)))
        (username (cdr (assq :username blog)))
        (xmlrpc (cdr (assq :xmlrpc blog))))
    (if (fboundp func)
        (apply func xmlrpc blog-id username password args)
      (error "Can't find function %s" func))))

At this point, the actual XML-RPC call is pretty anticlimactic:

(defun org-blog-wp-post-create (xmlrpc blog-id username password wp)
  "Create a post on the blog."
  (xml-rpc-method-call xmlrpc
                       'wp.newPost
                       blog-id
                       username
                       password
                       (org-blog-post-to-wp wp)))

Hmmm. Looking back on this, I can see that I'm going to end up changing this at some point. I feel certain there are more direct, cleverer ways to implement this pattern---ones that would even allow me to pull out the open-coded XML-RPC call in org-blog-wp-params. So I'll bee looking into this, though I still want to get through the initial implementation first.