tripal_core.toc.inc 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816
  1. <?php
  2. /**
  3. *
  4. */
  5. function tripal_core_node_toc_form($form, &$form_state, $node) {
  6. // Get info about this content type
  7. $all_types = node_type_get_types();
  8. $type_info = $all_types[$node->type];
  9. $form["#tree"] = TRUE;
  10. $form["instructions"] = array(
  11. '#type' => 'fieldset',
  12. '#collapsed' => TRUE,
  13. '#collapsible' => TRUE,
  14. '#title' => 'Instructions',
  15. );
  16. $admin_link = l(
  17. $type_info->name . " TOC administrative page",
  18. "admin/tripal/legacy/" . $type_info->module . "/" . $node->type . "toc",
  19. array('attributes' => array('target' => '_blank'))
  20. );
  21. $form["instructions"]["main"] = array(
  22. '#markup' => '<p>' . t("Below is a list of the titles of
  23. content panes that can appear on this page. These titles appear in the
  24. the following order in the Table of Contents (TOC). You may rename
  25. the titles or drag and drop them to change the order. <b>Any changes will
  26. only apply to this page</b>. If you would like to make changes apply to multiple
  27. pages of the same type, please visit the $admin_link. ") . '</p>' .
  28. '<p>' . t('The list below shows all possible content panes that can appear.
  29. However, those without content are automatically hidden and do not
  30. appear in the TOC.' . '</p>'),
  31. );
  32. $form['node'] = array(
  33. '#type' => 'value',
  34. '#value' => $node,
  35. );
  36. // Get the content array for this node, then pass it through the
  37. // tripal_core_node_view_alter which generates the TOC. After that
  38. // we can use the $build array to build the form. We have to add
  39. // a 'tripal_toc_mode' to the $node because we need to give the mode
  40. // to the tripal_core_node_view_build_toc function.
  41. $node->tripal_toc_mode = 'manage_node';
  42. node_build_content($node);
  43. $build = $node->content;
  44. $build["#node"] = $node;
  45. tripal_core_node_view_alter($build);
  46. // Iterate through the built items and add form elemetns for each one.
  47. foreach(element_children($build) as $key) {
  48. $element = $build[$key];
  49. if (array_key_exists('#tripal_toc_id', $element)) {
  50. $toc_id = $element['#tripal_toc_id'];
  51. $toc_title = $element['#tripal_toc_title'];
  52. $toc_weight = $element['#weight'];
  53. $toc_hide = $element['#hide'];
  54. // If this element is a link then we don't want to allow the user
  55. // to change the title as the link title is changed by using the
  56. // interface that created the link.
  57. $is_link = array_key_exists('#is_link', $element) ? $element['#is_link'] : FALSE;
  58. if (!$is_link) {
  59. $form['toc_items'][$toc_id]['title'] = array(
  60. '#type' => 'textfield',
  61. '#default_value' => $toc_title,
  62. );
  63. }
  64. else {
  65. $form['toc_items'][$toc_id]['title'] = array(
  66. '#markup' => '<i>link title:</i> ' . $toc_title,
  67. '#value' => $toc_title,
  68. );
  69. }
  70. $form['toc_items'][$toc_id]['hide'] = array(
  71. '#type' => 'checkbox',
  72. '#default_value' => $toc_hide,
  73. );
  74. $form['toc_items'][$toc_id]['weight'] = array(
  75. '#type' => 'textfield',
  76. '#default_value' => $toc_weight,
  77. '#attributes' => array(
  78. 'class' => array('tripal-node-toc-items-weights'),
  79. ),
  80. '#size' => 5,
  81. );
  82. }
  83. }
  84. $form['toc_items']['#theme'] = 'tripal_node_toc_items_table';
  85. $form['submit'] = array(
  86. '#type' => 'submit',
  87. '#name' => 'toc_submit',
  88. '#value' => t('Submit'),
  89. );
  90. $form['unset'] = array(
  91. '#type' => 'submit',
  92. '#name' => 'toc_unset',
  93. '#value' => t('Unset Node Customizations'),
  94. );
  95. // Check to see if this node's TOC is specifically being managed.
  96. $sql = "SELECT count(*) FROM {tripal_toc} where nid = :nid";
  97. $managed_items = db_query($sql, array(':nid' => $node->nid))->fetchField();
  98. if ($managed_items > 0) {
  99. $form['is_managed'] = array(
  100. '#markup' => '<p><font color="red">' .
  101. t('This page currently has customiations to the TOC.</font> This means
  102. that any customzations for the content type are overriden. Click the
  103. "Unset Node Customizations" button above to remove page-level
  104. customizations and default to the content type settings.') . '</p>',
  105. );
  106. }
  107. return $form;
  108. }
  109. /**
  110. *
  111. * @param $variables
  112. */
  113. function theme_tripal_node_toc_items_table($variables) {
  114. $elements = $variables['element'];
  115. $toc_items = array();
  116. // Sort the toc_items using a custom sort function. But we need to include
  117. // only the items we want in the table (exclude renderable stuff).
  118. foreach(element_children($elements) as $key) {
  119. $toc_items[] = $elements[$key];
  120. }
  121. usort($toc_items, 'theme_tripal_node_sort_toc_items');
  122. // Build the table header.
  123. $headers = array('Content Pane Name', 'Hide', 'Weight');
  124. // Format the form elements as rows in the table.
  125. $rows = array();
  126. foreach ($toc_items as $key => $item) {
  127. $rows[] = array(
  128. 'data' => array(
  129. drupal_render($item['title']),
  130. drupal_render($item['hide']),
  131. drupal_render($item['weight']),
  132. ),
  133. 'class' => array('draggable'),
  134. );
  135. }
  136. // Theme and return the table.
  137. $table = array(
  138. 'header' => $headers,
  139. 'rows' => $rows,
  140. 'attributes' => array("id" => 'tripal-node-toc-items-table'),
  141. 'sticky' => TRUE,
  142. 'caption' => t('Content Panes Available in the TOC'),
  143. 'colgroups' => array(),
  144. 'empty' => t('There are no content panes for this page'),
  145. );
  146. drupal_add_tabledrag('tripal-node-toc-items-table', 'order', 'sibling', 'tripal-node-toc-items-weights');
  147. return theme_table($table);
  148. }
  149. /**
  150. *
  151. * @param $a
  152. * @param $b
  153. */
  154. function theme_tripal_node_sort_toc_items($a, $b) {
  155. if ($a['weight']['#value'] < $b['weight']['#value']) {
  156. return -1;
  157. }
  158. if ($a['weight']['#value'] > $b['weight']['#value']) {
  159. return 1;
  160. }
  161. if ($a['weight']['#value'] == $b['weight']['#value']) {
  162. return strcmp($a['title']['#value'], $b['title']['#value']);
  163. }
  164. }
  165. /**
  166. * Implements hook_validate for the tripal_core_node_toc_form.
  167. */
  168. function tripal_core_node_toc_form_validate($form, &$form_state) {
  169. $toc_items = $form_state['values']['toc_items'];
  170. // Iterate through the TOC items and validate.
  171. foreach ($toc_items as $toc_id => $item) {
  172. if (array_key_exists('title', $item) and !$item['title']) {
  173. form_set_error('toc_items][' . $toc_id, "Please provide a valid title.");
  174. }
  175. }
  176. }
  177. /**
  178. * Implements hook_submit for the tripal_core_node_toc_form.
  179. */
  180. function tripal_core_node_toc_form_submit($form, &$form_state) {
  181. $toc_items = $form_state['values']['toc_items'];
  182. $node = $form_state['values']['node'];
  183. if ($form_state['clicked_button']['#name'] == "toc_submit") {
  184. $transaction = db_transaction();
  185. try {
  186. // First delete any settings for this node
  187. db_delete('tripal_toc')
  188. ->condition('nid', $node->nid)
  189. ->execute();
  190. // Second add in any new settings for this node
  191. foreach ($toc_items as $toc_id => $item) {
  192. db_insert('tripal_toc')
  193. ->fields(array(
  194. 'node_type' => $node->type,
  195. 'key' => $toc_id,
  196. 'title' => array_key_exists('title', $item) ? $item['title'] : '',
  197. 'weight' => $item['weight'],
  198. 'nid' => $node->nid,
  199. 'hide' => $item['hide'],
  200. ))
  201. ->execute();
  202. }
  203. drupal_set_message("TOC changes successfully applied to this node only.");
  204. }
  205. catch (Exception $e) {
  206. $transaction->rollback();
  207. drupal_set_message("Failed to apply TOC changes.", "error");
  208. }
  209. }
  210. if ($form_state['clicked_button']['#name'] == "toc_unset") {
  211. $transaction = db_transaction();
  212. try {
  213. // First delete any settings for this node
  214. db_delete('tripal_toc')
  215. ->condition('nid', $node->nid)
  216. ->execute();
  217. drupal_set_message("TOC is no longer customized specifically for this page. Now using the content type settings.");
  218. }
  219. catch (Exception $e) {
  220. $transaction->rollback();
  221. drupal_set_message("Failed to apply TOC changes.", "error");
  222. }
  223. }
  224. }
  225. /**
  226. * To be called by tripal_core_node_view_alter() to generate the TOC.
  227. *
  228. * @param $build
  229. * The build array passed to hook_node_view_alter()
  230. *
  231. */
  232. function tripal_core_node_view_build_toc(&$build) {
  233. global $theme;
  234. // if this is not a full node view, we do not want to alter
  235. if ($build['#view_mode'] != 'full' OR !array_key_exists('#tripal_generic_node_template', $build)) {
  236. return;
  237. }
  238. $node_type = $build["#node"]->type;
  239. $nid = $build["#node"]->nid;
  240. // The mode alters the format of the build array. There are three types of
  241. // modes: "display", "manage_node", "manage_type". If "display" is provided
  242. // then the build array is formatted for the display of the content.
  243. // If "manage_node" is provided then the build array will contain all
  244. // content panes regardless if the pane should be hidden. This allows
  245. // the management tool to find all content panes and their settings. If
  246. // "manage_type" is provided then node-specific content panes are
  247. // excluded. Node-specific content panes are those that appear only on
  248. // specific nodes and therefore should not be used when managing the
  249. // TOC for a content type.
  250. $mode = isset($build["#node"]->tripal_toc_mode) ? $build["#node"]->tripal_toc_mode : "display";
  251. $cache = cache_get("theme_registry:$theme", 'cache');
  252. $node = $build['#node'];
  253. $toc = array();
  254. $toc_html = '';
  255. // If we are looking at a Tripal node template then we want to
  256. // make some changes to each pane of content so that we can associate
  257. // a table of contents and add administrator and curator messages.
  258. if ($build['#tripal_generic_node_template'] == TRUE) {
  259. // Iterate through all the elements of the $build array and for those
  260. // that are wanting to provide content for this node.
  261. $markup = array();
  262. foreach ($build as $key => $value) {
  263. $value = $build[$key];
  264. // Skip the body element as the Tripal node types do not use it.
  265. if ($key == 'body') {
  266. continue;
  267. }
  268. // Skip the table of contents and links as those will be placed elsewhere.
  269. if (preg_match('/^#/', $key) or $key == 'tripal_toc' or $key == 'links') {
  270. continue;
  271. }
  272. // For backwards compatibility we will handle the content type fields
  273. // named 'field_resource_blocks', 'field_resource_titles', and 'field_resource_links'
  274. // these fields can be added on the Drupal content types page and were
  275. // specifically recoginzed by Tripal v1.1. If the mode type is "manage_type"
  276. // then remove these content panes because they are node specific.
  277. if ($mode == "manage_type" and (
  278. $key == "field_resource_links" or
  279. $key == "field_resource_titles" or
  280. $key == "field_resource_blocks")) {
  281. unset($build[$key]);
  282. continue;
  283. }
  284. if ($key == "field_resource_links") {
  285. // links should just appear on the sidebar as is and not open up a panel
  286. foreach (element_children($build[$key]) as $index) {
  287. $element = $build[$key][$index];
  288. $weight = 0;
  289. $hide = 0;
  290. $toc_item_id = "resource-link-$index";
  291. // Get any overrides for this key.
  292. $overrides = tripal_core_get_toc_overrides($nid, $toc_item_id, $node_type, $mode);
  293. $weight = $overrides['weight'] ? $overrides['weight'] : $weight;
  294. $hide = $overrides['hide'] ? $overrides['hide'] : $hide;
  295. // If the element should be hidden then unset this key the build
  296. // array continue to the next one
  297. if ($mode == "display" and $overrides['hide'] == 1) {
  298. continue;
  299. }
  300. // This field supports tokens, so we need to perform the substitutions
  301. // if one is needed. Get the tokens and format
  302. $base_table = preg_replace('/^chado_(.*)$/', '\1', $node_type);
  303. $tokens = chado_node_generate_tokens($base_table);
  304. $markup = $element['#markup'];
  305. // Determine which tokens were used in the format string
  306. if (preg_match_all('/\[[^]]+\]/', $markup, $used_tokens)) {
  307. // Get the value for each token used
  308. foreach ($used_tokens[0] as $token) {
  309. $token_info = $tokens[$token];
  310. if (!empty($token_info)) {
  311. $value = chado_get_token_value($token_info, $node);
  312. $markup = str_replace($token, $value, $markup);
  313. }
  314. }
  315. $element['#markup'] = $markup;
  316. }
  317. // Add the link to the TOC
  318. $parts = explode("|", $element['#markup']);
  319. if (count($parts) == 2) {
  320. $toc[$weight][$parts[0]] = "<div id=\"$toc_item_id\" class=\"tripal_toc_list_item\">" . l($parts[0], $parts[1], array('attributes' => array('target' => '_blank'))) . "</div>";
  321. }
  322. else {
  323. $toc[$weight][$parts[0]] = "<div id=\"$toc_item_id\" class=\"tripal_toc_list_item\">" . $element['#markup'] . "</div>";
  324. }
  325. // Add to the build array but do not add markup. This way
  326. // when the TOC is managed by the node 'TOC' menu these links can
  327. // be ordered as well.
  328. $build[$toc_item_id]['#toc_handled'] = TRUE;
  329. $build[$toc_item_id]['#tripal_toc_id'] = $toc_item_id;
  330. $build[$toc_item_id]['#tripal_toc_title'] = $parts[0];
  331. $build[$toc_item_id]['#weight'] = $weight;
  332. $build[$toc_item_id]['#hide'] = $hide;
  333. $build[$toc_item_id]['#is_link'] = TRUE;
  334. }
  335. // Remove the orilink from the build array as we've moved it to
  336. // appear in the TOC
  337. unset($build[$key]);
  338. continue;
  339. }
  340. if ($key == "field_resource_titles") {
  341. // ignore these, we will use them in the field_resource_blocks if
  342. // statement below
  343. continue;
  344. }
  345. if ($key == "field_resource_blocks") {
  346. foreach (element_children($build[$key]) as $index) {
  347. // get the details and the title
  348. $weight = 0;
  349. $hide = 0;
  350. $markup = $build[$key][$index]["#markup"];
  351. $toc_item_id = "resource-$index";
  352. // Get any overrides for this key.
  353. $overrides = tripal_core_get_toc_overrides($nid, $toc_item_id, $node_type, $mode);
  354. // If the element should be hidden then unset this key the build
  355. // array continue to the next one
  356. if ($mode == "display" and $overrides['hide'] == 1) {
  357. continue;
  358. }
  359. $toc_item_title = $build["field_resource_titles"][$index]["#markup"];
  360. $toc_item_title = $overrides['title'] ? $overrides['title'] : $toc_item_title;
  361. $weight = $overrides['weight'] ? $overrides['weight'] : $weight;
  362. $hide = $overrides['hide'] ? $overrides['hide'] : $hide;
  363. $updated_markup = "
  364. <div id=\"$toc_item_id-tripal-data-pane\" class=\"tripal-data-pane\">
  365. <div class=\"$toc_item_id-tripal-data-pane-title tripal-data-pane-title\">$toc_item_title</div>
  366. $markup
  367. </div>
  368. </div>
  369. ";
  370. $build[$toc_item_id]['#markup'] = $updated_markup;
  371. $build[$toc_item_id]['#toc_handled'] = TRUE;
  372. $build[$toc_item_id]['#tripal_toc_id'] = $toc_item_id;
  373. $build[$toc_item_id]['#tripal_toc_title'] = $toc_item_title;
  374. $build[$toc_item_id]['#weight'] = $weight;
  375. $build[$toc_item_id]['#hide'] = $hide;
  376. // add the entry to the TOC
  377. $toc_item_link = "
  378. <div class=\"tripal_toc_list_item\">
  379. <a id=\"$toc_item_id\" class=\"tripal_toc_list_item_link\" href=\"?pane=$toc_item_id\">$toc_item_title</a>
  380. </div>
  381. ";
  382. $toc[$weight][$toc_item_title] = $toc_item_link;
  383. }
  384. // Remove the key from the build array. We have have replaced it
  385. unset($build[$key]);
  386. unset($build["field_resource_titles"]);
  387. continue;
  388. } // end if ($mode != "manage_type" and $key == "field_resource_blocks") {
  389. // Skip any keys we may have already handled. This is the case for
  390. // the field_resource_blocks where we removed the old CCK fields
  391. // and added new ones. We don't want these new ones to be processed
  392. // again by the code below.
  393. if (array_key_exists('#toc_handled', $build[$key]) and $build[$key]['#toc_handled'] == TRUE) {
  394. continue;
  395. }
  396. // For all other fields we will handle in the following way.
  397. //-----------------------
  398. // INITIALIZE THE CONTENT VARIABLES
  399. //-----------------------
  400. $toc_item_title = $key;
  401. $toc_item_id = $key;
  402. $toc_item_link = '';
  403. $weight = 0;
  404. $hide = 0;
  405. // get the title for the table of contents. Tripal templates should
  406. // have a '#tripal_toc_title' element in the build array
  407. if (array_key_exists('#tripal_toc_title', $build[$key])) {
  408. $toc_item_title = $build[$key]['#tripal_toc_title'];
  409. }
  410. // other elements in the $build array may just have a '#title' element,
  411. if (array_key_exists('#title', $build[$key])) {
  412. $toc_item_title = $build[$key]['#title'];
  413. }
  414. $toc_item_title = ucwords($toc_item_title);
  415. if (array_key_exists('#weight', $build[$key])) {
  416. $weight = $build[$key]['#weight'];
  417. }
  418. if (array_key_exists('#tripal_toc_id', $build[$key])) {
  419. $toc_item_id = $build[$key]['#tripal_toc_id'];
  420. }
  421. // Get any overrides for this key.
  422. $overrides = tripal_core_get_toc_overrides($nid, $toc_item_id, $node_type, $mode);
  423. // If the element should be hidden then unset this key the build
  424. // array continue to the next one
  425. if ($mode == "display" and $overrides['hide'] == 1) {
  426. unset($build[$key]);
  427. continue;
  428. }
  429. // now override the title, weight, hidden values if a value is set in the tripal_toc table
  430. $toc_item_title = $overrides['title'] ? $overrides['title'] : $toc_item_title;
  431. $weight = $overrides['weight'] ? $overrides['weight'] : $weight;
  432. $hide = $overrides['hide'] ? $overrides['hide'] : $hide;
  433. $toc_item_link = "<div class=\"tripal_toc_list_item\"><a id=\"$toc_item_id\" class=\"tripal_toc_list_item_link\" href=\"?pane=$toc_item_id\">$toc_item_title</a></div>";
  434. //-----------------------
  435. // GET THE MARKUP FOR EACH ELEMENT
  436. //-----------------------
  437. $markup = '';
  438. // find the markup. Some fields will have a '#markup' and others, such
  439. // as CCK elements may have a set of '#markup' elements organized by
  440. // numerical keys.
  441. if (array_key_exists('#markup', $build[$key]) and trim($build[$key]['#markup'])) {
  442. $markup = $build[$key]['#markup'];
  443. }
  444. // For backwards copmatibility we should support the '#value' element as well.
  445. elseif (array_key_exists('#value', $build[$key]) and trim($build[$key]['#value'])) {
  446. $markup = $build[$key]['#markup'];
  447. }
  448. // if we have no '#markup' field then this element has not yet
  449. // been rendered. Let's render it and substitute that for markup
  450. if (!$markup) {
  451. $markup = trim(render($build[$key]));
  452. }
  453. // Setup the content array for this element
  454. $build[$key] = array(
  455. '#markup' => $markup,
  456. '#tripal_toc_id' => $toc_item_id,
  457. '#tripal_toc_title' => $toc_item_title,
  458. '#weight' => $weight,
  459. '#hide' => $hide,
  460. );
  461. // if we still don't have markup then skip this one
  462. if (!$markup) {
  463. continue;
  464. }
  465. //-----------------------
  466. // FIND THE TEMPLATE PATH
  467. //-----------------------
  468. // get the template path so we can put it in an admin message box
  469. $path = '';
  470. if (!array_key_exists('#tripal_template_show', $build[$key]) or
  471. $build[$key]['#tripal_template_show'] == TRUE) {
  472. if ($cache and array_key_exists($key, $cache->data) and array_key_exists('path', $cache->data[$key])) {
  473. $path = $cache->data[$key]['path'] . '/' . $key . '.tpl.php';
  474. $path = tripal_set_message("Administrators, you can
  475. customize the way the content above is presented. Tripal provides a template
  476. file for each pane of content. To customize, copy the template file to your
  477. site's default theme, edit then " .
  478. l('clear the Drupal cache', 'admin/config/development/performance', array('attributes' => array('target' => '_blank'))) . ".
  479. Currently, the content above is provided by this template: <br><br>$path",
  480. TRIPAL_INFO,
  481. array('return_html' => 1)
  482. );
  483. }
  484. }
  485. //-----------------------
  486. // ADD THIS PANE TO THE TOC BY ORDER OF WEIGHT
  487. //-----------------------
  488. // set the weight of the TOC item and add it to our $toc array
  489. // for building of the TOC below
  490. $weight = 0;
  491. if (array_key_exists('#weight', $build[$key])) {
  492. $weight = $build[$key]['#weight'];
  493. }
  494. $toc[$weight][$toc_item_title] = $toc_item_link;
  495. //-----------------------
  496. // CREATE THE CONTENT PANE MARKUP
  497. //-----------------------
  498. // add a surrounding <div> box around the content
  499. $updated_markup = "
  500. <div id=\"$toc_item_id-tripal-data-pane\" class=\"tripal-data-pane\">
  501. <div class=\"$toc_item_id-tripal-data-pane-title tripal-data-pane-title\">$toc_item_title</div>
  502. $markup
  503. $path
  504. </div>
  505. </div>
  506. ";
  507. $build[$key]['#markup'] = $updated_markup;
  508. } // end foreach ($build as $key => $value) {
  509. } // end if ($build['#tripal_generic_node_template'] == TRUE) {
  510. //-----------------------
  511. // BUILD THE TABLE OF CONTENTS LINKS
  512. //-----------------------
  513. // first sort the links numerically by their weight
  514. ksort($toc, SORT_NUMERIC);
  515. $toc_html = '';
  516. foreach ($toc as $weight => $links) {
  517. // for links in the same weight, sort them alphabetically
  518. ksort($links);
  519. foreach ($links as $toc_item_title => $toc_item_link) {
  520. $toc_html .= $toc_item_link;
  521. }
  522. }
  523. $build['tripal_toc']['#markup'] = "<div id=\"$node->type-tripal-toc-pane\" class=\"tripal-toc-pane\">$toc_html</div>";
  524. }
  525. /**
  526. *
  527. * @param $build
  528. */
  529. function tripal_core_get_toc_overrides($nid, $key, $node_type, $mode) {
  530. // Set override defaults
  531. $override_title = '';
  532. $override_weight = '';
  533. $override_hide = 0;
  534. if ($mode != "manage_type") {
  535. // First look to see if the node has customizations for this item.
  536. $toc_item_overrides = db_select('tripal_toc', 'tc')
  537. ->fields('tc', array('title', 'weight', 'hide'))
  538. ->condition('key', $key)
  539. ->condition('nid', $nid)
  540. ->execute()
  541. ->fetchObject();
  542. if ($toc_item_overrides) {
  543. $override_title = $toc_item_overrides->title;
  544. $override_weight = $toc_item_overrides->weight;
  545. $override_hide = $toc_item_overrides->hide;
  546. return array(
  547. 'title' => $override_title,
  548. 'weight' => $override_weight,
  549. 'hide' => $override_hide,
  550. );
  551. }
  552. }
  553. // If there are no specific node customizations then look to see if there
  554. // are customizations for this content type.
  555. $toc_item_overrides = db_select('tripal_toc', 'tc')
  556. ->fields('tc', array('title', 'weight', 'hide'))
  557. ->condition('node_type', $node_type)
  558. ->condition('key', $key)
  559. ->isNull('nid')
  560. ->execute()
  561. ->fetchObject();
  562. if ($toc_item_overrides) {
  563. $override_title = $toc_item_overrides->title;
  564. $override_weight = $toc_item_overrides->weight;
  565. $override_hide = $toc_item_overrides->hide;
  566. }
  567. return array(
  568. 'title' => $override_title,
  569. 'weight' => $override_weight,
  570. 'hide' => $override_hide,
  571. );
  572. }
  573. /**
  574. *
  575. */
  576. function tripal_core_content_type_toc_form($form, &$form_state, $content_type) {
  577. // Get the type details
  578. $all_types = node_type_get_types();
  579. $type_info = $all_types[$content_type];
  580. $form["#tree"] = TRUE;
  581. // Get a single node of this type so we can get all the possible content
  582. // for it.
  583. $sql = "SELECT nid FROM {node} WHERE type = :type LIMIT 1 OFFSET 0";
  584. $nid = db_query($sql, array(':type' => $content_type))->fetchField();
  585. if (!$nid) {
  586. $form["not_available"] = array(
  587. '#markup' => t('Please sync at least one %type_name record. A node
  588. must exist before customizations to the Table of Contents (TOC) can
  589. be performed.', array('%type_name' => $type_info->name)),
  590. );
  591. return $form;
  592. }
  593. // Load the node
  594. $node = node_load($nid);
  595. // Get the content array for this node, then pass it through the
  596. // tripal_core_node_view_alter which generates the TOC. After that
  597. // we can use the $build array to build the form. We have to add
  598. // a 'tripal_toc_mode' to the $node because we need to give the mode
  599. // to the tripal_core_node_view_build_toc function.
  600. $node->tripal_toc_mode = 'manage_type';
  601. node_build_content($node);
  602. $build = $node->content;
  603. $build["#node"] = $node;
  604. tripal_core_node_view_alter($build);
  605. $form["instructions"] = array(
  606. '#type' => 'fieldset',
  607. '#collapsed' => TRUE,
  608. '#collapsible' => TRUE,
  609. '#title' => 'Instructions',
  610. );
  611. $form["instructions"]["main"] = array(
  612. '#markup' => '</p>' . t('Below is a list of the titles of
  613. content panes that can appear on all %type_name pages. You may rename
  614. the titles or drag and drop them to change the order. Content that appears
  615. only on a single page can not be ordered here, but must be ordered using
  616. the TOC tab on the page itself. If a page has customized TOC settings
  617. then those settings will take precedent over these.',
  618. array('%type_name' => $type_info->name)) . '</p>' .
  619. '<p>' . t('The list below shows all possible content
  620. panes that can appear. However, those without content are automatically
  621. hidden and do not appear in the TOC.' . '</p>'),
  622. );
  623. $form['content_type'] = array(
  624. '#type' => 'value',
  625. '#value' => $content_type,
  626. );
  627. // Iterate through the built items and add form elemetns for each one.
  628. foreach(element_children($build) as $key) {
  629. $element = $build[$key];
  630. if (array_key_exists('#tripal_toc_id', $element)) {
  631. $toc_id = $element['#tripal_toc_id'];
  632. $toc_title = $element['#tripal_toc_title'];
  633. $toc_weight = $element['#weight'];
  634. $toc_hide = $element['#hide'];
  635. $form['toc_items'][$toc_id]['title'] = array(
  636. '#type' => 'textfield',
  637. '#default_value' => $toc_title,
  638. );
  639. $form['toc_items'][$toc_id]['hide'] = array(
  640. '#type' => 'checkbox',
  641. '#default_value' => $toc_hide,
  642. );
  643. $form['toc_items'][$toc_id]['weight'] = array(
  644. '#type' => 'textfield',
  645. '#default_value' => $toc_weight,
  646. '#attributes' => array(
  647. 'class' => array('tripal-node-toc-items-weights'),
  648. ),
  649. '#size' => 5,
  650. );
  651. }
  652. }
  653. $form['toc_items']['#theme'] = 'tripal_node_toc_items_table';
  654. $form['submit'] = array(
  655. '#type' => 'submit',
  656. '#name' => 'toc_submit',
  657. '#value' => t('Submit'),
  658. );
  659. $form['unset'] = array(
  660. '#type' => 'submit',
  661. '#name' => 'toc_unset',
  662. '#value' => t('Reset to Defaults'),
  663. );
  664. return $form;
  665. }
  666. /**
  667. * Implements hook_validate for the tripal_core_node_toc_form.
  668. */
  669. function tripal_core_content_type_toc_form_validate($form, &$form_state) {
  670. $toc_items = $form_state['values']['toc_items'];
  671. // Iterate through the TOC items and validate.
  672. foreach ($toc_items as $toc_id => $item) {
  673. if (!$item['title']) {
  674. form_set_error('toc_items][' . $toc_id, "Please provide a valid title.");
  675. }
  676. }
  677. }
  678. /**
  679. * Implements hook_submit for the tripal_core_node_toc_form.
  680. */
  681. function tripal_core_content_type_toc_form_submit($form, &$form_state) {
  682. $toc_items = $form_state['values']['toc_items'];
  683. $content_type = $form_state['values']['content_type'];
  684. if ($form_state['clicked_button']['#name'] == "toc_submit") {
  685. $transaction = db_transaction();
  686. try {
  687. // First delete any settings for this content type
  688. db_delete('tripal_toc')
  689. ->condition('node_type', $content_type)
  690. ->isNull('nid')
  691. ->execute();
  692. // Second add in any new settings for this node
  693. foreach ($toc_items as $toc_id => $item) {
  694. db_insert('tripal_toc')
  695. ->fields(array(
  696. 'node_type' => $content_type,
  697. 'key' => $toc_id,
  698. 'title' => $item['title'],
  699. 'weight' => $item['weight'],
  700. 'hide' => $item['hide'],
  701. ))
  702. ->execute();
  703. }
  704. drupal_set_message("TOC changes successfully applied to this content type.");
  705. }
  706. catch (Exception $e) {
  707. $transaction->rollback();
  708. drupal_set_message("Failed to apply TOC changes.", "error");
  709. }
  710. }
  711. if ($form_state['clicked_button']['#name'] == "toc_unset") {
  712. $transaction = db_transaction();
  713. try {
  714. // First delete any settings for this node
  715. db_delete('tripal_toc')
  716. ->condition('node_type', $content_type)
  717. ->isNull('nid')
  718. ->execute();
  719. drupal_set_message("The TOC is reset to defaults for this content type.");
  720. }
  721. catch (Exception $e) {
  722. $transaction->rollback();
  723. drupal_set_message("Failed to apply TOC changes.", "error");
  724. }
  725. }
  726. }