|  | @@ -0,0 +1,648 @@
 | 
	
		
			
				|  |  | +<?php
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +class TripalEntityService_v0_1 extends TripalWebService {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  /**
 | 
	
		
			
				|  |  | +   * The human-readable label for this web service.
 | 
	
		
			
				|  |  | +   */
 | 
	
		
			
				|  |  | +  public static $label = 'Content Types';
 | 
	
		
			
				|  |  | +  /**
 | 
	
		
			
				|  |  | +   * A bit of text to describe what this service provides.
 | 
	
		
			
				|  |  | +   */
 | 
	
		
			
				|  |  | +  public static $description = 'Provides acesss to the biological and ' .
 | 
	
		
			
				|  |  | +    'ancilliary data available on this site. Each content type represents ' .
 | 
	
		
			
				|  |  | +    'biological data that is defined in a controlled vocabulary (e.g. ' .
 | 
	
		
			
				|  |  | +    'Sequence Ontology term: gene (SO:0000704)).';
 | 
	
		
			
				|  |  | +  /**
 | 
	
		
			
				|  |  | +   * A machine-readable type for this service. This name must be unique
 | 
	
		
			
				|  |  | +   * among all Tripal web services and is used to form the URL to access
 | 
	
		
			
				|  |  | +   * this service.
 | 
	
		
			
				|  |  | +   */
 | 
	
		
			
				|  |  | +  public static $type = 'content';
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  /**
 | 
	
		
			
				|  |  | +   * Implements the constructor
 | 
	
		
			
				|  |  | +   */
 | 
	
		
			
				|  |  | +  public function __construct($base_path) {
 | 
	
		
			
				|  |  | +    parent::__construct($base_path);
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  /**
 | 
	
		
			
				|  |  | +   * @see TripalWebService::handleRequest()
 | 
	
		
			
				|  |  | +   */
 | 
	
		
			
				|  |  | +  public function handleRequest() {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // Get the content type.
 | 
	
		
			
				|  |  | +    $ctype     = (count($this->path) > 0) ? $this->path[0] : '';
 | 
	
		
			
				|  |  | +    $entity_id = (count($this->path) > 1) ? $this->path[1] : '';
 | 
	
		
			
				|  |  | +    $expfield  = (count($this->path) > 2) ? $this->path[2] : '';
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // If we have a content type then list all of the entities that belong
 | 
	
		
			
				|  |  | +    // to it.
 | 
	
		
			
				|  |  | +    if ($ctype and !$entity_id and !$expfield) {
 | 
	
		
			
				|  |  | +      $this->doContentTypeList($ctype);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    // If we have an entity ID then build the resource for a single entity.
 | 
	
		
			
				|  |  | +    else if ($ctype and $entity_id and !$expfield) {
 | 
	
		
			
				|  |  | +      $this->doEntity($ctype, $entity_id);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    else if ($ctype and $entity_id and $expfield) {
 | 
	
		
			
				|  |  | +      $this->doExpandedField($ctype, $entity_id, $expfield);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    // Otherwise just list all of the available content types.
 | 
	
		
			
				|  |  | +    else {
 | 
	
		
			
				|  |  | +      $this->doAllTypesList();
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  /**
 | 
	
		
			
				|  |  | +   * Creates a resource for an expanded field of an entity.
 | 
	
		
			
				|  |  | +   */
 | 
	
		
			
				|  |  | +  private function doExpandedField($ctype, $entity_id, $expfield) {
 | 
	
		
			
				|  |  | +    $service_path = $this->getServicePath() . '/' . urlencode($ctype) . '/' . $entity_id;
 | 
	
		
			
				|  |  | +    $this->resource = new TripalWebServiceResource($service_path);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // Get the TripalBundle, TripalTerm and TripalVocab for this type.
 | 
	
		
			
				|  |  | +    $bundle = tripal_load_bundle_entity(array('label' => $ctype));
 | 
	
		
			
				|  |  | +    $term = entity_load('TripalTerm', array('id' => $bundle->term_id));
 | 
	
		
			
				|  |  | +    $term = reset($term);
 | 
	
		
			
				|  |  | +    $vocab = $term->vocab;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // Get the TripalEntity
 | 
	
		
			
				|  |  | +    $entity = tripal_load_entity('TripalEntity', array('id' => $entity_id));
 | 
	
		
			
				|  |  | +    $entity = reset($entity);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // If we couldn't match this field argument to a field and entity then return
 | 
	
		
			
				|  |  | +    if (!$entity) {
 | 
	
		
			
				|  |  | +      throw new Exception("Canno find this entity.");
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    list($field, $instance, $term) = $this->findField($bundle, $expfield);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // Next add in the ID and Type for this resources.
 | 
	
		
			
				|  |  | +    $key = $term['name'];
 | 
	
		
			
				|  |  | +    $key_adj = strtolower(preg_replace('/ /', '_', $term['name']));
 | 
	
		
			
				|  |  | +    $this->resource->addContextItem($key_adj, $term['url']);
 | 
	
		
			
				|  |  | +    $this->resource->setID(urlencode($key));
 | 
	
		
			
				|  |  | +    $this->resource->setType($key_adj);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // Attach the field and then add it's values to the response.
 | 
	
		
			
				|  |  | +    field_attach_load($entity->type, array($entity->id => $entity),
 | 
	
		
			
				|  |  | +        FIELD_LOAD_CURRENT, array('field_id' => $field['id']));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    $this->addEntityField($key_adj, $term, $entity, $bundle, $field, $instance, $service_path, $expfield);
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  /**
 | 
	
		
			
				|  |  | +   * Find the field whose term matches the one provied.
 | 
	
		
			
				|  |  | +   */
 | 
	
		
			
				|  |  | +  private function findField($bundle, $expfield) {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    $value = array();
 | 
	
		
			
				|  |  | +    $instances = field_info_instances('TripalEntity', $bundle->name);
 | 
	
		
			
				|  |  | +    foreach ($instances as $instance) {
 | 
	
		
			
				|  |  | +      $field_name = $instance['field_name'];
 | 
	
		
			
				|  |  | +      $field = field_info_field($field_name);
 | 
	
		
			
				|  |  | +      $vocabulary = $instance['settings']['term_vocabulary'];
 | 
	
		
			
				|  |  | +      $accession = $instance['settings']['term_accession'];
 | 
	
		
			
				|  |  | +      $temp_term = tripal_get_term_details($vocabulary, $accession);
 | 
	
		
			
				|  |  | +      if ($temp_term['name'] == $expfield) {
 | 
	
		
			
				|  |  | +        return array($field, $instance, $temp_term);
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  /**
 | 
	
		
			
				|  |  | +   * Creates a resource for a single entity.
 | 
	
		
			
				|  |  | +   */
 | 
	
		
			
				|  |  | +  private function doEntity($ctype, $entity_id) {
 | 
	
		
			
				|  |  | +    $service_path = $this->getServicePath() . '/' . urlencode($ctype);
 | 
	
		
			
				|  |  | +    $this->resource = new TripalWebServiceResource($service_path);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // Get the TripalBundle, TripalTerm and TripalVocab type for this type.
 | 
	
		
			
				|  |  | +    $bundle = tripal_load_bundle_entity(array('label' => $ctype));
 | 
	
		
			
				|  |  | +    $term = entity_load('TripalTerm', array('id' => $bundle->term_id));
 | 
	
		
			
				|  |  | +    $term = reset($term);
 | 
	
		
			
				|  |  | +    $vocab = $term->vocab;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // Add the vocabulary to the context.
 | 
	
		
			
				|  |  | +    $this->resource->addContextItem($term->name, $term->url);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // Get the TripalEntity
 | 
	
		
			
				|  |  | +    $entity = tripal_load_entity('TripalEntity', array('id' => $entity_id));
 | 
	
		
			
				|  |  | +    $entity = reset($entity);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    $itemPage = tripal_get_term_details('schema', 'ItemPage');
 | 
	
		
			
				|  |  | +    $label = tripal_get_term_details('rdfs', 'label');
 | 
	
		
			
				|  |  | +    $this->resource->setID($entity_id);
 | 
	
		
			
				|  |  | +    $this->resource->setType($term->name);
 | 
	
		
			
				|  |  | +    $this->resource->addContextItem('label', $label['url']);
 | 
	
		
			
				|  |  | +    $this->resource->addContextItem('ItemPage', $itemPage['url']);
 | 
	
		
			
				|  |  | +    $this->resource->addProperty('label', $entity->title);
 | 
	
		
			
				|  |  | +    $this->resource->addProperty('ItemPage', url('/bio_data/' . $entity->id, array('absolute' => TRUE)));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    $this->addEntityFields($entity, $bundle, $term, $service_path);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +//    tripal_ws_services_v0_1_get_content_add_fields($entity, $bundle, $api_url, $response, $ws_path, $ctype, $entity_id, $params);
 | 
	
		
			
				|  |  | +//    tripal_ws_services_v0_1_write_context($response, $ctype);
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  /**
 | 
	
		
			
				|  |  | +   * Adds the fields as properties of an entity resource.
 | 
	
		
			
				|  |  | +   */
 | 
	
		
			
				|  |  | +  private function addEntityFields($entity, $bundle, $term, $service_path) {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // If the entity is set to hide fields that have no values then we
 | 
	
		
			
				|  |  | +    // want to honor that in the web services too.
 | 
	
		
			
				|  |  | +    $hide_fields = tripal_get_bundle_variable('hide_empty_field', $bundle->id, 'hide');
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // Get information about the fields attached to this bundle and sort them
 | 
	
		
			
				|  |  | +    // in the order they were set for the display.
 | 
	
		
			
				|  |  | +    $instances = field_info_instances('TripalEntity', $bundle->name);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    uasort($instances, function($a, $b) {
 | 
	
		
			
				|  |  | +      $a_weight = (is_array($a) && isset($a['widget']['weight'])) ? $a['widget']['weight'] : 0;
 | 
	
		
			
				|  |  | +      $b_weight = (is_array($b) && isset($b['widget']['weight'])) ? $b['widget']['weight'] : 0;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      if ($a_weight == $b_weight) {
 | 
	
		
			
				|  |  | +        return 0;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      return ($a_weight < $b_weight) ? -1 : 1;
 | 
	
		
			
				|  |  | +    });
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // Iterate through the fields and add each value to the response.
 | 
	
		
			
				|  |  | +    //$response['fields'] = $fields;
 | 
	
		
			
				|  |  | +    foreach ($instances as $field_name => $instance) {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      // Skip hidden fields.
 | 
	
		
			
				|  |  | +      if ($instance['display']['default']['type'] == 'hidden') {
 | 
	
		
			
				|  |  | +        continue;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      // Get the information about this field.
 | 
	
		
			
				|  |  | +      $field = field_info_field($field_name);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      // By default, the label for the key in the output should be the
 | 
	
		
			
				|  |  | +      // term from the vocabulary that the field is assigned. But in the
 | 
	
		
			
				|  |  | +      // case that the field is not assigned a term, we must use the field name.
 | 
	
		
			
				|  |  | +      $field_name = $instance['field_name'];
 | 
	
		
			
				|  |  | +      $vocabulary = $instance['settings']['term_vocabulary'];
 | 
	
		
			
				|  |  | +      $accession = $instance['settings']['term_accession'];
 | 
	
		
			
				|  |  | +      $term = tripal_get_term_details($vocabulary, $accession);
 | 
	
		
			
				|  |  | +      if (!$term) {
 | 
	
		
			
				|  |  | +        continue;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      $key = $term['name'];
 | 
	
		
			
				|  |  | +      $key_adj = strtolower(preg_replace('/ /', '_', $key));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      // If this field should not be attached by default then just add a link
 | 
	
		
			
				|  |  | +      // so that the caller can get the information separately.
 | 
	
		
			
				|  |  | +      $instance_settings = $instance['settings'];
 | 
	
		
			
				|  |  | +      if (array_key_exists('auto_attach', $instance['settings']) and
 | 
	
		
			
				|  |  | +          $instance_settings['auto_attach'] == FALSE) {
 | 
	
		
			
				|  |  | +        // Add a URL only if there are values. If there are no values then
 | 
	
		
			
				|  |  | +        // don't add a URL which would make the end-user think they can get
 | 
	
		
			
				|  |  | +        // that information.
 | 
	
		
			
				|  |  | +        $items = field_get_items('TripalEntity', $entity, $field_name);
 | 
	
		
			
				|  |  | +        if ($items and count($items) > 0 and $items[0]['value']) {
 | 
	
		
			
				|  |  | +          $this->resource->addContextItem($key_adj, $term['url']);
 | 
	
		
			
				|  |  | +          $this->resource->addProperty($key_adj, $service_path . '/' . $entity->id . '/' . urlencode($term['name']));
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        else {
 | 
	
		
			
				|  |  | +          if ($hide_fields == 'show') {
 | 
	
		
			
				|  |  | +            $this->resource->addContextItem($key_adj, $term['url']);
 | 
	
		
			
				|  |  | +            $this->resource->addProperty($key_adj, NULL);
 | 
	
		
			
				|  |  | +          }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        continue;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      // Get the details for this field for the JSON-LD response.
 | 
	
		
			
				|  |  | +      $this->addEntityField($key_adj, $term, $entity, $bundle, $field, $instance, $service_path);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  /**
 | 
	
		
			
				|  |  | +   * Adds the field as a property of the entity resource.
 | 
	
		
			
				|  |  | +   */
 | 
	
		
			
				|  |  | +  private function addEntityField($key, $term, $entity, $bundle, $field, $instance,
 | 
	
		
			
				|  |  | +      $service_path, $expfield = NULL) {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // If the entity is set to hide fields that have no values then we
 | 
	
		
			
				|  |  | +    // want to honor that in the web services too.
 | 
	
		
			
				|  |  | +    $hide_fields = tripal_get_bundle_variable('hide_empty_field', $bundle->id, 'hide');
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // Get the field  settings.
 | 
	
		
			
				|  |  | +    $field_name = $field['field_name'];
 | 
	
		
			
				|  |  | +    $field_settings = $field['settings'];
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    $items = field_get_items('TripalEntity', $entity, $field_name);
 | 
	
		
			
				|  |  | +    if (!$items) {
 | 
	
		
			
				|  |  | +      return;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // Give modules the opportunity to edit values for web services. This hook
 | 
	
		
			
				|  |  | +    // really should be used sparingly. Where it helps is with non Tripal fields
 | 
	
		
			
				|  |  | +    // that are added to a TripalEntity content type and it doesn't follow
 | 
	
		
			
				|  |  | +    // the rules (e.g. Image field).
 | 
	
		
			
				|  |  | +    drupal_alter('tripal_ws_value', $items, $field, $instance);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    $values = array();
 | 
	
		
			
				|  |  | +    for ($i = 0; $i < count($items); $i++) {
 | 
	
		
			
				|  |  | +      $values[$i] = $this->sanitizeFieldKeys($items[$i]['value'], $bundle, $service_path);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if ($hide_fields == 'hide' and empty($values[0])) {
 | 
	
		
			
				|  |  | +      return;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // If the field cardinality is 1
 | 
	
		
			
				|  |  | +    if ($field['cardinality'] == 1) {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      // If the value is an array and this is the field page then all of those
 | 
	
		
			
				|  |  | +      // key/value pairs should be added directly to the response.
 | 
	
		
			
				|  |  | +      if (is_array($values[0])) {
 | 
	
		
			
				|  |  | +        if ($expfield) {
 | 
	
		
			
				|  |  | +          foreach ($values[0] as $k => $v) {
 | 
	
		
			
				|  |  | +            $this->resource->addProperty($k, $v);
 | 
	
		
			
				|  |  | +          }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        else {
 | 
	
		
			
				|  |  | +          $this->resource->addContextItem($key, $term['url']);
 | 
	
		
			
				|  |  | +          $this->resource->addProperty($key, $values[0]);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      // If the value is not an array it's a scalar so add it as is to the
 | 
	
		
			
				|  |  | +      // response.
 | 
	
		
			
				|  |  | +      else {
 | 
	
		
			
				|  |  | +        $this->resource->addContextItem($key, $term['url']);
 | 
	
		
			
				|  |  | +        $this->resource->addProperty($key, $values[0]);
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // If the field cardinality is > 1
 | 
	
		
			
				|  |  | +    if ($field['cardinality'] != 1) {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      // If this is the expanded field page then we need to swap out
 | 
	
		
			
				|  |  | +      // the resource for a collection.
 | 
	
		
			
				|  |  | +      $response = new TripalWebServiceCollection($service_path . '/' . urlencode($expfield));
 | 
	
		
			
				|  |  | +      $label = tripal_get_term_details('rdfs', 'label');
 | 
	
		
			
				|  |  | +      $response->addContextItem('label', $label['url']);
 | 
	
		
			
				|  |  | +      $response->addProperty('label', $instance['label']);
 | 
	
		
			
				|  |  | +      $i = 0;
 | 
	
		
			
				|  |  | +      foreach ($values as $delta => $element) {
 | 
	
		
			
				|  |  | +        $member = new TripalWebServiceResource($service_path . '/' . urlencode($expfield));
 | 
	
		
			
				|  |  | +        $member->setID($i);
 | 
	
		
			
				|  |  | +        // Add the context of the parent resource because all of the keys
 | 
	
		
			
				|  |  | +        // were santizied and set to match the proper context.
 | 
	
		
			
				|  |  | +        $member->setContext($this->resource);
 | 
	
		
			
				|  |  | +        $member->setType($key);
 | 
	
		
			
				|  |  | +        foreach ($element as $key => $value) {
 | 
	
		
			
				|  |  | +          $member->addProperty($key, $value);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        $response->addMember($member);
 | 
	
		
			
				|  |  | +        $i++;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      if ($expfield) {
 | 
	
		
			
				|  |  | +        $this->resource = $response;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      else {
 | 
	
		
			
				|  |  | +        $this->resource->addProperty($key, $response);
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  /**
 | 
	
		
			
				|  |  | +   * Rewrites the keys of a field's items array for use with web services.
 | 
	
		
			
				|  |  | +   */
 | 
	
		
			
				|  |  | +  private function sanitizeFieldKeys($value, $bundle, $service_path) {
 | 
	
		
			
				|  |  | +    // If the entity is set to hide fields that have no values then we
 | 
	
		
			
				|  |  | +    // want to honor that in the web services too.
 | 
	
		
			
				|  |  | +    $hide_fields = tripal_get_bundle_variable('hide_empty_field', $bundle->id, 'hide');
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    $new_value = '';
 | 
	
		
			
				|  |  | +    // If the value is an array rather than a scalar then map the sub elements
 | 
	
		
			
				|  |  | +    // to controlled vocabulary terms.
 | 
	
		
			
				|  |  | +    if (is_array($value)) {
 | 
	
		
			
				|  |  | +      $temp = array();
 | 
	
		
			
				|  |  | +      foreach ($value as $k => $v) {
 | 
	
		
			
				|  |  | +        // exclude fields that have no values so we can hide them
 | 
	
		
			
				|  |  | +        if (empty($v) and $hide_fields == 'hide') {
 | 
	
		
			
				|  |  | +          continue;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        $matches = array();
 | 
	
		
			
				|  |  | +        if (preg_match('/^(.+):(.+)$/', $k, $matches)) {
 | 
	
		
			
				|  |  | +          $vocabulary = $matches[1];
 | 
	
		
			
				|  |  | +          $accession = $matches[2];
 | 
	
		
			
				|  |  | +          $term = tripal_get_term_details($vocabulary, $accession);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +          $key_adj = strtolower(preg_replace('/ /', '_', $term['name']));
 | 
	
		
			
				|  |  | +          if (is_array($v)) {
 | 
	
		
			
				|  |  | +            $temp[$key_adj] = $this->sanitizeFieldKeys($v, $bundle, $service_path);
 | 
	
		
			
				|  |  | +          }
 | 
	
		
			
				|  |  | +          else {
 | 
	
		
			
				|  |  | +            $temp[$key_adj] = $v !== "" ? $v : NULL;
 | 
	
		
			
				|  |  | +          }
 | 
	
		
			
				|  |  | +          $this->resource->addContextItem($key_adj, $term['url']);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        else {
 | 
	
		
			
				|  |  | +          // TODO: this is an error, if we get here then we have
 | 
	
		
			
				|  |  | +          // a key that isn't using the proper format... what to do?
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      $new_value = $temp;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      // Recurse through the values array and set the entity elements
 | 
	
		
			
				|  |  | +      // and add the fields to the context.
 | 
	
		
			
				|  |  | +      $this->sanitizeFieldEntity($new_value, $service_path);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    else {
 | 
	
		
			
				|  |  | +      $new_value = $value !== "" ? $value : NULL;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    return $new_value;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  /**
 | 
	
		
			
				|  |  | +   * Rewrites any TripalEntity elements in the values array for use with WS.
 | 
	
		
			
				|  |  | +   */
 | 
	
		
			
				|  |  | +  private function sanitizeFieldEntity(&$items, $service_path) {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if (!$items) {
 | 
	
		
			
				|  |  | +      return;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    foreach ($items as $key => $value) {
 | 
	
		
			
				|  |  | +      if (is_array($value)) {
 | 
	
		
			
				|  |  | +        $this->sanitizeFieldEntity($items[$key], $service_path);
 | 
	
		
			
				|  |  | +        continue;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      if ($key == 'entity') {
 | 
	
		
			
				|  |  | +        list($item_etype, $item_eid) = explode(':', $items['entity']);
 | 
	
		
			
				|  |  | +        if ($item_eid) {
 | 
	
		
			
				|  |  | +          $item_entity = tripal_load_entity($item_etype, array($item_eid));
 | 
	
		
			
				|  |  | +          $item_entity = reset($item_entity);
 | 
	
		
			
				|  |  | +          $bundle = tripal_load_bundle_entity(array('name' => $item_entity->bundle));
 | 
	
		
			
				|  |  | +          $items['@id'] = $this->getServicePath() . '/' . urlencode($bundle->label) . '/' . $item_eid;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        unset($items['entity']);
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  /**
 | 
	
		
			
				|  |  | +   * Creates a collection of resources for a given type.
 | 
	
		
			
				|  |  | +   */
 | 
	
		
			
				|  |  | +  private function doContentTypeList($ctype) {
 | 
	
		
			
				|  |  | +    $service_path = $this->getServicePath() . '/' . urlencode($ctype);
 | 
	
		
			
				|  |  | +    $label = tripal_get_term_details('rdfs', 'label');
 | 
	
		
			
				|  |  | +    $this->resource = new TripalWebServiceCollection($service_path);
 | 
	
		
			
				|  |  | +    $this->resource->addContextItem('label', $label['url']);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // Get the TripalBundle, TripalTerm and TripalVocab type for this type.
 | 
	
		
			
				|  |  | +    $bundle = tripal_load_bundle_entity(array('label' => $ctype));
 | 
	
		
			
				|  |  | +    $term = entity_load('TripalTerm', array('id' => $bundle->term_id));
 | 
	
		
			
				|  |  | +    $term = reset($term);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // Set the label for this collection.
 | 
	
		
			
				|  |  | +    $this->resource->addProperty('label', $bundle->label . " collection");
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // Iterate through the fields and create a $field_mapping array that makes
 | 
	
		
			
				|  |  | +    // it easier to determine which filter criteria belongs to which field. The
 | 
	
		
			
				|  |  | +    // key is the label for the field and the value is the field name. This way
 | 
	
		
			
				|  |  | +    // user's can use the field label or the field name to form a query.
 | 
	
		
			
				|  |  | +    $field_mapping = array();
 | 
	
		
			
				|  |  | +    $fields = field_info_fields();
 | 
	
		
			
				|  |  | +    foreach ($fields as $field) {
 | 
	
		
			
				|  |  | +      if (array_key_exists('TripalEntity', $field['bundles'])) {
 | 
	
		
			
				|  |  | +        foreach ($field['bundles']['TripalEntity'] as $bundle_name) {
 | 
	
		
			
				|  |  | +          if ($bundle_name == $bundle->name) {
 | 
	
		
			
				|  |  | +            $instance = field_info_instance('TripalEntity', $field['field_name'], $bundle_name);
 | 
	
		
			
				|  |  | +            if (array_key_exists('term_accession', $instance['settings'])){
 | 
	
		
			
				|  |  | +              $vocabulary = $instance['settings']['term_vocabulary'];
 | 
	
		
			
				|  |  | +              $accession = $instance['settings']['term_accession'];
 | 
	
		
			
				|  |  | +              $fterm = tripal_get_term_details($vocabulary, $accession);
 | 
	
		
			
				|  |  | +              $key = $fterm['name'];
 | 
	
		
			
				|  |  | +              $key = strtolower(preg_replace('/ /', '_', $key));
 | 
	
		
			
				|  |  | +              $field_mapping[$key] = $field['field_name'];
 | 
	
		
			
				|  |  | +              $field_mapping[$field['field_name']] = $field['field_name'];
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +          }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // Convert the filters to their field names
 | 
	
		
			
				|  |  | +    $new_params = array();
 | 
	
		
			
				|  |  | +    $order = array();
 | 
	
		
			
				|  |  | +    $order_dir = array();
 | 
	
		
			
				|  |  | +    $URL_add = array();
 | 
	
		
			
				|  |  | +    foreach ($this->params as $param => $value) {
 | 
	
		
			
				|  |  | +      $URL_add[] = "$param=$value";
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      // Ignore non filter parameters
 | 
	
		
			
				|  |  | +      if ($param == 'page' or $param == 'limit') {
 | 
	
		
			
				|  |  | +        continue;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      // Handle order separately
 | 
	
		
			
				|  |  | +      if ($param == 'order') {
 | 
	
		
			
				|  |  | +        $temp = explode(',', $value);
 | 
	
		
			
				|  |  | +        foreach ($temp as $key) {
 | 
	
		
			
				|  |  | +          $matches = array();
 | 
	
		
			
				|  |  | +          $dir = 'ASC';
 | 
	
		
			
				|  |  | +          // The user can provide a direction by separating the field key and the
 | 
	
		
			
				|  |  | +          // direction with a '|' character.
 | 
	
		
			
				|  |  | +          if (preg_match('/^(.*)\|(.*)$/', $key, $matches)) {
 | 
	
		
			
				|  |  | +            $key = $matches[1];
 | 
	
		
			
				|  |  | +            if ($matches[2] == 'ASC' or $matches[2] == 'DESC') {
 | 
	
		
			
				|  |  | +              $dir = $matches[2];
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            else {
 | 
	
		
			
				|  |  | +              // TODO: handle error of providing an incorrect direction.
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +          }
 | 
	
		
			
				|  |  | +          if (array_key_exists($key, $field_mapping)) {
 | 
	
		
			
				|  |  | +            $order[$field_mapping[$key]] = $key;
 | 
	
		
			
				|  |  | +            $order_dir[] = $dir;
 | 
	
		
			
				|  |  | +          }
 | 
	
		
			
				|  |  | +          else {
 | 
	
		
			
				|  |  | +            // TODO: handle error of providing a non existing field name.
 | 
	
		
			
				|  |  | +          }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        continue;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      // Break apart any operators
 | 
	
		
			
				|  |  | +      $key = $param;
 | 
	
		
			
				|  |  | +      $op = '=';
 | 
	
		
			
				|  |  | +      $matches = array();
 | 
	
		
			
				|  |  | +      if (preg_match('/^(.+);(.+)$/', $key, $matches)) {
 | 
	
		
			
				|  |  | +        $key = $matches[1];
 | 
	
		
			
				|  |  | +        $op = $matches[2];
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      // Break apart any subkeys and pull the first one out for the term name key.
 | 
	
		
			
				|  |  | +      $subkeys = explode(',', $key);
 | 
	
		
			
				|  |  | +      if (count($subkeys) > 0) {
 | 
	
		
			
				|  |  | +        $key = array_shift($subkeys);
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      $column_name = $key;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      // Map the values in the filters to their appropriate field names.
 | 
	
		
			
				|  |  | +      if (array_key_exists($key, $field_mapping)) {
 | 
	
		
			
				|  |  | +        $field_name = $field_mapping[$key];
 | 
	
		
			
				|  |  | +        if (count($subkeys) > 0) {
 | 
	
		
			
				|  |  | +          $column_name .= '.' . implode('.', $subkeys);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        $new_params[$field_name]['value'] = $value;
 | 
	
		
			
				|  |  | +        $new_params[$field_name]['op'] = $op;
 | 
	
		
			
				|  |  | +        $new_params[$field_name]['column'] = $column_name;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      else {
 | 
	
		
			
				|  |  | +        throw new Exception("The filter term, '$key', is not available for use.");
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // Get the list of entities for this bundle.
 | 
	
		
			
				|  |  | +    $query = new TripalFieldQuery();
 | 
	
		
			
				|  |  | +    $query->entityCondition('entity_type', 'TripalEntity');
 | 
	
		
			
				|  |  | +    $query->entityCondition('bundle', $bundle->name);
 | 
	
		
			
				|  |  | +    foreach($new_params as $field_name => $details) {
 | 
	
		
			
				|  |  | +      $value = $details['value'];
 | 
	
		
			
				|  |  | +      $column_name = $details['column'];
 | 
	
		
			
				|  |  | +      switch ($details['op']) {
 | 
	
		
			
				|  |  | +        case 'eq':
 | 
	
		
			
				|  |  | +          $op = '=';
 | 
	
		
			
				|  |  | +          break;
 | 
	
		
			
				|  |  | +        case 'gt':
 | 
	
		
			
				|  |  | +          $op = '>';
 | 
	
		
			
				|  |  | +          break;
 | 
	
		
			
				|  |  | +        case 'gte':
 | 
	
		
			
				|  |  | +          $op = '>=';
 | 
	
		
			
				|  |  | +          break;
 | 
	
		
			
				|  |  | +        case 'lt':
 | 
	
		
			
				|  |  | +          $op = '<';
 | 
	
		
			
				|  |  | +          break;
 | 
	
		
			
				|  |  | +        case 'lte':
 | 
	
		
			
				|  |  | +          $op = '<=';
 | 
	
		
			
				|  |  | +          break;
 | 
	
		
			
				|  |  | +        case 'ne':
 | 
	
		
			
				|  |  | +          $op = '<>';
 | 
	
		
			
				|  |  | +          break;
 | 
	
		
			
				|  |  | +        case 'contains':
 | 
	
		
			
				|  |  | +          $op = 'CONTAINS';
 | 
	
		
			
				|  |  | +          break;
 | 
	
		
			
				|  |  | +        case 'starts':
 | 
	
		
			
				|  |  | +          $op = 'STARTS WITH';
 | 
	
		
			
				|  |  | +          break;
 | 
	
		
			
				|  |  | +        default:
 | 
	
		
			
				|  |  | +          $op = '=';
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      // We pass in the $column_name as an identifier for any sub fields
 | 
	
		
			
				|  |  | +      // that are present for the fields.
 | 
	
		
			
				|  |  | +      $query->fieldCondition($field_name, $column_name, $value, $op);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // Perform the query just as a count first to get the number of records.
 | 
	
		
			
				|  |  | +    $cquery = clone $query;
 | 
	
		
			
				|  |  | +    $cquery->count();
 | 
	
		
			
				|  |  | +    $num_records = $cquery->execute();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if (!$num_records) {
 | 
	
		
			
				|  |  | +      $num_records = 0;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // Add in the pager to the response.
 | 
	
		
			
				|  |  | +    $response['totalItems'] = $num_records;
 | 
	
		
			
				|  |  | +    $limit = array_key_exists('limit', $this->params) ? $this->params['limit'] : 25;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    $total_pages = ceil($num_records / $limit);
 | 
	
		
			
				|  |  | +    $page = array_key_exists('page', $this->params) ? $this->params['page'] : 1;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // Set the query order
 | 
	
		
			
				|  |  | +    $order_keys = array_keys($order);
 | 
	
		
			
				|  |  | +    for($i = 0; $i < count($order_keys); $i++) {
 | 
	
		
			
				|  |  | +      $query->fieldOrderBy($order_keys[$i], $order[$order_keys[$i]], $order_dir[$i]);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // Set the query range
 | 
	
		
			
				|  |  | +    $start = ($page - 1) * $limit;
 | 
	
		
			
				|  |  | +    $query->range($start, $limit);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // Now perform the query.
 | 
	
		
			
				|  |  | +    $results = $query->execute();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    $this->resource->initPager($num_records, $limit, $page);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // Iterate through the entities and add them to the list.
 | 
	
		
			
				|  |  | +    foreach ($results['TripalEntity'] as $entity_id => $stub) {
 | 
	
		
			
				|  |  | +      // We don't need all of the attached fields for an entity so, we'll
 | 
	
		
			
				|  |  | +      // not use the entity_load() function.  Instead just pull it from the
 | 
	
		
			
				|  |  | +      // database table.
 | 
	
		
			
				|  |  | +      $query = db_select('tripal_entity', 'TE');
 | 
	
		
			
				|  |  | +      $query->join('tripal_term', 'TT', 'TE.term_id = TT.id');
 | 
	
		
			
				|  |  | +      $query->fields('TE');
 | 
	
		
			
				|  |  | +      $query->fields('TT', array('name'));
 | 
	
		
			
				|  |  | +      $query->condition('TE.id', $entity_id);
 | 
	
		
			
				|  |  | +      $entity = $query->execute()->fetchObject();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      $itemPage = tripal_get_term_details('schema', 'ItemPage');
 | 
	
		
			
				|  |  | +      $label = tripal_get_term_details('rdfs', 'label');
 | 
	
		
			
				|  |  | +      $member = new TripalWebServiceResource($service_path);
 | 
	
		
			
				|  |  | +      $member->addContextItem('label', $label['url']);
 | 
	
		
			
				|  |  | +      $member->addContextItem('ItemPage', $itemPage['url']);
 | 
	
		
			
				|  |  | +      $member->addContextItem($term->name, $term->url);
 | 
	
		
			
				|  |  | +      $member->setID($entity->id);
 | 
	
		
			
				|  |  | +      $member->setType($term->name);
 | 
	
		
			
				|  |  | +      $member->addProperty('label', $entity->title);
 | 
	
		
			
				|  |  | +      $member->addProperty('ItemPage', url('/bio_data/' . $entity->id, array('absolute' => TRUE)));
 | 
	
		
			
				|  |  | +      $this->resource->addMember($member);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  /**
 | 
	
		
			
				|  |  | +   * Creates a resources that contains the list of content types.
 | 
	
		
			
				|  |  | +   */
 | 
	
		
			
				|  |  | +  private function doAllTypesList() {
 | 
	
		
			
				|  |  | +    $service_path = $this->getServicePath();
 | 
	
		
			
				|  |  | +    $label = tripal_get_term_details('rdfs', 'label');
 | 
	
		
			
				|  |  | +    $this->resource = new TripalWebServiceCollection($service_path);
 | 
	
		
			
				|  |  | +    $this->resource->addContextItem('label', $label['url']);
 | 
	
		
			
				|  |  | +    $this->resource->addProperty('label', 'Content Types');
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // Get the list of published terms (these are the bundle IDs)
 | 
	
		
			
				|  |  | +    $bundles = db_select('tripal_bundle', 'tb')
 | 
	
		
			
				|  |  | +      ->fields('tb')
 | 
	
		
			
				|  |  | +      ->orderBy('tb.label', 'ASC')
 | 
	
		
			
				|  |  | +      ->execute();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // Iterate through the terms and add an entry in the collection.
 | 
	
		
			
				|  |  | +    $i = 0;
 | 
	
		
			
				|  |  | +    while ($bundle = $bundles->fetchObject()) {
 | 
	
		
			
				|  |  | +      $entity =  entity_load('TripalTerm', array('id' => $bundle->term_id));
 | 
	
		
			
				|  |  | +      $term = reset($entity);
 | 
	
		
			
				|  |  | +      $vocab = $term->vocab;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      // Get the bundle description. If no description is provided then
 | 
	
		
			
				|  |  | +      // use the term definition
 | 
	
		
			
				|  |  | +      $description = tripal_get_bundle_variable('description', $bundle->id);
 | 
	
		
			
				|  |  | +      if (!$description) {
 | 
	
		
			
				|  |  | +        $description = $term->definition;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      $member = new TripalWebServiceResource($service_path);
 | 
	
		
			
				|  |  | +      $member->addContextItem($term->name, $term->url);
 | 
	
		
			
				|  |  | +      $member->addContextItem('label', $label['url']);
 | 
	
		
			
				|  |  | +      $member->addContextItem('description', 'hydra:description');
 | 
	
		
			
				|  |  | +      $member->setID(urlencode($bundle->label));
 | 
	
		
			
				|  |  | +      $member->setType($term->name);
 | 
	
		
			
				|  |  | +      $member->addProperty('label', $bundle->label);
 | 
	
		
			
				|  |  | +      $member->addProperty('description', $description);
 | 
	
		
			
				|  |  | +      $this->resource->addMember($member);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +}
 |