theme.inc

  1. 7.x includes/theme.inc
  2. 6.x includes/theme.inc
  3. 4.x includes/theme.inc
  4. 5.x includes/theme.inc

File

includes/theme.inc
View source
  1. <?php
  2. /**
  3. * These functions deal mostly with theme-related functions.
  4. * In other words, functions responsible for drawing, rendering, etc, HTML
  5. * to the screen.
  6. */
  7. /**
  8. * Given an array of table headers (in the format listed below), returns back the HTML to draw it to the screen.
  9. * This makes them clickable, to make the table header sortable. This is meant to be used with queries, by adding
  10. * in an "ORDER BY" clause.
  11. *
  12. * $headers should look like this:
  13. * 0 = array('label' => 'First Name', 'field' => 'field__first_name');
  14. *
  15. * If the label should NOT be clickable, then "field" should be blank or absent.
  16. *
  17. *
  18. */
  19. function theme_table_header_sortable($headers = array(), $element_id = "default") {
  20. // Is there a "current student id" being specified in the URL? If so, let's keep it in our links.
  21. $csid = trim(@$_REQUEST['current_student_id']);
  22. if ($csid) {
  23. $csid = "&current_student_id=$csid";
  24. }
  25. $rtn = "";
  26. $rtn .= "<tr>";
  27. $filter = trim(@$_GET['filter']); // if there is an existing filter we need to preserve.
  28. $filter_line = "";
  29. if ($filter) {
  30. $filter_line = "&filter=" . $filter;
  31. }
  32. foreach ($headers as $header) {
  33. $th_class = fp_get_machine_readable(strtolower($header['label']));
  34. $rtn .= "<th class='header-sortable-$th_class'>";
  35. $label = $header['label'];
  36. $field = @$header['field'];
  37. $init_dir = @$hader['init_dir'];
  38. if (!$field) {
  39. $rtn .= $label;
  40. }
  41. else {
  42. // Convert label to a link. Also, show it as ASC or DESC based on if it is currently selected.
  43. // get the current header sort field and dir....
  44. $current_fsort = @$_GET['fsort'];
  45. $current_fsortdir = @$_GET['fsortdir'];
  46. $opposite_fsortdir = 'ASC';
  47. if ($current_fsortdir == 'ASC') {
  48. $opposite_fsortdir = 'DESC';
  49. }
  50. if ($field == $current_fsort) {
  51. if ($current_fsortdir == 'ASC') {
  52. $label .= " <i class='fa fa-chevron-up'></i>";
  53. }
  54. else {
  55. $label .= " <i class='fa fa-chevron-down'></i>";
  56. }
  57. }
  58. $new_fsortdir = 'ASC';
  59. //if ($default_sort) $new_fsortdir = $default_sort;
  60. // Scenario #1:
  61. // We have never clicked this item before. The link should be for THIS field, and for its "new_fsortdir"
  62. if ($current_fsort != $field) {
  63. $link = l($label, $_GET['q'], "fsort=$field&fsortdir=$new_fsortdir" . $filter_line . $csid);
  64. }
  65. // Scenario #2:
  66. // We have just recently clcked this item. We want to REVERSE the sort direction
  67. if ($current_fsort == $field) {
  68. $link = l($label, $_GET['q'], "fsort=$field&fsortdir=$opposite_fsortdir" . $filter_line . $csid);
  69. }
  70. $rtn .= $link;
  71. } // else
  72. $rtn .= "</th>";
  73. } // foreach header
  74. $rtn .= "</tr>";
  75. return $rtn;
  76. } // theme_table_header_sortable
  77. /**
  78. * Sets our initial sort, if there isn't already one set.
  79. */
  80. function theme_table_header_sortable_set_initial_sort($field, $dir) {
  81. if (@$_GET['fsort'] == '') {
  82. $_GET['fsort'] = $field;
  83. $_GET['fsortdir'] = $dir;
  84. }
  85. }
  86. /**
  87. * Used with the theme_table_header_sortable function (meant to be called AFTER headers have been created.)
  88. *
  89. * The main thing we want to do is confirm that what we are getting from GET is a valid fieldname in the headers array,
  90. * to prevent SQL injection.
  91. */
  92. function theme_table_header_sortable_order_by($headers) {
  93. $rtn = "";
  94. $fsort = @$_GET['fsort'];
  95. $fsortdir = @$_GET['fsortdir'];
  96. if (!$fsort) return '';
  97. if ($fsort) {
  98. // Confirm that this field is in the headers array.
  99. $bool_found_it = FALSE;
  100. foreach ($headers as $header) {
  101. if (isset($header['field']) && $header['field'] == $fsort) {
  102. $bool_found_it = TRUE;
  103. break;
  104. }
  105. }
  106. if (!$bool_found_it) return ""; // couldn't find it!
  107. }
  108. if ($fsortdir != "" && $fsortdir != 'ASC' && $fsortdir != 'DESC') {
  109. $fsortdir = '';
  110. }
  111. return "ORDER BY $fsort $fsortdir";
  112. } // ... sortable_order_by
  113. /**
  114. * Adapted from https://api.drupal.org/api/drupal/includes%21pager.inc/function/theme_pager/6.x
  115. *
  116. * The purpose of this is to return the HTML to display a "pager", as created from the pager_query() function.
  117. *
  118. * $tags: An array of labels for the controls in the pager.
  119. * $limit: The number of query results to display per page.
  120. * $element: An optional integer to distinguish between multiple pagers on one page.
  121. * $parameters: An associative array of query string parameters to append to the pager links.
  122. * $quantity: The number of pages in the list.
  123. *
  124. */
  125. function theme_pager($tags = array(), $limit = 10, $element = 0, $parameters = array(), $quantity = 9) {
  126. global $pager_page_array, $pager_total;
  127. // Calculate various markers within this pager piece:
  128. // Middle is used to "center" pages around the current page.
  129. $pager_middle = ceil($quantity / 2);
  130. if (!isset($pager_page_array)) $pager_page_array = array();
  131. if (!isset($pager_page_array[$element])) $pager_page_array[$element] = 0;
  132. if (!isset($pager_total)) $pager_total = array();
  133. if (!isset($pager_total[$element])) $pager_total[$element] = 0;
  134. // current is the page we are currently paged to
  135. $pager_current = $pager_page_array[$element] + 1;
  136. // first is the first page listed by this pager piece (re quantity)
  137. $pager_first = $pager_current - $pager_middle + 1;
  138. // last is the last page listed by this pager piece (re quantity)
  139. $pager_last = $pager_current + $quantity - $pager_middle;
  140. // max is the maximum page number
  141. $pager_max = $pager_total[$element];
  142. // End of marker calculations.
  143. // Prepare for generation loop.
  144. $i = $pager_first;
  145. if ($pager_last > $pager_max) {
  146. // Adjust "center" if at end of query.
  147. $i = $i + ($pager_max - $pager_last);
  148. $pager_last = $pager_max;
  149. }
  150. if ($i <= 0) {
  151. // Adjust "center" if at start of query.
  152. $pager_last = $pager_last + (1 - $i);
  153. $i = 1;
  154. }
  155. // End of generation loop preparation.
  156. $li_first = theme_pager_first(isset($tags[0]) ? $tags[0] : t('« first'), $limit, $element, $parameters);
  157. $li_previous = theme_pager_previous(isset($tags[1]) ? $tags[1] : t('‹ previous'), $limit, $element, 1, $parameters);
  158. $li_next = theme_pager_next(isset($tags[3]) ? $tags[3] : t('next ›'), $limit, $element, 1, $parameters);
  159. $li_last = theme_pager_last(isset($tags[4]) ? $tags[4] : t('last »'), $limit, $element, $parameters);
  160. if ($pager_total[$element] > 1) {
  161. if ($li_first) {
  162. $items[] = array(
  163. 'class' => 'pager-first',
  164. 'data' => $li_first,
  165. );
  166. }
  167. if ($li_previous) {
  168. $items[] = array(
  169. 'class' => 'pager-previous',
  170. 'data' => $li_previous,
  171. );
  172. }
  173. // When there is more than one page, create the pager list.
  174. if ($i != $pager_max) {
  175. if ($i > 1) {
  176. $items[] = array(
  177. 'class' => 'pager-ellipsis',
  178. 'data' => '…',
  179. );
  180. }
  181. // Now generate the actual pager piece.
  182. for (; $i <= $pager_last && $i <= $pager_max; $i++) {
  183. if ($i < $pager_current) {
  184. $items[] = array(
  185. 'class' => 'pager-item',
  186. 'data' => theme_pager_previous($i, $limit, $element, $pager_current - $i, $parameters),
  187. );
  188. }
  189. if ($i == $pager_current) {
  190. $items[] = array(
  191. 'class' => 'pager-current',
  192. 'data' => $i,
  193. );
  194. }
  195. if ($i > $pager_current) {
  196. $items[] = array(
  197. 'class' => 'pager-item',
  198. 'data' => theme_pager_next($i, $limit, $element, $i - $pager_current, $parameters),
  199. );
  200. }
  201. }
  202. if ($i < $pager_max) {
  203. $items[] = array(
  204. 'class' => 'pager-ellipsis',
  205. 'data' => '…',
  206. );
  207. }
  208. }
  209. // End generation.
  210. if ($li_next) {
  211. $items[] = array(
  212. 'class' => 'pager-next',
  213. 'data' => $li_next,
  214. );
  215. }
  216. if ($li_last) {
  217. $items[] = array(
  218. 'class' => 'pager-last',
  219. 'data' => $li_last,
  220. );
  221. }
  222. //return theme('item_list', $items, NULL, 'ul', array(
  223. // 'class' => 'pager',
  224. //));
  225. $rtn = "";
  226. $rtn = "<ul class='pager'>";
  227. foreach ($items as $details) {
  228. $class = @$details['class'];
  229. $data = @$details['data'];
  230. $rtn .= "<li class='$class'>$data</li>";
  231. }
  232. $rtn .= "</ul>";
  233. return "<div class='pager-wrapper pager-wrapper-$element'>$rtn</div>";
  234. }
  235. }
  236. /**
  237. * Adapted from https://api.drupal.org/api/drupal/includes%21pager.inc/function/pager_get_querystring/6.x
  238. */
  239. function pager_get_querystring() {
  240. static $string = NULL;
  241. if (!isset($string)) {
  242. $string = fp_query_string_encode($_REQUEST, array_merge(array(
  243. 'q',
  244. 'page',
  245. 'pass',
  246. ), array_keys($_COOKIE)));
  247. }
  248. return $string;
  249. }
  250. /**
  251. * Adapted from https://api.drupal.org/api/drupal/includes%21pager.inc/function/theme_pager_link/6.x
  252. *
  253. * $text: The link text. Also used to figure out the title attribute of the link, if it is not provided in $attributes['title'];
  254. * in this case, $text must be one of the standard pager link text strings that would be generated by the pager theme functions,
  255. * such as a number or t('« first').
  256. * $page_new: The first result to display on the linked page.
  257. * $element: An optional integer to distinguish between multiple pagers on one page.
  258. * $parameters: An associative array of query string parameters to append to the pager link.
  259. * $attributes: An associative array of HTML attributes to apply to the pager link.
  260. *
  261. */
  262. function theme_pager_link($text, $page_new, $element, $parameters = array(), $attributes = array()) {
  263. $page = isset($_GET['page']) ? $_GET['page'] : '';
  264. if ($new_page = implode(',', pager_load_array($page_new[$element], $element, explode(',', $page)))) {
  265. $parameters['page'] = $new_page;
  266. }
  267. $query = array();
  268. if (count($parameters)) {
  269. $query[] = fp_query_string_encode($parameters, array());
  270. }
  271. $querystring = pager_get_querystring();
  272. if ($querystring != '') {
  273. $query[] = $querystring;
  274. }
  275. // Set each pager link title
  276. if (!isset($attributes['title'])) {
  277. static $titles = NULL;
  278. if (!isset($titles)) {
  279. $titles = array(
  280. t('« first') => t('Go to first page'),
  281. t('‹ previous') => t('Go to previous page'),
  282. t('next ›') => t('Go to next page'),
  283. t('last »') => t('Go to last page'),
  284. );
  285. }
  286. if (isset($titles[$text])) {
  287. $attributes['title'] = $titles[$text];
  288. }
  289. else {
  290. if (is_numeric($text)) {
  291. $attributes['title'] = t('Go to page @number', array(
  292. '@number' => $text,
  293. ));
  294. }
  295. }
  296. }
  297. return l($text, $_GET['q'], count($query) ? implode('&', $query) : '', $attributes);
  298. /*
  299. return l($text, $_GET['q'], array(
  300. 'attributes' => $attributes,
  301. 'query' => count($query) ? implode('&', $query) : NULL,
  302. ));
  303. */
  304. }
  305. /**
  306. * Adapted from: https://api.drupal.org/api/drupal/includes%21pager.inc/function/theme_pager_first/6.x
  307. */
  308. function theme_pager_first($text, $limit, $element = 0, $parameters = array()) {
  309. global $pager_page_array;
  310. $output = '';
  311. // If we are anywhere but the first page
  312. if ($pager_page_array[$element] > 0) {
  313. $output = theme_pager_link($text, pager_load_array(0, $element, $pager_page_array), $element, $parameters);
  314. }
  315. return $output;
  316. }
  317. /**
  318. * Adapted from https://api.drupal.org/api/drupal/includes%21pager.inc/function/theme_pager_last/6.x
  319. */
  320. function theme_pager_last($text, $limit, $element = 0, $parameters = array()) {
  321. global $pager_page_array, $pager_total;
  322. $output = '';
  323. // If we are anywhere but the last page
  324. if ($pager_page_array[$element] < $pager_total[$element] - 1) {
  325. $output = theme_pager_link($text, pager_load_array($pager_total[$element] - 1, $element, $pager_page_array), $element, $parameters);
  326. }
  327. return $output;
  328. }
  329. /**
  330. * Adapted from https://api.drupal.org/api/drupal/includes%21pager.inc/function/theme_pager_next/6.x
  331. */
  332. function theme_pager_next($text, $limit, $element = 0, $interval = 1, $parameters = array()) {
  333. global $pager_page_array, $pager_total;
  334. $output = '';
  335. // If we are anywhere but the last page
  336. if ($pager_page_array[$element] < $pager_total[$element] - 1) {
  337. $page_new = pager_load_array($pager_page_array[$element] + $interval, $element, $pager_page_array);
  338. // If the next page is the last page, mark the link as such.
  339. if ($page_new[$element] == $pager_total[$element] - 1) {
  340. $output = theme_pager_last($text, $limit, $element, $parameters);
  341. }
  342. else {
  343. $output = theme_pager_link($text, $page_new, $element, $parameters);
  344. }
  345. }
  346. return $output;
  347. }
  348. /**
  349. * Adapted from https://api.drupal.org/api/drupal/includes%21pager.inc/function/theme_pager_previous/6.x
  350. */
  351. function theme_pager_previous($text, $limit, $element = 0, $interval = 1, $parameters = array()) {
  352. global $pager_page_array;
  353. $output = '';
  354. // If we are anywhere but the first page
  355. if ($pager_page_array[$element] > 0) {
  356. $page_new = pager_load_array($pager_page_array[$element] - $interval, $element, $pager_page_array);
  357. // If the previous page is the first page, mark the link as such.
  358. if ($page_new[$element] == 0) {
  359. $output = theme_pager_first($text, $limit, $element, $parameters);
  360. }
  361. else {
  362. $output = theme_pager_link($text, $page_new, $element, $parameters);
  363. }
  364. }
  365. return $output;
  366. }
  367. /**
  368. * Adapted from https://api.drupal.org/api/drupal/includes%21pager.inc/function/pager_load_array/6.x
  369. *
  370. * Copies $old_array to $new_array and sets $new_array[$element] = $value Fills in $new_array[0 .. $element - 1] = 0
  371. *
  372. */
  373. function pager_load_array($value, $element, $old_array) {
  374. $new_array = $old_array;
  375. // Look for empty elements.
  376. for ($i = 0; $i < $element; $i++) {
  377. if (!$new_array[$i]) {
  378. // Load found empty element with 0.
  379. $new_array[$i] = 0;
  380. }
  381. }
  382. // Update the changed element.
  383. $new_array[$element] = (int) $value;
  384. return $new_array;
  385. }
  386. /**
  387. * Format a timestamp using the date command.
  388. * TODO: Make the formats something which can be controlled through the settings.
  389. *
  390. * Available formats:
  391. * - standard
  392. * - short
  393. * - pretty
  394. * - just_date
  395. * - just_time
  396. *
  397. */
  398. function format_date($timestamp = 0, $format = "standard", $custom = "") {
  399. if (!is_numeric($timestamp)) {
  400. $timestamp = 0; // make sure it's numeric.
  401. }
  402. if ($timestamp == 0) {
  403. $timestamp = strtotime("now");
  404. }
  405. $f = "";
  406. if ($format == "standard") {
  407. $f = "n/d/Y h:i:sa";
  408. }
  409. if ($format == "short") {
  410. $f = "n/d/Y - g:ia";
  411. }
  412. if ($format == "pretty") {
  413. $f = "F jS, Y, g:ia";
  414. }
  415. if ($format == 'long_no_year') {
  416. $f = 'l, F jS \a\t g:ia';
  417. }
  418. if ($format == "just_date") {
  419. $f = "F jS, Y";
  420. }
  421. if ($format == 'just_time') {
  422. $f = "g:ia";
  423. }
  424. if ($custom != "") $f = $custom;
  425. return date($f, $timestamp);
  426. }
  427. /**
  428. * Render a "menu" block of menu items which are all rooted at the menu_root.
  429. * So if the menu root is tools, it might return items whose paths look like:
  430. * tools/fun
  431. * tools/here/there
  432. * So long as the menu type is "MENU_TYPE_NORMAL_ITEM" or "MENU_TYPE_DEFAULT_TAB". Other types will be ignored.
  433. *
  434. *
  435. * We want to
  436. */
  437. function fp_render_menu_block($title = "Tools", $menu_root = "tools", $bool_reset = FALSE) {
  438. $rtn = "";
  439. $is_empty = true;
  440. if ($title != "") {
  441. $rtn .= fp_render_section_title($title);
  442. }
  443. $menu_items = menu_get_items_beginning_with($menu_root);
  444. foreach ($menu_items as $item) {
  445. if ($item['path'] === $menu_root) continue; // don't need to duplicate the menu root link itself
  446. if ($item["type"] == MENU_TYPE_NORMAL_ITEM || $item['type'] == MENU_TYPE_DEFAULT_TAB) {
  447. $item = menu_get_item($item['path'], $bool_reset);
  448. $rtn .= fp_render_menu_item($item);
  449. $is_empty = false;
  450. }
  451. }
  452. if ($is_empty) {
  453. return "";
  454. }
  455. //pretty_print($menu_items);
  456. return $rtn;
  457. }
  458. /**
  459. * Output the contents of the $page variable to the screen.
  460. * $page is an array containing details about the page, as well as
  461. * its original menu item (router_item) definition.
  462. */
  463. function fp_display_page($page) {
  464. global $current_student_id, $screen, $user;
  465. $page_title = $page["title"];
  466. if (@$GLOBALS["fp_set_title"] != "") {
  467. $page_title = $GLOBALS["fp_set_title"];
  468. }
  469. if (!is_object($screen)) {
  470. $screen = new AdvisingScreen("",null,"not_advising");
  471. }
  472. $screen->page_title = $page_title;
  473. $screen->page_has_search = @$page["router_item"]["page_settings"]["page_has_search"];
  474. // Add some body classes to the page for this student.
  475. $student = $screen->student;
  476. if (!is_object($student)) {
  477. $student = new Student();
  478. $student->student_id = $current_student_id;
  479. $student->load_student_data();
  480. }
  481. if (is_object($student)) {
  482. fp_add_body_class("student-rank-$student->db_rank student-catalog-year-$student->catalog_year");
  483. }
  484. $screen->page_banner_is_link = @$page["router_item"]["page_settings"]["page_banner_is_link"];
  485. $screen->page_hide_report_error = @$page["router_item"]["page_settings"]["page_hide_report_error"];
  486. $screen->page_is_popup = @$page["router_item"]["page_settings"]["page_is_popup"];
  487. if (isset($page["router_item"]["page_settings"]["screen_mode"])) {
  488. $screen->screen_mode = $page["router_item"]["page_settings"]["screen_mode"];
  489. }
  490. if (isset($page["router_item"]["page_settings"]["bool_print"])) {
  491. $screen->bool_print = $page["router_item"]["page_settings"]["bool_print"];
  492. }
  493. if (@$_REQUEST["scroll_top"] != "") {
  494. $screen->page_scroll_top = $_REQUEST["scroll_top"];
  495. }
  496. // If there is a SESSION var for scroll_top, use that instead, then wipe it.
  497. if (@$_SESSION['scroll_top'] != "") {
  498. $screen->page_scroll_top = $_SESSION["scroll_top"];
  499. $_SESSION['scroll_top'] = "";
  500. unset($_SESSION['scroll_top']);
  501. }
  502. // Was this page a tab? And if so, are there any other tabs we need to display? //
  503. if (@$page["router_item"]["type"] == MENU_TYPE_TAB || @$page["router_item"]["type"] == MENU_TYPE_DEFAULT_TAB || @$page["router_item"]["tab_parent"] != "") {
  504. // We know we should have at least 1 tab for this page.
  505. $tab_array = fp_build_tab_array($page);
  506. $screen->page_tabs = fp_render_tab_array($tab_array);
  507. }
  508. // Should we override the page_tabs with what is in "fp_set_page_tabs" ?
  509. if (isset($GLOBALS["fp_set_page_tabs"]) && is_array($GLOBALS["fp_set_page_tabs"])) {
  510. //fpm($GLOBALS["fp_set_page_tabs"]);
  511. $screen->page_tabs = fp_render_tab_array($GLOBALS["fp_set_page_tabs"]);
  512. }
  513. // Build up the content //
  514. $content_top = "";
  515. $page_show_title = @$page["router_item"]["page_settings"]["page_show_title"];
  516. if (isset($GLOBALS["fp_set_show_title"])) {
  517. $page_show_title = $GLOBALS["fp_set_show_title"];
  518. }
  519. if ($page_show_title == FALSE) {
  520. $page_title = "";
  521. }
  522. $c = 0;
  523. // Are there any "menu_link"s for this? In order words, little links at the top of the page,
  524. // where breadcrumbs might appear.
  525. if (!$screen->bool_print && @is_array($page["router_item"]["page_settings"]["menu_links"])) {
  526. //$content_top .= "<ul class='top-menu-links'>";
  527. $crumbs = array();
  528. foreach ($page["router_item"]["page_settings"]["menu_links"] as $item) {
  529. $lclass = "";
  530. if ($c == 0) $lclass='first';
  531. $p = menu_convert_replacement_pattern(@$item["path"]);
  532. $q = menu_convert_replacement_pattern(@$item["query"]);
  533. $t = @$item["text"];
  534. $a = @$item["attributes"];
  535. if (!is_array($a)) $a = array();
  536. // Make sure the current user has access to view this link. Otherwise, do not even
  537. // bother showing it.
  538. $test_item = menu_get_item($p) ;
  539. if (!menu_check_user_access($test_item)) {
  540. continue;
  541. }
  542. //$content_top .= "<li class='$lclass'>" . l($t, $p, $q, $a) . "</li>";
  543. $crumbs[] = array('text' => $t, 'path' => $p, 'query' => $q, 'attributes' => $a);
  544. $c++;
  545. }
  546. //$content_top .= "</ul>";
  547. // If not already set!
  548. if (!isset($GLOBALS['fp_breadcrumbs'])) {
  549. fp_set_breadcrumbs($crumbs);
  550. }
  551. }
  552. // Any sub-tabs we need to render?
  553. if (@$page["router_item"]["type"] == MENU_TYPE_SUB_TAB) {
  554. $sub_tab_array = fp_build_sub_tab_array($page);
  555. $content_top .= fp_render_sub_tab_array($sub_tab_array);
  556. }
  557. // Should we override the page sub-tabs with what is in "fp_set_page_sub_tabs" ?
  558. if (isset($GLOBALS["fp_set_page_sub_tabs"]) && is_array($GLOBALS["fp_set_page_sub_tabs"])) {
  559. $content_top .= fp_render_sub_tab_array($GLOBALS["fp_set_page_sub_tabs"]);
  560. }
  561. // If the REQUEST specifically asks NOT to show waiting fp_messages, then clear them from the session.
  562. if (isset($_REQUEST['fp_messages']) && $_REQUEST['fp_messages'] == 'none') {
  563. unset($_SESSION['fp_messages']);
  564. }
  565. // If there are "messages" waiting, then let's add them to the top of content.
  566. if (isset($_SESSION["fp_messages"]) && is_array($_SESSION["fp_messages"]) && count($_SESSION["fp_messages"]) > 0) {
  567. $content_top .= "<div class='fp-messages'>";
  568. foreach ($_SESSION["fp_messages"] as $key => $tmsg) {
  569. $type = $tmsg["type"];
  570. $message = $tmsg["msg"];
  571. $content_top .= "<div class='fp-message fp-message-$type'>$message</div>";
  572. }
  573. $content_top .= "</div>";
  574. unset($_SESSION["fp_messages"]);
  575. }
  576. // content_top gets the Currently Advising box.
  577. if (@$page["router_item"]["page_settings"]["display_currently_advising"] == TRUE) {
  578. // To do this, we need to make sure the $screen->student object is loaded.
  579. $screen->page_display_currently_advising = TRUE;
  580. if (!$screen->student) {
  581. $screen->student = new Student($current_student_id);
  582. }
  583. }
  584. if (isset($page["router_item"]["page_settings"]["display_currently_advising"])) {
  585. if ($page["router_item"]["page_settings"]["display_currently_advising"] === FALSE) {
  586. // Meaning, we are explicitly saying do NOT show the currently advising box!
  587. $screen->page_display_currently_advising = FALSE;
  588. }
  589. }
  590. $screen->page_content = $content_top .= $page["content"];
  591. if ($user->id > 0) {
  592. // meaning, they are logged in.
  593. $screen->page_content .= fp_render_mobile_hamburger_menu(); // add to the bottom
  594. }
  595. // Add in the body classes
  596. $screen->page_body_classes .= " " . @$GLOBALS["fp_add_body_classes"];
  597. // Add in our URL (after we sanitize it appropriately)
  598. $class = @$_REQUEST['q'];
  599. $class = str_replace("'", '', $class);
  600. $class = str_replace('"', '', $class);
  601. $class = str_replace('(', '', $class);
  602. $class = str_replace(')', '', $class);
  603. $class = str_replace(';', '', $class);
  604. $class = str_replace('.', '', $class);
  605. $class = str_replace('<', '', $class);
  606. $class = str_replace('>', '', $class);
  607. $class = str_replace('/', '-', $class);
  608. $class = str_replace('\\', '', $class);
  609. $class = str_replace('#', '', $class);
  610. $class = str_replace('&', '', $class);
  611. $screen->page_body_classes .= " page--" . str_replace("/", "-", $class);
  612. $screen->output_to_browser();
  613. } // fp_display_page
  614. /**
  615. * This function accepts a "profile items" array by reference, which is presumed to have a "left_side" and a "right_side" already
  616. * defined. We can "push" items onto it, and the item will automatically go to the side with the fewest "items" so as to keep
  617. * it "balanced."
  618. */
  619. function fp_push_and_balance_profile_items(&$profile_items, array $item) {
  620. // We do the -1 to the right_side, because it is already unbalanced by 1 as a default.
  621. $dec = 1;
  622. if (count($profile_items['right_side']) == 0) $dec = 0;
  623. if (count($profile_items['left_side']) <= count($profile_items['right_side']) - $dec) {
  624. $profile_items['left_side'] += $item;
  625. }
  626. else {
  627. $profile_items['right_side'] += $item;
  628. }
  629. // No need to return, since passed by reference.
  630. } // fp_push_and_balance_profile_items
  631. /**
  632. * Returns the HTML for the "profile" header html for a student
  633. */
  634. function fp_render_student_profile_header($bool_mini = TRUE, $extra_profile_items = array()) {
  635. global $current_student_id, $screen, $user, $student;
  636. $csid = $current_student_id;
  637. $school_id = db_get_school_id_for_student_id($current_student_id);
  638. $degree_plan = NULL;
  639. $rtn = "";
  640. if (!isset($extra_profile_items['left_side'])) $extra_profile_items['left_side'] = array();
  641. if (!isset($extra_profile_items['right_side'])) $extra_profile_items['right_side'] = array();
  642. // Call a hook to possibly add more items to our profile items.
  643. invoke_hook("alter_student_profile_items", array($bool_mini, &$extra_profile_items));
  644. if (is_object($screen) && is_object($screen->degree_plan)) {
  645. $degree_plan = $screen->degree_plan;
  646. }
  647. if (!isset($student) || $student == NULL || !is_object($student)) {
  648. $student = new Student($current_student_id);
  649. }
  650. if ($degree_plan == NULL) {
  651. // Degree plan is still null. This probably means we are NOT on an advising screen, so, let's
  652. // use a FlightPath object to init our degree plan, which might actually be a combination of degrees.
  653. // First, we can cheat by seeing if we have anything cached for this student the last time their degree plan
  654. // was loaded. Using this,
  655. // its much faster & memory-friendly than trying to re-init a whole new FlightPath object and DegreePlan object(s).
  656. $bool_got_from_simple_cache = FALSE;
  657. // TODO: Check for _what_if if we are in what if mode?
  658. if (isset($_SESSION["fp_simple_degree_plan_cache_for_student"])) {
  659. if ($_SESSION["fp_simple_degree_plan_cache_for_student"]["cwid"] == $csid) {
  660. // Yes, it's for this student. Load her up.
  661. $degree_plan = new DegreePlan();
  662. $degree_plan->degree_id = $_SESSION["fp_simple_degree_plan_cache_for_student"]["degree_id"];
  663. $degree_plan->combined_degree_ids_array = $_SESSION["fp_simple_degree_plan_cache_for_student"]["combined_degree_ids_array"];
  664. $degree_plan->is_combined_dynamic_degree_plan = $_SESSION["fp_simple_degree_plan_cache_for_student"]["is_combined_dynamic_degree_plan"];
  665. $bool_got_from_simple_cache = TRUE;
  666. }
  667. }
  668. if (!$bool_got_from_simple_cache) {
  669. // didn't get it from the simple cache, so load it all fresh.
  670. $fp = new FlightPath($student);
  671. $fp->init(TRUE);
  672. $degree_plan = $fp->degree_plan;
  673. }
  674. }
  675. $cat_year = $student->catalog_year . "-" . ($student->catalog_year + 1);
  676. $rank = $student->rank;
  677. // Should we display a catalog year warning? This is
  678. // something that can be part of a settings table.
  679. if ($student->catalog_year < intval(variable_get_for_school("earliest_catalog_year", 2006, $school_id))) {
  680. $alert_msg = "";
  681. $alert_msg .= "<b>" . t("Important Notice:") . "</b> " . t("FlightPath cannot display degree plans from catalogs earlier than %earliest.
  682. The student&#039;s catalog year is %current, which means that the degree plan displayed may not accurately
  683. represent this student&#039;s degree requirements.", array("%earliest" => intval(variable_get_for_school("earliest_catalog_year", 2006, $school_id)) . "-" . (intval(variable_get_for_school("earliest_catalog_year", 2006, $school_id)) + 1), "%current" => $cat_year));
  684. $cat_year = "<span class='catalog-year-alert-early'>$cat_year<a href='javascript:fp_alert(\"$alert_msg\");' title='" . t("Important Notice") . "'><i class='fa fa-exclamation-triangle'></i></a></span>";
  685. $bool_catalog_warning = true;
  686. }
  687. if (variable_get_for_school("current_catalog_year",'', $school_id) > intval(variable_get_for_school("earliest_catalog_year", 2006, $school_id))) {
  688. // Is the student's catalog set beyond the range that
  689. // FP has data for? If so, show a warning.
  690. if ($student->catalog_year > variable_get_for_school("current_catalog_year",'', $school_id))
  691. {
  692. $alert_msg = t("This student&#039;s catalog year is @cat_year,
  693. and specific curriculum requirements are not yet
  694. available for this year.
  695. To advise this student according to @new_cat
  696. requirements, select the student&#039;s major using What If.", array("@cat_year" => $cat_year, "@new_cat" => variable_get_for_school("current_catalog_year",'',$school_id) . "-" . (variable_get_for_school("current_catalog_year",'',$school_id) + 1)));
  697. $cat_year = "<span class='catalog-year-alert-too-far'>$cat_year<a href='javascript:fp_alert(\"$alert_msg\");' title='" . t("Important Notice") . "'><i class='fa fa-exclamation-triangle'></i></a></span>";
  698. $bool_future_catalog_warning = true;
  699. }
  700. }
  701. $db = get_global_database_handler();
  702. ///////////////////////////
  703. $degree_title_div = "";
  704. $s = ""; // plural degrees?
  705. $bool_show_track_selection_link = FALSE;
  706. // We are trying to figure out what to display for the Degree field. If there is only ONE degree plan
  707. // to worry about, then we will display it.
  708. if ($degree_plan == null || $degree_plan->is_combined_dynamic_degree_plan != TRUE) {
  709. // This is an ordinary degree plan.
  710. $use_degree_plan = $degree_plan;
  711. $degree_title = "";
  712. if ($degree_plan != NULL) {
  713. $degree_title = $degree_plan->get_title2(TRUE);
  714. }
  715. /**
  716. * This degree is in fact a track.
  717. */
  718. if (strstr($degree_plan->major_code, "_")) {
  719. $degree_title = $degree_plan->get_title2(TRUE, TRUE);
  720. if ($degree_plan->db_allow_dynamic == 0) {
  721. // This degree is NON-dynamic. Meaning, if we change tracks, we should do it from the perspective
  722. // of the original major code, and how FP 4.x did things.
  723. $temp = explode("_", $degree_plan->major_code);
  724. $m = trim($temp[0]);
  725. // Remove trailing | if its there.
  726. $m = rtrim($m, "|");
  727. $use_degree_plan = $db->get_degree_plan($m, $degree_plan->catalog_year, TRUE); // the original degree plan!
  728. }
  729. }
  730. if ($screen->screen_mode == "detailed") {
  731. $degree_title .= " ($degree_plan->major_code)";
  732. }
  733. if ($use_degree_plan != null && $use_degree_plan->get_available_tracks()) {
  734. $bool_show_track_selection_link = TRUE;
  735. }
  736. $degree_title_div = "<div class='degree-title'>$degree_title</div>";
  737. //array_push($display_array, t("Degree:") . " ~~ " . $degree_title);
  738. }
  739. else {
  740. // This degree plan is made from combining several other degrees. let's trot them out and display them as well.
  741. $t_degree_plan_titles = "";
  742. $dc = 0;
  743. foreach ($degree_plan->combined_degree_ids_array as $t_degree_id) {
  744. $t_degree_plan = new DegreePlan();
  745. $t_degree_plan->degree_id = $t_degree_id;
  746. $t_degree_plan->load_descriptive_data();
  747. if ($t_degree_plan->get_available_tracks()) {
  748. $bool_show_track_selection_link = TRUE;
  749. }
  750. // Add it to our box...
  751. // If more than one major/minor, etc, combine them into one div
  752. $t_title = $t_degree_plan->get_title2(TRUE);
  753. $t_class = $t_degree_plan->degree_class;
  754. $t_class_details = fp_get_degree_classification_details($t_class);
  755. // If this is actually a track, let's get the track's title instead.
  756. if ($x = $t_degree_plan->get_track_title(TRUE)) {
  757. $t_title = $x;
  758. }
  759. if ($t_class_details["level_num"] == 3) {
  760. $t_title = "<span class='level-3-raquo'>&raquo;</span>" . $t_title;
  761. }
  762. $machine_major_code = fp_get_machine_readable($t_degree_plan->major_code);
  763. if ($t_degree_plan->track_code != "") {
  764. $machine_major_code .= "-" . fp_get_machine_readable($t_degree_plan->track_code);
  765. }
  766. $t_degree_plan_titles .= "<span class='multi-degree-title multi-degree-class-" . $t_class . "
  767. multi-degree-class-level-" . $t_class_details["level_num"] . "
  768. multi-degree-code-$machine_major_code multi-degree-num-$dc'>
  769. " . $t_title . "</span><span class='multi-degree-comma'>,</span>";
  770. $dc++;
  771. $s = "s";
  772. }
  773. // Trim the last comma off the end of t_degree_plan_titles
  774. $t_degree_plan_titles = rtrim($t_degree_plan_titles, "<span class='multi-degree-comma'>,</span>");
  775. $degree_title_div = $t_degree_plan_titles;
  776. }
  777. // Now, do we want to add an option to select a track to the degree_title_div?
  778. if ($bool_show_track_selection_link) {
  779. // Are we in what_if mode?
  780. $advising_what_if = @$GLOBALS["fp_advising"]["advising_what_if"];
  781. // We want to add a link to the popup to let the user select other degree tracks.
  782. $op_link = "<a class='degree-op-link-change-degree-options' href='javascript: popupSmallIframeDialog(\"" . fp_url("advise/popup-change-track", "advising_what_if=$advising_what_if") . "\",\"" . t("Select a Degree Option") . "\");'
  783. title='" . t("Change degree options") . "'><i class='fa fa-cog'></i></a>";
  784. if (!$screen || $screen->screen_mode == "not_advising" || $screen->screen_mode == "detailed") {
  785. $op_link = "";
  786. }
  787. if (!user_has_permission("can_advise_students")) {
  788. if (@$GLOBALS["fp_advising"]["advising_what_if"] != "yes")
  789. {
  790. // In other words, we do not have permission to advise,
  791. // and we are not in whatIf, so take out the link.
  792. $op_link = "";
  793. }
  794. }
  795. if ($op_link) {
  796. $degree_title_div .= "<span class='degree-op-link'>$op_link</span>";
  797. }
  798. }
  799. $right_side_top = "<h2>&nbsp; &nbsp; &nbsp; &nbsp;</h2>"; // need spacers on purpose
  800. $whatifclass = "";
  801. if (@$GLOBALS["fp_advising"]["advising_what_if"] == "yes") {
  802. $whatifclass = "student-mini-profile-what-if-mode";
  803. // Set the cat year to whatever our What If cat year was, current if we can't find it.
  804. $what_if_catalog_year = @$GLOBALS["fp_advising"]["what_if_catalog_year"];
  805. if ($what_if_catalog_year != 0 && $what_if_catalog_year != "") {
  806. $student->catalog_year = $what_if_catalog_year;
  807. }
  808. else {
  809. // Only change to current if that is how our settings are set...
  810. if (variable_get_for_school("what_if_catalog_year_mode", "current", $school_id) == "current") {
  811. $student->catalog_year = variable_get_for_school("current_catalog_year",'',$school_id);
  812. }
  813. }
  814. //$what_if_select = "<span class='what-if-change-settings'>" . l("<i class='fa fa-cog'></i> " . t("Change Settings"), "what-if", "advising_what_if=yes&what_if_major_code=none&what_if_track_code=none&what_if_track_degree_ids=none&current_student_id=$current_student_id") . "</span>";
  815. //$right_side_top = "<h2 class='what-if-notice'>" . t("What If Mode") . "</h2>";
  816. }
  817. // Figure out what the user's image is based on their account.
  818. $image_url = "";
  819. $student_account_user_id = db_get_user_id_from_cwid($student->student_id, 'student');
  820. if ($student_account_user_id) {
  821. $student_account = fp_load_user($student_account_user_id);
  822. if ($student_account) {
  823. $image_url = @$student_account->settings['image_url'];
  824. }
  825. }
  826. $rtn .= "<div class='student-mini-profile $whatifclass'>
  827. ";
  828. if ($image_url) {
  829. $rtn .= "<div class='header-profile-image'>
  830. <img src='$image_url' class='student-profile-image' />
  831. </div> <!-- profile-image -->
  832. ";
  833. }
  834. $school_html = $school_name = "";
  835. if (module_enabled("schools")) {
  836. // If we have schools module enabled, let's find out what school this student belongs to and display it
  837. $defs = schools_get_school_definitions(TRUE);
  838. $temp = @$defs[$student->school_id];
  839. if ($temp) {
  840. $school_html .= "
  841. <div class='profile-detail-line profile-inline-line profile-detail-line-school profile-line-detail-school-$student->school_id'>
  842. <label>" . t("School:") . "</label> <span class='profile-line-content'>" . $temp['name'] . "</span>
  843. </div>
  844. ";
  845. }
  846. }
  847. $rtn .= " <div class='profile-top-details-wrapper profile-top-wrapper-left-side'>
  848. <div class='profile-detail-line profile-detail-line-student-name-cwid'>
  849. <h2>$student->name &nbsp; &nbsp; ($student->student_id)</h2>
  850. </div>
  851. $school_html
  852. <div class='profile-detail-line profile-inline-line profile-detail-line-degree'>
  853. <label>" . t("Degree$s:") . "</label> <span class='profile-line-content'>$degree_title_div</span>
  854. </div>
  855. <div class='profile-detail-line profile-inline-line profile-detail-line-cat-year'>
  856. <label>" . t("Catalog Year:") . "</label> <span class='profile-line-content'>$cat_year</span>
  857. </div>
  858. ";
  859. if (isset($extra_profile_items['left_side'])) {
  860. foreach ($extra_profile_items['left_side'] as $details) {
  861. $label = @$details['label'];
  862. $content = @$details['content'];
  863. $extra_class = @$details['extra_class'];
  864. $mobile_content = @$details['mobile_content']; // displayed in an initially-hidden span, if provided.
  865. if ($mobile_content) {
  866. $mobile_content = "<span style='display:none;' class='mobile-profile-line-content'>$mobile_content</span>";
  867. $extra_class .= " has-mobile-content";
  868. }
  869. $rtn .= "<div class='profile-detail-line profile-inline-line $extra_class'>
  870. <label>$label</label> <span class='profile-line-content'>$content</span>$mobile_content
  871. </div>";
  872. }
  873. }
  874. $rtn .= "</div>
  875. <div class='profile-top-details-wrapper profile-top-wrapper-right-side'>
  876. <div class='profile-detail-line profile-detail-line-empty'>
  877. $right_side_top <!-- need something here so it lines up correctly -->
  878. </div>
  879. <div class='profile-detail-line profile-inline-line profile-detail-line-rank'>
  880. <label>" . t("Classification:") . "</label> <span class='profile-line-content'>$rank</span>
  881. </div>
  882. <div class='profile-detail-line profile-inline-line profile-detail-line-cumu'>
  883. <label>" . t("Cumulative:") . "</label> <span class='profile-line-content'>{$student->cumulative_hours} " . t("hrs") . " / " . fp_truncate_decimals($student->gpa, 3) . " " . t("GPA") . "</span>
  884. </div>
  885. ";
  886. if (isset($extra_profile_items['right_side'])) {
  887. foreach ($extra_profile_items['right_side'] as $details) {
  888. $label = @$details['label'];
  889. $content = @$details['content'];
  890. $extra_class = @$details['extra_class'];
  891. $mobile_content = @$details['mobile_content']; // displayed in an initially-hidden span, if provided.
  892. if ($mobile_content) {
  893. $mobile_content = "<span style='display:none;' class='mobile-profile-line-content'>$mobile_content</span>";
  894. $extra_class .= " has-mobile-content";
  895. }
  896. $rtn .= "<div class='profile-detail-line profile-inline-line $extra_class'>
  897. <label>$label</label> <span class='profile-line-content'>$content</span>$mobile_content
  898. </div>";
  899. }
  900. }
  901. $rtn .= "
  902. </div>
  903. <div class='clear'></div>
  904. </div>
  905. ";
  906. return $rtn;
  907. }
  908. /**
  909. * Return the HTML for breadcrumbs for the current page we are on.
  910. * Will skip any breadcrumbs we do not have permission to access.
  911. */
  912. function fp_render_breadcrumbs() {
  913. $rtn = "";
  914. $c = 0;
  915. if (isset($GLOBALS['fp_breadcrumbs']) && is_array($GLOBALS['fp_breadcrumbs'])) {
  916. $crumbs = $GLOBALS['fp_breadcrumbs'];
  917. $rtn .= "<div id='breadcrumb-inner-wrapper'>
  918. <ul class='breadcrumbs'>";
  919. foreach ($crumbs as $crumb) {
  920. $z_index = 20 - $c;
  921. $text = @$crumb['text'];
  922. $path = @$crumb['path'];
  923. $query = @$crumb['query'];
  924. $attributes = @$crumb['attributes'];
  925. // Do we have permission for this menu item? If not, do not render this breadcrumb.
  926. if ($path != "<front>") {
  927. $item = menu_get_item($path);
  928. if (!menu_check_user_access($item)) {
  929. continue;
  930. }
  931. }
  932. if (!$attributes || !is_array($attributes)) {
  933. $attributes = array();
  934. $attributes['style'] = '';
  935. }
  936. $attributes['style'] .= " z-index: $z_index;";
  937. $link = l($text, $path, $query, $attributes);
  938. $extra_class = "";
  939. if ($c == 0) $extra_class .= "first";
  940. if ($c == count($crumbs) -1) $extra_class .= " last";
  941. $rtn .= "<li class='crumbs $extra_class' style='z-index: $z_index;' >
  942. $link
  943. </li>";
  944. $c++;
  945. }
  946. $rtn .= "</ul>
  947. </div>";
  948. }
  949. return $rtn;
  950. } // fp_render_breadcrumbs
  951. /**
  952. * Returns the HTML for the left sidebar content.
  953. */
  954. function fp_render_sidebar_left_content($bool_for_hamburger_menu = FALSE) {
  955. global $user;
  956. $html = "";
  957. // Our links.... (we will check permissions later based on the path)
  958. $links = array();
  959. if ($_SESSION["fp_logged_in"] != TRUE) {
  960. // user is not logged in. The top-most link should be to log in.
  961. $links[] = array(
  962. 'path' => 'login',
  963. 'icon' => 'fa-sign-in',
  964. 'desc' => t('Login'),
  965. 'class' => 'login',
  966. 'weight' => 0,
  967. );
  968. }
  969. else {
  970. // the user is logged in normally, the top-most link should be the dashboard
  971. $links[] = array(
  972. 'path' => '<front>',
  973. 'icon' => 'fa-home',
  974. 'desc' => t('Dashboard'),
  975. 'class' => 'home',
  976. 'weight' => 0,
  977. );
  978. }
  979. if ($user->is_student) {
  980. $links[] = array(
  981. 'path' => 'student-profile',
  982. 'icon' => 'fa-graduation-cap',
  983. 'desc' => t('My Profile'),
  984. 'class' => 'my-profile',
  985. 'weight' => 10,
  986. );
  987. }
  988. $links[] = array(
  989. 'path' => 'calendar',
  990. 'icon' => 'fa-calendar',
  991. 'desc' => t('Appointments'),
  992. 'class' => 'appointments',
  993. 'weight' => 20,
  994. );
  995. $links[] = array(
  996. 'path' => 'student-search',
  997. 'icon' => 'fa-users',
  998. 'desc' => t('Students'),
  999. 'class' => 'students',
  1000. 'weight' => 30,
  1001. );
  1002. $links[] = array(
  1003. 'path' => 'tools/course-search',
  1004. 'icon' => 'fa-book',
  1005. 'desc' => t('Courses'),
  1006. 'class' => 'courses',
  1007. 'weight' => 40,
  1008. );
  1009. $links[] = array(
  1010. 'path' => 'tools/blank-degrees',
  1011. 'icon' => 'fa-university',
  1012. 'desc' => t('Degrees'),
  1013. 'class' => 'degrees',
  1014. 'weight' => 50,
  1015. );
  1016. $links[] = array(
  1017. 'path' => 'stats',
  1018. 'icon' => 'fa-bar-chart',
  1019. 'desc' => t('Analytics'),
  1020. 'class' => 'analytics',
  1021. 'weight' => 60,
  1022. );
  1023. $links[] = array(
  1024. 'path' => 'admin-tools',
  1025. 'icon' => 'fa-bolt',
  1026. 'desc' => t('Admin Tools'),
  1027. 'class' => 'admin-tools',
  1028. 'weight' => 70,
  1029. );
  1030. if ($bool_for_hamburger_menu) {
  1031. // Include a handy log-out on the mobile hamburger menu
  1032. $links[] = array(
  1033. 'path' => 'logout',
  1034. 'icon' => 'fa-sign-out',
  1035. 'desc' => t('Log Out'),
  1036. 'class' => 'logout',
  1037. 'weight' => 999,
  1038. );
  1039. }
  1040. // TODO: hook to allow other modules to add to this list or modify it.
  1041. // Sort links by weight
  1042. $temp = array();
  1043. foreach ($links as $c => $details) {
  1044. $weight = @floatval($details['weight']);
  1045. $temp[] = "$weight ~ $c";
  1046. }
  1047. sort($temp);
  1048. $new_links = array();
  1049. foreach ($temp as $line) {
  1050. $x = explode("~", $line);
  1051. $i = intval($x[1]);
  1052. $new_links[] = $links[$i];
  1053. }
  1054. $links = $new_links;
  1055. // Display
  1056. $html .= "<ul class='sidebar-left-nav'>";
  1057. foreach ($links as $c => $link) {
  1058. $path = $link['path'];
  1059. $icon = $link['icon'];
  1060. $desc = $link['desc'];
  1061. $query = @$link['query'];
  1062. $class = @$link['class'];
  1063. if ($c == 0) $class .= " first";
  1064. if ($c == count($links) - 1) $class .= " last";
  1065. // Do we have permission for this menu item?
  1066. if ($path != "<front>") {
  1067. $item = menu_get_item($path);
  1068. if (!menu_check_user_access($item)) {
  1069. continue;
  1070. }
  1071. }
  1072. // If we are here, we have access!
  1073. $html .= "<a href='" . fp_url($path, $query) . "'>
  1074. <li class='$class'>
  1075. <i class='fa $icon'></i>
  1076. <div class='desc'>$desc</div>
  1077. </li>
  1078. </a>";
  1079. } // foreach
  1080. $html .= "</ul>";
  1081. return $html;
  1082. } // fp_render_sidebar_left_content
  1083. /**
  1084. * This will create the HTML content for the "mobile hamburger" menu, which appears when we press
  1085. * the 3 lines icon or "hamburger" icon on a mobile device.
  1086. */
  1087. function fp_render_mobile_hamburger_menu() {
  1088. $rtn = "";
  1089. $rtn .= "<div id='mobile-hamburger-menu' style='display:none;'>
  1090. <div class='mobile-top-nav'>";
  1091. $rtn .= fp_render_top_nav_content(TRUE);
  1092. $rtn .= " </div>
  1093. <div class='clear'></div>
  1094. <div class='mobile-sidebar-content'>";
  1095. $rtn .= fp_render_sidebar_left_content(TRUE);
  1096. $rtn .= " </div>
  1097. </div>";
  1098. return $rtn;
  1099. }
  1100. /**
  1101. * Returns the HTML for the top navigation content of the screen itself.
  1102. *
  1103. * If the bool_for_hamburger_menu == true, then we are trying to render this for
  1104. * our mobile hamburger menu, so we will alter a little bit.
  1105. *
  1106. */
  1107. function fp_render_top_nav_content($bool_for_hamburger_menu = FALSE) {
  1108. global $user;
  1109. $html = "";
  1110. $name = "";
  1111. if ($user->is_faculty) {
  1112. $name = fp_get_faculty_name($user->cwid);
  1113. }
  1114. else {
  1115. $name = fp_get_student_name($user->cwid);
  1116. }
  1117. $badge = "";
  1118. // If user has new alerts to view, we should show a "badge" on the icon over the alerts icon
  1119. $alert_count_by_type = fp_get_alert_count_by_type();
  1120. if ($alert_count_by_type && is_array($alert_count_by_type) && count($alert_count_by_type) > 0) {
  1121. $unread_total = 0;
  1122. foreach ($alert_count_by_type as $module => $alert_types) {
  1123. if ($alert_types && is_array($alert_types)) {
  1124. foreach ($alert_types as $k => $details) {
  1125. $ur = intval( $details['unread']);
  1126. if ($ur < 0) $ur = 0; // bug that can happen after deletions, it can be in negative numbers.
  1127. $unread_total += $ur;
  1128. }
  1129. }
  1130. }
  1131. if ($unread_total > 0) {
  1132. $badge = "<span class='tub-alert-count'><i class='fa fa-circle'></i></span>";
  1133. }
  1134. }
  1135. if (!$bool_for_hamburger_menu) {
  1136. $html .= "<ul class='top-nav-ul'>";
  1137. // If we have a student selected, then we will display a link to go back to that student.
  1138. if ($user->is_faculty) {
  1139. if (@trim($_SESSION["last_student_selected"]) != '') {
  1140. $csid = trim($_SESSION["last_student_selected"]);
  1141. $sname = trim(fp_get_student_name($csid));
  1142. if ($sname) {
  1143. $sname = htmlentities($sname);
  1144. $cur_stu_link = l("<i class='fa fa-id-card-o'></i>", "student-select","current_student_id=$csid",array("title" => t("Return to @sname", array("@sname" => $sname))));
  1145. $html .= "<li class='current-student-link'>$cur_stu_link</li>";
  1146. }
  1147. }
  1148. }
  1149. if (user_has_permission('view_any_advising_session')) {
  1150. $html .= "<li class='student-search'>" . student_search_render_small_search() . "</li>";
  1151. }
  1152. if (user_has_permission('view_advisee_alerts')) {
  1153. $html .= "<li class='alerts'><span class='tub-icon-element-alert'><a href='" . fp_url('alerts') . "'><i class='fa fa-bell'></i>$badge</a></span></li>";
  1154. }
  1155. $html .= "<li class='user-options last'>";
  1156. $user_menu_links = array(
  1157. 0 => l(t('My Settings'), 'user-settings'),
  1158. 1 => l(t('Log Out'), 'logout'),
  1159. );
  1160. // Call a hook to allow others to modify this.
  1161. invoke_hook('user_menu_links_alter', array(&$user_menu_links));
  1162. $html .= "
  1163. <div class='tub-element tub-float-right-a tub-last-element tub-user-menu tub-icon-element dropdown'>
  1164. <div class='tub-element-wrapper'>
  1165. <a href='javascript:fpToggleUserMenu();' class='tub-link dropdown-trigger'>
  1166. <i class='fa fa-user'></i><span class='tub-caret-down'><i class='fa fa-caret-down'></i></span>
  1167. </a>
  1168. </div>
  1169. <div id='tub-user-pulldown' style='display:none;' >
  1170. $name
  1171. <ul class='user-pulldown'>
  1172. ";
  1173. foreach ($user_menu_links as $link) {
  1174. $html .= "<li>" . $link . "</li>";
  1175. }
  1176. $html .= "
  1177. </ul>
  1178. </div>
  1179. </div>
  1180. </li>
  1181. </ul>
  1182. ";
  1183. // We are also going to have a hidden "hamburger" icon, which gets displayed
  1184. // when we shrink to mobile. It will be invisible by default.
  1185. $html .= "<div class='mobile-hamburger-icon' style='display: none;'>
  1186. <a href='javascript:fpToggleHamburgerMenu();'><i class='fa fa-bars'></i></a>
  1187. </div>";
  1188. }
  1189. else {
  1190. // This IS for our *** hamburger menu **** !
  1191. $cog_class = "cog-only";
  1192. $html .= "<ul class='top-nav-ul'>";
  1193. if (user_has_permission('view_advisee_alerts')) {
  1194. $html .= "<li class='alerts first'><span class='tub-icon-element-alert'><a href='" . fp_url('alerts') . "'><i class='fa fa-bell'></i>$badge</a></span></li>";
  1195. $cog_class = "last";
  1196. }
  1197. $html .= "
  1198. <li class='user-options last $cog_class'>
  1199. <a href='" . fp_url('user-settings') . "'><i class='fa fa-cog'></i></a>
  1200. </li>
  1201. </ul>
  1202. ";
  1203. }
  1204. return $html;
  1205. } // fp_render_top_nav_content
  1206. /**
  1207. * Sets whether the title should be shown on the page or not.
  1208. */
  1209. function fp_show_title($bool_show = TRUE) {
  1210. $GLOBALS["fp_set_show_title"] = $bool_show;
  1211. }
  1212. /**
  1213. * This function will return the HTML to contruct a collapsible fieldset,
  1214. * complete with javascript and style tags.
  1215. *
  1216. * @param String $content
  1217. * @param String $legend
  1218. * @param bool $bool_start_closed
  1219. * @return String
  1220. */
  1221. function fp_render_c_fieldset($content, $legend = "Click to expand/collapse", $bool_start_closed = false, $extra_class = "")
  1222. {
  1223. // Create a random ID for this fieldset, js, and styles.
  1224. $id = md5(rand(9,99999) . time());
  1225. $start_js_val = 1;
  1226. $fsstate = "open";
  1227. $content_style = "";
  1228. if ($bool_start_closed) {
  1229. $start_js_val = 0;
  1230. $fsstate = "closed";
  1231. $content_style = "display: none;";
  1232. }
  1233. $js = "<script type='text/javascript'>
  1234. var fieldset_state_$id = $start_js_val;
  1235. function toggle_fieldset_$id() {
  1236. var content = document.getElementById('content_$id');
  1237. var fs = document.getElementById('fs_$id');
  1238. if (fieldset_state_$id == 1) {
  1239. // Already open. Let's close it.
  1240. fieldset_state_$id = 0;
  1241. \$(content).slideUp('medium');
  1242. fs.className = 'c-fieldset-closed-$id c-fieldset-closed c-fieldset';
  1243. }
  1244. else {
  1245. // Was closed. let's open it.
  1246. fieldset_state_$id = 1;
  1247. \$(content).slideDown('medium');
  1248. fs.className = 'c-fieldset-open-$id c-fieldset-open c-fieldset';
  1249. }
  1250. }
  1251. </script>";
  1252. $rtn = "
  1253. <fieldset class='c-fieldset-$fsstate-$id c-fieldset-$fsstate c-fieldset $extra_class' id='fs_$id'>
  1254. <legend><a href='javascript: toggle_fieldset_$id();' class='nounderline'>$legend</a></legend>
  1255. <div id='content_$id' class='c-fieldset-content' style='$content_style'>
  1256. $content
  1257. </div>
  1258. </fieldset>
  1259. $js
  1260. <style>
  1261. fieldset.c-fieldset-open-$id {
  1262. border: 1px solid;
  1263. }
  1264. fieldset.c-fieldset-closed-$id {
  1265. border: 1px solid;
  1266. border-bottom-width: 0;
  1267. border-left-width: 0;
  1268. border-right-width: 0;
  1269. }
  1270. legend a {
  1271. text-decoration: none;
  1272. }
  1273. </style>
  1274. ";
  1275. return $rtn;
  1276. }
  1277. /**
  1278. * Create a "sub-tab" array, which looks like a standard tab_array,
  1279. * but it contains only this page's sub-tab siblings.
  1280. */
  1281. function fp_build_sub_tab_array($page) {
  1282. global $current_student_id;
  1283. $tab_array = array();
  1284. $tab_family = $page["router_item"]["tab_family"];
  1285. $active_tab_path = $page["path"];
  1286. $items = menu_get_items_in_tab_family($tab_family);
  1287. foreach ($items as $item) {
  1288. // Does the user have access to this subtab?
  1289. if (!menu_check_user_access($item)) {
  1290. continue;
  1291. }
  1292. $title = $item["title"];
  1293. $path = $item["path"];
  1294. $active = FALSE;
  1295. $on_click = @$page["page_settings"]["tab_on_click"];
  1296. if ($on_click == "") {
  1297. // Just a simple link to the path
  1298. // Add the current_student_id to the query!
  1299. $query = "current_student_id=$current_student_id";
  1300. $turl = fp_url($path, $query, TRUE);
  1301. $on_click = "window.location=\"" . $turl . "\"";
  1302. }
  1303. if ($path == $active_tab_path) {
  1304. // This is the current page we are on.
  1305. $active = TRUE;
  1306. $title = $page["title"];
  1307. $on_click = "";
  1308. }
  1309. $tab_array[] = array(
  1310. "title" => $item["title"],
  1311. "active" => $active,
  1312. "on_click" => $on_click,
  1313. );
  1314. }
  1315. return $tab_array;
  1316. }
  1317. /**
  1318. * Looks at the current page array and returns a valid $tab_array
  1319. * Meant for the top of the screen.
  1320. */
  1321. function fp_build_tab_array($page) {
  1322. global $current_student_id;
  1323. $tab_array = array();
  1324. $tab_family = $page["router_item"]["tab_family"];
  1325. $active_tab_path = $page["path"];
  1326. if ($page["router_item"]["tab_parent"] != "") {
  1327. // We want to know the PARENT's tab_family, so we can display the correct tabs at the top of the page.
  1328. $tab_parent = $page["router_item"]["tab_parent"];
  1329. $item = menu_get_item($tab_parent);
  1330. $tab_family = $item["tab_family"];
  1331. $active_tab_path = $item["path"];
  1332. }
  1333. // look for other possible tabs, based on the "tab_family" value
  1334. // Also check to make sure the user has access to the tab.
  1335. $items = menu_get_items_in_tab_family($tab_family);
  1336. foreach ($items as $item) {
  1337. // Does the user have access to this tab?
  1338. if (!menu_check_user_access($item)) {
  1339. continue;
  1340. }
  1341. $title = $tab_title = $item["title"];
  1342. $path = $item["path"];
  1343. if (isset($item["page_settings"]["tab_title"])) {
  1344. $tab_title = $item["page_settings"]["tab_title"];
  1345. }
  1346. if (strstr($path, "%")) {
  1347. // it contains at least one wildcard. So, let's replace the wildcard with
  1348. // the coresponding value from arg(). Ex: content/%/edit (when we are on content/55/view) would == content/55/edit.
  1349. $new_path = "";
  1350. $pieces = explode("/", $path);
  1351. foreach ($pieces as $c => $piece) {
  1352. if ($piece != "%") {
  1353. $new_path .= $piece . "/";
  1354. }
  1355. else {
  1356. // This WAS a wildcard. Replace with arg() value.
  1357. $a = @arg($c);
  1358. $new_path .= $a . "/";
  1359. }
  1360. }
  1361. $new_path = rtrim($new_path, "/"); // get rid of trailing slash.
  1362. $path = $new_path;
  1363. }
  1364. $active = FALSE;
  1365. $on_click = @$page["page_settings"]["tab_on_click"];
  1366. $href = "";
  1367. if ($on_click == "") {
  1368. // Just a simple link to the path
  1369. // Include the current_student_id!
  1370. $query = "current_student_id=$current_student_id";
  1371. $turl = fp_url($path, $query, TRUE);
  1372. //$on_click = "window.location=\"" . $turl . "\"";
  1373. $href = $turl;
  1374. }
  1375. if ($path == $active_tab_path) {
  1376. // This is the current page we are on.
  1377. $active = TRUE;
  1378. $title = $tab_title;
  1379. $on_click = "";
  1380. $href = "";
  1381. }
  1382. $tab_array[] = array(
  1383. "title" => $tab_title,
  1384. "active" => $active,
  1385. "on_click" => $on_click,
  1386. "href" => $href,
  1387. );
  1388. }
  1389. return $tab_array;
  1390. }
  1391. /**
  1392. * Similar to render_tab_array.
  1393. */
  1394. function fp_render_sub_tab_array($tab_array) {
  1395. global $current_student_id;
  1396. $rtn = "";
  1397. $rtn .= "<div class='sub-tabs'>";
  1398. foreach ($tab_array as $tab) {
  1399. $title = @$tab["title"];
  1400. $on_click = @$tab["on_click"];
  1401. $active = @$tab["active"];
  1402. $type = @$tab["type"];
  1403. $extra_class = "";
  1404. if ($active) $extra_class = "gradbutton-active";
  1405. $extra_class .= " sub-tab-title-" . fp_get_machine_readable(strtolower(trim($title)));
  1406. if ($type == "link" ) {
  1407. // Render as a standard link
  1408. $label = @$tab["label"];
  1409. $text = @$tab["text"];
  1410. $link_title = @$tab['link_title'];
  1411. $link_class = @$tab['link_class'];
  1412. $rtn .= "<span class='subtab-link-wrapper $link_class'>";
  1413. if ($label) {
  1414. $rtn .= "<label>$label</label>";
  1415. }
  1416. $rtn .= "<a href='javascript: $on_click' class='fp-sub-tab-link $extra_class' title='$link_title'>$text</a>";
  1417. $rtn .= "</span>";
  1418. }
  1419. else {
  1420. // Render as a button
  1421. $rtn .= fp_render_button($title, $on_click, $extra_class);
  1422. }
  1423. }
  1424. $rtn .= "</div>";
  1425. return $rtn;
  1426. }
  1427. /**
  1428. * Returns the HTML to draw a pretty button.
  1429. *
  1430. */
  1431. function fp_render_button($title, $on_click, $extra_class = "") {
  1432. // we want to add on a variable-name-friendly version of the title to extra_class.
  1433. $extra_class .= " fp-render-button-" . fp_get_machine_readable(strtolower($title));
  1434. $rtn = "<button class='fp-render-button $extra_class' onClick='$on_click'>$title</button>";
  1435. return $rtn;
  1436. }
  1437. function fp_render_mobile_tab_array($tab_array) {
  1438. $rtn = "";
  1439. $js_vars = "var mobileTabSelections = new Array(); ";
  1440. if (count($tab_array) <= 1) return "";
  1441. $rtn .= "<table border='0' width='200' cellpadding='0' cellspacing='0' class='fp-mobile-tabs'>
  1442. <td>
  1443. <b>" . t("Display") . ": </b>";
  1444. $rtn .= "<select onChange='executeSelection()' id='mobileTabsSelect'>";
  1445. for ($t = 0; $t < count($tab_array); $t++)
  1446. {
  1447. $title = $tab_array[$t]["title"];
  1448. $active = $tab_array[$t]["active"];
  1449. $on_click = $tab_array[$t]["on_click"];
  1450. if ($title == "")
  1451. {
  1452. continue;
  1453. }
  1454. $sel = ($active == true) ? $sel = "selected":"";
  1455. $rtn .= "<option $sel value='$t'>$title</option>";
  1456. $js_vars .= "mobileTabSelections[$t] = '$on_click'; \n";
  1457. }
  1458. $rtn .= "</select>
  1459. </td></table>";
  1460. $rtn .= '
  1461. <script type="text/javascript">
  1462. ' . $js_vars . '
  1463. function executeSelection() {
  1464. var sel = document.getElementById("mobileTabsSelect").value;
  1465. var statement = mobileTabSelections[sel];
  1466. // Lets execute the statement...
  1467. eval(statement);
  1468. }
  1469. </script>
  1470. ';
  1471. return $rtn;
  1472. }
  1473. /**
  1474. * Given a propperly formatted tab_array, this will return the HTML
  1475. * to draw it on a page.
  1476. *
  1477. * @param array $tab_array
  1478. * - Array should have this structure:
  1479. * - $tab_array[i]["title"] = The title or caption of the tab. "main", or "Edit", etc.
  1480. * - $tab_array[i]["active"] = boolean. True if this is the tab we are currently looking at.
  1481. * - $tab_array[i]["href"] = This is a complete href for the link we will create.
  1482. * - $tab_array[i]["on_click"] = This is an onClick command for javascript. If this is set, href will be ignored.
  1483. *
  1484. * @return string
  1485. */
  1486. function fp_render_tab_array($tab_array) {
  1487. $rtn = "";
  1488. if (count($tab_array) == 0) return "";
  1489. $img_path = fp_theme_location() . "/images";
  1490. $rtn .= "<ul class='tabs'>";
  1491. for ($t = 0; $t < count($tab_array); $t++)
  1492. {
  1493. $title = @$tab_array[$t]["title"];
  1494. // If the title has a replacement pattern in it, then we need to call a hook to see what it should be set to.
  1495. if (strpos($title, "%") !== 0) {
  1496. $title = menu_convert_replacement_pattern($title);
  1497. }
  1498. $active = @$tab_array[$t]["active"];
  1499. $on_click = @$tab_array[$t]["on_click"];
  1500. $href = @$tab_array[$t]["href"];
  1501. $extra_a = "";
  1502. if ($on_click != "") {
  1503. $href = "javascript:void(0);";
  1504. $extra_a = "onclick='$on_click'";
  1505. }
  1506. if ($title == "")
  1507. {
  1508. continue;
  1509. }
  1510. $extra_class = "inactive";
  1511. if ($active) {
  1512. $extra_class = "active";
  1513. // the active tab is not clickable.
  1514. $href = 'javascript:void(0);';
  1515. $extra_a = '';
  1516. }
  1517. if ($t == 0) $extra_class .= " first";
  1518. if ($t == count($tab_array) - 1) $extra_class .= " last";
  1519. // Also add in a machine-friendly class based on the title and position
  1520. $extra_class .= " tab-count-$t tab-title-" . fp_get_machine_readable(strtolower(trim($title)));
  1521. $rtn .= "<li class='tab $extra_class'><a href='$href' $extra_a>$title</a></li>";
  1522. }
  1523. $rtn .= "</ul>";
  1524. return $rtn;
  1525. }
  1526. function display_not_found() {
  1527. header("HTTP/1.0 404 Not Found", TRUE, 404);
  1528. $page = array(
  1529. "title" => t("Not Found"),
  1530. "content" => "<h2>" . t("Page not found") . "</h2>" . t("Sorry, the requested page could not be found."),
  1531. );
  1532. $location = @$_SERVER["REQUEST_URI"];
  1533. watchdog("page_not_found", "404 - Page not found (" . strip_tags($location) . ")", array(), WATCHDOG_DEBUG);
  1534. fp_display_page($page);
  1535. die;
  1536. }
  1537. function display_access_denied() {
  1538. header('HTTP/1.1 403 Forbidden', TRUE, 403);
  1539. $page = array(
  1540. "title" => t("Access Denied"),
  1541. "content" => "<h2>" . t("Access Denied") . "</h2>" . t("Sorry, but you do not have access to the requested page or function."),
  1542. );
  1543. $location = @$_SERVER["REQUEST_URI"];
  1544. watchdog("access_denied", "403 - Access denied (" . strip_tags($location) . ")", array(), WATCHDOG_DEBUG);
  1545. fp_display_page($page);
  1546. die;
  1547. }
  1548. /**
  1549. * Return the theme location
  1550. */
  1551. function fp_theme_location($bool_include_base_path = TRUE) {
  1552. $p = variable_get("theme",'themes/fp6_clean');
  1553. // The theme hasn't been set for some reason
  1554. if ($p == "") {
  1555. $p = "themes/fp6_clean";
  1556. }
  1557. if ($bool_include_base_path) {
  1558. $bp = base_path();
  1559. // The following code is to fix a bug where we might end up with // as our location, if our base_path is simply "/", meaning,
  1560. // the site is located on a bare domain.
  1561. if ($bp != "/") {
  1562. $p = base_path() . "/" . $p;
  1563. }
  1564. else {
  1565. $p = "/" . $p;
  1566. }
  1567. }
  1568. return $p;
  1569. }
  1570. /**
  1571. * Will draw a string in a pretty curved box. Used for displaying semester
  1572. * titles.
  1573. *
  1574. * @param string $title
  1575. * @return string
  1576. */
  1577. function fp_render_curved_line($text) {
  1578. depricated_message();
  1579. // Will simply draw a curved title bar containing the $title
  1580. // as the text.
  1581. $rtn = "
  1582. <div class='blueTitle' style='text-align: center; border-radius: 5px; padding: 1px;'>
  1583. <span class='tenpt'><b>$text</b></span>
  1584. </div>
  1585. ";
  1586. return $rtn;
  1587. }
  1588. function fp_render_section_title($text, $extra_class = '') {
  1589. $extra_class .= " section-box-text-" . fp_get_machine_readable(strtolower(trim($text)));
  1590. $rtn = "<div class='section-box-title section-box-title-$extra_class'>$text</div>";
  1591. return $rtn;
  1592. }
  1593. /**
  1594. * Will draw a string in a pretty square box. Used for displaying semester
  1595. * titles.
  1596. *
  1597. * @param string $title
  1598. * @return string
  1599. */
  1600. function fp_render_square_line($text) {
  1601. depricated_message("render_square_line");
  1602. $rtn = "";
  1603. $rtn .= "
  1604. <table border='0' width='100%' cellpadding='0' cellspacing='0'>
  1605. <tr>
  1606. <td width='10%' align='left' valign='top'></td>
  1607. <td width='80%' align='center' rowspan='2'>
  1608. <span class='tenpt' style='color: white' ><b>$text</b></span>
  1609. </td>
  1610. <td width='10%' align='right' valign='top'></td>
  1611. </tr>
  1612. <tr>
  1613. <td align='left' valign='bottom'></td>
  1614. <td align='right' valign='bottom'></td>
  1615. </tr>
  1616. </table>
  1617. ";
  1618. return $rtn;
  1619. }
  1620. function fp_render_menu_item($item, $bool_check_user_access = TRUE) {
  1621. $rtn = "";
  1622. if ($bool_check_user_access) {
  1623. if (!menu_check_user_access($item)) {
  1624. return "";
  1625. }
  1626. }
  1627. $description = $item["description"];
  1628. $title = $item["title"];
  1629. $safe_title = htmlentities(trim($title), ENT_QUOTES);
  1630. //$url = $GLOBALS["fp_system_settings"]["base_path"] . "/" . $item["path"];
  1631. $url = fp_url($item["path"], "", TRUE);
  1632. $target = @$item["page_settings"]["target"];
  1633. $menu_icon = @$item["page_settings"]["menu_icon"];
  1634. $extra_class = "";
  1635. if ($menu_icon != "") {
  1636. if (!strstr($menu_icon, 'http')) {
  1637. $base_url = $GLOBALS['fp_system_settings']['base_url'];
  1638. if ($base_url == "/") $base_url = ""; // so that we don't have // as a path, because of the next line.
  1639. if (substr($menu_icon, 0, 1) == '/') {
  1640. // Already starts with a slash, so probably should just use as is.
  1641. // take no action.
  1642. }
  1643. else {
  1644. $menu_icon = $base_url . "/" . $menu_icon;
  1645. }
  1646. }
  1647. $icon_img = "<img src='$menu_icon' border='0' class='fpmn-icon' alt='$safe_title'>";
  1648. }
  1649. else {
  1650. $icon_img = "<span class='fp-menu-item-no-icon'></span>";
  1651. }
  1652. if (!$description) $extra_class = "fp-menu-item-tight";
  1653. $machine_title = strtolower(fp_get_machine_readable($title));
  1654. $machine_path = strtolower(fp_get_machine_readable($item['path']));
  1655. $extra_class .= " fp-menu-item-title-$machine_title fp-menu-item-path-$machine_path ";
  1656. $rtn .= "<div class='fp-menu-item $extra_class'>
  1657. <div class='fp-menu-item-link-line'>
  1658. <a href='$url' target='$target'>$icon_img$title</a>
  1659. </div>
  1660. ";
  1661. if ($description) {
  1662. $rtn .= " <div class='fp-menu-item-description'>$description</div>";
  1663. }
  1664. $rtn .= "</div>";
  1665. return $rtn;
  1666. }
  1667. /**
  1668. * Alias of pretty_print($var)
  1669. */
  1670. function ppm($var, $b = FALSE) {
  1671. return pretty_print($var, $b);
  1672. }
  1673. function pretty_print($var, $bool_return = FALSE) {
  1674. $x = "<pre>" . print_r($var, true) . "</pre>";
  1675. if ($bool_return) return $x;
  1676. print $x;
  1677. }

Functions

Namesort descending Description
display_access_denied
display_not_found
format_date Format a timestamp using the date command. TODO: Make the formats something which can be controlled through the settings.
fp_build_sub_tab_array Create a "sub-tab" array, which looks like a standard tab_array, but it contains only this page's sub-tab siblings.
fp_build_tab_array Looks at the current page array and returns a valid $tab_array Meant for the top of the screen.
fp_display_page Output the contents of the $page variable to the screen. $page is an array containing details about the page, as well as its original menu item (router_item) definition.
fp_push_and_balance_profile_items This function accepts a "profile items" array by reference, which is presumed to have a "left_side" and a "right_side" already defined. We can "push" items onto it, and the item will automatically go to the…
fp_render_breadcrumbs Return the HTML for breadcrumbs for the current page we are on. Will skip any breadcrumbs we do not have permission to access.
fp_render_button Returns the HTML to draw a pretty button.
fp_render_curved_line Will draw a string in a pretty curved box. Used for displaying semester titles.
fp_render_c_fieldset This function will return the HTML to contruct a collapsible fieldset, complete with javascript and style tags.
fp_render_menu_block Render a "menu" block of menu items which are all rooted at the menu_root. So if the menu root is tools, it might return items whose paths look like: tools/fun tools/here/there So long as the menu type is "MENU_TYPE_NORMAL_ITEM" or…
fp_render_menu_item
fp_render_mobile_hamburger_menu This will create the HTML content for the "mobile hamburger" menu, which appears when we press the 3 lines icon or "hamburger" icon on a mobile device.
fp_render_mobile_tab_array
fp_render_section_title
fp_render_sidebar_left_content Returns the HTML for the left sidebar content.
fp_render_square_line Will draw a string in a pretty square box. Used for displaying semester titles.
fp_render_student_profile_header Returns the HTML for the "profile" header html for a student
fp_render_sub_tab_array Similar to render_tab_array.
fp_render_tab_array Given a propperly formatted tab_array, this will return the HTML to draw it on a page.
fp_render_top_nav_content Returns the HTML for the top navigation content of the screen itself.
fp_show_title Sets whether the title should be shown on the page or not.
fp_theme_location Return the theme location
pager_get_querystring Adapted from https://api.drupal.org/api/drupal/includes%21pager.inc/function/pager_ge...
pager_load_array Adapted from https://api.drupal.org/api/drupal/includes%21pager.inc/function/pager_lo...
ppm Alias of pretty_print($var)
pretty_print
theme_pager Adapted from https://api.drupal.org/api/drupal/includes%21pager.inc/function/theme_pa...
theme_pager_first Adapted from: https://api.drupal.org/api/drupal/includes%21pager.inc/function/theme_pa...
theme_pager_last Adapted from https://api.drupal.org/api/drupal/includes%21pager.inc/function/theme_pa...
theme_pager_link Adapted from https://api.drupal.org/api/drupal/includes%21pager.inc/function/theme_pa...
theme_pager_next Adapted from https://api.drupal.org/api/drupal/includes%21pager.inc/function/theme_pa...
theme_pager_previous Adapted from https://api.drupal.org/api/drupal/includes%21pager.inc/function/theme_pa...
theme_table_header_sortable Given an array of table headers (in the format listed below), returns back the HTML to draw it to the screen. This makes them clickable, to make the table header sortable. This is meant to be used with queries, by adding in an "ORDER BY"…
theme_table_header_sortable_order_by Used with the theme_table_header_sortable function (meant to be called AFTER headers have been created.)
theme_table_header_sortable_set_initial_sort Sets our initial sort, if there isn't already one set.