This post describes my second bash at understanding PHP and SOAP webservices, work carried out off and on over the last couple of weeks. The first time I connected PHP to an externally hosted web-service was using a script that I wrote that was external to Moodle. Now my challenge is slightly different: to try to get Moodle calling external web services.
Just to make sure I understand everything, I'm going to present some background acronyms, try and remember what pages I looked at before, then step towards uncovering parts of Moodle that are in some way connected to the magic of web services.
I'm required to interface to web services that use the SOAP protocol (wikipedia). SOAP is, I am led to believe, an abbreviation for Simple Object Access Protocol. In a nutshell, SOAP allows you to send a message from one computer to another, telling it to do stuff, or asking it a question. In return, you're likely to get a response back that either tells you what you wanted or indicates why your request had failed. SOAP is one of many different techniques that you can use to pass messages to one computer to another over the internet.
Another technique, which is simpler (and faster) but has some limitations that SOAP gets round, is REST (wikipedia). More information on this 'architectural style' can be found quite easily by doing a quick internet search. My focus is, however, SOAP.
So, assuming that one computer exposes (or makes available) a web service to another computer, how do other computers know how to call a service? In other words, what parameters or data does a particular service expect? The answer is that the designers of SOAP service use a language that describes the format of the messages that the SOAP server (or service) will accept. This language is called WSDL, or Web Services Description Language (wikipedia).
Each SOAP server (or service) has a web address. If you need to find out what data a SOAP service requires, you can usually ask it by adding ?wsdl after the service name. This description, which is presented in a computer readable structure, can sometimes help you to build a SOAP call – a request from your computer to another.
Very often (in my limited experience of this area), the production and use of this intermediate language is carried out using layers of software tools and libraries. At one end, you will describe the parameters that you will process, and some magic programming will take your description (which you give in the language of your choice) and convert it into a difficult to read (for humans!) WSDL equivalent. But all this is a huge simplification, of course! And much can (and will) go wrong on the journey to get SOAP web services working.
A web service can be a building block of a Service Oriented Architecture (again, wikipedia), or SOA. In the middle, between different web services you can use the mysterious idea of middleware to connect different pieces of software together to manage the operation of a larger system, but this is a whole level of complexity which I'm very happy to avoid at this point!
Stuff I looked at earlier
The first place that I looked was in a book! Specifically, the PHP Cookbook.
Chapters 14, consuming web services, and 15, building web services looked to be of interest, specifically the sections entitled 'calling a SOAP method with/out WSDL'. Turning to this section I was presented immediately with a number of possibilities of how to make SOAP calls since there are a number of different implementations depending upon the version of PHP that you're using.
Moodle, as far as I understand, can work with version 4.3 of PHP, but moves are afoot to move entirely towards version 5. My reference suggested its perhaps best to use the bundled SOAP extension as opposed to the other (PEAR::SOAP or NuSoap) libraries since they are faster, more compatible with the standards, automatically bundled and exceptions (special case errors) that occur within SOAP are fed into corresponding PHP exception constructs to make programs (theoretically!) easier to read.
On my first attempt to call a web service, I ran into trouble straight after starting! All my code was failing for a mysterious reason and my debugger wasn't deciding to give me anything that was useful. After doing some searching and finding some on-line documentation I gave the PEAR library a try, but ended up just as confused. I ended up asking one of my illustrious colleagues for help who suggested that I should add an additional parameter to original attempts using the PHP extensions to take account of local network setup.
Calling seemed to be quite easy. I could create something called a SOAP client, tell it which address I want to call, give it some options and make a call my sending my client a message which has the same name of the web service which I want to call, optionally loaded up with all my parameters. To see more of what came back, I put some of the client variables in some temporary variables so I could more easily watch what was coming back in my debugger.
Now that I (more or less) knew how to call web services using PHP, it struck me that it might be useful to see how it might be possible to present web services using PHP. This was found in the next chapter of the book.
To maintain consistency, I asked the question how might I create some WSDL that describes a service? Unfortunately, there is not an easy answer to this one. Although the integral SOAP libraries don't directly offer support to do this, there are some known techniques and utilities that can help.
One of the big differences between PHP and the WSDL language is that PHP is happy to just go ahead and do things with data without having to know exactly what form (or type) the data takes. You only get into trouble when you ask PHP to carry out operations on a data item that doesn't make sense.
WSDL, on the other hand, describes everything, giving both the name of a data item and its type. Because of this, you can't directly take a PHP data structure and use it to create WSDL. To get round this difference one approach is to provide this additional information in the form of a comment. Although comments are intended to help programmers, they can also be read by other computer programs. By presenting data type information in the form of a comment, an intermediate program can create WSDL structures without too much trouble, saving developer time and heartache. This approach is used by both the NuSoap library and code that works with PHP 5. But I digress...
Moodle web services code
There appear to be some plans to expose some of the Moodle functionality via a series of web services, enabling Moodle to be connected to and used with a range of external applications. There is also a history connecting Moodle with external assessment systems using web services.
A grep through the Moodle codebase (for 1.9) reveals a library called (perhaps unsurprisingly) soaplib. There appears to be some programming logic which makes a decision about which SOAP interface library to use, depending upon the version of PHP: use the native version if PHP 5 is used, otherwise NuSoap.
I'm guessing that the need to use the NuSoap library will gradually disappear at some point, but a guess is totally different from finding out whether this is really going to happen.
One way to find out what is going on and what lies in store for the future is to explore the on-line discussion forums and quickly find a forum that is dedicated to discussing Moodle web services. It appears there are two interesting developments, something called the Moodle NetWork (which allows you to share resources between different instances of Moodle, at a first glance), and non-core Moodle code contribution called the OKTech Web Services. After a little poking around it's possible to find some documentation that describes this development in a little more detail.
I also discovered a documentation page entitled Web services API , but is related to XML-RPC (wikipedia) rather than SOAP. My head is beginning to hurt!
Returning to the Moodle core SOAP library, I ask the question: what uses the soaplib? One way to do this is to search for calls to functions that are contained within this library. I have to confess, I didn't find anything. But, what I did find is a discussion.
It turns out it was added as a result of work carried out at the University of York in the UK for a project called Serving Maths that created something called the Remote Question Protocol (RQP). The initial post mentions concerns about not being able to make use of some of the additional parameters that the PHP 5 library provides. This is a concern that I share.
I've more or less finished my whistlestop tour of Moodle components and code that relate to web services type stuff. I'm sure there is more lurking out there that I haven't discovered yet. But what of a conclusion?
Since I'm not planning on using Moodle to expose any web services I can thankfully sidestep some of the more difficult discussions I've uncovered.
Also, since there isn't much in the way of existing SOAP utility code that I can build upon and I roughly know more or less how to call web services using the magic functions that are provided in PHP 5, I'm going to try to more or less directly add some lines of code to Moodle. But before I do this, like every good developer, I'll test things out using a test harness to explore how my target services behave.
Image: modified from wikipedia