tripal_ws.rest.inc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. <?php
  2. /**
  3. *
  4. */
  5. function tripal_ws_rest() {
  6. global $base_url;
  7. $ws_args = func_get_args();
  8. // Set some initial variables.
  9. $response = array();
  10. $status = 'success';
  11. $version = 'v0.1';
  12. $message = '';
  13. $api_url = $base_url . '/ws/' . $version;
  14. $page_limit = 25;
  15. $pager_id = 0;
  16. // Set some defaults for the response.
  17. $response['@context'] = array();
  18. // Lump everything ito a try block so that if there is a problem we can
  19. // throw an error and have that returned in the response.
  20. try {
  21. // The services is the first argument
  22. $service = (count($ws_args) > 0) ? $ws_args[0] : '';
  23. switch ($service) {
  24. case 'doc':
  25. tripal_ws_handle_doc_service($api_url, $response);
  26. break;
  27. case 'content':
  28. tripal_ws_handle_content_service($api_url, $response, $ws_args);
  29. break;
  30. case 'vocab':
  31. break;
  32. default:
  33. tripal_ws_handle_no_service($api_url, $response);
  34. }
  35. }
  36. catch (Exception $e) {
  37. watchdog('tripal_ws', $e->getMessage(), array(), WATCHDOG_ERROR);
  38. $message = $e->getMessage();
  39. $status = 'error';
  40. }
  41. // The responses follow a similar format as the AGAVE API with a
  42. // status, message, version and all data in the 'result' object.
  43. /* $response['status'] = $status;
  44. $response['message'] = $message;
  45. $response['api_version'] = $version;
  46. $response['source'] = array(
  47. 'site_name' => variable_get('site_name', 'Unspecified'),
  48. 'site_url' => $base_url,
  49. 'site_slogan' => variable_get('site_slogan', 'Unspecified'),
  50. 'site_email' => variable_get('site_mail', 'Unspecified'),
  51. ); */
  52. // Rather than use the drupal_json_output() funciton we manually specify
  53. // content type because we want it to be 'ld+json'.
  54. drupal_add_http_header('Content-Type', 'application/ld+json');
  55. print drupal_json_encode($response);
  56. }
  57. /**
  58. * Provides the Hydra compatible apiDocumentation page that describes this API.
  59. *
  60. * @param $api_url
  61. * @param $response
  62. */
  63. function tripal_ws_handle_doc_service($api_url, &$response) {
  64. // First, add the vocabularies used into the @context section.
  65. $response['@context']['rdfs'] = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#';
  66. $response['@context']['hydra'] = 'http://www.w3.org/ns/hydra/core#';
  67. // Next add in the ID for tihs resource.
  68. $site_name = variable_get('site_name', '');
  69. $response['@id'] = $api_url . '/ws-doc/';
  70. $response['title'] = $site_name . ": RESTful Web Services API";
  71. $response['entrypoint'] = $api_url;
  72. $response['description'] = "A fully queryable REST API using JSON-LD and " .
  73. "discoverable using the WC3 Hydra specification.";
  74. // Lastly, add in the terms used into the @context section.
  75. $response['@context']['title'] = 'hydra:title';
  76. $response['@context']['entrypoint'] = array(
  77. "@id" => "hydra:entrypoint",
  78. "@type" => "@id",
  79. );
  80. $response['@context']['description'] = 'hydra:description';
  81. }
  82. /**
  83. * This function specifies the types of resources avaiable via the API.
  84. *
  85. * @param $api_url
  86. * @param $response
  87. * @param $ws_args
  88. */
  89. function tripal_ws_handle_no_service($api_url, &$response) {
  90. // Add in the term's will use for keys to the context.
  91. $response['@context']['itemListElement'] = 'schema:itemListElement';
  92. $response['@context']['position'] = 'schema:position';
  93. $response['@context']['item'] = 'schema:item';
  94. $response['@context']['name'] = 'foaf:name';
  95. $response['@context']['description'] = 'dc:description';
  96. $response['@context']['numberOfItems'] = 'schema:numberOfItems';
  97. $response['@context']['itemListOrder'] = 'schema:itemListOrder';
  98. $response['@context']['numberOfItems'] = 'schema:numberOfItems';
  99. $response['@context']['ListItem'] = 'schema:ListItem';
  100. // Start the list.
  101. $response['@type'] = 'ItemList';
  102. $response['itemListOrder'] = 'ItemListOrderAscending';
  103. $response['numberOfItems'] = 0;
  104. $response['name'] = 'Services';
  105. $response['itemListElement'][] = array(
  106. '@type' => 'ListItem',
  107. 'position' => 1,
  108. 'item' => array(
  109. '@id' => $api_url . '/data/',
  110. '@type' => $vocab->namespace . ':' . $term->accession,
  111. 'name' => $term->name,
  112. 'description' => 'This service provides acesss to the biological and ' .
  113. 'anciallary data available on this site.',
  114. ),
  115. );
  116. }
  117. /**
  118. *
  119. * @param $api_url
  120. * @param $response
  121. * @param $ws_args
  122. */
  123. function tripal_ws_handle_content_service($api_url, &$response, $ws_args) {
  124. // Get the content type.
  125. $ctype = (count($ws_args) > 1) ? $ws_args[1] : '';
  126. $entity_id = (count($ws_args) > 2) ? $ws_args[2] : '';
  127. // If we have no content type then list all of the available content types.
  128. if (!$ctype) {
  129. tripal_ws_get_content_types($api_url, $response);
  130. }
  131. // If we don't have an entity ID then show a paged list of entities with
  132. // the given type.
  133. else if ($ctype and !$entity_id) {
  134. tripal_ws_get_content_type($api_url, $response, $ws_args, $ctype);
  135. }
  136. // If we have a content type and an entity ID then show the entity
  137. else {
  138. tripal_ws_get_content($api_url, $response, $ws_args, $ctype, $entity_id);
  139. }
  140. }
  141. /**
  142. * Provides a collection (list) of all of the content types.
  143. *
  144. * @param $api_url
  145. * @param $response
  146. */
  147. function tripal_ws_get_content_types($api_url, &$response) {
  148. // First, add the vocabularies used into the @context section.
  149. $response['@context']['rdfs'] = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#';
  150. $response['@context']['hydra'] = 'http://www.w3.org/ns/hydra/core#';
  151. // Next add in the ID for tihs resource.
  152. $response['@id'] = $api_url . '/content';
  153. // Start the list.
  154. $response['@type'] = 'Collection';
  155. $response['totalItems'] = 0;
  156. $response['label'] = 'Content Types';
  157. // Get the list of published terms (these are the bundle IDs)
  158. $bundles = db_select('tripal_bundle', 'tb')
  159. ->fields('tb')
  160. ->orderBy('tb.label', 'ASC')
  161. ->execute();
  162. $terms = array();
  163. // Iterate through the terms and add the mas a entry in the collection.
  164. while ($bundle = $bundles->fetchObject()) {
  165. $entity = entity_load('TripalTerm', array('id' => $bundle->term_id));
  166. $term = reset($entity);
  167. $vocab = $term->vocab;
  168. if (!array_key_exists($vocab->namespace, $response['@context'])) {
  169. // If there is no URL prefix then use this API's vocabulary API
  170. if ($term->urlprefix) {
  171. $response['@context'][$vocab->namespace] = $term->urlprefix;
  172. }
  173. else {
  174. $response['@context'][$vocab->namespace] = $api_url . '/vocab/' . $vocab->namespace . '/';
  175. }
  176. }
  177. // Get the bundle description. If no description is provided then
  178. // use the term definition
  179. $description = tripal_get_bundle_variable('description', $bundle->id);
  180. if (!$description) {
  181. $description = $term->definition;
  182. }
  183. // Add the bundle as a content type.
  184. $response['member'][] = array(
  185. '@id' => $api_url . '/content/' . $bundle->label,
  186. '@type' => $vocab->namespace . ':' . $term->accession,
  187. 'label' => $bundle->label,
  188. 'description' => $description,
  189. );
  190. $i++;
  191. }
  192. $response['totalItems'] = $i;
  193. // Lastly, add in the terms used into the @context section.
  194. $response['@context']['Collection'] = 'hydra:Collection';
  195. $response['@context']['totalItems'] = 'hydra:totalItems';
  196. $response['@context']['member'] = 'hydra:member';
  197. $response['@context']['label'] = 'rdfs:label';
  198. $response['@context']['description'] = 'hydra:description';
  199. }
  200. /**
  201. *
  202. * @param $api_url
  203. * @param $response
  204. * @param $ws_args
  205. */
  206. function tripal_ws_get_content_type($api_url, &$response, $ws_args, $ctype) {
  207. // First, add the vocabularies used into the @context section.
  208. $response['@context']['rdfs'] = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#';
  209. $response['@context']['hydra'] = 'http://www.w3.org/ns/hydra/core#';
  210. $response['@context']['schema'] = 'https://schema.org/';
  211. // Next add in the ID for tihs resource.
  212. $response['@id'] = $api_url . '/content/' . $ctype;
  213. // Get the TripalBundle, TripalTerm and TripalVocab type for this type.
  214. $bundle = tripal_load_bundle_entity(array('label' => $ctype));
  215. $entity = entity_load('TripalTerm', array('id' => $bundle->term_id));
  216. $term = reset($entity);
  217. $vocab = $term->vocab;
  218. // Start the list.
  219. $response['@type'] = 'Collection';
  220. $response['totalItems'] = 0;
  221. // TODO: perhaps we should also have a plural label and get rid of the word
  222. // 'records'.
  223. $response['label'] = $bundle->label . " records";
  224. // Get the list of entities for this bundle.
  225. $query = new EntityFieldQuery;
  226. $query->entityCondition('entity_type', 'TripalEntity')
  227. ->entityCondition('bundle', $bundle->name)
  228. ->propertyOrderBy('title', 'DESC')
  229. ->pager(10);
  230. // Iterate through the entities and add them to the list.
  231. $results = $query->execute();
  232. $i = 0;
  233. if (isset($results['TripalEntity'])) {
  234. $entities = entity_load('TripalEntity', array_keys($results['TripalEntity']));
  235. foreach ($entities as $entity) {
  236. $response['member'][] = array(
  237. '@id' => $api_url . '/content/' . $ctype . '/' . $bundle->id,
  238. '@type' => $vocab->namespace . ':' . $term->accession,
  239. 'label' => $entity->title,
  240. 'itemPage' => url('/bio-data/' . $entity->id, array('absolute' => TRUE)),
  241. );
  242. $i++;
  243. }
  244. }
  245. $response['totalItems'] = $i;
  246. // Lastly, add in the terms used into the @context section.
  247. $response['@context']['Collection'] = 'hydra:Collection';
  248. $response['@context']['totalItems'] = 'hydra:totalItems';
  249. $response['@context']['member'] = 'hydra:member';
  250. $response['@context']['label'] = 'rdfs:label';
  251. $response['@context']['itemPage'] = 'schema:itemPage';
  252. }
  253. /**
  254. *
  255. * @param $api_url
  256. * @param $response
  257. * @param $ws_args
  258. */
  259. function tripal_ws_get_content($api_url, &$response, $ws_args, $ctype, $entity_id) {
  260. // First, add the vocabularies used into the @context section.
  261. $response['@context']['rdfs'] = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#';
  262. $response['@context']['hydra'] = 'http://www.w3.org/ns/hydra/core#';
  263. $response['@context']['schema'] = 'https://schema.org/';
  264. // Get the TripalBundle, TripalTerm and TripalVocab type for this type.
  265. $bundle = tripal_load_bundle_entity(array('label' => $ctype));
  266. $entity = entity_load('TripalTerm', array('id' => $bundle->term_id));
  267. $term = reset($entity);
  268. $vocab = $term->vocab;
  269. // Get the TripalEntity
  270. $entity = entity_load('TripalEntity', array('id' => $entity_id));
  271. $entity = reset($entity);
  272. // Next add in the ID and Type for this resources.
  273. $response['@id'] = $api_url . '/content/' . $ctype . '/' . $entity_id;
  274. $response['@type'] = $vocab->namespace . ':' . $term->accession,;
  275. $response['totalItems'] = 0;
  276. // TODO: perhaps we should also have a plural label and get rid of the word
  277. // 'records'.
  278. $response['label'] = $bundle->label . " records";
  279. // Get the list of entities for this bundle.
  280. $query = new EntityFieldQuery;
  281. $query->entityCondition('entity_type', 'TripalEntity')
  282. ->entityCondition('bundle', $bundle->name)
  283. ->propertyOrderBy('title', 'DESC')
  284. ->pager(10);
  285. // Iterate through the entities and add them to the list.
  286. $results = $query->execute();
  287. $i = 0;
  288. if (isset($results['TripalEntity'])) {
  289. $entities = entity_load('TripalEntity', array_keys($results['TripalEntity']));
  290. foreach ($entities as $entity) {
  291. $response['member'][] = array(
  292. '@id' => $api_url . '/content/' . $ctype . '/' . $bundle->id,
  293. '@type' => $vocab->namespace . ':' . $term->accession,
  294. 'label' => $entity->title,
  295. 'itemPage' => url('/bio-data/' . $bundle->id, array('absolute' => TRUE)),
  296. );
  297. $i++;
  298. }
  299. }
  300. $response['totalItems'] = $i;
  301. // Lastly, add in the terms used into the @context section.
  302. $response['@context']['Collection'] = 'hydra:Collection';
  303. $response['@context']['totalItems'] = 'hydra:totalItems';
  304. $response['@context']['member'] = 'hydra:member';
  305. $response['@context']['label'] = 'rdfs:label';
  306. $response['@context']['itemPage'] = 'schema:itemPage';
  307. }