TripalWebService.inc 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411
  1. <?php
  2. class TripalWebService {
  3. // --------------------------------------------------------------------------
  4. // EDITABLE STATIC CONSTANTS
  5. //
  6. // The following constants SHOULD be set for each descendent class. They are
  7. // used by the static functions to provide information to Drupal about
  8. // the field and it's default widget and formatter.
  9. // --------------------------------------------------------------------------
  10. /**
  11. * The human-readable label for this web service.
  12. */
  13. public static $label = 'Base WebService';
  14. /**
  15. * A bit of text to describe what this service provides.
  16. */
  17. public static $description = 'This is the base class for Tripal web services as is not meant to be used on it\'s own';
  18. /**
  19. * A machine-readable type for this service. This name must be unique
  20. * among all Tripal web services and is used to form the URL to access
  21. * this service.
  22. */
  23. public static $type = 'services';
  24. // --------------------------------------------------------------------------
  25. // PROTECTED CLASS MEMBERS -- DO NOT OVERRIDE
  26. // --------------------------------------------------------------------------
  27. /**
  28. * The resource that will be returned by the webservice given the
  29. * arguments provided. This is a private
  30. */
  31. protected $resource;
  32. /**
  33. * An array containing the elements of the URL path. Each level of the
  34. * URL appears in a separate element of the array. The service type and
  35. * version are automatically removed from the array.
  36. */
  37. protected $path;
  38. /**
  39. * The set of paramters provided to the sesrvice. These are the values
  40. * that would occur in a URL after the question mark in an HTTP GET or
  41. * the data items of an HTTP POST.
  42. */
  43. protected $params;
  44. /**
  45. * The URL at which Tripal web services are found. This is used
  46. * for creating the IRI for resources.
  47. */
  48. protected $base_path;
  49. // --------------------------------------------------------------------------
  50. // CONSTRUCTORS
  51. // --------------------------------------------------------------------------
  52. /**
  53. * Implements the constructor.
  54. */
  55. public function __construct($base_path) {
  56. if (!$base_path) {
  57. throw new Exception('Please provide a $base_path argument when creating a new TripalWebService.');
  58. }
  59. // Create a default resource so that the service always some something.
  60. $this->resource = new TripalWebServiceResource($base_path);
  61. // Intialize the private members variables.
  62. $this->path = array();
  63. $this->params = array();
  64. $this->base_path = $base_path;
  65. }
  66. // --------------------------------------------------------------------------
  67. // OVERRIDEABLE FUNCTIONS
  68. // --------------------------------------------------------------------------
  69. /**
  70. * Responds to the request argument provided to the service.
  71. *
  72. * This function should be implemented by a TripalWebService child class.
  73. *
  74. */
  75. public function handleRequest() {
  76. // TODO: make sure the $this->path and $this->params are set before
  77. // continuing.
  78. }
  79. // --------------------------------------------------------------------------
  80. // CLASS FUNCTIONS -- DO NOT OVERRIDE
  81. // --------------------------------------------------------------------------
  82. /**
  83. * Sets the URL path for the resource being called.
  84. *
  85. * @param $path
  86. * An array containing the elements of the URL path. Each level of the
  87. * URL appears in a separate element of the array. The service type and
  88. * version are automatically removed from the array. For example, a
  89. * URL of the type http://localhost/web-services/content/v0.1/Gene/sequence
  90. * will result in a $path array containing the following:
  91. * @code
  92. * array(
  93. * 'Gene',
  94. * 'sequence',
  95. * );
  96. * @endcode
  97. *
  98. * @param unknown $path
  99. */
  100. public function setPath($path) {
  101. $this->path = $path;
  102. }
  103. /**
  104. * Sets the parameters for the resource.
  105. *
  106. * @param $params
  107. * The set of paramters provided to the sesrvice. These are the values
  108. * that would occur in a URL after the question mark in an HTTP GET or
  109. * the data items of an HTTP POST.
  110. */
  111. public function setParams($params) {
  112. $this->params = $params;
  113. }
  114. /**
  115. * Retrieves the version number for this web service.
  116. *
  117. * Each web service must have version number built into the name of the
  118. * class. The version number appears at the end of the class name, begins
  119. * with a lower-case 'v' and is followed by two numbers (major and minor) that
  120. * are separated by an underscore. This function identifies the version
  121. * from the class name and returns it here in a human-readable format.
  122. *
  123. * @param $sanatize
  124. * Set to TRUE to convert the period to underscore.
  125. *
  126. * @return
  127. * The version number for this web service.
  128. */
  129. public function getVersion($sanatize = FALSE) {
  130. $class = get_class($this);
  131. $major_version = '';
  132. $minor_version = '';
  133. if (preg_match('/v(\d+)_(\d+)$/', $class, $matches)) {
  134. $major_version = $matches[1];
  135. $minor_version = $matches[2];
  136. return 'v' . $major_version . '.' . $minor_version;
  137. }
  138. return '';
  139. }
  140. /**
  141. * Retrieves the context section of the response.
  142. *
  143. * The JSON-LD response constists of two sections the '@context' section
  144. * and the data section. This function only returns the context section
  145. * of the response.
  146. *
  147. * @return
  148. * An associative array containing the context section of the response.
  149. */
  150. public function getContext() {
  151. return $this->resource->getContext();
  152. }
  153. /**
  154. * Returns the full web service response.
  155. *
  156. * The response includes both the @context and data sections of the
  157. * JSON-LD response.
  158. *
  159. * @return
  160. * An associative array containing that can be converted to JSON.
  161. */
  162. public function getResponse() {
  163. $context = $this->resource ? $this->resource->getContext() : array();
  164. $type = $this->resource ? $this->resource->getType() : 'unknown';
  165. $json_ld = array(
  166. '@context' => $context,
  167. '@id' => '',
  168. '@type' => $type,
  169. );
  170. $data = $this->getData();
  171. return array_merge($json_ld, $data);
  172. }
  173. /**
  174. * Retreives the service URL for this service.
  175. */
  176. public function getServicePath() {
  177. $class = get_class($this);
  178. $version = $this->getVersion();
  179. $type = $class::$type;
  180. return $this->base_path . '/' . $type . '/' . $version;
  181. }
  182. /**
  183. * Retrieves the data section of the response.
  184. *
  185. * The JSON-LD response constists of two sections the '@context' section
  186. * and the data section. This function only returns the data section
  187. * of the response.
  188. *
  189. * @return
  190. * An associative array containing the data section of the response.
  191. */
  192. public function getData() {
  193. if ($this->resource) {
  194. return $this->resource->getData();
  195. }
  196. return array();
  197. }
  198. /**
  199. * Sets the resource to be returned by this web service.
  200. *
  201. * @param $resource.
  202. * An implementation of a TripalWebServiceResource.
  203. */
  204. public function setResource($resource) {
  205. // Make sure the $servcie provides is a TripalWebServcie class.
  206. if (!is_a($resource, 'TripalWebServiceResource')) {
  207. throw new Exception("Cannot add a new resource to this web service as it is not a TripalWebServiceResource.");
  208. }
  209. $this->resource = $resource;
  210. }
  211. /**
  212. * Set an error for the service.
  213. *
  214. * @param $message
  215. * The error message to report.
  216. */
  217. public function setError($message) {
  218. $this->resource = new TripalWebServiceResource($this->base_path);
  219. $this->resource->setID('error');
  220. $this->resource->addContextItem('error', 'rdfs:error');
  221. $this->resource->setType('error');
  222. $this->resource->addProperty('error', $message);
  223. }
  224. /**
  225. * Retrieves an array contining the supported classes.
  226. *
  227. * Supported classe are resources provided by this web services and the
  228. * operations supported by those classes.
  229. *
  230. * @return
  231. * An array of TripalWebServiceResource objects that follow the Hydra
  232. * documentation for documenting supported classes.
  233. */
  234. public function getSupportedClasses() {
  235. $supported_classes = array();
  236. return $supported_classes;
  237. }
  238. /**
  239. * Adds a term to the '@context' section for a given resource.
  240. *
  241. * @param $resource
  242. * A TripalWebServiceResource instance.
  243. * @param $term
  244. * The term array.
  245. * @param $santize
  246. * An array of keywords indicating how to santize the key. By default,
  247. * no sanitizing occurs. The two valid types are 'lowercase', and 'spacing'
  248. * where 'lowercase' converts the term name to all lowercase and
  249. * 'spacing' replaces any spaces with underscores.
  250. * @return $key
  251. * The key (the term name but with spaces replaced with underscores).
  252. */
  253. public function addContextTerm($resource, $term, $sanitize = array()) {
  254. if (!is_a($resource, 'TripalWebServiceResource')) {
  255. throw new Exception('addContextTerm: Please provide a $resource of type TripalWebServiceResource.');
  256. }
  257. if (!$term) {
  258. $backtrace = debug_backtrace();
  259. throw new Exception('addContextTerm: Please provide a non NUll or non empty $term.');
  260. }
  261. if (!$term['name']) {
  262. throw new Exception('addContextTerm: The provided term does not have a name: ' . print_r($term, TRUE));
  263. }
  264. // Make sure the vocab is present
  265. $vocab = $term['vocabulary'];
  266. $this->addContextVocab($resource, $vocab);
  267. // Sanitize the term key
  268. $key = $term['name'];
  269. $key_adj = $key;
  270. if (in_array('spacing', $sanitize)) {
  271. $key_adj = preg_replace('/ /', '_', $key_adj);
  272. }
  273. if (in_array('lowercase', $sanitize)) {
  274. $key_adj = strtolower($key_adj);
  275. }
  276. // Create the compact IRI
  277. $compact_iri = $vocab['short_name'] . ':' . $term['accession'];
  278. // If the full naming is indicated in the service parameters then
  279. // set the full name of the keys to include the vocab short name.
  280. if (array_key_exists('full_keys', $this->params)) {
  281. //$key_adj = $vocab['short_name'] . ':' . $key_adj;
  282. }
  283. $iri = $term['url'];
  284. $resource->addContextItem($key_adj, $compact_iri);
  285. $resource->addContextItem($compact_iri, $iri);
  286. if ($key_adj == 'clause subject') {
  287. //print_r(debug_backtrace()[2]['function']);
  288. }
  289. return $key_adj;
  290. }
  291. /**
  292. * Adds a vocabulary to the '@context' section for a given resource.
  293. *
  294. * @param $resource
  295. * A TripalWebServiceResource instance.
  296. * @param $vocab
  297. * The vocabulary array.
  298. */
  299. public function addContextVocab($resource, $vocab) {
  300. if (!is_a($resource, 'TripalWebServiceResource')) {
  301. throw new Exception('addContextVocab: Please provide a $resource of type TripalWebServiceResource.');
  302. }
  303. $key = $vocab['short_name'];
  304. // The URL here should be the URL prefix not the database home
  305. // page. But unfortunately, the URL prefix can't be guaranteed to be
  306. // a true prefix. Not all databases place by the rules. For this reason,
  307. // we can never use JSON-LD compact IRIs. :-(
  308. $iri = $vocab['url'];
  309. $resource->addContextItem($key, $iri);
  310. }
  311. /**
  312. * Adds a key/value property to the given resource.
  313. *
  314. * @param $resource
  315. * A TripalWebServiceResource instance.
  316. * @param $term
  317. * The term array for the key.
  318. * @param $value
  319. * The value to add.
  320. * @param $santize
  321. * An array of keywords indicating how to santize the key. By default,
  322. * no sanitizing occurs. The two valid types are 'lowercase', and 'spacing'
  323. * where 'lowercase' converts the term name to all lowercase and
  324. * 'spacing' replaces any spaces with underscores.
  325. * @return $key
  326. * The key (the term name but with spaces replaced with underscores).
  327. */
  328. public function addResourceProperty($resource, $term, $value, $sanitize = array()) {
  329. if (!is_a($resource, 'TripalWebServiceResource')) {
  330. throw new Exception('addProperty: Please provide a $resource of type TripalWebServiceResource.');
  331. }
  332. // First add the term
  333. $key = $this->addContextTerm($resource, $term, $sanitize);
  334. // Then add the property.
  335. $resource->addProperty($key, $value);
  336. }
  337. /**
  338. * Sets the type for the given resource.
  339. *
  340. * The type exist in the context of the web service.
  341. *
  342. * @param $resource
  343. * A TripalWebServiceResource instance.
  344. * @param $type
  345. * The type
  346. * @param $santize
  347. * An array of keywords indicating how to santize the key. By default,
  348. * no sanitizing occurs. The two valid types are 'lowercase', and 'spacing'
  349. * where 'lowercase' converts the term name to all lowercase and
  350. * 'spacing' replaces any spaces with underscores.
  351. */
  352. public function setResourceType($resource, $term, $sanitize = array('spacing')) {
  353. if (!is_a($resource, 'TripalWebServiceResource')) {
  354. throw new Exception('addProperty: Please provide a $resource of type TripalWebServiceResource.');
  355. }
  356. // First add the term
  357. $key = $this->addContextTerm($resource, $term, $sanitize);
  358. // Then set the type
  359. $resource->setType($key);
  360. }
  361. }