TripalWebServiceResource.inc 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. <?php
  2. class TripalWebServiceResource {
  3. /**
  4. * The unique identifier for this resource.
  5. */
  6. protected $id;
  7. /**
  8. * The unique type of resource. The type must exists in the
  9. * context for the web service.
  10. */
  11. protected $type;
  12. /**
  13. * The JSON-LD compatible context for this resource.
  14. */
  15. protected $context;
  16. /**
  17. * Holds the data portion of the JSON-LD response for this resource.
  18. */
  19. protected $data;
  20. /**
  21. * The URL path that the service is providing to access this resource.
  22. * This path plus the $id are concatenated to form the IRI for this resource.
  23. */
  24. protected $service_path;
  25. /**
  26. * Implements the constructor.
  27. *
  28. * @param $service_path
  29. *
  30. */
  31. public function __construct($service_path) {
  32. $this->context = array();
  33. $this->data = array();
  34. $this->service_path = $service_path;
  35. // First, add the RDFS and Hydra vocabularies to the context. All Tripal
  36. // web services should use these.
  37. $this->addContextItem('rdf', "http://www.w3.org/1999/02/22-rdf-syntax-ns#");
  38. $this->addContextItem('rdfs', 'http://www.w3.org/2000/01/rdf-schema#');
  39. $this->addContextItem('hydra', "http://www.w3.org/ns/hydra/core#");
  40. $vocab = tripal_get_vocabulary_details('dc');
  41. $this->addContextItem('dc', $vocab['url']);
  42. $vocab = tripal_get_vocabulary_details('schema');
  43. $this->addContextItem('schema', $vocab['url']);
  44. $vocab = tripal_get_vocabulary_details('local');
  45. $this->addContextItem('local', url($vocab['url'], array('absolute' => TRUE)). '/');
  46. $this->data['@id'] = $service_path;
  47. $this->data['@type'] = '';
  48. }
  49. /**
  50. * Adds a term to the '@context' section for this resource.
  51. *
  52. * This function should not be called directory. Rather, the
  53. * addContextTerm() and addContextVocab() functions built
  54. * into the TripalWebService class should be used as these will help
  55. * ensure terms are added proper for the context of the web service.
  56. *
  57. * @param $name
  58. * The term name.
  59. * @param $iri
  60. * The Internationalized Resource Identifiers or it's shortcut.
  61. *
  62. */
  63. public function addContextItem($name, $iri) {
  64. if (array_key_exists($name, $this->context)) {
  65. return;
  66. }
  67. $this->context[$name] = $iri;
  68. }
  69. /**
  70. * Removes a term for the '@context' section for this resource.
  71. *
  72. * @param $name
  73. * The term name.
  74. * @param $iri
  75. * The Internationalized Resource Identifiers or it's shortcut.
  76. */
  77. public function removeContextItem($name, $iri) {
  78. // TODO: make sure that if a shortcut is used that the parent is present.
  79. unset($this->context[$name]);
  80. }
  81. /**
  82. * Sets the resource type.
  83. *
  84. * The type exist in the context of the web service.
  85. *
  86. * @param $type
  87. * The type
  88. */
  89. public function setType($type) {
  90. $this->checkKey($type);
  91. $this->type = $type;
  92. $this->data['@type'] = $type;
  93. }
  94. /**
  95. * Checks a key to ensure it is in the Context before being used.
  96. *
  97. * This function should be used before adding a property or type to this
  98. * resource. It ensures that the key for the property is already in the
  99. * context.
  100. *
  101. * @param $key
  102. * The key to check.
  103. * @throws Exception
  104. */
  105. private function checkKey($key) {
  106. // Make sure the key is already present in the context.
  107. $keys = array_keys($this->context);
  108. // Keys that are full HTML are acceptable
  109. if (preg_match('/^(http|https):\/\/.*/', $key)) {
  110. return;
  111. }
  112. // If the key has a colon separating the vocabulary and the term then we
  113. // just need to make sure that the vocabulary is present.
  114. $matches = array();
  115. if (preg_match('/^(.*?):(.*?)$/', $key, $matches)) {
  116. $vocab = $matches[1];
  117. $accession = $matches[2];
  118. // The underscore represents the blank node. So, these keys are okay.
  119. if ($vocab == '_') {
  120. return;
  121. }
  122. // If the vocabulary is not in the.
  123. if (!in_array($vocab, $keys)) {
  124. throw new Exception("The key, '$key', has a vocabulary that has not yet been added to the " .
  125. "context. Use the addContextItem() function to add the vocabulary prior to adding a value for it.");
  126. }
  127. }
  128. else {
  129. // If the key is not in the context then throw an error.
  130. if (!in_array($key, $keys)) {
  131. throw new Exception("The key, '$key', has not yet been added to the " .
  132. "context. Use the addContextItem() function to add this key prior to adding a value for it.");
  133. }
  134. }
  135. }
  136. /**
  137. * Set's the unique identifier for the resource.
  138. *
  139. * Every resource must have a unique Idientifer. In JSON-LD the '@id' element
  140. * identifies the IRI for the resource which will include the unique
  141. * identifier. The TraiplWebService to which a resource is added will
  142. * build the IRIs but it needs the unique ID of each resource.
  143. *
  144. * @param $id
  145. * The unique identifier for the resource.
  146. */
  147. public function setID($id) {
  148. $this->id = $id;
  149. $this->data['@id'] = $this->getURI($id);
  150. }
  151. /**
  152. * Retreives the IRI for an entity of a given ID in this web service.
  153. *
  154. * @param $id
  155. * The unique identifier for the resource.
  156. */
  157. public function getURI($id) {
  158. // If this is a key/value pair for an id and if the vocab portion is
  159. // an underscore then this represents a blank node and we don't want
  160. // to add the full path.
  161. $matches = array();
  162. if (preg_match('/^(.*?):(.*?)$/', $id, $matches)) {
  163. $vocab = $matches[1];
  164. if ($vocab == '_') {
  165. return $id;
  166. }
  167. return $id;
  168. }
  169. else {
  170. return $this->service_path . '/' . $id;
  171. }
  172. }
  173. /**
  174. * Retrieves the unique identifier for this resource.
  175. *
  176. * Every resource must have a unique Idientifer. In JSON-LD the '@id' element
  177. * identifies the IRI for the resource which will include the unique
  178. * identifier. The TraiplWebService to which a resource is added will
  179. * build the IRIs but it needs the unique ID of each resource.
  180. *
  181. * @return
  182. * The unique identifier for the resource.
  183. */
  184. public function getID() {
  185. return $this->id;
  186. }
  187. /**
  188. * Retreives the type of this resource.
  189. *
  190. * @return
  191. * The name of the resource.
  192. */
  193. public function getType() {
  194. return $this->type;
  195. }
  196. /**
  197. * Adds a new key/value pair to the web serivces response.
  198. *
  199. * The value must either be a scalar or another TripalWebServiceResource
  200. * object. If the same key is usesd multiple times then the resulting
  201. * resource will be presented as an array of elements.
  202. *
  203. * @param unknown $key
  204. * The name of the $key to add. This key must already be present in the
  205. * web service context by first adding it using the addContextItem()
  206. * member function.
  207. * @param unknown $value
  208. * The value of the key which must either be a scalar or a
  209. * TripalWebServiceResource instance.
  210. */
  211. public function addProperty($key, $value) {
  212. $this->checkKey($key);
  213. // If this is a numeric array then go through each element and add them.
  214. if (is_array($value) and count(array_filter(array_keys($value), 'is_int')) == count(array_keys($value))) {
  215. if (!array_key_exists($key, $this->data)) {
  216. $this->data[$key] = array();
  217. }
  218. foreach ($value as $item) {
  219. $this->addProperty($key, $item);
  220. }
  221. return;
  222. }
  223. // If this is a TripalWebServiceResource then get it's data and use that
  224. // as the new value.
  225. if (is_a($value, 'TripalWebServiceResource') or is_subclass_of($value, 'TripalWebServiceResource')) {
  226. // Add in the context items to this resource.
  227. $context = $value->getContext();
  228. foreach ($context as $k => $v) {
  229. $this->addContextItem($k, $v);
  230. }
  231. $value = $value->getData();
  232. }
  233. // If this key doesn't exist then add the value directly to the key.
  234. if (!array_key_exists($key, $this->data)) {
  235. $this->data[$key] = $value;
  236. }
  237. // Else if it does exist then we need to make sure that the element is
  238. // an array and add it.
  239. else {
  240. // If this is the second element, then convert it to an array. The
  241. // second test in the condition below is for for a numeric array.
  242. if (!is_array($this->data[$key]) or count(array_filter(array_keys($this->data[$key]), 'is_string')) > 0) {
  243. $element = $this->data[$key];
  244. $this->data[$key] = array();
  245. $this->data[$key][] = $element;
  246. }
  247. $this->data[$key][] = $value;
  248. }
  249. }
  250. /**
  251. * Retrieves the data section of the resource.
  252. *
  253. * The JSON-LD response constists of two sections the '@context' section
  254. * and the data section. This function only returns the data section
  255. * for this resource
  256. *
  257. * @return
  258. * An associative array containing the data section of the response.
  259. */
  260. public function getData() {
  261. return $this->data;
  262. }
  263. /**
  264. * Retrieves the data section of the resource.
  265. *
  266. * The JSON-LD response constists of two sections the '@context' section
  267. * and the data section. This function only returns the data section
  268. * for this resource
  269. *
  270. * @return
  271. * An associative array containing the data section of the response.
  272. */
  273. public function getContext() {
  274. return $this->context;
  275. }
  276. /**
  277. * Copies the context from a given TripalWebService resource to this
  278. * resource.
  279. *
  280. * @param $resource
  281. */
  282. public function setContext($resource) {
  283. if (!is_a($resource, 'TripalWebServiceResource')) {
  284. throw new Exception("The \$resource argument must be an instance of a TripalWebServiceResource.");
  285. }
  286. $this->context = $resource->getContext();
  287. }
  288. }