You are here

class clients_connection_drupal_services_6_2 in Web Service Clients 7

Same name and namespace in other branches
  1. 6.2 connections/clients_drupal/clients_drupal.inc \clients_connection_drupal_services_6_2
  2. 7.3 connections/clients_drupal/clients_drupal.inc \clients_connection_drupal_services_6_2
  3. 7.2 connections/clients_drupal/clients_drupal.inc \clients_connection_drupal_services_6_2

Drupal client for services on a Drupal 6 site for Services 6.x-2.x.

Developed against Services 6.x-2.4.

Hierarchy

Expanded class hierarchy of clients_connection_drupal_services_6_2

File

backends/clients_drupal/clients_drupal.inc, line 368
Defines methods and calls to Drupal services

View source
class clients_connection_drupal_services_6_2 extends clients_connection_drupal_services {

  /**
   * Call a remote method.
   *
   * @param $method
   *  The name of the remote method to call.
   * @param
   *  All other parameters are passed to the remote method.
   *
   * @return
   *  Whatever is returned from the remote site.
   */
  function callMethod($method) {

    // If HTTP requests are enabled, report the error and do nothing.
    // (Cribbed from Content distribution module.)
    if (variable_get('drupal_http_request_fails', FALSE) == TRUE) {
      drupal_set_message(t('Drupal is unable to make HTTP requests. Please reset the HTTP request status.'), 'error', FALSE);
      watchdog('integration', 'Drupal is unable to make HTTP requests. Please reset the HTTP request status.', array(), WATCHDOG_CRITICAL);
      return;
    }
    $config = $this->configuration;
    $endpoint = $this->endpoint;
    $api_key = $this->configuration['servicekey'];

    // Connect to the remote system service to get an initial session id to log in with.
    $connect = xmlrpc($this->endpoint, 'system.connect');
    $session_id = $connect['sessid'];

    // We may want to call only system.connect for testing purposes.
    if ($method == 'system.connect') {
      return $connect;
    }

    // Log in
    // Get the API key-related arguments.
    $key_args = $this
      ->xmlrpc_key_args('user.login');

    //dsm($key_args);

    // Build the array of connection arguments we need to log in.
    $username = $this->configuration['username'];
    $password = $this->configuration['password'];
    $login_args = array_merge(array(
      $this->endpoint,
      'user.login',
    ), $key_args, array(
      $session_id,
    ), array(
      $username,
      $password,
    ));

    // Call the xmlrpc method with our array of arguments. This accounts for
    // whether we use a key or not, and the extra parameters to pass to the method.
    $login = call_user_func_array('xmlrpc', $login_args);
    $login_session_id = $login['sessid'];

    // If the requested method is user.login, we're done.
    if ($method == 'user.login') {
      return $login;
    }

    // Get all the arguments this function has been passed.
    $function_args = func_get_args();

    // Slice out the ones that are arguments to the method call: everything past
    // the 1st argument.
    $method_args = array_slice($function_args, 1);

    // Get the API key-related arguments.
    $key_args = $this
      ->xmlrpc_key_args($method);

    // Build the array of connection arguments for the method we want to call.
    $xmlrpc_args = array_merge(array(
      $this->endpoint,
      $method,
    ), $key_args, array(
      $login_session_id,
    ), $method_args);

    // Call the xmlrpc method with our array of arguments.
    $result = call_user_func_array('xmlrpc', $xmlrpc_args);
    if ($result === FALSE) {

      //dsm('error');
      return xmlrpc_error();
    }
    return $result;
  }

  /**
   * Helper function to get key-related method arguments for the XMLRPC call.
   *
   * TODO: merge with getToken.
   */
  function xmlrpc_key_args($method) {
    $api_key = $this->configuration['servicekey'];

    // Build the API key arguments - if no key supplied supplied, presume not required
    if ($api_key != '') {

      //use api key to get a hash code for the service.
      $timestamp = (string) strtotime("now");

      // Note that the domain -- at least for Services 5 and 6.x-2.x -- is a
      // purely arbitrary string more akin to a username.
      // See http://drupal.org/node/821700 for background.
      $domain = $this->configuration['domain'];

      /*
      if (!strlen($domain)) {
        $domain = $_SERVER['SERVER_NAME'];
        if ($_SERVER['SERVER_PORT'] != 80) {
          $domain .= ':' . $_SERVER['SERVER_PORT'];
        }
      }
      */
      $nonce = uniqid();
      $hash_parameters = array(
        $timestamp,
        $domain,
        $nonce,
        $method,
      );
      $hash = hash_hmac("sha256", implode(';', $hash_parameters), $api_key);
      $key_args = array(
        $hash,
        $domain,
        $timestamp,
        $nonce,
      );
    }
    else {
      $key_args = array();
    }
    return $key_args;
  }

