tripal_ds.module 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585
  1. <?php
  2. require_once "includes/tripal_ds.inc";
  3. require_once "includes/tripal_ds.ds.inc";
  4. require_once "includes/tripal_ds.field_group.inc";
  5. require_once "includes/tripal_ds.field_formatter.inc";
  6. /**
  7. * Implements hook_init().
  8. *
  9. * Injects required javascript and css.
  10. */
  11. function tripal_ds_init() {
  12. drupal_add_css(drupal_get_path('module', 'tripal_ds') . '/theme/css/tripal_ds.css');
  13. drupal_add_js(drupal_get_path('module', 'tripal_ds') . '/theme/js/tripal_ds.js');
  14. $theme_dir = url(drupal_get_path('module', 'tripal_ds') . '/theme');
  15. drupal_add_js("var ds_theme_dir = '$theme_dir';", 'inline', 'header');
  16. // Icon fonts.
  17. drupal_add_css(drupal_get_path('module', 'tripal_ds') . '/theme/fonts/font-awesome-4.7.0/css/font-awesome.min.css');
  18. }
  19. /**
  20. * Implements hook_views_api().
  21. */
  22. function tripal_ds_views_api() {
  23. return array(
  24. 'api' => 3,
  25. 'path' => drupal_get_path('module', 'tripal_ds') . '/includes/views',
  26. );
  27. }
  28. /**
  29. * Implements hook_menu().
  30. * Defines all menu items needed by Tripal DS
  31. *
  32. */
  33. function tripal_ds_menu() {
  34. $items = array();
  35. // Adds a +Apply Tripal Display Suite option to 'Tripal Content Types' page.
  36. $items['admin/structure/bio_data/manage/%/display/apply'] = array(
  37. 'title' => 'Apply Default Tripal Layout (will reset current layout)',
  38. 'description' => t('Apply the Tripal Display Suite settings to this content type.'),
  39. 'page callback' => 'drupal_get_form',
  40. 'access arguments' => array('administer tripal'),
  41. 'page arguments' => array('tripal_ds_update_layout_form', 4),
  42. 'type' => MENU_LOCAL_ACTION,
  43. );
  44. // Adds a +Add Tripal Pane button to 'Tripal Content Types' page.
  45. $items['admin/structure/bio_data/manage/%/display/create'] = array(
  46. 'title' => 'Create an empty Tripal Pane',
  47. 'description' => t('Create a new empty tripal pane.'),
  48. 'page callback' => 'drupal_get_form',
  49. 'access arguments' => array('administer tripal'),
  50. 'page arguments' => array('tripal_ds_pane_addition_button_form', 4),
  51. 'type' => MENU_LOCAL_ACTION,
  52. );
  53. return $items;
  54. }
  55. /**
  56. * Implements hook_bundle_postcreate().
  57. *
  58. * This is a Triapl defined hook and is called in the TripalBundle::create()
  59. * function to allow modules to perform tasks when a bundle is created.
  60. *
  61. * @param $bundle
  62. */
  63. function tripal_ds_bundle_postcreate($bundle) {
  64. $bundle_name = $bundle->name;
  65. $bundle_data_table = $bundle->data_table;
  66. $instances = field_info_instances('TripalEntity', $bundle_name);
  67. if($bundle_data_table == 'pub'){
  68. _ds_layout_pub_settings_info($bundle_name, $instances);
  69. }
  70. else {
  71. _ds_layout_settings_info($bundle_name, $instances);
  72. }
  73. }
  74. /**
  75. * Update the tripal_ds table when a tripal pane is deleted. This will remove
  76. * the link from the table of contents block.
  77. *
  78. * @param $bundle
  79. */
  80. function tripal_ds_table_column_delete($bundle){
  81. $bundle_name = $bundle->name;
  82. db_delete('tripal_ds')
  83. ->condition('bundle', $bundle_name, '=')
  84. ->execute();
  85. }
  86. /**
  87. * Trigger the update to the tripal_ds table when a tripal pane is deleted.
  88. *
  89. * @param $bundle
  90. */
  91. function tripal_ds_bundle_delete($bundle){
  92. tripal_ds_table_column_delete($bundle);
  93. }
  94. /**
  95. * Implements hook_ds_field_settings_alter()
  96. *
  97. * Upon save field groups are reviewed so that the tripal_ds table is update and
  98. * thus the table of contents block is be updated.
  99. *
  100. * @param $field_settings
  101. * @param $form
  102. * @param $form_state
  103. */
  104. function tripal_ds_ds_field_settings_alter(&$field_settings, $form, $form_state){
  105. // Get the form info from the bundle about to be saved.
  106. $tripal_entity_object = $form_state['build_info']['args']['1'];
  107. // Grab the bundle.
  108. $bundle_id = $tripal_entity_object->name;
  109. // Grab the field groups from the bundle.
  110. $updated_field_groups = $form_state['field_group'];
  111. // Grab the fields from the bundle.
  112. $fields = $form_state['values']['fields'];
  113. // Delete the menu items associated with the bundle id.
  114. db_delete('tripal_ds')
  115. ->condition('bundle', $bundle_id, '=')
  116. ->execute();
  117. // Traverse the updated field_groups grabbing the tripal pane items.
  118. $tripal_pane_field_groups = array();
  119. $i = 0;
  120. foreach($updated_field_groups as $updated_field_group){
  121. if($updated_field_group->format_type == 'tripalpane'){
  122. $tripal_pane_field_groups += [ $i => $updated_field_group->group_name];
  123. $i++;
  124. }
  125. }
  126. // Now grab the labels of the tripalpane.
  127. foreach($updated_field_groups as $updated_field_group){
  128. foreach($tripal_pane_field_groups as $tripal_pane_field_group){
  129. if($updated_field_group->group_name == $tripal_pane_field_group){
  130. if($fields[$tripal_pane_field_group]['region'] !== 'hidden'){
  131. tripal_ds_bundle_menu_item($bundle_id, $updated_field_group->label, $tripal_pane_field_group, 'tripalentity');
  132. }
  133. }
  134. }
  135. }
  136. // Update the menu items weight.
  137. tripal_ds_toc_order($bundle_id, $form_state['values']['fields']);
  138. }
  139. /**
  140. *
  141. * Trigger the update to the tripal_ds table when a tripal pane is deleted.
  142. *
  143. * @param $bundle_name
  144. * @param $field_label
  145. * @param $field_name
  146. * @param $entity_type
  147. */
  148. function tripal_ds_bundle_menu_item($bundle_name, $field_label, $field_name, $entity_type){
  149. //Check the record does not already exist
  150. $tripal_ds_rows = db_select('tripal_ds', 'ds')
  151. ->fields('ds', array('tripal_ds_field_name', 'tripal_ds_field_label'))
  152. ->condition('bundle', $bundle_name, '=')
  153. ->condition('tripal_ds_field_label', $field_label, '=')
  154. ->condition('tripal_ds_field_name', $field_name, '=')
  155. ->execute()->fetchAll();
  156. if(!empty($tripal_ds_rows)){
  157. foreach ($tripal_ds_rows as $tripal_ds_row){
  158. if(($field_label == $tripal_ds_row->tripal_ds_field_label) && ($field_name == $tripal_ds_row->tripal_ds_field_name) && ($bundle_name == $tripal_ds_rows->bundle)) {
  159. // Do not write the field to the table
  160. drupal_set_message("Could not update the bundle menu because that field already exists.", 'error');
  161. }
  162. }
  163. }
  164. else {
  165. //Write to the tripal_ds table to record the new tripal pane.
  166. $field_for_table = new stdClass();
  167. $field_for_table->tripal_ds_field_name = $field_name;
  168. $field_for_table->tripal_ds_field_label = $field_label;
  169. $field_for_table->entity_type = $entity_type;
  170. $field_for_table->bundle = $bundle_name;
  171. drupal_write_record('tripal_ds', $field_for_table);
  172. }
  173. }
  174. /**
  175. * Implements hook_ds_layout_info() to define layouts from code in a module for
  176. * display suite.
  177. *
  178. * Defines the Tripal Feature Layout option.
  179. *
  180. */
  181. function tripal_ds_ds_layout_info() {
  182. $path = drupal_get_path('module', 'tripal_ds');
  183. $layouts = array(
  184. 'tripal_ds_feature' => array(
  185. 'label' => t('Tripal Feature Layout'),
  186. 'path' => $path . '/theme/templates',
  187. 'regions' => array(
  188. 'left' => t('Left'),
  189. 'right' => t('Right'),
  190. ),
  191. 'css' => TRUE,
  192. ),
  193. );
  194. return $layouts;
  195. }
  196. /**
  197. * Implements hook_form()
  198. *
  199. * Adds a confirmation message to applying default layout option in 'Manage
  200. * Display'.
  201. *
  202. * @param $form
  203. * @param $form_state
  204. * @param $bundle_name
  205. *
  206. * @return mixed
  207. */
  208. function tripal_ds_update_layout_form($form, &$form_state, $bundle_name) {
  209. $form = array();
  210. $form['bundle_name'] = array(
  211. '#type' => 'value',
  212. '#value' => $bundle_name,
  213. );
  214. $bundle = tripal_load_bundle_entity(array('name' => $bundle_name));
  215. $bundle_label = $bundle->label;
  216. return confirm_form($form,
  217. t('Please confirm you would like to apply this layout: ' . $bundle_label),
  218. 'admin/structure/bio_data/manage/' . $bundle_name . '/display',
  219. t('This action cannot be undone.'),
  220. t('Yes, apply layout'),
  221. t('No, cancel')
  222. );
  223. }
  224. /**
  225. * Implements hook_form_submit()
  226. *
  227. * Deletes all existing settings associated with a bundle's display settings
  228. * so that the default layout is applied cleanly.
  229. *
  230. * @param $form_state
  231. * @param $form
  232. */
  233. function tripal_ds_update_layout_form_submit($form, &$form_state) {
  234. $bundle_name = $form_state['build_info']['args'][0];
  235. $bundle = tripal_load_bundle_entity(array('name' => $bundle_name));
  236. //Build the identifier to check against ds_layout_settings.
  237. $ds_identifier = 'TripalEntity|'.$bundle_name.'|default';
  238. //Check to see if the layout already exists.
  239. $result = db_select('ds_layout_settings', 'ds')
  240. ->fields('ds')
  241. ->condition('id', $ds_identifier, '=')
  242. ->execute()
  243. ->fetchField();
  244. //Check to see if there are any field groups associated with the bundle.
  245. $result_fg = db_select('field_group', 'fg')
  246. ->fields('fg')
  247. ->condition('bundle', $bundle_name, '=')
  248. ->execute()
  249. ->fetchField();
  250. //Check to see if there are any tripal ds fields associated with the bundle.
  251. $result_tds = db_select('tripal_ds', 'tds')
  252. ->fields('tds')
  253. ->condition('bundle', $bundle_name, '=')
  254. ->execute();
  255. //Check to see if there are any field settings associated with the bundle.
  256. $result_fs = db_select('ds_field_settings', 'fs')
  257. ->fields('fs')
  258. ->condition('bundle', $bundle_name, '=')
  259. ->execute();
  260. //If the layout exists, delete it.
  261. if(!empty($result)) {
  262. db_delete('ds_layout_settings')
  263. ->condition('id', $ds_identifier, '=')
  264. ->execute();
  265. }
  266. //Then delete the field_group_fields associated with the identifier.
  267. if(!empty($result_fg)) {
  268. db_delete('field_group')
  269. ->condition('bundle', $bundle_name, '=')
  270. ->execute();
  271. }
  272. //Then delete the ds_field_settings associated with the identifier.
  273. if(!empty($result_tds)) {
  274. db_delete('ds_field_settings')
  275. ->condition('bundle', $bundle_name, '=')
  276. ->execute();
  277. }
  278. //Then delete the tripal_ds menu item.
  279. if(!empty($result_fs)) {
  280. db_delete('tripal_ds')
  281. ->condition('bundle', $bundle_name, '=')
  282. ->execute();
  283. }
  284. //Now you can build the layout fresh.
  285. $instances = field_info_instances('TripalEntity', $bundle_name);
  286. $bundle_data_table = $bundle->data_table;
  287. if($bundle_data_table == 'pub'){
  288. $success = _ds_layout_pub_settings_info($bundle_name, $instances);
  289. }
  290. else {
  291. $success = _ds_layout_settings_info($bundle_name, $instances);
  292. }
  293. if ($success) {
  294. drupal_set_message("Layout applied successfully and saved.");
  295. }
  296. else {
  297. drupal_set_message("Could not apply layout.", 'error');
  298. }
  299. drupal_goto("admin/structure/bio_data/manage/$bundle_name/display");
  300. }
  301. /**
  302. * Implements hook_form()
  303. *
  304. * Creates the button that creates an empty tripal pane.
  305. *
  306. * @param $form
  307. * @param $form_state
  308. * @param $bundle_name
  309. * @return mixed
  310. */
  311. function tripal_ds_pane_addition_button_form($form, &$form_state, $bundle_name) {
  312. $form = array();
  313. $form['bundle_name'] = array(
  314. '#type' => 'value',
  315. '#value' => $bundle_name,
  316. );
  317. $form['field_name'] = array(
  318. '#type' => 'textfield',
  319. '#title' => t('Tripal Panel Label'),
  320. '#required' => TRUE,
  321. '#description' => "Please enter the label for the new Tripal Pane",
  322. '#size' => 20,
  323. '#maxlength' => 50,
  324. );
  325. $bundle = tripal_load_bundle_entity(array('name' => $bundle_name));
  326. $bundle_label = $bundle->label;
  327. return confirm_form($form,
  328. t('Please confirm you would like to create a new field for: ' . $bundle_label),
  329. 'admin/structure/bio_data/manage/' . $bundle_name . '/display',
  330. t('Create new Tripal Pane'),
  331. t('Yes'),
  332. t('No, cancel')
  333. );
  334. }
  335. /**
  336. * Implements hook_form_submit()
  337. *
  338. * @param $form_state
  339. * @param $form
  340. */
  341. function tripal_ds_pane_addition_button_form_submit($form, &$form_state) {
  342. $bundle_name = $form_state['build_info']['args'][0];
  343. //Build the rest of the passed variables.
  344. $field_name = $form_state['input']['field_name'];
  345. $group_field_name = 'gp_'.$form_state['input']['field_name'];
  346. //Create the field groups, last passed parameter is NULL because there are no
  347. //children.
  348. _additional_fields_field_group_info($bundle_name, $field_name, $group_field_name, NULL);
  349. //Place the field groups in the layout.
  350. tripal_ds_update_ds_layout($bundle_name, NULL, $group_field_name);
  351. drupal_goto("admin/structure/bio_data/manage/$bundle_name/display");
  352. }
  353. /**
  354. * When called the function will add field_groups to the existing tripal_ds
  355. * layout in the correct regions.
  356. *
  357. * @param $bundle_name
  358. * The name of the bundle the pane is being added to.
  359. * @param $field_name
  360. * The machine name for the field.
  361. * @param $tripal_pane_name
  362. * The machine name for the tripal pane.
  363. */
  364. function tripal_ds_update_ds_layout($bundle_name, $field_name, $tripal_pane_name) {
  365. //Build the identifier to check against ds_layout_settings.
  366. $ds_identifier = 'TripalEntity|'.$bundle_name.'|default';
  367. //Check to see if the layout already exists.
  368. $result = db_select('ds_layout_settings', 'ds')
  369. ->fields('ds', array('settings'))
  370. ->condition('ds.id', $ds_identifier, '=')
  371. ->execute()
  372. ->fetchObject();
  373. //If the layout exists unserialize it.
  374. if(!empty($result)) {
  375. $layout_info = $result->settings;
  376. $layout_info = unserialize($layout_info);
  377. //Count the number of rows in the region and add the field to the region.
  378. $index = count($layout_info['regions']['right']);
  379. //Now add the tripal pane and field to the right region and field array.
  380. if(!empty($field_name)){
  381. $layout_info['regions']['right'][$index] = $field_name;
  382. $incremented_index = $index++;
  383. $layout_info['fields'][$field_name] = 'right';
  384. }
  385. if(!empty($tripal_pane_name)){
  386. if(!empty($incremented_index)){
  387. $layout_info['regions']['right'][$incremented_index] = $tripal_pane_name;
  388. $layout_info['fields'][$tripal_pane_name] = 'right';
  389. }
  390. else {
  391. $layout_info['regions']['right'][$index] = $tripal_pane_name;
  392. $layout_info['fields'][$tripal_pane_name] = 'right';
  393. }
  394. }
  395. //Update the ds_layout_settings table with the new layout info.
  396. drupal_write_record('ds_layout_settings', $layout_info);
  397. }
  398. }
  399. /*
  400. * Code for the view of the menu items
  401. //get tripal entity id from url then run it against tripal entity db
  402. //and grab the bundle id, then pass bundle id to view
  403. $url = current_path();
  404. $url_exploded = explode("/", $url);
  405. $tripal_entity_id = (int)$url_exploded[1];
  406. $result = db_select('tripal_entity', 'te')
  407. ->fields('te', array('bundle'))
  408. ->condition('id', $tripal_entity_id, '=')
  409. ->execute()
  410. ->fetchField();
  411. */
  412. /**
  413. * Implements hook_field_display_alter().
  414. * Alters the display settings of a field before it gets displayed.
  415. *
  416. * Hides the empty tripal panes if the content type has been set to hide empty
  417. * fields. This option is found in the edit tab of the tripal content type with
  418. * a title 'Field Display'.
  419. *
  420. * @param $display
  421. * @param $context
  422. */
  423. function tripal_ds_field_display_alter(&$display, $context){
  424. if ($context['entity_type'] == 'TripalEntity') {
  425. $field_name = $context['field']['field_name'];
  426. $bundle = $context['entity']->bundle;
  427. $bundle_info = tripal_load_bundle_entity(array('name' => $bundle));
  428. $hide_variable = tripal_get_bundle_variable('hide_empty_field', $bundle_info->id, 'hide');
  429. if ($field_name && ($hide_variable == 'hide')) {
  430. $item = field_get_items('TripalEntity', $context['entity'], $field_name);
  431. $field = field_info_field($field_name);
  432. if ($item) {
  433. if (tripal_field_is_empty($item[0], $field)) {
  434. $parent_field_info = tripal_ds_find_field_group_parent($field_name, 'TripalEntity', $bundle, $context);
  435. if (!empty($parent_field_info)) {
  436. foreach ($parent_field_info as $parent_key => $parent_field){
  437. // We want to use JavaScript to remove the fields rather than
  438. // CSS to hide them so that when users theme the table of
  439. // contents using CSS they aren't theming empty rows.
  440. drupal_add_js('jQuery(document).ready(function () { jQuery("#' . $parent_field_info[$parent_key] . '").parents(".views-row").remove() });', 'inline');
  441. }
  442. }
  443. }
  444. }
  445. }
  446. }
  447. }
  448. /**
  449. * Identifies field_group parents to find tripal_panes and return that
  450. * information to the function that calls it.
  451. *
  452. * @param $field_name
  453. * @param $entity_type
  454. * @param $bundle
  455. *
  456. * @return array
  457. */
  458. function tripal_ds_find_field_group_parent($field_name, $entity_type, $bundle, $context){
  459. $field_groups_to_hide = array();
  460. $increment = 0;
  461. // Get the field groups associated with this bundle.
  462. $fg_for_bundle = db_select('field_group', 'fg')
  463. ->fields('fg')
  464. ->condition('bundle', $bundle, '=')
  465. ->condition('entity_type', $entity_type, '=')
  466. ->execute()->fetchAll();
  467. // Run through the field groups looking for the provided $field_name
  468. foreach ($fg_for_bundle as $field_groups => $field_group) {
  469. $field_group_data = unserialize($field_group->data);
  470. // There is a separate function to deal with tables, so disregard.
  471. /*if ($field_group_data['format_type'] == 'table'){
  472. // Do nothing
  473. }
  474. else*/if (!empty($field_group_data['children'][0])) {
  475. $children = $field_group_data['children'];
  476. //If there is more than one child all need to be checked.
  477. if (count($children) > 1) {
  478. foreach ($children as $kids => $child) {
  479. // Now check if each child if empty.
  480. $item = field_get_items('TripalEntity', $context['entity'], $child);
  481. $field = field_info_field($child);
  482. if(!tripal_field_is_empty($item[0], $field)){
  483. //If any of the fields are not empty do not add the parent.
  484. break 2;
  485. }
  486. else {
  487. continue;
  488. }
  489. }
  490. $field_groups_to_hide[$increment] = $field_group->group_name;
  491. }
  492. elseif($children[0] == $field_name) {
  493. $field_groups_to_hide[$increment] = $field_group->group_name;
  494. }
  495. }
  496. $increment++;
  497. }
  498. // Remove duplicate values.
  499. $field_groups_to_hide = array_unique($field_groups_to_hide);
  500. return $field_groups_to_hide;
  501. }
  502. /**
  503. * Updates the tripal_ds table with weight information of field_groups on
  504. * save of "manage display' of content type. Weight is what is used to order
  505. * the menu items.
  506. *
  507. * @param $bundle
  508. * @param array $fields
  509. */
  510. function tripal_ds_toc_order($bundle, $fields = array()){
  511. // Find all menu items associated with the bundle id.
  512. $menu_items = db_select('tripal_ds', 'ds')
  513. ->fields('ds')
  514. ->condition('bundle', $bundle, '=')
  515. ->execute()->fetchAll();
  516. // Now find all menu items in the $fields array
  517. foreach ($menu_items as $menu_items => $menu_item) {
  518. $toc_field_name = $menu_item->tripal_ds_field_name;
  519. // Compare the field name from the table with the fields in the array.
  520. if (array_key_exists($toc_field_name, $fields)) {
  521. $weight = $fields[$toc_field_name]['weight'];
  522. //If a weight is returned update the tripal_ds table.
  523. if(!empty($weight)){
  524. db_update('tripal_ds')
  525. ->fields(array(
  526. 'weight' => $weight,
  527. ))
  528. ->condition('bundle', $bundle, '=')
  529. ->condition('tripal_ds_field_name', $toc_field_name, '=')
  530. ->execute();
  531. }
  532. }
  533. }
  534. }