tripal_ds.module 20 KB

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