chado_linker__relationship.inc 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851
  1. <?php
  2. class chado_linker__relationship extends TripalField {
  3. /**
  4. * @see TripalField::field_info()
  5. */
  6. function field_info() {
  7. return array(
  8. 'label' => t('Relationships'),
  9. 'description' => t('Relationships between records.'),
  10. 'default_widget' => 'chado_linker__relationship_widget',
  11. 'default_formatter' => 'chado_linker__relationship_formatter',
  12. 'settings' => array(),
  13. 'storage' => array(
  14. 'type' => 'field_chado_storage',
  15. 'module' => 'tripal_chado',
  16. 'active' => TRUE
  17. ),
  18. );
  19. }
  20. /**
  21. * @see TripalField::can_attach()
  22. */
  23. protected function can_attach($entity_type, $bundle, $details) {
  24. $table_name = $details['chado_table'];
  25. $type_table = $details['chado_type_table'];
  26. $type_field = $details['chado_type_column'];
  27. $cv_id = $details['chado_cv_id'];
  28. $cvterm_id = $details['chado_cvterm_id'];
  29. // If the linker table does not exists then we don't want to add attach.
  30. $rel_table = $table_name . '_relationship';
  31. if (chado_table_exists($rel_table)) {
  32. return TRUE;
  33. }
  34. return FALSE;
  35. }
  36. /**
  37. * @see TripalField::create_info()
  38. */
  39. function create_info($entity_type, $bundle, $details) {
  40. if (!$this->can_attach($entity_type, $bundle, $details)) {
  41. return;
  42. }
  43. $table_name = $details['chado_table'];
  44. $type_table = $details['chado_type_table'];
  45. $type_field = $details['chado_type_column'];
  46. $cv_id = $details['chado_cv_id'];
  47. $cvterm_id = $details['chado_cvterm_id'];
  48. $rel_table = $table_name . '_relationship';
  49. $schema = chado_get_schema($rel_table);
  50. $pkey = $schema['primary key'][0];
  51. return array(
  52. 'field_name' => $table_name . '_relationship',
  53. 'type' => 'chado_linker__relationship',
  54. 'cardinality' => FIELD_CARDINALITY_UNLIMITED,
  55. 'locked' => FALSE,
  56. 'storage' => array(
  57. 'type' => 'field_chado_storage',
  58. ),
  59. 'settings' => array(
  60. 'chado_table' => $rel_table,
  61. 'chado_column' => $pkey,
  62. 'base_table' => $table_name,
  63. 'semantic_web' => 'SBO:0000374',
  64. ),
  65. );
  66. }
  67. /**
  68. * @see TripalField::create_instance_info()
  69. */
  70. function create_instance_info($entity_type, $bundle, $details) {
  71. if (!$this->can_attach($entity_type, $bundle, $details)) {
  72. return;
  73. }
  74. $table_name = $details['chado_table'];
  75. $type_table = $details['chado_type_table'];
  76. $type_field = $details['chado_type_column'];
  77. $cv_id = $details['chado_cv_id'];
  78. $cvterm_id = $details['chado_cvterm_id'];
  79. return array(
  80. 'field_name' => $table_name . '_relationship',
  81. 'entity_type' => $entity_type,
  82. 'bundle' => $bundle->name,
  83. 'label' => 'Relationships',
  84. 'description' => 'Other records with relationships to this record.',
  85. 'required' => FALSE,
  86. 'settings' => array(
  87. 'auto_attach' => FALSE,
  88. ),
  89. 'widget' => array(
  90. 'type' => 'chado_linker__relationship_widget',
  91. 'settings' => array(
  92. 'display_label' => 1,
  93. ),
  94. ),
  95. 'display' => array(
  96. 'deafult' => array(
  97. 'label' => 'above',
  98. 'type' => 'chado_linker__relationship_formatter',
  99. 'settings' => array(),
  100. ),
  101. ),
  102. );
  103. }
  104. /**
  105. * @see TripalField::widget_info()
  106. */
  107. function widget_info() {
  108. return array(
  109. 'label' => t('Relationship Settings'),
  110. 'field types' => array('chado_linker__relationship')
  111. );
  112. }
  113. /**
  114. * @see TripalField::formatter_info()
  115. */
  116. function formatter_info() {
  117. return array(
  118. 'label' => t('Relationships'),
  119. 'field types' => array('chado_linker__relationship'),
  120. 'settings' => array(
  121. ),
  122. );
  123. }
  124. /**
  125. * @see TripalField::formatter_view()
  126. */
  127. function formatter_view(&$element, $entity_type, $entity,
  128. $field, $instance, $langcode, $items, $display) {
  129. // Get the settings
  130. $settings = $display['settings'];
  131. $rows = array();
  132. $headers = array('Subject' ,'Type', 'Object');
  133. $headers = array('Relationship');
  134. foreach ($items as $delta => $item) {
  135. if (!$item['value']) {
  136. continue;
  137. }
  138. $subject_name = $item['value']['subject']['name'];
  139. $subject_type = $item['value']['subject']['type'];
  140. $object_name = $item['value']['object']['name'];
  141. $object_type = $item['value']['object']['type'];
  142. $phrase = $item['value']['phrase'];
  143. // Handle some special cases.
  144. // For mRNA objects we don't want to show the CDS, exons, 5' UTR, etc.
  145. // we want to show the parent gene and the protein.
  146. if ($object_type == 'mRNA' and ($subject_type != 'polypeptide')) {
  147. continue;
  148. }
  149. if ($subject_type == 'mRNA' and ($object_type != 'gene')) {
  150. continue;
  151. }
  152. $phrase = preg_replace("/$subject_type/", "<b>$subject_type</b>", $phrase);
  153. $phrase = preg_replace("/$object_type/", "<b>$object_type</b>", $phrase);
  154. if (array_key_exists('entity_id', $item['value']['object'])) {
  155. $object_entity_id = $item['value']['object']['entity_id'];
  156. if ($object_entity_id != $entity->id) {
  157. $link = l($object_name, 'bio_data/' . $object_entity_id);
  158. $phrase = preg_replace("/$object_name/", $link, $phrase);
  159. }
  160. }
  161. if (array_key_exists('entity_id', $item['value']['subject'])) {
  162. $subject_entity_id = $item['value']['subject']['entity_id'];
  163. if ($subject_entity_id != $entity->id) {
  164. $link = l($subject_name, 'bio_data/' . $subject_entity_id);
  165. $phrase = preg_replace("/$subject_name/", $link, $phrase);
  166. }
  167. }
  168. $rows[] = array($phrase);
  169. }
  170. // the $table array contains the headers and rows array as well as other
  171. // options for controlling the display of the table. Additional
  172. // documentation can be found here:
  173. // https://api.drupal.org/api/drupal/includes%21theme.inc/function/theme_table/7
  174. $table = array(
  175. 'header' => $headers,
  176. 'rows' => $rows,
  177. 'attributes' => array(
  178. 'id' => 'chado-linker--relationship-table',
  179. 'class' => 'tripal-data-table'
  180. ),
  181. 'sticky' => FALSE,
  182. 'caption' => '',
  183. 'colgroups' => array(),
  184. 'empty' => 'There are no relationships',
  185. );
  186. // once we have our table array structure defined, we call Drupal's theme_table()
  187. // function to generate the table.
  188. if (count($items) > 0) {
  189. $element[0] = array(
  190. '#type' => 'markup',
  191. '#markup' => theme_table($table),
  192. );
  193. }
  194. }
  195. /**
  196. * @see TripalField::widget_form()
  197. */
  198. function widget_form(&$widget, &$form, &$form_state, $field, $instance,
  199. $langcode, $items, $delta, $element) {
  200. $field_name = $field['field_name'];
  201. $field_type = $field['type'];
  202. $field_table = $field['settings']['chado_table'];
  203. $field_column = $field['settings']['chado_column'];
  204. // Get the FK column that links to the base table.
  205. $chado_table = $field['settings']['chado_table'];
  206. $base_table = $field['settings']['base_table'];
  207. $schema = chado_get_schema($chado_table);
  208. $pkey = $schema['primary key'][0];
  209. $fkeys = array_values($schema['foreign keys'][$base_table]['columns']);
  210. $fkey = $fkeys[0];
  211. // Get the field defaults.
  212. $record_id = '';
  213. $fkey_value = $element['#entity']->chado_record_id;
  214. $subject_id = '';
  215. $subject_uniquename = '';
  216. $type_id = '';
  217. $type = '';
  218. $object_id = '';
  219. $object_uniquename = '';
  220. $value = '';
  221. $rank = '';
  222. // If the field already has a value then it will come through the $items
  223. // array. This happens when editing an existing record.
  224. if (array_key_exists($delta, $items)) {
  225. $record_id = $items[$delta][$field_table . '__' . $pkey];
  226. $subject_id = $items[$delta][$field_table . '__subject_id'];
  227. $type_id = $items[$delta][$field_table . '__type_id'];
  228. $object_id = $items[$delta][$field_table . '__object_id'];
  229. if (array_key_exists('value', $schema['fields'])) {
  230. $value = $items[$delta][$field_table . '__value'];
  231. }
  232. if (array_key_exists('rank', $schema['fields'])) {
  233. $rank = $items[$delta][$field_table . '__rank'];
  234. }
  235. $object_uniquename = $items[$delta]['object_name'];
  236. $subject_uniquename = $items[$delta]['subject_name'];
  237. $type = $items[$delta]['type_name'];
  238. }
  239. // Check $form_state['values'] to see if an AJAX call set the values.
  240. if (array_key_exists('values', $form_state) and array_key_exists($delta, $form_state['values'])) {
  241. $record_id = tripal_chado_get_field_form_values($field_name, $form_state, $delta, $field_table . '__' . $pkey);
  242. $subject_id = tripal_chado_get_field_form_values($field_name, $form_state, $delta, $field_table . '__subject_id');
  243. $subject_uniquename = tripal_chado_get_field_form_values($field_name, $form_state, $delta, 'subject_name');
  244. $type_id = tripal_chado_get_field_form_values($field_name, $form_state, $delta, $field_table . '__type_id');
  245. $type = tripal_chado_get_field_form_values($field_name, $form_state, $delta, 'type_name');
  246. $object_id = tripal_chado_get_field_form_values($field_name, $form_state, $delta, $field_table . '__object_id');
  247. $object_uniquename = tripal_chado_get_field_form_values($field_name, $form_state, $delta, 'object_name');
  248. $value = tripal_chado_get_field_form_values($field_name, $form_state, $delta, $field_table . '__value');
  249. $rank = tripal_chado_get_field_form_values($field_name, $form_state, $delta, $field_table . '__rank');
  250. }
  251. $widget['#table_name'] = $chado_table;
  252. $widget['#fkeys'] = $schema['foreign keys'];
  253. $widget['#base_table'] = $base_table;
  254. $widget['#chado_record_id'] = $form['#entity']->chado_record_id;
  255. //$widget['#element_validate'] = array('chado_linker__relationship_validate');
  256. $widget['#theme'] = 'chado_linker__relationship_widget';
  257. $widget['#prefix'] = "<span id='$chado_table-$delta'>";
  258. $widget['#suffix'] = "</span>";
  259. $widget['value'] = array(
  260. '#type' => 'value',
  261. '#value' => array_key_exists($delta, $items) ? $items[$delta]['value'] : '',
  262. );
  263. $widget[$field_table . '__' . $pkey] = array(
  264. '#type' => 'value',
  265. '#default_value' => $record_id,
  266. );
  267. $widget[$field_table . '__subject_id'] = array(
  268. '#type' => 'value',
  269. '#default_value' => $subject_id,
  270. );
  271. $widget[$field_table . '__type_id'] = array(
  272. '#type' => 'value',
  273. '#default_value' => $type_id,
  274. );
  275. $widget[$field_table . '__object_id'] = array(
  276. '#type' => 'value',
  277. '#default_value' => $object_id,
  278. );
  279. if (array_key_exists('value', $schema['fields'])) {
  280. $widget[$field_table . '__value'] = array(
  281. '#type' => 'value',
  282. '#default_value' => $value,
  283. );
  284. }
  285. if (array_key_exists('rank', $schema['fields'])) {
  286. $widget[$field_table . '__rank'] = array(
  287. '#type' => 'value',
  288. '#default_value' => $rank,
  289. );
  290. }
  291. $widget['subject_name'] = array(
  292. '#type' => 'textfield',
  293. '#title' => t('Subject'),
  294. '#default_value' => $subject_uniquename,
  295. '#required' => $element['#required'],
  296. '#maxlength' => array_key_exists('length', $schema['fields']['subject_id']) ? $schema['fields']['subject_id']['length'] : 255,
  297. '#size' => 35,
  298. '#autocomplete_path' => "admin/tripal/storage/chado/auto_name/$base_table",
  299. );
  300. $default_cv = tripal_get_default_cv($field_table, 'type_id');
  301. $options = array();
  302. if (!$default_cv) {
  303. drupal_set_message("There is no default vocabulary set for the relationships....");
  304. }
  305. else {
  306. $options = tripal_get_cvterm_select_options($default_cv->cv_id, TRUE);
  307. }
  308. $widget['type_name'] = array(
  309. '#type' => 'select',
  310. '#title' => t('Type'),
  311. '#options' => $options,
  312. '#required' => $element['#required'],
  313. '#default_value' => $type_id,
  314. );
  315. $widget['object_name'] = array(
  316. '#type' => 'textfield',
  317. '#title' => t('Object'),
  318. '#default_value' => $object_uniquename,
  319. '#required' => $element['#required'],
  320. '#maxlength' => array_key_exists('length', $schema['fields']['object_id']) ? $schema['fields']['object_id']['length'] : 255,
  321. '#size' => 35,
  322. '#autocomplete_path' => "admin/tripal/storage/chado/auto_name/$base_table",
  323. );
  324. }
  325. /**
  326. * @see TripalField::validate()
  327. */
  328. function validate($entity_type, $entity, $field, $instance, $langcode, $items, &$errors) {
  329. $field_name = $field['field_name'];
  330. $field_type = $field['type'];
  331. $field_table = $field['settings']['chado_table'];
  332. $field_column = $field['settings']['chado_column'];
  333. $base_table = $field['settings']['base_table'];
  334. $chado_record_id = $entity->chado_record_id;
  335. $schema = chado_get_schema($field_table);
  336. $fkeys = $schema['foreign keys'];
  337. foreach ($items as $delta => $item) {
  338. $subject_id = $item[$field_table . '__subject_id'];
  339. $object_id = $item[ $field_table . '__object_id'];
  340. $type_id = $item[$field_table . '__type_id'];
  341. $type_name = $item['type_name'];
  342. $subject_name = $item['subject_name'];
  343. $object_name = $item['object_name'];
  344. // If the row is empty then just continue, there's nothing to validate.
  345. if (!$type_name and !$subject_name and !$object_name) {
  346. continue;
  347. }
  348. // Make sure we have values for all of the fields.
  349. $form_error = FALSE;
  350. if (!$type_name) {
  351. $errors[$field['field_name']][$langcode][$delta][] = array(
  352. 'error' => 'chado_linker__relationship',
  353. 'message' => t("Please provide the type of relationship."),
  354. );
  355. }
  356. if (!$subject_name) {
  357. $errors[$field['field_name']][$langcode][$delta][] = array(
  358. 'error' => 'chado_linker__relationship',
  359. 'message' => t("Please provide the subject of the relationship."),
  360. );
  361. }
  362. if (!$object_name) {
  363. $errors[$field['field_name']][$langcode][$delta][] = array(
  364. 'error' => 'chado_linker__relationship',
  365. 'message' => t("Please provide the object of the relationship."),
  366. );
  367. }
  368. if ($form_error) {
  369. continue;
  370. }
  371. // Before submitting this form we need to make sure that our subject_id and
  372. // object_ids are real values. There are two ways to get the value, either
  373. // just with the text value or with an [id: \d+] string embedded. If the
  374. // later we will pull it out.
  375. $subject_id = '';
  376. $fkey_rcolumn = $fkeys[$base_table]['columns']['subject_id'];
  377. $matches = array();
  378. if (preg_match('/\[id: (\d+)\]/', $subject_name, $matches)) {
  379. $subject_id = $matches[1];
  380. $values = array($fkey_rcolumn => $subject_id);
  381. $subject = chado_select_record($base_table, array($fkey_rcolumn), $values);
  382. if (count($subject) == 0) {
  383. $errors[$field['field_name']][$langcode][$delta][] = array(
  384. 'error' => 'chado_linker__relationship',
  385. 'message' => t("The subject record cannot be found using the specified id (e.g. [id: xx])."),
  386. );
  387. }
  388. }
  389. else {
  390. $values = array('uniquename' => $subject_name);
  391. $subject = chado_select_record($base_table, array($fkey_rcolumn), $values);
  392. if (count($subject) == 0) {
  393. $errors[$field['field_name']][$langcode][$delta][] = array(
  394. 'error' => 'chado_linker__relationship',
  395. 'message' => t("The subject record cannot be found. Please check spelling."),
  396. );
  397. }
  398. elseif (count($subject) > 1) {
  399. $errors[$field['field_name']][$langcode][$delta][] = array(
  400. 'error' => 'chado_linker__relationship',
  401. 'message' => t("The subject is not unique and therefore the relationship cannot be made."),
  402. );
  403. }
  404. }
  405. // Now check for a matching object.
  406. $object_id = '';
  407. $fkey_rcolumn = $fkeys[$base_table]['columns']['object_id'];
  408. $matches = array();
  409. if (preg_match('/\[id: (\d+)\]/', $object_name, $matches)) {
  410. $object_id = $matches[1];
  411. $values = array($fkey_rcolumn => $object_id);
  412. $object = chado_select_record($base_table, array($fkey_rcolumn), $values);
  413. if (count($subject) == 0) {
  414. $errors[$field['field_name']][$langcode][$delta][] = array(
  415. 'error' => 'chado_linker__relationship',
  416. 'message' => t("The object record cannot be found using the specified id (e.g. [id: xx])."),
  417. );
  418. }
  419. }
  420. else {
  421. $values = array('uniquename' => $object_name);
  422. $object = chado_select_record($base_table, array($fkey_rcolumn), $values);
  423. if (count($object) == 0) {
  424. $errors[$field['field_name']][$langcode][$delta][] = array(
  425. 'error' => 'chado_linker__relationship',
  426. 'message' => t("The object record cannot be found. Please check spelling."),
  427. );;
  428. }
  429. elseif (count($object) > 1) {
  430. $errors[$field['field_name']][$langcode][$delta][] = array(
  431. 'error' => 'chado_linker__relationship',
  432. 'message' => t("The object is not unique and therefore the relationship cannot be made."),
  433. );
  434. }
  435. }
  436. // Make sure that either our object or our subject refers to the base record.
  437. if ($object_id != $chado_record_id and $subject_id != $chado_record_id) {
  438. $errors[$field['field_name']][$langcode][$delta][] = array(
  439. 'error' => 'chado_linker__relationship',
  440. 'message' => t("Either the subject or the object in the relationship must refer to this record."),
  441. );
  442. }
  443. // Make sure that the object and subject are not both the same thing.
  444. if ($object_id == $subject_id) {
  445. $errors[$field['field_name']][$langcode][$delta][] = array(
  446. 'error' => 'chado_linker__relationship',
  447. 'message' => t("The subject and the object in the relationship cannot both refer to the same record."),
  448. );
  449. }
  450. }
  451. }
  452. /**
  453. * @see TripalField::submit()
  454. */
  455. public function submit($entity_type, $entity, $field, $instance, $langcode,
  456. &$items, $form, &$form_state) {
  457. $field_name = $field['field_name'];
  458. $field_type = $field['type'];
  459. $field_table = $field['settings']['chado_table'];
  460. $field_column = $field['settings']['chado_column'];
  461. $base_table = $field['settings']['base_table'];
  462. $chado_record_id = $entity->chado_record_id;
  463. $schema = chado_get_schema($field_table);
  464. $fkeys = $schema['foreign keys'];
  465. foreach ($items as $delta => $item) {
  466. $subject_id = $item[$field_table . '__subject_id'];
  467. $object_id = $item[ $field_table . '__object_id'];
  468. $type_id = $item[$field_table . '__type_id'];
  469. $type_name = $item['type_name'];
  470. $subject_name = $item['subject_name'];
  471. $object_name = $item['object_name'];
  472. // If the row is empty then skip this one, there's nothing to validate.
  473. if (!$type_name and !$subject_name and !$object_name) {
  474. continue;
  475. }
  476. // Get the subject ID.
  477. $subject_id = '';
  478. $fkey_rcolumn = $fkeys[$base_table]['columns']['subject_id'];
  479. $matches = array();
  480. if (preg_match('/\[id: (\d+)\]/', $subject_name, $matches)) {
  481. $subject_id = $matches[1];
  482. }
  483. else {
  484. $values = array('uniquename' => $subject_name);
  485. $subject = chado_select_record($base_table, array($fkey_rcolumn), $values);
  486. $subject_id = $subject[0]->$fkey_rcolumn;
  487. }
  488. // Get the object ID.
  489. $object_id = '';
  490. $fkey_rcolumn = $fkeys[$base_table]['columns']['object_id'];
  491. $matches = array();
  492. if (preg_match('/\[id: (\d+)\]/', $object_name, $matches)) {
  493. $object_id = $matches[1];
  494. }
  495. else {
  496. $values = array('uniquename' => $object_name);
  497. $object = chado_select_record($base_table, array($fkey_rcolumn), $values);
  498. $object_id = $object[0]->$fkey_rcolumn;
  499. }
  500. // Set the IDs according to the values that were determined above.
  501. $items[$delta][$field_table . '__subject_id'] = $subject_id;
  502. $items[$delta][$field_table . '__object_id'] = $object_id;
  503. $items[$delta][$field_table . '__type_id'] = $type_name;
  504. $items[$delta][$field_table . '__rank'] = $item['_weight'];
  505. }
  506. }
  507. /**
  508. * @see TripalField::load()
  509. */
  510. function load($field, $entity, $details) {
  511. $settings = $field['settings'];
  512. $record = $details['record'];
  513. $field_name = $field['field_name'];
  514. $field_type = $field['type'];
  515. $field_table = $field['settings']['chado_table'];
  516. $field_column = $field['settings']['chado_column'];
  517. $base_table = $field['settings']['base_table'];
  518. // Get the PKey for this table
  519. $schema = chado_get_schema($field_table);
  520. $pkey = $schema['primary key'][0];
  521. // Get the Pkeys for the subject and object tables
  522. $subject_fkey_table = '';
  523. $object_fkey_table = '';
  524. $fkeys = $schema['foreign keys'];
  525. foreach ($fkeys as $fktable => $details) {
  526. foreach ($details['columns'] as $fkey_lcolumn => $fkey_rcolumn) {
  527. if ($fkey_lcolumn == 'subject_id') {
  528. $subject_fkey_table = $fktable;
  529. }
  530. if ($fkey_lcolumn == 'object_id') {
  531. $object_fkey_table = $fktable;
  532. }
  533. }
  534. }
  535. $subject_schema = chado_get_schema($subject_fkey_table);
  536. $object_schema = chado_get_schema($object_fkey_table);
  537. $subject_pkey = $subject_schema['primary key'][0];
  538. $object_pkey = $object_schema['primary key'][0];
  539. // Get the FK that links to the base record.
  540. $schema = chado_get_schema($field_table);
  541. $fkey_lcolumn = key($schema['foreign keys'][$base_table]['columns']);
  542. $fkey_rcolumn = $schema['foreign keys'][$base_table]['columns'][$fkey_lcolumn];
  543. // Set some defaults for the empty record.
  544. // TODO: don't hardcode the uniquename as all tables won't have that.
  545. $entity->{$field_name}['und'][0] = array(
  546. 'value' => array(),
  547. $field_table . '__' . $pkey => '',
  548. $field_table . '__subject_id' => '',
  549. $field_table . '__object_id' => '',
  550. $field_table . '__type_id' => '',
  551. // These elements don't need to follow the naming scheme above
  552. // becasue we don't need the chado_field_storage to try and
  553. // save these values.
  554. 'object_name' => '',
  555. 'subject_name' => '',
  556. 'type_name' => '',
  557. );
  558. if (array_key_exists('value', $schema['fields'])) {
  559. $entity->{$field_name}['und'][0][$field_table . '__value'] = '';
  560. }
  561. if (array_key_exists('rank', $schema['fields'])) {
  562. $entity->{$field_name}['und'][0][$field_table . '__rank'] = '';
  563. }
  564. if (!$record) {
  565. return;
  566. }
  567. // Expand the object to include the relationships.
  568. $options = array(
  569. 'return_array' => 1,
  570. // we don't want to fully recurse we only need information about the
  571. // relationship type and the object and subject
  572. 'include_fk' => array(
  573. 'type_id' => 1,
  574. 'object_id' => array(
  575. 'type_id' => 1,
  576. ),
  577. 'subject_id' => array(
  578. 'type_id' => 1,
  579. ),
  580. ),
  581. );
  582. $rel_table = $base_table . '_relationship';
  583. $schema = chado_get_schema($rel_table);
  584. if (array_key_exists('rank', $schema['fields'])) {
  585. $options['order_by'] = array('rank' => 'ASC');
  586. }
  587. $record = chado_expand_var($record, 'table', $rel_table, $options);
  588. if (!$record->$rel_table) {
  589. return;
  590. }
  591. $srelationships = $record->$rel_table->subject_id;
  592. $orelationships = $record->$rel_table->object_id;
  593. $i = 0;
  594. if ($orelationships) {
  595. foreach ($orelationships as $relationship) {
  596. $rel_acc = $relationship->type_id->dbxref_id->db_id->name . ':' . $relationship->type_id->dbxref_id->accession;
  597. $rel_type = $relationship->type_id->name;
  598. $verb = $this->get_rel_verb($rel_type);
  599. $subject_name = $relationship->subject_id->name;
  600. $subject_type = $relationship->subject_id->type_id->name;
  601. $object_name = $relationship->object_id->name;
  602. $object_type = $relationship->object_id->type_id->name;
  603. $entity->{$field_name}['und'][$i]['value'] = array(
  604. '@type' => $rel_acc,
  605. 'subject' => array(
  606. '@type' => $relationship->subject_id->type_id->dbxref_id->db_id->name .
  607. ':' . $relationship->subject_id->type_id->dbxref_id->accession,
  608. 'type' => $subject_type,
  609. 'name' => $subject_name,
  610. ),
  611. 'type' => $relationship->type_id->name,
  612. 'object' => array(
  613. '@type' => $relationship->object_id->type_id->dbxref_id->db_id->name .
  614. ':' . $relationship->object_id->type_id->dbxref_id->accession,
  615. // TODO the entity_id should not be here.... wherre to put it.
  616. 'entity_id' => $entity->id,
  617. 'entity_type' => 'TripalEntity',
  618. 'type' => $object_type,
  619. 'name' => $object_name,
  620. )
  621. );
  622. if (property_exists($relationship->subject_id, 'uniquename')) {
  623. $subject_name = $relationship->subject_id->uniquename;
  624. $entity->{$field_name}['und'][$i]['value']['subject']['name'] = $subject_name;
  625. }
  626. if (property_exists($relationship->object_id, 'uniquename')) {
  627. $object_name = $relationship->object_id->uniquename;
  628. $entity->{$field_name}['und'][$i]['value']['object']['name'] = $object_name;
  629. }
  630. if (property_exists($relationship->subject_id, 'entity_id')) {
  631. $entity_id = $relationship->subject_id->entity_id;
  632. $entity->{$field_name}['und'][$i]['value']['subject']['entity_id'] = $entity_id;
  633. $entity->{$field_name}['und'][$i]['value']['subject']['entity_type'] = 'TripalEntity';
  634. }
  635. $rel_type_clean = lcfirst(preg_replace('/_/', ' ', $rel_type));
  636. $entity->{$field_name}['und'][$i]['value']['phrase'] = 'The ' . $subject_type . ', ' .
  637. $subject_name . ', ' . $verb . ' ' . $rel_type_clean . ' this ' .
  638. $object_type . '.';
  639. $entity->{$field_name}['und'][$i][$field_table . '__' . $pkey] = $relationship->$pkey;
  640. $entity->{$field_name}['und'][$i][$field_table . '__subject_id'] = $relationship->subject_id->$subject_pkey;
  641. $entity->{$field_name}['und'][$i][$field_table . '__type_id'] = $relationship->type_id->cvterm_id;
  642. $entity->{$field_name}['und'][$i][$field_table . '__object_id'] = $relationship->object_id->$object_pkey;
  643. $entity->{$field_name}['und'][$i]['type_name'] = $relationship->type_id->name;
  644. $entity->{$field_name}['und'][$i]['subject_name'] = $relationship->subject_id->uniquename . ' [id: ' . $relationship->subject_id->$fkey_rcolumn . ']';
  645. $entity->{$field_name}['und'][$i]['object_name'] = $relationship->object_id->uniquename . ' [id: ' . $relationship->object_id->$fkey_rcolumn . ']';
  646. if (array_key_exists('value', $schema['fields'])) {
  647. $entity->{$field_name}['und'][$i][$field_table . '__value'] = $relationship->value;
  648. }
  649. if (array_key_exists('rank', $schema['fields'])) {
  650. $entity->{$field_name}['und'][$i][$field_table . '__rank'] = $relationship->rank;
  651. }
  652. $i++;
  653. }
  654. }
  655. if ($srelationships) {
  656. foreach ($srelationships as $relationship) {
  657. $rel_acc = $relationship->type_id->dbxref_id->db_id->name . ':' . $relationship->type_id->dbxref_id->accession;
  658. $rel_type = $relationship->type_id->name;
  659. $verb = $this->get_rel_verb($rel_type);
  660. $subject_name = $relationship->subject_id->name;
  661. $subject_type = $relationship->subject_id->type_id->name;
  662. $object_name = $relationship->object_id->name;
  663. $object_type = $relationship->object_id->type_id->name;
  664. $entity->{$field_name}['und'][$i]['value'] = array(
  665. '@type' => $rel_acc,
  666. 'subject' => array(
  667. '@type' => $relationship->subject_id->type_id->dbxref_id->db_id->name .
  668. ':' . $relationship->subject_id->type_id->dbxref_id->accession,
  669. 'type' => $subject_type,
  670. 'name' => $subject_name,
  671. 'entity_id' => $entity->id,
  672. 'entity_type' => 'TripalEntity',
  673. ),
  674. 'type' => $relationship->type_id->name,
  675. 'object' => array(
  676. '@type' => $relationship->object_id->type_id->dbxref_id->db_id->name .
  677. ':' . $relationship->object_id->type_id->dbxref_id->accession,
  678. 'type' => $object_type,
  679. 'name' => $object_name,
  680. )
  681. );
  682. if (property_exists($relationship->subject_id, 'uniquename')) {
  683. $subject_name = $relationship->subject_id->uniquename;
  684. $entity->{$field_name}['und'][$i]['value']['subject']['name'] = $subject_name;
  685. }
  686. if (property_exists($relationship->object_id, 'uniquename')) {
  687. $object_name = $relationship->object_id->uniquename;
  688. $entity->{$field_name}['und'][$i]['value']['object']['name'] = $object_name;
  689. }
  690. if (property_exists($relationship->object_id, 'entity_id')) {
  691. $entity_id = $relationship->object_id->entity_id;
  692. $entity->{$field_name}['und'][$i]['value']['object']['entity_id'] = $entity_id;
  693. $entity->{$field_name}['und'][$i]['value']['object']['entity_type'] = 'TripalEntity';
  694. }
  695. $rel_type_clean = lcfirst(preg_replace('/_/', ' ', $rel_type));
  696. $entity->{$field_name}['und'][$i]['value']['phrase'] = 'This ' .
  697. $subject_type . ' ' . $verb . ' ' . $rel_type_clean . ' the ' .
  698. $object_type . ', ' . $object_name . '.';
  699. $entity->{$field_name}['und'][$i][$field_table . '__' . $pkey] = $relationship->$pkey;
  700. $entity->{$field_name}['und'][$i][$field_table . '__subject_id'] = $relationship->subject_id->$subject_pkey;
  701. $entity->{$field_name}['und'][$i][$field_table . '__type_id'] = $relationship->type_id->cvterm_id;
  702. $entity->{$field_name}['und'][$i][$field_table . '__object_id'] = $relationship->object_id->$object_pkey;
  703. $entity->{$field_name}['und'][$i]['type_name'] = $relationship->type_id->name;
  704. $entity->{$field_name}['und'][$i]['subject_name'] = $relationship->subject_id->uniquename . ' [id: ' . $relationship->subject_id->$fkey_rcolumn . ']';
  705. $entity->{$field_name}['und'][$i]['object_name'] = $relationship->object_id->uniquename . ' [id: ' . $relationship->object_id->$fkey_rcolumn . ']';
  706. if (array_key_exists('value', $schema['fields'])) {
  707. $entity->{$field_name}['und'][$i][$field_table . '__value'] = $relationship->value;
  708. }
  709. if (array_key_exists('rank', $schema['fields'])) {
  710. $entity->{$field_name}['und'][$i][$field_table . '__rank'] = $relationship->rank;
  711. }
  712. $i++;
  713. }
  714. }
  715. }
  716. /**
  717. * A helper function to define English verbs for relationship types.
  718. *
  719. * @param $rel_type
  720. * The vocabulary term name for the relationship.
  721. *
  722. * @return
  723. * The verb to use when creating a sentence of the relationship.
  724. */
  725. private function get_rel_verb($rel_type) {
  726. $rel_type_clean = lcfirst(preg_replace('/_/', ' ', $rel_type));
  727. $verb = $rel_type_clean;
  728. switch ($rel_type_clean) {
  729. case 'integral part of':
  730. case 'instance of':
  731. $verb = 'is an';
  732. break;
  733. case 'proper part of':
  734. case 'transformation of':
  735. case 'genome of':
  736. case 'part of':
  737. $verb = 'is a';
  738. case 'position of':
  739. case 'sequence of':
  740. case 'variant of':
  741. $verb = 'is a';
  742. break;
  743. case 'derives from':
  744. case 'connects on':
  745. case 'contains':
  746. case 'finishes':
  747. case 'guides':
  748. case 'has origin':
  749. case 'has part':
  750. case 'has quality':
  751. case 'is consecutive sequence of':
  752. case 'maximally overlaps':
  753. case 'overlaps':
  754. case 'starts':
  755. break;
  756. default:
  757. $verb = 'is';
  758. }
  759. return $verb;
  760. }
  761. }
  762. /**
  763. * Theme function for the chado_linker__relationship_widget.
  764. */
  765. function theme_chado_linker__relationship_widget($variables) {
  766. $element = $variables['element'];
  767. $field_name = $element['#field_name'];
  768. $field = field_info_field($field_name);
  769. $field_type = $field['type'];
  770. $field_table = $field['settings']['chado_table'];
  771. $field_column = $field['settings']['chado_column'];
  772. $layout = "
  773. <div class=\"chado-linker--relationship-widget\">
  774. <div class=\"chado-linker--relationship-widget-item\">" .
  775. drupal_render($element['subject_name']) . "
  776. </div>
  777. <div class=\"chado-linker--relationship-widget-item\">" .
  778. drupal_render($element['type_name']) . "
  779. </div>
  780. <div class=\"chado-linker--relationship-widget-item\">" .
  781. drupal_render($element['object_name']) . "
  782. </div>
  783. </div>
  784. ";
  785. return $layout;
  786. }