| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378 | <?phpclass TripalWebServiceResource {  /**   * The unique identifier for this resource.   */  protected $id;  /**   * The unique type of resource.  The type must exists in the   * context for the web service.   */  protected $type;  /**   * The JSON-LD compatible context for this resource.   */  protected $context;  /**   * Holds the data portion of the JSON-LD response for this resource.   */  protected $data;  /**   * The URL path that the service is providing to access this resource.   * This path plus the $id are concatenated to form the IRI for this resource.   */  protected $service_path;  /**   * Implements the constructor.   *   * @param  $service_path   *   */  public function __construct($service_path) {    $this->context = array();    $this->data = array();    $this->service_path = $service_path;    // First, add the RDFS and Hydra vocabularies to the context.  All Tripal    // web services should use these.    $vocab = tripal_get_vocabulary_details('rdf');    $this->addContextItem('rdf', $this->cleanVocabURL($vocab));    $vocab = tripal_get_vocabulary_details('rdfs');    $this->addContextItem('rdfs', $this->cleanVocabURL($vocab));    $vocab = tripal_get_vocabulary_details('hydra');    $url = $this->cleanVocabURL($vocab);    // $remove the '#' from the end of the URL as the HydraConsole automatically    // wants to add it.    //$url = preg_replace('/#/', '', $url);    $this->addContextItem('hydra', $url);    $vocab = tripal_get_vocabulary_details('dc');    $this->addContextItem('dc', $this->cleanVocabURL($vocab));    $vocab = tripal_get_vocabulary_details('schema');    $this->addContextItem('schema', $this->cleanVocabURL($vocab));    $vocab = tripal_get_vocabulary_details('local');    $this->addContextItem('local', url($vocab['urlprefix'], array('absolute' => TRUE)). '/');    $this->data['@id'] = $service_path;    $this->data['@type'] = '';  }  /**   * A helper function to remove the {db} and {accession} from the URL prefix.   */  private function cleanVocabURL($vocab) {    $url = $vocab['urlprefix'];    $url = preg_replace('/{db}:{accession}/', '', $url);    $url = preg_replace('/{db}/', '', $url);    $url = preg_replace('/{accession}/', '', $url);    return $url;  }  /**   * Adds a term to the '@context' section for this resource.   *   * This function should not be called directory.  Rather, the   * addContextTerm() and addContextVocab() functions built   * into the TripalWebService class should be used as  these  will help   * ensure terms are added proper for the context of the web service.   *   * @param $name   *   The term name.   * @param $iri   *   The Internationalized Resource Identifiers or it's shortcut.   *   */  public function addContextItem($name, $iri) {    if (array_key_exists($name, $this->context)) {      return;    }    $this->context[$name] = $iri;  }  /**   * Removes a term for the '@context' section for this resource.   *   * @param $name   *   The term name.   * @param $iri   *   The Internationalized Resource Identifiers or it's shortcut.   */  public function removeContextItem($name, $iri) {    // TODO: make sure that if a shortcut is used that the parent is present.    unset($this->context[$name]);  }  /**   * Sets the resource type.   *   * The type exist in the context of the web service.   *   * @param $type   *   The type   */  public function setType($type) {    $this->checkKey($type);    $this->type = $type;    $this->data['@type'] = $type;  }  /**   * Checks a key to ensure it is in the Context before being used.   *   * This function should be used before adding a property or type to this   * resource.  It ensures that the key for the property is already in the   * context.   *   * @param $key   *   The key to check.   * @throws Exception   */  private function checkKey($key) {    // Make sure the key is already present in the context.    $keys = array_keys($this->context);    // Keys that are full HTML are acceptable    if (preg_match('/^(http|https):\/\/.*/', $key)) {      return;    }    // If the key has a colon separating the vocabulary and the term then we    // just need to make sure that the vocabulary is present.    $matches = array();    if (preg_match('/^(.*?):(.*?)$/', $key, $matches)) {      $vocab = $matches[1];      $accession = $matches[2];      // The underscore represents the blank node. So, these keys are okay.      if ($vocab == '_') {        return;      }      // If the vocabulary is not in the.      if (!in_array($vocab, $keys)) {        throw new Exception("The key, '$key', has a vocabulary that has not yet been added to the " .            "context. Use the addContextItem() function to add the vocabulary prior to adding a value for it.");      }    }    else {      // If the key is not in the context then throw an error.      if (!in_array($key, $keys)) {        throw new Exception("The key, '$key', has not yet been added to the " .            "context. Use the addContextItem() function to add this key prior to adding a value for it.");      }    }  }  /**   * Checks the value to make sure there are no problems with.   *   * Will also expand any TriaplWebServiceResource by adding their   * context to this resource and substitute their data in place of the   * value.   *   * @param $value   *   */  private function checkValue(&$value) {    if (is_array($value)) {      foreach ($value as $i => $v) {        $this->checkValue($value[$i]);      }    }    else {      // If this is a TripalWebServiceResource then get it's data and use that      // as the new value.  Also, add in the elements context to this resource.      if (is_a($value, 'TripalWebServiceResource') or is_subclass_of($value, 'TripalWebServiceResource')) {        $context = $value->getContext();        foreach ($context as $k => $v) {          $this->addContextItem($k, $v);        }        $value = $value->getData();      }    }  }  /**   * Set's the unique identifier for the resource.   *   * Every resource must have a unique Idientifer. In JSON-LD the '@id' element   * identifies the IRI for the resource which will include the unique   * identifier.  The TraiplWebService to which a resource is added will   * build the IRIs but it needs the unique ID of each resource.   *   * @param $id   *   The unique identifier for the resource.   */  public function setID($id) {    $this->id = $id;    $this->data['@id'] = $this->getURI($id);  }  /**   * Retreives the IRI for an entity of a given ID in this web service.   *   * @param $id   *   The unique identifier for the resource.   */  public function getURI($id) {    // If this is a key/value pair for an id and if the vocab portion is    // an underscore then this represents a blank node and we don't want    // to add the full path.    $matches = array();    if (preg_match('/^(.*?):(.*?)$/', $id, $matches)) {      $vocab = $matches[1];      if ($vocab == '_') {        return $id;      }      return $id;    }    else {      return $this->service_path . '/' . $id;    }  }  /**   * Retrieves the unique identifier for this resource.   *   * Every resource must have a unique Idientifer. In JSON-LD the '@id' element   * identifies the IRI for the resource which will include the unique   * identifier.  The TraiplWebService to which a resource is added will   * build the IRIs but it needs the unique ID of each resource.   *   * @return   *   The unique identifier for the resource.   */  public function getID() {    return $this->id;  }  /**   * Retreives the type of this resource.   *   * @return   *   The name of the resource.   */  public function getType() {    return $this->type;  }  /**   * Adds a new key/value pair to the web serivces response.   *   * The value must either be a scalar or another TripalWebServiceResource   * object.  If the same key is usesd multiple times then the resulting   * resource will be presented as an array of elements.   *   * @param unknown $key   *   The name of the $key to add. This key must already be present in the   *   web service context by first adding it using the addContextItem()   *   member function.   * @param unknown $value   *   The value of the key which must either be a scalar or a   *   TripalWebServiceResource instance.   */  public function addProperty($key, $value) {    $this->checkKey($key);    $this->checkValue($value);    // If this is a numeric keyed array then add each item.    if (is_array($value) and count(array_filter(array_keys($value), 'is_int')) == count(array_keys($value))) {      if (!array_key_exists($key, $this->data)) {        $this->data[$key] = array();      }      foreach ($value as $item) {        $this->addProperty($key, $item);      }      return;    }    // If this key doesn't exist then add the value directly to the key.    if (!array_key_exists($key, $this->data)) {      $this->data[$key] = $value;    }    // Else if it does exist then we need to make sure that the element is    // an array and add it.    else {      // If this is the second element, then convert it to an array.  The      // second test in the condition below is for for a numeric array.      if (!is_array($this->data[$key]) or count(array_filter(array_keys($this->data[$key]), 'is_string')) > 0) {        $element = $this->data[$key];        $this->data[$key] = array();        $this->data[$key][] = $element;      }      $this->data[$key][] = $value;    }  }  /**   * Retrieves the value of a property.   *   * @param $key   *   The name of the property.   *   * @param   *   The value of the property. This could be a scalar, array or   *   a TripalWebService object.   */  function getProperty($key) {    return $this->data[$key];  }  /**   * Retrieves the data section of the resource.   *   * The JSON-LD response constists of two sections the '@context' section   * and the data section.  This function only returns the data section   * for this resource   *   * @return   *   An associative array containing the data section of the response.   */  public function getData() {    return $this->data;  }  /**   * Retrieves the data section of the resource.   *   * The JSON-LD response constists of two sections the '@context' section   * and the data section.  This function only returns the data section   * for this resource   *   * @return   *   An associative array containing the data section of the response.   */  public function getContext() {      return $this->context;  }  /**   * Copies the context from a given TripalWebService resource to this   * resource.   *   * @param $resource   */  public function setContext($resource) {    if (!is_a($resource, 'TripalWebServiceResource')) {      throw new Exception("The \$resource argument must be an instance of a TripalWebServiceResource.");    }    $this->context = $resource->getContext();  }}
 |