AdvisingScreen.php

  1. 6.x classes/AdvisingScreen.php
  2. 4.x custom/classes/AdvisingScreen.php
  3. 5.x custom/classes/AdvisingScreen.php

File

classes/AdvisingScreen.php
View source
  1. <?php
  2. class AdvisingScreen extends stdClass
  3. {
  4. public $width_array, $popup_width_array, $script_filename, $is_on_left, $box_array;
  5. public $degree_plan, $student, $bool_popup, $footnote_array, $flightpath;
  6. public $screen_mode, $db, $bool_print, $view, $user_settings;
  7. public $bool_blank, $bool_hiding_grades, $bool_force_pie_charts;
  8. public $admin_message;
  9. // Variables for the template/theme output...
  10. public $theme_location, $page_content, $page_has_search, $page_tabs, $page_on_load;
  11. public $page_hide_report_error, $page_scroll_top, $page_is_popup;
  12. public $page_title, $page_extra_css_files, $page_body_classes, $page_display_currently_advising;
  13. /**
  14. * This is the constructor. Must be named this for inheritence to work
  15. * correctly.
  16. *
  17. * @param string $script_filename
  18. * - This is the script which forms with POST to. Ex: "advise.php"
  19. *
  20. * @param FlightPath $flightpath
  21. * - FlightPath object.
  22. *
  23. * @param string $screen_mode
  24. * - A string describing what "mode" we are in.
  25. * - If left blank, we assume it is full-screen and normal.
  26. * - If set to "popup" then we are in a popup window, and we will
  27. * not draw certain elements.
  28. *
  29. */
  30. function __construct($script_filename = "", FlightPath $flightpath = null, $screen_mode = "")
  31. {
  32. $this->width_array = Array("10%", "8%","8%", "17%", "26%", "10%", "10%", "9%");
  33. $this->popup_width_array = Array("17%", "1%", "1%", "15%", "26%", "15%", "15%", "10%");
  34. $this->script_filename = $script_filename;
  35. $this->is_on_left = true;
  36. $this->box_array = array();
  37. $this->footnote_array = array();
  38. $this->page_extra_css_files = array();
  39. $this->flightpath = $flightpath;
  40. if ($flightpath != null) {
  41. $this->degree_plan = $flightpath->degree_plan;
  42. $this->student = $flightpath->student;
  43. }
  44. $this->db = get_global_database_handler();
  45. if ($screen_mode == "popup")
  46. {
  47. $this->bool_popup = true;
  48. }
  49. $this->bool_blank = false;
  50. $this->screen_mode = $screen_mode;
  51. } // construct
  52. /**
  53. * This function will attempt to determine automatically
  54. * if we are on a mobile device. If so, it will set
  55. * $this->page_is_mobile = TRUE
  56. *
  57. */
  58. function determine_mobile_device(){
  59. depricated_message('determine_mobile_device is depricated');
  60. $user_agent = $_SERVER['HTTP_USER_AGENT'];
  61. $look_for = array(
  62. "ipod",
  63. "iphone",
  64. "android",
  65. "opera mini",
  66. "blackberry",
  67. "(pre\/|palm os|palm|hiptop|avantgo|plucker|xiino|blazer|elaine)",
  68. "(iris|3g_t|windows ce|opera mobi|windows ce; smartphone;|windows ce; iemobile)",
  69. "(smartphone|iemobile)",
  70. );
  71. foreach ($look_for as $test_agent) {
  72. if (preg_match('/' . $test_agent . '/i',$user_agent)) {
  73. $this->page_is_mobile = true;
  74. break;
  75. }
  76. }
  77. $GLOBALS["fp_page_is_mobile"] = $this->page_is_mobile;
  78. } // ends function mobile_device_detect
  79. /**
  80. * This function will return the HTML to contruct a collapsible fieldset,
  81. * complete with javascript and style tags.
  82. *
  83. * @param String $content
  84. * @param String $legend
  85. * @param bool $bool_start_closed
  86. * @return String
  87. */
  88. function draw_c_fieldset($content, $legend = "Click to expand/collapse", $bool_start_closed = false)
  89. {
  90. // Create a random ID for this fieldset, js, and styles.
  91. $id = md5(rand(9,99999) . time());
  92. $start_js_val = 1;
  93. $fsstate = "open";
  94. $content_style = "";
  95. if ($bool_start_closed) {
  96. $start_js_val = 0;
  97. $fsstate = "closed";
  98. $content_style = "display: none;";
  99. }
  100. $js = "<script type='text/javascript'>
  101. var fieldset_state_$id = $start_js_val;
  102. function toggle_fieldset_$id() {
  103. var content = document.getElementById('content_$id');
  104. var fs = document.getElementById('fs_$id');
  105. if (fieldset_state_$id == 1) {
  106. // Already open. Let's close it.
  107. fieldset_state_$id = 0;
  108. content.style.display = 'none';
  109. fs.className = 'c-fieldset-closed-$id';
  110. }
  111. else {
  112. // Was closed. let's open it.
  113. fieldset_state_$id = 1;
  114. content.style.display = '';
  115. fs.className = 'c-fieldset-open-$id';
  116. }
  117. }
  118. </script>";
  119. $rtn = "
  120. <fieldset class='c-fieldset-$fsstate-$id' id='fs_$id'>
  121. <legend><a href='javascript: toggle_fieldset_$id();' class='nounderline'>$legend</a></legend>
  122. <div id='content_$id' style='$content_style'>
  123. $content
  124. </div>
  125. </fieldset>
  126. $js
  127. <style>
  128. fieldset.c-fieldset-open-$id {
  129. border: 1px solid;
  130. }
  131. fieldset.c-fieldset-closed-$id {
  132. border: 1px solid;
  133. border-bottom-width: 0;
  134. border-left-width: 0;
  135. border-right-width: 0;
  136. }
  137. legend a {
  138. text-decoration: none;
  139. }
  140. </style>
  141. ";
  142. return $rtn;
  143. }
  144. /**
  145. * Simply builds a single menu item.
  146. *
  147. * @return string
  148. */
  149. function draw_menu_item($url, $target, $icon_img, $title, $description = "") {
  150. $rtn = "";
  151. if (!$description) $extra_class = "fp-menu-item-tight";
  152. $rtn .= "<div class='fp-menu-item $extra_class'>
  153. <div class='fp-menu-item-link-line'>
  154. <a href='$url' target='$target'>$icon_img $title</a>
  155. </div>
  156. ";
  157. if ($description) {
  158. $rtn .= " <div class='fp-menu-item-description'>$description</div>";
  159. }
  160. $rtn .= "</div>";
  161. return $rtn;
  162. }
  163. /**
  164. * Uses the draw_menu_item method to draw the HTML for
  165. * all the supplied menu items, assuming the user has
  166. * permission to view them.
  167. *
  168. * Returns the HTML or "" if no menus could be drawn.
  169. *
  170. * @param unknown_type $menu_array
  171. */
  172. function draw_menu_items($menu_array) {
  173. $rtn = "";
  174. if (count($menu_array) == 0) return "";
  175. foreach($menu_array as $item) {
  176. $url = $item["url"];
  177. $target = $item["target"];
  178. $icon = $item["icon"];
  179. if ($icon) {
  180. $icon_img = "<img src='$icon' border='0'>";
  181. }
  182. else {
  183. $icon_img = "<span class='fp-menu-item-no-icon'></span>";
  184. }
  185. $title = $item["title"];
  186. $description = $item["description"];
  187. // Make sure they have permission!
  188. if ($item["permission"] != "") {
  189. if (!user_has_permission($item["permission"])) {
  190. // User did NOT have permission to view this link.
  191. continue;
  192. }
  193. }
  194. $rtn .= $this->draw_menu_item($url, $target, $icon_img, $title, $description);
  195. }
  196. return $rtn;
  197. }
  198. /**
  199. * This method outputs the screen to the browser by performing
  200. * an include(path-to-theme-file.php). All necessary information
  201. * must be placed into certain variables before the include happens.
  202. *
  203. */
  204. function output_to_browser()
  205. {
  206. global $user, $current_student_id;
  207. // This method will output the screen to the browser.
  208. // outputs the $page_content variable.
  209. // Figure out our school id.
  210. $school_id = $user->school_id;
  211. if ($current_student_id) {
  212. $school_id = db_get_school_id_for_student_id($current_student_id);
  213. }
  214. else if (isset($this->student) && is_object($this->student)) {
  215. $school_id = $this->student->school_id;
  216. }
  217. else if (isset($this->degree_plan) && is_object($this->degree_plan)) {
  218. $school_id = $this->degree_plan->school_id;
  219. }
  220. $theme_location = fp_theme_location(); // file location of the theme folder
  221. $page_logo_url = variable_get("logo_image_url", "");
  222. if ($page_logo_url == "") {
  223. $page_logo_url = $theme_location . "/images/fp_banner_default.png";
  224. }
  225. $page_content = $this->page_content;
  226. $page_tabs = $this->page_tabs;
  227. $page_has_search = $this->page_has_search;
  228. $page_on_load = $this->page_on_load;
  229. $page_scroll_top = $this->page_scroll_top;
  230. $page_is_popup = $this->page_is_popup;
  231. $page_title = $this->page_title;
  232. $page_body_classes = $this->page_body_classes;
  233. // Are we explicitly setting that this is a popup in the URL?
  234. if (isset($_REQUEST['window_mode']) && $_REQUEST['window_mode'] == 'popup') {
  235. $page_is_popup = TRUE;
  236. }
  237. $page_extra_js_files = "";
  238. $page_extra_js_settings = "";
  239. $page_extra_css_files = "";
  240. $page_breadcrumbs = "";
  241. $system_name = variable_get("system_name", "FlightPath");
  242. if ($page_title == "") {
  243. // By default, page title is this...
  244. $page_title = variable_get_for_school("school_initials", "DEMO", $school_id) . " " . $system_name;
  245. }
  246. $page_title = menu_convert_replacement_pattern($page_title);
  247. $page_display_title = $page_title;
  248. if (isset($GLOBALS["fp_set_show_title"]) && $GLOBALS["fp_set_show_title"] === FALSE) {
  249. $page_display_title = "";
  250. }
  251. $page_title = strip_tags($page_title);
  252. $page_breadcrumbs = fp_render_breadcrumbs();
  253. if ($this->student && $this->page_display_currently_advising == TRUE && !$page_is_popup) {
  254. $page_student_profile_header = fp_render_student_profile_header();
  255. }
  256. $page_hide_report_error = $this->page_hide_report_error;
  257. $print_option = "";
  258. if ($this->bool_print == true) {
  259. $page_body_classes .= " bool-print";
  260. }
  261. if ($page_is_popup) {
  262. $page_body_classes .= " page-is-popup";
  263. }
  264. $page_body_classes .= " school-id-" . $school_id;
  265. if (module_enabled('schools')) {
  266. $page_body_classes .= " school-code-" . schools_get_school_code_for_id($school_id);
  267. }
  268. // A dummy query-string is added to filenames, to gain control over
  269. // browser-caching. The string changes on every update or full cache
  270. // flush, forcing browsers to load a new copy of the files, as the
  271. // URL changed.
  272. $page_css_js_query_string = variable_get('css_js_query_string', '0');
  273. // Add extra JS files.
  274. if (is_array($GLOBALS["fp_extra_js"]) && count($GLOBALS["fp_extra_js"]) > 0) {
  275. foreach ($GLOBALS["fp_extra_js"] as $js_file_name) {
  276. $page_extra_js_files .= "<script type='text/javascript' src='$js_file_name?$page_css_js_query_string'></script> \n";
  277. }
  278. }
  279. // Load any extra CSS files which addon modules might have added.
  280. if (isset($GLOBALS["fp_extra_css"]) && is_array($GLOBALS["fp_extra_css"]) && count($GLOBALS["fp_extra_css"]) > 0) {
  281. foreach ($GLOBALS["fp_extra_css"] as $css_file_name) {
  282. $page_extra_css_files .= "<link rel='stylesheet' type='text/css' href='$css_file_name?$page_css_js_query_string' /> \n";
  283. }
  284. }
  285. // Javascript settings... (I know this would be better as a recursive function. For now,
  286. // you can have up to 3 layers deep. Sorry for it looking so ugly.
  287. $page_extra_js_settings .= "var FlightPath = new Object(); \n";
  288. $page_extra_js_settings .= " FlightPath.settings = new Object(); \n";
  289. foreach ($GLOBALS["fp_extra_js_settings"] as $key => $val) {
  290. if (is_array($val)) {
  291. $page_extra_js_settings .= "FlightPath.settings.$key = new Array(); \n";
  292. foreach ($val as $k => $v) {
  293. if (is_array($v)) {
  294. $page_extra_js_settings .= "FlightPath.settings.$key" . "['" . "$k'] = new Array(); \n";
  295. foreach ($v as $kk => $vv) {
  296. $page_extra_js_settings .= "FlightPath.settings.$key" . "['" . "$k']['$kk'] = '$vv'; \n";
  297. }
  298. }
  299. else {
  300. $page_extra_js_settings .= "FlightPath.settings.$key" . "['" . "$k'] = '$v'; \n";
  301. }
  302. }
  303. }
  304. else {
  305. $page_extra_js_settings .= "FlightPath.settings.$key = '$val'; \n";
  306. }
  307. }
  308. // Scrolling somewhere? Add it to the page_on_load...
  309. if (trim($page_scroll_top != "")) {
  310. $page_on_load .= " scrollTo(0, $page_scroll_top);";
  311. }
  312. // Add our dialog HTML if the page isn't a popup.
  313. if (!$page_is_popup) {
  314. $page_content .= "
  315. <!-- iframe dialog, for use by javascript later on -->
  316. <div id='fp-iframe-dialog-small' style='display: none;' title=''>
  317. <iframe id='fp-iframe-dialog-small-iframe' class='dialog-iframe' ></iframe>
  318. </div>
  319. <div id='fp-iframe-dialog-large' style='display: none;' title=''>
  320. <iframe id='fp-iframe-dialog-large-iframe' class='dialog-iframe' ></iframe>
  321. </div>
  322. ";
  323. }
  324. else {
  325. // The page is in a dialog. In order to cope with a strange bug in Chrome (as of 10-29-2020), we need
  326. // to "nudge" the dialog window 1 pixel, or sometimes the internal iframe will not show up.
  327. // We do this after it loads.
  328. $page_on_load .= "\n\n // From: https://stackoverflow.com/questions/9847580/how-to-detect-safari-chrome-ie-firefox-and-opera-browser \n\n";
  329. $page_on_load .= ' var browser = (function() {
  330. var test = function(regexp) {return regexp.test(window.navigator.userAgent)}
  331. switch (true) {
  332. case test(/edg/i): return "Microsoft Edge";
  333. case test(/trident/i): return "Microsoft Internet Explorer";
  334. case test(/firefox|fxios/i): return "Mozilla Firefox";
  335. case test(/opr\//i): return "Opera";
  336. case test(/ucbrowser/i): return "UC Browser";
  337. case test(/samsungbrowser/i): return "Samsung Browser";
  338. case test(/chrome|chromium|crios/i): return "Google Chrome";
  339. case test(/safari/i): return "Apple Safari";
  340. default: return "Other";
  341. }
  342. })();';
  343. $page_on_load .= " if (browser == 'Google Chrome') {
  344. parent.fpNudgeDialog();
  345. }";
  346. }
  347. // Grab the appropriate sidebar & top nav content (if any)
  348. $page_sidebar_left_content = $page_top_nav_content = "";
  349. if (!$page_is_popup) {
  350. $page_sidebar_left_content = fp_render_sidebar_left_content();
  351. $page_top_nav_content = fp_render_top_nav_content();
  352. }
  353. if ($page_sidebar_left_content) {
  354. $page_body_classes .= " has-sidebar-left";
  355. }
  356. if ($page_tabs) {
  357. $page_body_classes .= " has-page-tabs";
  358. }
  359. // We are going to try to include the theme. If it can't be found, we will display a CORE theme, and display a message.
  360. $theme = variable_get("theme","themes/fp6_clean");
  361. $head_template_filename = $theme . "/head.tpl.php";
  362. $page_template_filename = $theme . "/page.tpl.php";
  363. // If there is a special theme file we should be using based on the URL, set it here.
  364. $q = trim(@strtolower($_REQUEST['q']));
  365. if ($q) {
  366. $q = trim(str_replace("/", "-", $q));
  367. if ($q) {
  368. if (file_exists($theme . "/page--" . $q . ".tpl.php")) {
  369. $page_template_filename = $theme . "/page--" . $q . ".tpl.php";
  370. }
  371. }
  372. }
  373. if (!file_exists($page_template_filename)) {
  374. print "<p><b>Theme Error:</b> Tried to load template from: $page_template_filename, but this file could not be found.
  375. <br>This is possibly because either the filename or the directory specified does not exist.
  376. <br>Contact site administrator.</p>";
  377. $page_template_filename = "themes/fp6_clean" . "/page.tpl.php";
  378. }
  379. // Are we adding any external CSS files?
  380. $external_css = variable_get("external_css", "");
  381. if ($external_css) {
  382. $temp = explode(",",$external_css);
  383. foreach ($temp as $line) {
  384. if (trim($line) == "") continue;
  385. $page_extra_css_files .= "<link rel='stylesheet' type='text/css' href='" . trim($line) . "?$page_css_js_query_string' /> \n";
  386. }
  387. }
  388. /////////////////////////
  389. // Output to browser:
  390. include($head_template_filename);
  391. include($page_template_filename);
  392. } // output_to_browser
  393. /**
  394. * This function simply adds a reference for additional CSS to be
  395. * link'd in to the theme. It is used by add-on modules.
  396. *
  397. * The filename needs to be from the reference of the base
  398. * FlightPath install.
  399. *
  400. * Ex: $screen->add_css("modules/course_search/css/style.css");
  401. *
  402. * @param String $filename
  403. */
  404. function add_css($filename) {
  405. $this->page_extra_css_files[] = $filename;
  406. }
  407. /**
  408. * Clear the session varibles.
  409. *
  410. */
  411. function clear_variables()
  412. {
  413. // Clear the session variables.
  414. $csid = $_REQUEST["current_student_id"];
  415. $_SESSION["advising_student_id$csid"] = "";
  416. $_SESSION["advising_student_id"] = "";
  417. $_SESSION["advising_major_code$csid"] = "";
  418. $_SESSION["advising_track_code$csid"] = "";
  419. $_SESSION["advising_track_degree_ids$csid"] = "";
  420. $_SESSION["advising_term_id$csid"] = "";
  421. $_SESSION["advising_what_if$csid"] = "";
  422. $_SESSION["what_if_major_code$csid"] = "";
  423. $_SESSION["cache_f_p$csid"] = "";
  424. $_SESSION["cache_what_if$csid"] = "";
  425. }
  426. /**
  427. * Constructs the HTML which will be used to display
  428. * the student's transfer credits
  429. *
  430. */
  431. function build_transfer_credit()
  432. {
  433. $pC = "";
  434. $is_empty = true;
  435. $pC .= $this->draw_semester_box_top("Transfer Credit", FALSE);
  436. // Basically, go through all the courses the student has taken,
  437. // And only show the transfers. This is similar to Excess credit.
  438. $student_id = $this->student->student_id;
  439. $school_id = db_get_school_id_for_student_id($student_id);
  440. $this->student->list_courses_taken->sort_alphabetical_order(false, true);
  441. $this->student->list_courses_taken->reset_counter();
  442. while($this->student->list_courses_taken->has_more())
  443. {
  444. $course = $this->student->list_courses_taken->get_next();
  445. // Skip non transfer credits.
  446. if ($course->bool_transfer != true)
  447. {
  448. continue;
  449. }
  450. $bool_add_footnote = false;
  451. if ($course->get_has_been_displayed($course->req_by_degree_id) == true)
  452. { // Show the footnote if this has already been displayed
  453. // elsewhere on the page.
  454. $bool_add_footnote = true;
  455. }
  456. // Tell the course what group we are coming from. (in this case: none)
  457. $course->disp_for_group_id = "";
  458. $pC .= $this->draw_course_row($course,"","",false,false,$bool_add_footnote,true);
  459. $is_empty = false;
  460. }
  461. if (@$GLOBALS["advising_course_has_asterisk"] == true)
  462. {
  463. $pC .= "<tr>
  464. <td colspan='10'>
  465. <div class=' ' style='margin-top: 10px; padding: 3px;'>
  466. <b>*</b> Courses marked with an asterisk (*) have
  467. equivalencies at " . variable_get_for_school("school_initials", "DEMO", $school_id) . ".
  468. Click on the course for more
  469. details.
  470. </div>
  471. </td>
  472. </tr>
  473. ";
  474. }
  475. $pC .= $this->draw_semester_box_bottom();
  476. if (!$is_empty)
  477. {
  478. $this->add_to_screen($pC, "TRANSFER_CREDIT");
  479. }
  480. } // function build_transfer_credit
  481. /**
  482. * Constructs the HTML which will be used to display
  483. * the student's graduate credits (if any exist)
  484. *
  485. */
  486. function build_graduate_credit()
  487. {
  488. $pC = "";
  489. $is_empty = true;
  490. $pC .= $this->draw_semester_box_top(variable_get_for_school("graduate_credits_block_title", t("Graduate Credits"), $this->student->school_id), FALSE);
  491. // Basically, go through all the courses the student has taken,
  492. // And only show the graduate credits. Similar to build_transfer_credits
  493. $graduate_level_codes_array = csv_to_array(variable_get_for_school("graduate_level_codes", "GR", $this->student->school_id));
  494. $this->student->list_courses_taken->sort_alphabetical_order(false, true);
  495. $this->student->list_courses_taken->reset_counter();
  496. while($this->student->list_courses_taken->has_more())
  497. {
  498. $course = $this->student->list_courses_taken->get_next();
  499. // Skip non graduate credits.
  500. if (!in_array($course->level_code, $graduate_level_codes_array))
  501. {
  502. continue;
  503. }
  504. // Tell the course_row what group we are coming from. (in this case: none)
  505. $course->disp_for_group_id = "";
  506. $pC .= $this->draw_course_row($course,"","",false,false,false,true);
  507. $is_empty = FALSE;
  508. }
  509. $notice = trim(variable_get_for_school("graduate_credits_block_notice", t("These courses may not be used for undergraduate credit."), $this->student->school_id));
  510. // Do we have a notice to display?
  511. if ($notice != "")
  512. {
  513. $pC .= "<tr><td colspan='8'>
  514. <div class='hypo ' style='margin-top: 15px; padding: 5px;'>
  515. <b>" . t("Important Notice:") . "</b> $notice
  516. </div>
  517. </td></tr>";
  518. }
  519. $pC .= $this->draw_semester_box_bottom();
  520. if (!$is_empty)
  521. {
  522. $this->add_to_screen($pC, "GRADUATE_CREDIT");
  523. }
  524. }
  525. /**
  526. * Constructs the HTML to show which courses have been added
  527. * by an advisor.
  528. *
  529. */
  530. function build_added_courses()
  531. {
  532. $pC = "";
  533. $semester = new Semester(DegreePlan::SEMESTER_NUM_FOR_COURSES_ADDED);
  534. if ($new_semester = $this->degree_plan->list_semesters->find_match($semester))
  535. {
  536. $this->add_to_screen($this->display_semester($new_semester), "ADDED_COURSES");
  537. }
  538. }
  539. /**
  540. * Constructs the HTML to show the Excess Credits list.
  541. *
  542. */
  543. function build_excess_credit()
  544. {
  545. $pC = "";
  546. $pC .= $this->draw_semester_box_top(t("Excess Credits"));
  547. $is_empty = true;
  548. // Should we exclude graduate credits from this list?
  549. $bool_grad_credit_block = (variable_get_for_school("display_graduate_credits_block", "yes", $this->student->school_id) == "yes") ? TRUE : FALSE;
  550. $graduate_level_codes_array = csv_to_array(variable_get_for_school("graduate_level_codes", "GR", $this->student->school_id));
  551. // Basically, go through all the courses the student has taken,
  552. // selecting out the ones that are not fulfilling any
  553. // requirements.
  554. $this->student->list_courses_taken->sort_alphabetical_order();
  555. $this->student->list_courses_taken->reset_counter();
  556. while($this->student->list_courses_taken->has_more())
  557. {
  558. $course = $this->student->list_courses_taken->get_next();
  559. if ($course->get_has_been_displayed($course->req_by_degree_id) == TRUE)
  560. { // Skip ones which have been assigned to groups or semesters.
  561. continue;
  562. }
  563. // Skip transfer credits.
  564. if ($course->bool_transfer == true)
  565. {
  566. continue;
  567. }
  568. // Skip substitutions
  569. // Only skip if we have substituted for every degree the student is enrolled in.
  570. if ($course->get_bool_substitution(-1) == TRUE)
  571. {
  572. //fpm($course->get_bool_substitution(-1));
  573. //fpm($course);
  574. continue;
  575. }
  576. // Exclude graduate credits?
  577. if ($bool_grad_credit_block && $course->level_code != "" && in_array($course->level_code, $graduate_level_codes_array)) {
  578. continue;
  579. }
  580. // Tell the course_row what group we are coming from. (in this case: none)
  581. $course->disp_for_group_id = "";
  582. $pC .= $this->draw_course_row($course,"","",false,false);
  583. $is_empty = false;
  584. }
  585. $pC .= $this->draw_semester_box_bottom();
  586. if (!$is_empty)
  587. {
  588. $this->add_to_screen($pC, "EXCESS_CREDIT");
  589. }
  590. }
  591. /**
  592. * Constructs the HTML which will show footnotes for substitutions
  593. * and transfer credits.
  594. *
  595. */
  596. function build_footnotes($bool_include_box_top = TRUE)
  597. {
  598. // Display the footnotes & messages.
  599. $student_id = $this->student->student_id;
  600. $render = array();
  601. $render['#id'] = 'AdvisingScreen_build_footnotes';
  602. $render['#student_id'] = $student_id;
  603. $render['#degree_plan'] = $this->degree_plan;
  604. $render['#degree_id'] = $this->degree_plan->degree_id;
  605. $render['#footnote_array'] = $this->footnote_array;
  606. $school_id = db_get_school_id_for_student_id($student_id);
  607. //$pC = "";
  608. $is_empty = true;
  609. if ($bool_include_box_top) {
  610. //$pC .= $this->draw_semester_box_top(t("Footnotes & Messages"), true);
  611. $render['box_top'] = array(
  612. 'value' => $this->draw_semester_box_top(t("Footnotes & Messages"), true),
  613. 'weight' => 100,
  614. );
  615. }
  616. //$pC .= "<tr><td colspan='8' class=' '>";
  617. $render['tr_td_start'] = array(
  618. 'value' => "<tr><td colspan='8' class=' '>",
  619. 'weight' => 110,
  620. );
  621. $weight = 200;
  622. $fn_type_array = array("substitution","transfer");
  623. $fn_char = array("substitution" => "S", "transfer"=>"T");
  624. $fn_name = array("substitution" => t("Substitutions"),
  625. "transfer" => t("Transfer Equivalency Footnotes"));
  626. $fn_between = array("substitution" => t("for"),
  627. "transfer" => t("for") . " " . variable_get_for_school("school_initials", "DEMO", $school_id) . "'s");
  628. for ($xx = 0; $xx <= 1; $xx++)
  629. {
  630. $fn_type = $fn_type_array[$xx];
  631. if (isset($this->footnote_array[$fn_type]) && @count($this->footnote_array[$fn_type]) < 1)
  632. {
  633. continue;
  634. }
  635. //$pC .= "<div style='padding-bottom: 10px;'><b>{$fn_name[$fn_type]}</b>";
  636. $render['section_' . $fn_name[$fn_type] . '_start'] = array(
  637. 'value' => "<div style='padding-bottom: 10px;'><b>{$fn_name[$fn_type]}</b>",
  638. 'weight' => $weight,
  639. );
  640. $weight = $weight + 10;
  641. $is_empty = false;
  642. $ccount = 0;
  643. if (isset($this->footnote_array) && is_array($this->footnote_array) && isset($this->footnote_array[$fn_type])) {
  644. $ccount = count($this->footnote_array[$fn_type]);
  645. }
  646. for ($t = 1; $t <= $ccount; $t++)
  647. {
  648. $line = @$this->footnote_array[$fn_type][$t];
  649. if ($line == "")
  650. {
  651. continue;
  652. }
  653. $extra = ".";
  654. $temp = explode(" ~~ ", $line);
  655. $o_course = trim(@$temp[0]);
  656. $new_course = trim(@$temp[1]);
  657. $using_hours = trim(@$temp[2]);
  658. if ($using_hours != "")
  659. {
  660. $using_hours = "($using_hours " . t("hrs") . ")";
  661. }
  662. $in_group = trim(@$temp[3]);
  663. $sub_id = trim(@$temp[4]);
  664. $fbetween = $fn_between[$fn_type];
  665. $sub_details = $this->db->get_substitution_details($sub_id);
  666. $remarks = @trim($sub_details["remarks"]);
  667. $sub_faculty_id = @$sub_details["faculty_id"];
  668. $sub_degree_plan = new DegreePlan();
  669. $sub_degree_plan->degree_id = @$sub_details["required_degree_id"];
  670. $sub_required_group_id = @$sub_details["required_group_id"];
  671. //if ($in_group > 0 && $fn_type=="substitution")
  672. if ($sub_required_group_id != "" && $fn_type=="substitution")
  673. {
  674. $new_group = new Group();
  675. $new_group->group_id = $sub_required_group_id;
  676. $new_group->load_descriptive_data();
  677. $extra = "<div style='padding-left: 45px;'><i>" . t("in") . " $new_group->title.</i></div>";
  678. if ($new_course == $o_course || $o_course == "")
  679. {
  680. $o_course = t("was added");
  681. $fbetween = "";
  682. $extra = str_replace("<i>" . t("in"), "<i>" . t("to"), $extra);
  683. }
  684. }
  685. // Clean this up, as far as the remarks and such. Make it look similar (new function?) as popup text for a substitution.
  686. if ($remarks) $remarks = " ($remarks) ";
  687. // Build a "theme" array, so we can pass it to other modules in a hook.
  688. $theme = array();
  689. $theme["footnote"] = array(
  690. "fn_char" => $fn_char,
  691. "fn_type" => $fn_type,
  692. "fn_num" => $t,
  693. "css_class" => "",
  694. "new_course" => $new_course,
  695. "using_hours" => $using_hours,
  696. "fbetween" => $fbetween,
  697. "o_course" => $o_course,
  698. "extra" => $extra,
  699. "remarks" => $remarks,
  700. "for_degree" => $sub_degree_plan->get_title2(FALSE, TRUE),
  701. "overwrite_with_html" => "",
  702. );
  703. // Invoke a hook on our theme array, so other modules have a chance to change it up.
  704. invoke_hook("theme_advise_footnote", array(&$theme));
  705. $sup = $theme["footnote"]["fn_char"][$theme["footnote"]["fn_type"]] . $theme["footnote"]["fn_num"];
  706. // Actually gather the output for the footnote:
  707. $html = "";
  708. if ($theme["footnote"]["overwrite_with_html"] != "") {
  709. $html = $theme["footnote"]["overwrite_with_html"];
  710. }
  711. else {
  712. $html = "<div class=' advise-footnote {$theme["footnote"]["css_class"]}'>
  713. <sup>$sup</sup>
  714. <span class='advise-footnote-body'>
  715. {$theme["footnote"]["new_course"]}
  716. {$theme["footnote"]["using_hours"]}
  717. {$theme["footnote"]["fbetween"]}
  718. {$theme["footnote"]["o_course"]}{$theme["footnote"]["extra"]}{$theme["footnote"]["remarks"]}
  719. <span class='footnote-for-degree'>(Degree {$theme["footnote"]["for_degree"]})</span>
  720. </span>
  721. </div>";
  722. }
  723. $render['section_' . $fn_name[$fn_type] . '_item_' . $t] = array(
  724. 'value' => $html,
  725. 'weight' => $weight,
  726. );
  727. $weight = $weight + 10;
  728. //$pC .= $html;
  729. }
  730. //$pC .= "</div>";
  731. $render['section_' . $fn_name[$fn_type] . '_end'] = array(
  732. 'value' => "</div>",
  733. 'weight' => $weight,
  734. );
  735. }
  736. //////////////////////////////
  737. /// Unassigned transfer eqv's
  738. $this->student->list_transfer_eqvs_unassigned->load_descriptive_transfer_data();
  739. $this->student->list_transfer_eqvs_unassigned->sort_alphabetical_order();
  740. $this->student->list_transfer_eqvs_unassigned->reset_counter();
  741. $ut_is_empty = TRUE;
  742. $html = "<!--TRANS_UN_COURSES-->";
  743. while ($this->student->list_transfer_eqvs_unassigned->has_more()) {
  744. $c = $this->student->list_transfer_eqvs_unassigned->get_next();
  745. $l_si = $c->subject_id;
  746. $l_cn = $c->course_num;
  747. $l_term = $c->get_term_description(true);
  748. $html .= "<div class=' ' style='padding-left: 10px; padding-bottom: 5px;
  749. margin-left: 1.5em; text-indent: -1.5em;'>
  750. $l_si $l_cn (" . $c->get_hours() . " " . t("hrs") . ") from <em>$c->institution_name</em>.
  751. ";
  752. $html .= "</div>";
  753. $ut_is_empty = false;
  754. $is_empty = false;
  755. }
  756. if ($ut_is_empty == false)
  757. {
  758. $mtitle = "<div style='padding-bottom: 10px;'>
  759. <div style='padding-bottom: 5px;'>
  760. <b>" . t("Transfer Equivalency Removed Courses") . "</b><br>
  761. " . t("These courses have had their default transfer equivalencies removed.
  762. ") . "</div>";
  763. $html = str_replace("<!--TRANS_UN_COURSES-->",$mtitle,$html);
  764. $html .= "</div>";
  765. $render['section_trans_un_courses'] = array(
  766. 'value' => $html,
  767. 'weight' => 400,
  768. );
  769. }
  770. ////////////////////////////////////
  771. //// Moved Courses...
  772. $m_is_empty = TRUE;
  773. $html = "<!--MOVEDCOURSES-->";
  774. $this->student->list_courses_taken->sort_alphabetical_order();
  775. $this->student->list_courses_taken->reset_counter();
  776. while($this->student->list_courses_taken->has_more())
  777. {
  778. $c = $this->student->list_courses_taken->get_next();
  779. // Skip courses which haven't had anything moved.
  780. if ($c->group_list_unassigned->is_empty == true) {
  781. continue;
  782. }
  783. if ($c->course_id > 0)
  784. { $c->load_descriptive_data(); }
  785. $l_s_i = $c->subject_id;
  786. $l_c_n = $c->course_num;
  787. $l_term = $c->get_term_description(true);
  788. $c->group_list_unassigned->reset_counter();
  789. while($c->group_list_unassigned->has_more()) {
  790. $html .= "<div class=' ' style='padding-left: 10px; padding-bottom: 5px;
  791. margin-left: 1.5em; text-indent: -1.5em;'>
  792. $l_s_i $l_c_n (" . $c->get_hours_awarded() . " " . t("hrs") . ") - $c->grade - $l_term
  793. ";
  794. $group = $c->group_list_unassigned->get_next();
  795. $group->load_descriptive_data();
  796. $group_title = "";
  797. $degree_title = "";
  798. if ($group->req_by_degree_id != 0) {
  799. $tdeg = new DegreePlan();
  800. $tdeg->degree_id = $group->req_by_degree_id;
  801. $degree_title = " (" . $tdeg->get_title2(FALSE, TRUE) . ")";
  802. }
  803. if ($group->group_id > 0)
  804. {
  805. $group_title = "<i>$group->title</i>";
  806. } else {
  807. $group_title = t("the degree plan");
  808. }
  809. $html .= t("was removed from") . " $group_title$degree_title.";
  810. $html .= "</div>";
  811. }
  812. $m_is_empty = false;
  813. $is_empty = false;
  814. }
  815. if ($m_is_empty == false)
  816. {
  817. $mtitle = "<div style='padding-bottom: 10px;'>
  818. <div style='padding-bottom: 5px;' class='moved-courses'>
  819. <b>" . t("Moved Courses") . "</b><br>
  820. " . t("These courses have been moved out of their
  821. original positions on your degree plan.") . "</div>";
  822. $html = str_replace("<!--MOVEDCOURSES-->",$mtitle,$html);
  823. $html .= "</div>";
  824. $render['section_moved_courses'] = array(
  825. 'value' => $html,
  826. 'weight' => 410,
  827. );
  828. }
  829. // For admins only....
  830. if (user_has_permission("can_substitute") && $bool_include_box_top) {
  831. if ($this->bool_print != true)
  832. {// Don't display in print view.
  833. $purl = fp_url("advise/popup-toolbox/transfers");
  834. $html = "<div class='admin-toolbox-link-wrapper'>
  835. <a href='javascript: popupSmallIframeDialog(\"" . $purl . "\",\"" . t("Administrator&#39;s Toolbox") . "\",\"\");'><img src='" . fp_theme_location() . "/images/toolbox.gif' border='0'>" . t("Administrator's Toolbox") . "</a>
  836. </div>";
  837. $is_empty = false;
  838. $render['section_administrator_toolbox_link'] = array(
  839. 'value' => $html,
  840. 'weight' => 700,
  841. );
  842. }
  843. }
  844. //$pC .= "</td></tr>";
  845. $render['tr_td_end'] = array(
  846. 'value' => "</td></tr>",
  847. 'weight' => 800,
  848. );
  849. if ($bool_include_box_top) {
  850. //$pC .= $this->draw_semester_box_bottom();
  851. $render['box_bottom'] = array(
  852. 'value' => $this->draw_semester_box_bottom(),
  853. 'weight' => 810,
  854. );
  855. }
  856. $output = fp_render_content($render, FALSE);
  857. if (!$is_empty)
  858. {
  859. $this->add_to_screen($output, "FOOTNOTES");
  860. }
  861. // Return so other functions can use this output, if needed.
  862. return $output;
  863. }
  864. /**
  865. * Used in the Toolbox popup, this will display content of the tab which
  866. * shows a student's substututions
  867. *
  868. * @return string
  869. */
  870. function display_toolbox_substitutions()
  871. {
  872. $pC = "";
  873. // This will display the substitution management screen.
  874. $pC .= fp_render_section_title(t("Manage Substitutions"));
  875. $pC .= "<div class=' manage-substitutions-wrapper'>
  876. " . t("The following substitutions have been made for this student:") . "
  877. <br><br>
  878. ";
  879. $is_empty = true;
  880. $this->student->list_substitutions->reset_counter();
  881. while ($this->student->list_substitutions->has_more())
  882. {
  883. $substitution = $this->student->list_substitutions->get_next();
  884. $db_substitution_id = $substitution->db_substitution_id;
  885. $course_requirement = $substitution->course_requirement;
  886. $subbed_course = $substitution->course_list_substitutions->get_first();
  887. $assigned_to_degree_id = $substitution->assigned_to_degree_id;
  888. $sub_s_i = $subbed_course->subject_id;
  889. $sub_c_n = $subbed_course->course_num;
  890. $cr_s_i = $course_requirement->subject_id;
  891. $cr_c_n = $course_requirement->course_num;
  892. $cr_hrs = $course_requirement->get_hours();
  893. $in_group = ".";
  894. //if ($subbed_course->assigned_to_group_id > 0)
  895. //if ($subbed_course->get_first_assigned_to_group_id() != "")
  896. if ($substitution->db_required_group_id != "")
  897. {
  898. $new_group = new Group();
  899. //$new_group->group_id = $subbed_course->assigned_to_group_id;
  900. //$new_group->group_id = $subbed_course->get_first_assigned_to_group_id();
  901. $new_group->group_id = $substitution->db_required_group_id;
  902. $new_group->load_descriptive_data();
  903. $in_group = " in $new_group->title.";
  904. }
  905. $sub_action = t("was substituted for");
  906. $sub_trans_notice = "";
  907. if ($substitution->bool_group_addition == true)
  908. {
  909. $sub_action = t("was added to");
  910. $cr_s_i = $cr_c_n = "";
  911. $in_group = str_replace("in","",$in_group);
  912. }
  913. if ($subbed_course->bool_transfer == true && is_object($subbed_course->course_transfer))
  914. {
  915. $sub_s_i = $subbed_course->course_transfer->subject_id;
  916. $sub_c_n = $subbed_course->course_transfer->course_num;
  917. $sub_trans_notice = "[" . t("transfer") . "]";
  918. }
  919. $extra = $by = $remarks = "";
  920. $temp = $this->db->get_substitution_details($db_substitution_id);
  921. $by = $this->db->get_faculty_name($temp["faculty_id"], false);
  922. $remarks = $temp["remarks"];
  923. $ondate = format_date($temp["posted"]);
  924. if ($by != "")
  925. {
  926. $by = " <br>&nbsp; &nbsp; " . t("Substitutor:") . " $by.
  927. <br>&nbsp; &nbsp; <i>$ondate.</i>";
  928. }
  929. if ($remarks != "")
  930. {
  931. $remarks = " <br>&nbsp; &nbsp; " . t("Remarks:") . " <i>$remarks</i>.";
  932. }
  933. // If the sub'd course had ghost hours, make a note of that.
  934. if ($subbed_course->bool_ghost_hour) {
  935. $subbed_course->substitution_hours = "0 (1 ghost) ";
  936. }
  937. if ($substitution->bool_outdated)
  938. {
  939. $extra .= " <span style='color:red'>[OUTDATED: ";
  940. $extra .= $substitution->outdated_note;
  941. $extra .= "]</span>";
  942. }
  943. $substitution_hours = $subbed_course->get_substitution_hours($assigned_to_degree_id);
  944. $pC .= "<div class=' toolbox-remove-sub-wrapper' style='margin-bottom: 20px;'>
  945. $sub_s_i $sub_c_n $sub_trans_notice ($substitution_hours " . t("hrs") . ") $sub_action
  946. $cr_s_i $cr_c_n$in_group $by$remarks $extra
  947. <br>
  948. <a href='javascript: popupRemoveSubstitution(\"$db_substitution_id\");'>" . t("Remove substitution?") . "</a>
  949. </div>";
  950. $is_empty = false;
  951. }
  952. if ($is_empty == true)
  953. {
  954. $pC .= "<div align='center'>" . t("No substitutions have been made for this student.") . "</div>";
  955. }
  956. $pC .= "</div>";
  957. watchdog("toolbox", "substitutions", array(), WATCHDOG_DEBUG);
  958. return $pC;
  959. }
  960. /**
  961. * Used in the Toolbox popup, this will display content of the tab which
  962. * shows a student's transfers
  963. *
  964. * @return string
  965. */
  966. function display_toolbox_transfers()
  967. {
  968. $pC = "";
  969. // This will display the substitution management screen.
  970. $pC .= fp_render_section_title(t("Manage Transfer Equivalencies"));
  971. $pC .= "<div class=' '>
  972. " . t("This student has the following transfer credits and equivalencies.") . "
  973. <br><br>
  974. ";
  975. $is_empty = true;
  976. $student_id = $this->student->student_id;
  977. $school_id = db_get_school_id_for_student_id($student_id);
  978. $retake_grades = csv_to_array(variable_get_for_school("retake_grades", "F,W", $school_id));
  979. $this->student->list_courses_taken->sort_alphabetical_order(false, true);
  980. $this->student->list_courses_taken->reset_counter();
  981. while($this->student->list_courses_taken->has_more())
  982. {
  983. $c = $this->student->list_courses_taken->get_next();
  984. // Skip non transfer credits.
  985. if ($c->bool_transfer != true)
  986. {
  987. continue;
  988. }
  989. if ($c->course_id > 0)
  990. {
  991. $c->load_descriptive_data();
  992. }
  993. $course = $c->course_transfer;
  994. $course->load_descriptive_transfer_data();
  995. $l_s_i = $c->subject_id;
  996. $l_c_n = $c->course_num;
  997. $l_title = $this->fix_course_title($c->title);
  998. $t_s_i = $course->subject_id;
  999. $t_c_n = $course->course_num;
  1000. $t_term = $c->get_term_description(true);
  1001. $grade = $c->grade;
  1002. if (in_array($grade, $retake_grades)) {
  1003. $grade = "<span style='color: red;'>$grade</span>";
  1004. }
  1005. $t_inst = $this->fix_institution_name($course->institution_name);
  1006. $pC .= "<div class=' ' style='padding-bottom: 15px;'>
  1007. <b>$t_s_i $t_c_n</b> (" . $c->get_hours_awarded() . " " . t("hrs") . ") - $grade - $t_term - $t_inst
  1008. ";
  1009. if (isset($c->bool_substitution) && $c->bool_substitution_split == true)
  1010. {
  1011. $pC .= "<div class=' '><b> +/- </b> This course's hours were split in a substitution.</div>";
  1012. }
  1013. $initials = variable_get_for_school("school_initials", "DEMO", $school_id);
  1014. // Does this course NOT have an equivalency?
  1015. if ($c->course_id == 0)
  1016. {
  1017. // But, has the eqv been removed? If so, display a link to restore it,
  1018. // if not, show a link to remove it!
  1019. if ($rC = $this->student->list_transfer_eqvs_unassigned->find_match($course))
  1020. {
  1021. // Yes, the eqv WAS removed (or unassigned)
  1022. $pC .= "<div class=' '>" . t("This course's @initials equivalency was removed for this student.", array("@initials" => $initials)) . "<br>
  1023. <a href='javascript: popupRestoreTransferEqv(\"$rC->db_unassign_transfer_id\")'>" . t("Restore?") . "</a></div>";
  1024. } else {
  1025. $pC .= "<div class=' '>" . t("@initials equivalency not yet entered (or is not applicable).", array("@initials" => $initials)) . "</div>";
  1026. }
  1027. } else {
  1028. // This course *DOES* have an equivalency.
  1029. $pC .= "<div class=' '>$initials eqv: $l_s_i $l_c_n - $l_title</div>";
  1030. $pC .= "<div>
  1031. <a href='javascript: popupUnassignTransferEqv(\"" . $course->course_id . "\");'>" . t("Remove this equivalency?") . "</a>
  1032. </div>";
  1033. }
  1034. $pC .= "</div>";
  1035. $is_empty = false;
  1036. }
  1037. if ($is_empty == true) {
  1038. $pC .= "<div align='center'>" . t("There are no transfer equivalencies for this student.") . "</div>";
  1039. }
  1040. $pC .= "</div>";
  1041. watchdog("toolbox", "transfers", array(), WATCHDOG_DEBUG);
  1042. return $pC;
  1043. }
  1044. /**
  1045. * Used in the Toolbox popup, this will display content of the tab which
  1046. * shows a student's courses which they have taken.
  1047. *
  1048. * @return string
  1049. */
  1050. function display_toolbox_courses()
  1051. {
  1052. $pC = "";
  1053. $ns = $os = $fan = $fat = "";
  1054. $pC .= fp_render_section_title(t("All Student Courses"));
  1055. $csid = @$_REQUEST["current_student_id"];
  1056. $school_id = db_get_school_id_for_student_id($csid);
  1057. $order = @$_REQUEST["order"];
  1058. if ($order == "name")
  1059. {
  1060. $ns = "font-weight: bold; text-decoration: none;";
  1061. $fan = " <i class='fa fa-angle-up' style='font-weight:bold;'></i>";
  1062. } else {
  1063. $os = "font-weight: bold; text-decoration: none;";
  1064. $fat = " <i class='fa fa-angle-down' style='font-weight:bold;'></i>";
  1065. }
  1066. /*
  1067. $pC .= "<div class=' '>
  1068. " . t("This window displays all of the student's courses
  1069. which FlightPath is able to load.") . "
  1070. <br><br>
  1071. " . t("Order by:") . " &nbsp; &nbsp;";
  1072. $pC .= l(t("Name"), "advise/popup-toolbox/courses", "order=name&current_student_id=$csid", array("style" => $ns)) . "&nbsp; &nbsp;";
  1073. $pC .= l(t("Term"), "advise/popup-toolbox/courses", "order=date&current_student_id=$csid", array("style" => $os));
  1074. */
  1075. $pC .= "
  1076. <table border='0' cellpadding='2' cellspacing='3'>
  1077. <tr>
  1078. <th colspan='2'>" . l(t("Name") . $fan, "advise/popup-toolbox/courses", "order=name&current_student_id=$csid", array("style" => $ns)) . "</th>
  1079. <th>Hr</th>
  1080. <th>Gr</th>
  1081. <th width=50>" . l(t("Term") . $fat, "advise/popup-toolbox/courses", "order=date&current_student_id=$csid", array("style" => $os)) . "</th>
  1082. <th>Attributes</th>
  1083. </tr>
  1084. ";
  1085. $is_empty = true;
  1086. if ($order == "name")
  1087. {
  1088. $this->student->list_courses_taken->sort_alphabetical_order();
  1089. } else {
  1090. $this->student->list_courses_taken->sort_most_recent_first();
  1091. }
  1092. $this->student->list_courses_taken->reset_counter();
  1093. while($this->student->list_courses_taken->has_more())
  1094. {
  1095. $c = $this->student->list_courses_taken->get_next();
  1096. if ($c->course_id > 0)
  1097. {
  1098. $c->load_descriptive_data();
  1099. }
  1100. $l_s_i = $c->subject_id;
  1101. $l_c_n = $c->course_num;
  1102. $eqv_line = "";
  1103. if (isset($c->course_transfer) && $c->course_transfer->course_id > 0)
  1104. {
  1105. if ($c->course_id > 0)
  1106. {
  1107. $eqv_line = "<tr>
  1108. <td colspan='8' class=' '
  1109. style='padding-left: 20px;'>
  1110. <i>*eqv to " . variable_get_for_school("school_initials", "DEMO", $school_id) . " $l_s_i $l_c_n</i></td>
  1111. </tr>";
  1112. }
  1113. $l_s_i = $c->course_transfer->subject_id;
  1114. $l_c_n = $c->course_transfer->course_num;
  1115. }
  1116. $l_title = $this->fix_course_title($c->title);
  1117. $l_term = $c->get_term_description(true);
  1118. $h = $c->get_hours_awarded();
  1119. if ($c->bool_ghost_hour) {
  1120. $h .= "(" . t("ghost") . "<a href='javascript:alertSubGhost()'>?</a>)";
  1121. }
  1122. $pC .= "<tr>
  1123. <td valign='top' class=' '>$l_s_i</td>
  1124. <td valign='top' class=' '>$l_c_n</td>
  1125. <td valign='top' class=' '>$h</td>
  1126. <td valign='top' class=' '>$c->grade</td>
  1127. <td valign='top' class=' '>$c->term_id</td>
  1128. ";
  1129. $pC .= "<td valign='top' class=' '>";
  1130. if ($c->bool_transfer) {$pC .= "T ";}
  1131. //if ($c->bool_substitution) {$pC .= "S ";}
  1132. if ($c->get_bool_substitution()) {$pC .= "S ";}
  1133. if ($c->get_has_been_assigned_to_any_degree())
  1134. {
  1135. $pC .= "A:";
  1136. //////////////////////////////
  1137. // List all the groups/degrees this course has been assigned to!
  1138. if ($c->get_first_assigned_to_group_id() == "")
  1139. {
  1140. $pC .= "degree plan";
  1141. }
  1142. else {
  1143. $temp_group = new Group();
  1144. //$temp_group->group_id = $c->assigned_to_group_id;
  1145. $temp_group->group_id = $c->get_first_assigned_to_group_id();
  1146. $temp_group->load_descriptive_data();
  1147. $pC .= $temp_group->title;
  1148. }
  1149. }
  1150. $pC .= "</td>";
  1151. $pC .= "</tr>$eqv_line";
  1152. $is_empty = false;
  1153. }
  1154. if ($is_empty == true)
  1155. {
  1156. $pC .= "<div align='center'>" . t("No courses have been moved for this student.") . "</div>";
  1157. }
  1158. $pC .= "</table>";
  1159. $pC .= "</div>";
  1160. $pC .= "<hr><p>" . t("Attrib Legend: T = Transfer credit, A = Assigned to (group or degree plan)") . "</p>";
  1161. watchdog("toolbox", "courses", array(), WATCHDOG_DEBUG);
  1162. return $pC;
  1163. }
  1164. /**
  1165. * Used in the Toolbox popup, this will display content of the tab which
  1166. * shows a student's moved courses. That is, courses which have had
  1167. * their group memberships changed.
  1168. *
  1169. * @return string
  1170. */
  1171. function display_toolbox_moved()
  1172. {
  1173. $pC = "";
  1174. $pC .= fp_render_section_title(t("Manage Moved Courses"));
  1175. $pC .= "<div class=' '>
  1176. " . t("This student has the following course movements.") . "
  1177. <br><br>
  1178. ";
  1179. $is_empty = true;
  1180. $this->student->list_courses_taken->sort_alphabetical_order();
  1181. $this->student->list_courses_taken->reset_counter();
  1182. while($this->student->list_courses_taken->has_more())
  1183. {
  1184. $c = $this->student->list_courses_taken->get_next();
  1185. // Skip courses which haven't had anything moved.
  1186. if ($c->group_list_unassigned->is_empty == true)
  1187. {
  1188. continue;
  1189. }
  1190. if ($c->course_id > 0)
  1191. {
  1192. $c->load_descriptive_data();
  1193. }
  1194. $l_s_i = $c->subject_id;
  1195. $l_c_n = $c->course_num;
  1196. $l_title = $this->fix_course_title($c->title);
  1197. $l_term = $c->get_term_description(true);
  1198. $h = $c->get_hours_awarded();
  1199. if ($c->bool_ghost_hour) {
  1200. $h .= " [" . t("ghost") . "<a href='javascript:alertSubGhost();'>?</a>] ";
  1201. }
  1202. $pC .= "<div class=' ' style='padding-bottom: 15px;'>
  1203. <b>$l_s_i $l_c_n</b> ($h " . t("hrs") . ") - $c->grade - $l_term
  1204. ";
  1205. $c->group_list_unassigned->reset_counter();
  1206. while($c->group_list_unassigned->has_more())
  1207. {
  1208. $group = $c->group_list_unassigned->get_next();
  1209. $group->load_descriptive_data();
  1210. $group_title = "";
  1211. if ($group->group_id > 0)
  1212. {
  1213. $group_title = "<i>$group->title</i>";
  1214. } else {
  1215. $group_title = t("the degree plan");
  1216. }
  1217. $degree_title = "";
  1218. if ($group->req_by_degree_id != 0) {
  1219. $tdeg = new DegreePlan();
  1220. $tdeg->degree_id = $group->req_by_degree_id;
  1221. $degree_title = " (" . $tdeg->get_title2(FALSE, TRUE) . ")";
  1222. }
  1223. $pC .= "<div class=' '>" . t("This course was removed from") . " $group_title$degree_title.<br>
  1224. <a href='javascript: popupRestoreUnassignFromGroup(\"$group->db_unassign_group_id\")'>" . t("Restore?") . "</a>
  1225. </div>
  1226. ";
  1227. }
  1228. $pC .= "</div>";
  1229. $is_empty = false;
  1230. }
  1231. if ($is_empty == true)
  1232. {
  1233. $pC .= "<div align='center'>" . t("No courses have been moved for this student.") . "</div>";
  1234. }
  1235. $pC .= "</div>";
  1236. watchdog("toolbox", "moved", array(), WATCHDOG_DEBUG);
  1237. return $pC;
  1238. }
  1239. /**
  1240. * Constructs the HTML to show the student's test scores.
  1241. *
  1242. */
  1243. function build_test_scores()
  1244. {
  1245. // This function will build our Test Scores box.
  1246. // Only do this if the student actually has any test scores.
  1247. if ($this->student->list_standardized_tests->is_empty)
  1248. {
  1249. return;
  1250. }
  1251. $top_scores = array();
  1252. $pC = "";
  1253. $pC .= $this->draw_semester_box_top(t("Test Scores"), TRUE);
  1254. $pC .= "<tr><td colspan='8' class=' '>
  1255. ";
  1256. $fsC = "";
  1257. // Go through and find all the test scores for the student...
  1258. $this->student->list_standardized_tests->reset_counter();
  1259. while($this->student->list_standardized_tests->has_more()) {
  1260. $st = $this->student->list_standardized_tests->get_next();
  1261. $extra_date_css = "";
  1262. if (!$st->bool_date_unavailable) {
  1263. $dt = strtotime($st->date_taken);
  1264. $ddate = format_date($dt, "just_date");
  1265. }
  1266. else {
  1267. // The date was not available!
  1268. $ddate = t("N/A");
  1269. $extra_date_css = " test-date-unavailable";
  1270. }
  1271. $fsC .= "<div class='test-section'>
  1272. <b class='test-description'>$st->description</b> - <span class='test-date $extra_date_css'>$ddate</span>
  1273. <ul>";
  1274. foreach($st->categories as $position => $cat_array)
  1275. {
  1276. $fsC .= "<li><span class='test-cat-desc'>{$cat_array["description"]}</span> - <span class='test-cat-score'>{$cat_array["score"]}</span></li>";
  1277. }
  1278. $fsC .= "</ul>
  1279. </div>";
  1280. }
  1281. $pC .= fp_render_c_fieldset($fsC, t("Click to view/hide standardized test scores"), TRUE);
  1282. $pC .= "</td></tr>";
  1283. $pC .= $this->draw_semester_box_bottom();
  1284. $this->add_to_screen($pC, "TEST_SCORES");
  1285. }
  1286. /**
  1287. * This function is used by the "build" functions most often. It very
  1288. * simply adds a block of HTML to an array called box_array.
  1289. *
  1290. * @param string $content_box
  1291. */
  1292. function add_to_screen($content_box, $index = "") {
  1293. if ($index == "") {
  1294. $this->box_array[] = $content_box;
  1295. }
  1296. else {
  1297. $this->box_array[$index] = $content_box;
  1298. }
  1299. }
  1300. /**
  1301. * This function calls the other "build" functions to assemble
  1302. * the View or What If tabs in FlightPath.
  1303. *
  1304. */
  1305. function build_screen_elements()
  1306. {
  1307. // This function will build & assemble all of the onscreen
  1308. // elements for the advising screen. It should be
  1309. // called before display_screen();
  1310. $this->build_semester_list();
  1311. $this->build_excess_credit();
  1312. $this->build_test_scores();
  1313. $this->build_transfer_credit();
  1314. // Should we add the graduate credit block?
  1315. if (variable_get("display_graduate_credits_block", "yes") == "yes") {
  1316. $this->build_graduate_credit();
  1317. }
  1318. if (!$this->bool_blank)
  1319. { // Don't show if this is a blank degree plan.
  1320. $this->build_footnotes();
  1321. $this->build_added_courses();
  1322. }
  1323. // invoke a hook, to give custom modules the chance to perform actions
  1324. // (or add blocks) to the advise screen after we have run this function.
  1325. invoke_hook("advise_build_screen_elements", array(&$this));
  1326. }
  1327. /**
  1328. * This function is used to draw an individual pie chart box.
  1329. * It accepts values of top/bottom in order to come up
  1330. * with a percentage.
  1331. *
  1332. * @param string $title
  1333. *
  1334. * @param float $top_value
  1335. * - The top part of a ratio. Ex: for 1/2, $top_value = 1.
  1336. *
  1337. * @param float $bottom_value
  1338. * - The bottom part of a ratio. For 1/2, $bottom_value = 2.
  1339. * - Do not let this equal zero. If it does, the calculation
  1340. * for the pie chart will never be evaluated.
  1341. * @param string $pal
  1342. * - Which palette to use for the pie chart. If set, fore_col will be ignored in the argument list.
  1343. * - Acceptable values:
  1344. * - core
  1345. * - major
  1346. * - cumulative
  1347. * - student
  1348. * @param string $back_col
  1349. * - If $pal is left blank, the value here will be used for the "back" or "unfinished" color.
  1350. * @param string $fore_col
  1351. * - If $pal is left blank, the value here will be used for the "foreground" or "progress" color.
  1352. *
  1353. *
  1354. * @return string
  1355. */
  1356. function draw_pie_chart_box($title, $top_value, $bottom_value, $pal = "", $back_col = "", $fore_col = "", $extra = "")
  1357. {
  1358. $rtn = "";
  1359. $val = 0;
  1360. if ($bottom_value > 0) {
  1361. $val = round(($top_value / $bottom_value)*100);
  1362. }
  1363. if ($val > 100) { $val = 100; }
  1364. $leftval = 100 - $val;
  1365. if ($back_col == "") $back_col = "660000";
  1366. if ($fore_col == "") $fore_col = "FFCC33";
  1367. if ($pal == "major") {
  1368. $fore_col = "93D18B";
  1369. }
  1370. if ($pal == "cumulative") {
  1371. $fore_col = "5B63A5";
  1372. }
  1373. // Remove # from colors, if needed.
  1374. $fore_col = str_replace("#", "", $fore_col);
  1375. $back_col = str_replace("#", "", $back_col);
  1376. $vval = $val;
  1377. if ($vval < 1) $vval = 1;
  1378. // Create a graph using our built-in pchart api:
  1379. // First, establish a token to we know the script is being called from US:
  1380. if (!isset($_SESSION["fp_pie_chart_token"])) {
  1381. $_SESSION["fp_pie_chart_token"] = md5(fp_token());
  1382. }
  1383. //old Google API url: $pie_chart_url = "https://chart.googleapis.com/chart?cht=p&chd=t:$vval,$leftval&chs=75x75&chco=$fore_col|$back_col&chp=91.1";
  1384. $pie_chart_url = base_url() . "/libraries/pchart/fp_pie_chart.php?progress=$vval&unfinished=$leftval&unfinished_col=$back_col&progress_col=$fore_col&token=" . $_SESSION["fp_pie_chart_token"];
  1385. $rtn .= "<table border='0' width='100%' height='100' class='pie-chart-individual-table pie-chart-individual-table-" . fp_get_machine_readable(strtolower($title)) . "' cellpadding='0' cellspacing='0' >
  1386. <tr class='pie-chart-title-tr'>
  1387. <td class='pie-chart-box-title-td' align='center' height='20'>
  1388. " . fp_render_section_title($title, 'pie-chart-box-section') . "
  1389. </td>
  1390. </tr>
  1391. <tr class='pie-chart-inner-table-tr'>
  1392. <td class='pie-chart-inner-table-td'>
  1393. <table border='0' class='pie-chart-chart-table'>
  1394. <td class='pie-visualization'>
  1395. <img src='$pie_chart_url'>
  1396. </td>
  1397. <td class='pie-values'>
  1398. <div class='pie-val-percent'>
  1399. <span class='pie-val-percent-complete'>$val% <span class='pie-v-cap'>" . t("Complete") . "</span></span>
  1400. </div>
  1401. <div class='pie-val-top-bottom'>
  1402. ( <span class='pie-val-top-val'>$top_value</span>
  1403. / <span class='pie-val-bottom-val'>$bottom_value <span class='pie-v-cap'>" . t("hours") . "</span></span> )
  1404. </div>
  1405. $extra";
  1406. $rtn .= "
  1407. </td>
  1408. </table>
  1409. </td>
  1410. </tr>
  1411. </table>
  1412. ";
  1413. return $rtn;
  1414. }
  1415. /**
  1416. * This function calls drawPieChart to construct the student's 3
  1417. * progress pie charts.
  1418. *
  1419. * @return string
  1420. */
  1421. function draw_progress_boxes()
  1422. {
  1423. global $user;
  1424. // Draw the boxes for student progress (where
  1425. // the pie charts go!)
  1426. $rtn = "";
  1427. if (!$this->db) {
  1428. $this->db = get_global_database_handler();
  1429. }
  1430. $bool_charts_are_hidden = FALSE;
  1431. // have we already calculated this degree's data?
  1432. if (@$this->degree_plan->bool_calculated_progess_hours != TRUE)
  1433. {
  1434. // Only bother to get the types calculations needed for the piecharts
  1435. // Get the requested piecharts from our config...
  1436. $types = array();
  1437. $temp = variable_get_for_school("pie_chart_config", "c ~ Core Requirements\nm ~ Major Requirements\ndegree ~ Degree Progress", $this->student->school_id);
  1438. $lines = explode("\n", $temp);
  1439. foreach ($lines as $line) {
  1440. if (trim($line) == "") continue;
  1441. $temp = explode("~", $line);
  1442. $requirement_type = trim($temp[0]);
  1443. $types[$requirement_type] = trim($temp[1]);
  1444. }
  1445. $this->degree_plan->calculate_progress_hours(FALSE, $types);
  1446. $this->degree_plan->calculate_progress_quality_points(FALSE, $types);
  1447. }
  1448. // Create a "theme" array for later use.
  1449. $pie_chart_theme_array = array();
  1450. $pie_chart_theme_array["screen"] = $this;
  1451. $pie_chart_theme_array["student"] = $this->student;
  1452. $pie_chart_theme_array["degree_plan"] = $this->degree_plan;
  1453. // Get the requested piecharts from our config...
  1454. $temp = variable_get_for_school("pie_chart_config", "c ~ Core Requirements\nm ~ Major Requirements\ndegree ~ Degree Progress", $this->student->school_id);
  1455. $config_lines = explode("\n", $temp);
  1456. // Go through each of the degrees we have piecharts for
  1457. foreach ($this->degree_plan->gpa_calculations as $degree_id => $val) {
  1458. $dp = new DegreePlan();
  1459. $dp->degree_id = $degree_id;
  1460. if ($degree_id > 0) {
  1461. $dp->load_descriptive_data();
  1462. $d_title = $dp->get_title2(FALSE, TRUE);
  1463. $d_code = fp_get_machine_readable($dp->major_code);
  1464. }
  1465. else {
  1466. // Degree_id == 0, so this is the "overall" degree.
  1467. $d_title = t("Overall Progress");
  1468. $d_code = "PIE_OVERALL_PROGRESS";
  1469. }
  1470. // Add to our theme array.
  1471. $pie_chart_theme_array["degree_rows"][$degree_id] = array(
  1472. "degree_id" => $degree_id,
  1473. "row_label" => $d_title,
  1474. "row_classes" => "",
  1475. "degree_plan" => $dp,
  1476. "degree_major_code_machine" => $d_code,
  1477. "bool_display" => TRUE,
  1478. );
  1479. foreach ($config_lines as $line) {
  1480. if (trim($line) == "") continue;
  1481. $temp = explode("~", $line);
  1482. $requirement_type = trim($temp[0]);
  1483. $label = trim($temp[1]);
  1484. $unfinished_col = @trim($temp[2]);
  1485. $progress_col = @trim($temp[3]);
  1486. if ($unfinished_col == "") $unfinished_col = "660000";
  1487. if ($progress_col == "") $progress_col = "FFCC33";
  1488. // Okay, let's see if this degreeplan even has any data on this requirement type.
  1489. $total_hours = $this->degree_plan->gpa_calculations[$degree_id][$requirement_type]["total_hours"]*1;
  1490. $fulfilled_hours = $this->degree_plan->gpa_calculations[$degree_id][$requirement_type]["fulfilled_hours"]*1;
  1491. $qpts = $this->degree_plan->gpa_calculations[$degree_id][$requirement_type]["qpts"]*1;
  1492. if (floatval($total_hours) == 0) continue; // no hours for this requirement type!
  1493. // Setting to display GPA
  1494. $gpa = $extra_gpa = "";
  1495. if (variable_get_for_school("pie_chart_gpa", "no", $this->student->school_id) == "yes") {
  1496. if ($this->degree_plan->gpa_calculations[$degree_id][$requirement_type]["qpts_hours"] > 0) {
  1497. $gpa = fp_truncate_decimals($qpts / $this->degree_plan->gpa_calculations[$degree_id][$requirement_type]["qpts_hours"], 3);
  1498. }
  1499. if ($gpa) {
  1500. $extra_gpa = "<div class='view-extra-gpa ' style='text-align: right; color: gray;'>GPA: $gpa</div>";
  1501. }
  1502. }
  1503. // If we are here, then there is indeed enough data to create a piechart!
  1504. // Generate the pie chart and add to our array, for later display.
  1505. $html = $this->draw_pie_chart_box($label,$fulfilled_hours, $total_hours, "", $unfinished_col, $progress_col, $extra_gpa);
  1506. $hide_pie_html = "$label: $fulfilled_hours / $total_hours";
  1507. // Will only display if we've set it above.
  1508. if ($gpa) {
  1509. $hide_pie_html .= " ($gpa)";
  1510. }
  1511. $pie_chart_html_array[] = array(
  1512. "pie" => $html,
  1513. "hide_pie" => $hide_pie_html,
  1514. );
  1515. // Add to our theme array
  1516. $pie_chart_theme_array["degree_rows"][$degree_id]["data"][$requirement_type] = array(
  1517. "full_html" => $html,
  1518. "hide_pie_html" => $hide_pie_html,
  1519. "requirement_type" => $requirement_type,
  1520. "label" => $label,
  1521. "unfinished_col" => $unfinished_col,
  1522. "progress_col" => $progress_col,
  1523. "total_hours" => $total_hours,
  1524. "fulfilled_hours" => $fulfilled_hours,
  1525. "qpts" => $qpts,
  1526. "bool_display" => TRUE,
  1527. "pie_classes" => '',
  1528. );
  1529. } // foreach $line (for piechart by type)
  1530. } //foreach $degree_id
  1531. //////////////////
  1532. // Send the pie_chart_theme_array to a hook for possible extra processing.
  1533. invoke_hook("theme_pie_charts", array(&$pie_chart_theme_array));
  1534. //////////////////
  1535. $prcount = 0;
  1536. $total_rows = count($pie_chart_theme_array["degree_rows"]);
  1537. $degree_classes = fp_get_degree_classifications();
  1538. // Now, cycle through all of the 'rows' of degrees we need to draw.
  1539. foreach ($pie_chart_theme_array["degree_rows"] as $degree_id => $details) {
  1540. if ($details["bool_display"] === FALSE) continue; // hide the entire row
  1541. // We also want to denote if this is part of a "combined" degree or not.
  1542. $extra_pie_trtd_class = "";
  1543. if ($this->degree_plan->is_combined_dynamic_degree_plan) {
  1544. $extra_pie_trtd_class .= "pie-combined-dynamic-degree-plan";
  1545. }
  1546. else {
  1547. $extra_pie_trtd_class .= "pie-single-degree-plan";
  1548. }
  1549. $degree_class = @$details['degree_plan']->degree_class;
  1550. if ($degree_class == "") $degree_class = "NOT_SET";
  1551. $degree_level_num = intval(@$degree_classes['machine_name_to_level_num'][$degree_class]);
  1552. $rtn .= "<tr class='pie-degree-row pie-degree-row-$degree_id pie-degree-row-class-$degree_class pie-total-rows-$total_rows pie-degree-row-degree-level-num-$degree_level_num pie-row-count-$prcount {$details['row_classes']}'><td colspan='2' class='$extra_pie_trtd_class'>
  1553. <div class='pie-row-label'>{$details["row_label"]}</div>";
  1554. $td_width = "";
  1555. if (@count($pie_chart_html_array) > 0) {
  1556. $td_width = round(100 / count($pie_chart_html_array));
  1557. }
  1558. if (!isset($user->settings["hide_charts"])) $user->settings["hide_charts"] = "";
  1559. if ($this->bool_force_pie_charts || ($user->settings["hide_charts"] != "hide" && $this->bool_blank == FALSE ))
  1560. { // Display the pie charts
  1561. $bool_charts_are_hidden = FALSE;
  1562. $rtn .= "
  1563. <div style='margin-bottom: 10px;' class='pies-wrapper'>
  1564. <table class='pie-chart-table' width='100%' cellspacing='0' cellpadding='0' border='0'>
  1565. <tr>
  1566. ";
  1567. $c = 0;
  1568. if (@isset($pie_chart_theme_array['degree_rows'][$degree_id]["data"])) {
  1569. foreach ($pie_chart_theme_array['degree_rows'][$degree_id]["data"] as $requirement_type => $val) {
  1570. $html = $val["full_html"];
  1571. if (@$val["bool_display"] === FALSE) continue; // this particular chart shouldn't be shown.
  1572. $style = @($c == count($pie_chart_html_array) - 1) ? "" : "padding-right:5px;";
  1573. $rtn .= "<td width='$td_width%' style='$style' class='td_full_pie td_full_pie_$requirement_type " . @$val["pie_classes"] . "'>
  1574. " . $html . "
  1575. </td>";
  1576. $c++;
  1577. }
  1578. }
  1579. $rtn .= " </table>";
  1580. $rtn .= "</div>"; // class pies-wrapper
  1581. }
  1582. else {
  1583. // Hide the charts!
  1584. $bool_charts_are_hidden = TRUE;
  1585. $rtn .= "
  1586. <table border='0' width='100%' class='pie-chart-table-hide-charts' cellpadding='0' cellspacing='0' >
  1587. <tr class='pie-hidden-charts-label-row'>
  1588. <td colspan='10' class='' align='center' height='20'>
  1589. " . fp_render_section_title(t("Progress"), 'hidden-pie-charts-section') . "
  1590. </td>
  1591. </tr>
  1592. <tr class='pie-hidden-charts-row'>";
  1593. $c = 0;
  1594. if (isset($pie_chart_theme_array['degree_rows'][$degree_id]["data"])) {
  1595. foreach ($pie_chart_theme_array['degree_rows'][$degree_id]["data"] as $requirement_type => $val) {
  1596. $html = $val["hide_pie_html"];
  1597. if ($val["bool_display"] === FALSE) continue; // this particular chart shouldn't be shown.
  1598. $rtn .= "<td width='$td_width%' align='center' class='td_hidden_pie td_hidden_pie_$requirement_type {$val["pie_classes"]} '>
  1599. " . $html . "
  1600. </td>";
  1601. $c++;
  1602. }
  1603. }
  1604. $rtn .= "
  1605. </tr>
  1606. </table>";
  1607. }
  1608. $rtn .= "</td></tr>";
  1609. $prcount++;
  1610. } // foreach degree_rows
  1611. return $rtn;
  1612. }
  1613. /**
  1614. * Will display the "public note" at the top of a degree. This
  1615. * was entred in Data Entry.
  1616. *
  1617. * @return string
  1618. */
  1619. function draw_public_note()
  1620. {
  1621. // This will display a "public note" to the user about
  1622. // this degree. The public note was entered in Data Entry.
  1623. if (count($this->degree_plan->public_notes_array) == 0)
  1624. {
  1625. return "";
  1626. }
  1627. $pC = "";
  1628. foreach ($this->degree_plan->public_notes_array as $degree_id => $note) {
  1629. if (trim($note) != "") {
  1630. $pC .= "<tr><td colspan='8'>
  1631. <div class=' '
  1632. style='border: 5px double #C1A599;
  1633. padding: 5px;
  1634. margin: 10px;'>
  1635. <b>" . t("Important Message:") . "</b> $note
  1636. </div>
  1637. </td></tr>";
  1638. }
  1639. }
  1640. return $pC;
  1641. }
  1642. /**
  1643. * This function generates the HTML to display the screen. Should
  1644. * be used in conjunction with output_to_browser()
  1645. *
  1646. * @return string
  1647. */
  1648. function display_screen()
  1649. {
  1650. // This will generate the html to display the screen.
  1651. $pC = "";
  1652. $school_id = db_get_school_id_for_student_id($this->student->student_id);
  1653. if (!$this->db) {
  1654. $this->db = get_global_database_handler();
  1655. }
  1656. if ($this->bool_hiding_grades && !$this->bool_print && variable_get_for_school("hiding_grades_message", '', $school_id) != "")
  1657. {
  1658. // Display the message about us hiding grades.
  1659. $pC .= "
  1660. <tr><td colspan='2'>
  1661. <div class=' hypo' style='margin-top: 4px; margin-bottom: 4px;
  1662. padding: 2px; border: 1px solid maroon;'>
  1663. <table border='0' cellspacing='0' cellpadding='0'>
  1664. <td valign='top'>
  1665. <img src='" . fp_theme_location() . "/images/alert_lg.gif' >
  1666. </td>
  1667. <td valign='middle' class=' ' style='padding-left: 8px;'>
  1668. " . variable_get_for_school("hiding_grades_message", "", $school_id) . "
  1669. </td>
  1670. </table>
  1671. </div>
  1672. </td></tr>
  1673. ";
  1674. }
  1675. //$pC .= $this->draw_currently_advising_box();
  1676. $pC .= $this->draw_progress_boxes();
  1677. $pC .= $this->draw_public_note();
  1678. $t = 0;
  1679. foreach ($this->box_array as $index => $box_array_contents) {
  1680. $align = "right";
  1681. if ($this->is_on_left)
  1682. {
  1683. $pC .= "<tr>";
  1684. $align= "left";
  1685. }
  1686. $css_index = fp_get_machine_readable($index);
  1687. $pC .= "<td valign='top' align='$align' class='fp-boxes fp-boxes-$css_index'>";
  1688. $pC .= $box_array_contents;
  1689. $pC .= "</td>";
  1690. if (!$this->is_on_left) // on right of page
  1691. {
  1692. $pC .= "</tr>";
  1693. }
  1694. $this->is_on_left = !$this->is_on_left;
  1695. }
  1696. if (!$this->is_on_left) // on right of the page.
  1697. { // close up any loose ends.
  1698. $pC .= "</tr>";
  1699. }
  1700. if (user_has_permission("can_advise_students"))
  1701. {
  1702. if (!$this->bool_print && !$this->bool_blank)
  1703. {
  1704. $pC .= "<tr>";
  1705. $pC .= "<td class='fp-boxes fp-boxes-blank'>&nbsp;</td>";
  1706. $render = array();
  1707. //$render['html'] = fp_render_button(t("Submit"),"submitSaveActive();");
  1708. $render['html'] = "<div class='buttons form-element element-type-submit'>
  1709. <input type='button' id='mainform_submit_btn' value='" . t("Submit") . "' onClick='submitSaveActive();'>
  1710. </div>";
  1711. invoke_hook("content_alter", array(&$render, 'advise_submit_button'));
  1712. $pC .= "<td class='fp-boxes fp-boxes-submit-button' align='center'>
  1713. <div class=' advise_submit_button_wrapper' style='margin-top:35px; margin-bottom:10px; padding: 10px;'>
  1714. " . $render['html'] . "
  1715. </div>
  1716. </td></tr>
  1717. ";
  1718. //$this->add_to_screen("<input type='button' value='Submit' onClick='submitSaveActive();'>");
  1719. }
  1720. }
  1721. return $pC;
  1722. }
  1723. /**
  1724. * Returns the HTML to draw a pretty button.
  1725. *
  1726. * @param string $title
  1727. * @param string $on_click
  1728. * @param bool $bool_padd
  1729. * @param string $style
  1730. * @return string
  1731. */
  1732. function draw_button($title, $on_click, $bool_padd = true, $style = "")
  1733. {
  1734. // Style is expected to look like:
  1735. // style='some:thing;'
  1736. // with SINGLE apostrophes! not quotes.
  1737. $on_mouse = "onmouseover='this.className=\"gradbutton gradbutton_hover hand\";'
  1738. onmouseout='this.className=\"gradbutton hand\";'
  1739. onmousedown='this.className=\"gradbutton gradbutton_down hand\";'
  1740. onmouseup='this.className=\"gradbutton gradbutton_hover hand\";'
  1741. ";
  1742. if ($bool_padd)
  1743. {
  1744. $padd = "&nbsp; &nbsp;";
  1745. }
  1746. $rtn = "<span class='gradbutton hand' onClick='$on_click' $on_mouse $style >
  1747. $padd $title $padd
  1748. </span>
  1749. ";
  1750. return $rtn;
  1751. }
  1752. /**
  1753. * Constructs the HTML to display the list of semesters for the student.
  1754. *
  1755. */
  1756. function build_semester_list() {
  1757. $list_semesters = $this->degree_plan->list_semesters;
  1758. // Go through each semester and add it to the screen...
  1759. $list_semesters->reset_counter();
  1760. while($list_semesters->has_more())
  1761. {
  1762. $semester = $list_semesters->get_next();
  1763. $semester->reset_list_counters();
  1764. if ($semester->semester_num == DegreePlan::SEMESTER_NUM_FOR_COURSES_ADDED)
  1765. { // These are the "added by advisor" courses. Skip them.
  1766. continue;
  1767. }
  1768. $semester->req_by_degree_id = $this->degree_plan->degree_id;
  1769. $disp_sem = $this->display_semester($semester, TRUE);
  1770. if ($disp_sem) {
  1771. $this->add_to_screen($disp_sem, "SEMESTER_" . $semester->semester_num);
  1772. }
  1773. }
  1774. }
  1775. /**
  1776. * This function is called when we know we are on a mobile
  1777. * browser. We have to handle tab rendering differently
  1778. * in order to make them all fit.
  1779. *
  1780. * @param unknown_type $tab_array
  1781. */
  1782. function z__draw_mobile_tabs($tab_array) {
  1783. $rtn = "";
  1784. $js_vars = "var mobileTabSelections = new Array(); ";
  1785. if (count($tab_array) <= 1) return "";
  1786. $rtn .= "<table border='0' width='200' cellpadding='0' cellspacing='0' class='fp-mobile-tabs'>
  1787. <td>
  1788. <b>Display: </b>";
  1789. /* if (count($tab_array) == 1) {
  1790. // Just one element, no need to render the select list.
  1791. $rtn .= $tab_array[0]["title"];
  1792. $rtn .= "</td></table>";
  1793. return $rtn;
  1794. }
  1795. */
  1796. $rtn .= "<select onChange='executeSelection()' id='mobileTabsSelect'>";
  1797. for ($t = 0; $t < count($tab_array); $t++)
  1798. {
  1799. $title = $tab_array[$t]["title"];
  1800. $active = $tab_array[$t]["active"];
  1801. $on_click = $tab_array[$t]["on_click"];
  1802. if ($title == "")
  1803. {
  1804. continue;
  1805. }
  1806. $sel = ($active == true) ? $sel = "selected":"";
  1807. $rtn .= "<option $sel value='$t'>$title</option>";
  1808. $js_vars .= "mobile_tab_selections[$t] = '$on_click'; \n";
  1809. }
  1810. $rtn .= "</select>
  1811. </td></table>";
  1812. $rtn .= '
  1813. <script type="text/javascript">
  1814. ' . $js_vars . '
  1815. function executeSelection() {
  1816. var sel = document.getElementById("mobileTabsSelect").value;
  1817. var statement = mobile_tab_selections[sel];
  1818. // Lets execute the statement...
  1819. eval(statement);
  1820. }
  1821. </script>
  1822. ';
  1823. return $rtn;
  1824. }
  1825. /**
  1826. * Displays the contents of the Descripton tab for the course popup.
  1827. *
  1828. * @param int $course_id
  1829. * - The course_id of the course to show. Leave blank if supplying
  1830. * the object instead.
  1831. *
  1832. * @param Course $course
  1833. * - The course object to display. Leave as NULL if supplying
  1834. * the course_id instead.
  1835. *
  1836. * @param Group $group
  1837. * - The Group object that this course has been placed into.
  1838. *
  1839. * @param bool $show_advising_buttons
  1840. * - Should we show the advising buttons in this popup? Would be
  1841. * set to false for student view, or for anyone who is not
  1842. * allowed to advise this course into a group for the student.
  1843. *
  1844. * @return string
  1845. */
  1846. function display_popup_course_description($course_id = "", Course $course = NULL, $group = NULL, $show_advising_buttons = FALSE)
  1847. {
  1848. $pC = "";
  1849. $db = $this->db;
  1850. if ($course_id != "" && $course_id != 0) {
  1851. $course = new Course($course_id);
  1852. }
  1853. // Set up our "render array" for later rendering, using the render API.
  1854. $render = array();
  1855. $render["#id"] = "AdvisingScreen_display_popup_course_description";
  1856. $render["#course"] = array(
  1857. 'type' => 'do_not_render',
  1858. 'value' => $course,
  1859. );
  1860. // Note: $render['#group'] is set lower in this function.
  1861. $db_group_requirement_id = @$_REQUEST["db_group_requirement_id"];
  1862. if ($course == null)
  1863. {
  1864. // No course available!
  1865. $render["no_course_selected"] = array(
  1866. "type" => "markup",
  1867. "value" => t("No course was selected. Please
  1868. click the Select tab at the top of the screen."),
  1869. "attributes" => array("style" => "margin-top: 13px;", "class" => " "),
  1870. );
  1871. $pC .= fp_render_content($render);
  1872. return $pC;
  1873. }
  1874. $school_id = $course->school_id;
  1875. // Not sure I need this line anymore.
  1876. $datastring_max_hours = $course->max_hours;
  1877. $datastring_bool_new_from_split = $course->get_bool_substitution_new_from_split();
  1878. $req_by_degree_id = $course->req_by_degree_id;
  1879. $advising_term_id = @$GLOBALS["fp_advising"]["advising_term_id"];
  1880. $course->load_descriptive_data(TRUE, TRUE, TRUE, FALSE, FALSE, FALSE);
  1881. $course_hours = $course->get_catalog_hours();
  1882. if ($course->bool_transfer)
  1883. {
  1884. // Nothing at the moment.
  1885. }
  1886. // Does this course have more than one valid (non-excluded) name?
  1887. $other_valid_names = "";
  1888. if (count($course->array_valid_names) > 1)
  1889. {
  1890. for ($t = 0; $t < count($course->array_valid_names); $t++)
  1891. {
  1892. $name = $course->array_valid_names[$t];
  1893. if ($name == "$course->subject_id~$course->course_num")
  1894. {
  1895. continue;
  1896. }
  1897. $other_valid_names .= ", " . str_replace("~"," ",$name);
  1898. }
  1899. }
  1900. $course->fix_title();
  1901. $initials = variable_get("school_initials", "DEMO", $school_id);
  1902. $pC .= "<!--EQV1-->";
  1903. $bool_transferEqv = true;
  1904. if ($course->bool_transfer)
  1905. {
  1906. // This is a transfer course. Begin by displaying the transfer credit's
  1907. // information.
  1908. $course->course_transfer->load_descriptive_transfer_data($this->student->student_id, $course->term_id);
  1909. $hrs = $course->course_transfer->get_hours()*1;
  1910. if ($hrs == 0)
  1911. {
  1912. $hrs = $course->get_hours();
  1913. }
  1914. // make transfer course titles all caps.
  1915. $course->course_transfer->title = strtoupper($course->course_transfer->title);
  1916. $html = "";
  1917. $html .= "<div style='margin-top: 13px;' class=' '>
  1918. <b>" . t("Transfer Credit Information:") . "</b><br>
  1919. <div style='margin-left: 20px;' class=' '>
  1920. " . t("Course:") . " " . $course->course_transfer->subject_id . " " . $course->course_transfer->course_num . "
  1921. - " . $course->course_transfer->title . " ($hrs " . t("hrs") . ")<br>
  1922. " . t("Institution:") . " " . $this->fix_institution_name($course->course_transfer->institution_name) . "<br>
  1923. " . t("Term:") . " " . $course->get_term_description() . "<br>
  1924. <!-- Grade: " . $course->grade . "<br> -->
  1925. ";
  1926. $transfer_eqv_text = $course->course_transfer->transfer_eqv_text;
  1927. if ($transfer_eqv_text == "") {
  1928. $transfer_eqv_text = t("Not entered or not applicable.");
  1929. $bool_transferEqv = false;
  1930. }
  1931. $html .= "$initials Eqv: $transfer_eqv_text<br>
  1932. </div>
  1933. </div>";
  1934. $render["transfer_credit_info"] = array(
  1935. "type" => "markup",
  1936. "value" => $html,
  1937. );
  1938. } // if course->bool_transfer
  1939. if ($course->course_id != 0)
  1940. {
  1941. $html = "";
  1942. $use_hours = $course_hours;
  1943. if ($course->bool_transfer)
  1944. {
  1945. $html .= "<b>$initials " . t("Equivalent Course Information:") . "</b><br>
  1946. <b>$course->subject_id $course->course_num</b> - ";
  1947. $new_course = new Course();
  1948. $new_course->course_id = $course->course_id;
  1949. $new_course->load_descriptive_data();
  1950. $use_hours = $new_course->get_catalog_hours();
  1951. }
  1952. // if this is a substitution, use the number of hours for the ORIGNAL course.
  1953. if ($course->get_bool_substitution() == TRUE) {
  1954. $sub_id = $course->db_substitution_id_array[$course->get_course_substitution()->req_by_degree_id];
  1955. $temp = $db->get_substitution_details($sub_id);
  1956. $sub_hours = @$temp['sub_hours'] * 1; // trim excess zeros with *1.
  1957. if ($sub_hours < $use_hours) {
  1958. $use_hours = $sub_hours;
  1959. }
  1960. }
  1961. $html .= "
  1962. <b>$course->subject_id $course->course_num - $course->title ($use_hours " . t("hrs") . ")</b>";
  1963. $render["course_title_line"] = array(
  1964. "type" => "markup",
  1965. "value" => $html,
  1966. "attributes" => array("style" => "margin-top: 13px; margin-bottom: 0;", "class" => " "),
  1967. "weight" => 10,
  1968. );
  1969. // If the course can be repeated for credit, show that information next.
  1970. if ($course->repeat_hours > $course->min_hours)
  1971. {
  1972. $html = t("May be repeated for up to @repeat hours of credit.", array("@repeat" => floatval($course->repeat_hours))); // floatval trims excess zeroes from display.
  1973. // if it is essentially infinite, then we just say it can be repeated for credit, period.
  1974. if ($course->repeat_hours > 20) {
  1975. $html = t("May be repeated for credit.");
  1976. }
  1977. $render["course_repeat_line"] = array(
  1978. "type" => "markup",
  1979. "value" => $html,
  1980. "attributes" => array("class" => " course-search-repeat"),
  1981. "weight" => 15,
  1982. );
  1983. }
  1984. } // if course->course_id != 0
  1985. if ($course->get_bool_substitution_new_from_split($req_by_degree_id) || $course->get_bool_substitution_split($req_by_degree_id))
  1986. {
  1987. $html = "";
  1988. $html .= "<div class=' ' style='margin-bottom:5px;'>
  1989. <i>" . t("This course's hours were split in a substitution.");
  1990. if ($course->get_bool_substitution_new_from_split()) {
  1991. $sub_remaining_hours = @$course->get_hours_awarded($req_by_degree_id);
  1992. $html .= "<br>" . t("Remaining hours after split:") . " $sub_remaining_hours " . t("hrs.") . "";
  1993. }
  1994. $html .= "</i>
  1995. <a href='javascript: alertSplitSub();'>?</a>
  1996. </div>";
  1997. $render["substitution_split"] = array(
  1998. "type" => "markup",
  1999. "value" => $html,
  2000. "weight" => 20,
  2001. );
  2002. }
  2003. if ($course->course_id != 0)
  2004. {
  2005. $render["course_description"] = array(
  2006. "type" => "markup",
  2007. "value" => $course->description,
  2008. "attributes" => array("class" => " "),
  2009. "weight" => 30,
  2010. );
  2011. }
  2012. // The -1 for get_bool_substitution means, is it being used in ANY substitution?
  2013. if ($course->bool_transfer == true && $course->course_id < 1 && $course->get_bool_substitution(-1) == FALSE)
  2014. { // No local eqv!
  2015. $html = "";
  2016. $html .= "<div class=' ' style='margin-top: 10px;'><b>Note:</b> ";
  2017. $pC = str_replace("<!--EQV1-->"," (" . t("Transfer Credit") . ")",$pC); // place the words "transfer credit" in the curved title line at the top.
  2018. if (!$bool_transferEqv)
  2019. {
  2020. $t_msg = t("This course does not have an assigned @initials equivalency, or the equivalency
  2021. has been removed for this student.
  2022. Ask your advisor if this course will count towards your degree.", array("@initials" => $initials)) . "
  2023. </div>";
  2024. }
  2025. else {
  2026. $t_msg = t("FlightPath cannot assign this course to a @initials equivalency on
  2027. the student's degree plan,
  2028. or the equivalency
  2029. has been removed for this student.
  2030. Ask your advisor if this course will count towards your degree.", array("@initials" => $initials)) . "
  2031. </div>";
  2032. }
  2033. $html .= $t_msg;
  2034. $render["course_transfer_no_eqv"] = array(
  2035. "type" => "markup",
  2036. "value" => $html,
  2037. "weight" => 40,
  2038. );
  2039. }
  2040. elseif ($course->bool_transfer == true && $course->course_id > 0 && $course->get_bool_substitution(-1) == FALSE)
  2041. { // Has a local eqv!
  2042. $html = "";
  2043. $t_s_i = $course->course_transfer->subject_id;
  2044. $t_c_n = $course->course_transfer->course_num;
  2045. /* $pC .= "<div class=' ' style='margin-top: 10px;'>
  2046. <b>Note:</b> The course listed above is equivalent
  2047. to <b>$t_s_i $t_c_n</b>,
  2048. which the student completed at <i>";
  2049. // Replace the temporary comment <!--EQV1--> in the header with
  2050. // the new eqv information.
  2051. */
  2052. $pC = str_replace("<!--EQV1-->"," (" . t("Transfer Credit") . " $t_s_i $t_c_n)",$pC);
  2053. // Admin function only.
  2054. if (user_has_permission("can_substitute"))
  2055. {
  2056. $html .= "<div align='left' class=' '>
  2057. <b>" . t("Special administrative function:") . "</b>
  2058. <a href='javascript: popupUnassignTransferEqv(\"" . $course->course_transfer->course_id . "\");'>" . t("Remove this equivalency?") . "</a></div>";
  2059. //$html .= "</div>"; // not sure what this went to. Commenting out.
  2060. }
  2061. //$pC .= "</div>"; // not sure what this went to... commenting out.
  2062. $render["course_transfer_local_eqv"] = array(
  2063. "type" => "markup",
  2064. "value" => $html,
  2065. "weight" => 50,
  2066. );
  2067. }
  2068. ////////////////////////////
  2069. // When was this student enrolled in this course?
  2070. $html = "";
  2071. if ($course->term_id != "" && $course->term_id != Course::COURSE_UNKNOWN_TERM_ID && $course->display_status != "eligible" && $course->display_status != "disabled")
  2072. {
  2073. $html .= "<div class=' ' style='margin-top: 10px;'>
  2074. " . t("The student enrolled in this course in") . " " . $course->get_term_description() . ".
  2075. </div>";
  2076. } else if ($course->term_id == Course::COURSE_UNKNOWN_TERM_ID)
  2077. {
  2078. $html .= "<div class=' ' style='margin-top: 10px;'>
  2079. " . t("The exact date that the student enrolled in this course
  2080. cannot be retrieved at this time. Please check the
  2081. student's official transcript for more details.") . "
  2082. </div>";
  2083. }
  2084. $render["when_enrolled"] = array(
  2085. "type" => "markup",
  2086. "value" => $html,
  2087. "weight" => 50,
  2088. );
  2089. ///////////////////////////////////
  2090. // Did the student earn a grade?
  2091. $html = "";
  2092. if ($course->grade != "") {
  2093. $grd = $course->grade;
  2094. $enrolled_grades = csv_to_array(variable_get_for_school("enrolled_grades",'E', $school_id));
  2095. if (in_array($grd, $enrolled_grades)) {
  2096. $html .= t("The student is currently enrolled in this course.", array("@grade" => $grd));
  2097. $render['enrolled_notice'] = array(
  2098. 'type' => 'markup',
  2099. 'value' => $html,
  2100. 'weight' => 54,
  2101. );
  2102. }
  2103. else {
  2104. if (trim($grd) != trim($course->db_grade)) {
  2105. $grd = "$course->db_grade ($grd)";
  2106. }
  2107. $disp_grade = $grd;
  2108. if (strstr($grd, "MID")) {
  2109. $disp_grade = str_replace("MID", "<span class='superscript'>mid</span>", $grd);
  2110. }
  2111. $html .= t("The student earned a grade of <strong>@grade</strong>.", array("@grade" => $disp_grade));
  2112. $render['earned_grade'] = array(
  2113. 'type' => 'markup',
  2114. 'value' => $html,
  2115. 'weight' => 55,
  2116. );
  2117. }
  2118. }
  2119. ////////////////////////////////
  2120. // Conditions on which this will even appear? Like only if the student has more than one degree selected?
  2121. // What degrees is this course fulfilling?
  2122. if (count($course->assigned_to_degree_ids_array) > 0) {
  2123. $html = "";
  2124. $html .= "<div class=' course-description-assigned-to-degrees'>
  2125. " . t("This course is fulfilling a requirement for: ");
  2126. $c = "";
  2127. $d = "";
  2128. foreach ($course->assigned_to_degree_ids_array as $degree_id) {
  2129. $d .= $degree_id . ",";
  2130. $t_degree_plan = new DegreePlan();
  2131. $t_degree_plan->degree_id = $degree_id;
  2132. $c .= "<span>" . $t_degree_plan->get_title2(FALSE, TRUE) . "</span>, ";
  2133. }
  2134. $c = rtrim($c, ", ");
  2135. $html .= "$c</div>";
  2136. $render["fulfilling_reqs_for_degrees"] = array(
  2137. "type" => "markup",
  2138. "value" => $html,
  2139. "weight" => 60,
  2140. );
  2141. // Also keep track of what degree ids we are fulfilling reqs for, in case we need it later.
  2142. $render["#fulfilling_reqs_for_degree_ids"] = array(
  2143. "type" => "do_not_render",
  2144. "value" => $d,
  2145. );
  2146. }
  2147. ////////////////
  2148. // Is this course assigned to a group?
  2149. if ($course->disp_for_group_id != "" && $course->grade != "" && $course->bool_transfer != true && $course->get_bool_substitution($course->req_by_degree_id) != TRUE)
  2150. {
  2151. $html = "";
  2152. $g = new Group();
  2153. $g->group_id = $course->disp_for_group_id;
  2154. $g->load_descriptive_data();
  2155. $html .= "<div class=' ' style='margin-top: 10px;'>
  2156. <img src='" . fp_theme_location() . "/images/icons/$g->icon_filename' width='19' height='19'>
  2157. &nbsp;
  2158. " . t("This course is a member of") . " $g->title.
  2159. ";
  2160. // If user is an admin...
  2161. if (user_has_permission("can_substitute")) {
  2162. $tflag = intval($course->bool_transfer);
  2163. $html .= "<div align='left' class=' '>
  2164. <b>" . t("Special administrative function:") . "</b>
  2165. <a href='javascript: popupUnassignFromGroup(\"$course->course_id\",\"$course->term_id\",\"$tflag\",\"$g->group_id\",\"$req_by_degree_id\");'>" . t("Remove from this group?") . "</a></div>";
  2166. $html .= "</div>";
  2167. }
  2168. $render["course_assigned_to_group"] = array(
  2169. "type" => "markup",
  2170. "value" => $html,
  2171. "weight" => 70,
  2172. );
  2173. $render["#group"] = $g;
  2174. }
  2175. else if ($course->grade != "" && $course->bool_transfer != true && $course->get_bool_substitution($course->req_by_degree_id) != TRUE && $course->get_has_been_assigned_to_degree_id()) {
  2176. // Course is not assigned to a group; it's on the bare degree plan. group_id = 0.
  2177. // If user is an admin...
  2178. $html = "";
  2179. if (user_has_permission("can_substitute"))
  2180. {
  2181. $tflag = intval($course->bool_transfer);
  2182. $html .= "<div align='left' class=' '>
  2183. <b>" . t("Special administrative function:") . "</b>
  2184. <a href='javascript: popupUnassignFromGroup(\"$course->course_id\",\"$course->term_id\",\"$tflag\",\"0\",\"$req_by_degree_id\");'>" . t("Unassign fulfillment?") . "</a></div>";
  2185. $html .= "</div>";
  2186. }
  2187. $render["course_not_assigned_to_group"] = array(
  2188. "type" => "markup",
  2189. "value" => $html,
  2190. "weight" => 80,
  2191. );
  2192. }
  2193. // Substitutors get extra information:
  2194. if (user_has_permission("can_substitute") && $course->get_first_assigned_to_group_id()) {
  2195. $html = "";
  2196. $html .= "
  2197. <span id='viewinfolink'
  2198. onClick='document.getElementById(\"admin_info\").style.display=\"\"; this.style.display=\"none\"; '
  2199. class='hand' style='color: blue;'
  2200. > - " . t("Click to show") . " -</span>
  2201. <div style='padding-left: 20px; display:none;' id='admin_info'>
  2202. Groups this course has been assigned to:
  2203. ";
  2204. // Course is assigned to a group.
  2205. // might be assigned to multiple groups, so show them in a loop
  2206. if ($course->get_first_assigned_to_group_id()) {
  2207. foreach ($course->assigned_to_group_ids_array as $group_id) {
  2208. $group = new Group();
  2209. $group->group_id = $group_id;
  2210. $group->load_descriptive_data();
  2211. $html .= "<div>
  2212. " . t("Course is assigned to group:") . "<br>
  2213. &nbsp; " . t("Group ID:") . " $group->group_id<br>
  2214. &nbsp; " . t("Title:") . " $group->title<br>";
  2215. $html .= "&nbsp; <i>" . t("Internal name:") . " $group->group_name</i><br>";
  2216. $html .= "&nbsp; " . t("Catalog year:") . " $group->catalog_year
  2217. </div>";
  2218. }
  2219. }
  2220. $html .= "
  2221. </div>";
  2222. $render["substitutor_extra"] = array(
  2223. "type" => "markup",
  2224. "label" => ("Special administrative information:"),
  2225. "value" => $html,
  2226. "weight" => 90,
  2227. "attributes" => array("class" => " "),
  2228. );
  2229. }
  2230. // Has the course been substituted into *this* degree plan?
  2231. if ($course->get_bool_substitution() == TRUE)
  2232. {
  2233. $html = "";
  2234. // Find out who did it and if they left any remarks.
  2235. $db = $this->db;
  2236. $sub_id = $course->db_substitution_id_array[$course->get_course_substitution()->req_by_degree_id];
  2237. $temp = $db->get_substitution_details($sub_id);
  2238. $required_degree_id = $temp["required_degree_id"];
  2239. $req_degree_plan = new DegreePlan();
  2240. $req_degree_plan->degree_id = $required_degree_id;
  2241. $by = $db->get_faculty_name($temp["faculty_id"], false);
  2242. $remarks = $temp["remarks"];
  2243. $ondate = format_date($temp["posted"], "", "n/d/Y");
  2244. if ($by != "") {
  2245. $by = " by $by, on $ondate.";
  2246. }
  2247. if ($remarks != "")
  2248. {
  2249. $remarks = " " . t("Substitution remarks:") . " <i>$remarks</i>.";
  2250. }
  2251. $forthecourse = t("for the original course
  2252. requirement of") . " <b>" . $course->get_course_substitution()->subject_id . "
  2253. " . $course->get_course_substitution()->course_num . " (" . $course->get_course_substitution()->get_hours() . " " . t("hrs") . ")</b>";
  2254. if ($temp["required_course_id"]*1 == 0)
  2255. {
  2256. $forthecourse = "";
  2257. }
  2258. $html .= "<div class=' ' style='margin-top: 10px;'>
  2259. <b>" . t("Note:") . "</b> " . t("This course was substituted into the %title
  2260. degree plan", array("%title" => $req_degree_plan->get_title2())) . " $forthecourse
  2261. $by$remarks";
  2262. if (user_has_permission("can_substitute")) {
  2263. $html .= "<div align='left' class=' ' style='padding-left: 10px;'>
  2264. <b>" . t("Special administrative function:") . "</b>
  2265. <a href='javascript: popupRemoveSubstitution(\"$sub_id\");'>" . t("Remove substitution?") . "</a>
  2266. </div>";
  2267. }
  2268. $render["course_sub_this_degree_plan"] = array(
  2269. "type" => "markup",
  2270. "value" => $html,
  2271. "weight" => 100,
  2272. );
  2273. }
  2274. // Variable hours? Only show if the course has not been taken...
  2275. $var_hours_default = "";
  2276. if ($course->has_variable_hours() && $course->grade == "")
  2277. {
  2278. $html = "";
  2279. $html .= "<div class=' '>
  2280. " . t("This course has variable hours. Please select
  2281. how many hours this course will be worth:") . "<br>
  2282. <div style='text-align: center;'>
  2283. <select name='selHours' id='selHours' onChange='popupSetVarHours();'>
  2284. ";
  2285. // Correct for ghost hours, if they are there.
  2286. $min_h = $course->min_hours*1;
  2287. $max_h = $course->max_hours*1;
  2288. if ($course->bool_ghost_min_hour) $min_h = 0;
  2289. if ($course->bool_ghost_hour) $max_h = 0;
  2290. for($t = $min_h; $t <= $max_h; $t++)
  2291. {
  2292. $sel = "";
  2293. if ($t == $course->advised_hours){ $sel = "SELECTED"; }
  2294. $html .= "<option value='$t' $sel>$t</option>";
  2295. }
  2296. $html .= "</select> " . t("hours.") . "<br>
  2297. </div>
  2298. </div>";
  2299. if ($course->advised_hours > -1)
  2300. {
  2301. $var_hours_default = $course->advised_hours *1;
  2302. } else {
  2303. $var_hours_default = $min_h;
  2304. }
  2305. $render["course_var_hour_select"] = array(
  2306. "value" => $html,
  2307. "weight" => 110,
  2308. );
  2309. }
  2310. // Some hidden vars and other details
  2311. $html = "";
  2312. if ($show_advising_buttons == true && !$this->bool_blank) {
  2313. // Insert a hidden radio button so the javascript works okay...
  2314. $html .= "<input type='radio' name='course' value='$course->course_id' checked='checked'
  2315. style='display: none;'>
  2316. <input type='hidden' name='varHours' id='varHours' value='$var_hours_default'>";
  2317. if (user_has_permission("can_advise_students"))
  2318. {
  2319. $html .= fp_render_button(t("Select Course"), "popupAssignSelectedCourseToGroup(\"$group->assigned_to_semester_num\", \"$group->group_id\",\"$advising_term_id\",\"$db_group_requirement_id\",\"$req_by_degree_id\");", true, "style='font-size: 10pt;'");
  2320. }
  2321. }
  2322. else if ($show_advising_buttons == false && $course->has_variable_hours() == true && $course->grade == "" && user_has_permission("can_advise_students") && !$this->bool_blank) {
  2323. // Show an "update" button, and use the course's assigned_to_group_id and
  2324. // assigned_to_semester_num.
  2325. $html .= "
  2326. <input type='hidden' name='varHours' id='varHours' value='$var_hours_default'>";
  2327. // Same situation about the group_id. I guess need to find out exactly which group it was assigned to?
  2328. $html .= fp_render_button(t("Update"), "popupUpdateSelectedCourse(\"$course->course_id\",\"" . $course->get_first_assigned_to_group_id() . "\",\"$course->assigned_to_semester_num\",\"$course->random_id\",\"$advising_term_id\",\"$req_by_degree_id\");");
  2329. }
  2330. $render["hidden_vars_and_buttons"] = array(
  2331. "value" => $html,
  2332. "weight" => 1000,
  2333. );
  2334. watchdog("advise", "popup_course_description $course->course_id. <pre>" . print_r($course, TRUE) . "</pre>", array(), WATCHDOG_DEBUG);
  2335. // Okay, render our render array and return.
  2336. $pC .= fp_render_content($render);
  2337. return $pC;
  2338. }
  2339. /**
  2340. * Simple function to make an institution name look more pretty, because
  2341. * all institution names pass through ucwords(), sometimes the capitalization
  2342. * gets messed up. This function tries to correct it.
  2343. *
  2344. * Feel free to override it and add to it, if needed.
  2345. *
  2346. * @param string $str
  2347. * @return string
  2348. */
  2349. function fix_institution_name($str)
  2350. {
  2351. $student_id = $this->student->student_id;
  2352. $school_id = db_get_school_id_for_student_id($student_id);
  2353. // Should we do this at all? We will look at the "autocapitalize_institution_names" setting.
  2354. $auto = variable_get_for_school("autocapitalize_institution_names", 'yes', $school_id);
  2355. if ($auto == "no") {
  2356. // Nope! Just return.
  2357. return $str;
  2358. }
  2359. $str = str_replace("-", " - ", $str);
  2360. $str = ucwords(strtolower($str));
  2361. $str = str_replace(" Of ", " of ", $str);
  2362. $str = str_replace("clep", "CLEP", $str);
  2363. $str = str_replace("_clep", "CLEP", $str);
  2364. $str = str_replace("_act", "ACT", $str);
  2365. $str = str_replace("_sat", "SAT", $str);
  2366. $str = str_replace("Ap ", "AP ", $str);
  2367. $str = str_replace("_dsst", "DSST", $str);
  2368. // Fix school initials.
  2369. // Turns "Ulm" into "ULM"
  2370. $school_initials = variable_get_for_school("school_initials", "DEMO", $school_id);
  2371. $str = str_replace(ucwords(strtolower($school_initials)), $school_initials, $str);
  2372. if ($str == "")
  2373. {
  2374. $str = "<i>unknown institution</i>";
  2375. }
  2376. return $str;
  2377. }
  2378. /**
  2379. * Left in for legacy reasons, this function uses a new Course object's
  2380. * method of $course->fix_title to make a course's title more readable.
  2381. *
  2382. * @param string $str
  2383. * @return stromg
  2384. */
  2385. function fix_course_title($str)
  2386. {
  2387. $new_course = new Course();
  2388. $str = $new_course->fix_title($str);
  2389. return $str;
  2390. }
  2391. /**
  2392. * Given a Semester object, this will generate the HTML to draw it out
  2393. * to the screen. We will take advantage of the render engine, so we
  2394. * can utilize hook_content_alter later on.
  2395. *
  2396. * @param Semester $semester
  2397. * @param bool $bool_display_hour_count
  2398. * - If set to TRUE, it will display a small "hour count" message
  2399. * at the bottom of each semester, showing how many hours are in
  2400. * the semester. Good for debugging purposes.
  2401. *
  2402. * @return string
  2403. */
  2404. function display_semester(Semester $semester, $bool_display_hour_count = false)
  2405. {
  2406. // Display the contents of a semester object
  2407. // on the screen (in HTML)
  2408. $render = array();
  2409. $render['#id'] = 'AdvisingScreen_display_semester';
  2410. $render['#semester'] = $semester;
  2411. $render['#degree_plan'] = $this->degree_plan;
  2412. $render['#bool_display_hour_count'] = $bool_display_hour_count;
  2413. $render_weight = 0;
  2414. $render['semester_box_top'] = array(
  2415. 'value' => $this->draw_semester_box_top($semester->title),
  2416. 'weight' => $render_weight,
  2417. );
  2418. $count_hoursCompleted = 0;
  2419. $html = array();
  2420. // Create a temporary caching system for degree titles, so we don't have to keep looking them back up.
  2421. if (!isset($GLOBALS["fp_temp_degree_titles"])) {
  2422. $GLOBALS["fp_temp_degree_titles"] = array();
  2423. $GLOBALS["fp_temp_degree_types"] = array();
  2424. $GLOBALS["fp_temp_degree_classes"] = array();
  2425. $GLOBALS["fp_temp_degree_levels"] = array();
  2426. }
  2427. $degree_sort_policy = variable_get_for_school("degree_requirement_sort_policy", "alpha", $this->student->school_id);
  2428. // First, display the list of bare courses.
  2429. if ($degree_sort_policy == 'database') {
  2430. $semester->list_courses->sort_degree_requirement_id();
  2431. }
  2432. else {
  2433. // By default, sort alphabetical
  2434. $semester->list_courses->sort_alphabetical_order(); // sort, including the degree title we're sorting for.
  2435. }
  2436. $semester->list_courses->reset_counter();
  2437. while($semester->list_courses->has_more())
  2438. {
  2439. $course = $semester->list_courses->get_next();
  2440. if (!isset($html[$course->req_by_degree_id])) {
  2441. $html[$course->req_by_degree_id] = "";
  2442. }
  2443. // Is this course being fulfilled by anything?
  2444. if (!($course->course_list_fulfilled_by->is_empty))
  2445. { // this requirement is being fulfilled by something the student took...
  2446. $c = $course->course_list_fulfilled_by->get_first();
  2447. $c->req_by_degree_id = $course->req_by_degree_id; // make sure we assign it to the current degree_id.
  2448. // Tell the course what group we are coming from. (in this case: none)
  2449. $c->disp_for_group_id = "";
  2450. $html[$course->req_by_degree_id] .= $this->draw_course_row($c);
  2451. $c->set_has_been_displayed($course->req_by_degree_id);
  2452. if ($c->display_status == "completed")
  2453. { // We only want to count completed hours, no midterm or enrolled courses.
  2454. $h = $c->get_hours_awarded();
  2455. if ($c->bool_ghost_hour == TRUE) {
  2456. $h = 0;
  2457. }
  2458. $count_hoursCompleted += $h;
  2459. }
  2460. } else {
  2461. // This requirement is not being fulfilled...
  2462. // Tell the course what group we are coming from. (in this case: none)
  2463. $course->disp_for_group_id = "";
  2464. $x = $this->draw_course_row($course);
  2465. //fpm(htmlentities($x));
  2466. $html[$course->req_by_degree_id] .= $x;
  2467. }
  2468. }
  2469. /////////////////////////////////////
  2470. // Now, draw all the groups.
  2471. $semester->list_groups->sort_alphabetical_order();
  2472. $semester->list_groups->reset_counter();
  2473. while($semester->list_groups->has_more())
  2474. {
  2475. $group = $semester->list_groups->get_next();
  2476. if (!isset($html[$group->req_by_degree_id])) {
  2477. $html[$group->req_by_degree_id] = "";
  2478. }
  2479. //$html[$group->req_by_degree_id] .= "<tr class='semester-display-group-tr'><td colspan='8'>";
  2480. $x = $this->display_group($group);
  2481. //fpm(htmlentities($x, TRUE));
  2482. $html[$group->req_by_degree_id] .= $x;
  2483. $count_hoursCompleted += $group->hours_fulfilled_for_credit;
  2484. //$html[$group->req_by_degree_id] .= "</td></tr>";
  2485. } //while groups.
  2486. // Sort by degree's advising weight
  2487. $new_html = array();
  2488. foreach($html as $req_by_degree_id => $content) {
  2489. $dtitle = @$GLOBALS["fp_temp_degree_titles"][$req_by_degree_id];
  2490. $dweight = intval(@$GLOBALS["fp_temp_degree_advising_weights"][$req_by_degree_id]);
  2491. if ($dtitle == "") {
  2492. $t_degree_plan = new DegreePlan();
  2493. $t_degree_plan->degree_id = $req_by_degree_id;
  2494. //$t_degree_plan->load_descriptive_data();
  2495. $dtitle = $t_degree_plan->get_title2(TRUE, TRUE);
  2496. $dweight = $t_degree_plan->db_advising_weight;
  2497. $dtype = $t_degree_plan->degree_type;
  2498. $dclass = $t_degree_plan->degree_class;
  2499. $dlevel = $t_degree_plan->degree_level;
  2500. $GLOBALS["fp_temp_degree_titles"][$req_by_degree_id] = $dtitle . " "; //save for next time.
  2501. $GLOBALS["fp_temp_degree_types"][$req_by_degree_id] = $dtype; //save for next time.
  2502. $GLOBALS["fp_temp_degree_classes"][$req_by_degree_id] = $dclass; //save for next time.
  2503. $GLOBALS["fp_temp_degree_levels"][$req_by_degree_id] = $dlevel; //save for next time.
  2504. $GLOBALS["fp_temp_degree_advising_weights"][$req_by_degree_id] = $dweight . " "; //save for next time.
  2505. }
  2506. $degree_title = fp_get_machine_readable($dtitle); // make it machine readable. No funny characters.
  2507. $degree_advising_weight = str_pad($dweight, 4, "0", STR_PAD_LEFT);
  2508. $new_html[$degree_advising_weight . "__" . $degree_title][$req_by_degree_id] = $content;
  2509. }
  2510. // Sort by the first index, the advising weight.
  2511. ksort($new_html);
  2512. $pC = "";
  2513. //////////////////////////
  2514. // Okay, now let's go through our HTML array and add to the screen....
  2515. foreach ($new_html as $w => $html) {
  2516. foreach($html as $req_by_degree_id => $content) {
  2517. // Get the degree title...
  2518. $dtitle = @$GLOBALS["fp_temp_degree_titles"][$req_by_degree_id];
  2519. $dtype = @$GLOBALS["fp_temp_degree_types"][$req_by_degree_id];
  2520. $dclass = @$GLOBALS["fp_temp_degree_classes"][$req_by_degree_id];
  2521. $dlevel = @$GLOBALS["fp_temp_degree_levels"][$req_by_degree_id];
  2522. if ($dtitle == "") {
  2523. $t_degree_plan = new DegreePlan();
  2524. $t_degree_plan->degree_id = $req_by_degree_id;
  2525. //$t_degree_plan->load_descriptive_data();
  2526. $dtitle = $t_degree_plan->get_title2(TRUE, TRUE);
  2527. $dtype = $t_degree_plan->degree_type;
  2528. $dclass = $t_degree_plan->degree_class;
  2529. $dlevel = $t_degree_plan->degree_level;
  2530. $GLOBALS["fp_temp_degree_titles"][$req_by_degree_id] = $dtitle; //save for next time.
  2531. $GLOBALS["fp_temp_degree_types"][$req_by_degree_id] = $dtype; //save for next time.
  2532. $GLOBALS["fp_temp_degree_classes"][$req_by_degree_id] = $dclass; //save for next time.
  2533. $GLOBALS["fp_temp_degree_levels"][$req_by_degree_id] = $dlevel; //save for next time.
  2534. }
  2535. $css_dtitle = fp_get_machine_readable($dtitle);
  2536. $theme = array(
  2537. 'classes' => array(' ', 'required-by-degree',
  2538. "required-by-degree-$css_dtitle",
  2539. "required-by-degree-type-" . fp_get_machine_readable($dtype),
  2540. "required-by-degree-class-" . fp_get_machine_readable($dclass),
  2541. "required-by-degree-level-" . fp_get_machine_readable($dlevel)),
  2542. 'css_dtitle' => $css_dtitle,
  2543. 'degree_id' => $req_by_degree_id,
  2544. 'required_by_html' => "<span class='req-by-label'>" . t("Required by") . "</span> <span class='req-by-degree-title'>$dtitle</span>",
  2545. 'view_by' => 'year',
  2546. );
  2547. // Don't display if we are in the Courses Added semester, or if we are NOT a "combined" degree.
  2548. if ($semester->semester_num == DegreePlan::SEMESTER_NUM_FOR_COURSES_ADDED || (is_object($this->degree_plan)) && !$this->degree_plan->is_combined_dynamic_degree_plan) {
  2549. $theme['required_by_html'] = '';
  2550. }
  2551. invoke_hook("theme_advise_degree_header_row", array(&$theme));
  2552. if ($theme['required_by_html']) {
  2553. $pC .= "<tr><td colspan='8' class='required-by-td'>
  2554. <div class='" . implode(' ',$theme['classes']) ."'>{$theme['required_by_html']}</div>
  2555. </td></tr>";
  2556. }
  2557. $pC .= $content;
  2558. }
  2559. }
  2560. $render_weight = $render_weight + 10;
  2561. $render['semester_content'] = array(
  2562. 'value' => $pC,
  2563. 'weight' => $render_weight,
  2564. );
  2565. // Add hour count to the bottom...
  2566. if ($bool_display_hour_count == true && $count_hoursCompleted > 0)
  2567. {
  2568. $p = "<tr><td colspan='8'>
  2569. <div class='advise-completed-hours' style='text-align:right; margin-top: 10px;'>
  2570. <span class='completed-hours-label'>" . t("Completed hours:") . "</span> <span class='count-hours-completed'>$count_hoursCompleted</span>
  2571. </div>
  2572. </td></tr>";
  2573. $render_weight = $render_weight + 10;
  2574. $render['semester_disp_hour_count'] = array(
  2575. 'value' => $p,
  2576. 'weight' => $render_weight,
  2577. );
  2578. }
  2579. // Does the semester have a notice?
  2580. if ($semester->notice != "")
  2581. {
  2582. $p = "<tr><td colspan='8'>
  2583. <div class='hypo advise-semester-notice' style='margin-top: 15px; padding: 5px;'>
  2584. <b>" . t("Important Notice:") . "</b> $semester->notice
  2585. </div>
  2586. </td></tr>";
  2587. $render_weight = $render_weight + 10;
  2588. $render['semester_notice'] = array(
  2589. 'value' => $p,
  2590. 'weight' => $render_weight,
  2591. );
  2592. }
  2593. //$pC .= $this->draw_semester_box_bottom();
  2594. $render_weight = $render_weight + 10;
  2595. $render['semester_box_bottom'] = array(
  2596. 'value' => $this->draw_semester_box_bottom(),
  2597. 'weight' => $render_weight,
  2598. );
  2599. // If the semester has NO content, then just return FALSE.
  2600. if (trim($render['semester_content']['value']) == "" && !isset($render['semester_notice']) && !isset($render['semester_disp_hour_count'])) {
  2601. return FALSE;
  2602. }
  2603. // Otherwise, render out and return the HTML
  2604. return fp_render_content($render);
  2605. }
  2606. /**
  2607. * This function displays a Group object on the degree plan. This is not
  2608. * the selection popup display. It will either show the group as multi
  2609. * rows, filled in with courses, or as a "blank row" for the user to click
  2610. * on.
  2611. *
  2612. * @param Group $place_group
  2613. * @return string
  2614. */
  2615. function display_group(Group $place_group)
  2616. {
  2617. // Display a group, either filled in with courses,
  2618. // and/or with a "blank row" for the user to
  2619. // click on.
  2620. $rtn = "";
  2621. // Now, if you will recall, all of the groups and their courses, etc,
  2622. // are in the degree_plan's list_groups. The $place_group object here
  2623. // is just a placeholder. So, get the real group...
  2624. if (!$group = $this->degree_plan->find_group($place_group->group_id))
  2625. {
  2626. fpm("Group not found.");
  2627. return;
  2628. }
  2629. $title = $group->title;
  2630. $display_course_list = new CourseList();
  2631. // Okay, first look for courses in the first level
  2632. // of the group.
  2633. $display_semesterNum = $place_group->assigned_to_semester_num;
  2634. $req_by_degree_id = $group->req_by_degree_id;
  2635. // Make sure all courses and subgroups have the same req_by_degree_id set.
  2636. $group->set_req_by_degree_id($group->req_by_degree_id);
  2637. // What we are trying to do is end up with a list of courses we want to display on the screen (for example,
  2638. // that the student took or were substituted in)
  2639. $group->list_courses->remove_unfulfilled_and_unadvised_courses();
  2640. $group->list_courses->reset_counter();
  2641. while($group->list_courses->has_more())
  2642. {
  2643. $course = $group->list_courses->get_next();
  2644. // Do we have enough hours to keep going?
  2645. $fulfilled_hours = $display_course_list->count_hours("", FALSE, TRUE, FALSE, FALSE, $req_by_degree_id);
  2646. $remaining = $place_group->hours_required - $fulfilled_hours;
  2647. // If the course in question is part of a substitution that is not
  2648. // for this group, then we should skip it.
  2649. if (!($course->course_list_fulfilled_by->is_empty))
  2650. {
  2651. $try_c = $course->course_list_fulfilled_by->get_first();
  2652. if ($try_c->get_bool_substitution($req_by_degree_id) == TRUE && $try_c->get_bool_assigned_to_group_id($group->group_id) != TRUE)
  2653. {
  2654. continue;
  2655. }
  2656. }
  2657. if (!($course->course_list_fulfilled_by->is_empty) && $course->course_list_fulfilled_by->get_first()->get_has_been_displayed($req_by_degree_id) != TRUE && $course->get_has_been_displayed($req_by_degree_id) != TRUE)
  2658. {
  2659. $c = $course->course_list_fulfilled_by->get_first();
  2660. $ch = $c->get_hours($req_by_degree_id);
  2661. // Because PHP has dumb floating point arithmatic, we are going to round our values to 8 places,
  2662. // otherwise I was getting weird results like 0.34 < 0.34 == true. I chose 8 places to make sure it wouldn't
  2663. // actually cause the values to round and mess up the math.
  2664. $remaining = round($remaining, 8);
  2665. $ch = round($ch, 8);
  2666. // Is whats remaining actually LESS than the course hours? If so, we need to skip it.
  2667. if ($remaining < $ch)
  2668. {
  2669. continue;
  2670. }
  2671. $c->temp_flag = false;
  2672. $c->icon_filename = $group->icon_filename;
  2673. $c->title_text = "This course is a member of $group->title." . " ($place_group->requirement_type)";
  2674. $c->requirement_type = $place_group->requirement_type;
  2675. $c->req_by_degree_id = $req_by_degree_id;
  2676. $display_course_list->add($c);
  2677. }
  2678. if ($course->bool_advised_to_take && $course->get_has_been_displayed($req_by_degree_id) != true && $course->assigned_to_semester_num == $display_semesterNum)
  2679. {
  2680. $c = $course;
  2681. if ($remaining < $c->get_hours($req_by_degree_id))
  2682. {
  2683. continue;
  2684. }
  2685. $c->temp_flag = true;
  2686. $c->icon_filename = $group->icon_filename;
  2687. $c->req_by_degree_id = $req_by_degree_id;
  2688. $c->title_text = t("The student has been advised to take this course to fulfill a @gt requirement.", array("@gt" => $group->title));
  2689. $display_course_list->add($c);
  2690. }
  2691. }
  2692. $group->list_groups->reset_counter();
  2693. while($group->list_groups->has_more())
  2694. {
  2695. $branch = $group->list_groups->get_next();
  2696. // look for courses at this level...
  2697. if (!$branch->list_courses->is_empty)
  2698. {
  2699. $branch->list_courses->sort_alphabetical_order();
  2700. $branch->list_courses->reset_counter();
  2701. while($branch->list_courses->has_more())
  2702. {
  2703. $course = $branch->list_courses->get_next();
  2704. // Do we have enough hours to keep going?
  2705. $fulfilled_hours = $display_course_list->count_hours("", FALSE, TRUE, FALSE, FALSE, $req_by_degree_id);
  2706. $remaining = $place_group->hours_required - $fulfilled_hours;
  2707. if (!($course->course_list_fulfilled_by->is_empty) && $course->course_list_fulfilled_by->get_first()->get_has_been_displayed($req_by_degree_id) != true && $course->get_has_been_displayed($req_by_degree_id) != true)
  2708. {
  2709. $c = $course->course_list_fulfilled_by->get_first();
  2710. if ($remaining < $c->get_hours() || $remaining == 0)
  2711. {
  2712. continue;
  2713. }
  2714. $c->temp_flag = false;
  2715. $c->icon_filename = $group->icon_filename;
  2716. $c->title_text = "This course is a member of $group->title." . "($place_group->requirement_type)";
  2717. $c->requirement_type = $place_group->requirement_type;
  2718. $c->req_by_degree_id = $req_by_degree_id;
  2719. // TODO: This right here is how we show specified-repeats in groups with branches.
  2720. // TODO: Originally we were making sure there wasn't a "match" already in the display_course_list, which was
  2721. // of course excluding any of our specified repeats.
  2722. //if (!$display_course_list->find_match($c))
  2723. $found_match = $display_course_list->find_match($c);
  2724. if (!$found_match || ($found_match && $c->bool_specified_repeat == TRUE)) {
  2725. $display_course_list->add($c);
  2726. }
  2727. else if (is_object($c->course_transfer)) {
  2728. if (!$display_course_list->find_match($c->course_transfer))
  2729. { // Make sure it isn't already in the display list.
  2730. $display_course_list->add($c);
  2731. }
  2732. }
  2733. }
  2734. if ($course->bool_advised_to_take && $course->get_has_been_displayed($req_by_degree_id) != true && $course->assigned_to_semester_num == $display_semesterNum)
  2735. {
  2736. $c = $course;
  2737. if ($remaining < $c->get_hours($req_by_degree_id) || $remaining == 0)
  2738. {
  2739. continue;
  2740. }
  2741. $c->temp_flag = true;
  2742. $c->icon_filename = $group->icon_filename;
  2743. $c->req_by_degree_id = $req_by_degree_id;
  2744. $c->title_text = "The student has been advised to take this course to fulfill a $group->title requirement.";
  2745. if (!$display_course_list->find_match($c))
  2746. {
  2747. $display_course_list->add($c);
  2748. }
  2749. }
  2750. }
  2751. }
  2752. }
  2753. $display_course_list->sort_advised_last_alphabetical();
  2754. // Make sure we're all on the same page, for what degree_id we're being displayed under.
  2755. $display_course_list->set_req_by_degree_id($req_by_degree_id);
  2756. $rtn .= $this->display_group_course_list($display_course_list, $group, $display_semesterNum);
  2757. // original: $fulfilled_hours = $display_course_list->count_hours("", false, false, TRUE, false, $req_by_degree_id);
  2758. // Changing to new line, to match other argument list for previous occurances of 'fulfilled_hours'. This makes it so that
  2759. // a zero-hour course does not "use up" a 1 hour spot in the course hour counts.
  2760. // TODO: This might cause a group of *only* zero hour courses to never count as being filled.
  2761. // TODO: Maybe this difference between the original and this line should be a setting? Or per-group?
  2762. $fulfilled_hours = $display_course_list->count_hours("", FALSE, TRUE, FALSE, FALSE, $req_by_degree_id);
  2763. $fulfilled_credit_hours = $display_course_list->count_credit_hours("",false,true);
  2764. $test_hours = $fulfilled_hours;
  2765. // if the fulfilledCreditHours is > than the fulfilledHours,
  2766. // then assign the fulfilledCreditHours to the testHours.
  2767. if ($fulfilled_credit_hours > $fulfilled_hours)
  2768. { // done to fix a bug involving splitting hours in a substitution.
  2769. $test_hours = $fulfilled_credit_hours;
  2770. }
  2771. // If there are any remaining hours in this group,
  2772. // draw a "blank" selection row.
  2773. $remaining = $place_group->hours_required - $test_hours;
  2774. $place_group->hours_remaining = $remaining;
  2775. $place_group->hours_fulfilled = $fulfilled_hours;
  2776. $place_group->hours_fulfilled_for_credit = $fulfilled_credit_hours;
  2777. if ($remaining > 0)
  2778. {
  2779. $rowclass = "";
  2780. // If we have met the min hours (if the group even HAS min hours) then add a class to $rowclass,
  2781. // so we can hide it or whatever with CSS.
  2782. if ($group->has_min_hours_allowed()) {
  2783. if ($test_hours >= $group->min_hours_allowed) {
  2784. $rowclass .= "group-select-min-hours-fulfilled";
  2785. }
  2786. }
  2787. $rtn .= $this->draw_group_select_row($place_group, $remaining, $rowclass);
  2788. }
  2789. return $rtn;
  2790. }
  2791. /**
  2792. * Find all instaces of a Course in a Group and mark as displayed.
  2793. *
  2794. * @param Group $group
  2795. * @param Course $course
  2796. */
  2797. function mark_course_as_displayed(Group $group, Course $course)
  2798. {
  2799. // Find all instances of $course in $group,
  2800. // and mark as displayed.
  2801. if ($obj_list = $group->list_courses->find_all_matches($course))
  2802. {
  2803. $course_list = CourseList::cast($obj_list);
  2804. $course_list->mark_as_displayed();
  2805. }
  2806. // Now, go through all the course lists within each branch...
  2807. $group->list_groups->reset_counter();
  2808. while($group->list_groups->has_more())
  2809. {
  2810. $g = $group->list_groups->get_next();
  2811. if ($obj_list = $g->list_courses->find_all_matches($course))
  2812. {
  2813. $course_list = CourseList::cast($obj_list);
  2814. $course_list->mark_as_displayed($semester_num);
  2815. }
  2816. }
  2817. }
  2818. /**
  2819. * Displays all the courses in a CourseList object, using
  2820. * the draw_course_row function.
  2821. *
  2822. * It looks like the group and semester_num are not being used
  2823. * anymore.
  2824. *
  2825. * @todo Check on unused variables.
  2826. *
  2827. * @param CourseList $course_list
  2828. * @param unknown_type $group
  2829. * @param unknown_type $semester_num
  2830. * @return unknown
  2831. */
  2832. function display_group_course_list($course_list, $group, $semester_num)
  2833. {
  2834. $pC = "";
  2835. $course_list->reset_counter();
  2836. while($course_list->has_more())
  2837. {
  2838. $course = $course_list->get_next();
  2839. // Tell the course what group we are coming from, so it displays correctly
  2840. $course->disp_for_group_id = $group->group_id;
  2841. $pC .= $this->draw_course_row($course, $course->icon_filename, $course->title_text, $course->temp_flag, TRUE, TRUE, FALSE, $group);
  2842. // Doesn't matter if its a specified repeat or not. Just
  2843. // mark it as having been displayed.
  2844. $course->set_has_been_displayed($group->req_by_degree_id);
  2845. }
  2846. return $pC;
  2847. }
  2848. /**
  2849. * This draws the "blank row" for a group on the degree plan, which instructs
  2850. * the user to click on it to select a course from the popup.
  2851. *
  2852. * @param Group $group
  2853. * @param int $remaining_hours
  2854. * @return string
  2855. */
  2856. function draw_group_select_row(Group $group, $remaining_hours, $rowclass = "")
  2857. {
  2858. $img_path = fp_theme_location() . "/images";
  2859. $on_mouse_over = "
  2860. onmouseover='$(this).addClass(\"selection_highlight\");'
  2861. onmouseout='$(this).removeClass(\"selection_highlight\");' ";
  2862. $render = array();
  2863. $render['#id'] = 'AdvisingScreen_draw_group_select_row';
  2864. $render['#group'] = $group;
  2865. $render['#group_name'] = $group->group_name;
  2866. $render['#remaining_hours'] = $remaining_hours;
  2867. $render['#semester_num'] = $group->assigned_to_semester_num;
  2868. $school_id = $group->school_id;
  2869. $s = "s";
  2870. if ($remaining_hours < 2)
  2871. {
  2872. $s = "";
  2873. }
  2874. $title_text = $extra_classes = "";
  2875. // Add the name of the group to the extra-classes
  2876. $extra_classes .= " gr-" . fp_get_machine_readable($group->group_name);
  2877. $select_icon = "<img src='$img_path/select.gif' border='0'>";
  2878. $icon_link = "<img src='$img_path/icons/$group->icon_filename' width='19' height='19' border='0' alt='$title_text' title='$title_text'>";
  2879. $blank_degree_id = "";
  2880. if ($this->bool_blank)
  2881. {
  2882. $blank_degree_id = $this->degree_plan->degree_id;
  2883. }
  2884. $req_by_degree_id = $group->req_by_degree_id;
  2885. $render['#degree_id'] = $req_by_degree_id;
  2886. $disp_remaining_hours = $remaining_hours;
  2887. // If the group has min_hours, then the disp_remaining_hours gets that too.
  2888. if ($group->has_min_hours_allowed()) {
  2889. $disp_remaining_hours = ($group->min_hours_allowed - $group->hours_fulfilled) . "-" . $remaining_hours;
  2890. }
  2891. $dialog_title = t("Select @disp_hrs hour$s from %group_title", array('@disp_hrs' => $disp_remaining_hours, '%group_title' => $group->title));
  2892. if ($remaining_hours > 200) {
  2893. // Don't bother showing the remaining hours number.
  2894. $dialog_title = t("Select additional hour$s from %group_title", array('%group_title' => $group->title));
  2895. if ($group->group_id == DegreePlan::GROUP_ID_FOR_COURSES_ADDED) {
  2896. $dialog_title = t("Select additional courses");
  2897. }
  2898. }
  2899. $js_code = "selectCourseFromGroup(\"$group->group_id\", \"$group->assigned_to_semester_num\", \"$remaining_hours\", \"$blank_degree_id\",\"$req_by_degree_id\",\"$dialog_title\");";
  2900. $row_msg = t("Click") . " <span style='color:red;' class='group-select-arrows'>&gt;&gt;</span> " . t("to select @drh hour$s.", array("@drh" => $disp_remaining_hours));
  2901. if ($remaining_hours > 200) {
  2902. // Don't bother showing the remaining hours number.
  2903. $row_msg = t("Click") . " <span style='color:red;' class='group-select-arrows'>&gt;&gt;</span> " . t("to select additional courses.");
  2904. }
  2905. $hand_class = "hand";
  2906. if (variable_get_for_school("show_group_titles_on_view", "no", $school_id) == "yes")
  2907. {
  2908. $row_msg = t("Select") . " $disp_remaining_hours " . t("hour$s from") . " $group->title.";
  2909. if ($remaining_hours > 200) {
  2910. // Don't bother showing the remaining hours number.
  2911. $row_msg = t("Select additional courses from") . " $group->title.";
  2912. }
  2913. if ($this->bool_print) {
  2914. // In print view, disable all popups and mouseovers.
  2915. $on_mouse_over = "";
  2916. $js_code = "";
  2917. $hand_class = "";
  2918. }
  2919. }
  2920. if ($group->group_id == DegreePlan::GROUP_ID_FOR_COURSES_ADDED)
  2921. { // This is the Add a Course group.
  2922. $row_msg = t("Click to add an additional course.");
  2923. $select_icon = "<span style='font-size: 16pt; color:blue;'>+</span>";
  2924. $icon_link = "";
  2925. }
  2926. // Let's find out if this group contains courses which can be used in more than one degree.
  2927. $res = intval($this->degree_plan->get_max_course_appears_in_degrees_count($group->group_id));
  2928. if ($res > 1) {
  2929. $extra_classes .= " contains-course-which-appears-in-mult-degrees contains-course-which-appears-in-$res-degrees";
  2930. }
  2931. // Just like the other times we check to theme a course row, let's give the option to theme this as well.
  2932. $theme = array();
  2933. $theme["screen"] = $this;
  2934. $theme["degree_plan"] = $this->degree_plan;
  2935. $theme["student"] = $this->student;
  2936. $theme["group"]["group"] = $group;
  2937. $theme["group"]["extra_classes"] = $extra_classes;
  2938. $theme["group"]["icon_link"] = $icon_link;
  2939. $theme["group"]["select_icon"] = $select_icon;
  2940. $theme["group"]["js_code"] = $js_code;
  2941. $theme["group"]["row_msg"] = $row_msg;
  2942. $theme["group"]["title"] = $group->title;
  2943. $theme["group"]["remaining_hours"] = $remaining_hours;
  2944. // Invoke a hook on our theme array, so other modules have a chance to change it up.
  2945. invoke_hook("theme_advise_group_select_row", array(&$theme));
  2946. $render['#js_code'] = $js_code;
  2947. $render['start_group_select_row'] = array(
  2948. 'value' => "<tr class='from-render-api $rowclass'><td colspan='8' class='group-select-row-tr'>",
  2949. 'weight' => 0,
  2950. );
  2951. $render['group_select_table_top'] = array(
  2952. 'value' => "<table border='0' cellpadding='0' class='table-group-select-row' cellspacing='0' >",
  2953. 'weight' => 100,
  2954. );
  2955. $render['group_select_table_tr'] = array(
  2956. 'value' => "<tr class='$hand_class {$theme["group"]["extra_classes"]} group-select-row'
  2957. $on_mouse_over title='{$theme["group"]["title"]}'>",
  2958. 'weight' => 200,
  2959. );
  2960. $render['group_select_table_w1_1'] = array(
  2961. 'value' => "<td class='group-w1_1 w1_1' ></td>",
  2962. 'weight' => 300,
  2963. );
  2964. $render['group_select_table_icon_link'] = array(
  2965. 'value' => "<td class='group-w1_2 w1_2' onClick='{$theme["group"]["js_code"]}'>{$theme["group"]["icon_link"]}</td>",
  2966. 'weight' => 400,
  2967. );
  2968. $render['group_select_table_select_icon'] = array(
  2969. 'value' => "<td class='group-w1_3 w1_3' onClick='{$theme["group"]["js_code"]}'>{$theme["group"]["select_icon"]}</td>",
  2970. 'weight' => 500,
  2971. );
  2972. $render['group_select_table_row_msg'] = array(
  2973. 'value' => "<td class='underline group-row-msg' onClick='{$theme["group"]["js_code"]}'>
  2974. {$theme["group"]["row_msg"]}
  2975. </td>",
  2976. 'weight' => 600,
  2977. );
  2978. $render['group_select_table_bottom'] = array(
  2979. 'value' => "</tr>
  2980. </table>",
  2981. 'weight' => 5000,
  2982. );
  2983. $render['end_group_select_row'] = array(
  2984. 'value' => "</td></tr>",
  2985. 'weight' => 9999,
  2986. );
  2987. return fp_render_content($render, FALSE);
  2988. }
  2989. /**
  2990. * Uses the draw_box_top function, specifically for semesters.
  2991. *
  2992. * @param string $title
  2993. * @param bool $hideheaders
  2994. * @return string
  2995. */
  2996. function draw_semester_box_top($title, $hideheaders = false)
  2997. {
  2998. $extra_classes = " fp-semester-box-top fp-semester-box-top-" . fp_get_machine_readable(strtolower($title));
  2999. return $this->draw_box_top($title, $hideheaders, $extra_classes);
  3000. }
  3001. /**
  3002. * Uses the draw_box_bottom function, specifically for semesters.
  3003. * Actually, this function is a straight alias for $this->draw_box_bottom().
  3004. *
  3005. * @return string
  3006. */
  3007. function draw_semester_box_bottom()
  3008. {
  3009. return $this->draw_box_bottom();
  3010. }
  3011. /**
  3012. * Very, very simple. Just returns "</table>";
  3013. *
  3014. * @return string
  3015. */
  3016. function draw_box_bottom()
  3017. {
  3018. return "</table>";
  3019. }
  3020. /**
  3021. * Used to draw the beginning of semester boxes and other boxes, for example
  3022. * the footnotes.
  3023. *
  3024. * @param string $title
  3025. * @param bool $hideheaders
  3026. * - If TRUE, then the course/hrs/grd headers will not be displayed.
  3027. *
  3028. * @param int $table_width
  3029. * - The HTML table width, in pixels. If not set, it will default
  3030. * to 300 pixels wide.
  3031. *
  3032. * @return string
  3033. */
  3034. function draw_box_top($title, $hideheaders=false, $extra_classes = ""){
  3035. // returns the beginnings of the semester block tables...
  3036. $headers = array();
  3037. if ($hideheaders != true)
  3038. {
  3039. $headers[0] = t("Course");
  3040. $headers[1] = t("Hrs");
  3041. $headers[2] = t("Grd");
  3042. $headers[3] = t("Pts");
  3043. }
  3044. $extra_classes .= " fp-box-top-" . fp_get_machine_readable(strtolower($title));
  3045. $render = array();
  3046. $render['#id'] = 'AdvisingScreen_draw_box_top';
  3047. $render['#title'] = $title;
  3048. $render['#hideheaders'] = $hideheaders;
  3049. $render['#extra_classes'] = $extra_classes;
  3050. $render['table_top'] = array(
  3051. 'value' => "<table border='0' cellpadding='0' cellspacing='0' class='fp-box-top $extra_classes'>",
  3052. );
  3053. $render['semester_title_box_top'] = array(
  3054. 'value' => "<tr>
  3055. <td colspan='8' class='semester-box-top'>
  3056. ",
  3057. );
  3058. $render['section_title'] = array(
  3059. 'value' => fp_render_section_title($title),
  3060. );
  3061. $render['semester_title_box_bottom'] = array(
  3062. 'value' => "</td>
  3063. </tr>",
  3064. );
  3065. if (!$hideheaders)
  3066. {
  3067. $render['headers'] = array(
  3068. 'value' => "<tr class='box-headers-row'>
  3069. <td colspan='8'>
  3070. <table class='header-table' cellpadding='0' cellspacing='0'>
  3071. <th class='w1_1'></th>
  3072. <th class='w1_2'></th>
  3073. <th class='w1_3'></th>
  3074. <th class='w2'>
  3075. $headers[0]
  3076. </th>
  3077. <th class='w3'></th>
  3078. <th class='w4'>
  3079. $headers[1]
  3080. </th>
  3081. <th class='w5'>
  3082. $headers[2]
  3083. </th>
  3084. <th class='w6'>
  3085. $headers[3]
  3086. </th>
  3087. <!--after_last_th-->
  3088. </tr>
  3089. </table>
  3090. </td>
  3091. </tr>
  3092. ",
  3093. );
  3094. }
  3095. return fp_render_content($render, FALSE);
  3096. } // draw_year_box_top
  3097. /**
  3098. * This is used by lots of other functions to display a course on the screen.
  3099. * It will show the course, the hours, the grade, and quality points, as well
  3100. * as any necessary icons next to it.
  3101. *
  3102. * @param Course $course
  3103. * @param string $icon_filename
  3104. * @param string $title_text
  3105. * @param bool $js_toggle_and_save
  3106. * - If set to TRUE, when the checkbox next to this course is clicked,
  3107. * the page will be submitted and a draft will be saved.
  3108. *
  3109. * @param bool $bool_display_check
  3110. * - If set to FALSE, no checkbox will be displayed for this course row.
  3111. *
  3112. * @param bool $bool_add_footnote
  3113. * @param bool $bool_add_asterisk_to_transfers
  3114. *
  3115. * @return string
  3116. */
  3117. function draw_course_row(Course $course, $icon_filename = "", $title_text = "", $js_toggle_and_save = false, $bool_display_check = true, $bool_add_footnote = true, $bool_add_asterisk_to_transfers = false, $group = null)
  3118. {
  3119. $render = array();
  3120. $render['#id'] = 'AdvisingScreen_draw_course_row';
  3121. $render['#course'] = $course;
  3122. $render['#group'] = $group;
  3123. // Display a course itself
  3124. $theme = array();
  3125. $theme["screen"] = $this;
  3126. $theme["student"] = $this->student;
  3127. $theme["degree_plan"] = $this->degree_plan;
  3128. $img_path = fp_theme_location() . "/images";
  3129. // The current term we are advising for.
  3130. $advising_term_id = @$GLOBALS["fp_advising"]["advising_term_id"];
  3131. $pts = "";
  3132. if (!$advising_term_id) {
  3133. $advising_term_id = 0;
  3134. }
  3135. $extra_classes = "";
  3136. $course->assign_display_status();
  3137. // If the course has already been advised in a different semester,
  3138. // we should set the advising_term_id to that and disable unchecking.
  3139. if ($course->advised_term_id*1 > 0 && $course->bool_advised_to_take == true && $course->advised_term_id != $advising_term_id)
  3140. {
  3141. $course->display_status = "disabled";
  3142. $advising_term_id = $course->advised_term_id;
  3143. }
  3144. // Add the name of the course to the extra-classes
  3145. $extra_classes .= " cr-" . fp_get_machine_readable($course->subject_id . " " . $course->course_num);
  3146. // Has the course been assigned to more than one degree?
  3147. if (count($course->assigned_to_degree_ids_array) > 1) {
  3148. $extra_classes .= " course-assigned-more-than-one-degree course-assigned-" . count($course->assigned_to_degree_ids_array) . "-degrees";
  3149. }
  3150. // If this is a course fragment, created as a remainder of a split substitution, add extra class.
  3151. if (@$course->details_by_degree_array[$course->req_by_degree_id]["bool_substitution_new_from_split"]) {
  3152. $extra_classes .= " course-sub-new-from-split";
  3153. }
  3154. if (@$course->details_by_degree_array[$course->req_by_degree_id]["bool_substitution_split"]) {
  3155. $extra_classes .= " course-sub-split";
  3156. }
  3157. // If the course has NOT been assigned, but is appearing in more than one degree, give it an extra CSS class
  3158. // Check to see if the course is in our required_courses_id_array for more than one degree.
  3159. if ($course->display_status == "eligible") {
  3160. if (isset($this->degree_plan->required_course_id_array[$course->course_id])) {
  3161. if (count($this->degree_plan->required_course_id_array[$course->course_id]) > 1) {
  3162. // Add a new classname for this course...
  3163. $extra_classes .= " course-appears-in-mult-degrees course-appears-in-" . count($this->degree_plan->required_course_id_array[$course->course_id]) . "-degrees";
  3164. }
  3165. }
  3166. }
  3167. if ($course->subject_id == "")
  3168. {
  3169. $course->load_descriptive_data();
  3170. }
  3171. $subject_id = $course->subject_id;
  3172. $course_num = $course->course_num;
  3173. $o_subject_id = $subject_id;
  3174. $o_course_num = $course_num;
  3175. $degree_id = $course->req_by_degree_id;
  3176. $footnote = "";
  3177. $ast = "";
  3178. // Is this actually a transfer course? If so, display its
  3179. // original subject_id and course_num.
  3180. if ($course->bool_transfer == true)
  3181. {
  3182. $subject_id = $course->course_transfer->subject_id;
  3183. $course_num = $course->course_transfer->course_num;
  3184. $institution_name = $course->course_transfer->institution_name;
  3185. if ($bool_add_asterisk_to_transfers == true)
  3186. {
  3187. $course->course_transfer->load_descriptive_transfer_data($this->student->student_id);
  3188. if ($course->course_transfer->transfer_eqv_text != "")
  3189. {
  3190. $ast = "*";
  3191. $GLOBALS["advising_course_has_asterisk"] = true;
  3192. }
  3193. }
  3194. // Apply a footnote if it has a local eqv.
  3195. if ($bool_add_footnote == true && $course->course_id > 0)
  3196. {
  3197. $footnote = "";
  3198. $footnote .= "<span class='superscript'>T";
  3199. $fcount = 0;
  3200. if (isset($this->footnote_array) && is_array($this->footnote_array) && isset($this->footnote_array["transfer"])) {
  3201. $fcount = @count($this->footnote_array["transfer"]) + 1;
  3202. }
  3203. if ($course->get_has_been_displayed() == true)
  3204. { // If we've already displayed this course once, and are
  3205. // now showing it again (like in the Transfer Credit list)
  3206. // we do not want to increment the footnote counter.
  3207. $fcount = $course->transfer_footnote;
  3208. }
  3209. $course->transfer_footnote = $fcount;
  3210. $footnote .= "$fcount</span>";
  3211. $this->footnote_array["transfer"][$fcount] = "$o_subject_id $o_course_num ~~ $subject_id $course_num ~~ ~~ $institution_name";
  3212. }
  3213. } // bool_transfer == true
  3214. $hours = $course->get_hours_awarded();
  3215. if ($course->get_bool_substitution() == TRUE )
  3216. {
  3217. $hours = $course->get_substitution_hours();
  3218. $temp_sub_course = $course->get_course_substitution();
  3219. if (is_object($temp_sub_course))
  3220. {
  3221. if ($temp_sub_course->subject_id == "")
  3222. { // Reload subject_id, course_num, etc, for the substitution course,
  3223. // which is actually the original requirement.
  3224. $temp_sub_course->load_descriptive_data();
  3225. }
  3226. $o_subject_id = $temp_sub_course->subject_id;
  3227. $o_course_num = $temp_sub_course->course_num;
  3228. }
  3229. if ($bool_add_footnote == true)
  3230. {
  3231. if (!isset($this->footnote_array["substitution"])) $this->footnote_array["substitution"] = array();
  3232. $footnote = "";
  3233. $footnote .= "<span class='superscript'>S";
  3234. $fcount = count($this->footnote_array["substitution"]) + 1;
  3235. if ($course->get_has_been_displayed($course->req_by_degree_id) == true)
  3236. { // If we've already displayed this course once, and are
  3237. // now showing it again (like in the Transfer Credit list)
  3238. // we do not want to increment the footnote counter.
  3239. $fcount = $course->substitution_footnote;
  3240. }
  3241. $course->substitution_footnote = $fcount;
  3242. $footnote .= "$fcount</span>";
  3243. $r = $course->req_by_degree_id;
  3244. @$sub_id = $course->db_substitution_id_array[$r];
  3245. $this->footnote_array["substitution"][$fcount] = "$o_subject_id $o_course_num ~~ $subject_id $course_num ~~ " . $course->get_substitution_hours() . " ~~ " . $course->get_first_assigned_to_group_id() . " ~~ $sub_id";
  3246. }
  3247. } // if course->get_bool_substitution() == true
  3248. if (is_numeric($hours) && $hours <= 0) {
  3249. // Some kind of error-- default to catalog hours
  3250. $hours = $course->get_catalog_hours();
  3251. }
  3252. if (is_numeric($hours)) {
  3253. $hours = $hours * 1; // force numeric, trim extra zeros.
  3254. }
  3255. $var_hour_icon = "&nbsp;";
  3256. if ($course->has_variable_hours() == true && !$course->bool_taken)
  3257. {
  3258. // The bool_taken part of this IF statement is because if the course
  3259. // has been completed, we should only use the hours_awarded.
  3260. $var_hour_icon = "<img src='" . fp_theme_location() . "/images/var_hour.gif'
  3261. title='" . t("This course has variable hours.") . "'
  3262. alt='" . t("This course has variable hours.") . "'>";
  3263. $hours = $course->get_advised_hours();
  3264. }
  3265. if ($course->bool_ghost_hour == TRUE) {
  3266. // This course was given a "ghost hour", meaning it is actually
  3267. // worth 0 hours, not 1, even though it's hours_awarded is currently
  3268. // set to 1. So, let's just make the display be 0.
  3269. $hours = "0";
  3270. }
  3271. $grade = $course->grade;
  3272. $dispgrade = $grade;
  3273. // If there is a MID, then this is a midterm grade.
  3274. $dispgrade = str_replace("MID","<span class='superscript'>" . t("mid") . "</span>",$dispgrade);
  3275. if (strtoupper($grade) == "E")
  3276. { // Currently enrolled. Show no grade.
  3277. $dispgrade = "";
  3278. }
  3279. if ($course->bool_hide_grade)
  3280. {
  3281. $dispgrade = "--";
  3282. $this->bool_hiding_grades = true;
  3283. }
  3284. $display_status = $course->display_status;
  3285. if ($display_status == "completed")
  3286. {
  3287. $pts = $this->get_quality_points($grade, $hours);
  3288. }
  3289. $course_id = $course->course_id;
  3290. $semester_num = $course->assigned_to_semester_num;
  3291. if ($group != NULL && $course->bool_advised_to_take != TRUE) {
  3292. $semester_num = $group->assigned_to_semester_num;
  3293. }
  3294. $render['#semester_num'] = $semester_num;
  3295. $render['#course_id'] = $course_id;
  3296. //$group_id = $course->assigned_to_group_id;
  3297. $group_id = $course->get_first_assigned_to_group_id();
  3298. $hid_group_id = str_replace("_", "U", $group_id); // replace _ with placeholder U so it doesn't mess up submission.
  3299. $random_id = $course->random_id;
  3300. $advised_hours = $course->advised_hours*1;
  3301. $unique_id = $course_id . "_" . $semester_num . "_" . mt_rand(1,99999);
  3302. $hid_name = "advcr_$course_id" . "_$semester_num" . "_$hid_group_id" . "_$advised_hours" . "_$random_id" . "_$advising_term_id" . "_$degree_id" . "_r" . mt_rand(1,99);
  3303. // Due to an interesting bug, the hid_name cannot contain periods. So, if a course
  3304. // has decimal hours, we need to replace the decimal with a placeholder.
  3305. if (strstr($hid_name, ".")) {
  3306. $hid_name = str_replace(".", "DoT", $hid_name);
  3307. }
  3308. $hid_value = "";
  3309. $opchecked = "";
  3310. if ($course->bool_advised_to_take == true)
  3311. {
  3312. $hid_value = "true";
  3313. $opchecked = "-check";
  3314. }
  3315. $op_on_click_function = "toggleSelection";
  3316. if ($js_toggle_and_save == true)
  3317. {
  3318. $op_on_click_function = "toggleSelectionAndSave";
  3319. }
  3320. $extra_js_vars = "";
  3321. if ($course->display_status == "disabled")
  3322. { // Checkbox needs to be disabled because this was advised in another
  3323. // term.
  3324. $op_on_click_function = "toggleDisabledChangeTerm";
  3325. $course->term_id = $course->advised_term_id;
  3326. $extra_js_vars = $course->get_term_description();
  3327. }
  3328. if ($course->display_status == "completed" || $course->display_status == "enrolled")
  3329. {
  3330. $op_on_click_function = "toggleDisabledCompleted";
  3331. $opchecked = "";
  3332. $extra_js_vars = $course->display_status;
  3333. }
  3334. if ($course->display_status == "retake")
  3335. {
  3336. // this course was probably subbed in while the student
  3337. // was still enrolled, and they have since made an F or W.
  3338. // So, disable it.
  3339. $op_on_click_function = "dummyToggleSelection";
  3340. $opchecked = "";
  3341. }
  3342. if ($this->bool_print || $this->bool_blank)
  3343. {
  3344. // If this is print view, disable clicking.
  3345. $op_on_click_function = "dummyToggleSelection";
  3346. }
  3347. if (!user_has_permission("can_advise_students"))
  3348. {
  3349. // This user does not have the abilty to advise,
  3350. // so take away the ability to toggle anything (like
  3351. // we are in print view).
  3352. $op_on_click_function = "dummyToggleSelection";
  3353. }
  3354. $extra_css = "";
  3355. if ($opchecked == "-check") {
  3356. $extra_css .= " advise-checkbox-$display_status-checked";
  3357. }
  3358. $theme["op"] = array(
  3359. "display_status" => $display_status,
  3360. "extra_css" => $extra_css,
  3361. "unique_id" => $unique_id,
  3362. "onclick" => array(
  3363. "function" => $op_on_click_function,
  3364. "arguments" => array($unique_id, $display_status, $extra_js_vars),
  3365. ),
  3366. "hidden_field" => "<input type='hidden' name='$hid_name' id='advcr_$unique_id' value='$hid_value'>",
  3367. );
  3368. // Okay, we can't actually serialize a course, as it takes too much space.
  3369. // It was slowing down the page load significantly! So, I am going
  3370. // to use a function I wrote called to_data_string().
  3371. $data_string = $course->to_data_string();
  3372. $blank_degree_id = "";
  3373. if ($this->bool_blank == true)
  3374. {
  3375. $blank_degree_id = $this->degree_plan->degree_id;
  3376. }
  3377. $js_code = "describeCourse(\"$data_string\",\"$blank_degree_id\",\"$subject_id $course_num\");";
  3378. $theme["course"]["js_code"] = $js_code;
  3379. // Assemble theme array elements for the course itself.
  3380. $theme["course"] = array(
  3381. "course" => $course,
  3382. "js_code" => $js_code,
  3383. "subject_id" => $subject_id,
  3384. "course_num" => $course_num,
  3385. "display_status" => $display_status,
  3386. "extra_classes" => $extra_classes,
  3387. "footnote" => $footnote,
  3388. "hours" => $hours,
  3389. "var_hour_icon" => $var_hour_icon,
  3390. "dispgrade" => $dispgrade,
  3391. "grade" => $grade,
  3392. "pts" => $pts,
  3393. "title" => $title_text,
  3394. "group_id" => $group_id,
  3395. );
  3396. // If the course has a 'u' in it, it is a 'University Capstone' course.
  3397. if (strstr($course->requirement_type, "u")) {
  3398. $icon_filename = "ucap.gif";
  3399. $title_text = t("This course is a University Capstone.");
  3400. }
  3401. if ($icon_filename != "") {
  3402. //$icon_link = "<img src='" . fp_theme_location() . "/images/icons/$icon_filename' width='19' height='19' border='0' alt='$title_text' title='$title_text'>";
  3403. $theme["icon"] = array();
  3404. $theme["icon"]["filename"] = $icon_filename;
  3405. $theme["icon"]["location"] = fp_theme_location() . "/images/icons";
  3406. $theme["icon"]["title"] = $title_text;
  3407. }
  3408. $on_mouse_over = "
  3409. onmouseover='$(this).addClass(\"selection_highlight\");'
  3410. onmouseout='$(this).removeClass(\"selection_highlight\");'
  3411. ";
  3412. $hand_class = "hand";
  3413. if ($bool_display_check == false) {
  3414. unset($theme["op"]);
  3415. }
  3416. if ($this->bool_print) {
  3417. // In print view, disable all popups and mouseovers.
  3418. $on_mouse_over = "";
  3419. $theme["course"]["js_code"] = "";
  3420. $hand_class = "";
  3421. }
  3422. // Invoke a hook on our theme array, so other modules have a chance to change it up.
  3423. invoke_hook("theme_advise_course_row", array(&$theme));
  3424. $render['#degree_id'] = $degree_id;
  3425. /////////////////////////////////
  3426. // Actually draw out our $theme array now....
  3427. // The checkbox & hidden element....
  3428. $op = $hid = "";
  3429. if (isset($theme["op"]) && count($theme["op"]) > 0) {
  3430. $onclick = "";
  3431. $onclick = $theme["op"]["onclick"]["function"] . "(\"" . join("\",\"", $theme["op"]["onclick"]["arguments"]) . "\")";
  3432. $op = "<span class='advise-checkbox advise-checkbox-{$theme["op"]["display_status"]} {$theme["op"]["extra_css"]}'
  3433. id='cb_span_{$theme["op"]["unique_id"]}'
  3434. onClick='$onclick;'></span>";
  3435. $hid = $theme["op"]["hidden_field"];
  3436. }
  3437. // The icon....
  3438. $icon_html = "";
  3439. if (isset($theme["icon"]) && count($theme["icon"]) > 0) {
  3440. $icon_html = "<img class='advising-course-row-icon'
  3441. src='{$theme["icon"]["location"]}/{$theme["icon"]["filename"]}' width='19' height='19' border='0' alt='{$theme["icon"]["title"]}' title='{$theme["icon"]["title"]}'>";
  3442. }
  3443. ////////////////////////////////////
  3444. // Draw the actual course row...
  3445. $render['start_course_row'] = array(
  3446. 'value' => "<tr class='from-render-api'><td colspan='8'>",
  3447. 'weight' => 0,
  3448. );
  3449. if ($course->get_bool_substitution_new_from_split() != TRUE || ($course->get_bool_substitution_new_from_split() == TRUE && $course->display_status != "eligible")){
  3450. if ($course_num == ""){
  3451. $course_num = "&nbsp;";
  3452. }
  3453. $js_code = $theme["course"]["js_code"];
  3454. $render['#js_code'] = $js_code;
  3455. $render['course_row_start_table'] = array(
  3456. 'value' => "<table border='0' cellpadding='0' cellspacing='0' class='draw-course-row'>",
  3457. 'weight' => 100,
  3458. );
  3459. $render['course_row_start_tr'] = array(
  3460. 'value' => "<tr class='$hand_class {$theme["course"]["display_status"]} {$theme["course"]["extra_classes"]}'
  3461. $on_mouse_over title='{$theme["course"]["title"]}' >",
  3462. 'weight' => 200,
  3463. );
  3464. $render['course_row_td_op_and_hidden'] = array(
  3465. 'value' => "<td class='w1_1'>$op$hid</td>",
  3466. 'weight' => 300,
  3467. );
  3468. $render['course_row_td_icon_html'] = array(
  3469. 'value' => "<td class='w1_2' onClick='$js_code'>$icon_html</td>",
  3470. 'weight' => 400,
  3471. );
  3472. $render['course_row_td_ast'] = array(
  3473. 'value' => "<td class='w1_3' onClick='$js_code'>&nbsp;$ast</td>",
  3474. 'weight' => 500,
  3475. );
  3476. $render['course_row_td_subject_id'] = array(
  3477. 'value' => "<td class='underline w2 ' onClick='$js_code'>
  3478. {$theme["course"]["subject_id"]}</td>",
  3479. 'weight' => 600,
  3480. );
  3481. $render['course_row_td_course_num'] = array(
  3482. 'value' => "<td class='underline w3' align='left'
  3483. onClick='$js_code'>
  3484. {$theme["course"]["course_num"]}{$theme["course"]["footnote"]}</td>",
  3485. 'weight' => 700,
  3486. );
  3487. $render['course_row_td_hrs'] = array(
  3488. 'value' => "<td class='underline w4' onClick='$js_code'>{$theme["course"]["hours"]}{$theme["course"]["var_hour_icon"]}</td>",
  3489. 'weight' => 800,
  3490. );
  3491. $render['course_row_td_grd'] = array(
  3492. 'value' => "<td class='underline w5' onClick='$js_code'>{$theme["course"]["dispgrade"]}&nbsp;</td>",
  3493. 'weight' => 900,
  3494. );
  3495. $render['course_row_td_pts'] = array(
  3496. 'value' => "<td class='underline w6' onClick='$js_code'>{$theme["course"]["pts"]}&nbsp;</td>",
  3497. 'weight' => 1000,
  3498. );
  3499. /*
  3500. $pC .= "
  3501. <table border='0' cellpadding='0' width='100%' cellspacing='0' align='left' class='draw-course-row'>
  3502. <tr height='20' class='$hand_class {$theme["course"]["display_status"]} {$theme["course"]["extra_classes"]}'
  3503. $on_mouse_over title='{$theme["course"]["title"]}' >
  3504. <td style='width:$w1_1; white-space:nowrap;' class='w1_1' align='left'>$op$hid</td>
  3505. <td style='width:$w1_2; white-space:nowrap;' align='left' class='w1_2' onClick='$js_code'>$icon_html</td>
  3506. <td style='width:$w1_3; white-space:nowrap;' align='left' class='w1_3' onClick='$js_code'>&nbsp;$ast</td>
  3507. <td align='left' style='width:$w2; white-space:nowrap;' class='underline w2 ' onClick='$js_code'>
  3508. {$theme["course"]["subject_id"]}</td>
  3509. <td class='underline w3' style='width:$w3; white-space:nowrap;' align='left'
  3510. onClick='$js_code'>
  3511. {$theme["course"]["course_num"]}{$theme["course"]["footnote"]}</td>
  3512. <td class='underline w4' style='width:$w4; max-width:36px; white-space:nowrap;' onClick='$js_code'>{$theme["course"]["hours"]}{$theme["course"]["var_hour_icon"]}</td>
  3513. <td class='underline w5' style='width:$w5; max-width:35px; white-space:nowrap;' onClick='$js_code'>{$theme["course"]["dispgrade"]}&nbsp;</td>
  3514. <td class='underline w6' style='width:$w6; max-width:31px; white-space:nowrap;' onClick='$js_code'>{$theme["course"]["pts"]}&nbsp;</td>
  3515. </tr>
  3516. </table>";
  3517. */
  3518. $render['course_row_end_row_and_table'] = array(
  3519. 'value' => "</tr></table>",
  3520. 'weight' => 5000,
  3521. );
  3522. }
  3523. else {
  3524. // These are the leftover hours from a partial substitution.
  3525. $render['#leftover_hours_from_partial_sub'] = TRUE;
  3526. $render['#js_code'] = $js_code;
  3527. $render['course_row_start_table'] = array(
  3528. 'value' => "<table border='0' cellpadding='0' width='100%' cellspacing='0' align='left' class='draw-course-row-leftover-hours'>",
  3529. 'weight' => 100,
  3530. );
  3531. $render['course_row_start_tr'] = array(
  3532. 'value' => "<tr class='hand {$theme["course"]["display_status"]}'
  3533. $on_mouse_over title='{$theme["course"]["title"]}'>",
  3534. 'weight' => 200,
  3535. );
  3536. $render['course_row_td_op_and_hidden'] = array(
  3537. 'value' => "<td class='w1_1'>$op$hid</td>",
  3538. 'weight' => 300,
  3539. );
  3540. $render['course_row_td_icon_html'] = array(
  3541. 'value' => "<td class='w1_2' onClick='$js_code'>$icon_html</td>",
  3542. 'weight' => 400,
  3543. );
  3544. $render['course_row_td_ast'] = array(
  3545. 'value' => "<td class='w1_3' onClick='$js_code'>&nbsp;</td>",
  3546. 'weight' => 500,
  3547. );
  3548. $render['course_row_td_leftover_course_details'] = array(
  3549. 'value' => "<td class='underline course-part-sub-hrs-left' onClick='$js_code'
  3550. colspan='4'>
  3551. &nbsp; &nbsp; {$theme["course"]["subject_id"]} &nbsp;
  3552. {$theme["course"]["course_num"]}{$theme["course"]["footnote"]}
  3553. &nbsp; ({$theme["course"]["hours"]} " . t("hrs left") . ")
  3554. </td>",
  3555. 'weight' => 600,
  3556. );
  3557. $render['course_row_end_row_and_table'] = array(
  3558. 'value' => "</tr></table>",
  3559. 'weight' => 5000,
  3560. );
  3561. }
  3562. $render['end_course_row'] = array(
  3563. 'value' => "</td></tr>",
  3564. 'weight' => 9999,
  3565. );
  3566. return fp_render_content($render, FALSE);
  3567. //return $pC;
  3568. }
  3569. /**
  3570. * Calculate the quality points for a grade and hours.
  3571. *
  3572. * This function is very similar to the one in the Course class.
  3573. * It is only slightly different here. Possibly, the two functions should be
  3574. * merged.
  3575. *
  3576. * @param string $grade
  3577. * @param int $hours
  3578. * @return int
  3579. */
  3580. function get_quality_points($grade, $hours){
  3581. $pts = 0;
  3582. $qpts_grades = array();
  3583. // Let's find out what our quality point grades & values are...
  3584. if (isset($GLOBALS["qpts_grades"])) {
  3585. // have we already cached this?
  3586. $qpts_grades = $GLOBALS["qpts_grades"];
  3587. }
  3588. else {
  3589. $tlines = explode("\n", variable_get_for_school("quality_points_grades", "A ~ 4\nB ~ 3\nC ~ 2\nD ~ 1\nF ~ 0\nI ~ 0", $this->student->school_id));
  3590. foreach ($tlines as $tline) {
  3591. $temp = explode("~", trim($tline));
  3592. if (trim($temp[0]) != "") {
  3593. $qpts_grades[trim($temp[0])] = trim($temp[1]);
  3594. }
  3595. }
  3596. $GLOBALS["qpts_grades"] = $qpts_grades; // save to cache
  3597. }
  3598. // Okay, find out what the points are by multiplying value * hours...
  3599. if (isset($qpts_grades[$grade])) {
  3600. $pts = $qpts_grades[$grade] * $hours;
  3601. }
  3602. return $pts;
  3603. }
  3604. /**
  3605. * Used in the group selection popup, this will display a course with
  3606. * a radio button next to it, so the user can select it.
  3607. *
  3608. * @param Course $course
  3609. * @param int $group_hours_remaining
  3610. *
  3611. * @return string
  3612. */
  3613. function draw_popup_group_select_course_row(Course $course, $group_hours_remaining = 0)
  3614. {
  3615. // Display a course itself...
  3616. $pC = "";
  3617. $w1_1 = $this->popup_width_array[0];
  3618. $w1_2 = $this->popup_width_array[1];
  3619. $w1_3 = $this->popup_width_array[2];
  3620. $w2 = $this->popup_width_array[3];
  3621. $w3 = $this->popup_width_array[4];
  3622. $w4 = $this->popup_width_array[5];
  3623. $w5 = $this->popup_width_array[6];
  3624. $w6 = $this->popup_width_array[7];
  3625. $title_text = "";
  3626. $icon_html = "";
  3627. $pts = "";
  3628. $theme["icon"] = array();
  3629. $theme = array();
  3630. $theme["screen"] = $this;
  3631. $theme["student"] = $this->student;
  3632. $theme["degree_plan"] = $this->degree_plan;
  3633. $theme["from_group_select"] = TRUE;
  3634. if ($course->subject_id == "")
  3635. {
  3636. // Lacking course's display data, so reload it from the DB.
  3637. $course->load_course($course->course_id);
  3638. }
  3639. $subject_id = $course->subject_id;
  3640. $course_num = $course->course_num;
  3641. $hours = $course->get_catalog_hours();
  3642. $display_status = $course->display_status;
  3643. $db_group_requirement_id = $course->db_group_requirement_id;
  3644. $grade = $course->grade;
  3645. $repeats = $course->specified_repeats;
  3646. if ($repeats > 0 && $show_repeat_information)
  3647. {
  3648. $w3 = "15%";
  3649. }
  3650. $attributes = $course->db_group_attributes;
  3651. $attributes_class = "";
  3652. if ($attributes == "*") {
  3653. $attributes_class .= "group-attr-recommended";
  3654. }
  3655. if ($attributes == "-") {
  3656. $attributes_class .= "group-attr-hidden";
  3657. }
  3658. //Setting in Configure School Settings:
  3659. $show_repeat_information = (variable_get_for_school("group_list_course_show_repeat_information", "yes", $course->school_id) == "yes");
  3660. $course_id = $course->course_id;
  3661. //$group_id = $course->assigned_to_group_id;
  3662. $group_id = $course->get_first_assigned_to_group_id();
  3663. $semester_num = $course->assigned_to_semester_num;
  3664. $req_by_degree_id = $course->req_by_degree_id;
  3665. $min_var_hours = "";
  3666. $var_hour_icon = "&nbsp;";
  3667. if ($course->has_variable_hours() == true)
  3668. {
  3669. $var_hour_icon = "<img src='" . fp_theme_location() . "/images/var_hour.gif'
  3670. title='" . t("This course has variable hours.") . "'
  3671. alt='" . t("This course has variable hours.") . "'>";
  3672. $min_var_hours = $course->min_hours;
  3673. // Does the var hours actually start at zero?
  3674. if ($course->bool_ghost_min_hour) {
  3675. $min_var_hours = 0;
  3676. }
  3677. }
  3678. $checked = "";
  3679. if ($course->bool_selected == true)
  3680. {
  3681. $checked = " checked='checked' ";
  3682. }
  3683. $blank_degree_id = "";
  3684. if ($this->bool_blank)
  3685. {
  3686. $blank_degree_id = $this->degree_plan->degree_id;
  3687. }
  3688. //$serializedCourse = urlencode(serialize($course));
  3689. $js_code = "popupDescribeSelected(\"$group_id\",\"$semester_num\",\"$course_id\",\"$subject_id\",\"req_by_degree_id=$req_by_degree_id&group_hours_remaining=$group_hours_remaining&db_group_requirement_id=$db_group_requirement_id&blank_degree_id=$blank_degree_id\");";
  3690. /*
  3691. $on_mouse_over = " onmouseover=\"style.backgroundColor='#FFFF99'\"
  3692. onmouseout=\"style.backgroundColor='white'\" ";
  3693. */
  3694. $on_mouse_over = "
  3695. onmouseover='$(this).addClass(\"selection_highlight\");'
  3696. onmouseout='$(this).removeClass(\"selection_highlight\");'
  3697. ";
  3698. $hand_class = "hand";
  3699. $extra_style = $extra_classes = $extra_css = $extra_html = "";
  3700. // Add the name of the course to the extra-classes
  3701. $extra_classes .= " cr-" . fp_get_machine_readable($course->subject_id . " " . $course->course_num);
  3702. // Check to see if the course is in our required_courses_id_array for more than one degree.
  3703. if (isset($this->degree_plan->required_course_id_array[$course->course_id])) {
  3704. if (count($this->degree_plan->required_course_id_array[$course->course_id]) > 1) {
  3705. // Add a new classname for this course...
  3706. $extra_classes .= " course-appears-in-mult-degrees course-appears-in-" . count($this->degree_plan->required_course_id_array[$course->course_id]) . "-degrees";
  3707. }
  3708. }
  3709. // Assemble theme array elements for the course itself.
  3710. $theme["course"] = array(
  3711. "course" => $course,
  3712. "course_id" => $course->course_id,
  3713. "js_code" => $js_code,
  3714. "subject_id" => $subject_id,
  3715. "course_num" => $course_num,
  3716. "display_status" => $display_status,
  3717. "extra_classes" => $extra_classes,
  3718. "hours" => $hours,
  3719. "var_hour_icon" => $var_hour_icon,
  3720. "grade" => $grade,
  3721. "pts" => $pts,
  3722. "title" => $title_text,
  3723. "extra_html" => $extra_html,
  3724. );
  3725. $op_on_click_function = "adviseSelectCourseFromGroupPopup";
  3726. $theme["op"] = array(
  3727. "display_status" => $display_status,
  3728. "extra_css" => $extra_css,
  3729. "onclick" => array(
  3730. "function" => $op_on_click_function,
  3731. "arguments" => array(""),
  3732. ),
  3733. "checked" => $checked,
  3734. "hidden_field" => "<input type='hidden' name='$course_id" . "_subject'
  3735. id='$course_id" . "_subject' value='$subject_id'>
  3736. <input type='hidden' name='$course_id" . "_db_group_requirement_id'
  3737. id='$course_id" . "_db_group_requirement_id' value='$db_group_requirement_id'>
  3738. <input type='hidden' name='$course_id" . "_req_by_degree_id' id='$course_id" . "_req_by_degree_id' value='$req_by_degree_id'>
  3739. <input type='hidden' name='$course_id" . "_min_var_hours' id='$course_id" . "_min_var_hours' value='$min_var_hours'>
  3740. ",
  3741. );
  3742. $theme["course"]["js_code"] = $js_code;
  3743. // Invoke a hook on our theme array, so other modules have a chance to change it up.
  3744. invoke_hook("theme_advise_course_row", array(&$theme));
  3745. /////////////////////////////////
  3746. // Actually draw out our $theme array now....
  3747. // The checkbox & hidden element....
  3748. $op = $hid = "";
  3749. if (isset($theme["op"]) && count($theme["op"]) > 0) {
  3750. $onclick = "";
  3751. $onclick = $theme["op"]["onclick"]["function"] . "(\"" . join("\",\"", $theme["op"]["onclick"]["arguments"]) . "\")";
  3752. $checked = $theme["op"]["checked"];
  3753. $hid = $theme["op"]["hidden_field"];
  3754. $op = "<input type='radio' name='course' class='cb-course' id='cb-course-$course_id' value='$course_id' $checked onClick='return $onclick;' $extra_css>";
  3755. }
  3756. // The icon....
  3757. $icon_html = "";
  3758. if (isset($theme["icon"]) && count($theme["icon"]) > 0) {
  3759. $icon_html = "<img class='advising-course-row-icon'
  3760. src='{$theme["icon"]["location"]}/{$theme["icon"]["filename"]}' width='14' height='14' border='0' alt='{$theme["icon"]["title"]}' title='{$theme["icon"]["title"]}'>";
  3761. }
  3762. if ($course->bool_unselectable == true)
  3763. {
  3764. // Cannot be selected, so remove that ability!
  3765. $hand_class = "";
  3766. $on_mouse_over = "";
  3767. $js_code = "";
  3768. $op = $op_on_click_function = "";
  3769. $extra_style = "style='font-style: italic; color:gray;'";
  3770. }
  3771. //////////////////////////////////////
  3772. //////////////////////////////////////
  3773. // Actually draw the row's HTML
  3774. //////////////////////////////////////
  3775. $js_code = $theme["course"]["js_code"];
  3776. $pC .= "
  3777. <table border='0' cellpadding='0' width='100%' cellspacing='0' align='left' class='group-course-row $attributes_class'>
  3778. <tr class='$hand_class {$theme["course"]["display_status"]} {$theme["course"]["extra_classes"]}'
  3779. $on_mouse_over title='{$theme["course"]["title"]}'>
  3780. <td width='$w1_1' class='group-w1_1' align='left'>$op$hid<span onClick='$js_code'>$icon_html</span></td>
  3781. <td width='$w1_2' class='group-w1_2' align='left' onClick='$js_code'> </td>
  3782. <td width='$w1_3' class='group-w1_3' align='left' onClick='$js_code'>&nbsp;</td>
  3783. <td align='left' width='$w2' class=' underline group-w2'
  3784. onClick='$js_code' $extra_style>
  3785. {$theme["course"]["subject_id"]}</td>
  3786. <td class=' underline group-w3' $extra_style width='$w3' align='left'
  3787. onClick='$js_code'>
  3788. {$theme["course"]["course_num"]}</td>
  3789. ";
  3790. if ($repeats > 0 && $repeats < 20 && $show_repeat_information)
  3791. {
  3792. $pC .= "
  3793. <td class=' underline group-may-repeat' style='color: gray;'
  3794. onClick='$js_code' colspan='3'>
  3795. <i>" . t("May take up to") . " <span style='color: blue;'>" . ($repeats + 1) . "</span> " . t("times.") . "</i>
  3796. </td>
  3797. ";
  3798. }
  3799. else if ($repeats > 0 && $repeats >= 20 && $show_repeat_information) {
  3800. $pC .= "
  3801. <td class=' underline group-may-repeat' style='color: gray;'
  3802. onClick='$js_code' colspan='3'>
  3803. <i>" . t("May be repeated for credit.") . "</i>
  3804. </td>
  3805. ";
  3806. }
  3807. else if ($theme["course"]["extra_html"] != "") {
  3808. $pC .= "
  3809. <td class=' underline' class='group-w4' width='$w4' onClick='$js_code' $extra_style>{$theme["course"]["hours"]} {$theme["course"]["var_hour_icon"]}</td>
  3810. <td class=' underline group-course-extra-html'
  3811. onClick='$js_code' colspan='10'>
  3812. {$theme["course"]["extra_html"]}
  3813. </td>
  3814. ";
  3815. }
  3816. else {
  3817. $pC .= "
  3818. <td class=' underline' class='group-w4' width='$w4' onClick='$js_code' $extra_style>{$theme["course"]["hours"]} {$theme["course"]["var_hour_icon"]}</td>
  3819. <td class=' underline' class='group-w5' width='$w5' onClick='$js_code'>{$theme["course"]["grade"]}&nbsp;</td>
  3820. <td class=' underline' class='group-w6' width='$w6' onClick='$js_code'>{$theme["course"]["pts"]}&nbsp;</td>
  3821. ";
  3822. }
  3823. $pC .= "
  3824. </tr>
  3825. </table>";
  3826. return $pC;
  3827. }
  3828. /**
  3829. * This is used to display the substitution popup to a user, to let them
  3830. * actually make a substitution.
  3831. *
  3832. * @param int $course_id
  3833. * @param int $group_id
  3834. * @param int $semester_num
  3835. * @param int $hours_avail
  3836. *
  3837. * @return string
  3838. */
  3839. function display_popup_substitute($course_id = 0, $group_id, $semester_num, $hours_avail = "", $req_by_degree_id = 0)
  3840. {
  3841. global $current_student_id;
  3842. // This lets the user make a substitution for a course.
  3843. $pC = "";
  3844. $school_id = db_get_school_id_for_student_id($current_student_id);
  3845. // Bring in advise's css...
  3846. fp_add_css(fp_get_module_path("advise") . "/css/advise.css");
  3847. $course = new Course($course_id);
  3848. $bool_sub_add = false;
  3849. $req_degree_plan = new DegreePlan();
  3850. $req_degree_plan->degree_id = $req_by_degree_id;
  3851. if ($req_by_degree_id > 0) {
  3852. $course->req_by_degree_id = $req_by_degree_id;
  3853. $req_degree_plan->load_descriptive_data();
  3854. }
  3855. $c_title = t("Substitute for") . " $course->subject_id $course->course_num";
  3856. if ($course_id == 0)
  3857. {
  3858. $c_title = t("Substitute an additional course");
  3859. $bool_sub_add = true;
  3860. }
  3861. $pC .= fp_render_section_title($c_title);
  3862. if ($req_by_degree_id > 0) {
  3863. $pC .= "<div class=' sub-req-by-degree-title-line'>" . t("This substitution will only affect the <b>%title</b> degree requirements.", array("%title" => $req_degree_plan->get_title2())) . "
  3864. </div>";
  3865. }
  3866. $extra = ".<input type='checkbox' id='cbAddition' value='true' style='display:none;'>";
  3867. if ($group_id > 0)
  3868. {
  3869. $new_group = new Group($group_id);
  3870. $checked = "";
  3871. if ($bool_sub_add == true){$checked = "checked disabled";}
  3872. $extra = " " . t("in the group %newg.", array("%newg" => $new_group->title)) . "
  3873. " . t("Addition only:") . " <input type='checkbox' id='cbAddition' value='true' $checked>
  3874. <a href='javascript: alertSubAddition();'>?</a>";
  3875. }
  3876. $c_hours = $course->max_hours*1;
  3877. $c_ghost_hour = "";
  3878. if ($course->bool_ghost_hour == TRUE) {
  3879. $c_ghost_hour = t("ghost") . "<a href='javascript: alertSubGhost();'>?</a>";
  3880. }
  3881. if (($hours_avail*1 > 0 && $hours_avail < $c_hours) || ($c_hours <= 0))
  3882. {
  3883. // Use the remaining hours if we have fewer hours left in
  3884. // the group than the course we are subbing for.
  3885. $c_hours = $hours_avail;
  3886. }
  3887. if ($hours_avail == "" || $hours_avail*1 <= 0)
  3888. {
  3889. $hours_avail = $c_hours;
  3890. }
  3891. $pC .= "<div class=' '>
  3892. " . t("Please select a course to substitute
  3893. for %course", array("%course" => "$course->subject_id $course->course_num ($c_hours $c_ghost_hour " . t("hrs") . ")")) . "$extra
  3894. </div>
  3895. ";
  3896. // If this course has ghost hours, and if we've set that you can only sub ghost hours
  3897. // for other ghost hours, then display a message here explaining that.
  3898. $bool_ghost_for_ghost = (variable_get("restrict_ghost_subs_to_ghost_hours", "yes") == "yes" && $course->bool_ghost_hour);
  3899. if ($bool_ghost_for_ghost) {
  3900. $pC .= "<div class=' '>" . t("<b>Note:</b> As per a setting in FlightPath, the only courses which
  3901. may be substituted must be worth zero hours (1 ghost hour).") . "</div>";
  3902. }
  3903. $pC .= "
  3904. <div class=' '
  3905. style='height: 175px; overflow: auto; border:1px inset black; padding: 5px;'>
  3906. <table border='0' cellpadding='0' cellspacing='0' width='100%'>
  3907. ";
  3908. $this->student->list_courses_taken->sort_alphabetical_order(false, true, FALSE, $req_by_degree_id);
  3909. $school_id = db_get_school_id_for_student_id($this->student->student_id);
  3910. for ($t = 0; $t <= 1; $t++)
  3911. {
  3912. if ($t == 0) {$the_title = variable_get_for_school("school_initials", "DEMO", $school_id) . " " . t("Credits"); $bool_transferTest = true;}
  3913. if ($t == 1) {$the_title = t("Transfer Credits"); $bool_transferTest = false;}
  3914. $pC .= "<tr><td colspan='3' valign='top' class=' ' style='padding-bottom: 10px;'>
  3915. $the_title
  3916. </td>
  3917. <td class=' ' valign='top' >" . t("Hrs") . "</td>
  3918. <td class=' ' valign='top' >" . t("Grd") . "</td>
  3919. <td class=' ' valign='top' >" . t("Term") . "</td>
  3920. </tr>";
  3921. $already_seen = array(); // keep track of the courses we've already seen.
  3922. $used_hours_subs = array(); // extra help keeping up with how many hours we've used for particular courses in split up subs.
  3923. $is_empty = true;
  3924. $this->student->list_courses_taken->reset_counter();
  3925. while($this->student->list_courses_taken->has_more())
  3926. {
  3927. $c = $this->student->list_courses_taken->get_next();
  3928. if ($c->bool_transfer == $bool_transferTest)
  3929. {
  3930. continue;
  3931. }
  3932. if (!$c->meets_min_grade_requirement_of(null, variable_get_for_school("minimum_substitutable_grade", "D", $school_id)))
  3933. {// Make sure the grade is OK.
  3934. continue;
  3935. }
  3936. $bool_disable_selection = $disabled_msg = FALSE;
  3937. // Should we skip this course, because of a ghost_for_ghost requirement?
  3938. if ($bool_ghost_for_ghost && !$c->bool_ghost_hour) {
  3939. continue;
  3940. }
  3941. // If we are supposed to restrict ghost for ghost, but the course does NOT
  3942. // have a ghost hour, and this $c course does, then disable it
  3943. if (variable_get_for_school("restrict_ghost_subs_to_ghost_hours", "yes", $school_id) == "yes"
  3944. && $course->bool_ghost_hour != TRUE
  3945. && $c->bool_ghost_hour == TRUE) {
  3946. $bool_disable_selection = TRUE;
  3947. $disabled_msg = t("Substitution of this course has been disabled.
  3948. As per a setting in FlightPath, courses worth zero hours (1 ghost hour)
  3949. may only be substituted for course requirements also worth zero hours.");
  3950. }
  3951. $t_flag = 0;
  3952. if ($c->bool_transfer == true)
  3953. {
  3954. $t_flag = 1;
  3955. }
  3956. $is_empty = false;
  3957. $subject_id = $c->subject_id;
  3958. $course_num = $c->course_num;
  3959. $tcourse_id = $c->course_id;
  3960. if ($bool_transferTest == false)
  3961. {
  3962. // Meaning, we are looking at transfers now.
  3963. // Does the transfer course have an eqv set up? If so,
  3964. // we want *that* course to appear.
  3965. if (is_object($c->course_transfer))
  3966. {
  3967. $subject_id = $c->course_transfer->subject_id;
  3968. $course_num = $c->course_transfer->course_num;
  3969. $tcourse_id = $c->course_transfer->course_id;
  3970. $t_flag = 1;
  3971. }
  3972. }
  3973. $m_hours = $c->get_hours_awarded($req_by_degree_id);
  3974. /*
  3975. *
  3976. * We don't want to do this. What it's saying is if the max_hours (from the course database)
  3977. * is LESS than the awarded hours, use the lower hours. Instead, we want to always use
  3978. * what the student was AWARDED.
  3979. *
  3980. if ($c->max_hours*1 < $m_hours)
  3981. {
  3982. $m_hours = $c->max_hours*1;
  3983. }
  3984. */
  3985. if (($hours_avail*1 > 0 && $hours_avail < $m_hours) || ($m_hours == 0))
  3986. {
  3987. $m_hours = $hours_avail;
  3988. }
  3989. // is max_hours more than the original course's hours?
  3990. if ($m_hours > $c_hours)
  3991. {
  3992. $m_hours = $c_hours;
  3993. }
  3994. if ($m_hours > $c->get_hours_awarded($req_by_degree_id))
  3995. {
  3996. $m_hours = $c->get_hours_awarded($req_by_degree_id);
  3997. }
  3998. // If we have already displayed this EXACT course, then we shouldn't display it again. This is to
  3999. // fix a multi-degree bug, where we see the same course however many times it was split for a DIFFERENT degree.
  4000. // If it's never been split for THIS degree, it should just show up as 1 course.
  4001. $ukey = md5($c->course_id . $c->catalog_year . $c->term_id . $m_hours . $tcourse_id . intval(@$c->db_substitution_id_array[$req_by_degree_id]));
  4002. if (isset($already_seen[$ukey])) {
  4003. continue;
  4004. }
  4005. // Else, add it.
  4006. $already_seen[$ukey] = TRUE;
  4007. // We should also keep up with how many hours have been used by this sub...
  4008. // Is this course NOT a substitution for this degree, and NOT an outdated sub?
  4009. // In other words, are we safe to just display this course as an option for selection?
  4010. if ($c->get_bool_substitution($req_by_degree_id) != TRUE && $c->get_bool_outdated_sub($req_by_degree_id) != TRUE)
  4011. {
  4012. $h = $c->get_hours_awarded($req_by_degree_id);
  4013. if ($c->bool_ghost_hour == TRUE) {
  4014. $h .= "(ghost<a href='javascript: alertSubGhost();'>?</a>)";
  4015. }
  4016. // If this course was split up, we need to use our
  4017. // helper array to see what the OTHER, already-used pieces add up to.
  4018. if ($c->get_bool_substitution_split($req_by_degree_id)) {
  4019. $ukey = md5($c->course_id . $c->catalog_year . $c->term_id . $tcourse_id);
  4020. if (isset($used_hours_subs[$ukey])) {
  4021. $used_hours = $used_hours_subs[$ukey];
  4022. // Get the remaining hours by subtracting the ORIGINAL hours for this course against
  4023. // the used hours.
  4024. // Okay, I believe this is a bug. Somewhere, I have set the hours_awarded to the remaining hours, so
  4025. // this math is no longer needed.
  4026. /*
  4027. $remaining_hours = $c->get_hours_awarded(0) - $used_hours; // (0) gets the original hours awarded.
  4028. if ($remaining_hours > 0) {
  4029. $h = $remaining_hours;
  4030. }*/
  4031. }
  4032. }
  4033. $pC .= "<tr>
  4034. <td valign='top' class=' ' width='15%'>
  4035. <input type='radio' name='subCourse' id='subCourse' value='$tcourse_id'
  4036. onClick='popupUpdateSubData(\"$m_hours\",\"$c->term_id\",\"$t_flag\",\"$hours_avail\",\"" . $c->get_hours_awarded($req_by_degree_id) . "\");'
  4037. ";
  4038. if ($bool_disable_selection) $pC .= "disabled=disabled";
  4039. $pC .= " >";
  4040. if ($disabled_msg) {
  4041. $pC .= fp_get_js_alert_link(fp_reduce_whitespace(str_replace("\n", " ", $disabled_msg)), "?");
  4042. }
  4043. $pC .= "
  4044. </td>
  4045. <td valign='top' class=' underline' width='13%'>
  4046. $subject_id
  4047. </td>
  4048. <td valign='top' class=' underline' width='15%'>
  4049. $course_num
  4050. </td>
  4051. <td valign='top' class=' underline' width='10%'>
  4052. $h
  4053. </td>
  4054. <td valign='top' class=' underline' width='10%'>
  4055. $c->grade
  4056. </td>
  4057. <td valign='top' class=' underline'>
  4058. " . $c->get_term_description(true) . "
  4059. </td>
  4060. </tr>
  4061. ";
  4062. }
  4063. else {
  4064. // Does this course have a substitution for THIS degree?
  4065. if (!is_object($c->get_course_substitution($req_by_degree_id))) {
  4066. continue;
  4067. }
  4068. if (is_object($c->get_course_substitution($req_by_degree_id)) && $c->get_course_substitution($req_by_degree_id)->subject_id == "")
  4069. { // Load subject_id and course_num of the original
  4070. // requirement.
  4071. $c->get_course_substitution($req_by_degree_id)->load_descriptive_data();
  4072. }
  4073. $extra = "";
  4074. //if ($c->assigned_to_group_id > 0)
  4075. if ($c->get_bool_assigned_to_group_id(-1))
  4076. {
  4077. // TODO: based on degree (hint: probably so...?
  4078. $new_group = new Group($c->get_first_assigned_to_group_id());
  4079. $extra = " in $new_group->title";
  4080. }
  4081. if ($c->get_bool_outdated_sub($req_by_degree_id))
  4082. {
  4083. $help_link = fp_get_js_alert_link(t("This substitution is outdated. It was made for a course or group which does not currently appear on the student's degree plan. You may remove this sub using the Administrator's Toolbox, at the bottom of the View tab."), "?");
  4084. $extra .= " <span style='color:red;'>[" . t("Outdated") . "$help_link]</span>";
  4085. }
  4086. // It has already been substituted!
  4087. $pC .= "<tr style='background-color: beige;'>
  4088. <td valign='top' class=' ' width='15%'>
  4089. " . t("Sub:") . "
  4090. </td>
  4091. <td valign='top' class=' ' colspan='5'>
  4092. $subject_id
  4093. $course_num (" . $c->get_substitution_hours($req_by_degree_id) . ")
  4094. -> " . $c->get_course_substitution($req_by_degree_id)->subject_id . "
  4095. " . $c->get_course_substitution($req_by_degree_id)->course_num . "$extra
  4096. </td>
  4097. </tr>
  4098. ";
  4099. // Keep track of how many hours THIS course has been subbed, if it was split.
  4100. $ukey = md5($c->course_id . $c->catalog_year . $c->term_id . $tcourse_id);
  4101. if (!isset($used_hours_subs[$ukey])) $used_hours_subs[$ukey] = 0;
  4102. $used_hours_subs[$ukey] += $c->get_substitution_hours($req_by_degree_id);
  4103. }
  4104. // If this was a transfer course, have an extra line under the course, stating it's title.
  4105. if ($bool_transferTest == FALSE) { // Means this IS INDEED a transfer courses.
  4106. $c->course_transfer->load_descriptive_transfer_data($this->student->student_id, $c->term_id);
  4107. $pC .= "<tr class='advise-substitute-popup-transfer-course-title'>
  4108. <td colspan='8'>
  4109. {$c->course_transfer->title} ({$c->course_transfer->institution_name})
  4110. </td>
  4111. </tr>";
  4112. }
  4113. } // while list_courses_taken
  4114. if ($is_empty == true)
  4115. {
  4116. // Meaning, there were no credits (may be the case with
  4117. // transfer credits)
  4118. $pC .= "<tr><td colspan='8' class=' '>
  4119. - " . t("No substitutable credits available.") . "
  4120. </td></tr>";
  4121. }
  4122. $pC .= "<tr><td colspan='4'>&nbsp;</td></tr>";
  4123. }
  4124. $pC .= "</table></div>
  4125. <div class=' ' style='margin-top: 5px;'>
  4126. " . t("Select number of hrs to use:") . "
  4127. <select name='subHours' id='subHours' onChange='popupOnChangeSubHours()'>
  4128. <option value=''>" . t("None Selected") . "</option>
  4129. </select>
  4130. ";
  4131. // If we have entered manual hours (like for decimals), they go here:
  4132. // The subManual span will *display* them, the hidden field keeps them so they can be transmitted.
  4133. $pC .= "
  4134. <span id='subManual' style='font-style:italic; display:none;'></span>
  4135. <input type='hidden' id='subManualHours' value=''>
  4136. </div>
  4137. <input type='hidden' name='subTransferFlag' id='subTransferFlag' value=''>
  4138. <input type='hidden' name='subTermID' id='subTermID' value=''>
  4139. <input type='button' value='Save Substitution' onClick='popupSaveSubstitution(\"$course_id\",\"$group_id\",\"$semester_num\",\"$req_by_degree_id\");'>
  4140. <div class=' ' style='padding-top: 5px;'><b>" . t("Optional") . "</b> - " . t("Enter remarks:") . "
  4141. <input type='text' name='subRemarks' id='subRemarks' value='' size='30' maxlength='254'>
  4142. </div>
  4143. ";
  4144. return $pC;
  4145. }
  4146. /**
  4147. * This function displays the popup which lets a user select a course to be
  4148. * advised into a group.
  4149. *
  4150. * @param Group $place_group
  4151. * @param int $group_hours_remaining
  4152. * @return string
  4153. */
  4154. function display_popup_group_select(Group $place_group, $group_hours_remaining = 0, $req_by_degree_id = 0)
  4155. {
  4156. $pC = "";
  4157. $advising_term_id = $GLOBALS["fp_advising"]["advising_term_id"];
  4158. if ($req_by_degree_id == 0) {
  4159. $req_by_degree_id = $place_group->req_by_degree_id;
  4160. }
  4161. $bool_no_courses = FALSE;
  4162. if ($place_group->group_id != DegreePlan::GROUP_ID_FOR_COURSES_ADDED)
  4163. {
  4164. // This is NOT the Add a Course group.
  4165. if (!$group = $this->degree_plan->find_group($place_group->group_id))
  4166. {
  4167. fpm("Group not found.");
  4168. return;
  4169. }
  4170. else {
  4171. // Found the group... we don't need to do anything.
  4172. }
  4173. }
  4174. else {
  4175. // This is the Add a Course group.
  4176. $group = $place_group;
  4177. }
  4178. $group_id = $group->group_id;
  4179. // So now we have a group object, $group, which is most likely
  4180. // missing courses. This is because when we loaded & cached it
  4181. // earlier, we did not load any course which wasn't a "significant course,"
  4182. // meaning, the student didn't have credit for it or the like.
  4183. // So what we need to do now is reload the group, being careful
  4184. // to preserve the existing courses / sub groups in the group.
  4185. $group->reload_missing_courses();
  4186. if ($group_hours_remaining == 0)
  4187. {
  4188. // Attempt to figure out the remaining hours (NOT WORKING IN ALL CASES!)
  4189. // This specifically messes up when trying to get fulfilled hours in groups
  4190. // with branches.
  4191. $group_fulfilled_hours = $group->get_fulfilled_hours(true, true, false, $place_group->assigned_to_semester_num);
  4192. $group_hours_remaining = $place_group->hours_required - $group_fulfilled_hours;
  4193. }
  4194. $display_semesterNum = $place_group->assigned_to_semester_num;
  4195. $pC .= "<!--MSG--><!--MSG2--><!--BOXTOP-->";
  4196. $bool_display_submit = true;
  4197. $bool_display_back_to_subject_select = false;
  4198. $bool_subject_select = false;
  4199. $bool_unselectableCourses = false;
  4200. $final_course_list = new CourseList();
  4201. $public_note = trim($group->public_note);
  4202. if ($public_note) {
  4203. $pC .= "<tr><td colspan='8'><div class='group-public-note'>" . $public_note . "</div></td></tr>";
  4204. }
  4205. $group_sort_policy = variable_get_for_school("group_requirement_sort_policy", "alpha", $this->student->school_id);
  4206. $group->list_courses->reset_counter();
  4207. if (!($group->list_courses->is_empty))
  4208. {
  4209. $group->list_courses->assign_semester_num($display_semesterNum);
  4210. $new_course_list = $group->list_courses;
  4211. // Is this list so long that we first need to ask the user to
  4212. // select a subject?
  4213. if ($new_course_list->get_size() > 30)
  4214. {
  4215. // First, we are only going to do this if there are more
  4216. // than 30 courses, AND more than 2 subjects in the list.
  4217. $new_course_list->sort_alphabetical_order();
  4218. $subject_array = $new_course_list->get_course_subjects();
  4219. //print_pre($new_course_list->to_string());
  4220. //var_dump($subject_array);
  4221. if (count($subject_array) > 2)
  4222. {
  4223. // First, check to see if the user has already
  4224. // selected a subject.
  4225. $selected_subject = trim(addslashes(@$_GET["selected_subject"]));
  4226. if ($selected_subject == "")
  4227. {
  4228. // Prompt them to select a subject first.
  4229. $pC .= $this->draw_popup_group_subject_select($subject_array, $group->group_id, $display_semesterNum, $group_hours_remaining, $req_by_degree_id);
  4230. $new_course_list = new CourseList(); // empty it
  4231. $bool_display_submit = false;
  4232. $bool_subject_select = true;
  4233. } else {
  4234. // Reduce the newCourseList to only contain the
  4235. // subjects selected.
  4236. $new_course_list->exclude_all_subjects_except($selected_subject);
  4237. $bool_display_back_to_subject_select = true;
  4238. }
  4239. }
  4240. }
  4241. if ($group_sort_policy == 'database') {
  4242. $new_course_list->sort_group_requirement_id();
  4243. }
  4244. else {
  4245. // By default, sort alphabetical
  4246. $new_course_list->sort_alphabetical_order();
  4247. }
  4248. $new_course_list->reset_counter();
  4249. $final_course_list->add_list($new_course_list);
  4250. }
  4251. if (!($group->list_groups->is_empty))
  4252. {
  4253. // Basically, this means that this group
  4254. // has multiple subgroups. We need to find out
  4255. // which branches the student may select from
  4256. // (based on what they have already taken, or been
  4257. // advised to take), and display it (excluding duplicates).
  4258. //print_pre($group->to_string());
  4259. // The first thing we need to do, is find the subgroup
  4260. // or subgroups with the most # of matches.
  4261. $new_course_list = new CourseList();
  4262. $all_zero= true;
  4263. // Okay, this is a little squirely. What I need to do
  4264. // first is get a course list of all the courses which
  4265. // are currently either fulfilling or advised for all branches
  4266. // of this group.
  4267. $fa_course_list = new CourseList();
  4268. $group->list_groups->reset_counter();
  4269. while($group->list_groups->has_more())
  4270. {
  4271. $branch = $group->list_groups->get_next();
  4272. $fa_course_list->add_list($branch->list_courses->get_fulfilled_or_advised(true));
  4273. }
  4274. $fa_course_list->remove_duplicates();
  4275. //print_pre($fa_course_list->to_string());
  4276. // Alright, now we create a fake student and set their
  4277. // list_courses_taken, so that we can use this student
  4278. // to recalculate the count_of_matches in just a moment.
  4279. $new_student = new Student();
  4280. $new_student->load_student();
  4281. $new_student->list_courses_taken = $fa_course_list;
  4282. $new_student->load_significant_courses_from_list_courses_taken();
  4283. // Okay, now we need to go through and re-calculate our
  4284. // count_of_matches for each branch. This is because we
  4285. // have cached this value, and after some advisings, it may
  4286. // not be true any longer.
  4287. $highest_match_count = 0;
  4288. $group->list_groups->reset_counter();
  4289. while($group->list_groups->has_more())
  4290. {
  4291. $branch = $group->list_groups->get_next();
  4292. // recalculate count_of_matches here.
  4293. $clone_branch = new Group();
  4294. $clone_branch->list_courses = $branch->list_courses->get_clone(true);
  4295. $matches_count = $this->flightpath->get_count_of_matches($clone_branch, $new_student, $group);
  4296. $branch->count_of_matches = $matches_count;
  4297. if ($matches_count >= $highest_match_count)
  4298. { // Has more than one match on this branch.
  4299. $highest_match_count = $matches_count;
  4300. }
  4301. }
  4302. // If highestMatchCount > 0, then get all the branches
  4303. // which have that same match count.
  4304. if ($highest_match_count > 0)
  4305. {
  4306. $group->list_groups->reset_counter();
  4307. while($group->list_groups->has_more())
  4308. {
  4309. $branch = $group->list_groups->get_next();
  4310. if ($branch->count_of_matches == $highest_match_count)
  4311. { // This branch has the right number of matches. Add it.
  4312. $new_course_list->add_list($branch->list_courses);
  4313. $all_zero = false;
  4314. }
  4315. }
  4316. }
  4317. if ($all_zero == true)
  4318. {
  4319. // Meaning, all of the branches had 0 matches,
  4320. // so we should add all the branches to the
  4321. // newCourseList.
  4322. $group->list_groups->reset_counter();
  4323. while($group->list_groups->has_more())
  4324. {
  4325. $branch = $group->list_groups->get_next();
  4326. $new_course_list->add_list($branch->list_courses);
  4327. }
  4328. } else {
  4329. // Meaning that at at least one branch is favored.
  4330. // This also means that a user's course
  4331. // selections have been restricted as a result.
  4332. // Replace the MSG at the top saying so.
  4333. $msg = "<div class=' '>" . t("Your selection of courses has been
  4334. restricted based on previous course selections.") . "</div>";
  4335. $pC = str_replace("<!--MSG-->", $msg, $pC);
  4336. }
  4337. // Okay, in the newCourseList object, we should
  4338. // now have a list of all the courses the student is
  4339. // allowed to take, but there are probably duplicates.
  4340. //print_pre($new_course_list->to_string());
  4341. $new_course_list->remove_duplicates();
  4342. $new_course_list->assign_group_id($group->group_id);
  4343. $new_course_list->assign_semester_num($display_semesterNum);
  4344. $final_course_list->add_list($new_course_list);
  4345. }
  4346. // Remove courses which have been marked as "exclude" in the database.
  4347. $final_course_list->remove_excluded();
  4348. $final_course_list->assign_group_id($group->group_id); // make sure everyone is in THIS group.
  4349. //print_pre($final_course_list->to_string());
  4350. // Here's a fun one: We need to remove courses for which the student
  4351. // already has credit that *don't* have repeating hours.
  4352. // For example, if a student took MATH 113, and it fills in to
  4353. // Core Math, then we should not see it as a choice for advising
  4354. // in Free Electives (or any other group except Add a Course).
  4355. // We also should not see it in other instances of Core Math.
  4356. if ($group->group_id != DegreePlan::SEMESTER_NUM_FOR_COURSES_ADDED && $this->bool_blank != TRUE)
  4357. {
  4358. // Only do this if NOT in Add a Course group...
  4359. // also, don't do it if we're looking at a "blank" degree.
  4360. $final_course_list->remove_previously_fulfilled($this->student->list_courses_taken, $group->group_id, true, $this->student->list_substitutions, $req_by_degree_id);
  4361. }
  4362. if ($group_sort_policy == 'database') {
  4363. $final_course_list->sort_group_requirement_id();
  4364. }
  4365. else {
  4366. // By default, sort alphabetical
  4367. $final_course_list->sort_alphabetical_order();
  4368. }
  4369. // flag any courses with more hours than are available for this group.
  4370. if ($final_course_list->assign_unselectable_courses_with_hours_greater_than($group_hours_remaining))
  4371. {
  4372. $bool_unselectableCourses = true;
  4373. }
  4374. // Make sure all the courses in our final list have the same req_by_degree_id.
  4375. $final_course_list->set_req_by_degree_id($req_by_degree_id);
  4376. $pC .= $this->display_popup_group_select_course_list($final_course_list, $group_hours_remaining);
  4377. // If there were no courses in the finalCourseList, display a message.
  4378. if (count($final_course_list->array_list) < 1 && !$bool_subject_select)
  4379. {
  4380. $pC .= "<tr>
  4381. <td colspan='8'>
  4382. <div class=' '>
  4383. <b>Please Note:</b>
  4384. " . t("FlightPath could not find any eligible
  4385. courses to display for this list. Ask your advisor
  4386. if you have completed courses, or may enroll in
  4387. courses, which can be
  4388. displayed here.");
  4389. if (user_has_permission("can_advise_students")){
  4390. // This is an advisor, so put in a little more
  4391. // information.
  4392. $pC .= "
  4393. <div class=' ' style='padding-top: 5px;'><b>" . t("Special note to advisors:") . "</b> " . t("You may still
  4394. advise a student to take a course, even if it is unselectable
  4395. in this list. Use the \"add an additional course\" link at
  4396. the bottom of the page.") . "</div>";
  4397. }
  4398. $pC .= " </div>
  4399. </td>
  4400. </tr>";
  4401. $bool_no_courses = true;
  4402. }
  4403. $pC .= $this->draw_semester_box_bottom();
  4404. $s = "s";
  4405. //print_pre($place_group->to_string());
  4406. $unselectable_notice = "";
  4407. if ($group_hours_remaining == 1){$s = "";}
  4408. if ($bool_unselectableCourses == true) {
  4409. $unselectable_notice = " <div class=' '><i>(" . t("Courses worth more than %hrs hour$s
  4410. may not be selected.", array("%hrs" => $group_hours_remaining)) . ")</i></div>";
  4411. if (user_has_permission("can_advise_students")) {
  4412. // This is an advisor, so put in a little more
  4413. // information.
  4414. $unselectable_notice .= "
  4415. <div class=' ' style='padding-top: 5px;'><b>" . t("Special note to advisors:") . "</b> " . t("You may still
  4416. advise a student to take a course, even if it is unselectable
  4417. in this list. Use the \"add an additional course\" link at
  4418. the bottom of the page.") . "</div>";
  4419. }
  4420. }
  4421. if ($group_hours_remaining < 200 && $bool_no_courses != true) {
  4422. $disp_group_hours_remaining = $group_hours_remaining;
  4423. // If we have min_hours, display that information.
  4424. if ($place_group->has_min_hours_allowed()) {
  4425. // Make sure the "real" group has the same min hours set.
  4426. $group->min_hours_allowed = $place_group->min_hours_allowed;
  4427. }
  4428. if ($group->has_min_hours_allowed()) {
  4429. $g_fulfilled_hours = $group->hours_required - $group_hours_remaining; // How many have we actually used?
  4430. $d_min_hours = $group->min_hours_allowed - $g_fulfilled_hours; // min hours must be reduced by the number already assigned
  4431. $disp_group_hours_remaining = $d_min_hours . "-" . $group_hours_remaining;
  4432. }
  4433. // Don't show for huge groups (like add-a-course)
  4434. $pC .= "<div class=' ' style='margin-top:5px;'>
  4435. " . t("You may select <b>@hrs</b>
  4436. hour$s from this list.", array("@hrs" => $disp_group_hours_remaining)) . "$unselectable_notice</div>";
  4437. }
  4438. ////////////////////////////////
  4439. // TODO: Conditions on which this will even appear? Like only if the student has more than one degree selected?
  4440. // What degrees is this group req by?
  4441. $t_degree_plan = new DegreePlan();
  4442. $t_degree_plan->degree_id = $req_by_degree_id;
  4443. $t = $t_degree_plan->get_title2(FALSE, TRUE);
  4444. if (trim($t) != "") {
  4445. $pC .= "<div class=' group-select-req-by-degree'>
  4446. " . t("This group is required by ");
  4447. $html = "";
  4448. $html .= "<span class='group-req-by-degree-title'>" . $t . "</span>";
  4449. $pC .= "$html</div>";
  4450. }
  4451. /////////////////////////////
  4452. if ($bool_display_submit == true && !$this->bool_blank && $bool_no_courses != true)
  4453. {
  4454. if (user_has_permission("can_advise_students")) {
  4455. $pC .= "<input type='hidden' name='varHours' id='varHours' value=''>
  4456. <div style='margin-top: 20px;'>
  4457. " . fp_render_button(t("Select Course"), "popupAssignSelectedCourseToGroup(\"$place_group->assigned_to_semester_num\", \"$group->group_id\",\"$advising_term_id\",\"-1\");", true, "style='font-size: 10pt;'") . "
  4458. </div>
  4459. ";
  4460. }
  4461. }
  4462. // Substitutors get extra information:
  4463. if (user_has_permission("can_substitute") && $group->group_id != DegreePlan::GROUP_ID_FOR_COURSES_ADDED)
  4464. {
  4465. $pC .= "<div class=' ' style='margin-top: 20px;'>
  4466. <b>" . t("Special administrative information:") . "</b>
  4467. <span id='viewinfolink'
  4468. onClick='document.getElementById(\"admin_info\").style.display=\"\"; this.style.display=\"none\"; '
  4469. class='hand' style='color: blue;'
  4470. > - " . t("Click to show") . " -</span>
  4471. <div style='padding-left: 20px; display:none;' id='admin_info'>
  4472. " . t("Information about this group:") . "<br>
  4473. &nbsp; " . t("Group ID:") . " $group->group_id<br>
  4474. &nbsp; " . t("Title:") . " $group->title<br>";
  4475. $pC .= "&nbsp; <i>" . t("Internal name:") . " $group->group_name</i><br>";
  4476. $pC .= "&nbsp; " . t("Catalog year:") . " $group->catalog_year
  4477. </div>
  4478. </div>";
  4479. }
  4480. if ($bool_display_back_to_subject_select == true) {
  4481. $csid = $GLOBALS["current_student_id"];
  4482. $blank_degree_id = "";
  4483. if ($this->bool_blank)
  4484. {
  4485. $blank_degree_id = $this->degree_plan->degree_id;
  4486. }
  4487. $back_link = "<span class=' '>
  4488. <a href='" . fp_url("advise/popup-group-select", "window_mode=popup&group_id=$group->group_id&semester_num=$display_semesterNum&group_hours_remaining=$group_hours_remaining&current_student_id=$csid&blank_degree_id=$blank_degree_id") . "'
  4489. class='nounderline'>&laquo; " . t("return to subject selection") . "</a></span>";
  4490. $pC = str_replace("<!--MSG2-->",$back_link,$pC);
  4491. }
  4492. $box_top = $this->draw_semester_box_top("$group->title", !$bool_display_submit);
  4493. $pC = str_replace("<!--BOXTOP-->",$box_top,$pC);
  4494. watchdog("advise", "popup_group_select id:$group->group_id, name:$group->group_name, semester_num:$display_semesterNum", array(), WATCHDOG_DEBUG);
  4495. return $pC;
  4496. }
  4497. /**
  4498. * When the groupSelect has too many courses, they are broken down into
  4499. * subjects, and the user first selects a subject. This function will
  4500. * draw out that select list.
  4501. *
  4502. * @param array $subject_array
  4503. * @param int $group_id
  4504. * @param int $semester_num
  4505. * @param int $group_hours_remaining
  4506. * @return string
  4507. */
  4508. function draw_popup_group_subject_select($subject_array, $group_id, $semester_num, $group_hours_remaining = 0, $req_by_degree_id = 0)
  4509. {
  4510. $csid = $GLOBALS["current_student_id"];
  4511. $blank_degree_id = "";
  4512. if ($this->bool_blank)
  4513. {
  4514. $blank_degree_id = $this->degree_plan->degree_id;
  4515. }
  4516. $db = get_global_database_handler();
  4517. $school_id = db_get_school_id_for_student_id($this->student->student_id);
  4518. $pC = "";
  4519. $clean_urls = variable_get("clean_urls", FALSE);
  4520. $pC .= "<tr><td colspan='8' class=' '>";
  4521. $pC .= "<form action='" . fp_url("advise/popup-group-select") . "' method='GET' style='margin:0px; padding:0px;' id='theform'>
  4522. <input type='hidden' name='window_mode' value='popup'>
  4523. <input type='hidden' name='group_id' value='$group_id'>";
  4524. if (!$clean_urls) {
  4525. // Hack so that non-clean URLs sites still work
  4526. $pC .= "<input type='hidden' name='q' value='advise/popup-group-select'>";
  4527. }
  4528. $pC .= "
  4529. <input type='hidden' name='semester_num' value='$semester_num'>
  4530. <input type='hidden' name='group_hours_remaining' value='$group_hours_remaining'>
  4531. <input type='hidden' name='current_student_id' value='$csid'>
  4532. <input type='hidden' name='blank_degree_id' value='$blank_degree_id'>
  4533. <input type='hidden' name='req_by_degree_id' value='$req_by_degree_id'>
  4534. " . t("Please begin by selecting a subject from the list below.") . "
  4535. <br><br>
  4536. <select name='selected_subject'>
  4537. <option value=''>" . t("Please select a subject...") . "</option>
  4538. <option value=''>----------------------------------------</option>
  4539. ";
  4540. $new_array = array();
  4541. foreach($subject_array as $key => $subject_id)
  4542. {
  4543. if ($title = $this->flightpath->get_subject_title($subject_id, $school_id)) {
  4544. $new_array[] = "$title ~~ $subject_id";
  4545. } else {
  4546. $new_array[] = "$subject_id ~~ $subject_id";
  4547. }
  4548. }
  4549. sort($new_array);
  4550. foreach ($new_array as $key => $value)
  4551. {
  4552. $temp = explode(" ~~ ",$value);
  4553. $title = trim($temp[0]);
  4554. $subject_id = trim($temp[1]);
  4555. $pC .= "<option value='$subject_id'>$title ($subject_id)</option>";
  4556. }
  4557. $pC .= "</select>
  4558. <div style='margin: 20px;' align='left'>
  4559. " . fp_render_button(t("Next") . " ->","document.getElementById(\"theform\").submit();") . "
  4560. </div>
  4561. <!-- <input type='submit' value='submit'> -->
  4562. </form>
  4563. ";
  4564. $pC .= "</td></tr>";
  4565. return $pC;
  4566. }
  4567. /**
  4568. * Accepts a CourseList object and draws it out to the screen. Meant to
  4569. * be called by display_popup_group_select();
  4570. *
  4571. * @param CourseList $course_list
  4572. * @param int $group_hours_remaining
  4573. * @return string
  4574. */
  4575. function display_popup_group_select_course_list(CourseList $course_list = null, $group_hours_remaining = 0)
  4576. {
  4577. // Accepts a CourseList object and draws it out to the screen. Meant to
  4578. // be called by display_popup_group_select().
  4579. $rtn = "";
  4580. if ($course_list == null)
  4581. {
  4582. return;
  4583. }
  4584. $old_course = null;
  4585. $bool_has_recommended = FALSE;
  4586. $course_list->reset_counter();
  4587. while($course_list->has_more())
  4588. {
  4589. $course = $course_list->get_next();
  4590. if ($course->equals($old_course))
  4591. { // don't display the same course twice in a row.
  4592. continue;
  4593. }
  4594. if ($course->db_group_attributes == "*") {
  4595. $bool_has_recommended = TRUE;
  4596. }
  4597. $rtn .= "<tr><td colspan='8'>";
  4598. // Only display this course for advising IF it hasn't been fulfilled, or if it has infinite repeats, and only if it isn't already
  4599. // advised to be taken.
  4600. if (($course->course_list_fulfilled_by->is_empty || $course->specified_repeats == Group::GROUP_COURSE_INFINITE_REPEATS) && !$course->bool_advised_to_take ){
  4601. // So, only display if it has not been fulfilled by anything.
  4602. $rtn .= $this->draw_popup_group_select_course_row($course, $group_hours_remaining);
  4603. $old_course = $course;
  4604. }
  4605. $rtn .= "</td></tr>";
  4606. }
  4607. if ($bool_has_recommended) {
  4608. $rtn .= "<tr><td colspan='8'><span class='group-recommended-message'>" . t("<b>Note:</b> Courses in <strong>bold</strong> are recommended.") . "</span></td></tr>";
  4609. }
  4610. return $rtn;
  4611. }
  4612. /**
  4613. * Returns a list of "hidden" HTML input tags which are used to keep
  4614. * track of advising variables between page loads.
  4615. *
  4616. * @param string $perform_action
  4617. * - Used for when we submit the form, so that FlightPath will
  4618. * know what action we are trying to take.
  4619. *
  4620. * @return string
  4621. */
  4622. function get_hidden_advising_variables($perform_action = "")
  4623. {
  4624. $school_id = db_get_school_id_for_student_id($GLOBALS["fp_advising"]["current_student_id"]);
  4625. $rtn = "";
  4626. if (!isset($GLOBALS["print_view"])) $GLOBALS["print_view"] = "";
  4627. $rtn .= "<span id='hidden_elements'>
  4628. <input type='hidden' name='perform_action' id='perform_action' value='$perform_action'>
  4629. <input type='hidden' name='perform_action2' id='perform_action2' value=''>
  4630. <input type='hidden' name='scroll_top' id='scroll_top' value=''>
  4631. <input type='hidden' name='load_from_cache' id='load_from_cache' value='yes'>
  4632. <input type='hidden' name='print_view' id='print_view' value='{$GLOBALS["print_view"]}'>
  4633. <input type='hidden' name='hide_charts' id='hide_charts' value=''>
  4634. <input type='hidden' name='advising_load_active' id='advising_load_active' value='{$GLOBALS["fp_advising"]["advising_load_active"]}'>
  4635. <input type='hidden' name='advising_student_id' id='advising_student_id' value='{$GLOBALS["fp_advising"]["advising_student_id"]}'>
  4636. <input type='hidden' name='advising_term_id' id='advising_term_id' value='{$GLOBALS["fp_advising"]["advising_term_id"]}'>
  4637. <input type='hidden' name='advising_major_code' id='advising_major_code' value='{$GLOBALS["fp_advising"]["advising_major_code"]}'>
  4638. <input type='hidden' name='advising_track_degree_ids' id='advising_track_degree_ids' value='{$GLOBALS["fp_advising"]["advising_track_degree_ids"]}'>
  4639. <input type='hidden' name='advising_update_student_settings_flag' id='advising_update_student_settings_flag' value=''>
  4640. <input type='hidden' name='advising_what_if' id='advising_what_if' value='{$GLOBALS["fp_advising"]["advising_what_if"]}'>
  4641. <input type='hidden' name='what_if_major_code' id='what_if_major_code' value='{$GLOBALS["fp_advising"]["what_if_major_code"]}'>
  4642. <input type='hidden' name='what_if_catalog_year' id='what_if_catalog_year' value='{$GLOBALS["fp_advising"]["what_if_catalog_year"]}'>
  4643. <input type='hidden' name='what_if_track_degree_ids' id='what_if_track_degree_ids' value='{$GLOBALS["fp_advising"]["what_if_track_degree_ids"]}'>
  4644. <input type='hidden' name='advising_view' id='advising_view' value='{$GLOBALS["fp_advising"]["advising_view"]}'>
  4645. <input type='hidden' name='current_student_id' id='current_student_id' value='{$GLOBALS["fp_advising"]["current_student_id"]}'>
  4646. <input type='hidden' name='log_addition' id='log_addition' value=''>
  4647. <input type='hidden' name='fp_update_user_settings_flag' id='fp_update_user_settings_flag' value=''>
  4648. <input type='hidden' name='advising_update_student_degrees_flag' id='advising_update_student_degrees_flag' value=''>
  4649. <input type='hidden' name='reinit_fp_after_draft_save' id='reinit_fp_after_draft_save' value='no'>
  4650. </span>
  4651. ";
  4652. return $rtn;
  4653. }
  4654. }

Classes

Namesort descending Description
AdvisingScreen