$vocab['sw_url'] . 'apiDocumentation', 'href' => $api_url . '/doc/v0.1', ); drupal_add_html_head_link($attributes, $header = FALSE); } /** * Implements hook_menu(). * Defines all menu items needed by Tripal Core * * @ingroup tripal_ws */ function tripal_ws_menu() { // Web Services API callbacks. $items['web-services'] = array( 'title' => 'Tripal Web Services API', 'page callback' => 'tripal_ws_get_services', 'access arguments' => array('access content'), 'type' => MENU_CALLBACK, ); $items['remote/%/%/%/%'] = array( 'page callback' => 'tripal_ws_load_remote_entity', 'page arguments' => array(1, 2, 3, 4), 'access arguments' => array('access content'), 'type' => MENU_CALLBACK, ); // Tripal Web Services setting groups $items['admin/tripal/storage/ws'] = array( 'title' => 'Remote Tripal Sites', 'description' => t("Create mashups of content using data from this site and remote Tripal sites."), 'weight' => 20, 'page callback' => 'system_admin_menu_block_page', 'access arguments' => array('administer tripal'), 'file' => 'system.admin.inc', 'file path' => drupal_get_path('module', 'system'), ); $items['admin/tripal/storage/ws/tripal_sites'] = array( 'title' => 'Configuration', 'description' => t('Provides information about other Tripal sites. This allows data exchange and communication betwen Tripal enabled sites through the web services.'), 'page callback' => 'drupal_get_form', 'page arguments' => array('tripal_ws_tripal_sites_form'), 'access arguments' => array('administer tripal'), 'type' => MENU_NORMAL_ITEM, 'weight' => 0, 'file' => 'includes/tripal_ws.admin.inc', 'file path' => drupal_get_path('module', 'tripal_ws'), ); $items['admin/tripal/storage/ws/tripal_sites/edit'] = array( 'title' => 'Add Tripal Site', 'description' => 'Add a Tripal site', 'page callback' => 'drupal_get_form', 'page arguments' => array('tripal_ws_tripal_sites_edit_form'), 'access arguments' => array('administer tripal'), 'file' => 'includes/tripal_ws.admin.inc', 'file path' => drupal_get_path('module', 'tripal_ws'), 'type' => MENU_LOCAL_ACTION, 'weight' => 2 ); $items['admin/tripal/storage/ws/tripal_sites/remove/%'] = array( 'title' => 'Remove Tripal Site', 'description' => 'Remove a Tripal site', 'page callback' => 'drupal_get_form', 'page arguments' => array('tripal_ws_tripal_sites_remove_form', 6), 'access arguments' => array('administer tripal'), 'file' => 'includes/tripal_ws.admin.inc', 'file path' => drupal_get_path('module', 'tripal_ws'), 'type' => MENU_CALLBACK, 'weight' => 2 ); return $items; } /** * The callback function for all RESTful web services. * */ function tripal_ws_get_services() { global $base_url; $service_path = $base_url . '/web-services'; // This should go out as ld+json drupal_add_http_header('Content-Type', 'application/ld+json'); // Add a link header for the vocabulary service so that clients // know where to find the docs. tripal_load_include_web_service_class('TripalDocService_v0_1'); $service = new TripalDocService_v0_1($service_path); $vocab = tripal_get_vocabulary_details('hydra'); drupal_add_http_header('Link', '<' . $service->getServicePath() . '>; rel="' . $vocab['sw_url'] . 'apiDocumentation"'); drupal_add_http_header('Cache-Control', "no-cache"); try { $ws_path = func_get_args(); $args = $_GET; unset($args['q']); // The web services should never be cached. drupal_page_is_cacheable(FALSE); // The Tripal web services bath will be: // [base_path]/web-services/[service name]/v[major_version].[minor_version] $matches = array(); $service = ''; $major_version = ''; $minor_version = ''; $list_services = FALSE; // If there is no path then we should list all of the services available. if (empty($ws_path)) { tripal_ws_list_services(); return; } // A service path will have the service name in $ws_path[0] and the // version in $ws_path[1]. If we check that the version is correctly // formatted then we can look for the service class and invoke it. else if (preg_match("/^v(\d+)\.(\d+)$/", $ws_path[1], $matches)) { $service_type = $ws_path[0]; $major_version = $matches[1]; $minor_version = $matches[2]; $service_version = 'v' . $major_version . '.' . $minor_version; } // If the URL doesn't match then return not found. else { throw new Exception("Unsupported service URL: '" . $ws_path[1] . "'"); } // Get the service that matches the service_name $service = NULL; $services = tripal_get_web_services(); foreach ($services as $service_class) { tripal_load_include_web_service_class($service_class); if ($service_class::$type == $service_type) { $service = new $service_class($service_path); if ($service->getVersion() == $service_version) { break; } $service = NULL; } } // If a service was not provided then return an error. if (!$service) { throw new Exception('The service type, "' . $service_type . '", is not available'); } // Adjust the path to remove the service type and the version. $adj_path = $ws_path; array_shift($adj_path); array_shift($adj_path); // Now call the service to handle the request. $service->setPath($adj_path); $service->setParams($args); $service->handleRequest(); $response = $service->getResponse(); print drupal_json_encode($response); } catch (Exception $e) { $service = new TripalWebService($service_path); $service->setError($e->getMessage()); $response = $service->getResponse(); print drupal_json_encode($response); } } /** * Generates the list of services as the "home page" for Tripal web services. */ function tripal_ws_list_services() { global $base_url; $base_path = $base_url . '/web-services'; // Create an instance of the TriaplWebService class and use it to build // the entry point for the web serivces. $service = new TripalWebService($base_path); // Get the list of web service classes. $services = tripal_get_web_services(); // Create the parent resource which is a collection. $resource = new TripalWebServiceResource($base_path); // Add the vocabulary to the context. tripal_load_include_web_service_class('TripalDocService_v0_1'); $service = new TripalDocService_v0_1($base_path); $resource->addContextItem('vocab', $service->getServicePath() . '#'); $resource->addContextItem('EntryPoint', 'vocab:EntryPoint'); $resource->setType('EntryPoint'); // Now add the services as properties. foreach ($services as $service_class) { tripal_load_include_web_service_class($service_class); if ($service_class == 'TripalDocService_v0_1') { continue; } $service = new $service_class($base_path); $resource->addContextItem($service_class::$type, array( '@id' => 'vocab:EntryPoint/' . $service_class::$type, '@type' => '@id', )); $resource->addProperty($service_class::$type, $service->getServicePath()); } $service->setResource($resource); $response = $service->getResponse(); print drupal_json_encode($response); } /** * The callback function for all RESTful web services. * */ function tripal_ws_services() { $ws_path = func_get_args(); $params = $_GET; unset($params['q']); // The web services should never be cached. drupal_page_is_cacheable(FALSE); // Using the provided version number, determine which web services // verion to call. $version = array_shift($ws_path); if ($version and preg_match('/v\d+\.\d+/', $version)) { $api_url = 'ws/' . $version; // Add the file with the appropriate web services. module_load_include('inc', 'tripal_ws', 'includes/tripal_ws.rest_' . $version); $version = preg_replace('/\./', '_', $version); $function = 'tripal_ws_services_' . $version; $response = array(); if (function_exists($function)) { $response = $function($api_url, $ws_path, $params); } } else { // TODO: What do we do if no version is provided? } drupal_add_http_header('Content-Type', 'application/ld+json'); print drupal_json_encode($response); } /** * * @param $site_id * @param $api_version * @param $ctype * @param $id * * @return */ function tripal_ws_load_remote_entity($site_id, $api_version, $ctype, $id) { // Get the content type on this site $bundle = tripal_load_bundle_entity(array('label' => $ctype)); $term = entity_load('TripalTerm', array('id' => $bundle->term_id)); $term = reset($term); $vocab = $term->vocab; $query = db_select('tripal_sites', 'ts'); $query->fields('ts'); $query->condition('id', $site_id); $site = $query->execute()->fetchObject(); if (!$site) { return 'Could not find specified site.'; } // Get the content from the web services of the remote site. $url = $site->url . "/ws/v0.1/content/" . $ctype . "/" . $id; $json = file_get_contents($url); $response = json_decode($json, TRUE); // Set the title for this page to match the title provided. drupal_set_title($response['label']); // Attribute this data to the proper source. $source_url = l($response['label'], $response['ItemPage'], array('attributes' => array('target' => '_blank'))); $content = '