'. t('Visit the Services Handbook for help and information.', array('@handbook_url' => 'http://drupal.org/node/109782')) .'

'; break; case 'admin/build/services': $output = '

'. t('Services are collections of methods available to remote applications. They are defined in modules, and may be accessed in a number of ways through server modules. Visit the Services Handbook for help and information.', array('@handbook_url' => 'http://drupal.org/node/109782')) .'

'; $output .= '

'. t('All enabled services and methods are shown. Click on any method to view information or test.') .'

'; $output .= '
Enabled
Enabled With Debug
Disabled
'; break; } return $output; } /** * Implementation of hook_perm(). */ function services_perm() { return array( 'administer services', // File resource permissions 'get any binary files', 'get own binary files', 'save file information', // System resource permissions 'get a system variable', 'set a system variable', ); } /** * Implementation of hook_hook_info(). */ function services_hook_info() { $hooks['services_resources'] = array( 'group' => 'services', ); return $hooks; } /** * Implementation of hook_menu(). */ function services_menu() { $base = array( 'access arguments' => array('administer services'), 'file' => 'services.admin.inc', ); $items['admin/build/services'] = array( 'title' => 'Services', 'description' => 'Manage how external applications communicates with Drupal.', 'page callback' => 'services_list_endpoint', ) + $base; $items['admin/build/services/list'] = array( 'title' => 'List', 'page callback' => 'services_list_endpoint', 'type' => MENU_DEFAULT_LOCAL_TASK, 'weight' => -10, ) + $base; $items['admin/build/services/add'] = array( 'title' => 'Add endpoint', 'page callback' => 'services_add_endpoint', 'type' => MENU_LOCAL_TASK, ) + $base; $items['admin/build/services/%services_endpoint/edit'] = array( 'title' => 'Edit endpoint', 'page callback' => 'services_edit_endpoint', 'page arguments' => array(3), 'type' => MENU_LOCAL_TASK, ) + $base; $items['admin/build/services/%services_endpoint/authentication'] = array( 'title' => 'Authentication', 'page callback' => 'services_edit_endpoint_authentication', 'page arguments' => array(3), 'type' => MENU_LOCAL_TASK, 'weight' => 5, ) + $base; $items['admin/build/services/%services_endpoint/resources'] = array( 'title' => 'Resources', 'page callback' => 'services_edit_endpoint_resources', 'page arguments' => array(3), 'type' => MENU_LOCAL_TASK, 'weight' => 10, ) + $base; $items['admin/build/services/%services_endpoint/export'] = array( 'title' => 'Export endpoint', 'page callback' => 'drupal_get_form', 'page arguments' => array('services_export_endpoint', 3), 'type' => MENU_LOCAL_TASK, 'weight' => 20, ) + $base; $items['admin/build/services/%services_endpoint/delete'] = array( 'title' => 'Delete endpoint', 'page callback' => 'drupal_get_form', 'page arguments' => array('services_delete_confirm_endpoint', 3), 'type' => MENU_CALLBACK, ) + $base; $items['admin/build/services/%services_endpoint/disabledebug'] = array( 'page callback' => 'services_disable_debug_mode', 'page arguments' => array(3), 'type' => MENU_CALLBACK, ) + $base; $items['admin/build/services/%services_endpoint/enabledebug'] = array( 'page callback' => 'services_enable_debug_mode', 'page arguments' => array(3), 'type' => MENU_CALLBACK, ) + $base; $items['admin/build/services/%services_endpoint/disable'] = array( 'page callback' => 'services_disable_endpoint', 'page arguments' => array(3), 'type' => MENU_CALLBACK, ) + $base; $items['admin/build/services/%services_endpoint/enable'] = array( 'page callback' => 'services_enable_endpoint', 'page arguments' => array(3), 'type' => MENU_CALLBACK, ) + $base; $items['admin/build/services/ahah/security-options'] = array( 'page callback' => '_services_ahah_security_options', 'type' => MENU_CALLBACK, ) + $base; $items['crossdomain.xml'] = array( 'access callback' => 'services_access_menu', 'page callback' => 'services_crossdomain_xml', 'type' => MENU_CALLBACK, ); // Add menu items for the different endpoints $endpoints = services_endpoint_load_all(); foreach ($endpoints as $endpoint) { if ($endpoint->status) { $items[$endpoint->path] = array( 'title' => 'Services endpoint', 'access callback' => 'services_access_menu', 'page callback' => 'services_endpoint_callback', 'page arguments' => array($endpoint->name), 'type' => MENU_CALLBACK, ); } } return $items; } /** * Access callback that always returns TRUE. * * This callback is necessary for services like login and logout that should * always be wide open and accessible. * * *** USE THIS WITH GREAT CAUTION *** * * If you think you need it you are almost certainly wrong. */ function services_access_menu() { return TRUE; } /** * Implementation of hook_theme(). */ function services_theme() { return array( 'services_endpoint_index' => array( 'template' => 'services_endpoint_index', 'arguments' => array('endpoints' => NULL), ), ); } /** * Returns information about the installed server modules on the system. * * @return array * An associative array keyed after module name containing information about * the installed server implementations. */ function services_get_servers() { static $servers; if (!$servers) { $servers = array(); foreach (module_implements('server_info') as $module) { $servers[$module] = call_user_func($module . '_server_info'); } } return $servers; } /** * Menu system page callback for server endpoints. * * @param string $endpoint * The endpoint name. * @return void */ function services_endpoint_callback($endpoint_name) { module_load_include('runtime.inc', 'services'); $endpoint = services_endpoint_load($endpoint_name); $server = $endpoint->server; if (function_exists($server . '_server')) { // call the server if($endpoint->debug) { watchdog('services', 'Calling server :'. $server . '_server'); } services_set_server_info_from_array(array( 'module' => $server, 'endpoint' => $endpoint_name, 'endpoint_path' => $endpoint->path, 'debug' => $endpoint->debug, 'drupal_path' => getcwd(), )); if($endpoint->debug) { watchdog('services', 'Server Info Main Object
'. print_r(services_server_info_object(), 1));
    }
    print call_user_func($server . '_server');

    // Do not let this output
    module_invoke_all('exit');
    exit;
  }
  // return 404 if the server doesn't exist
  drupal_not_found();
}