  /**
   * Provide buttons for the connection testing page.
   *
   * @param $form_state
   *  This is passed in so you can set defaults based on user input.
   */
  function getTestOperations($form_state, $cid) {
    $buttons['connect'] = array(
      '#value' => 'Test connection',
      '#type' => 'submit',
      //'#name' => 'connect', // wtf does this do?
      '#action_type' => 'method',
      '#action_submit' => 'testConnectionConnect',
      '#description' => t('Test the connection settings by calling system.connect on the remote server.'),
    );
    $buttons['login'] = array(
      '#value' => 'Test user login',
      '#type' => 'submit',
      //'#name' => 'login',
      '#action_type' => 'method',
      '#action_submit' => 'testConnectionLogin',
      '#description' => t('Test the remote user settings and by calling user.login on the remote server.'),
    );
    $buttons['node_load'] = array(
      '#type' => 'fieldset',
    );
    $buttons['node_load']['nid'] = array(
      '#type' => 'textfield',
      '#title' => 'Node ID',
      '#size' => 6,
      '#default_value' => isset($form_state['values']['buttons']['node_load']['nid']) ? $form_state['values']['buttons']['node_load']['nid'] : NULL,
    );
    $buttons['node_load']['button'] = array(
      '#value' => 'Test node retrieval',
      '#type' => 'submit',
      //'#name' => 'login',

      // TODO: tidy up these method names!
      '#action_type' => 'method',
      '#action_submit' => 'testConnectionNodeLoad',
      '#action_validate' => 'testConnectionNodeLoadValidate',
      '#description' => t('Attempt to load a remote node.'),
    );
    return $buttons;
  }

  /**
   * Connection test button handler: basic connection.
   *
   * Connection test handlers should return the raw data they got back from the
   * connection for display to the user.
   */
  function testConnectionConnect(&$button_form_values) {

    // Call the connect method.
    $connect = $this
      ->callMethod('system.connect');
    if (is_array($connect) && isset($connect['user'])) {
      drupal_set_message(t('Sucessfully connected to the remote site.'));
    }
    else {
      drupal_set_message(t('Could not connect to the remote site.'), 'warning');
    }
    return $connect;
  }

  /**
   * Connection test button handler: user login.
   */
  function testConnectionLogin(&$button_form_values) {

    // Call the login method.
    $login = $this
      ->callMethod('user.login');

    // Eep. we need user details!!!
    if (is_array($login) && isset($login['user'])) {
      drupal_set_message(t('Sucessfully logged in to the remote site; got back details for user %user (uid @uid).', array(
        '%user' => $login['user']['name'],
        '@uid' => $login['user']['uid'],
      )));
    }
    else {
      drupal_set_message(t('Could not log in to the remote site.'), 'warning');
    }
    return $login;
  }

  /**
   * Connection test button validate handler: loading a node.
   */
  function testConnectionNodeLoadValidate(&$button_form_values) {
    if (empty($button_form_values['nid'])) {
      form_set_error('buttons][node_load][nid', 'Node id is required for the node retrieval test.');
    }
  }

  /**
   * Connection test button handler: loading a node.
   */
  function testConnectionNodeLoad(&$button_form_values) {

    // Must be cast to integer for faffiness of XMLRPC and Services.
    $nid = (int) $button_form_values['nid'];
    $fields = array();
    $node = $this
      ->callMethod('node.get', $nid, $fields);
    if (is_array($node) && isset($node['nid'])) {
      drupal_set_message(t('Sucessfully retrieved node %title (nid @nid).', array(
        '%title' => $node['title'],
        '@nid' => $node['nid'],
      )));
    }
    else {
      drupal_set_message(t('Could not retrieve a node from the remote site.'), 'warning');
    }
    return $node;
  }

}

Members

Namesort descending Modifiers Type Description Overrides
clients_connection_base::$cid public property
clients_connection_base::$configuration public property
clients_connection_base::$endpoint public property
clients_connection_base::$name public property
clients_connection_base::doCall protected static function Takes variable number of params after cacheid.
clients_connection_drupal_services::call public static function Executes call and processes data Overrides clients_connection_base::call
clients_connection_drupal_services::connect public static function Use for testing
clients_connection_drupal_services::connectionSettingsForm static function Form builder for adding or editing connections of this class.
clients_connection_drupal_services::connectionSettingsForm_submit static function Submit handler for saving/updating connections of this class. Overrides clients_connection_base::connectionSettingsForm_submit
clients_connection_drupal_services::fetch protected static function Gets raw data from service call
clients_connection_drupal_services::getToken public static function Prepares a hashed token for the service, based on current time, the required service and config values; serviceKey and serviceDomain t
clients_connection_drupal_services::getUser public static function Connects to Drupal Services and logs in the user provided in the config. Returns a session for the user. @todo needs error catching in case service is down
clients_connection_drupal_services::__construct function Constructor method. Overrides clients_connection_base::__construct
clients_connection_drupal_services_6_2::callMethod function Call a remote method. Overrides clients_connection_drupal_services::callMethod 1
clients_connection_drupal_services_6_2::getTestOperations function Provide buttons for the connection testing page. Overrides clients_connection_base::getTestOperations 1
clients_connection_drupal_services_6_2::testConnectionConnect function Connection test button handler: basic connection.
clients_connection_drupal_services_6_2::testConnectionLogin function Connection test button handler: user login.
clients_connection_drupal_services_6_2::testConnectionNodeLoad function Connection test button handler: loading a node. 1
clients_connection_drupal_services_6_2::testConnectionNodeLoadValidate function Connection test button validate handler: loading a node.
clients_connection_drupal_services_6_2::xmlrpc_key_args function Helper function to get key-related method arguments for the XMLRPC call.