Edit me

Introduction

Le webservice du module de stats est basé sur l’architecture REST, l’objet qu’il représente est le plan d’analyse (amap).

Adresse du webservice: https://stats.voozanoo.net/modulestats/ws/amap

Les actions possibles:

  • GET:
    • Renvoi la liste des plans d’analyse de l’utilisateur
    • Renvoi le résultat d’un plan d’analyse
  • POST:
    • Exécution d’un plan d’analyse

L’authentification est de type basic:
https://login:password@stats.voozanoo.net/modulestats/ws/amap

API

GET

Renvoi la liste des plans d’analyses de l’utilisateur
Method: GET
Adresse: https://stats.voozanoo.net/modulestats/ws/amap

Retour

Nom Type Description
status string Contient success si aucune erreur
message string Message d’erreur si status est différent de success
response Object Voir le chapitre Response

Response

Nom Type Description
amap array Liste des plans d’analyse.
Voir le chapitre Amap

Amap

Nom Type Description
id_data integer Identifiant du plan d’analyse
id_amap integer Identique à id_data
name string Nom du plan d’analyse
description string Description du plan d’analyse
tags string Tags du plan d’analyse, séparés par des espaces
providers Object Listes des providers, c’est à dire les entités qui sont source de données.
Voir le chapitre Provider

Provider

Nom Type Description
id_provider integer Identifiant unique du provider
name string Nom du provider
type_id integer Identifiant unique du type
type_label string Type, valeurs possibles: Webservice Voozanoo4 Webservice File
type_code string Code du type, valeurs possibles: ws vzn4 ws file
ws_username string Login utilisé pour se connecter au provider (providers de type Webservice, Webservice Voozanoo4)
ws_csv_url string URL du provider (providers de type Webservice, Webservice Voozanoo4)
file_id integer Identifiant du fichier (provider de type File)
file_name string Nom du fichier (provider de type File)

Exemple en annexe

POST/id/[AMAP_ID]

Exécute un plan d’analyse.
Method: POST
Adresse: https://stats.voozanoo.net/modulestats/ws/amap/id/[id_amap]/token/[token]

Paramètres
Nom Type Description
id_amap ou id integer Identifiant du plan d’analyse
type string Format de sortie.
Valeur(s) possible(s) html (défaut)
params array Paramètres à transmettre au module de stats.
Sous la forme d’un tableau associatif.
data string Paramètre optionnel
Données à utiliser pour l’exécution du plan d’analyse. Il s’agit un fichier zippé pouvant contenir plusieurs fichiers de données.
Le fichier de données est un fichier zip contenant un ou plusieurs fichiers CSV. Le nom des fichiers CSV est important, ils doivent correspondre aux alias des fichiers indiqués dans le plan d’analyse, pour les providers de type fichier.
Les fichiers doivent directement être au plus haut niveau du zip. Il ne doit pas y avoir de sous-dossiers.
data_hash string Paramètre optionnel, doit être déclaré si le paramètre data est passé.
Hash des données passées via le paramètre data. Permet de vérifier s’il n’y a pas eu d’altération des données pendant le transfert.
transfert_mode string Paramètre optionnel, est utilisé si le paramètre data est passé.
Valeurs possibles complete (défaut) chunk (envoi des fichiers par “morceaux”)
last_chunk boolean Transfert de fichier par chunk: indique s’il s’agit du dernier chunk.
id_chunk string Transfert de fichier par chunk: chemin vers le fichier sur le module de stats. Fourni par le module de stats après l’envoi du premier chunk
token string Token amap renvoyé par le module de stats.
debug boolean Active le mode debug sur les scripts R
(false par défault)

Exemple de fonction PHP de transfert de fichier par chunk:

