Una vez terminado mi trabajo para la wiki 2.0 (estuve trabajando en la parte de migración que consistía en migrar las bases de datos de otras wikis como Ewiki o la antigua Nwiki hacia la nueva wiki), ahora he sido redirigido a la última parte del proyecto de final de carrera: Ayudar en el desarrollo de la capa de Interoperabilidad para Moodle 2.0 (más conocido como Web Services).
Cada vez más usuarios y organizaciones utilizan Moodle, y estos cada vez utilizan otras plataformas de acceso, ya sea un móvil, cómo una wii, un iPhone... Esta capa garantizará independencia tecnológica que permitirá a estos dispositivos "hablar" con Moodle, "interoperar". Antes Moodle era una aplicación monolítica y todo funcionaba desde la propia aplicación Moodle.
Esto puede derivar en un amplio abanico de posibilidades: Los desarrolladores podrán crear clientes que puedan interactuar con Moodle.
Ejemplo:
- Moodle está hecho en PHP, y el Web Service estará implementado de la misma forma. Y tenemos a la FIB, una facultad que tiene Moodle instalado para sus estudiantes, y (por decir algo) una aplicación de automatrícula hecha en Python, y desearía que, a la vez que se matriculan los estudiantes, se cree un usuario automáticamente, sin necesitar que haya un becario que haga el trabajo de ir creando a los estudiantes en el Moodle uno a uno.
- De forma "directa", no puedes hacer que una aplicación escrita en Python se comunique con otra aplicación escrita en PHP. Sin webservices, nuestro objetivo es difícil de conseguir.
- Con Web Services podemos conseguirlo. Imaginemos que Moodle dispone de un servicio que es "crear usuario". La aplicación en Python utilizaría ese servicio (transmitiéndole los datos necesarios), y Moodle le contestaría a la aplicación diciéndole si ha habido éxito en la inserción o no, y posibles errores.
Y todo eso, cómo se hace?
Hay varios tipos de protocolos que permiten esto: REST, SOAP, OKI, XML-RPC... De momento, sólamente hay implementado parcialmente REST y SOAP. Estos són los encargados de comunicarse con los clientes. Los clientes mandan la petición en un formato estándar (ya sea en una petición HTTP como en REST, o una petición HTTP + un XML como en SOAP), y el Web Service contesta con un XML con los resultados.
Aquí pongo un esquema de lo que sería la comunicación:
Una vez realizada esta pequeña introducción a los Web Services, pasemos otra vez a Moodle y el trabajo que hay que desarrollar.
En esta capa de Interoperabilidad habrá protocolos REST, SOAP, OKI... cada uno de estos componentes invocará las operaciones de dominio y devolverá resultados. Las operaciones de dominio, por supuesto, serán comunes (se hace una implementación única para todos los protocolos). Estas operaciones que se ponen a disposición del Web Service se conoce como API (application programming interface, un conjunto de operaciones o rutinas que sirven para soportar el desarrollo de aplicaciones).
En este dibujo mostramos cuál será la estructura interna de los WebServices:
- Estará compuesto por tres capas:
- la Externa, la Media y la Core. En la externa (ubicada en la carpeta /webservices) se encontrarán los protocolos (REST en /webservices/rest, SOAP en /webservices/soap,...). Esta capa tiene por objetivo analizar la petición del cliente, y llamar la función correspondiente del external.php
- La capa media está compuesta por varios fichero external.php, un fichero external.php por cada parte de la aplicación (/admin/external.php, /user/external.php, /mod/forum/external.php,...). Estos ficheros se encargan de tratar los parámetros que le llegan de la capa externa y pasarselos a la capa de core.
- La capa core está compuesta por ficheros api.php, un fichero por cada parte de la aplicación, como en el caso del external.php. Estos ficheros son lo que sería la antigua lib.php, el fichero donde se implementan las funciones para acceder a base de datos o ejecutar diferentes acciones.
Cómo implementaremos esto?
El siguiente esquema explica cual será el funcionamiento básico de una petición:
- El protocolo no guarda estado. Esto significa que en cada petición el cliente deberá autentificarse enviando su usuario y su password. Una vez autentificado, el protocolo devolverá un "token", que autentificará al cliente durante toda la petición.
- El cliente llama una función concreta del Web Service, enviando el nombre del módulo, función a llamar y parámetros, incluído el token.
- El protocolo utiliza el token para verificar que la sesión es válida y activa.
- El protocolo llama a la función externa correspondiente, ubicado en el external.php del módulo correspondiente.
- La función en external.php comprueba que el usuario realmente está autorizado a realizar dicha acción.
- La función externa llama a la correspondiente función en core.
- Y el resultado de la función es devuelto al externo, de externo al protocolo, y del protocolo al cliente./li>
Aquí tenemos el diagrama de secuencia que correspondría al ciclo de una petición (almenos en REST, y supongo que será un esquema compartido por todos los protocolos):
La solución de la implementación para el caso de la capa media y de core (la implementación de la capa de protocolo porque depende del protocolo) es la siguiente:
- external.php:
Se usa una convención de nombres para el nombre de las clases: las clases tendrán la terminación "_external", y delante llevarán el nombre del módulo en cuestión. Si se trata de una clase de core (como admin o user) el nombre de la clase sería admin_external o user_external respectivamente, y si es un módulo (como el foro) entonces seria mod_forum_external. Básicamente el nombre depende del Path: por ejemplo, como el external.php del foro se encuentra en /mod/forum, la clase debe llamarse mod_forum_external. Si cambiáramos el nombre de la carpeta, habría que adaptar el nombre de la clase.
Todo esto es por temas de implementación interna. Recordemos que habíamos dicho anteriormente que la capa de protocolo es la que se encarga de localizar y delegar la petición al external.php correspondiente. Pues la localización del módulo se realiza mediante esta convención de nombres.
- En la constructora de la clase se definen las operaciones que se deben llamar en una array "descriptions". Por cada operación se definen cuales son los parámetros de entra y de retorno.
- Las operaciones que se definen en la clase serán todas estáticas, y comprobarán la autorización del usuario, adaptarán los parámetros y llamarán a la función correspondiente de core.
- api.php:
- Todas las funciones serán estaticas.
- El nombre de la clase seguirá la misma convención de nombres que en el caso de la external, pero finalizado en "_api".
En esta página podréis ver código de ejemplo del protocolo REST y del external.php: http://docs.moodle.org/en/Development:Web_services
Enlaces relacionados: