21 août 2006

Serveur SOAP en PHP 5 pour "Microsoft Office Research Service"

Présentation

Avec Microsoft Office, on a la possibilité d'utiliser un volet (ou panneau) de recherche dans les applications Microsoft (Word, Excel, Internet Explorer).

Ce bandeau ou volet permet d'effectuer des recherches dans des bases de données ou dans des sites web sur Internet. (Pour plus de détails)

Fonctionnement

Techniquement, le panneau de recherche fait une demande à un serveur distant, à l'aide du protocole SOAP. Théoriquement, cette technique est interopérable. Malheureusement, avec Microsoft, cette interopérabilité n'est pas tout à fait complète.

Pour ce service, le serveur SOAP définit deux actions :

  • Registration
  • Query

Ces deux actions SOAP prennent en entrée et en sortie des objets contenant du XML. Ce XML est normalisé par des Schemas

En PHP

Voici comme réaliser, en PHP, un serveur SOAP capable de répondre aux applications Microsoft.

Définitions des types

Pour chaque action SOAP, on a un type en entrée et un type en sortie :


/**
 * Objet en entrée de la méthode Status
 */
class Status { }
/**
 * Objet en retour de la méthode Status
 */
class StatusResponse 
{
    public $StatusResult;
}
/**
 * Objet en entrée de la méthode Registration
 */
class Registration  
{
    public $registrationXml;
}
/**
 * Objet en retour de la méthode Registration
 */
class RegistrationResponse 
{
    public $RegistrationResult;
}
/**
 * Objet en entrée de la méthode Query
 */
class Query 
{
    public $queryXml;
}
/**
 * Objet en retour de la méthode Query
 */
class QueryResponse 
{
    public $QueryResult;
}

Classe d'action

Cette classe regroupe les actions SOAP.


class MicrosoftOfficeResearchService 
{
    /**
     * @param void
     * @return StatusResponse
     */
    function Status()
    {
        $result = new  StatusResponse;
        $result->StatusResult = 'ONLINE'; // or OFFLINE
        return $result;
    }
    /**
     * @param Registration
     * @return RegistrationResponse
     */
    function Registration($request)
    {
        $response = new RegistrationResponse;
        $response->RegistrationResult = file_get_contents('Registration.xml');
        return $response;
    }
    /**
     * @param Query
     * @return QueryResponse
     */
    function Query($request)
    {
        $doc = new DOMDocument();
        $doc->loadXML($request->queryXml);

        $xpath = new DOMXPath($doc);
        $xpath->registerNamespace('m', 'urn:Microsoft.Search.Query');

        $QueryTextNodeList = $xpath->query('//m:QueryText');
        $QueryText = $QueryTextNodeList->item(0)->nodeValue;

        // la variable $QueryText contient la valeur saisie 
        // dans le volet de recherche.
        //
        // On peut ici effectuer un traitement spécifique 
        // 

        $response = new QueryResponse;
        $response->QueryResult = str_replace('Exemple', $QueryText, file_get_contents('Query.xml'));
        
        return $response;
    }
}

Pour l'exemple, les deux actions renvoient une réponse préformatée : Query.xml et Registration.xml. Ces deux fichiers sont spécifiques à chaque service. Un exemple du contenu de ces fichiers est disponible à cette adresse

Description du service SOAP

Cette description se fait au moyen du fichier XML au format WSDL. C'est inutile de chercher à générer ce fichier automatiquement à partir du fichier source ou encore de chercher à l'écrire soi-même. Il y a une méthode beaucoup plus simple...

Il suffit de récupérer le fichier WSDL d'un serveur existant, par exemple,
celui-ci, et de légèrement l'adapter :

  • En supprimant tout ce qui concerne les protocoles GET et POST (*HttpPost et *HttpGet)
  • En renommant quelques noms (notamment pour les balises wsdl:service, wsdl:port, wsdl:binding et wsdl:portType
  • En modifiant toutes les URLs

Pour être encore plus rapide, on peut prendre le fichier WSDL de l'exemple fournit avec cet article.

Écriture du serveur SOAP

Avec PHP 5, rien de plus simple, la classe SoapServer s'occupe de tout.
Par contre, il faut ajouter un traitement particulier pour les clients Microsoft. En effet, ceux-ci sont très sensibles aux espaces de noms. On doit modifier à la volée les espaces de noms générés par la classe SoapServer pour qu'ils soient compatibles avec les clients Microsoft.


// {{{ Serveur SOAP 
$server = new SoapServer($wsdl, array('uri' => $uri, 'classmap' => $classmap));
$server->setClass($class);
/**
 * Correction du flux SOAP pour qui il soit compatible avvec les clients Microsoft
 * @param string flux XML/SOAP
 * @return string flux XML/SOAP
 */
function callback($buffer)
{
    $s = array('<ns1:RegistrationResponse>', 'ns1:', 'xmlns:ns1="urn:Microsoft.Search"');
    $r = array('<RegistrationResponse xmlns="urn:Microsoft.Search">', '', '');
   return (str_replace($s, $r, $buffer));
}
ob_start('callback');
$server->handle();
ob_end_flush();
// }}}

Exemple complet

Pour tester pour de vrai ce service web, il suffit de télécharger l'archive et de la décompresser à la racine d'un serveur apache-php5.

http://www.touv.fr/IMG/zip/SearchService.zip