FlightPath.php

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

File

classes/FlightPath.php
View source
  1. <?php
  2. class FlightPath extends stdClass
  3. {
  4. public $student, $degree_plan, $db, $bool_what_if;
  5. public $course_list_advised_courses;
  6. function __construct($student = "", $degree_plan = "", DatabaseHandler $db = null, $bool_perform_full_init = false)
  7. {
  8. if ($student != "")
  9. {
  10. $this->student = $student;
  11. }
  12. if ($degree_plan != "")
  13. {
  14. $this->degree_plan = $degree_plan;
  15. }
  16. if ($db != null)
  17. {
  18. $this->db = $db;
  19. } else {
  20. $this->db = get_global_database_handler();
  21. }
  22. if ($bool_perform_full_init == true)
  23. {
  24. $this->init(true);
  25. }
  26. $this->course_list_advised_courses = new CourseList();
  27. }
  28. function init($bool_init_advising_variables = false, $bool_ignore_what_if_advising_variables = false, $bool_load_full = true) {
  29. global $current_student_id, $user, $student;
  30. // This will initialize this flightPath object
  31. // based on what is available in the global variables.
  32. // Takes the place of what was going on at the beginning
  33. // of advise.php.
  34. if ($bool_init_advising_variables == true)
  35. {
  36. //$temp_screen = new AdvisingScreen();
  37. //$temp_screen->init_advising_variables($bool_ignore_what_if_advising_variables);
  38. //advise_load_advising_variables_from_db($current_student_id, $user->id);
  39. advise_init_advising_variables();
  40. }
  41. $major_code_csv = $GLOBALS["fp_advising"]["advising_major_code"];
  42. //$track_code = $GLOBALS["fp_advising"]["advising_track_code"];
  43. $track_degree_ids = $GLOBALS["fp_advising"]["advising_track_degree_ids"];
  44. $student_id = $GLOBALS["fp_advising"]["advising_student_id"];
  45. $advising_term_id = $GLOBALS["fp_advising"]["advising_term_id"];
  46. @$available_terms = $GLOBALS["fp_advising"]["available_advising_term_ids"];
  47. // Keep in mind-- at this point, major_coe might be a CSV of major codes.
  48. $this->bool_what_if = false;
  49. // Are we in WhatIf mode?
  50. if ($GLOBALS["fp_advising"]["advising_what_if"] == "yes")
  51. {
  52. $major_code_csv = $GLOBALS["fp_advising"]["what_if_major_code"];
  53. $track_degree_ids = $GLOBALS["fp_advising"]["what_if_track_degree_ids"];
  54. $this->bool_what_if = true;
  55. }
  56. if ($bool_load_full == false)
  57. { // not trying to load anything, so return.
  58. return;
  59. }
  60. $db = $this->db;
  61. if ($bool_load_full == true)
  62. {
  63. $student = new Student($student_id);
  64. } else {
  65. $student = new Student();
  66. $student->student_id = $student_id;
  67. }
  68. $student_school_id = $db->get_school_id_for_student_id($student_id);
  69. $catalog_year = $student->catalog_year;
  70. if ($this->bool_what_if)
  71. {
  72. // We need to look at a "what_if_catalog_year" value.
  73. $catalog_year = $GLOBALS["fp_advising"]["what_if_catalog_year"];
  74. if ($catalog_year == "" || $catalog_year == 0) {
  75. // Some problem, default to current cat year.
  76. $catalog_year = variable_get_for_school("current_catalog_year",'',$student_school_id);
  77. }
  78. }
  79. // make sure their catalog year is not past the system's current
  80. // year setting.
  81. if ($catalog_year > variable_get_for_school("current_catalog_year",'',$student_school_id) && variable_get_for_school("current_catalog_year",'',$student_school_id) > intval(variable_get_for_school("earliest_catalog_year", 2006, $student_school_id)))
  82. { // Make sure degree plan is blank if it is!
  83. $catalog_year = 99999;
  84. }
  85. if ($GLOBALS["fp_advising"]["advising_update_student_settings_flag"] != "")
  86. {
  87. // TODO: This is used in What If mode. We need to make sure that these track_degree_ids
  88. // actually do match to the selected majors. If not, then we should remove them. This
  89. // is to make sure that when we switch What If settings, these get cleared.
  90. $wi = "";
  91. if ($this->bool_what_if) {
  92. $wi = "what_if_";
  93. }
  94. //$student->array_settings["track_code"] = $track_code;
  95. $student->array_settings[$wi . "track_degree_ids"] = $track_degree_ids;
  96. $student->array_settings[$wi . "major_code_csv"] = $major_code_csv;
  97. }
  98. // Let's add the track_degree_ids to the major_code_csv...
  99. $major_code_csv .= "," . $track_degree_ids;
  100. ///////////////////////////////
  101. // Okay folks. So this is basically where we will be iterating through all
  102. // of the student's major_codes (if they have more than one), and squishing them together,
  103. // to create a single DegreePlan object, made out of all the options.
  104. // We need like a loop here.
  105. $degree_plans = array();
  106. $temparr = explode(",", $major_code_csv);
  107. foreach ($temparr as $major_code) {
  108. $t_major_code = $major_code;
  109. if (trim($major_code) == "") continue;
  110. // If we are dealing with a track, then just get the degree_id directly, else, figure out the
  111. // degree_id from the t_major_code.
  112. if (is_numeric($t_major_code)) {
  113. $degree_id = $t_major_code;
  114. }
  115. else {
  116. $degree_id = $db->get_degree_id($t_major_code, $catalog_year, FALSE, $student_school_id);
  117. }
  118. // If we couldn't find the degree_id, then we should just skip it.
  119. if (!$degree_id || $degree_id == 0) {
  120. if (variable_get("warning_on_view_if_degree_not_found", "yes") == 'yes') {
  121. fp_add_message(t("Could not find degree %maj in catalog year %cat. FlightPath will
  122. skip loading this degree for now. If this message continues to appear,
  123. contact your advisor.", array("%maj" => $t_major_code, "%cat" => $student->catalog_year . "-" . ($student->catalog_year + 1))), "error", TRUE);
  124. }
  125. continue;
  126. }
  127. if ($bool_load_full == true)
  128. {
  129. $this->student = $student;
  130. $degree_plan = fp_load_degree($degree_id, $db, FALSE, $student->array_significant_courses);
  131. //$degree_plan = new DegreePlan($degree_id, $db, FALSE, $student->array_significant_courses);
  132. $degree_plan->add_semester_developmental($student->student_id);
  133. //$this->degree_plan = $degree_plan;
  134. $degree_plans[$degree_plan->degree_id] = $degree_plan;
  135. }
  136. } // foreach temparr as major_code. The foreach loop through all our major codes.
  137. // Okay, coming out of this, we have an array of degree_plans (maybe). If it's just one, then set it to that one.
  138. if (count($degree_plans) == 1) {
  139. $this->degree_plan = $degree_plan;
  140. }
  141. else if (count($degree_plans) > 1) {
  142. // Okay folks, here's the magic. We need to combine the degree plans in this array
  143. // into 1 generated degree plan.
  144. $combined_degree_plan = $this->combine_degree_plans($degree_plans, $student_id, $student_school_id);
  145. $combined_degree_plan->db_allow_dynamic = 1; // since they are combined, we must be allowing dynamic.
  146. $this->degree_plan = $combined_degree_plan;
  147. } // else if count(degree_plans) > 1
  148. else if (count($degree_plans) < 1) {
  149. // Meaning, we couldn't find any degree plans for this student! Let's just load some blank objects.
  150. $this->degree_plan = new DegreePlan();
  151. $this->student = $student;
  152. }
  153. // Invoke a hook which lets other modules act on this student and degree plan we just loaded.
  154. invoke_hook('init_flightpath_degree', array($this->student->student_id, &$this->degree_plan));
  155. $wi = "";
  156. if ($this->bool_what_if) $wi = "_what_if";
  157. if (isset($this->degree_plan) && $this->degree_plan != null) {
  158. // Add degree_plan to a simple cache to make our lives easier later on.
  159. $_SESSION["fp_simple_degree_plan_cache_for_student" . $wi] = array(
  160. "cwid" => $student_id,
  161. "degree_id" => $this->degree_plan->degree_id,
  162. "combined_degree_ids_array" => $this->degree_plan->combined_degree_ids_array,
  163. "is_combined_dynamic_degree_plan" => $this->degree_plan->is_combined_dynamic_degree_plan,
  164. );
  165. }
  166. } // end of function fp_init
  167. /**
  168. * This function is responsible for combining multiple degree plans into a single unified degree plan,
  169. * then returning it.
  170. */
  171. function combine_degree_plans($degree_plans, $student_id, $school_id = 0) {
  172. //DEV: return $degree_plans[0];
  173. $new_degree_plan = new DegreePlan();
  174. $new_degree_plan->school_id = intval($school_id);
  175. // Loop through the degree plans one at a time...
  176. foreach ($degree_plans as $degree_plan) {
  177. $new_degree_plan->combined_degree_ids_array[] = intval($degree_plan->degree_id);
  178. $new_degree_plan->add_to_required_course_id_array($degree_plan->required_course_id_array);
  179. // Is there a public note to copy over?
  180. if (isset($degree_plan->public_notes_array[$degree_plan->degree_id])) {
  181. $new_degree_plan->public_notes_array[$degree_plan->degree_id] = $degree_plan->public_notes_array[$degree_plan->degree_id];
  182. }
  183. if ($degree_plan->catalog_year == "" || $degree_plan->catalog_year == 0) {
  184. $degree_plan->load_descriptive_data();
  185. }
  186. $new_degree_plan->catalog_year = $degree_plan->catalog_year;
  187. // Okay, now copy whatever we need to into the new_degree_plan.
  188. // First, go through its list of semesters, and copy out all the courses and groups
  189. $degree_plan->list_semesters->reset_counter();
  190. while ($degree_plan->list_semesters->has_more()) {
  191. $sem = $degree_plan->list_semesters->get_next();
  192. // If the semester is the Added by Advisor (-88), or the developmental block (-55) then skip for now.
  193. if ($sem->semester_num == DegreePlan::SEMESTER_NUM_FOR_COURSES_ADDED || $sem->semester_num == DegreePlan::SEMESTER_NUM_FOR_DEVELOPMENTALS) {
  194. // This is the special one that is "added by advisor". Skip it. But remember to add it later to the finished product.
  195. // Or, it's the developmentals block. Add that later too.
  196. continue;
  197. }
  198. // Okay, the semester contains a CourseList called list_courses, and a GroupList caled list_groups.
  199. $new_list_courses = $sem->list_courses->get_clone();
  200. // Now, let's add them to the new_degree_plan's semester...
  201. // if the new degree plan already has this semester, get that instead.
  202. $the_semester = $new_degree_plan->get_semester($sem->semester_num);
  203. if (!$the_semester) {
  204. $the_semester = new Semester($sem->semester_num);
  205. $new_degree_plan->list_semesters->add($the_semester);
  206. }
  207. // Should we rename the_semester's title (because the semester we are grabbing is overriding?)
  208. //$degree_plan->load_descriptive_data(); // Doesn't appear to be necessary at this stage.
  209. $stitle = fp_trim(@$degree_plan->array_semester_titles[$sem->semester_num]);
  210. if ($stitle != "") {
  211. // Meaning we should overwrite the semester title, because this degree isn't using the default title
  212. $the_semester->title = $stitle;
  213. $the_semester->bool_using_default_title = FALSE;
  214. }
  215. // Okay, now add the courses to the_semester
  216. $the_semester->list_courses->add_list($new_list_courses);
  217. ////////////////////////////
  218. // Getting the list of groups is going to be similar to getting our list of courses.
  219. // Go through the list of groups for this semester.
  220. $new_list_groups = $sem->list_groups->get_clone(FALSE, FALSE, FALSE);
  221. // Okay, now we can add to our semester
  222. $the_semester->list_groups->add_list($new_list_groups);
  223. // Also add this group list to the degree plan's list_groups.
  224. $new_degree_plan->list_groups->add_list($new_list_groups);
  225. } // while, listing semesters in degree plan.
  226. } // foreach degree_plans
  227. //////////////////////////////
  228. // Okay, now to put the finishing touches on the $new_degree_plan
  229. // Add in the "Developmental Req's" if required for this student.
  230. $new_degree_plan->add_semester_developmental($student_id);
  231. // Add in the "Courses added by advisor"
  232. $new_degree_plan->add_semester_courses_added();
  233. if (count($degree_plans) > 1) {
  234. $new_degree_plan->is_combined_dynamic_degree_plan = TRUE;
  235. $new_degree_plan->degree_id = DegreePlan::DEGREE_ID_FOR_COMBINED_DEGREE; // use constant to make it easier later on.
  236. }
  237. // Make sure all of our groups have reloaded any missing courses.
  238. $new_degree_plan->list_semesters->reset_counter();
  239. while ($new_degree_plan->list_semesters->has_more()) {
  240. $sem = $new_degree_plan->list_semesters->get_next();
  241. $sem->list_groups->reload_missing_courses();
  242. }
  243. return $new_degree_plan;
  244. } // combine_degree_plans
  245. /**
  246. * This function will check to see if we are trying to save
  247. * the draft from a tab change. It should be near the top
  248. * of all of FP's "tab" pages, like Main, Comments, etc.
  249. *
  250. */
  251. function process_request_save_draft()
  252. {
  253. /////////////////////////////////////
  254. /// Are we trying to save the draft
  255. /// from a tab change?
  256. /////////////////////////////////////
  257. if ($_REQUEST["save_draft"] == "yes")
  258. {
  259. $this->init(true, false, false);
  260. // If we are coming from the WhatIf tab, we need to save
  261. // as WhatIf. Else, save as normal.
  262. if ($_REQUEST["from_w_i"] == "yes")
  263. {
  264. // Yes, we are coming from WhatIf mode, so
  265. // save under WhatIf.
  266. $GLOBALS["advising_what_if"] = "yes";
  267. $this->init(false);
  268. } else {
  269. // NOT coming from WhatIf mode. Save as a normal draft.
  270. $GLOBALS["advising_what_if"] = "no";
  271. $this->init(true, true);
  272. }
  273. $this->save_advising_session_from_post(0,true);
  274. }
  275. }
  276. function assign_courses_to_groups() {
  277. // This method will look at the student's courses
  278. // and decide which groups they should be fit into.
  279. // We will be going through the degree plan's master list
  280. // of groups to decide this.
  281. $student = $this->student;
  282. $school_id = $student->school_id;
  283. $this->degree_plan->list_groups->sort_priority();
  284. // Now, sort by the advising weight of the degree itself.
  285. $this->degree_plan->list_groups->sort_degree_advising_weight();
  286. $this->degree_plan->list_groups->reset_counter();
  287. while($this->degree_plan->list_groups->has_more())
  288. {
  289. $g = $this->degree_plan->list_groups->get_next();
  290. if ($g->group_id == DegreePlan::GROUP_ID_FOR_COURSES_ADDED)
  291. {
  292. // Add a course group. Skip.
  293. continue;
  294. }
  295. // Does the student have any group additions for this
  296. // group? Technically it is a substitution.
  297. // We will add them in now, because we do not take additions
  298. // into consideration when figuring out branches.
  299. if ($course_list_additions = $student->list_substitutions->find_group_additions($g))
  300. {
  301. $course_list_additions->reset_counter();
  302. while($course_list_additions->has_more())
  303. {
  304. $cA = $course_list_additions->get_next();
  305. $new_course = new Course();
  306. $new_course->course_id = $cA->course_id;
  307. if ($cA->bool_transfer == true)
  308. {
  309. if ($cA->course_id == 0 && is_object($cA->course_transfer))
  310. { // This is a transfer course which has been added.
  311. $new_course->course_id = $cA->course_transfer->course_id;
  312. }
  313. $new_course->bool_transfer = true;
  314. }
  315. $new_course->assigned_to_semester_num = $g->assigned_to_semester_num;
  316. $new_course->requirement_type = $g->requirement_type;
  317. // Add this course as a requirement.
  318. //$new_course->load_descriptive_data();
  319. $g->list_courses->add($new_course, true);
  320. // Later on, when we do assign_courses_to_list, it
  321. // will automatically find this course and apply the
  322. // substitution.
  323. }
  324. }
  325. // First we see if there are any bare courses at this level. If there
  326. // are, then this group has NO branches! Otherwise, the courses must
  327. // always be contained in a branch!
  328. if (!$g->list_courses->is_empty)
  329. {
  330. // Yes, there are courses here. So, assign them at this level.
  331. $this->assign_courses_to_list($g->list_courses, $this->student, true, $g, true);
  332. // Okay, if we have fulfilled our courses at this level.
  333. // then we can continue on to the next "top level" group.
  334. //continue;
  335. }
  336. if (!$g->list_groups->is_empty)
  337. {
  338. /*
  339. Now we've got some trouble. This is our first level of groups.
  340. If this object exists, then it means that this group branches off
  341. at its first level. So, instead of actually assigning courses to
  342. groups, we need to find out which group has the most matches, and THEN
  343. we will assign them.
  344. */
  345. $g->reload_missing_courses();
  346. $high_count = -1;
  347. $best_branch = -1;
  348. // Sort our list of groups by student's grades, if applicable.
  349. $sort_policy = variable_get_for_school("initial_student_course_sort_policy", "alpha", $school_id); // will either be "alpha" or "grade"
  350. if ($sort_policy == "grade") {
  351. $g->list_groups->sort_best_grade_first_by_student_grades($student);
  352. }
  353. $g->list_groups->reset_counter();
  354. while($g->list_groups->has_more())
  355. {
  356. $branch_one = $g->list_groups->get_next();
  357. if (!$branch_one->list_courses->is_empty)
  358. {
  359. // This does not actually assign. Just counts.
  360. $count = $this->get_count_of_matches($branch_one, $this->student, $g);
  361. $branch_one->count_of_matches = $count;
  362. if ($count > $high_count)
  363. {
  364. $high_count = $count;
  365. $best_branch = $g->list_groups->object_index_of($branch_one);
  366. }
  367. }
  368. }
  369. // Okay, coming out of that, we should know which branch has the best count (number
  370. // of matches). So, let's assign courses to that branch.
  371. if ($best_branch != -1)
  372. {
  373. $winning_branch = $g->list_groups->get_element($best_branch);
  374. $winning_branch->bool_winning_branch = TRUE;
  375. $this->assign_courses_to_list($winning_branch->list_courses, $this->student, TRUE, $g, TRUE);
  376. }
  377. }
  378. } // while
  379. }
  380. function get_count_of_matches($branch, $student, $group)
  381. {
  382. return $this->assign_courses_to_list($branch->list_courses, $student, FALSE, $group, TRUE);
  383. }
  384. function flag_outdated_substitutions()
  385. {
  386. // Go through the student's substitutions and flag ones that
  387. // do not apply to this degree plan. Also, unset any bool_substitution
  388. // variables which were set.
  389. $this->student->list_substitutions->reset_counter();
  390. while ($this->student->list_substitutions->has_more())
  391. {
  392. $substitution = $this->student->list_substitutions->get_next();
  393. ////////////////////////////
  394. // Ticket #2316, from Logan Buth, this is to better detect outdated subs for combined degrees.
  395. $bool_sub_valid = TRUE;
  396. $outdated_note = "";
  397. if ($this->degree_plan->degree_id == DegreePlan::DEGREE_ID_FOR_COMBINED_DEGREE &&
  398. !in_array($substitution->db_required_degree_id, $this->degree_plan->combined_degree_ids_array)) {
  399. //combined degree plan, degree id not in it.
  400. $bool_sub_valid = FALSE;
  401. $sub_degree_title = fp_get_degree_title($substitution->db_required_degree_id, TRUE, TRUE, FALSE, TRUE);
  402. $outdated_note = t("This substitution is for the degree %did
  403. which is no longer in the student's degrees.", array("%did" => $sub_degree_title));
  404. }
  405. else if ($this->degree_plan->degree_id != DegreePlan::DEGREE_ID_FOR_COMBINED_DEGREE &&
  406. $this->degree_plan->degree_id != $substitution->db_required_degree_id) {
  407. $bool_sub_valid = FALSE;
  408. $sub_degree_title = fp_get_degree_title($substitution->db_required_degree_id, TRUE, TRUE, FALSE, TRUE);
  409. $outdated_note = t("This substitution is for the degree %did
  410. which is no longer the student's degree", array("%did" => $sub_degree_title));
  411. }
  412. //////////////
  413. //$required_group_id = $substitution->course_requirement->assigned_to_group_id;
  414. $required_group_id = $substitution->course_requirement->get_first_assigned_to_group_id(); // we assume there's only one group to get
  415. // First check-- does this degree even have this group ID?
  416. if ($bool_sub_valid && ($required_group_id == 0 || $required_group_id == '' || $required_group_id == NULL)) {
  417. // bare degree plan.
  418. // Does the bare degree plan list the course_requirement
  419. // anywhere?
  420. $bool_sub_valid = FALSE;
  421. $this->degree_plan->list_semesters->reset_counter();
  422. while($this->degree_plan->list_semesters->has_more() && $bool_sub_valid == FALSE)
  423. {
  424. $sem = $this->degree_plan->list_semesters->get_next();
  425. if ($sem->list_courses->find_match($substitution->course_requirement))
  426. {
  427. $bool_sub_valid = TRUE;
  428. }
  429. else {
  430. // Could not find the course requirement in question.
  431. $bool_sub_valid = FALSE;
  432. $scr = $substitution->course_requirement;
  433. $scr->load_descriptive_data();
  434. $outdated_note = t("This substitution is for the course %info on the
  435. bare degree plan, but the student's current degree does
  436. not specify this course.", array("%info" => "$scr->subject_id $scr->course_num (id: $scr->course_id)"));
  437. }
  438. }
  439. }
  440. else if ($bool_sub_valid && $required_group_id != 0 && $required_group_id != '' && $required_group_id != NULL) {
  441. // required_group_id != 0, meaning, NOT the bare degree plan.
  442. // So, does this degree plan have a group with this id (required_group_id)?
  443. $bool_sub_valid = false;
  444. if ($g = $this->degree_plan->find_group($required_group_id)) {
  445. $bool_sub_valid = true;
  446. }
  447. else {
  448. // Could not find the group in question. Add an "outdated_note"
  449. // to the sub...
  450. $bool_sub_valid = FALSE;
  451. $new_group = new Group();
  452. $new_group->group_id = $required_group_id;
  453. $new_group->load_descriptive_data();
  454. $group_name = "";
  455. if (user_has_permission("can_access_data_entry")) {
  456. // only show if we are a data entry administrator.
  457. $group_name = "<i>$new_group->group_name,</i>";
  458. }
  459. $outdated_note = t("This substitution is for the group %info,
  460. but the student's current degree does not call for this
  461. specific group.", array("%info" => "$new_group->title (id: $new_group->group_id, $group_name $new_group->catalog_year)"));
  462. }
  463. }
  464. if ($bool_sub_valid == FALSE) {
  465. // Couldn't find a match, so remove this sub!
  466. $substitution->bool_outdated = TRUE;
  467. $substitution->outdated_note = $outdated_note;
  468. $substitution->course_list_substitutions->get_first()->bool_outdated_sub = TRUE;
  469. $substitution->course_list_substitutions->get_first()->set_bool_outdated_sub(0, TRUE);
  470. //$substitution->course_list_substitutions->get_first()->bool_substitution = false;
  471. $substitution->course_list_substitutions->get_first()->set_bool_substitution(0, FALSE);
  472. if ($substitution->course_list_substitutions->get_first()->temp_old_course_id > 0)
  473. { // Restore the course_id *if* it was set to 0 on purpose. (happens
  474. // when there is a sub of a transfer to kill the transfer eqv. This will
  475. // restore it).
  476. $substitution->course_list_substitutions->get_first()->course_id = $substitution->course_list_substitutions->get_first()->temp_old_course_id;
  477. }
  478. }
  479. }
  480. }
  481. function assign_courses_to_list(ObjList $list_requirements, Student $student, $bool_perform_assignment = true, Group $group = null, $bool_check_significant_courses = false, $assign_to_semester_num = -1)
  482. {
  483. $count = 0;
  484. $school_id = 0;
  485. if ($student) {
  486. $school_id = $student->school_id;
  487. }
  488. if ($group == NULL || $group == '' || $group == 0 || $group == FALSE)
  489. {
  490. $group = new Group();
  491. $group->group_id = 0;
  492. }
  493. else if ($group->min_grade != "") {
  494. $group->assign_min_grade($group->min_grade); // If this is a group with a min grade value, let's make sure we assign all the courses in it to this min grade.
  495. }
  496. $sort_policy = variable_get_for_school("initial_student_course_sort_policy", "alpha", $school_id); // will either be "alpha" or "grade"
  497. $bool_disallow_graduate_credits = (variable_get_for_school("disallow_graduate_credits", "yes", $school_id) == "yes") ? TRUE : FALSE;
  498. $graduate_level_codes_array = csv_to_array(variable_get_for_school("graduate_level_codes", "GR", $school_id));
  499. // Get the course repeat policy.
  500. $course_repeat_policy = variable_get_for_school("course_repeat_policy", "most_recent_exclude_previous", $school_id);
  501. // Set the $bool_mark_repeats_exclude variable based on the course_repeat_policy.
  502. $bool_mark_repeats_exclude = ($course_repeat_policy == "most_recent_exclude_previous" || $course_repeat_policy == "best_grade_exclude_others");
  503. $group_id = $group->group_id;
  504. // If the group_id == 0 or blank or null, we may be talking about the bare degree plan.
  505. $hours_required = $group->hours_required*1;
  506. $hours_assigned = $group->hours_assigned;
  507. $meet_min_hours = 999999; // effectively infinite by default, to make logic easier later on.
  508. // If the group has min_hours, then we should allow the user to get at least the min hours before we stop trying to fill.
  509. if ($group->has_min_hours_allowed() && variable_get_for_school("group_full_at_min_hours", "yes", $school_id) == "yes") {
  510. $meet_min_hours = $group->min_hours_allowed;
  511. }
  512. if ($hours_required <= 0 || $hours_required == "")
  513. {
  514. $hours_required = 999999;
  515. }
  516. $list_requirements->sort_smallest_hours_first();
  517. // sort the requirement list by the best grades that the student has made? Similar to the substitutions?
  518. if ($sort_policy == "grade") {
  519. $list_requirements->sort_best_grade_first($student);
  520. }
  521. else if ($sort_policy == "alpha") {
  522. $list_requirements->sort_alphabetical_order();
  523. }
  524. $list_requirements->sort_substitutions_first($student->list_substitutions, $group_id);
  525. $list_requirements->reset_counter();
  526. while($list_requirements->has_more())
  527. {
  528. $course_requirement = $list_requirements->get_next();
  529. $req_by_degree_id = $course_requirement->req_by_degree_id; // what degree is requiring this course?
  530. // If we're dealing with a group, use it's required by degree id.
  531. if (($group->group_id != "" && $group->group_id != 0 && $group->group_id != NULL) && ($group->req_by_degree_id != '' && $group->req_by_degree_id != 0 && $group->req_by_degree_id != NULL)) {
  532. $req_by_degree_id = $group->req_by_degree_id;
  533. }
  534. if ($bool_check_significant_courses == true)
  535. {
  536. // Only look for the course_requirement if it is in the student's
  537. // array_significant_courses array.
  538. if (isset($student->array_significant_courses[$course_requirement->course_id]) && $student->array_significant_courses[$course_requirement->course_id] != true)
  539. {// course was not in there, so skip!
  540. continue;
  541. }
  542. }
  543. if ($course_requirement->bool_specified_repeat == true)
  544. {
  545. // Since this requirement has specified repeats, we want
  546. // to make all of the student's taken courses (for this course)
  547. // also have specified repeats.
  548. $student->list_courses_taken->set_specified_repeats($course_requirement, $course_requirement->specified_repeats);
  549. }
  550. // Does the student have any substitutions for this requirement?
  551. if ($substitution = $student->list_substitutions->find_requirement($course_requirement, true, $group_id, $req_by_degree_id))
  552. {
  553. // Since the substitution was made, I don't really care about
  554. // min grades or the like. Let's just put it in.
  555. if ($bool_perform_assignment == TRUE)
  556. {
  557. // Check to see if this course requirement has "infinite repeats". If it does, then we want to
  558. // clone it and add it back into our list of requirements.
  559. if ($course_requirement->specified_repeats == Group::GROUP_COURSE_INFINITE_REPEATS) {
  560. $temp_ds = $course_requirement->to_data_string();
  561. $new_course = new Course();
  562. $new_course->load_course_from_data_string_for_requirement_clone($temp_ds);
  563. $new_course->min_grade = $course_requirement->min_grade;
  564. if ($assign_to_semester_num !== -1) {
  565. $new_course->assigned_to_semester_num = $assign_to_semester_num;
  566. }
  567. $list_requirements->add($new_course);
  568. }
  569. // Make sure this isn't a group addition and we are *currently*
  570. // NOT looking at the group it is being added to. This is to
  571. // correct a bug.
  572. if ($substitution->bool_group_addition == true)
  573. {
  574. if ($substitution->course_requirement->get_first_assigned_to_group_id() != $group_id)
  575. {
  576. continue;
  577. }
  578. }
  579. // If the course_requirement's min_hours are greater than
  580. // the substitution's hours, then we have to split the
  581. // coureRequirement into 2 pieces, and add the second piece just
  582. // after this one in the list.
  583. $course_sub = $substitution->course_list_substitutions->get_first();
  584. if (floatval($course_requirement->min_hours) > floatval($course_sub->get_hours_awarded($req_by_degree_id)))
  585. {
  586. // Because float math can create some very strange results, we must
  587. // perform some rounding. We will round to 6 decimal places, which should
  588. // provide us the accuracy w/o losing precision (since we can only represent a max
  589. // of 4 decimals in the database anyway.
  590. $remaining_hours = round($course_requirement->min_hours - $course_sub->get_hours_awarded($req_by_degree_id), 6);
  591. $new_course_string = $course_requirement->to_data_string();
  592. $new_course = new Course();
  593. $new_course->load_course_from_data_string($new_course_string);
  594. $new_course->min_hours = $new_course->max_hours = $remaining_hours;
  595. $new_course->set_bool_substitution_split($req_by_degree_id, TRUE);
  596. $new_course->set_bool_substitution_new_from_split($req_by_degree_id, TRUE);
  597. $new_course->requirement_type = $course_requirement->requirement_type;
  598. $new_course->min_grade = $course_requirement->min_grade;
  599. $new_course->req_by_degree_id = $req_by_degree_id;
  600. $new_course->assigned_to_degree_ids_array[$req_by_degree_id] = $req_by_degree_id;
  601. $new_course->db_degree_requirement_id = floatval($course_requirement->db_degree_requirement_id . ".1");
  602. if ($assign_to_semester_num !== -1) {
  603. $new_course->assigned_to_semester_num = $assign_to_semester_num;
  604. }
  605. $course_requirement->set_bool_substitution_split($req_by_degree_id, TRUE);
  606. // I am commenting this out-- if we split up a sub multiple times, then we shouldn't
  607. // set the old course requirement to say it WASN'T from a split. This was causing a bug
  608. // where the pie charts got weird if you did more than 1 split. Was counting total
  609. // hours as more, in CourseList->count_hours().
  610. //$course_requirement->bool_substitution_new_from_split = false;
  611. // Only do this if we are NOT in a group! This is to correct a bug where split additions to groups wound up
  612. // being displayed like available selections in the group. It was like, weird man.
  613. if ($group_id == 0 || $group_id == '' || $group_id == NULL) {
  614. // Now, add this into the list, right after the course_requirement.
  615. $current_i = $list_requirements->i;
  616. $list_requirements->insert_after_index($current_i, $new_course);
  617. }
  618. } // if min_hours > sub's awarded hours
  619. $course_requirement->course_list_fulfilled_by = $substitution->course_list_substitutions;
  620. $substitution->course_list_substitutions->assign_group_id($group_id);
  621. $substitution->course_list_substitutions->set_has_been_assigned(true);
  622. $substitution->course_list_substitutions->set_bool_substitution($req_by_degree_id, TRUE);
  623. $course_requirement->db_substitution_id_array[] = $substitution->db_substitution_id;
  624. $substitution->course_list_substitutions->set_course_substitution($course_requirement, $substitution->remarks, $req_by_degree_id);
  625. $substitution->bool_has_been_applied = TRUE;
  626. if ($group_id != "" && intval($group_id) > 0) {
  627. // We are going to add the course_sub's hours in as being assigned to this list, if this is for a group.
  628. // I am surprised this wasn't already here. This fixes a bug with groups that allow min hours.
  629. $hours_assigned += $course_sub->get_hours_awarded($req_by_degree_id);
  630. }
  631. }
  632. $count++;
  633. continue;
  634. } // if student has any substitutions for this requirement
  635. // Has the student taken this course requirement?
  636. if ($c = $student->list_courses_taken->find_best_match($course_requirement, $course_requirement->min_grade, $bool_mark_repeats_exclude, $req_by_degree_id, TRUE, TRUE, $group_id))
  637. {
  638. $h_get_hours = $c->get_hours();
  639. if ($c->bool_ghost_hour) {
  640. // If this is a ghost hour, then $h_get_hours would == 0 right now,
  641. // instead, use the the adjusted value (probably 1).
  642. $h_get_hours = $c->get_hours_awarded($req_by_degree_id);
  643. }
  644. // Can we assign any more hours to this group? Are we
  645. // out of hours, and should stop?
  646. if ($hours_assigned >= $hours_required || $hours_assigned >= $meet_min_hours)
  647. {
  648. continue;
  649. }
  650. $c_hours_awarded = $c->get_hours_awarded($req_by_degree_id);
  651. // Will the hours of this course put us over the hours_required limit? NOTE: We don't care if it puts us over the min_hours, in fact, we want that.
  652. if ($hours_assigned + $c_hours_awarded > $hours_required )
  653. {
  654. continue;
  655. }
  656. // Do not apply substitution new_from_split courses to anything automatically. (from any degree!)
  657. // They must be applied by substitutions.
  658. if ($c->get_bool_substitution_new_from_split() == TRUE)
  659. {
  660. continue;
  661. }
  662. // Make sure the course meets min grade requirements.
  663. if (!$c->meets_min_grade_requirement_of($course_requirement))
  664. {
  665. continue;
  666. }
  667. // Has the course been unassigned from this group?
  668. if ($c->group_list_unassigned->find_match_with_degree_id($group, $req_by_degree_id))
  669. {
  670. continue;
  671. }
  672. // Make sure $c is not being used in a substitution (for this degree)
  673. if ($c->get_bool_substitution($req_by_degree_id) == TRUE) {
  674. continue;
  675. }
  676. // If this is a graduate level course, and we are not allowing grad credits, then skip!
  677. if ($c->level_code != "" && in_array($c->level_code, $graduate_level_codes_array)) {
  678. if ($bool_disallow_graduate_credits) {
  679. continue;
  680. }
  681. }
  682. // Check hooks to see if this course is allowed to be assigned to the GROUP in question.
  683. if ($group_id != "" && $group_id != 0 && $group_id != NULL) {
  684. $bool_can_proceed = TRUE;
  685. $result = invoke_hook("flightpath_can_assign_course_to_group", array($group, $c));
  686. foreach ($result as $m => $val) {
  687. // If *any* module said FALSE, then we must skip this course and not assign it to this degree.
  688. if ($val === FALSE) $bool_can_proceed = $val;
  689. }
  690. if (!$bool_can_proceed) {
  691. continue; // don't assign!
  692. }
  693. } // if group_id != ""
  694. // We want to see if this course has already been assigned to THIS degree...
  695. if (!in_array($req_by_degree_id, $c->assigned_to_degree_ids_array))
  696. {//Don't count courses which have already been placed in other groups.
  697. // Check hooks to see if this course is allowed to be assigned to the degree in question.
  698. $bool_can_proceed = TRUE;
  699. $result = invoke_hook("flightpath_can_assign_course_to_degree_id", array($req_by_degree_id, $c));
  700. foreach ($result as $m => $val) {
  701. // If *any* module said FALSE, then we must skip this course and not assign it to this degree.
  702. if ($val === FALSE) $bool_can_proceed = $val;
  703. }
  704. if (!$bool_can_proceed) {
  705. continue; // don't assign!
  706. }
  707. // Has another version of this course already been
  708. // assigned? And if so, are repeats allowed for this
  709. // course? And if so, then how many hours of the
  710. // repeat_hours have I used up? If I cannot do any more
  711. // repeats, then quit. Otherwise, let it continue...
  712. $course_list_repeats = $student->list_courses_taken->get_previous_assignments($c->course_id);
  713. if ($course_list_repeats->get_size() > 0)
  714. {
  715. // So, a copy of this course has been assigned more than once...
  716. // Get the total number of hours taken up by this course.
  717. $cc = $course_list_repeats->count_hours();
  718. // have we exceeded the number of available repeat_hours
  719. // for this course?
  720. if ($course_requirement->repeat_hours <= 0)
  721. {
  722. $course_requirement->load_descriptive_data();
  723. }
  724. if (($course_requirement->bool_ghost_hour != TRUE || $c->bool_ghost_hour != TRUE)
  725. && $cc + $h_get_hours > $course_requirement->repeat_hours*1)
  726. {
  727. // Do not allow the repeat, unless we are talking about courses worth zero hours.
  728. // meaning, they have a ghost hour. In which case, allow it.
  729. continue;
  730. }
  731. }
  732. // Basically--- if the most recent attempt fails
  733. // a min grade check, then tag all attempts as "unuseable"
  734. // so that they can't be used in other groups. --
  735. // unless they are able to be repeated. BARF!
  736. // Inc hours_assigned, even if we aren't actually
  737. // performing an assignment. This helps us accurately
  738. // calculate the count.
  739. $hours_assigned = $hours_assigned + $h_get_hours;
  740. if ($bool_perform_assignment == TRUE)
  741. {
  742. // If this course has an "infinite" number of specified repeats, then
  743. // let's actually clone the course and insert it as a new requirement, to replace
  744. // the one we're about to use.
  745. if ($course_requirement->specified_repeats == Group::GROUP_COURSE_INFINITE_REPEATS) {
  746. $temp_ds = $course_requirement->to_data_string();
  747. $new_course = new Course();
  748. $new_course->load_course_from_data_string_for_requirement_clone($temp_ds);
  749. $new_course->min_grade = $course_requirement->min_grade;
  750. if ($assign_to_semester_num !== -1) {
  751. $new_course->assigned_to_semester_num = $assign_to_semester_num;
  752. $new_course->appears_in_semester_nums[] = $assign_to_semester_num; // for combo-degrees
  753. }
  754. $list_requirements->add($new_course);
  755. } // infinite repeats?
  756. // Which degree is this coming from?
  757. //$req_by_degree_id = $course_requirement->req_by_degree_id;
  758. $c->assigned_to_degree_ids_array[$req_by_degree_id] = $req_by_degree_id;
  759. // Go ahead and state that the requirement was fulfilled.
  760. $course_requirement->course_list_fulfilled_by->add($c);
  761. $course_requirement->grade = $c->grade;
  762. $course_requirement->set_hours_awarded($req_by_degree_id, $c->get_hours_awarded($req_by_degree_id));
  763. $course_requirement->bool_ghost_hour = $c->bool_ghost_hour;
  764. if ($course_requirement->extra_attribs != "") {
  765. $c->extra_attribs = $course_requirement->extra_attribs;
  766. }
  767. // No longer using... using the assigned_to_degree_ids_array instead. // $c->bool_has_been_assigned = true;
  768. //$c->requirement_type = $course_requirement->requirement_type;
  769. if ($c->requirement_type == "") {
  770. // No requirement type given? Perhaps we are part of a group. If so, use that.
  771. //$c->requirement_type = $group->requirement_type;
  772. //$course_requirement->requirement_type = $group->requirement_type;
  773. }
  774. if ($assign_to_semester_num !== -1) {
  775. $c->assigned_to_semester_num = $assign_to_semester_num;
  776. $c->appears_in_semester_nums[] = $assign_to_semester_num; // for combo-degrees
  777. }
  778. // Check what groups it has been assigned to already.
  779. //$c->assigned_to_group_id = $group_id;
  780. if ($group_id != '') {
  781. $c->assigned_to_group_ids_array[$group_id . "_" . $req_by_degree_id] = $group_id;
  782. }
  783. $group->hours_assigned = $hours_assigned;
  784. // Should check for:
  785. // Can it be assigned, based on the number of allowed course repeats?
  786. if ($course_requirement->bool_specified_repeat == true)
  787. {
  788. // $c is what they actually took.
  789. $c->bool_specified_repeat = true;
  790. $c->specified_repeats = $course_requirement->specified_repeats;
  791. $list_requirements->dec_specified_repeats($c);
  792. }
  793. } // bool_perform_assignment == true
  794. $count++;
  795. }
  796. }
  797. }
  798. return $count;
  799. }
  800. function assign_courses_to_semesters()
  801. {
  802. // This method will look at the student's courses
  803. // and decide if they should be assigned to degree requirements
  804. // which have been spelled out in each semester. This
  805. // is not where it looks into groups.
  806. //fpm($this->degree_plan, 5);
  807. $this->degree_plan->list_semesters->reset_counter();
  808. while($this->degree_plan->list_semesters->has_more())
  809. {
  810. $semester = $this->degree_plan->list_semesters->get_next();
  811. $semester_num = $semester->semester_num;
  812. // Okay, let's look at the courses (not groups) in this
  813. // semester...
  814. $this->assign_courses_to_list($semester->list_courses, $this->student, TRUE, NULL, FALSE, $semester_num);
  815. }
  816. }
  817. /**
  818. * Get the plain English title of a subject, from
  819. * subject_id. Ex: COSC = Computer Science.
  820. *
  821. * @param unknown_type $subject_id
  822. * @return unknown
  823. */
  824. function get_subject_title($subject_id, $school_id = 0)
  825. {
  826. // From the subject_id, get the title.
  827. // Example: COSC = Computer Science.
  828. $res = $this->db->db_query("SELECT title FROM subjects
  829. WHERE subject_id = ?
  830. AND school_id = ?
  831. LIMIT 1 ", $subject_id, $school_id);
  832. $cur = $this->db->db_fetch_array($res);
  833. if ($cur) {
  834. return trim($cur["title"]);
  835. }
  836. }
  837. function get_all_courses_in_catalog_year($catalog_year = "2006", $bool_load_descriptive_data = false, $limit_start = 0, $limit_size = 0, $school_id = 0, $bool_only_undergrad = TRUE, $bool_skip_excluded = FALSE)
  838. {
  839. // Returns a CourseList object of all the
  840. // courses in the supplied catalog_year.
  841. $lim_line = "";
  842. if ($limit_size > 0)
  843. {
  844. $lim_line = " limit $limit_start, $limit_size ";
  845. }
  846. $rtn_list = new CourseList();
  847. $c_array = array();
  848. $params = array();
  849. $params[":catalog_year"] = $catalog_year;
  850. $params[":school_id"] = $school_id;
  851. $exclude_line = "";
  852. if ($bool_skip_excluded) {
  853. $exclude_line = " AND exclude = 0 ";
  854. }
  855. $course_num_line = "";
  856. if ($bool_only_undergrad) {
  857. $course_num_line = " AND course_num < :gradnum ";
  858. $params[":params"] = variable_get_for_school("graduate_level_course_num", 5000, $school_id);
  859. }
  860. $result = $this->db->db_query("SELECT * FROM courses
  861. WHERE
  862. catalog_year = :catalog_year
  863. $course_num_line
  864. AND school_id = :school_id
  865. AND delete_flag = 0
  866. $exclude_line
  867. ORDER BY subject_id, course_num
  868. $lim_line
  869. ", $params);
  870. while($cur = $this->db->db_fetch_array($result))
  871. {
  872. $course = new Course();
  873. $course->course_id = $cur["course_id"];
  874. $course->subject_id = $cur["subject_id"];
  875. $course->course_num = $cur["course_num"];
  876. $course->min_hours = $cur["min_hours"];
  877. $course->max_hours = $cur["max_hours"];
  878. if ($bool_load_descriptive_data == true)
  879. {
  880. $course->load_descriptive_data();
  881. }
  882. $rtn_list->add($course);
  883. }
  884. return $rtn_list;
  885. }
  886. /**
  887. * This function replaces the original method of caching the course inventory, to something which uses
  888. * a file instead of database.
  889. */
  890. function z_____cache_course_inventory($limit_start = 0, $limit_size = 4000) {
  891. // This functionality has moved to the system module to make it easier to call.
  892. // This will eventually be depricated.
  893. system_reload_and_cache_course_inventory();
  894. } // function
  895. function z__cache_course_inventory($limit_start = 0, $limit_size = 4000)
  896. {
  897. // Load courses from the inventory into the inventory cache...
  898. // Attempt to load the course inventory cache...
  899. if ($course_inventory = unserialize(@$_SESSION["fp_cache_course_inventory"]))
  900. {
  901. $GLOBALS["fp_course_inventory"] = $course_inventory;
  902. }
  903. $result = $this->db->db_query("SELECT DISTINCT course_id FROM courses
  904. WHERE
  905. course_num < ?
  906. LIMIT $limit_start, $limit_size
  907. ", variable_get("graduate_level_course_num", 5000)); // just use default?
  908. while($cur = $this->db->db_fetch_array($result))
  909. {
  910. $course_id = $cur["course_id"];
  911. $this->db->load_course_descriptive_data(null, $course_id);
  912. }
  913. // Should we re-cache the course inventory? If there have been any changes
  914. // to it, then we will see that in a GLOBALS variable...
  915. if ($GLOBALS["cache_course_inventory"] == true)
  916. {
  917. $_SESSION["fp_cache_course_inventory"] = serialize($GLOBALS["fp_course_inventory"]);
  918. }
  919. }
  920. function replace_missing_course_in_group($course_id, $group_id)
  921. {
  922. // Given a group in the degree plan, this will
  923. // make sure that course is actually in the group. If it
  924. // is not, then it will add it in where it should be.
  925. // This is necessary because we have previously removed
  926. // courses which the student hadn't taken. Well, if the
  927. // student was advised for a particular course in a group,
  928. // then that course probably was originally removed
  929. // from the group. So, put it back in.
  930. // Were we given a valid group_id?
  931. if (!$group_id) return;
  932. // First, find the group.
  933. if (!$group = $this->degree_plan->find_group($group_id))
  934. {
  935. fpm("Admin note: could not find group '$group_id' for replace_missing_course_in_group, for course '$course_id'.");
  936. return;
  937. }
  938. // Okay, now tell the group to replace the instance of this course
  939. // in the group. This is made easy, because we have
  940. // the dbGroupRequirementID, which is the actual id from the
  941. // row in group_requirements that this course was advised from.
  942. $group->replace_missing_course($course_id);
  943. }
  944. function save_advising_session_from_post($faculty_id = 0, $bool_draft = true)
  945. {
  946. global $user;
  947. $catalog_year = 0;
  948. $bool_fp_goto_at_end = FALSE;
  949. // This method will, only by looking at variables in the
  950. // POST, save an advising session into the database.
  951. $db = get_global_database_handler();
  952. if ($faculty_id == 0) {
  953. // if none supplied, use the one from the session of
  954. // whomever is currently logged in.
  955. $faculty_id = $user->cwid;
  956. }
  957. $advising_session_token = $db->request_new_advising_session_token();
  958. // It's possible the user has simply pressed "refresh" after submitting the form. If so,
  959. // there is no reason to re-submit everything, creating duplicate data in some situations.
  960. $post_md5 = md5(serialize($_POST));
  961. if (@$_SESSION["fp_previous_advising_post_md5"] == $post_md5) {
  962. return array();
  963. }
  964. // We may proceed, but save the POST md5 for next time.
  965. $_SESSION["fp_previous_advising_post_md5"] = $post_md5;
  966. $bool_found_update_match = false;
  967. $student_id = $this->student->student_id;
  968. $school_id = db_get_school_id_for_student_id($student_id);
  969. $degree_id = $this->degree_plan->degree_id;
  970. $major_code_csv = $this->degree_plan->get_major_code_csv();
  971. $catalog_year = $this->degree_plan->catalog_year;
  972. $available_terms = variable_get_for_school("available_advising_term_ids", "0", $school_id);
  973. // Do we need to update the student's settings?
  974. if (trim($_POST["advising_update_student_settings_flag"]) != "")
  975. {
  976. // We are to assume that the student's array_settings
  977. // have already been updated by this point, so we will
  978. // simply convert them to XML and store in the database.
  979. $result = $db->db_query("REPLACE INTO student_settings
  980. (student_id, settings, posted)
  981. VALUES ('?','?', '?' ) ", $student_id, serialize($this->student->array_settings), time());
  982. watchdog("update_student_settings", "Settings updated for this student.");
  983. }
  984. //var_dump($_POST);
  985. // die;
  986. // We have changed tracks, so we are to edit the student degrees table.
  987. if (isset($_POST["advising_update_student_degrees_flag"]) && $_POST["advising_update_student_degrees_flag"] == "true") {
  988. // Begin by deleting all the "editable" rows for this student
  989. // in student_degrees.
  990. db_query("DELETE FROM student_degrees
  991. WHERE student_id = '?'
  992. AND is_editable = '1' ", $student_id);
  993. // Now, go through our list of degree tracks ids we're adding back in, and add to the table.
  994. $temp = explode(",", $_POST["advising_track_degree_ids"]);
  995. foreach ($temp as $tdegree_id) {
  996. if (trim($tdegree_id) == "") continue;
  997. if (!is_numeric($tdegree_id)) continue;
  998. $tdegree_plan = fp_load_degree($tdegree_id, NULL, TRUE);
  999. $tmajor_code = $tdegree_plan->major_code;
  1000. /* // shouldn't need this anymore, as the major_code will contain both the major and track in one.
  1001. $tmajor_code = $tdegree_plan->major_code;
  1002. if (!strstr($tmajor_code, "|")) {
  1003. $tmajor_code .= "|";
  1004. }
  1005. $tmajor_code .= "_" . $tdegree_plan->track_code;
  1006. */
  1007. db_query("INSERT INTO student_degrees
  1008. (student_id, major_code, is_editable)
  1009. VALUES ('?', '?', '1')", $student_id, $tmajor_code);
  1010. }
  1011. // Reset the SESSION variables and re-init, so we get the correct
  1012. // major codes and track codes for this student.
  1013. $_SESSION["advising_track_degree_ids$student_id"] = "";
  1014. $_SESSION["advising_major_code$student_id"] = "";
  1015. $_REQUEST["advising_major_code"] = "";
  1016. $_REQUEST["advising_track_degree_ids"] = "";
  1017. $this->student->load_student_data();
  1018. // force re-build of cache
  1019. //$_REQUEST["load_from_cache"] = "no";
  1020. //$_SESSION["cache_fp$student_id"] = "";
  1021. //$_SESSION["cache_what_if$student_id"] = "";
  1022. $GLOBALS["fp_advising"]["load_from_cache"] = "no";
  1023. $this->init(TRUE);
  1024. $bool_fp_goto_at_end = TRUE;
  1025. } // editing degrees?
  1026. // Is there anything in "log_addition" which we should write to the log?
  1027. if (isset($_POST["log_addition"]) && $_POST["log_addition"])
  1028. {
  1029. $temp = explode("~", (string) $_POST["log_addition"]);
  1030. if ($temp[0] == "change_term") {
  1031. watchdog("change_term", "$student_id," . $temp[1]);
  1032. }
  1033. if ($temp[0] == "change_track"){
  1034. watchdog("change_track", "$student_id," . $temp[1]);
  1035. }
  1036. }
  1037. // If this user cannot advise, then just return right now.
  1038. if (!user_has_permission("can_advise_students")) {
  1039. return;
  1040. }
  1041. // First, create a new entry in the advising_sessions table,
  1042. // so we can get the advising_session_id.
  1043. // But before we can do that, we look for an existing entry
  1044. // which matches this. If we find it, we delete it so the
  1045. // new one will display instead.
  1046. // Only delete if its a draft copy!
  1047. $is_draft = intval($bool_draft);
  1048. $is_what_if = intval($this->bool_what_if);
  1049. // Since we only want one draft copy per term/per student and faculty,
  1050. // let's delete
  1051. // any draft copies already in existence, if we are saving a draft.
  1052. $result = $db->db_query("DELETE FROM advising_sessions
  1053. WHERE student_id = ?
  1054. AND is_draft = 1
  1055. AND faculty_id = ?
  1056. AND degree_id = ?
  1057. AND is_whatif = ? ", $student_id, $faculty_id, $degree_id, $is_what_if);
  1058. // Set all other advising sessions' "most_recent_session" flag to zero (0) for this student (but only if this is NOT an "is_draft" save!)
  1059. if ($is_draft === 0) {
  1060. db_query("UPDATE advising_sessions SET most_recent_session = 0 WHERE student_id = ?", array($student_id));
  1061. }
  1062. // The first thing we need to do is go through the available_terms,
  1063. // create new entries for them in the table, and store what their
  1064. // session ID's are in an array.
  1065. $advising_session_id_array = array();
  1066. $advising_session_id_array_count = array();
  1067. $posted = time();
  1068. $temp = explode(",",$available_terms);
  1069. foreach ($temp as $term_id)
  1070. {
  1071. $term_id = trim($term_id);
  1072. if ($term_id == "") { continue; }
  1073. // Okay, now create a new entry in the system for that term.
  1074. // We create entries for all available terms, whether we
  1075. // are going to use them later or not.
  1076. $result = $db->db_query("INSERT INTO advising_sessions
  1077. (student_id, faculty_id, term_id, degree_id,
  1078. major_code_csv,
  1079. catalog_year, posted, is_whatif, is_draft, advising_session_token, delete_flag, most_recent_session)
  1080. VALUES
  1081. (?,?,?,?,?,?,?,?,?,?, 0, 1)
  1082. ", $student_id, $faculty_id,$term_id,$degree_id, $major_code_csv, $catalog_year, $posted, $is_what_if, $is_draft, $advising_session_token);
  1083. $advising_session_id = db_insert_id();
  1084. $advising_session_id_array[$term_id] = $advising_session_id;
  1085. $advising_session_id_array_count[$term_id] = 0;
  1086. }
  1087. $wi = "";
  1088. if ($is_what_if == "1"){$wi = "_whatif";}
  1089. if ($bool_draft) {
  1090. watchdog("save_adv_draft$wi", "$student_id,major_code_csv:$major_code_csv~adv_session_token:$advising_session_token");
  1091. }
  1092. else {
  1093. watchdog("save_adv_active$wi", "$student_id,major_code_csv:$major_code_csv~adv_session_token:$advising_session_token");
  1094. }
  1095. // Go through the POST, looking for the
  1096. // phrase "advisecourse_" in the name of the variables.
  1097. // There should be one of these for every course that was
  1098. // on the page. It looks like this:
  1099. // advisecourse_course_id_semesterNum_group_id_varHours_randomID
  1100. foreach($_POST as $key => $value)
  1101. {
  1102. if (!strstr($key,"advisecourse_") && !(strstr($key, "advcr_")))
  1103. { // Skip vars which don't have this as part of the name.
  1104. // We accept either advisecourse_ or advcr_ for short. advisecourse_ is the old way.
  1105. // I changed to use advcr_ to save space, because some browsers will not allow long input names.
  1106. continue;
  1107. }
  1108. if ($value != "true")
  1109. { // This means the course was *not* advised to be taken,
  1110. // so, skip it.
  1111. continue;
  1112. }
  1113. // The key might contain a DoT (dot placeholder) instead of a period. If so, let's
  1114. // add the period back in. This was to correct a bug where courses with dots couldn't
  1115. // be advised.
  1116. if (strstr($key, "DoT")) {
  1117. $key = str_replace("DoT", ".", $key);
  1118. }
  1119. $temp = explode("_",$key);
  1120. $course_id = trim($temp[1]);
  1121. $semester_num = trim($temp[2]);
  1122. $group_id = str_replace("U", "_", trim($temp[3])); // replace U with _, which was required for the submission to work (couldn't use the _ in group_id.)
  1123. $var_hours = trim($temp[4]) * 1;
  1124. $random_id = trim($temp[5]);
  1125. $advised_term_id = trim($temp[6]);
  1126. //$db_group_requirement_id = trim($temp[7]);
  1127. $degree_id = trim($temp[7]);
  1128. if ($degree_id == "group") {
  1129. // Get degree_id from the group_id.
  1130. $tt = explode("_", $group_id);
  1131. $degree_id = $tt[1];
  1132. }
  1133. $advising_session_id = $advising_session_id_array[$advised_term_id];
  1134. $new_course = new Course($course_id);
  1135. $new_course->load_descriptive_data();
  1136. $entry_value = "$new_course->subject_id~$new_course->course_num";
  1137. // Some particular course should be updated. Possibly this one.
  1138. // Updates happen because of a student changing the
  1139. // variable hours, for example.
  1140. if (isset($_POST["updatecourse"]) && trim($_POST["updatecourse"]) != "")
  1141. {
  1142. $temp2 = explode("~",trim($_POST["updatecourse"]));
  1143. $tcourse_id = $temp2[0];
  1144. $tgroup_id = $temp2[1];
  1145. $tsemester_num = $temp2[2];
  1146. $tvar_hours = $temp2[3];
  1147. $trandom_id = $temp2[4];
  1148. $tadvised_term_id = $temp2[5];
  1149. $tdegree_id = $temp2[6];
  1150. // Do we have a match?
  1151. if ($course_id == $tcourse_id && $random_id == $trandom_id)
  1152. {
  1153. // We have a match, so update with the new information.
  1154. $var_hours = $tvar_hours;
  1155. $degree_id = $tdegree_id;
  1156. $new_course = new Course($tcourse_id);
  1157. $new_course->load_descriptive_data();
  1158. $entry_value = "$new_course->subject_id~$new_course->course_num";
  1159. $bool_found_update_match = true;
  1160. }
  1161. }
  1162. if ($group_id != 0 && $group_id != '' && $group_id != NULL)
  1163. {
  1164. $this->replace_missing_course_in_group($course_id, $group_id);
  1165. }
  1166. // Make sure degree_id is a valid number for the database.
  1167. if (!is_numeric($degree_id) || intval($degree_id) < 0) {
  1168. $degree_id = 0;
  1169. }
  1170. // Okay, write it to the table...
  1171. $result = $db->db_query("INSERT INTO advised_courses
  1172. (`advising_session_id`,`course_id`,
  1173. `entry_value`,`semester_num`,
  1174. `group_id`,`var_hours`,`term_id`, `degree_id`)
  1175. VALUES
  1176. ('?','?','?','?','?','?','?','?')
  1177. ", $advising_session_id, $course_id, $entry_value, $semester_num, $group_id, $var_hours, $advised_term_id, $degree_id);
  1178. $advising_session_id_array_count[$advised_term_id]++;
  1179. }
  1180. // Did we have to perform an update-- but no course was found?
  1181. if (isset($_POST["updatecourse"]) && trim($_POST["updatecourse"]) != "" && $bool_found_update_match == false)
  1182. {
  1183. // This means that the course was probably on the bare
  1184. // degree program, and not already checked for advising. So,
  1185. // let's add it to the advised_courses table, so it DOES
  1186. // get checked for advising.
  1187. $temp2 = explode("~",trim($_POST["updatecourse"]));
  1188. $course_id = $temp2[0];
  1189. $group_id = $temp2[1];
  1190. $semester_num = $temp2[2];
  1191. $var_hours = $temp2[3];
  1192. $advised_term_id = $temp2[5];
  1193. $degree_id = $temp2[6];
  1194. $new_course = new Course($course_id);
  1195. $new_course->load_descriptive_data();
  1196. $entry_value = "$new_course->subject_id~$new_course->course_num";
  1197. $advising_session_id = $advising_session_id_array[$advised_term_id];
  1198. $result = $db->db_query("INSERT INTO advised_courses
  1199. (`advising_session_id`,`course_id`,`entry_value`,`semester_num`,
  1200. `group_id`,`var_hours`,`term_id`,`degree_id`)
  1201. VALUES
  1202. ('?','?','?','?','?','?','?','?')
  1203. ", $advising_session_id,$course_id,$entry_value,$semester_num,$group_id,$var_hours,$advised_term_id,$degree_id);
  1204. $advising_session_id_array_count[$advised_term_id]++;
  1205. if ($group_id != 0 && $group_id != '' && $group_id != NULL)
  1206. {
  1207. $this->replace_missing_course_in_group($course_id, $group_id);
  1208. }
  1209. }
  1210. //------------------------------------------------------
  1211. //
  1212. // Substitutions...
  1213. //
  1214. //-------------------------------------------------------
  1215. // check permissions for substitutions before saving
  1216. if (isset($_POST["savesubstitution"]) && trim($_POST["savesubstitution"]) != "" && user_has_permission("can_substitute")) {
  1217. $temp = explode("~",trim($_POST["savesubstitution"]));
  1218. $course_id = $temp[0]; // required course
  1219. $group_id = trim($temp[1]);
  1220. $req_by_degree_id = $temp[2];
  1221. $semester_num = $temp[3] * 1;
  1222. $sub_course_id = $temp[4];
  1223. $sub_term_id = $temp[5];
  1224. $sub_transfer_flag = $temp[6];
  1225. $sub_hours = $temp[7] * 1;
  1226. $sub_addition = $temp[8];
  1227. $sub_remarks = urldecode($temp[9]);
  1228. if ($sub_addition == "true")
  1229. {
  1230. $course_id = 0;
  1231. }
  1232. // Figure out the entry values for the required course & sub course...
  1233. $required_entry_value = $sub_entry_value = "";
  1234. if ($course_id > 0)
  1235. {
  1236. $new_course = new Course($course_id);
  1237. $new_course->load_descriptive_data();
  1238. $required_entry_value = "$new_course->subject_id~$new_course->course_num";
  1239. }
  1240. if ($sub_transfer_flag != 1)
  1241. {
  1242. $new_course = new Course($sub_course_id);
  1243. $new_course->load_descriptive_data();
  1244. $sub_entry_value = "$new_course->subject_id~$new_course->course_num";
  1245. }
  1246. if (($group_id != 0 && $group_id != '' && $group_id != NULL) && $course_id != 0)
  1247. {
  1248. $this->replace_missing_course_in_group($course_id, $group_id);
  1249. }
  1250. // Make sure the sub_hours aren't larger than the sub_course_id's awarded hours.
  1251. // This is to stop a bug from happening where sometimes, some people are able to substitute
  1252. // a course for larger than the awarded hours. I believe it is a javascript bug.
  1253. if ($test_c = $this->student->list_courses_taken->find_specific_course($sub_course_id, $sub_term_id, (bool) $sub_transfer_flag, true)) {
  1254. // Are the hours out of whack?
  1255. if (floatval($sub_hours) > floatval($test_c->get_hours_awarded($req_by_degree_id))) {
  1256. // Yes! Set it to the value of the hours_awarded.
  1257. $sub_hours = floatval($test_c->get_hours_awarded($req_by_degree_id));
  1258. }
  1259. }
  1260. $result = $db->db_query("INSERT INTO student_substitutions
  1261. (`student_id`,`faculty_id`,`required_course_id`,`required_entry_value`,
  1262. `required_group_id`,`required_degree_id`,`required_semester_num`,`sub_course_id`,`sub_entry_value`,
  1263. `sub_term_id`,`sub_transfer_flag`,`sub_hours`,`sub_remarks`,`posted`)
  1264. VALUES
  1265. ('?','?','?','?','?','?','?','?','?','?','?','?','?','?')
  1266. ", $student_id,$faculty_id,$course_id,$required_entry_value,$group_id,$req_by_degree_id,$semester_num,$sub_course_id,$sub_entry_value,$sub_term_id,$sub_transfer_flag,$sub_hours,$sub_remarks, time());
  1267. watchdog("save_substitution", "$student_id,group_id:$group_id,insert_id:" . db_insert_id());
  1268. }
  1269. if (isset($_POST["removesubstitution"]) && trim($_POST["removesubstitution"]) != "")
  1270. {
  1271. $temp = explode("~",trim($_POST["removesubstitution"]));
  1272. $sub_id = trim($temp[0]) * 1;
  1273. $result = $db->db_query("UPDATE student_substitutions
  1274. SET `delete_flag`='1'
  1275. WHERE `id`='?' ", $sub_id);
  1276. watchdog("remove_substitution", "$student_id,sub_id:$sub_id");
  1277. }
  1278. //------------------------------------------------------
  1279. //
  1280. // Group Unassignments
  1281. //
  1282. //-------------------------------------------------------
  1283. if (isset($_POST["unassign_group"]) && trim($_POST["unassign_group"]) != "")
  1284. {
  1285. $temp = explode("~",trim($_POST["unassign_group"]));
  1286. $course_id = $temp[0];
  1287. $term_id = $temp[1];
  1288. $transfer_flag = $temp[2];
  1289. $group_id = $temp[3];
  1290. $degree_id = $temp[4];
  1291. $result = db_query("INSERT INTO student_unassign_group
  1292. (`student_id`,`faculty_id`,`course_id`,
  1293. `term_id`,`transfer_flag`,`group_id`,`degree_id`,
  1294. `posted`)
  1295. VALUES
  1296. ('?','?','?','?','?','?','?','?')
  1297. ", $student_id,$faculty_id,$course_id,$term_id,$transfer_flag,$group_id,$degree_id,time());
  1298. watchdog("save_unassign_group", "$student_id,group_id:$group_id,degree_id:$degree_id");
  1299. }
  1300. if (isset($_POST["restore_unassign_group"]) && trim($_POST["restore_unassign_group"]) != "")
  1301. {
  1302. $temp = explode("~",trim($_POST["restore_unassign_group"]));
  1303. $unassign_id = trim($temp[0]) * 1;
  1304. $result = $db->db_query("UPDATE student_unassign_group
  1305. SET `delete_flag`='1'
  1306. WHERE `id`='?' ", $unassign_id);
  1307. watchdog("restore_unassign_group", "$student_id,unassign_id:$unassign_id");
  1308. }
  1309. //------------------------------------------------------
  1310. //
  1311. // Transfer EQV Unassignments
  1312. //
  1313. //-------------------------------------------------------
  1314. if (isset($_POST["unassign_transfer_eqv"]) && trim($_POST["unassign_transfer_eqv"]) != "")
  1315. {
  1316. $temp = explode("~",trim($_POST["unassign_transfer_eqv"]));
  1317. $course_id = $temp[0];
  1318. $result = $db->db_query("INSERT INTO student_unassign_transfer_eqv
  1319. (`student_id`,`faculty_id`,`transfer_course_id`,
  1320. `posted`)
  1321. VALUES
  1322. ('?','?','?','?')
  1323. ", $student_id, $faculty_id, $course_id, time());
  1324. watchdog("save_unassign_transfer", "$student_id,course_id:$course_id");
  1325. }
  1326. if (isset($_POST["restore_transfer_eqv"]) && trim($_POST["restore_transfer_eqv"]) != "")
  1327. {
  1328. $temp = explode("~",trim($_POST["restore_transfer_eqv"]));
  1329. $unassign_id = trim($temp[0]) * 1;
  1330. $result = $db->db_query("UPDATE student_unassign_transfer_eqv
  1331. SET `delete_flag`='1'
  1332. WHERE `id`='?' ", $unassign_id);
  1333. watchdog("restore_unassign_transfer", "$student_id,unassign_id:$unassign_id");
  1334. }
  1335. ////////////////////////////////////////////////////
  1336. /////// Cleanup !////////////////////////////////
  1337. ////////////////////////////////////////////////////
  1338. // If any of the advisingSessions we created earlier
  1339. // are blank, we should FLAG them, so they will not
  1340. // show up under the student's history.
  1341. // Only flag non-draft empty ones. If they are draft,
  1342. // let them be.
  1343. // We just look at $advising_session_id_array_count[] to see
  1344. // if any of the counts are still 0. If they are, delete
  1345. // that advisingSessionID from the table.
  1346. if ($is_draft == 0)
  1347. {
  1348. foreach ($advising_session_id_array as $term_id => $advising_session_id)
  1349. {
  1350. if ($advising_session_id_array_count[$term_id] == 0)
  1351. {
  1352. // This one is blank! Delete it!
  1353. $res = $db->db_query("UPDATE advising_sessions
  1354. SET is_empty = 1
  1355. WHERE advising_session_id = ? ", $advising_session_id);
  1356. $advising_session_id_array[$term_id] = "";
  1357. }
  1358. }
  1359. }
  1360. watchdog("advising", "Student has been advised: @student", array("@student" => $student_id));
  1361. // Call a hook so other modules can act when the advising session gets saved.
  1362. invoke_hook('save_advising_session_from_post', array($student_id, $is_draft, $advising_session_id_array));
  1363. // Instead of executing the page, we will issue a redirect using fp_goto.
  1364. // This makes it so if the user hits "refresh", it will not re-submit a POST request.
  1365. if ($bool_fp_goto_at_end) {
  1366. // Goto the same page we are already on. This mimics Drupal's Form API behavior.
  1367. $q = $_REQUEST['q'];
  1368. fp_goto($q, "advising_major_code=&load_from_cache=no&advising_student_id=$student_id");
  1369. }
  1370. return $advising_session_id_array;
  1371. }
  1372. function load_advising_session_from_database($faculty_id = 0, $term_id = "", $bool_what_if = false, $bool_draft = true, $advising_session_id = 0, $duplicate_for_faculty_id = 0)
  1373. {
  1374. global $user;
  1375. // This method will load an advising session for a particular
  1376. // student, and modify the degree plan object to reflect
  1377. // the advisings.
  1378. $db = get_global_database_handler();
  1379. $is_what_if = "0";
  1380. $is_draft = "0";
  1381. if ($bool_what_if == true){$is_what_if = "1";}
  1382. if ($bool_draft == true){$is_draft = "1";}
  1383. $degree_id = $this->degree_plan->degree_id;
  1384. $student_id = $this->student->student_id;
  1385. $school_id = db_get_school_id_for_student_id($student_id);
  1386. $available_terms = variable_get_for_school("available_advising_term_ids", "0", $school_id);
  1387. // If we are pulling up an active student record, then let's
  1388. // delete any draft sessions for this faculty user and student, so as not to cause
  1389. // a bug later on when changing tabs. We don't care if $faculty_id is set or not, just
  1390. // the current user's CWID.
  1391. if ($bool_draft == FALSE && $user->cwid != 0) {
  1392. $res = db_query("DELETE FROM advising_sessions
  1393. WHERE student_id = ?
  1394. AND faculty_id = ?
  1395. AND is_draft = 1
  1396. ", $student_id, $user->cwid);
  1397. }
  1398. $advising_session_line = " `advising_session_id`='$advising_session_id' ";
  1399. // First, find the advising session id...
  1400. if ($advising_session_id < 1 && $available_terms == "")
  1401. {
  1402. $advising_session_id = $this->db->get_advising_session_id($faculty_id, $student_id, $term_id, $degree_id, $bool_what_if, $bool_draft, TRUE);
  1403. $advising_session_line = " `advising_session_id`='$advising_session_id' ";
  1404. // Create a duplicate of this session as a draft...
  1405. if ($bool_draft == FALSE) {
  1406. $db->duplicate_advising_session($advising_session_id, $duplicate_for_faculty_id, "", "", "", "", 1);
  1407. }
  1408. } else if ($advising_session_id < 1 && $available_terms != "")
  1409. {
  1410. // Meaning, we are looking for more than one term.
  1411. $advising_session_line = "(";
  1412. $temp = explode(",",$available_terms);
  1413. for ($t = 0; $t < count($temp); $t++)
  1414. {
  1415. $t_id = trim($temp[$t]);
  1416. $asid = $this->db->get_advising_session_id($faculty_id, $student_id, $t_id,$degree_id, $bool_what_if, $bool_draft, TRUE);
  1417. if ($asid != 0)
  1418. {
  1419. $advising_session_line .= " advising_session_id='$asid' || ";
  1420. // Create a duplicate of this session as a draft...
  1421. if ($bool_draft == FALSE) {
  1422. $db->duplicate_advising_session($asid, $duplicate_for_faculty_id, "", "", "", "", 1);
  1423. }
  1424. }
  1425. }
  1426. // Take off the last 3 chars...
  1427. $advising_session_line = substr($advising_session_line, 0, -3);
  1428. $advising_session_line .= ")";
  1429. if ($advising_session_line == ")")
  1430. { // Found NO previously advised semesters, so just
  1431. // use a dummy value which guarantees it pulls up nothing.
  1432. $advising_session_line = " advising_session_id='-99999'";
  1433. }
  1434. }
  1435. // Now, look up the courses they were advised to take.
  1436. $query = "SELECT * FROM advised_courses
  1437. WHERE
  1438. $advising_session_line
  1439. ORDER BY `id` ";
  1440. $result = $db->db_query($query);
  1441. while($cur = $db->db_fetch_array($result))
  1442. {
  1443. $course_id = trim($cur["course_id"]);
  1444. $semester_num = trim($cur["semester_num"]);
  1445. $group_id = trim($cur["group_id"]);
  1446. $degree_id = $cur["degree_id"];
  1447. $var_hours = trim($cur["var_hours"]);
  1448. $advised_term_id = trim($cur["term_id"]);
  1449. $id = trim($cur["id"]);
  1450. // Add this course to the generic list of advised courses. Useful
  1451. // if we are using this to pull up an advising summary.
  1452. $temp_course = new Course($course_id);
  1453. $temp_course->advised_hours = $var_hours;
  1454. $this->course_list_advised_courses->add($temp_course);
  1455. if ($semester_num == DegreePlan::SEMESTER_NUM_FOR_COURSES_ADDED)
  1456. {
  1457. // This was a courses added by the advisor.
  1458. $this->assign_course_to_courses_added_list($course_id, $var_hours, $id, $advised_term_id);
  1459. continue;
  1460. }
  1461. // Now, we need to modify the degree_plan object to
  1462. // show these advisings.
  1463. if ($course_list = $this->degree_plan->find_courses($course_id, $group_id, $semester_num, $degree_id))
  1464. {
  1465. // This course may exist in several different branches of a group, so we need
  1466. // to mark all the branches as having been advised to take. Usually, this CourseList
  1467. // will probably only have 1 course object in it. But, better safe than sorry.
  1468. $course_list->reset_counter();
  1469. if ($course = $course_list->get_next())
  1470. {
  1471. // make sure the hour count has been loaded correctly.
  1472. if ($course->get_catalog_hours() < 1)
  1473. {
  1474. $course->load_descriptive_data();
  1475. }
  1476. // Let's start by looking at the first course. Is it
  1477. // supposed to be repeated?
  1478. if ($course->bool_specified_repeat==true
  1479. && $course->specified_repeats >= 0 )
  1480. {
  1481. // This is a course which is supposed to be repeated.
  1482. // We need to cycle through and find an instance
  1483. // of this course which has not been advised yet.
  1484. $course_list->reset_counter();
  1485. while($course_list->has_more())
  1486. {
  1487. $course = $course_list->get_next();
  1488. // make sure the hour count has been loaded correctly.
  1489. if ($course->get_catalog_hours() < 1)
  1490. {
  1491. $course->load_descriptive_data();
  1492. }
  1493. ////////////////////
  1494. // Logan's change: https://bytetask.com/node/2455
  1495. // If we have the setting which says we should skip if it's already been completed/enrolled for this term,
  1496. // then we should do that.
  1497. if (variable_get_for_school("remove_advised_when_course_taken", "no", $school_id) == "yes") {
  1498. // First, see if this advised course has been attempted already.
  1499. if ($this->student->list_courses_taken->find_specific_course($course->course_id, $advised_term_id)) {
  1500. // Yep, found it! So, skip this one.
  1501. continue;
  1502. }
  1503. }
  1504. //////////////////////////
  1505. //if ($course->bool_advised_to_take != true && !is_object($course->courseFulfilledBy))
  1506. if ($course->bool_advised_to_take != true && $course->course_list_fulfilled_by->is_empty == true)
  1507. {
  1508. // Okay, this course is supposed to be taken/advised
  1509. // more than once. So, I will mark this one as
  1510. // advised, and then break out of the loop, since
  1511. // I don't want to mark all occurances as advised.
  1512. $course->bool_advised_to_take = true;
  1513. $course->assigned_to_semester_num = $semester_num;
  1514. //$course->assigned_to_group_id = $group_id;
  1515. $course->assigned_to_group_ids_array[$group_id] = $group_id;
  1516. // Make sure we assign the hours to the group, so this
  1517. // advised courses takes up a spot in the group. Otherwise
  1518. // it may be missed in later logic.
  1519. if ($g = $this->degree_plan->find_group($group_id)) {
  1520. $h = $var_hours;
  1521. if ($h == 0) {
  1522. $h = $course->get_catalog_hours();
  1523. if ($h == 0) {
  1524. $h = 1; // some problem occured. Just give it a token hour so it doesn't
  1525. // horribly break.
  1526. }
  1527. }
  1528. $g->hours_assigned += $h;
  1529. }
  1530. $course->advised_hours = $var_hours;
  1531. $course->advised_term_id = $advised_term_id;
  1532. $course->db_advised_courses_id = $id;
  1533. $course_list->dec_specified_repeats($course);
  1534. break;
  1535. }
  1536. }
  1537. continue; // Go to the next advised course.
  1538. }
  1539. } // if $course = $course_list->get_next();
  1540. //////////////////////////////
  1541. // We're here, because it was not a repeatable course.
  1542. // ** We should only go through THIS loop once! So,
  1543. // we will break after we make our assignment.
  1544. $course_list->reset_counter();
  1545. while($course_list->has_more())
  1546. {
  1547. $course = $course_list->get_next();
  1548. // make sure the hour count has been loaded correctly.
  1549. if ($course->get_catalog_hours() < 1)
  1550. {
  1551. $course->load_descriptive_data();
  1552. }
  1553. // make sure it has not already been advised to take.
  1554. // Would occur if the same course is specified more
  1555. // than once in a semester.
  1556. if ($course->bool_advised_to_take == true)
  1557. {
  1558. continue;
  1559. }
  1560. // If we have the setting which says we should skip if it's already been completed/enrolled for this term,
  1561. // then we should do that.
  1562. if (variable_get_for_school("remove_advised_when_course_taken", "no", $school_id) == "yes") {
  1563. // First, see if this advised course has been attempted already.
  1564. if ($taken_course = $this->student->list_courses_taken->find_specific_course($course->course_id, $advised_term_id)) {
  1565. // Yep, found it! So, skip this one.
  1566. continue;
  1567. }
  1568. }
  1569. // Has this course already been fulfilled by something?
  1570. // If so, we cannot attempt to say it's been advised!
  1571. if (!$course->course_list_fulfilled_by->is_empty)
  1572. {
  1573. // meaning, this course HAS been fulfilled.
  1574. // So, let's move this advising to the "added by advisor"
  1575. // spot.
  1576. /* This is the original bit of code here. It is causing a problem when there are courses which are supposed to be
  1577. * repeated. Example: MUSC courses which are advised one term at a time.
  1578. *
  1579. *
  1580. $this->assign_course_to_courses_added_list($course_id, $var_hours, $id, $advised_term_id);
  1581. break;
  1582. *
  1583. * Strategy: Find out how many courses are in this course_list by looking at the size of the list. If it's > 1, then just continue. If it == 1, then
  1584. * do the original logic.
  1585. *
  1586. */
  1587. if ($course_list->get_size() > 1) {
  1588. continue;
  1589. }
  1590. else {
  1591. $this->assign_course_to_courses_added_list($course_id, $var_hours, $id, $advised_term_id);
  1592. break;
  1593. }
  1594. }
  1595. $course->bool_advised_to_take = true;
  1596. $course->assigned_to_semester_num = $semester_num;
  1597. //$course->assigned_to_group_id = $group_id;
  1598. $course->assigned_to_group_ids_array[$group_id] = $group_id;
  1599. // Make sure we assign the hours to the group, so this
  1600. // advised courses takes up a spot in the group. Otherwise
  1601. // it may be missed in later logic.
  1602. if ($g = $this->degree_plan->find_group($group_id)) {
  1603. $h = $var_hours;
  1604. if ($h == 0) {
  1605. $h = $course->get_catalog_hours();
  1606. if ($h == 0) {
  1607. $h = 1; // some problem occured. Just give it a token hour so it doesn't
  1608. // horribly break.
  1609. }
  1610. }
  1611. $g->hours_assigned += $h;
  1612. }
  1613. $course->advised_hours = $var_hours;
  1614. $course->advised_term_id = $advised_term_id;
  1615. $course->db_advised_courses_id = $id;
  1616. if ($course->required_on_branch_id > 0)
  1617. {
  1618. // In other words, this course was found on a branch, so we need
  1619. // to increment that branch's count_of_matches.
  1620. if ($branch = $this->degree_plan->find_group($course->required_on_branch_id))
  1621. {
  1622. $branch->count_of_matches++;
  1623. } else {
  1624. fpm("Error: Could not find branch.");
  1625. }
  1626. }
  1627. // We should only be in this loop once, so let's
  1628. // break after we make our assignment.
  1629. break;
  1630. }
  1631. }
  1632. }
  1633. // Now, what we need to do is tell the DegreePlan to re-sort its
  1634. // group's course lists, so that the advised courses are lower
  1635. // than the fulfilled courses.
  1636. //$this->degree_plan->sortGroupsFulfilledFirst();
  1637. //print_pre($this->degree_plan->list_groups->toString());
  1638. } // function loadAdvisingSessionFromDatabase
  1639. function split_requirements_by_substitutions()
  1640. {
  1641. // Go through all the required courses on the degree plan,
  1642. // and if there is a partial substitution specified in the student's
  1643. // list of substitutions, then split that requirement into 2 courses,
  1644. // one with enough hours to satisfy the sub, and the remaining hours.
  1645. $degree_plan = $this->degree_plan;
  1646. $student = $this->student;
  1647. $student->list_substitutions->reset_counter();
  1648. while($student->list_substitutions->has_more())
  1649. {
  1650. $substitution = $student->list_substitutions->get_next();
  1651. $course_requirement = $substitution->course_requirement;
  1652. $course_sub = $substitution->course_list_substitutions->get_first();
  1653. // TODO: This could be an important part right here
  1654. // Check to see if the courseSub's hours_awarded are less than the
  1655. // course_requirement's min hours...
  1656. if ($course_requirement->min_hours > $course_sub->get_hours_awarded())
  1657. {
  1658. // Meaning the original course requirement is not being
  1659. // fully satisfied by this substitution! The original
  1660. // course requirement has hours left over which must be
  1661. // fulfilled somehow.
  1662. $remaining_hours = round($course_requirement->min_hours - $course_sub->get_hours_awarded(), 6);
  1663. // This means that the course requirement needs to be split.
  1664. // So, find this course in the degree plan.
  1665. $required_course_id = $course_requirement->course_id;
  1666. //$required_group_id = $course_requirement->assigned_to_group_id;
  1667. $required_group_id = $course_requirement->get_first_assigned_to_group_id(); // we assume a course requirement is only assigned to 1 group.
  1668. $required_semester_num = $course_requirement->assigned_to_semester_num;
  1669. }
  1670. }
  1671. } // split_requirements_by_substitution
  1672. function assign_course_to_courses_added_list($course_id, $var_hours = 0, $db_advised_courses_id = 0, $advised_term_id = 0)
  1673. {
  1674. // Set the supplied course as "advised to take" in the degree plan's
  1675. // special added courses group, which is number -88.
  1676. $course = new Course($course_id, false, $this->db);
  1677. $course->bool_advised_to_take = true;
  1678. $course->assigned_to_semester_num = DegreePlan::SEMESTER_NUM_FOR_COURSES_ADDED;
  1679. //$course->assigned_to_group_id = -88;
  1680. $course->assigned_to_group_ids_array[DegreePlan::GROUP_ID_FOR_COURSES_ADDED] = DegreePlan::GROUP_ID_FOR_COURSES_ADDED;
  1681. $course->advised_hours = $var_hours;
  1682. $course->db_advised_courses_id = $db_advised_courses_id;
  1683. $course->advised_term_id = $advised_term_id;
  1684. if ($group = $this->degree_plan->find_group(DegreePlan::GROUP_ID_FOR_COURSES_ADDED))
  1685. {
  1686. $group->list_courses->add($course);
  1687. }
  1688. // Done!
  1689. }
  1690. }

Classes

Namesort descending Description
FlightPath