/**
 * Callback for crossdomain.xml
 */
function services_crossdomain_xml() {
  $output = '' . "\n";
  $output .= '' . "\n";

  $domains = module_invoke_all('services_crossdomain_domain_policy');
  drupal_alter('services_crossdomain_domain_policy', $domains);

  foreach ($domains as $domain => $info) {
    $output .= '  ' . "\n";
    if ($info['subdomain_wildcard']) {
      $output .= '  ' . "\n";
    }
  }

  $output .= '';

  services_xml_output($output);
}

/**
 * Implementation of hook_services_crossdomain_domain_policy().
 */
function services_services_crossdomain_domain_policy() {
  // Allow our own domain and it's subdomains
  return array(
    $_SERVER['HTTP_HOST'] => array(
      'subdomain_wildcard' => TRUE,
    ),
  );
}

/**
 * Helper function for services_crossdomain_xml().
 * Outputs the necessary http headers and xml processing instruction then exits.
 *
 * @param string $xml
 *  The xml document to print.
 * @return void
 *  This function never returns, it always exits.
 */
function services_xml_output($xml) {
  $xml = '' . "\n" . $xml;
  header('Connection: close');
  header('Content-Length: ' . strlen($xml));
  header('Content-Type: text/xml');
  header('Date: ' . date('r'));
  echo $xml;
  exit;
}

/**
 * Create a new endpoint with defaults appropriately set from schema.
 *
 * @return stdClass
 *  An endpoint initialized with the default values.
 */
function services_endpoint_new() {
  ctools_include('export');
  return ctools_export_new_object('services_endpoint');
}

/**
 * Load a single endpoint.
 *
 * @param string $name
 *  The name of the endpoint.
 * @return stdClass
 *  The endpoint configuration.
 */
function services_endpoint_load($name) {
  ctools_include('export');
  $result = ctools_export_load_object('services_endpoint', 'names', array($name));
  if (isset($result[$name])) {
    return $result[$name];
  } 
  else {
   $result =  db_query("SELECT * FROM {services_endpoint} WHERE name = '%s'", $name);
   $matches = array();
    while ($endpoint = db_fetch_object($result)) {
      return $endpoint;
    }
  }
  return FALSE;
}

/**
 * Load all endpoints.
 *
 * @return array
 *  Array of endpoint objects keyed by endpoint names.
 */