protected function _transferFile( Zend_Rest_Client $oClient, $sFileFullPath )
{
	$oSplitter = new Core_Library_File_Splitter( array(
		'FileFullPath' => $sFileFullPath,
		'Base64Handling' => true
	) );

	$iChunkIndex = 1;
	$sFileNameOnStatMod = null;
	$sToken = null;

	while ( $iChunkIndex <= $oSplitter->GetTotalChunks() ) {

		if ( $iChunkIndex == $oSplitter->GetTotalChunks() ) {
			$oClient->last_chunk( true );
		}
		if ( $sFileNameOnStatMod != null ) {
			$oClient->id_chunk( $sFileNameOnStatMod );
		}
		if ( $sToken != null ) {
			$oClient->token( $sToken );
		}

		$oClient->data( $oSplitter->GetChunk( $iChunkIndex ) );
		$oClient->data_hash( $oSplitter->GetChunkHash() );
		$oClient->transfert_mode( 'chunk' );

		$oResult = $oClient->post();
		if ( false === $oResult->isSuccess() ) {
			throw new Core_Library_Exception_WebServiceError( sprintf(
				'An error occured while calling webservice : %s ', $oResult->message
			));
		}
		$sFileNameOnStatMod = $oResult->response->id_chunk;

		if ( isset( $oResult->response->token ) ) {
			$sToken = (string) $oResult->response->token;
		}

		$iChunkIndex++;
	}

	return $sToken;
}

Retour

Nom Type Description
status string Contient success si aucune erreur
message string Message d’erreur si status est différent de success
response Object Voir le chapitre Response
Response
Nom Type Description
state string Statut de l’exécution: initializing onidle fail ready success
html string Résultat au format HTML.
Est vide si statut = onidle ou initializing
json string Résultat au format JSON
Est vide si statut = onidle ou initializing

Format utilisé pour la cartographie dynamique, contient des données au format GeoJSON.
token string Token d’exécution, à utiliser en paramètre du GET pour récupérer le résultat.

GET/id/[AMAP_ID]/token/[TOKEN]

Renvoi un plan d’analyse avec son résultat, ou l’avancement de l’exécution.
Method: GET
Adresse: https://stats.voozanoo.net/modulestats/ws/amap/id/[id_amap]/token/[token]

Paramètres

Nom Type Description
id_amap ou id integer Identifiant du plan d’analyse
token string Identifiant d’exécution, renvoyé par le POST

Retour

Nom Type Description
status string Contient success si aucune erreur
message string Message d’erreur si status est différent de success
response Object Voir le chapitre Response
Response

| Nom | Type | Description | | ——- | ——- | ————————————————————————————————————————————————————————– | | state | string | Statut de l’exécution: initializing onidle fail ready success | | percent | integer | Avancée de l’exécution en % | | html | string | Résultat au format HTML.
Est vide si statut = onidle ou initializing | | json | string | Résultat au format JSON
Est vide si statut = onidle ou initializing

Format utilisé pour la cartographie dynamique, contient des données au format GeoJSON. | | error | string | Est vide si status != fail |

Exemples

Exécution d’un plan d’analyse et affichage du résultat

$oClient = new Zend_Rest_Client(
	"https://" . $login  . ":" . $spassword . "@stats.voozanoo.net/modulestats/ws/amap"
);

$iIdAmap = 33;

$oClient->id( $iIdAmap );

$oResult = $oClient->post();

if ( false === $oResult->isSuccess() ) {
	throw new Exception(
		sprintf( 'An error occured while calling webservice : %s ', $oResult->message )
	);
}

$sToken = (string) $oResult->response->token;
do {

	$oClient->id( $iIdAmap );
	$oClient->token( $sToken );

	$oResult = $oClient->get();

	if ( false == $oResult->isSuccess() ) {
		throw new Exception( sprintf(
			'An error occured while calling webservice : %s ', $oResult->message )
		);
	}

	$sState = (string) $oResult->state;

} while ( $sState == 'onidle' || $sState == 'initializing' );

header( 'content-type: text/html' );
echo $oResult->response->html;

L’exemple ci-dessus utilise la version du webservice qui ne gère qu’un seul type de résultat, du HTML.

Envoi des données (par chunk)

$oClient = new Zend_Rest_Client(
	"https://" . $login  . ":" . $spassword . "@stats.voozanoo.net/modulestats/ws/amap"
);


$iIdAmap = 33;

$oClient->id( $iIdAmap );

$sData = FileGetContents( 'data.csv' );
$sZippedData = ZipString( $sData, 'Tiramisu.csv' );
$sTmpFileName = tempnam( sys_get_temp_dir(), 'stat' );
file_put_contents( $sTmpFileName, $sZippedData );

