'. 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_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', array('%server' => $server . '_server'), WATCHDOG_DEBUG); } 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:
@info
', array('@info' => print_r(services_server_info_object(), TRUE)), WATCHDOG_DEBUG); } 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]; } } } } }