'SBO', // The name of the term. 'term_name' => 'Relationship', // The unique ID (i.e. accession) of the term. 'term_accession' => '0000374', // Set to TRUE if the site admin is allowed to change the term // type. This will create form elements when editing the field instance // to allow the site admin to change the term settings above. 'term_fixed' => FALSE, ); // The default widget for this field. public static $default_widget = 'sbo__relationship_widget'; // The default formatter for this field. public static $default_formatter = 'sbo__relationship_formatter'; // -------------------------------------------------------------------------- // PROTECTED CLASS MEMBERS -- DO NOT OVERRIDE // -------------------------------------------------------------------------- // An array containing details about the field. The format of this array // is the same as that returned by field_info_fields() protected $field; // An array containing details about an instance of the field. A field does // not have to have an instance. But if dealing with an instance (such as // when using the widgetForm, formatterSettingsForm, etc.) it should be set. protected $instance; /** * * @see TripalField::load() */ public function load($entity, $details = array()) { $settings = $this->field['settings']; $record = $details['record']; $field_name = $this->field['field_name']; $field_type = $this->field['type']; $field_table = $this->instance['settings']['chado_table']; $field_column = $this->instance['settings']['chado_column']; $base_table = $this->instance['settings']['base_table']; // Get the PKey for this table $schema = chado_get_schema($field_table); $pkey = $schema['primary key'][0]; // Get the Pkeys for the subject and object tables $subject_fkey_table = ''; $object_fkey_table = ''; $fkeys = $schema['foreign keys']; $subject_id_key = 'subject_id'; $object_id_key = 'object_id'; foreach ($fkeys as $fktable => $details) { foreach ($details['columns'] as $fkey_lcolumn => $fkey_rcolumn) { if (preg_match('/^subject_.*id/', $fkey_lcolumn)) { $subject_fkey_table = $fktable; $subject_id_key = $fkey_lcolumn; } if (preg_match('/^object_.*id/', $fkey_lcolumn)) { $object_fkey_table = $fktable; $object_id_key = $fkey_lcolumn; } } } $subject_schema = chado_get_schema($subject_fkey_table); $object_schema = chado_get_schema($object_fkey_table); $subject_pkey = $subject_schema['primary key'][0]; $object_pkey = $object_schema['primary key'][0]; // Get the FK that links to the base record. $schema = chado_get_schema($field_table); $fkey_lcolumn = key($schema['foreign keys'][$base_table]['columns']); $fkey_rcolumn = $schema['foreign keys'][$base_table]['columns'][$fkey_lcolumn]; // Set some defaults for the empty record. $entity->{$field_name}['und'][0] = array( 'value' => array( /* The following shows what may be present in the value array // Clause 'SIO:000493' => '', 'local:relationship_subject' => array( // Identifier 'data:0842' => '', 'schema:name' => '', 'rdfs:type' => '' ), 'local:relationship_object' => array( // Identifier 'data:0842' => '', 'schema:name' => '', 'rdfs:type' => '', ), 'local:relationship_type' => '', */ ), 'chado-' . $field_table . '__' . $pkey => '', 'chado-' . $field_table . '__' . $subject_id_key => '', 'chado-' . $field_table . '__' . $object_id_key => '', 'chado-' . $field_table . '__type_id' => '', // These elements don't need to follow the naming scheme above // becasue we don't need the chado_field_storage to try and // save these values. 'object_name' => '', 'subject_name' => '', 'type_name' => '', ); // If the table has rank and value fields then add those to the default // value array. if (array_key_exists('value', $schema['fields'])) { $entity->{$field_name}['und'][0]['chado-' . $field_table . '__value'] = ''; } if (array_key_exists('rank', $schema['fields'])) { $entity->{$field_name}['und'][0]['chado-' . $field_table . '__rank'] = ''; } // If we have no record then just return. if (!$record) { return; } // Expand the object to include the relationships. $options = array( 'return_array' => 1, // we don't want to fully recurse we only need information about the // relationship type and the object and subject 'include_fk' => array( 'type_id' => 1, $object_id_key => array( 'type_id' => 1, ), $subject_id_key => array( 'type_id' => 1, ), ), ); $rel_table = $base_table . '_relationship'; $schema = chado_get_schema($rel_table); if (array_key_exists('rank', $schema['fields'])) { $options['order_by'] = array('rank' => 'ASC'); } $record = chado_expand_var($record, 'table', $rel_table, $options); if (!$record->$rel_table) { return; } $srelationships = null; $orelationships = null; if (isset($record->$rel_table->$subject_id_key)) { $srelationships = $record->$rel_table->$subject_id_key; } if (isset($record->$rel_table->$object_id_key)) { $orelationships = $record->$rel_table->$object_id_key; } $i = 0; if ($orelationships) { foreach ($orelationships as $relationship) { $rel_acc = $relationship->type_id->dbxref_id->db_id->name . ':' . $relationship->type_id->dbxref_id->accession; $rel_type = $relationship->type_id->name; $verb = self::get_rel_verb($rel_type); $subject_name = $relationship->$subject_id_key->name; $subject_type = $relationship->$subject_id_key->type_id->name; $object_name = $relationship->$object_id_key->name; $object_type = $relationship->$object_id_key->type_id->name; $entity->{$field_name}['und'][$i]['value'] = array( 'local:relationship_subject' => array( 'rdfs:type' => $subject_type, 'schema:name' => $subject_name, ), 'local:relationship_type' => $relationship->type_id->name, 'local:relationship_object' => array( 'rdfs:type' => $object_type, 'schema:name' => $object_name, 'entity' => 'TripalEntity:' . $entity->id, ) ); if (property_exists($relationship->$subject_id_key, 'uniquename')) { $entity->{$field_name}['und'][$i]['value']['local:relationship_subject']['data:0842'] = $relationship->$subject_id_key->uniquename;; } if (property_exists($relationship->$object_id_key, 'uniquename')) { $entity->{$field_name}['und'][$i]['value']['local:relationship_object']['data:0842'] = $relationship->$object_id_key->uniquename; } if (property_exists($relationship->$subject_id_key, 'entity_id')) { $entity_id = $relationship->$subject_id_key->entity_id; $entity->{$field_name}['und'][$i]['value']['local:relationship_subject']['entity'] = 'TripalEntity:' . $entity_id; } $rel_type_clean = lcfirst(preg_replace('/_/', ' ', $rel_type)); $entity->{$field_name}['und'][$i]['value']['SIO:000493'] = 'The ' . $subject_type . ', ' . $subject_name . ', ' . $verb . ' ' . $rel_type_clean . ' this ' . $object_type . '.'; //dpm("OR:" . $entity->{$field_name}['und'][$i]['value']['SIO:000493']); $entity->{$field_name}['und'][$i]['chado-' . $field_table . '__' . $pkey] = $relationship->$pkey; $entity->{$field_name}['und'][$i]['chado-' . $field_table . '__' . $subject_id_key] = $relationship->$subject_id_key->$subject_pkey; $entity->{$field_name}['und'][$i]['chado-' . $field_table . '__type_id'] = $relationship->type_id->cvterm_id; $entity->{$field_name}['und'][$i]['chado-' . $field_table . '__' . $object_id_key] = $relationship->$object_id_key->$object_pkey; $entity->{$field_name}['und'][$i]['type_name'] = $relationship->type_id->name; $entity->{$field_name}['und'][$i]['subject_name'] = $relationship->$subject_id_key->name . ' [id: ' . $relationship->$subject_id_key->$fkey_rcolumn . ']'; $entity->{$field_name}['und'][$i]['object_name'] = $relationship->$object_id_key->name . ' [id: ' . $relationship->$object_id_key->$fkey_rcolumn . ']'; if (array_key_exists('value', $schema['fields'])) { $entity->{$field_name}['und'][$i]['chado-' . $field_table . '__value'] = $relationship->value; } if (array_key_exists('rank', $schema['fields'])) { $entity->{$field_name}['und'][$i]['chado-' . $field_table . '__rank'] = $relationship->rank; } $i++; } } if ($srelationships) { foreach ($srelationships as $relationship) { $rel_acc = $relationship->type_id->dbxref_id->db_id->name . ':' . $relationship->type_id->dbxref_id->accession; $rel_type = $relationship->type_id->name; $verb = self::get_rel_verb($rel_type); $subject_name = isset($relationship->$subject_id_key->name) ? $relationship->$subject_id_key->name : ''; if (!$subject_name) { if ($relationship->tablename == 'organism_relationship') { $subject_name = $relationship->$subject_id_key->genus . ' ' . $relationship->$subject_id_key->species; } } $subject_type = isset($relationship->$subject_id_key->type_id) ? $relationship->$subject_id_key->type_id->name : ' '; $object_name = isset($relationship->$object_id_key->name) ? $relationship->$object_id_key->name : ''; if (!$object_name) { if ($relationship->tablename == 'organism_relationship') { $object_name = $relationship->$object_id_key->genus . ' ' . $relationship->$object_id_key->species; } } $object_type = isset($relationship->$object_id_key->type_id) ? $relationship->$object_id_key->type_id->name : ' '; $entity->{$field_name}['und'][$i]['value'] = array( 'local:relationship_subject' => array( 'rdfs:type' => $subject_type, 'schema:name' => $subject_name, 'entity' => 'TripalEntity:' . $entity->id, ), 'local:relationship_type' => $relationship->type_id->name, 'local:relationship_object' => array( 'rdfs:type' => $object_type, 'schema:name' => $object_name, ) ); if (property_exists($relationship->$subject_id_key, 'uniquename')) { $entity->{$field_name}['und'][$i]['value']['local:relationship_subject']['data:0842'] = $relationship->$subject_id_key->uniquename; } if (property_exists($relationship->$object_id_key, 'uniquename')) { $entity->{$field_name}['und'][$i]['value']['local:relationship_object']['data:0842'] = $relationship->$object_id_key->uniquename; } if (property_exists($relationship->$object_id_key, 'entity_id')) { $entity_id = $relationship->$object_id_key->entity_id; $entity->{$field_name}['und'][$i]['value']['local:relationship_object']['entity'] = 'TripalEntity:' . $entity_id; } $rel_type_clean = lcfirst(preg_replace('/_/', ' ', $rel_type)); $entity->{$field_name}['und'][$i]['value']['SIO:000493'] = 'This ' . $subject_name . ' ' . $verb . ' ' . $rel_type_clean . ' the ' . $object_type . ', ' . $object_name . '.'; //dpm("SR:" . $entity->{$field_name}['und'][$i]['value']['SIO:000493']); $entity->{$field_name}['und'][$i]['chado-' . $field_table . '__' . $pkey] = $relationship->$pkey; $entity->{$field_name}['und'][$i]['chado-' . $field_table . '__' . $subject_id_key] = $relationship->$subject_id_key->$subject_pkey; $entity->{$field_name}['und'][$i]['chado-' . $field_table . '__type_id'] = $relationship->type_id->cvterm_id; $entity->{$field_name}['und'][$i]['chado-' . $field_table . '__' . $object_id_key] = $relationship->$object_id_key->$object_pkey; $entity->{$field_name}['und'][$i]['type_name'] = $relationship->type_id->name; $entity->{$field_name}['und'][$i]['subject_name'] = $subject_name . ' [id: ' . $relationship->$subject_id_key->$fkey_rcolumn . ']'; $entity->{$field_name}['und'][$i]['object_name'] = $object_name . ' [id: ' . $relationship->$object_id_key->$fkey_rcolumn . ']'; if (array_key_exists('value', $schema['fields'])) { $entity->{$field_name}['und'][$i]['chado-' . $field_table . '__value'] = $relationship->value; } if (array_key_exists('rank', $schema['fields'])) { $entity->{$field_name}['und'][$i]['chado-' . $field_table . '__rank'] = $relationship->rank; } $i++; } } } /** * @see ChadoField::query() */ public function query($query, $condition) { $alias = $this->field['field_name']; $chado_table = $this->instance['settings']['chado_table']; $base_table = $this->instance['settings']['base_table']; $bschema = chado_get_schema($base_table); $bpkey = $bschema['primary key'][0]; // Filter by the name of the subject or object. if ($condition['column'] == 'relationship.clause_subject.schema:name' or $condition['column'] == 'relationship.clause_subject.name') { $query->join($chado_table, $alias, "base.$bpkey = $alias.object_id"); $query->join($base_table, 'base2', "base2.$bpkey = $alias.subject_id"); $query->condition("base2.name", $condition['value']); } if ($condition['column'] == 'relationship.clause_predicate.schema:name' or $condition['column'] == 'relationship.clause_predicate.name') { $query->join($chado_table, $alias, "base.$bpkey = $alias.subject_id"); $query->join($base_table, 'base2', "base2.$bpkey = $alias.object_id"); $query->condition("base2.name", $condition['value']); } // Filter by unique name of the subject or object. if ($condition['column'] == 'relationship.clause_subject.data:0842' or $condition['column'] == 'relationship.clause_subject.identifier') { $query->join($chado_table, $alias, "base.$bpkey = $alias.object_id"); $query->join($base_table, 'base2', "base2.$bpkey = $alias.subject_id"); $query->condition("base2.uniquename", $condition['value']); } if ($condition['column'] == 'relationship.clause_predicate.data:0842' or $condition['column'] == 'relationship.clause_predicate.identifier') { $query->join($chado_table, $alias, "base.$bpkey = $alias.subject_id"); $query->join($base_table, 'base2', "base2.$bpkey = $alias.object_id"); $query->condition("base2.uniquename", $condition['value']); } // Filter by the type of the subject or object if ($condition['column'] == 'relationship.clause_subject.rdfs:type' or $condition['column'] == 'relationship.clause_subject.type') { $query->join($chado_table, $alias, "base.$bpkey = $alias.object_id"); $query->join($base_table, 'base2', "base2.$bpkey = $alias.subject_id"); $query->join('cvterm', 'SubjectCVT', "SubjectCVT.cvterm_id = base2.type_id"); $query->condition("SubjectCVT.name", $condition['value']); } if ($condition['column'] == 'relationship.clause_predicate.rdfs:type' or $condition['column'] == 'relationship.clause_predicate.type') { $query->join($chado_table, $alias, "base.$bpkey = $alias.subject_id"); $query->join($base_table, 'base2', "base2.$bpkey = $alias.object_id"); $query->join('cvterm', 'ObjectCVT', "ObjectCVT.cvterm_id = base2.type_id"); $query->condition("ObjectCVT.name", $condition['value']); } // Filter by relationship type if ($condition['column'] == 'relationship.relationship_type') { // This filter commented out because it's way to slow... // $query->join($chado_table, $alias, "base.$bpkey = $alias.subject_id OR base.$bpkey = $alias.object_id"); // $query->join('cvterm', 'RelTypeCVT', "RelTypeCVT.cvterm_id = $alias.type_id"); // $query->condition("RelTypeCVT.name", $condition['value']); } } /** * A helper function to define English verbs for relationship types. * * @param $rel_type * The vocabulary term name for the relationship. * * @return * The verb to use when creating a sentence of the relationship. */ public static function get_rel_verb($rel_type) { $rel_type_clean = lcfirst(preg_replace('/_/', ' ', $rel_type)); $verb = ''; switch ($rel_type_clean) { case 'integral part of': case 'instance of': $verb = 'is an'; break; case 'proper part of': case 'transformation of': case 'genome of': case 'part of': $verb = 'is a'; case 'position of': case 'sequence of': case 'variant of': $verb = 'is a'; break; case 'derives from': case 'connects on': case 'contains': case 'finishes': case 'guides': case 'has origin': case 'has part': case 'has quality': case 'is consecutive sequence of': case 'maximally overlaps': case 'overlaps': case 'starts': break; default: $verb = 'is'; } return $verb; } /** * * @see TripalField::settingsForm() */ public function settingsForm($has_data) { $element = parent::instanceSettingsForm(); //$element = parent::instanceSettingsForm(); $element['relationships'] = array( '#type' => 'fieldset', '#title' => 'Allowed Relationship Types', '#description' => t('There are three ways that relationship types can be limited for users who have permission to add new relationships. Please select the most appropriate for you use case. By default all vocabularies are provided to the user which allows use of any term for the relationship type.'), '#collapsed' => TRUE, '#collapsible' => TRUE, ); // $element['instructions'] = array( // '#type' => 'item', // '#markup' => 'You may provide a list of terms that will be available in a select box // as the relationship types. This select box will replace the vocabulary select box if the // following value is set.' // ); $vocs = tripal_get_cv_select_options(); $element['relationships']['option1'] = array( '#type' => 'item', '#title' => 'Option #1', '#description' => t('Use this option to limit the vocabularies that a user . could use to specify relationship types. With this option any term in . the vocabulary can be used for the relationship type. You may select more than one vocabulary.'), ); $element['relationships']['option1_vocabs'] = array( '#type' => 'select', '#multiple' => TRUE, '#options' => $vocs, '#size' => 6, '#default_value' => $this->instance['settings']['relationships']['option1_vocabs'], // TODO add ajax here so that the relationship autocomplete below works ); $element['relationships']['option2'] = array( '#type' => 'item', '#title' => 'Option #2', '#description' => 'Some vocabularies are heirarchichal (an ontology). Within this heirarchy groups of related terms typically fall under a common parent. If you wish to limit the list of terms that a user can use for the relationship type, you can provide the parent term here. Then, only that term\'s children will be avilable for use as a relationship type.', ); $element['relationships']['option2_vocab'] = array( '#type' => 'select', '#description' => 'Specify Default Vocabulary', '#multiple' => FALSE, '#options' => $vocs, '#default_value' => $this->instance['settings']['relationships']['option2_vocab'], '#ajax' => array( 'callback' => "sbo__relationship_instance_settings_form_ajax_callback", 'wrapper' => 'relationships-option2-parent', 'effect' => 'fade', 'method' => 'replace' ), ); $element['relationships']['option2_parent'] = array( '#type' => 'textfield', '#description' => 'Specify a Heirarchical Parent Term', '#default_value' => $this->instance['settings']['relationships']['option2_parent'], '#autocomplete_path' => "admin/tripal/storage/chado/auto_name/cvterm/", '#prefix' => '