$oSplitter = new Core_Library_File_Splitter( array(
	'FileFullPath' => $sTmpFileName,
	'Base64Handling' => true
) );

$iChunkIndex = 1;
$sFileNameOnStatMod = null;
$sToken = null;
while ( $iChunkIndex <= $oSplitter->GetTotalChunks() ) {

	if ( $iChunkIndex == $oSplitter->GetTotalChunks()  ) {
		$oClient->last_chunk( true );
	}
	if ( $sFileNameOnStatMod != null ) {
		$oClient->id_chunk( $sFileNameOnStatMod );
	}

	$oClient->data( $oSplitter->GetChunk( $iChunkIndex ) );
	$oClient->data_hash( $oSplitter->GetChunkHash() );
	$oClient->transfert_mode( 'chunk' );

	$oResult = $oClient->post();
	if ( false === $oResult->isSuccess() ) {
		throw new Exception( sprintf(
			'An error occured while calling webservice : %s ', $oResult->message )
		);
	}
	$sFileNameOnStatMod = $oResult->response->id_chunk;

	if ( isset( $oResult->response->token ) ) {
		$sToken = (string) $oResult->response->token;
	}

	$iChunkIndex++;
}

unlink( $sTmpFileName );

if ( $sToken == null ) {
	throw new Exception( 'Undefined token!' );
}

do {

	$oClient->id( $iIdAmap );
	$oClient->token( $sToken );

	$oResult = $oClient->get();

	if ( false == $oResult->isSuccess() ) {
		throw new Exception( sprintf(
			'An error occured while calling webservice : %s ', $oResult->message )
		);
	}

	$sState = (string) $oResult->state;

} while ( $sState == 'onidle' || $sState == 'initializing' );

header( 'content-type: text/html' );
echo $oResult->response->html;

Passage de paramètre

$oClient->params( json_encode( array(
	'level' => 3,
	'param1' => 'foo',
	'param2' => 'bar'
) ) ) ;
.level = JSON$params$level

Annexe

Exemple d’une liste de plans d’analyses renvoyée par le GET

