tripal_phylogeny.chado_node.inc 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782
  1. <?php
  2. /**
  3. * @file
  4. * Implements the phylotree node content type
  5. */
  6. /**
  7. * Implements hook_node_info().
  8. *
  9. * Provide information to drupal about the node types that we're creating
  10. * in this module.
  11. *
  12. * @ingroup tripal_legacy_phylogeny
  13. */
  14. function tripal_phylogeny_node_info() {
  15. $nodes = array();
  16. $nodes['chado_phylotree'] = array(
  17. 'name' => t('Phylotree (Tripal v2 legacy)'),
  18. 'base' => 'chado_phylotree',
  19. 'description' => t('A phylotree from the chado database'),
  20. 'has_title' => TRUE,
  21. 'locked' => TRUE,
  22. 'chado_node_api' => array(
  23. 'base_table' => 'phylotree',
  24. 'hook_prefix' => 'chado_phylotree',
  25. 'record_type_title' => array(
  26. 'singular' => t('Phylotree'),
  27. 'plural' => t('Phylotrees')
  28. ),
  29. /* sync_filters: tripal is hardcoded to look for this
  30. sync_filter settings: type_id and organism_id. (phylotree does
  31. not have organism_id but need to set it false anyways. */
  32. 'sync_filters' => array(
  33. 'type_id' => FALSE,
  34. 'organism_id' => FALSE
  35. ),
  36. )
  37. );
  38. return $nodes;
  39. }
  40. /**
  41. * Implements hook_node_view(). Acts on all content types
  42. *
  43. * @ingroup tripal_legacy_phylogeny
  44. */
  45. function tripal_phylogeny_node_view($node, $view_mode, $langcode) {
  46. if($node->type != 'chado_phylotree') { return; }
  47. switch($view_mode) {
  48. case 'full':
  49. $node->content['tripal_phylogeny_base'] = array(
  50. '#theme' => 'tripal_phylogeny_base',
  51. '#node' => $node,
  52. '#tripal_toc_id' => 'base',
  53. '#tripal_toc_title' => 'Overview',
  54. '#weight' => -100,
  55. );
  56. $node->content['tripal_phylogeny_phylogram'] = array(
  57. '#theme' => 'tripal_phylogeny_phylogram',
  58. '#node' => $node,
  59. '#tripal_toc_id' => 'phylotree_phylogram',
  60. '#tripal_toc_title' => 'Phylogram',
  61. '#weight' => -90,
  62. );
  63. $node->content['tripal_phylogeny_taxonomic_tree'] = array(
  64. '#theme' => 'tripal_phylogeny_taxonomic_tree',
  65. '#node' => $node,
  66. '#tripal_toc_id' => 'tripal_phylogeny_taxonomic_tree',
  67. '#tripal_toc_title' => 'Taxonomic Tree',
  68. '#weight' => -80,
  69. );
  70. $node->content['tripal_phylogeny_organisms'] = array(
  71. '#theme' => 'tripal_phylogeny_organisms',
  72. '#node' => $node,
  73. '#tripal_toc_id' => 'phylotree_organisms',
  74. '#tripal_toc_title' => 'Organisms',
  75. '#weight' => -70,
  76. );
  77. $node->content['tripal_phylogeny_references'] = array(
  78. '#theme' => 'tripal_phylogeny_references',
  79. '#node' => $node,
  80. '#tripal_toc_id' => 'phylotree_references',
  81. '#tripal_toc_title' => 'Cross References',
  82. );
  83. $node->content['tripal_phylogeny_analysis'] = array(
  84. '#theme' => 'tripal_phylogeny_analysis',
  85. '#node' => $node,
  86. '#tripal_toc_id' => 'phylotree_analysis',
  87. '#tripal_toc_title' => 'Analysis',
  88. );
  89. break;
  90. case 'teaser':
  91. $node->content['tripal_phylogeny_teaser'] = array(
  92. '#theme' => 'tripal_phylogeny_teaser',
  93. '#node' => $node,
  94. );
  95. break;
  96. }
  97. }
  98. /**
  99. * Implementation of hook_form().
  100. *
  101. * @ingroup tripal_legacy_phylogeny
  102. */
  103. function chado_phylotree_form($node, &$form_state) {
  104. $form = array();
  105. // Default values can come in the following ways:
  106. //
  107. // 1) as elements of the $node object. This occurs when editing an existing phylotree
  108. // 2) in the $form_state['values'] array which occurs on a failed validation or
  109. // ajax callbacks from non submit form elements
  110. // 3) in the $form_state['input'[ array which occurs on ajax callbacks from submit
  111. // form elements and the form is being rebuilt
  112. //
  113. // set form field defaults
  114. $phylotree = null;
  115. $phylotree_id = null;
  116. $tree_name = '';
  117. $leaf_type = '';
  118. $analysis_id = '';
  119. $dbxref = '';
  120. $comment = '';
  121. $tree_required = TRUE;
  122. $tree_file = '';
  123. $name_re = '';
  124. $match = '';
  125. // If we are editing an existing node then the phylotree is already part of the node.
  126. if (property_exists($node, 'phylotree')) {
  127. $phylotree = $node->phylotree;
  128. $phylotree = chado_expand_var($phylotree, 'field', 'phylotree.comment');
  129. $phylotree_id = $phylotree->phylotree_id;
  130. $tree_name = $phylotree->name;
  131. $leaf_type = $phylotree->type_id ? $phylotree->type_id->name : '';
  132. $comment = $phylotree->comment;
  133. $analysis_id = $phylotree->analysis_id ? $phylotree->analysis_id->analysis_id : '';
  134. $dbxref = $phylotree->dbxref_id->db_id->name . ":" . $phylotree->dbxref_id->accession;
  135. $name_re = $phylotree->tripal_variables->phylotree_name_re;
  136. $match = $phylotree->tripal_variables->phylotree_use_uniquename;
  137. // If the dbxref is the null db then hide it.
  138. if ($phylotree->dbxref_id->db_id->name == 'null') {
  139. $dbxref = '';
  140. }
  141. // Get the tree file name. If the file was added via the Drupal interface
  142. // then a numeric file_id will be present in the phylotree_tree_file
  143. // variable. If not then the tree was loaded on the command-line and
  144. // the actual filename is in this variable.
  145. $file_id = $phylotree->tripal_variables->phylotree_tree_file;
  146. if (is_numeric($file_id)) {
  147. $file = file_load($file_id);
  148. if ($file) {
  149. $tree_file = $file->filename;
  150. }
  151. }
  152. else {
  153. $tree_file = $file_id;
  154. }
  155. // The tree file is not a required input field when editing the node.
  156. $tree_required = FALSE;
  157. // Keep track of the phylotree id.
  158. $form['phylotree_id'] = array(
  159. '#type' => 'value',
  160. '#value' => $phylotree_id,
  161. );
  162. }
  163. // If we are re constructing the form from a failed validation or ajax callback
  164. // then use the $form_state['values'] values.
  165. if (array_key_exists('values', $form_state) and isset($form_state['values']['tree_name'])) {
  166. $tree_name = $form_state['values']['tree_name'];
  167. $leaf_type = $form_state['values']['leaf_type'];
  168. $analysis_id = $form_state['values']['analysis_id'];
  169. $dbxref = $form_state['values']['dbxref'];
  170. $comment = $form_state['values']['description'];
  171. }
  172. // If we are re building the form from after submission (from ajax call) then
  173. // the values are in the $form_state['input'] array.
  174. if (array_key_exists('input', $form_state) and !empty($form_state['input'])) {
  175. $tree_name = $form_state['input']['tree_name'];
  176. $leaf_type = $form_state['input']['leaf_type'];
  177. $analysis_id = $form_state['input']['analysis_id'];
  178. $comment = $form_state['input']['description'];
  179. $dbxref = $form_state['input']['dbxref'];
  180. }
  181. $form['tree_name']= array(
  182. '#type' => 'textfield',
  183. '#title' => t('Tree Name'),
  184. '#required' => TRUE,
  185. '#default_value' => $tree_name,
  186. '#description' => t('Enter the name used to refer to this phylogenetic tree.'),
  187. '#maxlength' => 255
  188. );
  189. $type_cv = tripal_get_default_cv('phylotree', 'type_id');
  190. $so_cv = tripal_get_cv(array('name' => 'sequence'));
  191. $cv_id = $so_cv->cv_id;
  192. if (!$so_cv) {
  193. drupal_set_message('The Sequence Ontolgoy does not appear to be imported.
  194. Please import the Sequence Ontology before adding a tree.', 'error');
  195. }
  196. $form['leaf_type'] = array(
  197. '#title' => t('Tree Type'),
  198. '#type' => 'textfield',
  199. '#description' => t("Choose the tree type. The type is
  200. a valid Sequence Ontology (SO) term. For example, trees derived
  201. from protein sequences should use the SO term 'polypeptide'.
  202. Alternatively, a phylotree can be used for representing a taxonomic
  203. tree. In this case, the word 'taxonomy' should be used."),
  204. '#required' => TRUE,
  205. '#default_value' => $leaf_type,
  206. '#autocomplete_path' => "admin/tripal/legacy/tripal_cv/cvterm/auto_name/$cv_id",
  207. );
  208. // Get the list of analyses.
  209. $sql = "SELECT * FROM {analysis} ORDER BY name";
  210. $arset = chado_query($sql);
  211. $analyses = array();
  212. $analyses[''] = '';
  213. while ($analysis = $arset->fetchObject()) {
  214. $analyses[$analysis->analysis_id] = $analysis->name;
  215. }
  216. $form['analysis_id'] = array(
  217. '#title' => t('Analysis'),
  218. '#type' => 'select',
  219. '#description' => t("Choose the analysis from which this phylogenetic tree was derived"),
  220. '#required' => TRUE,
  221. '#default_value' => $analysis_id,
  222. '#options' => $analyses,
  223. );
  224. $form['dbxref'] = array(
  225. '#title' => t('Database Cross-Reference'),
  226. '#type' => 'textfield',
  227. '#description' => t("Enter a database cross-reference of the form
  228. [DB name]:[accession]. The database name must already exist in the
  229. database. If the accession does not exist it is automatically added."),
  230. '#required' => FALSE,
  231. '#default_value' => $dbxref,
  232. );
  233. $form['description']= array(
  234. '#type' => 'textarea',
  235. '#title' => t('Description'),
  236. '#required' => TRUE,
  237. '#default_value' => $comment,
  238. '#description' => t('Enter a description for this tree.'),
  239. );
  240. $upload_location = tripal_get_files_stream('tripal_phylogeny');
  241. $form['tree_file'] = array(
  242. '#type' => 'fieldset',
  243. '#title' => t('Tree File Import'),
  244. '#collapsible' => FALSE,
  245. );
  246. $description = t('Please provide a file in the Newick format that contains
  247. the nodes of this tree.');
  248. if ($tree_file) {
  249. $form['tree_file']['curr_file'] = array(
  250. '#type' => 'item',
  251. '#title' => 'Current Tree File',
  252. '#markup' => $tree_file,
  253. );
  254. $description = t('Please provide a file in the Newick format that
  255. contains the nodes of this tree. Please note that uploading a new
  256. file will overwrite the current tree.');
  257. }
  258. $form['tree_file']['tree_file'] = array(
  259. '#type' => 'managed_file',
  260. '#title' => t('New Tree File'),
  261. '#description' => $description,
  262. '#upload_location' => $upload_location,
  263. '#upload_validators' => array(
  264. // We don't want to require a specific file extension so leave the array empty.
  265. 'file_validate_extensions' => array(),
  266. // The following is for checking the Newick file format.
  267. 'chado_phylotree_validate_newick_format' => array(),
  268. ),
  269. '#required' => $tree_required,
  270. );
  271. $form['tree_file']['name_re'] = array(
  272. '#title' => t('Feature Name Regular Expression'),
  273. '#type' => 'textfield',
  274. '#description' => t('If this is a phylogenetic (non taxonomic) tree, then
  275. the tree nodes will be automatically associated with features. However,
  276. if the nodes in the tree file are not exactly as the names of features
  277. but have enough information to uniquely identify the feature then you
  278. may provide a regular expression that the importer will use to extract
  279. the feature names from the node names.'),
  280. '#default_value' => $name_re,
  281. );
  282. $form['tree_file']['match'] = array(
  283. '#title' => t('Use Unique Feature Name'),
  284. '#type' => 'checkbox',
  285. '#description' => t('If this is a phylogenetic (non taonomic tree) and the nodes ' .
  286. 'should match the unique name of the feature rather than the name of the feautre ' .
  287. 'then select this box. If unselected the loader will try to match the feature ' .
  288. 'using the feature name.'),
  289. '#default_value' => $match,
  290. );
  291. return $form;
  292. }
  293. /**
  294. * A validation function for checking the newick file format.
  295. *
  296. * @param stdClass $file
  297. * A Drupal file object.
  298. */
  299. function chado_phylotree_validate_newick_format(stdClass $file) {
  300. // An array of strings where each string represents a unique error
  301. // when examining the file.
  302. $errors = array();
  303. // TODO: check the newick file format for errors.
  304. return $errors;
  305. }
  306. /**
  307. * Implementation of hook_validate().
  308. *
  309. * This validation is being used for three activities:
  310. * CASE A: Update a node that exists in both drupal and chado
  311. * CASE B: Synchronizing a node from chado to drupal
  312. * CASE C: Inserting a new node that exists in niether drupal nor chado
  313. *
  314. * @ingroup tripal_legacy_phylogeny
  315. */
  316. function chado_phylotree_validate($node, $form, &$form_state) {
  317. // We are syncing if we do not have a node ID but we do have a phylotree_id. We don't
  318. // need to validate during syncing so just skip it.
  319. if (is_null($node->nid) and property_exists($node, 'phylotree_id') and $node->phylotree_id != 0) {
  320. return;
  321. }
  322. // Remove surrounding white-space on submitted values.
  323. $node->tree_name = trim($node->tree_name);
  324. $node->description = trim($node->description);
  325. $node->dbxref = trim($node->dbxref);
  326. // if this is a delete then don't validate
  327. if ($node->op == 'Delete') {
  328. return;
  329. }
  330. $errors = array();
  331. $warnings = array();
  332. $options = array(
  333. 'name' => $node->tree_name,
  334. 'description' => $node->description,
  335. 'analysis_id' => $node->analysis_id,
  336. 'leaf_type' => $node->leaf_type,
  337. 'tree_file' => $node->tree_file,
  338. 'format' => 'newick',
  339. 'dbxref' => $node->dbxref,
  340. 'match' => $node->match,
  341. 'name_re' => $node->name_re,
  342. );
  343. // If we have a node id already then this is an update:
  344. if ($node->nid) {
  345. $options['phylotree_id'] = $node->phylotree_id;
  346. tripal_validate_phylotree('update', $options, $errors, $warnings);
  347. }
  348. else {
  349. tripal_validate_phylotree('insert', $options, $errors, $warnings);
  350. }
  351. // Now set form errors if any errors were detected.
  352. if (count($errors) > 0) {
  353. foreach($errors as $field => $message) {
  354. if ($field == 'name') {
  355. $field = 'tree_name';
  356. }
  357. form_set_error($field, $message);
  358. }
  359. }
  360. // Add any warnings if any were detected
  361. if (count($warnings) > 0) {
  362. foreach($warnings as $field => $message) {
  363. drupal_set_message($message, 'warning');
  364. }
  365. }
  366. }
  367. /**
  368. * Implements hook_node_presave(). Acts on all node content types.
  369. *
  370. * @ingroup tripal_legacy_phylogeny
  371. */
  372. function tripal_phylogeny_node_presave($node) {
  373. switch ($node->type) {
  374. // This step is for setting the title for the Drupal node. This title
  375. // is permanent and thus is created to be unique. Title changes provided
  376. // by tokens are generated on the fly dynamically, but the node title
  377. // seen in the content listing needs to be set here. Do not call
  378. // the chado_get_node_title() function here to set the title as the node
  379. // object isn't properly filled out and the function will fail.
  380. case 'chado_phylotree':
  381. // for a form submission the 'phylotreename' field will be set,
  382. // for a sync, we must pull from the phylotree object
  383. if (property_exists($node, 'phylotreename')) {
  384. // set the title
  385. $node->title = $node->tree_name;
  386. }
  387. else if (property_exists($node, 'phylotree')) {
  388. $node->title = $node->phylotree->name;
  389. }
  390. break;
  391. }
  392. }
  393. /**
  394. * Implements hook_node_insert().
  395. * Acts on all content types.
  396. *
  397. * @ingroup tripal_legacy_phylogeny
  398. */
  399. function tripal_phylogeny_node_insert($node) {
  400. switch ($node->type) {
  401. case 'chado_phylotree':
  402. $phylotree_id = chado_get_id_from_nid('phylotree', $node->nid);
  403. $values = array('phylotree_id' => $phylotree_id);
  404. $phylotree = chado_generate_var('phylotree', $values);
  405. $phylotree = chado_expand_var($phylotree, 'field', 'phylotree.comment');
  406. $node->phylotree = $phylotree;
  407. // Now use the API to set the path.
  408. chado_set_node_url($node);
  409. // Now get the title.
  410. $node->title = chado_get_node_title($node);
  411. break;
  412. }
  413. }
  414. /**
  415. * Implements hook_node_update().
  416. * Acts on all content types.
  417. *
  418. * @ingroup tripal_legacy_phylogeny
  419. */
  420. function tripal_phylogeny_node_update($node) {
  421. switch ($node->type) {
  422. case 'chado_phylotree':
  423. $phylotree_id = chado_get_id_from_nid('phylotree', $node->nid);
  424. $values = array('phylotree_id' => $phylotree_id);
  425. $phylotree = chado_generate_var('phylotree', $values);
  426. $phylotree = chado_expand_var($phylotree, 'field', 'phylotree.comment');
  427. $node->phylotree = $phylotree;
  428. // Now get the title
  429. $node->title = chado_get_node_title($node);
  430. break;
  431. }
  432. }
  433. /**
  434. * Implements [content_type]_chado_node_default_title_format().
  435. *
  436. * Defines a default title format for the Chado Node API to set the titles on
  437. * Chado phylotree nodes based on chado fields.
  438. *
  439. * @ingroup tripal_legacy_phylogeny
  440. */
  441. function chado_phylotree_chado_node_default_title_format() {
  442. return '[phylotree.name]';
  443. }
  444. /**
  445. * Implements hook_chado_node_default_url_format().
  446. *
  447. * Designates a default URL format for phylotree nodes.
  448. */
  449. function chado_phylotree_chado_node_default_url_format() {
  450. return '/phylotree/[phylotree.name]';
  451. }
  452. /**
  453. * Implements hook_insert().
  454. *
  455. * When a new chado_phylotree node is created we also need to add
  456. * information to our chado_phylotree table. This function is called
  457. * on insert of a new node of type 'chado_phylotree' and inserts the
  458. * necessary information.
  459. *
  460. * @ingroup tripal_legacy_phylogeny
  461. */
  462. function chado_phylotree_insert($node) {
  463. global $user;
  464. $node->tree_name = trim($node->tree_name);
  465. $node->description = trim($node->description);
  466. $node->dbxref = trim($node->dbxref);
  467. // if there is a phylotree_id in the $node object then this must
  468. // be a sync (not an insert) so we can skip adding the phylotree as it is
  469. // already there, although we do need to proceed with the rest of the
  470. // insert.
  471. $phylotree_id = NULL;
  472. if (!property_exists($node, 'phylotree_id')) {
  473. $options = array(
  474. 'name' => $node->tree_name,
  475. 'description' => $node->description,
  476. 'analysis_id' => $node->analysis_id,
  477. 'leaf_type' => $node->leaf_type,
  478. 'tree_file' => $node->tree_file,
  479. 'format' => 'newick',
  480. 'dbxref' => $node->dbxref,
  481. 'match' => $node->match,
  482. 'name_re' => $node->name_re,
  483. );
  484. $errors = array();
  485. $warnings = array();
  486. if (tripal_insert_phylotree($options, $errors, $warnings)) {
  487. $phylotree_id = $options['phylotree_id'];
  488. // Add the Tripal variables to this node.
  489. tripal_add_node_variable($node->nid, 'phylotree_name_re', $node->name_re);
  490. tripal_add_node_variable($node->nid, 'phylotree_use_uniquename', $node->match);
  491. tripal_add_node_variable($node->nid, 'phylotree_tree_file', $node->tree_file);
  492. }
  493. else {
  494. drupal_set_message(t('Unable to insert phylotree.'), 'error');
  495. tripal_report_error('tripal_phylogeny', TRIPAL_WARNING,
  496. 'Insert phylotree: Unable to insert phylotree where values: %values',
  497. array('%values' => print_r($options, TRUE))
  498. );
  499. }
  500. }
  501. else {
  502. $phylotree_id = $node->phylotree_id;
  503. }
  504. // Make sure the entry for this phylotree doesn't already exist in the
  505. // chado_phylotree table if it doesn't exist then we want to add it.
  506. $check_org_id = chado_get_id_from_nid('phylotree', $node->nid);
  507. if (!$check_org_id) {
  508. $record = new stdClass();
  509. $record->nid = $node->nid;
  510. $record->vid = $node->vid;
  511. $record->phylotree_id = $phylotree_id;
  512. drupal_write_record('chado_phylotree', $record);
  513. }
  514. }
  515. /**
  516. * Implements hook_update().
  517. *
  518. * @ingroup tripal_legacy_phylogeny
  519. */
  520. function chado_phylotree_update($node) {
  521. global $user;
  522. $node->tree_name = trim($node->tree_name);
  523. $node->description = trim($node->description);
  524. $node->dbxref = trim($node->dbxref);
  525. // Get the phylotree_id for this node.
  526. $phylotree_id = chado_get_id_from_nid('phylotree', $node->nid) ;
  527. $options = array(
  528. 'phylotree_id' => $node->phylotree_id,
  529. 'name' => $node->tree_name,
  530. 'description' => $node->description,
  531. 'analysis_id' => $node->analysis_id,
  532. 'leaf_type' => $node->leaf_type,
  533. 'tree_file' => $node->tree_file,
  534. 'format' => 'newick',
  535. 'dbxref' => $node->dbxref,
  536. 'match' => $node->match,
  537. 'name_re' => $node->name_re,
  538. );
  539. $success = tripal_update_phylotree($phylotree_id, $options);
  540. if (!$success) {
  541. drupal_set_message("Unable to update phylotree.", "error");
  542. tripal_report_error('tripal_phylogeny', TRIPAL_WARNING,
  543. 'Update phylotree: Unable to update phylotree where values: %values',
  544. array('%values' => print_r($options, TRUE))
  545. );
  546. return;
  547. }
  548. // Remove any variables and then add back the variables from the form.
  549. tripal_delete_node_variables($node->nid);
  550. tripal_add_node_variable($node->nid, 'phylotree_name_re', $node->name_re);
  551. tripal_add_node_variable($node->nid, 'phylotree_use_uniquename', $node->match);
  552. tripal_add_node_variable($node->nid, 'phylotree_tree_file', $node->tree_file);
  553. }
  554. /**
  555. * Implements hook_load().
  556. *
  557. * When a node is requested by the user this function is called to allow us
  558. * to add auxiliary data to the node object.
  559. *
  560. * @ingroup tripal_legacy_phylogeny
  561. */
  562. function chado_phylotree_load($nodes) {
  563. foreach ($nodes as $nid => $node) {
  564. $phylotree_id = chado_get_id_from_nid('phylotree', $nid);
  565. // If the nid does not have a matching record then skip this node.
  566. // this can happen with orphaned nodes.
  567. if (!$phylotree_id) {
  568. continue;
  569. }
  570. // Build the Chado variable for the phylotree.
  571. $values = array('phylotree_id' => $phylotree_id);
  572. $phylotree = chado_generate_var('phylotree', $values);
  573. $nodes[$nid]->phylotree = $phylotree;
  574. // Expand the comment field, chado_generate_var() omits it by default
  575. // because it is a large text field.
  576. $phylotree = chado_expand_var($phylotree, 'field', 'phylotree.comment');
  577. // Add non Chado information to the object. These variables are needed
  578. // for the edit/update forms.
  579. $phylotree->tripal_variables = new stdClass;
  580. $variables = tripal_get_node_variables($nid, 'phylotree_name_re');
  581. $phylotree->tripal_variables->phylotree_name_re = count($variables) > 0 ? $variables[0]->value : '';
  582. $variables = tripal_get_node_variables($nid, 'phylotree_use_uniquename');
  583. $phylotree->tripal_variables->phylotree_use_uniquename = count($variables) > 0 ? $variables[0]->value : '';
  584. $variables = tripal_get_node_variables($nid, 'phylotree_tree_file');
  585. $phylotree->tripal_variables->phylotree_tree_file = count($variables) > 0 ? $variables[0]->value : '';
  586. // Set the title for this node.
  587. $node->title = chado_get_node_title($node);
  588. }
  589. }
  590. /**
  591. * Implements hook_delete().
  592. *
  593. * Delete data from drupal and chado databases when a node is deleted
  594. *
  595. * @ingroup tripal_legacy_phylogeny
  596. */
  597. function chado_phylotree_delete(&$node) {
  598. $phylotree_id = chado_get_id_from_nid('phylotree', $node->nid);
  599. // if we don't have a phylotree id for this node then this isn't a node of
  600. // type chado_phylotree or the entry in the chado_phylotree table was lost.
  601. if (!$phylotree_id) {
  602. return;
  603. }
  604. // Remove data from {chado_phylotree}, {node} and {node_revisions} tables of
  605. // drupal database
  606. $sql_del = "DELETE FROM {chado_phylotree} WHERE nid = :nid AND vid = :vid";
  607. db_query($sql_del, array(':nid' => $node->nid, ':vid' => $node->vid));
  608. $sql_del = "DELETE FROM {node_revision} WHERE nid = :nid AND vid = :vid";
  609. db_query($sql_del, array(':nid' => $node->nid, ':vid' => $node->vid));
  610. $sql_del = "DELETE FROM {node} WHERE nid = :nid AND vid = :vid";
  611. db_query($sql_del, array(':nid' => $node->nid, ':vid' => $node->vid));
  612. // Remove data from phylotree and phylotreeprop tables of chado
  613. // database as well
  614. chado_query("DELETE FROM {phylotree} WHERE phylotree_id = :phylotree_id", array(':phylotree_id' => $phylotree_id));
  615. }
  616. /**
  617. * Implement hook_node_access().
  618. *
  619. * This hook allows node modules to limit access to the node types they define.
  620. *
  621. * @param $node
  622. * The node on which the operation is to be performed, or, if it does not yet exist, the
  623. * type of node to be created
  624. *
  625. * @param $op
  626. * The operation to be performed
  627. *
  628. * @param $account
  629. * A user object representing the user for whom the operation is to be performed
  630. *
  631. * @return
  632. * If the permission for the specified operation is not set then return FALSE. If the
  633. * permission is set then return NULL as this allows other modules to disable
  634. * access. The only exception is when the $op == 'create'. We will always
  635. * return TRUE if the permission is set.
  636. *
  637. * @ingroup tripal_legacy_phylogeny
  638. */
  639. function chado_phylotree_node_access($node, $op, $account) {
  640. $node_type = $node;
  641. if (is_object($node)) {
  642. $node_type = $node->type;
  643. }
  644. if($node_type == 'chado_phylotree') {
  645. if ($op == 'create') {
  646. if (!user_access('create chado_phylotree content', $account)) {
  647. return NODE_ACCESS_DENY;
  648. }
  649. return NODE_ACCESS_ALLOW;
  650. }
  651. if ($op == 'update') {
  652. if (!user_access('edit chado_phylotree content', $account)) {
  653. return NODE_ACCESS_DENY;
  654. }
  655. }
  656. if ($op == 'delete') {
  657. if (!user_access('delete chado_phylotree content', $account)) {
  658. return NODE_ACCESS_DENY;
  659. }
  660. }
  661. if ($op == 'view') {
  662. if (!user_access('access chado_phylotree content', $account)) {
  663. return NODE_ACCESS_DENY;
  664. }
  665. }
  666. return NODE_ACCESS_IGNORE;
  667. }
  668. }
  669. /**
  670. * Phylotree feature summary.
  671. *
  672. * Get an array of feature counts by organism. key = organism
  673. * abbreviation. value = number of features for this phylotree having
  674. * this organism.
  675. *
  676. * @param int phylotree_id
  677. * @return array
  678. * @ingroup tripal_legacy_phylogeny
  679. */
  680. function phylotree_feature_summary($phylotree_id) {
  681. $sql = "
  682. SELECT o.abbreviation, COUNT(o.organism_id) AS count
  683. FROM {phylonode} n
  684. LEFT OUTER JOIN {feature} f ON n.feature_id = f.feature_id
  685. LEFT OUTER JOIN {organism} o ON f.organism_id = o.organism_id
  686. WHERE n.phylotree_id = :phylotree_id
  687. AND n.feature_id IS NOT NULL
  688. GROUP BY o.organism_id
  689. ";
  690. $args = array(':phylotree_id' => $phylotree_id);
  691. $result = chado_query($sql, $args);
  692. $summary = array();
  693. foreach($result as $r) {
  694. $summary[$r->abbreviation] = $r->count;
  695. }
  696. return $summary;
  697. }