_AdvisingScreen.php

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

Classes

Namesort descending Description
_AdvisingScreen