tripal_chado.custom_tables.inc 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455
  1. <?php
  2. /**
  3. * @file
  4. * Contains functions for creating, editing and deleting custom tables
  5. * on the Tripal website.
  6. *
  7. */
  8. /**
  9. * Provides a landing page for administrating custom tables.
  10. */
  11. function tripal_custom_table_admin_view() {
  12. $output = '';
  13. // set the breadcrumb
  14. $breadcrumb = [];
  15. $breadcrumb[] = l('Home', '<front>');
  16. $breadcrumb[] = l('Administration', 'admin');
  17. $breadcrumb[] = l('Tripal', 'admin/tripal');
  18. $breadcrumb[] = l('Chado Schema', 'admin/tripal/storage/chado');
  19. $breadcrumb[] = l('Custom Tables', 'admin/tripal/storage/chado/custom_tables');
  20. drupal_set_breadcrumb($breadcrumb);
  21. // Add the view
  22. $view = views_embed_view('tripal_admin_custom_table', 'default');
  23. if (isset($view)) {
  24. $output .= $view;
  25. }
  26. else {
  27. $output .= '<p>The Tripal Custom Table management system uses primarily views to provide an '
  28. . 'administrative interface. Currently one or more views needed for this '
  29. . 'administrative interface are disabled. <strong>Click each of the following links to '
  30. . 'enable the pertinent views</strong>:</p>';
  31. $output .= '<ul>';
  32. $output .= '<li>' . l('Custom Tables View', 'admin/tripal/storage/chado/custom_tables/views/tables/enable') . '</li>';
  33. $output .= '</ul>';
  34. }
  35. return $output;
  36. }
  37. /**
  38. * Renders the tripal_custom_tables_form.
  39. *
  40. */
  41. function tripal_custom_table_new_page() {
  42. $form = drupal_get_form('tripal_custom_tables_form');
  43. return drupal_render($form);
  44. }
  45. /**
  46. * A template function which returns markup to display details for the custom
  47. * table
  48. *
  49. * @param $table_id
  50. * The unique ID of the custom table
  51. *
  52. */
  53. function tripal_custom_table_view($table_id) {
  54. // get this custom_table details
  55. $sql = "SELECT * FROM {tripal_custom_tables} WHERE table_id = :table_id";
  56. $results = db_query($sql, [':table_id' => $table_id]);
  57. $custom_table = $results->fetchObject();
  58. // create a table with each row containig stats for
  59. // an individual job in the results set.
  60. $return_url = url("admin/tripal/storage/chado/custom_tables");
  61. $output = "<p><a href=\"$return_url\">" . t("Return to list of custom tables") . "</a></p>";
  62. $output .= "<br />";
  63. $output .= "<p>Details for <b>$custom_table->table_name</b>:</p>";
  64. $output .= "<br />";
  65. $output .= "<table class=\"border-table\">";
  66. if ($custom_table->table_name) {
  67. $output .= " <tr>" .
  68. " <th>Table Name</th>" .
  69. " <td>$custom_table->table_name</td>" .
  70. " </tr>";
  71. }
  72. if ($custom_table->schema) {
  73. $output .= " <tr>" .
  74. " <th>Table Field Definitions</th>" .
  75. " <td><pre>" . var_export(unserialize($custom_table->schema), 1) . "</pre></td>" .
  76. " </tr>";
  77. }
  78. // build the URLs using the url function so we can handle installations where
  79. // clean URLs are or are not used
  80. $delete_url = url("admin/tripal/storage/chado/custom_tables/delete/$custom_table->table_id");
  81. $edit_url = url("admin/tripal/storage/chado/custom_tables/edit/$custom_table->table_id");
  82. $output .= "<tr><th>Actions</th>" .
  83. "<td>" .
  84. " <a href='$edit_url'>Edit</a>, " .
  85. " <a href='$delete_url'>Delete</a></td></tr>";
  86. $output .= "</table>";
  87. return $output;
  88. }
  89. /**
  90. * A Form to Create/Edit a Custom table.
  91. *
  92. * @param $form_state
  93. * The current state of the form (Form API)
  94. * @param $table_id
  95. * The unique ID of the Custom table to Edit or NULL if creating a new table
  96. *
  97. * @return
  98. * A form array (Form API)
  99. *
  100. */
  101. function tripal_custom_tables_form($form, &$form_state = NULL, $table_id = NULL) {
  102. // set the breadcrumb
  103. $breadcrumb = [];
  104. $breadcrumb[] = l('Home', '<front>');
  105. $breadcrumb[] = l('Administration', 'admin');
  106. $breadcrumb[] = l('Tripal', 'admin/tripal');
  107. $breadcrumb[] = l('Chado Schema', 'admin/tripal/storage/chado');
  108. $breadcrumb[] = l('Custom Tables', 'admin/tripal/storage/chado/custom_tables');
  109. drupal_set_breadcrumb($breadcrumb);
  110. if (!$table_id) {
  111. $action = 'Add';
  112. }
  113. else {
  114. $action = 'Edit';
  115. }
  116. // get this requested table
  117. $default_schema = '';
  118. $default_force_drop = 0;
  119. $default_is_base = 0;
  120. if (strcmp($action, 'Edit') == 0) {
  121. $sql = "SELECT * FROM {tripal_custom_tables} WHERE table_id = :table_id ";
  122. $results = db_query($sql, [':table_id' => $table_id]);
  123. $custom_table = $results->fetchObject();
  124. // if this is a materialized view then don't allow editing with this function
  125. if (property_exists($custom_table, 'mview_id') and $custom_table->mview_id) {
  126. drupal_set_message("This custom table is a materialized view. Please use the " . l('Materialized View', 'admin/tripal/storage/chado/mviews') . " interface to edit it.", 'error');
  127. drupal_goto("admin/tripal/storage/chado/custom_tables");
  128. return [];
  129. }
  130. // set the default values. If there is a value set in the
  131. // form_state then let's use that, otherwise, we'll pull
  132. // the values from the database
  133. if (array_key_exists('values', $form_state)) {
  134. $default_schema = $form_state['values']['schema'];
  135. $default_force_drop = $form_state['values']['force_drop'];
  136. $default_is_base = $form_state['values']['is_base'];
  137. }
  138. else {
  139. $default_is_base = $custom_table->is_base;
  140. }
  141. if (!$default_schema) {
  142. $default_schema = var_export(unserialize($custom_table->schema), 1);
  143. $default_schema = preg_replace('/=>\s+\n\s+array/', '=> array', $default_schema);
  144. }
  145. }
  146. // Build the form
  147. $form['action'] = [
  148. '#type' => 'value',
  149. '#value' => $action,
  150. ];
  151. $form['table_id'] = [
  152. '#type' => 'value',
  153. '#value' => $table_id,
  154. ];
  155. $form['instructions'] = [
  156. '#type' => 'fieldset',
  157. '#title' => 'Instructions',
  158. '#collapsible' => TRUE,
  159. '#collapsed' => TRUE,
  160. ];
  161. $form['instructions']['text'] = [
  162. '#type' => 'item',
  163. '#markup' => '<p>' . t('At times it is necessary to add a custom table
  164. to the Chado schema. These are not offically sanctioned tables but may
  165. be necessary for local data requirements. Avoid creating custom tables
  166. when possible as other GMOD tools may not recognize these tables nor
  167. the data in them. Linker tables or property tables are often a good
  168. candidate for a custom table. For example a table to link stocks and
  169. libraries (e.g. library_stock). Try to model linker or propery tables
  170. after existing tables. If the table already exists it will not be
  171. modified. To force dropping and recreation of the table
  172. click the checkbox below. Tables are defined using the ' .
  173. l('Drupal Schema API', 'https://api.drupal.org/api/drupal/includes!database!schema.inc/group/schemaapi/7',
  174. ['attributes' => ['target' => '_blank']]) . '</p>' .
  175. '<p>Please note that table names should be all lower-case.</p>'
  176. ),
  177. ];
  178. $form['instructions']['example'] = [
  179. '#type' => 'item',
  180. '#markup' => "Example library_stock table: <pre>
  181. array (
  182. 'table' => 'library_stock',
  183. 'fields' => array (
  184. 'library_stock_id' => array(
  185. 'type' => 'serial',
  186. 'not null' => TRUE,
  187. ),
  188. 'library_id' => array(
  189. 'type' => 'int',
  190. 'not null' => TRUE,
  191. ),
  192. 'stock_id' => array(
  193. 'type' => 'int',
  194. 'not null' => TRUE,
  195. ),
  196. ),
  197. 'primary key' => array(
  198. 'library_stock_id'
  199. ),
  200. 'unique keys' => array(
  201. 'library_stock_c1' => array(
  202. 'library_id',
  203. 'stock_id'
  204. ),
  205. ),
  206. 'foreign keys' => array(
  207. 'library' => array(
  208. 'table' => 'library',
  209. 'columns' => array(
  210. 'library_id' => 'library_id',
  211. ),
  212. ),
  213. 'stock' => array(
  214. 'table' => 'stock',
  215. 'columns' => array(
  216. 'stock_id' => 'stock_id',
  217. ),
  218. ),
  219. ),
  220. )
  221. </pre>",
  222. ];
  223. $form['force_drop'] = [
  224. '#type' => 'checkbox',
  225. '#title' => t('Re-create table'),
  226. '#description' => t('Check this box if your table already exists and you would like to drop it and recreate it.'),
  227. '#default_value' => $default_force_drop,
  228. ];
  229. $form['is_base'] = [
  230. '#type' => 'checkbox',
  231. '#title' => t('Is this a base table?'),
  232. '#description' => t('Check this box if this custom table will contain records '.
  233. 'that can be published. For example, tables such as "feature", ' .
  234. '"stock", "analysis" are all tables in Chado that contain "base" ' .
  235. 'records that can be published and anciallary data attached via '.
  236. 'fields. If selected, site admins can create new content types ' .
  237. 'that resolve to this table.'),
  238. '#default_value' => $default_is_base,
  239. ];
  240. $form['schema'] = [
  241. '#type' => 'textarea',
  242. '#title' => t('Schema Array'),
  243. '#description' => t('Please enter the ' . l('Drupal Schema API', 'https://api.drupal.org/api/drupal/includes!database!schema.inc/group/schemaapi/7', ['attributes' => ['target' => '_blank']]) . ' compatible array that defines the table.'),
  244. '#required' => FALSE,
  245. '#default_value' => $default_schema,
  246. '#rows' => 25,
  247. ];
  248. if ($action == 'Edit') {
  249. $value = 'Save';
  250. }
  251. if ($action == 'Add') {
  252. $value = 'Add';
  253. }
  254. $form['submit'] = [
  255. '#type' => 'submit',
  256. '#value' => t($value),
  257. '#executes_submit_callback' => TRUE,
  258. ];
  259. $form['cancel'] = [
  260. '#type' => 'markup',
  261. '#markup' => l('Cancel', 'admin/tripal/storage/chado/custom_tables'),
  262. ];
  263. return $form;
  264. }
  265. /**
  266. * Implements hook_validate().
  267. * Validate the Create/Edit custom table form.
  268. *
  269. */
  270. function tripal_custom_tables_form_validate($form, &$form_state) {
  271. $action = $form_state['values']['action'];
  272. $table_id = $form_state['values']['table_id'];
  273. $schema = $form_state['values']['schema'];
  274. $force_drop = $form_state['values']['force_drop'];
  275. if (!$schema) {
  276. form_set_error($form_state['values']['schema'], t('Schema array field is required.'));
  277. }
  278. // make sure the array is valid
  279. $schema_array = [];
  280. if ($schema) {
  281. $success = preg_match('/^\s*array/', $schema);
  282. if (!$success) {
  283. form_set_error($form_state['values']['schema'],
  284. t("The schema array should begin with the word 'array'."));
  285. }
  286. else {
  287. $success = eval("\$schema_array = $schema;");
  288. if ($success === FALSE) {
  289. $error = error_get_last();
  290. form_set_error('schema', t("The schema array is improperly formatted. Parse Error : " . $error["message"]));
  291. }
  292. if (is_array($schema_array) and !array_key_exists('table', $schema_array)) {
  293. form_set_error('schema', t("The schema array must have key named 'table'"));
  294. }
  295. // validate the contents of the array
  296. $error = chado_validate_custom_table_schema($schema_array);
  297. if ($error) {
  298. form_set_error('schema', $error);
  299. }
  300. if ($action == 'Edit') {
  301. // see if the table name has changed. If so, then check to make sure
  302. // it doesn't already exists. We don't want to drop a table we didn't mean to
  303. $sql = "SELECT * FROM {tripal_custom_tables} WHERE table_id = :table_id";
  304. $results = db_query($sql, [':table_id' => $table_id]);
  305. $ct = $results->fetchObject();
  306. if ($ct->table_name != $schema_array['table']) {
  307. $exists = chado_table_exists($schema_array['table']);
  308. if ($exists) {
  309. form_set_error($form_state['values']['schema'],
  310. t("The table name already exists, please choose a different name."));
  311. }
  312. }
  313. }
  314. }
  315. }
  316. }
  317. /**
  318. * Submit the Create/Edit Custom table form
  319. * Implements hook_form_submit().
  320. *
  321. */
  322. function tripal_custom_tables_form_submit($form, &$form_state) {
  323. $ret = [];
  324. $action = $form_state['values']['action'];
  325. $table_id = $form_state['values']['table_id'];
  326. $schema = $form_state['values']['schema'];
  327. $force_drop = $form_state['values']['force_drop'];
  328. $is_base = $form_state['values']['is_base'];
  329. $skip_creation = 1;
  330. if ($force_drop) {
  331. $skip_creation = 0;
  332. }
  333. // convert the schema into a PHP array
  334. $schema_arr = [];
  335. eval("\$schema_arr = $schema;");
  336. if (strcmp($action, 'Edit') == 0) {
  337. chado_edit_custom_table($table_id, $schema_arr['table'], $schema_arr, $skip_creation, $is_base);
  338. }
  339. elseif (strcmp($action, 'Add') == 0) {
  340. chado_create_custom_table($schema_arr['table'], $schema_arr, $skip_creation,
  341. NULL, FALSE, $is_base);
  342. }
  343. else {
  344. drupal_set_message(t("No action performed."));
  345. }
  346. if ($is_base == 1) {
  347. drupal_set_message(t("The custom table is a base table. Before you can use this
  348. table for content publication you must 1) be sure to map
  349. the controlled vocabulary terms for the columns of this table prior
  350. to creating a new content type for this table. You can set the
  351. terms at !link",
  352. ['!link' => l('Admin > Tripal > Data Storage > Chado > Semantic Web', 'admin/tripal/storage/chado/semweb/' . $schema_arr['table'])]
  353. ));
  354. }
  355. drupal_goto("admin/tripal/storage/chado/custom_tables");
  356. }
  357. /**
  358. * Just a simple form for confirming deletion of a custom table
  359. *
  360. */
  361. function tripal_custom_tables_delete_form($form, &$form_state, $table_id) {
  362. // get details about this table entry
  363. $sql = "SELECT * FROM {tripal_custom_tables} WHERE table_id = :table_id";
  364. $results = db_query($sql, [':table_id' => $table_id]);
  365. $entry = $results->fetchObject();
  366. // if this is a materialized view then don't allow editing with this function
  367. if ($entry->mview_id) {
  368. drupal_set_message("This custom table is a materialized view. Please use the " . l('Materialized View', 'admin/tripal/storage/chado/mviews') . " interface to delete it.", 'error');
  369. drupal_goto("admin/tripal/storage/chado/custom_tables");
  370. return [];
  371. }
  372. $form = [];
  373. $form['table_id'] = [
  374. '#type' => 'value',
  375. '#value' => $table_id,
  376. ];
  377. $form['sure'] = [
  378. '#type' => 'markup',
  379. '#markup' => '<p>Are you sure you want to delete the "' . $entry->table_name . '" custom table?</p>',
  380. ];
  381. $form['submit'] = [
  382. '#type' => 'submit',
  383. '#value' => 'Delete',
  384. ];
  385. $form['cancel'] = [
  386. '#type' => 'submit',
  387. '#value' => 'Cancel',
  388. ];
  389. return $form;
  390. }
  391. /**
  392. * form submit hook for the tripal_custom_tables_delete_form form.
  393. *
  394. * @param $form
  395. * @param $form_state
  396. */
  397. function tripal_custom_tables_delete_form_submit($form, &$form_state) {
  398. $action = $form_state['clicked_button']['#value'];
  399. $table_id = $form_state['values']['table_id'];
  400. if (strcmp($action, 'Delete') == 0) {
  401. chado_delete_custom_table($table_id);
  402. }
  403. else {
  404. drupal_set_message(t("No action performed."));
  405. }
  406. drupal_goto("admin/tripal/storage/chado/custom_tables");
  407. }