tripal_core.custom_tables.inc 13 KB

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