_AdvisingScreen.php

  1. 5.x classes/_AdvisingScreen.php
  2. 4.x classes/_AdvisingScreen.php

Classes

NameDescription
_AdvisingScreen

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