Actually I m working with the D7 version with all http://drupal.org/node/1129282#comment-4605446 but I could select it. (perhaps a dev release would be nice.)
Anyway I believe it should be possible for module to override the controller.
Normaly a drupal webservice is [module].[method_name] but we want the service for example to understand getEvents directly so we could implement a hook that allows that. That way we can create the proper name like defined in hook_services_resources and call it directly. (This is what happend when a premade wsdl without knowing about drupal has to be implemented.)
Example:
This is a hook_services_resources()
function ao_service_services_resources() {
return array(
'ao_service' => array(
'getEvents' => array(
'file' => array('type' => 'inc', 'module' => 'ao_service', 'name' => 'resources/ao_service.resource'),
'help' => t('This method returns a list of events.'),
'access callback' => 'ao_service_get_events_access',
'callback' => 'ao_service_get_events',
'args' => array(
array(
'name' => 'date',
'type' => 'string',
'description' => t('date.'),
'source' => 'data',
'optional' => FALSE,
),
),
),
),
);
}
We can add the check in class ServicesSoapServer
class ServicesSoapServer {
public function __call($method_name, $args) {
// Handle the request.
$info = services_server_info_object();
$endpoint = services_endpoint_load($info->endpoint);
//Invoke the hook to override the controller
$controller_overrides = module_invoke_all('soap_server_controller', $method_name, $endpoint->name);
if (empty($controller_overrides) && !$args['prevent_override']) {
$services_method_name = str_replace('_soap_', '.', $method_name);
$controller = services_controller_get($services_method_name, $endpoint->name);
}
else {
$controller = services_controller_get(array_shift($controller_overrides));
}
// make sure any arguments not passed have default values inserted if they are supplied
// TODO: should we be validating argument types here?
foreach ($controller['args'] as $key => $arg_config) {
if (!isset($args[$key]) && isset($arg_config['default value'])) {
$args[$key] = $arg_config['default value'];
}
}
if ($endpoint->debug) {
watchdog('soap server', "METHOD_NAME:<pre>". print_r($method_name, TRUE)."</pre");
watchdog('soap server', "ENDPOINT:<pre>". print_r($endpoint, TRUE)."</pre");
watchdog('soap server', "ARGS:<pre>". print_r($args, TRUE)."</pre");
watchdog('soap server', "CONTROLLER:<pre>". print_r($controller, TRUE)."</pre");
}
try {
$ret = services_controller_execute($controller, $args);
}
catch (Exception $e) {
$code = $e->getCode();
$soap_fault = new SoapFault($e->getMessage(), $code);
watchdog('soap_server', $e->getMessage(), 'error');
throw $soap_fault;
}
return $ret;
}
}
We implment the hook soap_servcer_controller to override
function ao_service_soap_server_controller($method_name, $endpoint) {
if ($method_name == 'getEvents' && $endpoint == 'soap_server') {
return 'ao_service.getEvents';
}
}
Now this will work (using wsclient module to operate the client)
$service = wsclient_service_load('ao');
$out = $service->invoke('getEvents', array());
You could still tell drupal not to listen to the override if needed, so the normal way can still work.
$service = wsclient_service_load('ao');
$args['prevent_override'] = true;
$out = $service->invoke('ao_service.getEvents', true);
I didnt roll a patch because this is allready code that is patch 17 times (http://drupal.org/node/1129282#comment-4605446) I hope I m making sense and the possibility is added to the module.
Comments
Comment #1
marcus_clements commentedSounds like a good idea - are you using this system in a working site?
Please roll a patch against 7.x-3.x dev if you have time.