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.