chado_linker__relationship.inc 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592
  1. <?php
  2. class chado_linker__relationship extends TripalField {
  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. // The term that this field maps to. The format for the term should be:
  11. // [vocab]:[accession] where [vocab] is the short name of the vocabulary
  12. // and [acession] is the unique accession number for the term. This term
  13. // must already exist in the vocabulary storage backend. This
  14. // value should never be changed once fields exist for this type.
  15. public static $term = 'SBO:0000374';
  16. // The default lable for this field.
  17. public static $label = 'Relationships';
  18. // The default description for this field.
  19. public static $description = 'Relationships between records.';
  20. // Provide a list of global settings. These can be accessed witihn the
  21. // globalSettingsForm. When the globalSettingsForm is submitted then
  22. // Drupal will automatically change these settings for all fields.
  23. public static $settings = array(
  24. 'chado_table' => '',
  25. 'chado_column' => '',
  26. 'base_table' => '',
  27. );
  28. // Provide a list of instance specific settings. These can be access within
  29. // the instanceSettingsForm. When the instanceSettingsForm is submitted
  30. // then Drupal with automatically change these settings for the instnace.
  31. // It is recommended to put settings at the instance level whenever possible.
  32. public static $instance_settings = array();
  33. // Set this to the name of the storage backend that by default will support
  34. // this field.
  35. public static $storage = 'tripal_no_storage';
  36. // The default widget for this field.
  37. public static $default_widget = 'chado_linker__relationship_widget';
  38. // The default formatter for this field.
  39. public static $default_formatter = 'chado_linker__relationship_formatter';
  40. // --------------------------------------------------------------------------
  41. // PROTECTED CLASS MEMBERS -- DO NOT OVERRIDE
  42. // --------------------------------------------------------------------------
  43. // An array containing details about the field. The format of this array
  44. // is the same as that returned by field_info_fields()
  45. protected $field;
  46. // An array containing details about an instance of the field. A field does
  47. // not have to have an instance. But if dealing with an instance (such as
  48. // when using the widgetForm, formatterSettingsForm, etc.) it should be set.
  49. protected $instance;
  50. /**
  51. *
  52. * @see TripalField::validate()
  53. */
  54. public function validate($entity_type, $entity, $field, $items, &$errors) {
  55. }
  56. /**
  57. *
  58. * @see TripalField::load()
  59. */
  60. public function load($entity, $details = array()) {
  61. $settings = $this->field['settings'];
  62. $record = $details['record'];
  63. $field_name = $this->field['field_name'];
  64. $field_type = $this->field['type'];
  65. $field_table = $this->field['settings']['chado_table'];
  66. $field_column = $this->field['settings']['chado_column'];
  67. $base_table = $this->field['settings']['base_table'];
  68. // Get the PKey for this table
  69. $schema = chado_get_schema($field_table);
  70. $pkey = $schema['primary key'][0];
  71. // Get the Pkeys for the subject and object tables
  72. $subject_fkey_table = '';
  73. $object_fkey_table = '';
  74. $fkeys = $schema['foreign keys'];
  75. foreach ($fkeys as $fktable => $details) {
  76. foreach ($details['columns'] as $fkey_lcolumn => $fkey_rcolumn) {
  77. if ($fkey_lcolumn == 'subject_id') {
  78. $subject_fkey_table = $fktable;
  79. }
  80. if ($fkey_lcolumn == 'object_id') {
  81. $object_fkey_table = $fktable;
  82. }
  83. }
  84. }
  85. $subject_schema = chado_get_schema($subject_fkey_table);
  86. $object_schema = chado_get_schema($object_fkey_table);
  87. $subject_pkey = $subject_schema['primary key'][0];
  88. $object_pkey = $object_schema['primary key'][0];
  89. // Get the FK that links to the base record.
  90. $schema = chado_get_schema($field_table);
  91. $fkey_lcolumn = key($schema['foreign keys'][$base_table]['columns']);
  92. $fkey_rcolumn = $schema['foreign keys'][$base_table]['columns'][$fkey_lcolumn];
  93. // Set some defaults for the empty record.
  94. $entity->{$field_name}['und'][0] = array(
  95. 'value' => array(),
  96. 'chado-' . $field_table . '__' . $pkey => '',
  97. 'chado-' . $field_table . '__subject_id' => '',
  98. 'chado-' . $field_table . '__object_id' => '',
  99. 'chado-' . $field_table . '__type_id' => '',
  100. // These elements don't need to follow the naming scheme above
  101. // becasue we don't need the chado_field_storage to try and
  102. // save these values.
  103. 'object_name' => '',
  104. 'subject_name' => '',
  105. 'type_name' => '',
  106. );
  107. // If the table has rank and value fields then add those to the default
  108. // value array.
  109. if (array_key_exists('value', $schema['fields'])) {
  110. $entity->{$field_name}['und'][0]['chado-' . $field_table . '__value'] = '';
  111. }
  112. if (array_key_exists('rank', $schema['fields'])) {
  113. $entity->{$field_name}['und'][0]['chado-' . $field_table . '__rank'] = '';
  114. }
  115. // If we have no record then just return.
  116. if (!$record) {
  117. return;
  118. }
  119. // Expand the object to include the relationships.
  120. $options = array(
  121. 'return_array' => 1,
  122. // we don't want to fully recurse we only need information about the
  123. // relationship type and the object and subject
  124. 'include_fk' => array(
  125. 'type_id' => 1,
  126. 'object_id' => array(
  127. 'type_id' => 1,
  128. ),
  129. 'subject_id' => array(
  130. 'type_id' => 1,
  131. ),
  132. ),
  133. );
  134. $rel_table = $base_table . '_relationship';
  135. $schema = chado_get_schema($rel_table);
  136. if (array_key_exists('rank', $schema['fields'])) {
  137. $options['order_by'] = array('rank' => 'ASC');
  138. }
  139. $record = chado_expand_var($record, 'table', $rel_table, $options);
  140. if (!$record->$rel_table) {
  141. return;
  142. }
  143. $srelationships = null;
  144. $orelationships = null;
  145. if ($rel_table == 'nd_reagent_relationship') {
  146. $srelationships = $record->$rel_table->subject_reagent_id;
  147. $orelationships = $record->$rel_table->object_reagent_id;
  148. }
  149. else if ($rel_table == 'project_relationship') {
  150. $srelationships = $record->$rel_table->subject_project_id;
  151. $orelationships = $record->$rel_table->object_project_id;
  152. }
  153. else {
  154. $srelationships = $record->$rel_table->subject_id;
  155. $orelationships = $record->$rel_table->object_id;
  156. }
  157. $i = 0;
  158. if ($orelationships) {
  159. foreach ($orelationships as $relationship) {
  160. $rel_acc = $relationship->type_id->dbxref_id->db_id->name . ':' . $relationship->type_id->dbxref_id->accession;
  161. $rel_type = $relationship->type_id->name;
  162. $verb = self::get_rel_verb($rel_type);
  163. $subject_name = $relationship->subject_id->name;
  164. $subject_type = $relationship->subject_id->type_id->name;
  165. $object_name = $relationship->object_id->name;
  166. $object_type = $relationship->object_id->type_id->name;
  167. $entity->{$field_name}['und'][$i]['value'] = array(
  168. 'type' => $relationship->type_id->name,
  169. 'subject' => array(
  170. 'type' => $subject_type,
  171. 'name' => $subject_name,
  172. ),
  173. 'type' => $relationship->type_id->name,
  174. 'object' => array(
  175. 'type' => $object_type,
  176. 'name' => $object_name,
  177. 'entity' => 'TripalEntity:' . $entity->id,
  178. )
  179. );
  180. if (property_exists($relationship->subject_id, 'uniquename')) {
  181. $entity->{$field_name}['und'][$i]['value']['subject']['identifier'] = $relationship->subject_id->uniquename;;
  182. }
  183. if (property_exists($relationship->object_id, 'uniquename')) {
  184. $entity->{$field_name}['und'][$i]['value']['object']['identifier'] = $relationship->object_id->uniquename;
  185. }
  186. if (property_exists($relationship->subject_id, 'entity_id')) {
  187. $entity_id = $relationship->subject_id->entity_id;
  188. $entity->{$field_name}['und'][$i]['value']['subject']['entity'] = 'TripalEntity:' . $entity_id;
  189. }
  190. $rel_type_clean = lcfirst(preg_replace('/_/', ' ', $rel_type));
  191. $entity->{$field_name}['und'][$i]['value']['phrase'] = 'The ' . $subject_type . ', ' .
  192. $subject_name . ', ' . $verb . ' ' . $rel_type_clean . ' this ' .
  193. $object_type . '.';
  194. $entity->{$field_name}['und'][$i]['semantic_web'] = array(
  195. 'type' => $rel_acc,
  196. 'subject' => $relationship->subject_id->type_id->dbxref_id->db_id->name . ':' . $relationship->subject_id->type_id->dbxref_id->accession,
  197. 'object' => $relationship->object_id->type_id->dbxref_id->db_id->name . ':' . $relationship->object_id->type_id->dbxref_id->accession,
  198. );
  199. $entity->{$field_name}['und'][$i]['chado-' . $field_table . '__' . $pkey] = $relationship->$pkey;
  200. $entity->{$field_name}['und'][$i]['chado-' . $field_table . '__subject_id'] = $relationship->subject_id->$subject_pkey;
  201. $entity->{$field_name}['und'][$i]['chado-' . $field_table . '__type_id'] = $relationship->type_id->cvterm_id;
  202. $entity->{$field_name}['und'][$i]['chado-' . $field_table . '__object_id'] = $relationship->object_id->$object_pkey;
  203. $entity->{$field_name}['und'][$i]['type_name'] = $relationship->type_id->name;
  204. $entity->{$field_name}['und'][$i]['subject_name'] = $relationship->subject_id->name . ' [id: ' . $relationship->subject_id->$fkey_rcolumn . ']';
  205. $entity->{$field_name}['und'][$i]['object_name'] = $relationship->object_id->name . ' [id: ' . $relationship->object_id->$fkey_rcolumn . ']';
  206. if (array_key_exists('value', $schema['fields'])) {
  207. $entity->{$field_name}['und'][$i]['chado-' . $field_table . '__value'] = $relationship->value;
  208. }
  209. if (array_key_exists('rank', $schema['fields'])) {
  210. $entity->{$field_name}['und'][$i]['chado-' . $field_table . '__rank'] = $relationship->rank;
  211. }
  212. $i++;
  213. }
  214. }
  215. if ($srelationships) {
  216. foreach ($srelationships as $relationship) {
  217. $rel_acc = $relationship->type_id->dbxref_id->db_id->name . ':' . $relationship->type_id->dbxref_id->accession;
  218. $rel_type = $relationship->type_id->name;
  219. $verb = self::get_rel_verb($rel_type);
  220. $subject_name = $relationship->subject_id->name;
  221. $subject_type = $relationship->subject_id->type_id->name;
  222. $object_name = $relationship->object_id->name;
  223. $object_type = $relationship->object_id->type_id->name;
  224. $entity->{$field_name}['und'][$i]['value'] = array(
  225. '@type' => $relationship->type_id->name,
  226. 'subject' => array(
  227. 'type' => $subject_type,
  228. 'name' => $subject_name,
  229. 'entity' => 'TripalEntity:' . $entity->id,
  230. ),
  231. 'type' => $relationship->type_id->name,
  232. 'object' => array(
  233. 'type' => $object_type,
  234. 'name' => $object_name,
  235. )
  236. );
  237. if (property_exists($relationship->subject_id, 'uniquename')) {
  238. $entity->{$field_name}['und'][$i]['value']['subject']['identifier'] = $relationship->subject_id->uniquename;
  239. }
  240. if (property_exists($relationship->object_id, 'uniquename')) {
  241. $entity->{$field_name}['und'][$i]['value']['object']['identifier'] = $relationship->object_id->uniquename;
  242. }
  243. if (property_exists($relationship->object_id, 'entity_id')) {
  244. $entity_id = $relationship->object_id->entity_id;
  245. $entity->{$field_name}['und'][$i]['value']['object']['entity'] = 'TripalEntity:' . $entity_id;
  246. }
  247. $rel_type_clean = lcfirst(preg_replace('/_/', ' ', $rel_type));
  248. $entity->{$field_name}['und'][$i]['value']['phrase'] = 'This ' .
  249. $subject_type . ' ' . $verb . ' ' . $rel_type_clean . ' the ' .
  250. $object_type . ', ' . $object_name . '.';
  251. $entity->{$field_name}['und'][$i]['semantic_web'] = array(
  252. 'type' => $rel_acc,
  253. 'subject' => $relationship->subject_id->type_id->dbxref_id->db_id->name . ':' . $relationship->subject_id->type_id->dbxref_id->accession,
  254. 'object' => $relationship->object_id->type_id->dbxref_id->db_id->name . ':' . $relationship->object_id->type_id->dbxref_id->accession,
  255. );
  256. $entity->{$field_name}['und'][$i]['chado-' . $field_table . '__' . $pkey] = $relationship->$pkey;
  257. $entity->{$field_name}['und'][$i]['chado-' . $field_table . '__subject_id'] = $relationship->subject_id->$subject_pkey;
  258. $entity->{$field_name}['und'][$i]['chado-' . $field_table . '__type_id'] = $relationship->type_id->cvterm_id;
  259. $entity->{$field_name}['und'][$i]['chado-' . $field_table . '__object_id'] = $relationship->object_id->$object_pkey;
  260. $entity->{$field_name}['und'][$i]['type_name'] = $relationship->type_id->name;
  261. $entity->{$field_name}['und'][$i]['subject_name'] = $relationship->subject_id->name . ' [id: ' . $relationship->subject_id->$fkey_rcolumn . ']';
  262. $entity->{$field_name}['und'][$i]['object_name'] = $relationship->object_id->name . ' [id: ' . $relationship->object_id->$fkey_rcolumn . ']';
  263. if (array_key_exists('value', $schema['fields'])) {
  264. $entity->{$field_name}['und'][$i]['chado-' . $field_table . '__value'] = $relationship->value;
  265. }
  266. if (array_key_exists('rank', $schema['fields'])) {
  267. $entity->{$field_name}['und'][$i]['chado-' . $field_table . '__rank'] = $relationship->rank;
  268. }
  269. $i++;
  270. }
  271. }
  272. }
  273. /**
  274. * A helper function to define English verbs for relationship types.
  275. *
  276. * @param $rel_type
  277. * The vocabulary term name for the relationship.
  278. *
  279. * @return
  280. * The verb to use when creating a sentence of the relationship.
  281. */
  282. public static function get_rel_verb($rel_type) {
  283. $rel_type_clean = lcfirst(preg_replace('/_/', ' ', $rel_type));
  284. $verb = $rel_type_clean;
  285. switch ($rel_type_clean) {
  286. case 'integral part of':
  287. case 'instance of':
  288. $verb = 'is an';
  289. break;
  290. case 'proper part of':
  291. case 'transformation of':
  292. case 'genome of':
  293. case 'part of':
  294. $verb = 'is a';
  295. case 'position of':
  296. case 'sequence of':
  297. case 'variant of':
  298. $verb = 'is a';
  299. break;
  300. case 'derives from':
  301. case 'connects on':
  302. case 'contains':
  303. case 'finishes':
  304. case 'guides':
  305. case 'has origin':
  306. case 'has part':
  307. case 'has quality':
  308. case 'is consecutive sequence of':
  309. case 'maximally overlaps':
  310. case 'overlaps':
  311. case 'starts':
  312. break;
  313. default:
  314. $verb = 'is';
  315. }
  316. return $verb;
  317. }
  318. /**
  319. *
  320. * @see TripalField::settingsForm()
  321. */
  322. public function settingsForm($has_data) {
  323. $element = parent::instanceSettingsForm();
  324. //$element = parent::instanceSettingsForm();
  325. $element['relationships'] = array(
  326. '#type' => 'fieldset',
  327. '#title' => 'Allowed Relationship Types',
  328. '#description' => t('There are three ways that relationship types
  329. can be limited for users who have permission to add new relationships.
  330. Please select the most appropriate for you use case. By default
  331. all vocabularies are provided to the user which allows use of any
  332. term for the relationship type.'),
  333. '#collapsed' => TRUE,
  334. '#collapsible' => TRUE,
  335. '#theme' => 'chado_linker__relationship_instance_settings'
  336. );
  337. // $element['instructions'] = array(
  338. // '#type' => 'item',
  339. // '#markup' => 'You may provide a list of terms that will be available in a select box
  340. // as the relationship types. This select box will replace the vocabulary select box if the
  341. // following value is set.'
  342. // );
  343. $vocs = tripal_get_cv_select_options();
  344. $element['relationships']['option1'] = array(
  345. '#type' => 'item',
  346. '#title' => 'Option #1',
  347. '#description' => t('Use this option to limit the vocabularies that a user .
  348. could use to specify relationship types. With this option any term in .
  349. the vocabulary can be used for the relationship type. You may select
  350. more than one vocabulary.'),
  351. );
  352. $element['relationships']['option1_vocabs'] = array(
  353. '#type' => 'select',
  354. '#multiple' => TRUE,
  355. '#options' => $vocs,
  356. '#size' => 6,
  357. '#default_value' => $this->instance['settings']['relationships']['option1_vocabs'],
  358. // TODO add ajax here so that the relationship autocomplete below works
  359. );
  360. $element['relationships']['option2'] = array(
  361. '#type' => 'item',
  362. '#title' => '<b>Option #2</b>',
  363. '#description' => 'Some vocabularies are heirarchichal (an ontology). Within this
  364. heirarchy groups of related terms typically fall under a common parent. If you
  365. wish to limit the list of terms that a user can use for the relationship type,
  366. you can provide the parent term here. Then, only that term\'s children will
  367. be avilable for use as a relationship type.',
  368. );
  369. $element['relationships']['option2_vocab'] = array(
  370. '#type' => 'select',
  371. '#description' => 'Specify Default Vocabulary',
  372. '#multiple' => FALSE,
  373. '#options' => $vocs,
  374. '#default_value' => $this->instance['settings']['relationships']['option2_vocab'],
  375. '#ajax' => array(
  376. 'callback' => "chado_linker__relationship_instance_settings_form_ajax_callback",
  377. 'wrapper' => 'relationships-option2-parent',
  378. 'effect' => 'fade',
  379. 'method' => 'replace'
  380. ),
  381. );
  382. $element['relationships']['option2_parent'] = array(
  383. '#type' => 'textfield',
  384. '#description' => 'Specify a Heirarchical Parent Term',
  385. '#default_value' => $this->instance['settings']['relationships']['option2_parent'],
  386. '#autocomplete_path' => "admin/tripal/storage/chado/auto_name/cvterm/",
  387. '#prefix' => '<div id=relationships-option2-parent>',
  388. '#suffix' => '</div>'
  389. );
  390. $element['relationships']['option3'] = array(
  391. '#type' => 'item',
  392. '#title' => 'Option #3',
  393. '#description' => 'Provide terms separated by a new line. The term provided should be
  394. unique and distinguishable by the name. You can use a bar | to separate a vocabulary
  395. and a term to allow more specific assignment.',
  396. );
  397. $element['relationships']['relationship_types'] = array(
  398. '#type' => 'textarea',
  399. '#default_value' => $this->instance['settings']['relationships']['relationship_types'],
  400. );
  401. return $element;
  402. }
  403. /**
  404. *
  405. * @param unknown $form
  406. * @param unknown $form_state
  407. */
  408. public function settingsFormValidate($form, &$form_state) {
  409. // Get relationships settings
  410. $settings = $form_state['values']['instance']['settings']['relationships'];
  411. $form_state['values']['instance']['settings']['relationships']['relationship_types']= trim($settings['relationship_types']);
  412. // Make sure only one option is selected
  413. $option1test = $settings['option1_vocabs'];
  414. $option1 = isset($settings['option1_vocabs']) && array_pop($option1test);
  415. $option2 = (isset($settings['option2_vocab']) && $settings['option2_vocab']) || $settings['option2_parent'];
  416. $option3 = isset($settings['relationship_types']) && trim($settings['relationship_types']);
  417. if ($option1 && ($option2 || $option3) == 1 ||
  418. $option2 && ($option1 || $option3) == 1 ||
  419. $option3 && ($option1 || $option2) == 1
  420. ) {
  421. form_set_error(
  422. "instance][settings][relationships",
  423. t("Only one option is allowed to limit the relationship types.")
  424. );
  425. return;
  426. }
  427. // For option3, make sure the supplied types are valid cvterms
  428. if ($option3) {
  429. $rel_types = explode(PHP_EOL, $settings['relationship_types']);
  430. foreach($rel_types AS $type) {
  431. $type = trim($type);
  432. // Ignore empty lines
  433. if ($type == '') {
  434. continue;
  435. }
  436. // Find the matching cvterm
  437. $sql = "SELECT cvterm_id FROM {cvterm} WHERE name = :name";
  438. $results = chado_query($sql, array(':name' => $type));
  439. $terms = array();
  440. while ($obj = $results->fetchObject()) {
  441. $terms[] = $obj;
  442. }
  443. // Don't save the form if a term can not be found or it matches more than one cvterm
  444. $cv = '';
  445. if (count($terms) == 0) {
  446. // If a term can not be found, maybe the type contains '|', parse it as 'vocabulary|cvterm'
  447. if (strpos($type, '|')) {
  448. $tmp = explode('|', $type, 2);
  449. $type = trim($tmp[1]);
  450. $cv = tripal_get_cv(array('name' => trim($tmp[0])));
  451. if($cv) {
  452. $sql = "SELECT cvterm_id FROM {cvterm} WHERE name = :name AND cv_id = :cv_id";
  453. $results = chado_query($sql, array(':name' => $type, ':cv_id' => $cv->cv_id));
  454. while ($obj = $results->fetchObject()) {
  455. $terms[] = $obj;
  456. }
  457. }
  458. else {
  459. $cv = $tmp[0];
  460. }
  461. }
  462. if (count($terms) != 1) {
  463. $message = "The term '@type' can not be found.";
  464. $token = array('@type' => $type);
  465. if ($cv) {
  466. $message = "The term '@type' can not be found within the vocabulary '@vocab'.";
  467. $token['@vocab'] = $cv;
  468. }
  469. form_set_error(
  470. "instance][settings][relationships][relationship_types",
  471. t($message, $token)
  472. );
  473. }
  474. }
  475. else if (count($terms) > 1) {
  476. // If a type matches more than one term, parse it as 'vocabulary|cvterm' and try again
  477. if (strpos($type, '|')) {
  478. $tmp = explode('|', $type, 2);
  479. $type = trim($tmp[1]);
  480. $cv = tripal_get_cv(array('name' => trim($tmp[0])));
  481. if ($cv) {
  482. $sql = "SELECT cvterm_id FROM {cvterm} WHERE name = :name AND cv_id = :cv_id";
  483. $results = chado_query($sql, array(':name' => $type, ':cv_id' => $cv->cv_id));
  484. while ($obj = $results->fetchObject()) {
  485. $terms[] = $obj;
  486. }
  487. }
  488. }
  489. if(count($terms) != 1) {
  490. form_set_error(
  491. "instance][settings][relationships][relationship_types",
  492. t("The term '@type' matches more than one term. Please specify its vocabulary in
  493. the format of 'vocabulary|@type'.", array('@type' => $type))
  494. );
  495. }
  496. }
  497. }
  498. }
  499. // For option2: Make sure the parent term is a valid cvterm
  500. if ($option2) {
  501. $cv_id = $settings['option2_vocab'];
  502. $supertype = $settings['option2_parent'];
  503. $term = tripal_get_cvterm(array(
  504. 'name' => trim($supertype),
  505. 'cv_id' => $cv_id,
  506. ));
  507. // Tripal cv autocomplete also allow cvterm synonyms, if the parent term doesn't match
  508. // a cvterm, try cvtermsynonym
  509. if (!$term) {
  510. $synonym = tripal_get_cvterm(
  511. array(
  512. 'synonym' => array(
  513. 'name' => trim($supertype),
  514. )
  515. )
  516. );
  517. if ($synonym && $synonym->cv_id->cv_id == $cv_id) {
  518. $term = $synonym;
  519. }
  520. }
  521. if (!isset($term->cvterm_id)) {
  522. form_set_error(
  523. "instance][settings][relationships][option2_parent",
  524. t("The term '@type' is not a valid term for the vocabulary selected.", array('@type' => $supertype))
  525. );
  526. }
  527. }
  528. }
  529. /**
  530. *
  531. * @see TripalField::instanceSettingsForm()
  532. */
  533. public function instanceSettingsForm() {
  534. }
  535. /**
  536. *
  537. * @see TripalField::instanceSettingsFormValidate()
  538. */
  539. public function instanceSettingsFormValidate($form, &$form_state) {
  540. }
  541. }