function services_endpoint_load_all() {
  ctools_include('export');
  if(!ctools_export_load_object('services_endpoint')) {
   $result =  db_query("SELECT * FROM {services_endpoint}");
   $matches = array();
    while ($endpoint = db_fetch_object($result)) {
      $matches[] = $endpoint;
    }
    return $matches;
  }
  return ctools_export_load_object('services_endpoint');
}

/**
 * Saves an endpoint in the database.
 *
 * @return void
 */
function services_endpoint_save($endpoint) {
  $update = (isset($endpoint->eid)) ? array('eid') : array();
  drupal_write_record('services_endpoint', $endpoint, $update);
  menu_rebuild();
  cache_clear_all('services:' . $endpoint->name . ':', 'cache', TRUE);
}

/**
 * Remove an endpoint.
 *
 * @return void
 */
function services_endpoint_delete($endpoint) {
  db_query("DELETE FROM {services_endpoint} WHERE name = '%s' AND eid = %d", $endpoint->name, $endpoint->eid);
  menu_rebuild();
  cache_clear_all('services:' . $endpoint->name . ':', 'cache', TRUE);
}

/**
 * Export an endpoint.
 *
 * @return string
 */
function services_endpoint_export($endpoint, $indent = '') {
  ctools_include('export');
  $output = ctools_export_object('services_endpoint', $endpoint, $indent);
  return $output;
}

/**
 * Lists all available endpoints.
 *
 * @return array
 */
function services_endpoint_list() {
  $return = array();
  $endpoints = services_endpoint_load_all();
  foreach ($endpoints as $endpoint) {
    $return[$endpoint->name] = $endpoint->title;
  }
  return $return;
}

/**
 * Gets all resource definitions.
 *
 * @param string $endpoint_name
 *   Optional. The endpoint endpoint that's being used.
 * @return array
 *  An array containing all resources.
 */
function services_get_resources($endpoint_name = '') {
  $cache_key = 'services:' . $endpoint_name . ':resources';

  $resources = array();
  if (($cache = cache_get($cache_key)) && isset($cache->data)) {
    $resources = $cache->data;
  }
  else {
    module_load_include('resource_build.inc', 'services');
    $resources = _services_build_resources($endpoint_name);
    cache_set($cache_key, $resources);
  }

  return $resources;
}

/**
 * Implementation of hook_services_resources().
 */
function services_services_resources() {
  module_load_include('resource_build.inc', 'services');
  // Return resources representing legacy services
  return array_merge(_services_core_resources(), _services_legacy_services_as_resources());
}

/**
 * Returns all the controller names for a endpoint.
 *
 * @param string $endpoint
 *  The endpoint that should be used.
 * @return array
 *  Either a non associative array containing all controller names. Or, if
 *  $key_by_resource was set to TRUE, a associative array where the resource
 *  name is the key and the value is a non-associative array containing the
 *  resource's controller names.
 */
function services_controllers_list($endpoint) {
  $controllers = array();
  $ops = array('actions', 'relationships', 'targeted actions');
  $resources = services_get_resources($endpoint);
  foreach ($resources as $resource_name => $res) {
    // Get all basic operations
    foreach (array('create', 'retrieve', 'update', 'delete', 'index') as $op) {
      if (isset($res[$op])) {
        $controllers[] = $resource_name . '.' . $op;
      }
    }
 
    // Handle extended operatios
    foreach ($ops as $op) {
      if (isset($res[$op])) {
        foreach ($res[$op] as $name => $def) {
          // Append prefix if it isn't empty
          $controllers[] = $resource_name . '.' . $name;
        }
      }
    }
  }
  return $controllers;
}

/**
 * Returns the requested controller.
 *
 * @param string $name
 *  The name of the controller in the format: {resource}.{name} or
 *  {resource}.{operation}. Examples: "node.retrieve", "system.getVariable".
 * @param string $endpoint
 *  The endpoint that should be used.
 */
function services_controller_get($name, $endpoint) {
  list($resource_name, $method) = explode('.', $name);
  $ops = array('actions', 'relationships', 'targeted actions');
  $resources = services_get_resources($endpoint);

  if (isset($resources[$resource_name])) {
    $res = $resources[$resource_name];
    
    if (isset($res[$method])) {
      return $res[$method];
    } 
    else {
      // Handle extended operatios
      foreach ($ops as $op) {
        if (isset($res[$op]) && isset($res[$op][$method])) {
          return $res[$op][$method];
        }
      }
    }
  }
}