function return_wsdl($source_object, $user_id = 0)
    {
        global $charset;
        global $declared_types;
        global $type_aliases;
        $cache_ref = "api_soap_wsdl_" . $source_object->id;
        if ($source_object->connector->config["cache_wsdl"]) {
            //Voyons si on peut trouver quelque chose de pas trop vieux dans le cache
            $es_cache = new external_services_cache('es_cache_blob', 3600);
            $cached_result = $es_cache->decache_single_object($cache_ref, CACHE_TYPE_MISC);
            if ($cached_result !== false) {
                //Il est bon? On l'envoi
                if (!isset($_GET["nx"])) {
                    header('Content-Type: text/xml');
                }
                print $cached_result;
                exit;
            }
        }
        //Récupérons la liste des fonctions que l'on doit exporter
        $api_catalog = new es_catalog();
        $api_es = new external_services();
        //$api_rights = new external_services_rights($api_es);
        $final_method_list = array();
        foreach ($source_object->config["exported_functions"] as $amethod) {
            //		if ($api_rights->has_rights($user_id, $amethod["group"], $amethod["name"])) {
            $final_method_list[] = $amethod;
            //		}
        }
        //Les entêtes du fichier
        $wsdl_headers = '<?xml version="1.0" encoding="UTF-8"?>
		<?xml-stylesheet type="text/xsl" href="connecteurs/out/apisoap/wsdl-viewer.xsl"?>
		<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://sigb.net/pmb/es/apisoap" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="PMBSOAPAPI" targetNamespace="http://sigb.net/pmb/es/apisoap">';
        //Les entêtes des déclaration de type
        $wsdl_types = '<wsdl:types>
		    <xsd:schema targetNamespace="http://sigb.net/pmb/es/apisoap" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">
		    	<xsd:import namespace="http://schemas.xmlsoap.org/soap/encoding/"/>';
        //On va construire la liste des types à déclarer en fonction de ce que l'on va rencontrer, puis on y reviendra
        $additional_definitions = array();
        $declared_types = array();
        $type_aliases = array();
        //Ajoutons les types du manifest s'il y en a
        $handled_groups = array();
        foreach ($final_method_list as $amethod) {
            //Vérifions si on a pas déjà traité les types de ce groupe
            if (isset($handled_groups[$amethod["group"]])) {
                continue;
            }
            //Ajoutons les types du groupe de la methode courante
            foreach ($api_catalog->groups[$amethod["group"]]->types as &$atype) {
                if ($atype->imported) {
                    $base_name = $api_catalog->groups[$atype->imported_from]->name . '_' . $atype->name;
                    $local_base_name = $api_catalog->groups[$amethod["group"]]->methods[$amethod["name"]]->group . '_' . $atype->name;
                    if (isset($declared_types[$base_name])) {
                        if (!isset($type_aliases[$local_base_name])) {
                            $type_aliases[$local_base_name] = $base_name;
                        }
                        continue;
                    }
                    $this->type_to_wsdl($api_catalog->groups[$atype->imported_from]->types[$atype->name], $base_name, $atype->imported_from, $additional_definitions, "element");
                    $type_aliases[$local_base_name] = $base_name;
                } else {
                    $base_name = $api_catalog->groups[$amethod["group"]]->methods[$amethod["name"]]->group . '_' . $atype->name;
                    if (isset($declared_types[$base_name])) {
                        continue;
                    }
                    $this->type_to_wsdl($atype, $base_name, $amethod["group"], $additional_definitions, "element");
                }
                $declared_types[$base_name] = true;
            }
            $handled_groups[$amethod["group"]] = true;
        }
        //Construction des messages
        $wsdl_messages = "";
        foreach ($final_method_list as $amethod) {
            $method_name = $api_catalog->groups[$amethod["group"]]->methods[$amethod["name"]]->group . '_' . $api_catalog->groups[$amethod["group"]]->methods[$amethod["name"]]->name;
            $wsdl_messages .= '<wsdl:message name="' . XMLEntities($method_name) . 'Request">';
            foreach ($api_catalog->groups[$amethod["group"]]->methods[$amethod["name"]]->inputs as $ainput) {
                $wsdl_messages .= $this->input_to_wsdl($ainput, $method_name, $amethod["group"], $additional_definitions, "part");
            }
            $wsdl_messages .= '</wsdl:message>';
            $wsdl_messages .= '<wsdl:message name="' . XMLEntities($method_name) . 'Response">';
            $output_count = count($api_catalog->groups[$amethod["group"]]->methods[$amethod["name"]]->outputs);
            if ($output_count > 1) {
                $additional_definition = "";
                $additional_definition .= '<xsd:complexType name="' . XMLEntities($method_name) . 'ResponseStruct">';
                $additional_definition .= '<xsd:sequence>';
                foreach ($api_catalog->groups[$amethod["group"]]->methods[$amethod["name"]]->outputs as $ainput) {
                    $additional_definition .= $this->output_to_wsdl($ainput, $method_name, $amethod["group"], $additional_definitions, "element");
                }
                $additional_definition .= '</xsd:sequence>';
                $additional_definition .= '</xsd:complexType>';
                $additional_definitions[XMLEntities($method_name) . 'ResponseStruct'] = $additional_definition;
                $wsdl_messages .= '<wsdl:part name="result" type="tns:' . XMLEntities($method_name) . 'ResponseStruct"/>';
            } else {
                if ($output_count) {
                    $wsdl_messages .= $this->output_to_wsdl($api_catalog->groups[$amethod["group"]]->methods[$amethod["name"]]->outputs[0], $method_name, $amethod["group"], $additional_definitions, "part");
                }
            }
            $wsdl_messages .= '</wsdl:message>';
        }
        //On a maintenant les types, on fini de construire le bloc associé
        $wsdl_types .= implode("", $additional_definitions);
        $wsdl_types .= '</xsd:schema>
		     	</wsdl:types>';
        //PortType
        $wsdl_porttype = "";
        $wsdl_porttype .= '<wsdl:portType name="PMBSOAPAPI">';
        foreach ($final_method_list as $amethod) {
            $method_name = $api_catalog->groups[$amethod["group"]]->methods[$amethod["name"]]->group . '_' . $api_catalog->groups[$amethod["group"]]->methods[$amethod["name"]]->name;
            $method_group = $amethod["group"];
            $method_description = $api_catalog->groups[$amethod["group"]]->methods[$amethod["name"]]->description;
            $input_description = $api_catalog->groups[$amethod["group"]]->methods[$amethod["name"]]->input_description;
            $output_description = $api_catalog->groups[$amethod["group"]]->methods[$amethod["name"]]->output_description;
            $wsdl_porttype .= '
			       <wsdl:operation name="' . XMLEntities($method_name) . '">
	                 <wsdl:documentation>' . XMLEntities($api_es->get_text($method_description, $method_group)) . '</wsdl:documentation>
			         <wsdl:input message="tns:' . XMLEntities($method_name) . 'Request">
			           <wsdl:documentation>' . XMLEntities($api_es->get_text($input_description, $method_group)) . '</wsdl:documentation>
			         </wsdl:input>
			         <wsdl:output message="tns:' . XMLEntities($method_name) . 'Response">
			           <wsdl:documentation>' . XMLEntities($api_es->get_text($output_description, $method_group)) . '</wsdl:documentation>
			         </wsdl:output>
			       </wsdl:operation>';
        }
        $wsdl_porttype .= '</wsdl:portType>';
        //Binding
        $wsdl_binding = "";
        $wsdl_binding .= '<wsdl:binding name="PMBSOAPAPI_Binding" type="tns:PMBSOAPAPI">
			    <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>';
        foreach ($final_method_list as $amethod) {
            $method_name = $api_catalog->groups[$amethod["group"]]->methods[$amethod["name"]]->group . '_' . $api_catalog->groups[$amethod["group"]]->methods[$amethod["name"]]->name;
            $wsdl_binding .= '
				   <wsdl:operation name="' . XMLEntities($method_name) . '">
				      <soap:operation soapAction="http://sigb.net/pmb/es/apisoap/' . XMLEntities($method_name) . '" style="rpc"/>
				      <wsdl:input>
 			            <soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" use="encoded" />
  				      </wsdl:input>
				      <wsdl:output>
				        <soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" use="encoded" />
				      </wsdl:output>
				   </wsdl:operation>';
        }
        $wsdl_binding .= '</wsdl:binding>';
        //Service
        $server_location = serverURL();
        $wsdl_service = "";
        $wsdl_service .= '
	  <wsdl:service name="PMBSOAPAPI">
	    <wsdl:port binding="tns:PMBSOAPAPI_Binding" name="PMBSOAPAPI">
	      <soap:address location="' . XMLEntities($server_location) . '"/>
	    </wsdl:port>
	  </wsdl:service>';
        $wsdl_footer = '</wsdl:definitions>';
        //On conbine le tout pour donner le wsdl final
        $wsdl = $wsdl_headers . $wsdl_types . $wsdl_messages . $wsdl_porttype . $wsdl_binding . $wsdl_service . $wsdl_footer;
        if ($charset != 'utf-8') {
            $wsdl = utf8_encode($wsdl);
        }
        //On le met en cache si on le souhaite
        if ($source_object->connector->config["cache_wsdl"]) {
            $es_cache = new external_services_cache('es_cache_blob', 600);
            $es_cache->encache_single_object($cache_ref, CACHE_TYPE_MISC, $wsdl);
        }
        //Et on l'envoi
        if (!isset($_GET["nx"])) {
            header('Content-Type: text/xml');
        }
        print $wsdl;
        exit;
    }