[status] => success
			[response] => SimpleXMLElement Object
				(
					[amap] => Array
						(
							[0] => SimpleXMLElement Object
								(
									[id_data] => 1
									[id_amap] => 1
									[name] => Carto élections USA
									[description] => SimpleXMLElement Object
										(
										)

									[tags] => election usa présidentielle carto
									[providers] => SimpleXMLElement Object
										(
											[provider] => Array
												(
													[0] => SimpleXMLElement Object
														(
															[id_provider] => 1
															[name] => election2012
															[type_id] => 72
															[type_label] => File
															[type_code] => file
															[ws_username] => SimpleXMLElement Object
																(
																)

															[ws_csv_url] => SimpleXMLElement Object
																(
																)

															[file_id] => 1
															[file_name] => 2012_US_elect_results_county_level(EuroFormat) (1).csv
														)

													[1] => SimpleXMLElement Object
														(
															[id_provider] => 2
															[name] => jpelection2012
															[type_id] => 72
															[type_label] => File
															[type_code] => file
															[ws_username] => SimpleXMLElement Object
																(
																)

															[ws_csv_url] => SimpleXMLElement Object
																(
																)

															[file_id] => 2
															[file_name] => 2012_US_elections_jpdecorps.csv
														)

													[2] => SimpleXMLElement Object
														(
															[id_provider] => 3
															[name] => electionwithspread2012
															[type_id] => 72
															[type_label] => File
															[type_code] => file
															[ws_username] => SimpleXMLElement Object
																(
																)

															[ws_csv_url] => SimpleXMLElement Object
																(
																)

															[file_id] => 3
															[file_name] => 2012_US_elect_results_county_levelplus spread(EuroFormat).csv
														)

												)

										)

								)

							[1] => SimpleXMLElement Object
								(
									[id_data] => 6
									[id_amap] => 6
									[name] => Démo Kévin
									[description] => SimpleXMLElement Object
										(
										)

									[tags] => SimpleXMLElement Object
										(
										)

									[providers] => SimpleXMLElement Object
										(
											[provider] => SimpleXMLElement Object
												(
													[id_provider] => 8
													[name] => esis
													[type_id] => 72
													[type_label] => File
													[type_code] => file
													[ws_username] => SimpleXMLElement Object
														(
														)

													[ws_csv_url] => SimpleXMLElement Object
														(
														)

													[file_id] => 8
													[file_name] => esis.css
												)

										)

								)

Core_Library_Statmod_Client

<?php
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * This is VOOZANOO, a program. Contact voozanoo@epiconcept.fr, or   *
 * see http://www.voozanoo.net/ for more information.				*
 *																   *
 * Copyright 2001-2010 Epiconcept									*
 *																   *
 * This program is free software; you can redistribute it and/or	 *
 * modify it under the terms of the GNU General Public License as	*
 * published by the Free Software Foundation - version 2			 *
 *																   *
 * This program is distributed in the hope that it will be useful,   *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of	*
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the	 *
 * GNU General Public License in file COPYING for more details.	  *
 *																   *
 * You should have received a copy of the GNU General Public		 *
 * License along with this program; if not, write to the Free		*
 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,	   *
 * Boston, MA 02111, USA.											*
 *																   *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

/**
 * Voozanoo library
 *
 * @package Statmod
 * @copyright Copyright (c) 2010 Epiconcept (http://www.epiconcept.fr)
 */

/**
 * Client for stats module
 */
class Core_Library_Statmod_Client extends Core_Library_Project_BaseObject
{
	/**
	 * Adresse du module de stats utilisée par défaut si aucune adresse n'est fournie
	 */
	const DEFAULT_MODSTAT_URL = 'https://stats.voozanoo.net';

	/**
	 *
	 * @param array $aOptions
	 * @return array
	 * @throws Core_Library_Exception_WebServiceError
	 */
	public function GetAmapList( array $aOptions = array() )
	{
		$oClient = $this->_retrieveClientFromOptions( $aOptions );
		$oResult = $oClient->get();

		if ( false === $oResult->isSuccess() ) {
			throw new Core_Library_Exception_WebServiceError( sprintf(
					'An error occured while calling webservice : %s ',
					$oResult->message
				)
			);
		}

		return $oResult->response->amap;
	}

	/**
	 *
	 * @param string $sUrl URL du module de stats (ex: https://stats.voozanoo.net).
	 * Par défaut: https://stats.voozanoo.net.
	 * L'adresse peut aussi être définie dans le fichier de conf de l'application,
	 * en mettant comme chemin: modstat.url
	 * Ex: modstat.url = "https://stats.preprod.voozanoo.net"
	 * @param string $sLogin Identifiant pour se connecter au module de stats.
	 * Peut être défini dans le fichier de conf de l'application: modstat.login
	 * @param string $sPassword Mot de passe sur le module de stats.
	 * Peut être défini dans le fichier de conf de l'application: modstat.password
	 * @return \Zend_Rest_Client
	 * @throws Core_Library_Exception
	 */
	public function GetRestClient( $sUrl = null, $sLogin = null, $sPassword = null )
	{
		if ( $sUrl == null ) {
			// Récupération de l'adresse du module de stats si non fournie.
			// Elle doit être déclarée dans le fichier de conf de l'application sous la forme:
			// modstat.url = "https://stats.preprod.voozanoo.net"
			// Valeur par défaut si non définie: https://stats.voozanoo.net
			$sUrl = Core_Library_Options::get( 'modstat.url', self::DEFAULT_MODSTAT_URL );
		}

		// Ajout dans l'url du nom du projet et du webservice
		$sUrl = rtrim( $sUrl, '/' ) . '/modulestats/ws/amap';

		// Récupération du login et du mot de passe si non fournis, ils doivent être
		// définis dans le fichier de conf de l'appli:
		// modstat.login = "foo"
		if ( $sLogin == null ) {
			$sLogin = Core_Library_Options::get( 'modstat.login' );
		}

		// modstat.password = "bar"
		if ( $sPassword == null ) {
			$sPassword = Core_Library_Options::get( 'modstat.password' );
		}

		// Ajout du login et du mot de passe dans l'adresse
		if ( false === preg_match( '#(https://|http://)(.*)#', $sUrl, $aMatches ) ) {
			throw new Core_Library_Exception( sprintf( "Can't parse url %s, preg match error", $sUrl ) );
		}

		if ( ! isset( $aMatches[ 1 ] ) || ! isset( $aMatches[ 2 ] ) ) {
			throw new Core_Library_Exception( sprintf( "Can't parse url %s", $sUrl ) );
		}

		$sUrl = sprintf( "%s%s:%s@%s", $aMatches[1], $sLogin, $sPassword, $aMatches[2] );

		return new Zend_Rest_Client( $sUrl );
	}

	/**
	 * Transfert le fichier par chunk au module de stats
	 * @param Zend_Rest_Client $oClient
	 * @param string $sFileFullPath Chemin vers le fichier à transférer. Il doit
	 * s'agit un fichier zip.
	 * @return string Token renvoyé par le module de stats
	 * @throws Core_Library_Exception_WebServiceError
	 */
	protected function _transferFile( Zend_Rest_Client $oClient, $sFileFullPath )
	{
		$oSplitter = new Core_Library_File_Splitter( array(
			'FileFullPath' => $sFileFullPath,
			'Base64Handling' => true
		) );

		$iChunkIndex = 1;
		$sFileNameOnStatMod = null;
		$sToken = null;

		while ( $iChunkIndex <= $oSplitter->GetTotalChunks() ) {

			if ( $iChunkIndex == $oSplitter->GetTotalChunks() ) {
				$oClient->last_chunk( true );
			}
			if ( $sFileNameOnStatMod != null ) {
				$oClient->id_chunk( $sFileNameOnStatMod );
			}
			if ( $sToken != null ) {
				$oClient->token( $sToken );
			}

			$oClient->data( $oSplitter->GetChunk( $iChunkIndex ) );
			$oClient->data_hash( $oSplitter->GetChunkHash() );
			$oClient->transfert_mode( 'chunk' );

			/* @var $oResult Zend_Rest_Client_Result */
			$oResult = $oClient->post();
			if ( false === $oResult->isSuccess() ) {
				throw new Core_Library_Exception_WebServiceError( sprintf(
					  'An error occured while calling webservice : %s ', $oResult->message
				));
			}
			$sFileNameOnStatMod = $oResult->response->id_chunk;

			if ( isset( $oResult->response->token ) ) {
				$sToken = (string) $oResult->response->token;
			}

			$iChunkIndex++;
		}

		return $sToken;
	}

	/**
	 * Renvoi le client en fonction du contenu de $aOptions
	 * @param array $aOptions
	 * @return Zend_Rest_Client
	 */
	protected function _retrieveClientFromOptions( array $aOptions )
	{
		if ( isset( $aOptions[ 'client' ] ) ) {
			$oClient = $aOptions[ 'client' ];
		} else {
			$oClient = $this->GetRestClient(
				( isset( $aOptions[ 'url' ] ) ? $aOptions[ 'url' ] : null ),
				( isset( $aOptions[ 'login' ] ) ? $aOptions[ 'login' ] : null ),
				( isset( $aOptions[ 'password' ] ) ? $aOptions[ 'password' ] : null )
			);
		}

		return $oClient;
	}

	/**
	 * Execute un plan d'analyse sur le module de stats
	 *
	 * @param array $aOptions
	 * <ul>
	 *	<li>'id_amap' => string Identifiant du plan d'analyse (Obligatoire)</li>
	 *	  <li>'params' => array Paramètres à envoyer </li>
	 *	  <li>'file' => string Fichier de données, chemin complet, doit être un zip</li>
	 *	  <li>Pour échanger avec le module de stats, soit une instance du client:<br>
	 *		'client' => Zend_Rest_Client Le client
	 *	  </li>
	 *	<li>Soit les paramètres de connexion:<br>
	 *		  'url' => string Adresse du module de stats<br>
	 *		'login' => string Login<br>
	 *		'password' => string Mot de passe
	 *	  </li>
	 *	  <li>Soit définir les paramètres de connexion dans le fichier de conf:<br>
	 *		  modstat.url<br>
	 *		modstat.login<br>
	 *		modstat.password<br>
	 *	</li>
	 * </ul>
	 * @return \Core_library_Statmod_Response
	 * @throws InvalidArgumentException
	 * @throws Core_Library_Exception_WebServiceError
	 */
	public function Execute( array $aOptions )
	{
		// Récupération de l'identfiant du plan d'analyse (obligatoire)
		if ( ! isset( $aOptions[ 'id_amap' ] ) ) {
			throw new InvalidArgumentException( 'id_amap required' );
		}

		$iIdAmap = (int) $aOptions[ 'id_amap' ];

		// Récupération des paramètres
		if ( isset( $aOptions[ 'params' ] ) ) {
			if ( ! is_array( $aOptions[ 'params' ] ) ) {
				throw new InvalidArgumentException( 'params option bad format, expected array' );
			}
			$aParams = $aOptions[ 'params' ];
		} else {
			$aParams = array();
		}

		// Récupération du client
		$oClient = $this->_retrieveClientFromOptions( $aOptions );

		$oClient->id( $iIdAmap );
		if ( count( $aParams ) ) {
			$oClient->params( Zend_Json::encode( $aParams ) );
		}

		// S'il y a un fichier dans les options, il est envoyé au module de stats
		// par chunk (le fichier doit être un zip).
		if ( isset( $aOptions[ 'file' ] ) ) {
			if ( ! file_exists( $aOptions[ 'file' ] ) ) {
				throw new Core_Library_Exception_FileNotFound( sprintf( 'File %s not found', $aOptions[ 'file' ] ) );
			}
			$sToken = $this->_transferFile( $oClient, $aOptions[ 'file' ] );
		} else {
			// Lancement du plan d'analyse
			$oResult = $oClient->post();
			if ( false === $oResult->isSuccess() ) {
				throw new Core_Library_Exception_WebServiceError(
					sprintf( 'An error occured while calling webservice : %s ', $oResult->message )
				);
			}
			$sToken = (string) $oResult->response->token;
		}

		$oClient->id( $iIdAmap );
		$oClient->token( $sToken );

		// Récupération du statut de l'exécution
		$oResult = $oClient->get();
		if ( false === $oResult->isSuccess() ) {
			throw new Core_Library_Exception_WebServiceError(
				sprintf( 'An error occured while calling webservice : %s ', $oResult->message )
			);
		}

		return $this->_prepareReponse( $iIdAmap, $oClient, $oResult, $sToken );
	}

	/**
	 * Récupération du statut de l'exécution
	 *
	 * @param array $aOptions
	 * <ul>
	 *	<li>'id_amap' => string Identifiant du plan d'analyse (Obligatoire)</li>
	 *	  <li>'token' => string Token renvoyé par le module de stats à l'exécution</li>
	 *	  <li>Pour échanger avec le module de stats, soit une instance du client:<br>
	 *		'client' => Zend_Rest_Client Le client
	 *	  </li>
	 *	<li>Soit les paramètres de connexion:<br>
	 *		  'url' => string Adresse du module de stats<br>
	 *		'login' => string Login<br>
	 *		'password' => string Mot de passe
	 *	  </li>
	 *	  <li>Soit définir les paramètres de connexion dans le fichier de conf:<br>
	 *		  modstat.url<br>
	 *		modstat.login<br>
	 *		modstat.password<br>
	 *	</li>
	 *	<li>
	 *		  OU<br>
	 *		  'response' => Core_library_Statmod_Response Renvoyé par Execute
	 *	 </li>
	 * </ul>
	 * @return \Core_library_Statmod_Response
	 * @throws InvalidArgumentException
	 * @throws Core_Library_Exception_WebServiceError
	 */
	public function getExecutionStatus( array $aOptions )
	{
		if ( isset( $aOptions[ 'response' ] ) ) {
			/* @var $oResponse Core_library_Statmod_Response */
			$oResponse = $aOptions[ 'response' ];
			$iIdAmap = $oResponse->GetIdAmap();
			$sToken = $oResponse->GetToken();
			$oClient = $oResponse->GetClient();

		} else {
			// Récupération de l'identfiant du plan d'analyse (obligatoire)
			if ( ! isset( $aOptions[ 'id_amap' ] ) ) {
				throw new InvalidArgumentException( 'id_amap required' );
			}

			$iIdAmap = (int) $aOptions[ 'id_amap' ];

			// Récupération du token (obligatoire)
			if ( ! isset( $aOptions[ 'token' ] ) ) {
				throw new InvalidArgumentException( 'token required' );
			}

			$sToken = (string) $aOptions[ 'token' ];

			// Récupération du client
			$oClient = $this->_retrieveClientFromOptions( $aOptions );
		}

		$oClient->id( $iIdAmap );
		$oClient->token( $sToken );

		$oResult = $oClient->get();

		if ( false == $oResult->isSuccess() ) {
			throw new Core_Library_Exception_WebServiceError( sprintf(
				 'An error occured while calling webservice : %s ', $oResult->message
			) );
		}

		return $this->_prepareReponse( $iIdAmap, $oClient, $oResult, $sToken );
	}

	/**
	 * Retourne une instance de Core_Library_Statmod_Response construit à partir
	 * de la réponse du webservice
	 *
	 * @param integer $iIdAmap
	 * @param Zend_Rest_Client $oClient
	 * @param type $oResult
	 * @param string $sToken
	 * @return \Core_Library_Statmod_Response
	 */
	protected function _prepareReponse( $iIdAmap, $oClient, $oResult, $sToken )
	{
		$oResponse = new Core_Library_Statmod_Response( array(
			'id_amap' => (int) $iIdAmap,
			'state' => (string) $oResult->response->state,
			'client' => $oClient,
			'token' => $sToken
		));

		if ( $sToken ) {
			$oResponse->SetToken( $sToken );
		}

		if ( $this->GetProject() ) {
			$oResponse->SetProject( $this->GetProject() );
		}

		if ( isset( $oResult->response->json ) ) {
			$oResponse->SetResult( (string) $oResult->response->json );
			$oResponse->SetResultType( Core_library_Statmod_Response::RESULT_TYPE_JSON );
		} else if ( isset( $oResult->response->html ) ) {
			$oResponse->SetResult( (string) $oResult->response->html );
			$oResponse->SetResultType( Core_library_Statmod_Response::RESULT_TYPE_HTML );
		} else {
			throw new Core_Library_Exception( 'Result not found in response' );
		}

		return $oResponse;
	}
}

Core_library_Statmod_Response

<?php
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * This is VOOZANOO, a program. Contact voozanoo@epiconcept.fr, or   *
 * see http://www.voozanoo.net/ for more information.				*
 *																   *
 * Copyright 2001-2010 Epiconcept									*
 *																   *
 * This program is free software; you can redistribute it and/or	 *
 * modify it under the terms of the GNU General Public License as	*
 * published by the Free Software Foundation - version 2			 *
 *																   *
 * This program is distributed in the hope that it will be useful,   *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of	*
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the	 *
 * GNU General Public License in file COPYING for more details.	  *
 *																   *
 * You should have received a copy of the GNU General Public		 *
 * License along with this program; if not, write to the Free		*
 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,	   *
 * Boston, MA 02111, USA.											*
 *																   *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

/**
 * Voozanoo library
 *
 * @package Statmod
 * @copyright Copyright (c) 2010 Epiconcept (http://www.epiconcept.fr)
 */

/**
 * Client for stats module
 */
class Core_library_Statmod_Response extends Core_Library_Project_BaseObject
{
	/**
	 * Plan d'analyse en cours d'initialisation
	 */
	const	STATE_INITIALIZING = 'initializing';

	/**
	 * Plan d'analyse en cours d'exécution
	 */
	const	STATE_ONIDLE = 'onidle';

	/**
	 * L'exécution du plan d'analyse a échoué
	 */
	const	STATE_FAIL = 'fail';

	/**
	 * Le plan d'analyse a été exécuté, le résultat est disponible
	 */
	const	STATE_READY = 'ready';

	/**
	 * Le plan d'analyse a été exécuté, le résultat est disponible
	 */
	const	STATE_SUCCESS = 'success';

	/**
	 * Result is JSON
	 */
	const	RESULT_TYPE_JSON = 'json';

	/**
	 * Result is HTML
	 */
	const	RESULT_TYPE_HTML = 'html';

	/**
	 * Identifiant du plan d'analyse
	 * @var integer
	 */
	protected $_iIdAmap;

	/**
	 * Token retourné par le module de stats pour suivre la progression
	 * de l'exécution du plan d'analyse
	 * @var string
	 */
	protected $_sToken;

	/**
	 * Statut de l'exécution du plan (@see const STATE_*)
	 * @var string
	 */
	protected $_sState;

	/**
	 * Progression de l'exécution
	 * @var integer
	 */
	protected $_iPercent;

	/**
	 * Client utilisé pour communiquer avec le module de stats, à l'origine de
	 * la réponse
	 * @var Zend_Rest_Client
	 */
	protected $_oRestClient;

	/**
	 * Résultat du plan d'analyse, HTML, ou JSON (sous forme de string)
	 * @var string
	 */
	protected $_sResult;

	/**
	 * Type du résultat, json ou html.
	 * @var string
	 */
	protected $_sResultType;

	/**
	 * Indique si la réponse contient un résultat
	 * @return boolean
	 */
	public function IsResult()
	{
		return ( strlen( $this->_sResult ) > 0 );
	}

	/**
	 * Result type setter @see constants self::RESULT_TYPE_*
	 * @param string $sType
	 */
	public function SetResultType( $sType )
	{
		if ( $sType != self::RESULT_TYPE_HTML && $sType != self::RESULT_TYPE_JSON ) {
			throw new Core_Library_Exception( 'Unknow type ' . $sType );
		}
		$this->_sResultType = $sType;
	}

	/**
	 * Result type getter
	 * @return string
	 */
	public function GetResultType()
	{
		return $this->_sResultType;
	}

	/**
	 * Id amap setter
	 * @param integer $iIdAmap
	 */
	public function SetIdAmap( $iIdAmap )
	{
		$this->_iIdAmap = (int) $iIdAmap;
	}

	/**
	 * Id amap getter
	 * @return integer
	 */
	public function GetIdAmap()
	{
		return $this->_iIdAmap;
	}

	/**
	 * Token setter
	 * @param string $sToken
	 */
	public function SetToken( $sToken )
	{
		$this->_sToken = (string) $sToken;
	}

	/**
	 * Token getter
	 * @return string
	 */
	public function GetToken()
	{
		return $this->_sToken;
	}

	/**
	 * State setter
	 * @param string $sState
	 */
	public function SetState( $sState )
	{
		$aExpectedState = array(
			self::STATE_FAIL,
			self::STATE_INITIALIZING,
			self::STATE_ONIDLE,
			self::STATE_READY,
			self::STATE_SUCCESS
		);

		if ( ! in_array( $sState, $aExpectedState ) ) {
			throw new Core_Library_Exception( sprintf(
				'Invalid state (%s), expected state: %s', $sState, implode( ',', $aExpectedState)
			) );
		}
		$this->_sState = (string) $sState;
	}

	/**
	 * State getter
	 * @return string
	 */
	public function GetState()
	{
		return $this->_sState;
	}

	/**
	 * Result setter
	 * @param string $sResult
	 */
	public function SetResult( $sResult )
	{
		$sResult = trim( $sResult );

		if ( ! strlen( $sResult ) ) {
			return;
		}
		$this->_sResult = $sResult;
	}

	/**
	 * Strip new lines in string
	 * @param string $sValue
	 * @return string
	 */
	protected function _stripNewLines( $sValue )
	{
		return str_replace( array( "\n",  "\r" ), array( "\\n", "\\r" ), $sValue );
	}


	/**
	 * Result getter
	 * @param boolean $bStripNewLines
	 * @return string
	 */
	public function GetResult( $bStripNewLines = false)
	{
		if ( $bStripNewLines ) {
			return $this->_stripNewLines( $this->_sResult );
		}
		return $this->_sResult;
	}

	/**
	 * Client setter
	 * @param Zend_Rest_Client $oClient
	 */
	public function SetClient( Zend_Rest_Client $oClient )
	{
		$this->_oRestClient = $oClient;
	}

	/**
	 * Client getter
	 * @return Zend_Rest_Client
	 */
	public function GetClient()
	{
		return $this->_oRestClient;
	}

	/**
	 * Percent setter
	 * @param integer $iPercent
	 */
	public function SetPercent( $iPercent )
	{
		$this->_iPercent = (int) $iPercent;
	}

	/**
	 * Percent getter
	 * @return integer
	 */
	public function GetPercent()
	{
		return $this->_iPercent;
	}
}