function services_method_call in Services 5
Same name and namespace in other branches
- 6 services.module \services_method_call()
- 6.2 services.module \services_method_call()
- 7 services.module \services_method_call()
This is the magic function through which all remote method calls must pass.
2 calls to services_method_call()
- services_admin_browse_test_submit in ./services_admin_browse.inc 
- xmlrpc_server_call_wrapper in servers/xmlrpc_server/ xmlrpc_server.module 
File
- ./services.module, line 339 
- The module which provides the core code for drupal services
Code
function services_method_call($method_name, $args = array(), $ignore_hash = FALSE) {
  $method = services_method_get($method_name);
  // Check that method exists.
  if (empty($method)) {
    return services_error(t('Method %name does not exist.', array(
      '%name' => $method_name,
    )));
  }
  // Check for missing args and identify if arg is required in the hash.
  $hash_parameters = array();
  foreach ($method['#args'] as $key => $arg) {
    if (!$arg['#optional']) {
      if (!isset($args[$key]) && !is_array($args[$key]) && !is_bool($args[$key])) {
        if ($arg['#name'] == 'sessid' && session_id()) {
          $args[$key] = session_id();
        }
        else {
          return services_error(t('Missing required arguments.'));
        }
      }
    }
    // Key is part of the hash
    if ($arg['#signed'] == TRUE && variable_get('services_use_key', TRUE)) {
      if (is_numeric($args[$key]) || !empty($args[$key])) {
        if (is_array($args[$key]) || is_object($args[$key])) {
          $hash_parameters[] = serialize($args[$key]);
        }
        else {
          $hash_parameters[] = $args[$key];
        }
      }
      else {
        $hash_parameters[] = '';
      }
    }
  }
  // Add additonal processing for methods requiring api key.
  if ($method['#key'] && variable_get('services_use_key', TRUE)) {
    $hash = array_shift($args);
    $domain = array_shift($args);
    $timestamp = array_shift($args);
    $nonce = array_shift($args);
    $expiry_time = $timestamp + variable_get('services_key_expiry', 30);
    if ($expiry_time < time()) {
      return services_error(t('Token has expired.'));
    }
    // Still in time but has it been used before
    if (db_result(db_query("SELECT count(*) FROM {services_timestamp_nonce} WHERE domain = '%s' AND timestamp = %d AND nonce = '%s'", $domain, $timestamp, $nonce))) {
      return services_error(t('Token has been used previously for a request.'));
    }
    else {
      db_query("INSERT INTO {services_timestamp_nonce} (domain, timestamp, nonce) VALUES ('%s', %d, '%s')", $domain, $timestamp, $nonce);
    }
    $api_key = db_result(db_query("SELECT kid FROM {services_keys} WHERE domain = '%s'", $domain));
    if (!services_validate_key($api_key, $timestamp, $domain, $nonce, $method_name, $hash_parameters, $hash)) {
      return services_error(t('Invalid API key.'));
    }
  }
  // Add additonal processing for methods requiring authentication.
  $session_backup = NULL;
  if ($method['#auth'] && variable_get('services_use_sessid', TRUE)) {
    $sessid = array_shift($args);
    if (empty($sessid)) {
      return services_error(t('Invalid sessid.'));
    }
    $session_backup = services_session_load($sessid);
  }
  // Check access
  $access_arguments = isset($method['#access arguments']) ? $method['#access arguments'] : $args;
  // Call default or custom access callback
  if (call_user_func_array($method['#access callback'], $access_arguments) != TRUE) {
    return services_error(t('Access denied.'));
  }
  // Change working directory to drupal root to call drupal function,
  // then change it back to server module root to handle return.
  $server_root = getcwd();
  $server_info = services_get_server_info();
  if ($server_info) {
    chdir($server_info->drupal_path);
  }
  $result = call_user_func_array($method['#callback'], $args);
  if ($server_info) {
    chdir($server_root);
  }
  // Add additonal processing for methods requiring authentication.
  if ($session_backup !== NULL) {
    services_session_unload($session_backup);
  }
  return $result;
}