tripal_views_integration.inc 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107
  1. <?php
  2. /**
  3. * @file
  4. * Functions related to the UI for integrating tables with views
  5. */
  6. /**
  7. * Purpose: Provide Guidance to new Tripal Admin
  8. *
  9. * @return
  10. * HTML Formatted text
  11. *
  12. * @ingroup tripal_views_integration
  13. */
  14. function tripal_views_description_page() {
  15. $text .= '<h3>Tripal Views Quick Links:</h3>';
  16. $text .= "<ul>
  17. <li><a href=\"" . url("admin/tripal/views/integration/list") . "\">List of integrated tables</a></li>
  18. <li><a href=\"" . url("admin/tripal/views/integration/new") . "\">Integrate a new table</a></li>
  19. <li><a href=\"" . url("admin/tripal/views/integration/import") . "\">Import a previously exported table integration.</a></li>
  20. </ul>";
  21. $text .= '<h3>Views Integration Description:</h3>';
  22. $text .= '<p>Tripal Views provides an interface for integrating <a href="http://drupal.org/project/views">Drupal Views</a>
  23. with Tripal materialized views. This will allow site administrators to create custom queries for the materialized views
  24. and in turn provide custom content pages, custom blocks and custom search forms. The forms allow a site administrator
  25. to select a materialized view and associate other Chado tables on which the view can join. Usage of this module requires
  26. a good understanding of foreign-key relationships in Chado.
  27. </p>';
  28. $text .= '<h3>Setup Instructions:</h3>';
  29. $text .= '<p>After installation of the Tripal core module. The following tasks should be performed
  30. <ol>
  31. <li><b>Set Permissions</b>: To allow access to site administrators for this module, simply
  32. <a href="' . url('admin/user/permissions') . '">assign permissions</a> to the appropriate user roles for the
  33. permission type "manage tripal_views_integration". </li>
  34. </ol>
  35. </p>';
  36. $text .= '<h3>Usage Instructions:</h3>';
  37. $text .= "<p>To use Tripal Views integration follow these steps:
  38. <ol>
  39. <li><b>Identify or create a materialized view:</b> Using the <a href=\"" . url("admin/tripal/views/mviews") . "\">
  40. Tripal materialized View</a> interface, identify the view you would like to integrate or create a new one.</li>
  41. <li><b>Setup the Views Integration</b>: Navigate to the <a href=\"" . url("admin/tripal/views/integration/mviews/new") . "\">
  42. Tripal views integration setup page</a> to integrate the selected materialized view. Provide a user friendly name
  43. and description to help you remember the purpose for integrating the view. Next, select the view you want to integrate
  44. from the provided select box. If your materialized view has fields that can join with other Chado tables, you may
  45. provide those relationships in the provided form. Finally, if your fields require a special handler for display, you
  46. may select it from the drop down provided</li>
  47. <li><b>Create custom pages/block/search form</b>: After saving setup information from step 2 above, you will be redirected to the
  48. Drupal Views interface</a> where you can create a custom page, block or search form.</li>
  49. <li><b>Review your integrated views</b>: A page providing a
  50. <a href=\"" . url("admin/tripal/views/integration/mviews/list") . "\">list of all integrated views</a> is provided. You may
  51. view this page to see all integrated views, but also to remove any unwanted integrations.</li>
  52. </ol>
  53. </p>";
  54. return $text;
  55. }
  56. /**
  57. * Purpose: Generates a themable table containing the list of integrated tables
  58. * The look-and-feel of the table can be altered by overriding the theme for
  59. * tables.
  60. *
  61. * @return
  62. * a themed HTML table
  63. *
  64. * @ingroup tripal_views_integration
  65. */
  66. function tripal_views_integration_setup_list() {
  67. $output = '';
  68. $output .= '<h3>' . l(t('Add a new entry'), "admin/tripal/views/integration/new") . " | " .
  69. l(t("Create Materialized View"), 'admin/build/views/add') . '</h3>';
  70. $output .= '<p>The following tables list the views integration setups available. If '
  71. .'there is more then one setup for a given table, then the setup with the lightest '
  72. .'priority will be used. For example, if you have created a custom setup for the '
  73. .'feature chado table and your setup has a priority of -5 then your setup will be '
  74. .'used instead of the default feature integration because -5 is lighter then 10.'
  75. .'Priorities use the Drupal -10 to +10 scale where a record with -10 has a '
  76. .'greater priority then one with 0 and both have a greater priority then one with +10.</p>';
  77. // Start with materialized views
  78. $output .= '<br /><h3>Materialized Views</h3>';
  79. $header = array('', 'Drupal Views Type Name', 'Table Name', 'Is Legacy?', 'Priority', 'Comment');
  80. $rows = array();
  81. // get the list of materialized views
  82. $tviews = db_query('SELECT tv.setup_id, tv.name, tv.table_name, tc.table_id, tv.priority, tv.comment '
  83. .'FROM {tripal_views} tv '
  84. .'LEFT JOIN {tripal_custom_tables} tc ON tc.table_name=tv.table_name '
  85. .'WHERE tv.mview_id IS NOT NULL '
  86. .'ORDER BY tv.table_name ASC, tv.priority ASC');
  87. while ($tview = db_fetch_object($tviews)) {
  88. $rows[] = array(
  89. l(t('Edit'), "admin/tripal/views/integration/edit/" . $tview->setup_id) . "<br />"
  90. . l(t('Export'), "admin/tripal/views/integration/export/" . $tview->setup_id) . "<br />"
  91. . l(t('Delete'), "admin/tripal/views/integration/delete/" . $tview->setup_id),
  92. $tview->name,
  93. $tview->table_name,
  94. ($tview->table_id) ? 'No' : 'Yes',
  95. $tview->priority,
  96. $tview->comment,
  97. );
  98. }
  99. if ($rows) {
  100. $output .= theme('table', $header, $rows);
  101. }
  102. else {
  103. $output .= '<p>There are currently no Materialized Views defined.</p>';
  104. }
  105. // Now list non-mview custom tables
  106. $output .= '<br /><h3>Custom Tables</h3>';
  107. $header = array('', 'Drupal Views Type Name', 'Table Name', 'Priority', 'Comment');
  108. $rows = array();
  109. // get the list of chado tables
  110. $tviews = db_query('SELECT tv.setup_id, tv.name, tv.table_name, tv.priority, tv.comment '
  111. .'FROM {tripal_views} tv '
  112. .'LEFT JOIN {tripal_custom_tables} tc ON tc.table_name=tv.table_name '
  113. .'WHERE mview_id IS NULL AND tc.table_id IS NOT NULL '
  114. .'ORDER BY table_name ASC, priority ASC');
  115. while ($tview = db_fetch_object($tviews)) {
  116. $rows[] = array(
  117. l(t('Edit'), "admin/tripal/views/integration/edit/" . $tview->setup_id) . "<br />"
  118. . l(t('Export'), "admin/tripal/views/integration/export/" . $tview->setup_id) . "<br />"
  119. . l(t('Delete'), "admin/tripal/views/integration/delete/" . $tview->setup_id),
  120. $tview->name,
  121. $tview->table_name,
  122. $tview->priority,
  123. $tview->comment,
  124. );
  125. }
  126. if ($rows) {
  127. $output .= theme('table', $header, $rows);
  128. }
  129. else {
  130. $output .= '<p>There are currently no non-Materialized View Custom Tables defined.</p>';
  131. }
  132. // Now list chado tables
  133. $output .= '<br /><h3>Chado Tables</h3>';
  134. $header = array('', 'Drupal Views Type Name', 'Table Name', 'Priority', 'Comment');
  135. $rows = array();
  136. // get the list of chado tables
  137. $tviews = db_query('SELECT tv.setup_id, tv.name, tv.table_name, tv.priority, tv.comment '
  138. .'FROM {tripal_views} tv '
  139. .'LEFT JOIN {tripal_custom_tables} tc ON tc.table_name=tv.table_name '
  140. .'WHERE mview_id IS NULL AND tc.table_id IS NULL '
  141. .'ORDER BY table_name ASC, priority ASC');
  142. while ($tview = db_fetch_object($tviews)) {
  143. $rows[] = array(
  144. l(t('Edit'), "admin/tripal/views/integration/edit/" . $tview->setup_id) . "<br />"
  145. . l(t('Export'), "admin/tripal/views/integration/export/" . $tview->setup_id) . "<br />"
  146. . l(t('Delete'), "admin/tripal/views/integration/delete/" . $tview->setup_id),
  147. $tview->name,
  148. $tview->table_name,
  149. $tview->priority,
  150. $tview->comment,
  151. );
  152. }
  153. $output .= theme('table', $header, $rows);
  154. return $output;
  155. }
  156. /**
  157. * Purpose: Deletes integration of a table with the Views module. This
  158. * function is meant to be called from a menu item. After completion it
  159. * redirects the user to the views intergation page.
  160. *
  161. * @param $setup_id
  162. * the unique setup id for the integrated table
  163. *
  164. * @ingroup tripal_views_integration
  165. */
  166. function tripal_views_integration_delete($setup_id) {
  167. tripal_views_integration_remove_entry_by_setup_id($setup_id);
  168. drupal_set_message(t("Record Deleted"));
  169. drupal_goto('admin/tripal/views/integration');
  170. }
  171. /**
  172. * Purpose: defines the web form used for specifing the base table, joins and
  173. * handlers when integrating a table with views. This form is used for both
  174. * creating a new record and editing an existing record.
  175. *
  176. * @param &$form_state
  177. * The form state which is passed automatically by drupal
  178. *
  179. * @param $setup_id
  180. * The unique setup for an integrated table. This value is only set when
  181. * the form is used for updating an existing record.
  182. *
  183. * @return
  184. * A proper Drupal form associative array.
  185. *
  186. * @ingroup tripal_views_integration
  187. */
  188. function tripal_views_integration_form(&$form_state, $setup_id = NULL) {
  189. $form = array();
  190. $data = array();
  191. $form['#cache'] = TRUE;
  192. // ahah_helper requires us to register the form with it's module
  193. ahah_helper_register($form, $form_state);
  194. // if a setup_id is provided then we want to get the form defaults
  195. $setup_obj = array();
  196. if (isset($setup_id)) {
  197. // get the deafult setup values
  198. $sql = "SELECT * FROM {tripal_views} WHERE setup_id = %d";
  199. $setup_obj = db_fetch_object(db_query($sql, $setup_id));
  200. $mview_id = $setup_obj->mview_id;
  201. $table_name = $setup_obj->table_name;
  202. $form_state['storage']['mview_id'] = $mview_id;
  203. $form_state['storage']['table_name'] = $table_name;
  204. // get the default field name/description
  205. $sql = "SELECT * FROM {tripal_views_field} WHERE setup_id=%d";
  206. $query = db_query($sql, $setup_id);
  207. $default_fields = array();
  208. while ($field = db_fetch_object($query)) {
  209. $default_fields[$field->column_name]['name'] = $field->name;
  210. $default_fields[$field->column_name]['description'] = $field->description;
  211. }
  212. // get the default join settings and handlers
  213. $sql = "SELECT * FROM {tripal_views_join} WHERE setup_id = %d";
  214. $query = db_query($sql, $setup_id);
  215. $default_joins = array();
  216. while ($join = db_fetch_object($query)) {
  217. $default_joins[$join->base_field]['left_table'] = $join->left_table;
  218. $default_joins[$join->base_field]['left_field'] = $join->left_field;
  219. }
  220. // get the default handlers
  221. $sql = "SELECT * FROM {tripal_views_handlers} WHERE setup_id = %d";
  222. $query = db_query($sql, $setup_id);
  223. $default_handlers = array();
  224. while ($handler = db_fetch_object($query)) {
  225. $default_handlers[$handler->column_name][$handler->handler_type]['handler_name'] = $handler->handler_name;
  226. $default_handlers[$handler->column_name][$handler->handler_type]['arguments'] = $handler->arguments;
  227. }
  228. // get the default join handlers
  229. $sql = "SELECT * FROM {tripal_views_join} WHERE setup_id = %d";
  230. $query = db_query($sql, $setup_id);
  231. while ($handler = db_fetch_object($query)) {
  232. $default_handlers[$handler->base_field]['join']['handler_name'] = $handler->handler;
  233. //$default_handlers[$handler->base_field]['join']['arguments'] = $handler->arguments;
  234. }
  235. // add in the setup_id for the form so we know this is an update not an insert
  236. $form['setup_id'] = array(
  237. '#type' => 'hidden',
  238. '#value' => $setup_id,
  239. );
  240. }
  241. // add a fieldset for the MView & Chado table selectors
  242. $form['base_table_type'] = array(
  243. '#type' => 'fieldset',
  244. '#title' => 'Base Table',
  245. '#description' => 'Please select either a materialized view or a Chado table for integration with '.
  246. 'Drupal Views. In Drupal Views terminology, the selected table becomes the "base table". '.
  247. 'After you select a table from either list, the fields from that table will appear below '.
  248. 'and you can specify other tables to join with and handlers.',
  249. );
  250. // build the form element for the Chado tables
  251. $chado_tables = tripal_core_get_chado_tables();
  252. $chado_tables = array_merge(array('Select'), $chado_tables);
  253. $form['base_table_type']['table_name'] = array(
  254. '#title' => t('Chado/Custom Table'),
  255. '#type' => 'select',
  256. '#options' => $chado_tables,
  257. '#description' => t('Tables from Chado, custom tables and materialized view tables (non-legacy MViews) can be selected for integration.'),
  258. '#default_value' => (!$setup_obj->mview_id) ? $setup_obj->table_name : '',
  259. '#ahah' => array(
  260. 'path' => ahah_helper_path(array('view_setup_table')),
  261. 'wrapper' => 'table-rows-div',
  262. 'effect' => 'fade',
  263. 'event' => 'change',
  264. 'method' => 'replace',
  265. ),
  266. );
  267. // build the form element that lists the materialized views
  268. $query = db_query("SELECT mview_id, name FROM {tripal_mviews} WHERE mv_schema is NULL or mv_schema = '' ORDER BY name");
  269. $mview_tables = array();
  270. $mview_tables['0'] = 'Select';
  271. while ($mview = db_fetch_object($query)) {
  272. $mview_tables[$mview->mview_id] = $mview->name;
  273. }
  274. $form['base_table_type']['mview_id'] = array(
  275. '#title' => t('Legacy Materialized View'),
  276. '#type' => 'select',
  277. '#options' => $mview_tables,
  278. '#description' => 'Which materialized view to use.',
  279. '#default_value' => $setup_obj->mview_id,
  280. '#ahah' => array(
  281. 'path' => ahah_helper_path(array('view_setup_table')),
  282. 'wrapper' => 'table-rows-div',
  283. 'effect' => 'fade',
  284. 'event' => 'change',
  285. 'method' => 'replace',
  286. ),
  287. );
  288. $form['views_type'] = array(
  289. '#type' => 'fieldset',
  290. '#title' => 'View Type',
  291. '#description' => 'Here you can provide the "type" of View you want to create.',
  292. );
  293. // field for the name of the
  294. $form['views_type']['row_name'] = array(
  295. '#title' => t('View Type Name'),
  296. '#type' => 'textfield',
  297. '#default_value' => $setup_obj->name,
  298. '#size' => 60,
  299. '#maxlength' => 128,
  300. '#description' => 'Provide the view type name. This is the name that will appear in '.
  301. 'the Drupal Views interface when adding a new view. The view type name '.
  302. 'must be unique.',
  303. '#required' => TRUE,
  304. );
  305. if (isset($setup_id)) {
  306. $form['row_name']['#attributes'] = array('readonly' => 'readonly');
  307. }
  308. $priorities = array();
  309. foreach (range(-10, 10) as $v) {
  310. $priorities[$v] = (string) $v;
  311. }
  312. $form['views_type']['row_priority'] = array(
  313. '#type' => 'select',
  314. '#title' => t('Priority'),
  315. '#description' => t('The level of priority your Views integration has in relation to the '
  316. .'default core and module definitions. The views integration definition with the '
  317. .'lightest priority will be used. For example, if there is a definition created by '
  318. .'core with a priority of 10 and another by a custom module of 5 and yours is -1 then '
  319. .'you definition will be used for that table because -1 is lighter then both 5 and 10.'),
  320. '#options' => $priorities,
  321. '#default_value' => (isset($setup_obj->priority)) ? $setup_obj->priority : -1,
  322. );
  323. if ($setup_obj->priority >= 9) {
  324. drupal_set_message('You are editing a default views integration. To ensure your changes
  325. are used, change the priority to -10.','warning');
  326. }
  327. $form['views_type']['base_table'] = array(
  328. '#type' => 'checkbox',
  329. '#title' => t('Base Table?'),
  330. '#description' => t('If you want this table to show up as one of the options in the '
  331. . 'add view page, then check this checkbox. It allows you to create listings '
  332. . 'primarily from this table'),
  333. '#default_value' => (isset($setup_obj->base_table)) ? $setup_obj->base_table : 1,
  334. );
  335. $form['views_type']['row_description'] = array(
  336. '#title' => t('Comment'),
  337. '#type' => 'textarea',
  338. '#description' => '(Optional). Provide any details regarding this setup you would like. This '.
  339. 'description will appear when selecting a type for a new Drupal View',
  340. '#required' => FALSE,
  341. '#default_value' => (isset($setup_obj->comment)) ? $setup_obj->comment : '',
  342. );
  343. // we need a div block where the table fields will get put when the
  344. // AHAH callback is made
  345. $form['view_setup_table'] = array(
  346. '#type' => 'item',
  347. '#prefix' => '<div id="table-rows-div">',
  348. '#suffix' => '</div>',
  349. );
  350. // add the fieldset for the table fields, but only if the $mview_id or $table_name
  351. // is set. The only times these values are set is if we're editing an existing
  352. // record or if the AHAH callback is being made.
  353. if ($form_state['storage']['mview_id'] or $form_state['storage']['table_name']) {
  354. $mview_id = $form_state['storage']['mview_id'];
  355. $table_name = $form_state['storage']['table_name'];
  356. $form['view_setup_table'] = array(
  357. '#type' => 'fieldset',
  358. '#title' => 'Join Selection',
  359. '#prefix' => '<div id="fieldset-table-rows-wrapper">',
  360. '#suffix' => '</div>',
  361. );
  362. // get the columns in this materialized view. They are separated by commas
  363. // where the first word is the column name and the rest is the type
  364. $columns = array();
  365. if ($mview_id) {
  366. $sql = "SELECT mv_specs FROM {tripal_mviews} WHERE mview_id = %d";
  367. $mview = db_fetch_object(db_query($sql, $mview_id));
  368. $columns = explode(",", $mview->mv_specs);
  369. }
  370. else {
  371. $table_desc = tripal_core_get_chado_table_schema($table_name);
  372. if ($table_desc) {
  373. $fields = $table_desc['fields'];
  374. // iterate through the columns and build the format
  375. // compatible with the code below. The column name is first followed
  376. // by the type with a separating space
  377. foreach ($fields as $column => $attrs) {
  378. $columns[] = "$column " . $attrs['type'];
  379. }
  380. }
  381. // now do the same for the custom tables
  382. $table_desc = tripal_get_chado_custom_schema($table_name);
  383. if ($table_desc) {
  384. $fields = $table_desc['fields'];
  385. foreach ($fields as $column => $attrs) {
  386. $columns[] = "$column " . $attrs['type'];
  387. }
  388. }
  389. }
  390. $i=1;
  391. $form['view_setup_table']["instructions"] = array(
  392. '#type' => 'markup',
  393. '#value' => filter_xss("Select an optional table to which the fields of the ".
  394. "materialized view can join. If a field does not need to ".
  395. "join you may leave the selection blank."),
  396. );
  397. $data['field_types'] = array();
  398. // get the list of chado tables to join on
  399. $chado_join_tables = tripal_core_get_chado_tables();
  400. $chado_join_tables = array_merge(array('Select a Join Table'), $chado_join_tables);
  401. // get list of all handlers
  402. $all_handlers = tripal_views_integration_discover_handlers();
  403. $handlers_fields = array(0 => "Select a field handler");
  404. $handlers_filters = array(0 => "Select a filter handler");
  405. $handlers_sort = array(0 => "Select a sort handler");
  406. $handlers_argument = array(0 => "Select an argument handler");
  407. $handlers_join = array(0 => "Select a join handler");
  408. $handlers_rel = array(0 => "Select a relationship handler");
  409. foreach ($all_handlers as $handler) {
  410. if (preg_match("/views_handler_field/", $handler)) {
  411. $handlers_fields[$handler] = $handler;
  412. }
  413. if (preg_match("/views_handler_filter/", $handler)) {
  414. $handlers_filters[$handler] = $handler;
  415. }
  416. if (preg_match("/views_handler_sort/", $handler)) {
  417. $handlers_sort[$handler] = $handler;
  418. }
  419. if (preg_match("/views_handler_argument/", $handler)) {
  420. $handlers_argument[$handler] = $handler;
  421. }
  422. if (preg_match("/_join/", $handler)) {
  423. $handlers_join[$handler] = $handler;
  424. }
  425. if (preg_match("/views_handler_relationship/", $handler)) {
  426. $handlers_rel[$handler] = $handler;
  427. }
  428. }
  429. // generate a unique $table_id for keeping track of the table
  430. if ($mview_id) {
  431. $table_id = $mview_id;
  432. }
  433. else {
  434. $table_id = $table_name;
  435. }
  436. // Per Row (Fields) --------------
  437. // now iterate through the columns of the materialized view or
  438. // chado table and generate the join and handler fields
  439. foreach ($columns as $column) {
  440. $column = trim($column); // trim trailing and leading spaces
  441. preg_match("/^(.*?)\ (.*?)$/", $column, $matches);
  442. $column_name = $matches[1];
  443. $column_type = $matches[2];
  444. $form['view_setup_table']["$table_id-$i"] = array(
  445. '#type' => 'markup',
  446. '#prefix' => "<div class=\"fields-new-row\">",
  447. '#suffix' => "</div>",
  448. '#value' => filter_xss('')
  449. );
  450. // COLUMN I
  451. $form['view_setup_table']["$table_id-$i"]["fields_name_$table_id-$i"] = array(
  452. '#type' => 'markup',
  453. '#prefix' => "<div class=\"column-one\">",
  454. '#value' => "<span class=\"column-name\">" . filter_xss($column_name) . "</span>".
  455. "<br /><span class=\"column-type\">" . filter_xss($column_type) . "</span>",
  456. '#suffix' => "</div>",
  457. );
  458. $data['field_types'][$column_name] = $column_type;
  459. // COLUMN II
  460. $form['view_setup_table']["$table_id-$i"]['column-2'] = array(
  461. '#type' => 'markup',
  462. '#prefix' => "<div class=\"column-two\">",
  463. '#suffix' => "</div>",
  464. '#value' => filter_xss('')
  465. );
  466. // set the default values for the human-readable name and description
  467. $default_name = '';
  468. $default_descrip = '';
  469. if (isset($setup_id) && !isset($form_state['storage']["fields_readable_name_$table_id-$i"])) {
  470. $default_name = $default_fields[$column_name]['name'];
  471. $default_descrip = $default_fields[$column_name]['description'];
  472. }
  473. else {
  474. $default_name = $form_state['storage']["fields_readable_name_$table_id-$i"];
  475. $default_descrip = $form_state['storage']["fields_description_$table_id-$i"];
  476. }
  477. $form['view_setup_table']["$table_id-$i"]['column-2']["fields_readable_name_$table_id-$i"] = array(
  478. '#type' => 'textfield',
  479. '#title' => 'Human-Readable Name',
  480. '#description' => 'This is the name of the field in the Views UI',
  481. '#required' => TRUE,
  482. '#default_value' => $default_name,
  483. '#size' => 42,
  484. );
  485. $form['view_setup_table']["$table_id-$i"]['column-2']["fields_description_$table_id-$i"] = array(
  486. '#type' => 'textarea',
  487. '#title' => 'Short Description',
  488. '#description' => 'This is the field help in the Views UI',
  489. '#required' => TRUE,
  490. '#cols' => 42,
  491. '#rows' => 3,
  492. '#default_value' => $default_descrip,
  493. );
  494. // COLUMN III
  495. $form['view_setup_table']["$table_id-$i"]['column-3'] = array(
  496. '#type' => 'markup',
  497. '#prefix' => "<div class=\"column-three\">",
  498. '#suffix' => "</div>",
  499. '#value' => filter_xss('')
  500. );
  501. // set the default values for the join table and columns
  502. $default_join_table = 0;
  503. $default_join_field = 0;
  504. if (isset($setup_id) && !isset($form_state['storage']["fields_join_$table_id-$i"])) {
  505. $default_join_table = $default_joins[$column_name]['left_table'];
  506. $default_join_field = $default_joins[$column_name]['left_field'];
  507. $form_state['storage']["fields_join_$table_id-$i"] = $default_join_table;
  508. $form_state['storage']["fields_join_column_$table_id-$i"] = $default_join_field;
  509. }
  510. else{
  511. $default_join_table = $form_state['storage']["fields_join_$table_id-$i"];
  512. $default_join_field = $form_state['storage']["fields_join_column_$table_id-$i"];
  513. }
  514. $form['view_setup_table']["$table_id-$i"]['column-3']["fields_join_$table_id-$i"] = array(
  515. '#type' => 'select',
  516. '#prefix' => "<div class=\"fields-column-join\">",
  517. '#suffix' => "</div>",
  518. '#options' => $chado_join_tables,
  519. '#required' => FALSE,
  520. '#default_value' => $default_join_table,
  521. '#ahah' => array(
  522. 'path' => ahah_helper_path(array("view_setup_table", "$table_id-$i", 'column-3', "fields_join_column_$table_id-$i")),
  523. 'wrapper' => "fields-column-join-column-$table_id-$i",
  524. 'effect' => 'fade',
  525. 'event' => 'change',
  526. 'method' => 'replace',
  527. ),
  528. );
  529. $columns = array();
  530. if ($default_join_table) {
  531. // get the table description in the typical way and if it returns
  532. // nothing then get the custom table description
  533. $table_desc = tripal_core_get_chado_table_schema($default_join_table);
  534. if (!$table_desc) {
  535. $table_desc = tripal_get_chado_custom_schema($default_join_table);
  536. }
  537. foreach ($table_desc['fields'] as $column => $def) {
  538. $columns[$column] = $column;
  539. }
  540. }
  541. else {
  542. $columns = array('Select Join Column');
  543. }
  544. $form['view_setup_table']["$table_id-$i"]['column-3']["fields_join_column_$table_id-$i"] = array(
  545. '#type' => 'select',
  546. '#prefix' => " <div id=\"fields-column-join-column-$table_id-$i\" class=\"fields-column-join-column\">",
  547. '#suffix' => "</div>",
  548. '#options' => $columns,
  549. '#required' => FALSE,
  550. '#default_value' => $default_join_field
  551. );
  552. $default_join_handler = 0;
  553. if (isset($setup_id) && !isset($form_state['storage']["fields_join_handler_$table_id-$i"])) {
  554. $default_join_handler = $default_handlers[$column_name]['join']['handler_name'];
  555. $form_state['storage']["fields_join_handler_$table_id-$i"] = $default_join_handler;
  556. }
  557. else {
  558. $default_join_handler = $form_state['storage']["fields_join_handler_$table_id-$i"];
  559. }
  560. $form['view_setup_table']["$table_id-$i"]['column-3']["fields_join_handler_$table_id-$i"] = array(
  561. '#type' => 'select',
  562. '#prefix' => "<div class=\"fields-join-handler\">",
  563. '#suffix' => "</div>",
  564. '#options' => $handlers_join,
  565. '#required' => FALSE,
  566. '#default_value' => $default_join_handler,
  567. );
  568. // COLUMN 4
  569. $form['view_setup_table']["$table_id-$i"]['column-4'] = array(
  570. '#type' => 'markup',
  571. '#prefix' => "<div class=\"column-four\">",
  572. '#suffix' => "</div>",
  573. '#value' => filter_xss('')
  574. );
  575. // create the handler fields
  576. $default_field_handler = 0;
  577. if (isset($setup_id) && !isset($form_state['storage']["fields_field_handler_$table_id-$i"])) {
  578. $default_field_handler = $default_handlers[$column_name]['field']['handler_name'];
  579. $form_state['storage']["fields_field_handler_$table_id-$i"] = $default_field_handler;
  580. }
  581. else {
  582. $default_field_handler = $form_state['storage']["fields_field_handler_$table_id-$i"];
  583. if (!$default_field_handler) {
  584. if ($column_type == 'integer' or $column_type == 'int' or $column_type == 'serial') {
  585. $default_field_handler = 'chado_views_handler_field_numeric';
  586. }
  587. elseif (preg_match("/character varying/", $column_type) or $column_type == 'char' or $column_type == 'text' or $column_type == 'varchar') {
  588. $default_field_handler = 'chado_views_handler_field';
  589. }
  590. elseif ($column_type == 'boolean') {
  591. $default_field_handler = 'chado_views_handler_field_boolean';
  592. }
  593. elseif ($column_type == 'float') {
  594. $default_field_handler = 'chado_views_handler_field_numeric';
  595. }
  596. elseif ($column_type == 'datetime') {
  597. $default_field_handler = 'chado_views_handler_field_date';
  598. }
  599. }
  600. }
  601. $form['view_setup_table']["$table_id-$i"]['column-4']["fields_field_handler_$table_id-$i"] = array(
  602. '#type' => 'select',
  603. '#prefix' => "<div class=\"fields-field-handler\">",
  604. '#suffix' => "</div>",
  605. '#options' => $handlers_fields,
  606. '#required' => FALSE,
  607. '#default_value' => $default_field_handler,
  608. );
  609. $default_filter_handler = 0;
  610. if (isset($setup_id) && !isset($form_state['storage']["fields_filter_handler_$table_id-$i"])) {
  611. $default_filter_handler = $default_handlers[$column_name]['filter']['handler_name'];
  612. $form_state['storage']["fields_filter_handler_$table_id-$i"]= $default_filter_handler;
  613. }
  614. else {
  615. $default_filter_handler = $form_state['storage']["fields_filter_handler_$table_id-$i"];
  616. if (!$default_filter_handler) {
  617. if ($column_type == 'integer' or $column_type == 'int' or $column_type == 'serial') {
  618. $default_filter_handler = 'chado_views_handler_filter_numeric';
  619. }
  620. elseif (preg_match("/^character varying/", $column_type) or $column_type == 'char' or $column_type == 'text' or $column_type == 'varchar') {
  621. $default_filter_handler = 'chado_views_handler_filter_string';
  622. }
  623. elseif ($column_type == 'boolean') {
  624. $default_filter_handler = 'chado_views_handler_filter_boolean';
  625. }
  626. elseif ($column_type == 'float') {
  627. $default_filter_handler = 'chado_views_handler_filter_float';
  628. }
  629. elseif ($column_type == 'datetime') {
  630. $default_filter_handler = 'chado_views_handler_filter_date';
  631. }
  632. }
  633. }
  634. $form['view_setup_table']["$table_id-$i"]['column-4']["fields_filter_handler_$table_id-$i"] = array(
  635. '#type' => 'select',
  636. '#prefix' => "<div class=\"fields-filter-handler\">",
  637. '#suffix' => "</div>",
  638. '#options' => $handlers_filters,
  639. '#required' => FALSE,
  640. '#default_value' => $default_filter_handler,
  641. );
  642. $default_sort_handler = 0;
  643. if (isset($setup_id) && !isset($form_state['storage']["fields_sort_handler_$table_id-$i"])) {
  644. $default_sort_handler = $default_handlers[$column_name]['sort']['handler_name'];
  645. $form_state['storage']["fields_sort_handler_$table_id-$i"] = $default_sort_handler;
  646. }
  647. else {
  648. $default_sort_handler = $form_state['storage']["fields_sort_handler_$table_id-$i"];
  649. if (!$default_sort_handler) {
  650. if ($column_type == 'integer' or $column_type == 'int' or $column_type == 'serial') {
  651. $default_sort_handler = 'chado_views_handler_sort';
  652. }
  653. elseif (preg_match("/character varying/", $column_type) or $column_type == 'char' or $column_type == 'text' or $column_type == 'varchar') {
  654. $default_sort_handler = 'chado_views_handler_sort';
  655. }
  656. elseif ($column_type == 'boolean') {
  657. $default_sort_handler = 'chado_views_handler_sort';
  658. }
  659. elseif ($column_type == 'float') {
  660. $default_sort_handler = 'chado_views_handler_sort';
  661. }
  662. elseif ($column_type == 'datetime') {
  663. $default_sort_handler = 'chado_views_handler_sort_date';
  664. }
  665. }
  666. }
  667. $form['view_setup_table']["$table_id-$i"]['column-4']["fields_sort_handler_$table_id-$i"] = array(
  668. '#type' => 'select',
  669. '#prefix' => "<div class=\"fields-sort-handler\">",
  670. '#suffix' => "</div>",
  671. '#options' => $handlers_sort,
  672. '#required' => FALSE,
  673. '#default_value' => $default_sort_handler,
  674. );
  675. $default_argument_handler = 0;
  676. if (isset($setup_id) && !isset($form_state['storage']["fields_argument_handler_$table_id-$i"])) {
  677. $default_argument_handler = $default_handlers[$column_name]['argument']['handler_name'];
  678. $form_state['storage']["fields_argument_handler_$table_id-$i"]=$default_argument_handler ;
  679. }
  680. else {
  681. $default_argument_handler = $form_state['storage']["fields_argument_handler_$table_id-$i"];
  682. if (!$default_argument_handler) {
  683. if ($column_type == 'integer' or $column_type == 'int' or $column_type == 'serial') {
  684. $default_argument_handler = 'views_handler_argument_numeric';
  685. }
  686. elseif (preg_match("/character varying/", $column_type) or $column_type == 'char' or $column_type == 'text' or $column_type == 'varchar') {
  687. $default_argument_handler = 'views_handler_argument_string';
  688. }
  689. elseif ($column_type == 'boolean') {
  690. $default_argument_handler = 'views_handler_argument_numeric';
  691. }
  692. elseif ($column_type == 'float') {
  693. $default_argument_handler = 'views_handler_argument_numeric';
  694. }
  695. elseif ($column_type == 'datetime') {
  696. $default_argument_handler = 'views_handler_argument_date';
  697. }
  698. }
  699. }
  700. $form['view_setup_table']["$table_id-$i"]['column-4']["fields_argument_handler_$table_id-$i"] = array(
  701. '#type' => 'select',
  702. '#prefix' => "<div class=\"fields-argument-handler\">",
  703. '#suffix' => "</div>",
  704. '#options' => $handlers_argument,
  705. '#required' => FALSE,
  706. '#default_value' => $default_argument_handler,
  707. );
  708. $default_relationship_handler = 0;
  709. if (isset($setup_id) && !isset($form_state['storage']["fields_relationship_handler_$table_id-$i"])) {
  710. $default_relationship_handler = $default_handlers[$column_name]['relationship']['handler_name'];
  711. $form_state['storage']["fields_relationship_handler_$table_id-$i"]=$default_relationship_handler;
  712. }
  713. else {
  714. $default_relationship_handler = $form_state['storage']["fields_relationship_handler_$table_id-$i"];
  715. if (!$default_relationship_handler) {
  716. if ($column_type == 'integer' or $column_type == 'int' or $column_type == 'serial') {
  717. $default_relationship_handler = 'views_handler_relationship';
  718. }
  719. elseif (preg_match("/character varying/", $column_type) or $column_type == 'char' or $column_type == 'text' or $column_type == 'varchar') {
  720. $default_relationship_handler = 'views_handler_relationship';
  721. }
  722. elseif ($column_type == 'boolean') {
  723. $default_relationship_handler = 'views_handler_relationship';
  724. }
  725. elseif ($column_type == 'float') {
  726. $default_relationship_handler = 'views_handler_relationship';
  727. }
  728. elseif ($column_type == 'datetime') {
  729. $default_relationship_handler = 'views_handler_relationship';
  730. }
  731. }
  732. }
  733. $form['view_setup_table']["$table_id-$i"]['column-4']["fields_relationship_handler_$table_id-$i"] = array(
  734. '#type' => 'select',
  735. '#prefix' => "<div class=\"fields-relationship-handler\">",
  736. '#suffix' => "</div>",
  737. '#options' => $handlers_rel,
  738. '#required' => FALSE,
  739. '#default_value' => $default_relationship_handler,
  740. );
  741. $i++;
  742. }
  743. $form['view_setup_table']['save'] = array(
  744. '#type' => 'submit',
  745. '#value' => t('Save'),
  746. );
  747. $data['row_count'] = $i - 1;
  748. }
  749. //use this to put values into $form_state['values']
  750. $form['data'] = array();
  751. // Ensure that we don't store an array
  752. // since we will get a check_plain:htmlspecial_characters error if we do
  753. foreach ($data as $key => $value) {
  754. if (is_array($value)) {
  755. $form['data'][$key] = array(
  756. '#type' => 'hidden',
  757. '#value' => serialize($value),
  758. );
  759. }
  760. else {
  761. $form['data'][$key] = array(
  762. '#type' => 'hidden',
  763. '#value' => $value,
  764. );
  765. }
  766. }
  767. $form['#redirect'] = 'admin/tripal/views/integration/list';
  768. return $form;
  769. }
  770. /**
  771. * Purpose: validates the tripal_views_integration_form after submission
  772. *
  773. * @param $form
  774. * The form object which is passed automatically by drupal
  775. *
  776. * @param &$form_state
  777. * The form state pbject which is passed automatically by drupal
  778. *
  779. * @ingroup tripal_views_integration
  780. */
  781. function tripal_views_integration_form_validate($form, &$form_state) {
  782. $name_array = explode(" ", $form_state['values']['row_name']);
  783. $mview_id = $form_state['values']['mview_id'];
  784. $table_name = $form_state['values']['table_name'];
  785. // if (count($name_array) > 1) {
  786. // form_set_error($form_state['values']['row_name'], 'The View type name must be a single word only.');
  787. // }
  788. if ($mview_id and $table_name) {
  789. form_set_error($form_state['values']['mview_id'], 'Please select either a materialized view or a Chado table but not both');
  790. }
  791. if (!$mview_id and !$table_name) {
  792. form_set_error($form_state['values']['mview_id'], 'Please select either a materialized view or a Chado table');
  793. }
  794. // TODO: do we need to require that a handler be set for each field and each type of handler?
  795. }
  796. /**
  797. * Purpose: inserts or updates the record in the tripal views integration
  798. * tables. This function is only called if validation is passed.
  799. *
  800. * @param $form
  801. * The form object which is passed automatically by drupal
  802. *
  803. * @param &$form_state
  804. * The form state pbject which is passed automatically by drupal
  805. *
  806. * @ingroup tripal_views_integration
  807. */
  808. function tripal_views_integration_form_submit($form, &$form_state) {
  809. $name = $form_state['values']['row_name'];
  810. $mview_id = $form_state['values']['mview_id'];
  811. $table_name = $form_state['values']['table_name'];
  812. $setup_id = $form_state['values']['setup_id'];
  813. $priority = $form_state['values']['row_priority'];
  814. $comment = $form_state['values']['row_description'];
  815. // get details about this mview
  816. if ($mview_id) {
  817. $sql = "SELECT * FROM {tripal_mviews} WHERE mview_id = %d";
  818. $mview = db_fetch_object(db_query($sql, $mview_id));
  819. $table_name = $mview->mv_table;
  820. $table_id = $mview_id;
  821. $type = 'mview';
  822. }
  823. else {
  824. $type = 'chado';
  825. $table_id = $table_name;
  826. }
  827. // If this is for a materialized view then we want to add/update that record
  828. $tripal_views_record = array();
  829. if ($mview_id) {
  830. // get details about this mview
  831. $sql = "SELECT * FROM {tripal_mviews} WHERE mview_id = %d";
  832. $mview = db_fetch_object(db_query($sql, $mview_id));
  833. // build the record for insert/update
  834. $tripal_views_record = array(
  835. 'mview_id' => $mview_id,
  836. 'table_name' => $mview->mv_table,
  837. 'name' => $name,
  838. 'priority' => $priority,
  839. 'comment' => $comment,
  840. 'base_table' => $form_state['values']['base_table']
  841. );
  842. }
  843. // if a chado table then...
  844. else {
  845. // build the record for insert/update
  846. $tripal_views_record = array(
  847. 'table_name' => $table_name,
  848. 'name' => $name,
  849. 'priority' => $priority,
  850. 'comment' => $comment,
  851. 'base_table' => $form_state['values']['base_table']
  852. );
  853. }
  854. // perform the insert or update
  855. if (!$setup_id) { // this is an insert
  856. if (!drupal_write_record('tripal_views', $tripal_views_record)) {
  857. drupal_set_message(t("Failed to add record."), 'error');
  858. return;
  859. }
  860. }
  861. else { // this is an update
  862. $tripal_views_record['setup_id'] = $setup_id;
  863. if (!drupal_write_record('tripal_views', $tripal_views_record, array('setup_id'))) {
  864. drupal_set_message(t("Failed to update record."), 'error');
  865. return;
  866. }
  867. }
  868. // if this is an update then clean out the existing joins and handlers so we can add new ones
  869. if ($setup_id) {
  870. db_query("DELETE FROM {tripal_views_field} WHERE setup_id = %d", $setup_id);
  871. db_query("DELETE FROM {tripal_views_join} WHERE setup_id = %d", $setup_id);
  872. db_query("DELETE FROM {tripal_views_handlers} WHERE setup_id = %d", $setup_id);
  873. }
  874. // iterate through the columns of the form and add
  875. // the joins if provided, and the handlers
  876. $i = 1;
  877. foreach (unserialize($form_state['values']['field_types']) as $key => $value) {
  878. // add the field definition
  879. $view_field_record = array(
  880. 'setup_id' => $tripal_views_record['setup_id'],
  881. 'column_name' => $key,
  882. 'name' => $form_state['values']["fields_readable_name_$table_id-$i"],
  883. 'description' => $form_state['values']["fields_description_$table_id-$i"],
  884. 'type' => $value,
  885. );
  886. drupal_write_record('tripal_views_field', $view_field_record);
  887. // first add the join if it exists
  888. $left_table = $form_state['values']["fields_join_$table_id-$i"];
  889. $left_column = $form_state['values']["fields_join_column_$table_id-$i"];
  890. if ($left_column) {
  891. if ($mview_id) {
  892. $base_table = $mview->mv_table;
  893. }
  894. else {
  895. $base_table = $table_name;
  896. }
  897. $view_join_record = array(
  898. 'setup_id' => $tripal_views_record['setup_id'],
  899. 'base_table' => $base_table,
  900. 'base_field' => $key,
  901. 'left_table' => $left_table,
  902. 'left_field' => $left_column,
  903. 'handler' => $form_state['values']["fields_join_handler_$table_id-$i"],
  904. );
  905. // write the new joins to the database
  906. drupal_write_record('tripal_views_join', $view_join_record);
  907. }
  908. // add the hanlders
  909. $handlers = array('filter', 'field', 'sort', 'argument', 'join', 'relationship');
  910. foreach ($handlers as $handler) {
  911. $handler_name = $form_state['values']["fields_" . $handler . "_handler_$table_id-$i"];
  912. if ($handler_name) {
  913. $handler_record = array(
  914. 'setup_id' => $tripal_views_record['setup_id'],
  915. 'column_name' => $key,
  916. 'handler_type' => $handler,
  917. 'handler_name' => $handler_name,
  918. );
  919. drupal_write_record('tripal_views_handlers', $handler_record);
  920. }
  921. }
  922. $i++;
  923. }
  924. if ($setup_id) {
  925. drupal_set_message(t('Record Updated'));
  926. }
  927. else {
  928. drupal_set_message(t('Record Added'));
  929. }
  930. // now clear all the caches so that Drupal views picks up our chages
  931. views_invalidate_cache();
  932. }
  933. /**
  934. * Purpose: this function queries all modules currently enabled on the site
  935. * looking for custom handlers and returns a list of all available handerls.
  936. * The base View handlers are also included.
  937. *
  938. * @return
  939. * Returns an array of handler names
  940. *
  941. * @ingroup tripal_views_integration
  942. */
  943. function tripal_views_integration_discover_handlers() {
  944. $handlers = array();
  945. // Get handlers from all modules.
  946. foreach (module_implements('views_handlers') as $module) {
  947. $function = $module . '_views_handlers';
  948. $result = $function();
  949. if (!is_array($result)) {
  950. continue;
  951. }
  952. foreach ($result['handlers'] as $handler => $parent) {
  953. $handlers[] = $handler;
  954. }
  955. }
  956. // these handlers are hard coded because I could not
  957. // get the views_handlers() function to be called
  958. // in the code above. However, we will be creating
  959. // Chado wrappers for many of these and once that work
  960. // is done these will no longer be needed.
  961. // argument handlers
  962. $handlers[] = 'views_handler_argument';
  963. $handlers[] = 'views_handler_argument_numeric';
  964. $handlers[] = 'views_handler_argument_formula';
  965. $handlers[] = 'views_handler_argument_date';
  966. $handlers[] = 'views_handler_argument_string';
  967. $handlers[] = 'views_handler_argument_many_to_one';
  968. $handlers[] = 'views_handler_argument_null';
  969. // field handlers
  970. $handlers[] = 'views_handler_field';
  971. $handlers[] = 'views_handler_field_date';
  972. $handlers[] = 'views_handler_field_boolean';
  973. $handlers[] = 'views_handler_field_markup';
  974. $handlers[] = 'views_handler_field_xss';
  975. $handlers[] = 'views_handler_field_url';
  976. $handlers[] = 'views_handler_field_file_size';
  977. $handlers[] = 'views_handler_field_prerender_list';
  978. $handlers[] = 'views_handler_field_numeric';
  979. $handlers[] = 'views_handler_field_custom';
  980. $handlers[] = 'views_handler_field_counter';
  981. // filter handlers
  982. $handlers[] = 'views_handler_filter';
  983. $handlers[] = 'views_handler_filter_equality';
  984. $handlers[] = 'views_handler_filter_string';
  985. $handlers[] = 'views_handler_filter_boolean_operator';
  986. $handlers[] = 'views_handler_filter_boolean_operator_string';
  987. $handlers[] = 'views_handler_filter_in_operator';
  988. $handlers[] = 'views_handler_filter_numeric';
  989. $handlers[] = 'views_handler_filter_float';
  990. $handlers[] = 'views_handler_filter_date';
  991. $handlers[] = 'views_handler_filter_many_to_one';
  992. // relationship handlers
  993. $handlers[] = 'views_handler_relationship';
  994. // sort handlers
  995. $handlers[] = 'views_handler_sort';
  996. $handlers[] = 'views_handler_sort_formula';
  997. $handlers[] = 'views_handler_sort_date';
  998. $handlers[] = 'views_handler_sort_menu_hierarchy';
  999. $handlers[] = 'views_handler_sort_random';
  1000. // join handler
  1001. $handlers[] = 'views_join';
  1002. return $handlers;
  1003. }