admin.degrees.inc

  1. 6.x modules/admin/admin.degrees.inc
  2. 4.x modules/admin/admin.degrees.inc
  3. 5.x modules/admin/admin.degrees.inc

File

modules/admin/admin.degrees.inc
View source
  1. <?php
  2. function admin_display_degrees_popup_add_group2() {
  3. $semester_num = trim($_GET["semester_num"]);
  4. $school_id = intval($_GET["school_id"]);
  5. $de_catalog_year = admin_get_de_catalog_year(TRUE, $school_id);
  6. $school_name = "";
  7. if ($school_id > 0) $school_name = " School-" . $school_id;
  8. if (module_enabled("schools")) {
  9. $defs = schools_get_school_definitions();
  10. if (isset($defs[$school_id])) $school_name = $defs[$school_id];
  11. }
  12. fp_add_js(fp_get_module_path("admin") . "/js/admin.js");
  13. $rtn = "";
  14. $rtn .= "<b>" . t("Add an elective group to block number: @semester_num in catalog year @de_catalog_year", array("@semester_num" => ($semester_num + 1), "@de_catalog_year" => $de_catalog_year)) . "</b><br>";
  15. if ($school_name) {
  16. $rtn .= "<div class='add-group-popup-school-line'><strong>" . t("Groups in School: %school", array("%school" => $school_name)) . "</strong></div>";
  17. }
  18. $rtn .="<span class='tenpt'>" . t("Use keyboard shortcut CTRL-F to find groups quickly.") . "</span>
  19. <br><br>
  20. " . t("First, select a group (from @cat)", array("@cat" => $de_catalog_year));
  21. if ($school_name) {
  22. $rtn .= " " . t(" and school <b>%school</b>", array("%school" => $school_name));
  23. }
  24. $rtn .= ":
  25. <div class='tenpt'
  26. style='height:200px; overflow-y: scroll; border: 1px solid black;
  27. margin:5px;'>
  28. <table border='0' cellspacing='5'>";
  29. $res = db_query("SELECT * FROM draft_groups
  30. WHERE catalog_year = ?
  31. AND delete_flag = 0
  32. AND school_id = ?
  33. ORDER BY title ", $de_catalog_year, $school_id);
  34. while($cur = db_fetch_array($res)) {
  35. extract($cur, 3, "db");
  36. $rtn .= "<tr><td valign='middle'>
  37. <input type='radio' name='rgroups' value='$db_group_id'></td>
  38. <td valign='top' class='tenpt'>
  39. $db_title<br><i>$db_group_name</i>
  40. </td>
  41. </tr>
  42. ";
  43. }
  44. $min_grades = csv_to_array(variable_get_for_school("group_min_grades", "A,B,C,D", $school_id));
  45. $rtn .= "</table></div>
  46. " . t("Next, select properties for this group:") . "
  47. <a href='javascript: adminPopupAlertHelp(\"group_properties\");'>?</a>
  48. <div class='tenpt' style='padding-top: 5px;'>
  49. " . t("Hrs:") . " <input type='text' name='hours' id='hours' size='2'>
  50. " . t("Min Grade:") . " <select name='min_grade' id='min_grade'>
  51. <option value=''>--</option>
  52. ";
  53. foreach ($min_grades as $g) {
  54. $rtn .= "<option value='$g'>$g</option>";
  55. }
  56. $rtn .= "
  57. </select>
  58. Type: <select name='type' id='type'>";
  59. // Get our list of requirement types from our settings.
  60. $types = fp_get_requirement_types($school_id);
  61. foreach ($types as $code => $desc) {
  62. $rtn .= "<option value='$code'>$code - $desc</option>";
  63. }
  64. $rtn .= "
  65. </select>
  66. &nbsp; &nbsp;
  67. " . fp_render_button("Add group &raquo;", "adminPopupAddGroup2(\"$semester_num\");") . "
  68. </div>";
  69. return $rtn;
  70. }
  71. /**
  72. * This form lets the user copy a degree and all of it's tracks & concentrations.
  73. */
  74. function admin_copy_degree_form() {
  75. $de_catalog_year = admin_get_de_catalog_year();
  76. fp_set_title(t("Copy Degree for") . " $de_catalog_year");
  77. $form = array();
  78. $m = 0;
  79. $form["mark" . $m++] = array(
  80. "type" => "markup",
  81. "value" => t("Use this form to duplicate a degree plan in this catalog year."),
  82. "weight" => 10,
  83. );
  84. $form["de_catalog_year"] = array(
  85. "type" => "hidden",
  86. "value" => $de_catalog_year,
  87. );
  88. $form["source_major_code"] = array(
  89. "type" => "textfield",
  90. "size" => 35,
  91. "label" => t("Enter the SOURCE major code you wish to copy:"),
  92. "required" => TRUE,
  93. "description" => t("Ex: ART or GBUS. Do not enter any track or concentration codes here."),
  94. "weight" => 20,
  95. );
  96. /* use default school_id */
  97. $form['school_id'] = array(
  98. 'type' => 'hidden',
  99. 'value' => '0',
  100. );
  101. $form["include_tracks"] = array(
  102. "type" => "checkboxes",
  103. "label" => t("Include tracks/level-3 degrees?"),
  104. "options" => array("yes" => "Yes, include all associated tracks (level-3 degrees)."),
  105. "description" => t("Check this box if you wish to also copy any tracks/level-3 degrees
  106. this major code may have associated with it. If you do not check this box,
  107. only the base degree will be copied. If the major does not have
  108. tracks/level-3 degrees, leave this unchecked."),
  109. "weight" => 30,
  110. );
  111. $form['destination_school_id'] = array(
  112. 'type' => 'hidden',
  113. 'value' => '0',
  114. );
  115. $form["destination_major_code"] = array(
  116. "type" => "textfield",
  117. "size" => 35,
  118. "label" => t("Enter the DESTINATION major code you wish to create/overwrite:"),
  119. "required" => TRUE,
  120. "description" => t("Ex: CHEM or XYZ. Do not enter any track or concentration codes here."),
  121. "weight" => 40,
  122. );
  123. $form["allow_overwrite"] = array(
  124. "type" => "radios",
  125. "label" => t("Overwrite if major code already exists?"),
  126. "options" => array(
  127. "no" => t("No, DO NOT delete and overwrite any existing major codes & associated tracks/level-3 degrees. Instead, return here with a warning message."),
  128. "yes" => t("Yes, if my destination major already exists, overwrite <b>and delete all associated tracks/level-3 degrees</b> for this year. (Use caution with this option!)"),
  129. ),
  130. "value" => "no",
  131. "weight" => 50,
  132. );
  133. // Our submit button.
  134. $form["submit"] = array(
  135. "type" => "submit",
  136. "value" => "Submit",
  137. "prefix" => "<hr>",
  138. "weight" => 200,
  139. );
  140. return $form;
  141. }
  142. /**
  143. * Validate handler.
  144. * Make sure our allow_overwrite setting is working. Check for existing major code.
  145. */
  146. function admin_copy_degree_form_validate($form, $form_state) {
  147. $values = $form_state["values"];
  148. $de_catalog_year = $values["de_catalog_year"];
  149. $destination_major_code = trim(strtoupper($values["destination_major_code"]));
  150. $school_id = intval($values['school_id']);
  151. $destination_school_id = intval($values['destination_school_id']);
  152. $source_major_code = trim(strtoupper($values["source_major_code"]));
  153. $include_tracks = $values["include_tracks"]["yes"];
  154. $for_school = $school_name = "";
  155. if (module_enabled("schools")) {
  156. $for_school = " for school %school";
  157. $source_school_name = schools_get_school_name_for_id($school_id);
  158. $dest_school_name = schools_get_school_name_for_id($destination_school_id);
  159. }
  160. if (admin_string_contains_illegal_chars($destination_major_code)) {
  161. form_error("destination_major_code", t("Sorry, the destination major code must contain only numbers, letters, and dashes (-)."));
  162. return;
  163. }
  164. if ($values["allow_overwrite"] == "no") {
  165. // Check to see if destination major code already exists.
  166. // First thing's first. Make sure the sourceMajorCode exists.
  167. $res = db_query("SELECT * FROM draft_degrees
  168. WHERE major_code = ?
  169. AND catalog_year = ?
  170. AND school_id = ? ", $destination_major_code, $de_catalog_year, $destination_school_id) ;
  171. if (db_num_rows($res) != 0) {
  172. // Meaning, it WAS be found.
  173. form_error("destination_major_code", t("The destination major, %dest, was found for %year$for_school. Since you selected not to overwrite
  174. existing majors, your submission was not processed. Please try again.", array("%dest" => $destination_major_code, "%year" => $de_catalog_year, "%school" => $dest_school_name)));
  175. }
  176. } // allow_overwrite == no
  177. // First thing's first. Make sure the sourceMajorCode exists.
  178. $res = db_query("SELECT * FROM draft_degrees
  179. WHERE (major_code = ?
  180. OR major_code LIKE ?)
  181. AND catalog_year = ?
  182. AND school_id = ? ", $source_major_code, "$source_major_code|%", $de_catalog_year, $school_id) ;
  183. if (db_num_rows($res) == 0) {
  184. // Meaning, it could not be found.
  185. form_error("source_major_code", t("The source major, %source, could not be found for %year$for_school.", array("%source" => $source_major_code, "%year" => $de_catalog_year, "%school" => $source_school_name)));
  186. }
  187. } // validate
  188. /*
  189. From: https://stackoverflow.com/questions/32138089/how-to-check-if-a-string-contains-certain-characters-using-an-array-in-php
  190. We will use this function to make sure a major code doesn't contain any "illegal" characters.
  191. */
  192. function admin_string_contains_illegal_chars($testString) {
  193. // These are characters we will allow:
  194. static $MsgAry1 = array("a","b","c","d",
  195. "e","f","g","h","i","j","k","l","m","n",
  196. "o","p","q","r","s","t","u","v","w","x",
  197. "y","z","1","2","3","4","5","6","7","8",
  198. "9","0","-");
  199. $test = str_ireplace($MsgAry1, '', $testString);
  200. if (strstr($test, " ")) return TRUE; // contains an illegal character!
  201. // test should be empty if we only used valid chars!
  202. if (trim($test) == "") return FALSE;
  203. return TRUE;
  204. }
  205. function admin_copy_degree_form_submit($form, &$form_state) {
  206. global $db;
  207. $values = $form_state["values"];
  208. $de_catalog_year = $values["de_catalog_year"];
  209. $school_id = intval($values['school_id']);
  210. $destination_school_id = intval($values['destination_school_id']);
  211. $source_major_code = trim(strtoupper($values["source_major_code"]));
  212. $destination_major_code = trim(strtoupper($values["destination_major_code"]));
  213. $include_tracks = $values["include_tracks"]["yes"];
  214. // Alright, if we got to here, we can proceed. We need to
  215. // delete everything involving the destination major.
  216. // First, get the degree_id's in a select...
  217. $res = db_query("SELECT * FROM draft_degrees
  218. WHERE (major_code = ?
  219. OR major_code LIKE ?)
  220. AND catalog_year = ?
  221. AND school_id = ? ", $destination_major_code, "$destination_major_code|%", $de_catalog_year, $destination_school_id ) ;
  222. if (db_num_rows($res) > 0) {
  223. while ($cur = db_fetch_array($res)) {
  224. $degree_id = $cur["degree_id"];
  225. $res2 = db_query("DELETE FROM draft_degree_requirements
  226. WHERE degree_id='?' ", $degree_id) ;
  227. $res2 = db_query("DELETE FROM draft_degrees
  228. WHERE degree_id = '?' ", $degree_id) ;
  229. }
  230. // Now, delete the tracks.
  231. $res2 = db_query("DELETE FROM draft_degree_tracks
  232. WHERE major_code = ?
  233. AND catalog_year = ?
  234. AND school_id = ?", $destination_major_code, $de_catalog_year, $destination_school_id) ;
  235. }
  236. // Okay, with the destination major good and deleted, we can proceed with
  237. // the copy.
  238. // Let's build up an array of all the degrees we will be copying.
  239. $source_array = array();
  240. // First, the base degree...
  241. $res = db_query("SELECT * FROM draft_degrees
  242. WHERE major_code = ?
  243. AND catalog_year= ?
  244. AND school_id = ? ", $source_major_code, $de_catalog_year, $school_id) ;
  245. $cur = db_fetch_array($res);
  246. $source_array[] = $cur;
  247. // Now, any tracks or concentrations?
  248. if ($include_tracks == "yes") {
  249. $res = db_query("SELECT * FROM draft_degrees
  250. WHERE major_code LIKE ?
  251. AND catalog_year = ?
  252. AND school_id = ? ", "$source_major_code|%", $de_catalog_year, $school_id) ;
  253. while ($cur = db_fetch_array($res)) {
  254. $source_array[] = $cur;
  255. }
  256. // While we're here, let's go ahead and make a copy of the tracks.
  257. $res = db_query("SELECT * FROM draft_degree_tracks
  258. WHERE (major_code = ?
  259. OR major_code LIKE ? )
  260. AND catalog_year = ?
  261. AND school_id = ? ", $source_major_code, "$source_major_code|%", $de_catalog_year, $school_id) ;
  262. while($cur = db_fetch_array($res)) {
  263. extract($cur, 3, "db");
  264. $dest_code = $destination_major_code;
  265. if (strstr($db_major_code, "|")) {
  266. // We need to adjust the destCode to match
  267. //the source.
  268. $dest_code = str_replace("$source_major_code|", "$destination_major_code|", $db_major_code);
  269. }
  270. $res2 = db_query("INSERT INTO draft_degree_tracks
  271. (catalog_year, major_code, track_code,
  272. track_title, track_short_title, track_description, school_id)
  273. VALUES
  274. (?, ?, ?, ?, ?, ?, ?) ",
  275. $de_catalog_year, $dest_code, $db_track_code,
  276. $db_track_title, $db_track_short_title,
  277. $db_track_description, $destination_school_id) ;
  278. }
  279. }
  280. $db = get_global_database_handler();
  281. // Okay, now it's time to go through the sourceArray
  282. // and duplicate them.
  283. foreach ($source_array as $src) {
  284. extract($src, 3, "src");
  285. $dest_code = $destination_major_code;
  286. if (strstr($src_major_code, "|")) {
  287. // We need to adjust the destCode to match
  288. //the source.
  289. $dest_code = str_replace("$source_major_code|", "$destination_major_code|", $src_major_code);
  290. }
  291. //var_dump($dest_code);
  292. $dest_degree_id = $db->request_new_degree_id();
  293. // Let's save our src_degree_id and dest_degree_id in $form_state, for other possible modules to use.
  294. $form_state['degrees'][] = array(
  295. 'src' => $src_degree_id,
  296. 'src_catalog_year' => $de_catalog_year,
  297. 'school_id' => $school_id,
  298. 'dest' => $dest_degree_id,
  299. 'dest_major_code' => $dest_code,
  300. 'dest_catalog_year' => $de_catalog_year,
  301. );
  302. // Create the entry in the degrees table.
  303. $res = db_query("INSERT INTO draft_degrees
  304. (degree_id, major_code, degree_type, degree_level, degree_class, title,
  305. public_note, semester_titles_csv,
  306. catalog_year, exclude, allow_dynamic, advising_weight, override_degree_hours,
  307. min_tracks, max_tracks, default_tracks, track_selection_config, school_id)
  308. VALUES
  309. (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ",
  310. $dest_degree_id, $dest_code, $src_degree_type, $src_degree_level, $src_degree_class, $src_title,
  311. $src_public_note, $src_semester_titles_csv,
  312. $de_catalog_year, $src_exclude, $src_allow_dynamic, $src_advising_weight, $src_override_degree_hours,
  313. $src_min_tracks, $src_max_tracks, $src_default_tracks, $src_track_selection_config, $destination_school_id);
  314. // Now, go through the source's degree requirements and copy those over.
  315. $res = db_query("SELECT * FROM draft_degree_requirements
  316. WHERE degree_id = ?", array($src_degree_id));
  317. while ($cur = db_fetch_array($res)) {
  318. extract($cur, 3, "db");
  319. $res2 = $db->db_query("INSERT INTO draft_degree_requirements
  320. (degree_id, semester_num, group_id,
  321. group_requirement_type,
  322. group_hours_required,
  323. group_min_hours_allowed,
  324. group_min_grade, course_id,
  325. course_min_grade,
  326. course_requirement_type,
  327. data_entry_value)
  328. VALUES
  329. (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ",
  330. $dest_degree_id, $db_semester_num, $db_group_id,
  331. $db_group_requirement_type,
  332. $db_group_hours_required,
  333. $db_group_min_hours_allowed,
  334. $db_group_min_grade, $db_course_id,
  335. $db_course_min_grade,
  336. $db_course_requirement_type,
  337. $db_data_entry_value);
  338. }
  339. }
  340. // Make a - entry into the draft_instruction table so it will
  341. // remind the administrator to apply draft changes.
  342. $res = db_query("INSERT INTO draft_instructions
  343. (instruction) VALUES ('-') ");
  344. $for_school = $school_name = "";
  345. if (module_enabled("schools")) {
  346. $for_school = " for school %school";
  347. $school_name = schools_get_school_name_for_id($destination_school_id);
  348. }
  349. watchdog("admin", "Copied degree $source_major_code to $destination_major_code,school id: $school_id, ($de_catalog_year) successfully.
  350. Source degree id: $src_degree_id. New degree id = $dest_degree_id");
  351. fp_add_message(t("Degree %source has been copied to %dest for %year$for_school.",
  352. array("%source" => $source_major_code, "%dest" => $destination_major_code, "%year" => $de_catalog_year, "%school" => $school_name)));
  353. }
  354. /**
  355. * This form lets the user add a degree to the database.
  356. */
  357. function admin_add_degree_form() {
  358. $de_catalog_year = admin_get_de_catalog_year();
  359. fp_set_title(t("Add Degree for") . " " . $de_catalog_year);
  360. $form = array();
  361. $m = 0;
  362. $form["markup" . $m++] = array(
  363. "type" => "markup",
  364. "value" => t("You may use this screen to add a new degree,
  365. by entering a new degree code (Level 1 or 2) or <em>track</em> (Level-3 degree) code.
  366. <br><br><em>Note: For simplicity, FlightPath refers to Level-1 and -2 degree codes as \"major codes\" and Level-3 degree codes as \"track codes\".</e>"),
  367. );
  368. $bool_legacy_concentrations = variable_get("enable_legacy_concentrations", FALSE);
  369. $legacy_text = "";
  370. if ($bool_legacy_concentrations) {
  371. $legacy_text = " [and concentration] ";
  372. }
  373. $form["de_catalog_year"] = array(
  374. "type" => "hidden",
  375. "value" => $de_catalog_year,
  376. );
  377. $form["new_major"] = array(
  378. "type" => "radios",
  379. "label" => t("Are you entering a new major code $legacy_text,<br>
  380. or an existing major code $legacy_text (so you can add a new track)?"),
  381. "options" => array(
  382. "new" => t("Entering a <b>new</b> major code"),
  383. "existing" => t("Entering an <b>existing</b> major code (only adding a new Level-3 track)"),
  384. ),
  385. "required" => TRUE,
  386. "weight" => 10,
  387. );
  388. $desc = "Enter the Level-1 or -2 Major Code here.
  389. Do not enter any Level 3 codes (ex: Tracks or Concentrations).
  390. <br>For example, enter ACCT or ENGL. <i><b>But not ENGL|_TRKA, etc</b></i>";
  391. if ($bool_legacy_concentrations) {
  392. $desc = "To enter a concentration code, use MAJOR|CONC.
  393. The | character is call the pipe, and it should under the backspace key.
  394. If adding a new concentration to an existing major, you still put this in as a
  395. NEW major code. Do not have any spaces in this box. The concentration code
  396. is optional. If the major does not have a concentration,
  397. then simply enter the major code by itself. The combined major code and optional track
  398. code can only be 18 characters maximum.";
  399. }
  400. $form["major_code"] = array(
  401. "type" => "textfield",
  402. "size" => 15,
  403. "label" => t("Level-1 or -2 Major Code:"),
  404. "description" => t($desc),
  405. "required" => TRUE,
  406. "weight" => 20,
  407. "description" => t("Enter only letters, numbers, or dash (-). NO other symbols of any kind."),
  408. );
  409. $form["new_track"] = array(
  410. "type" => "radios",
  411. "label" => t("Are you entering a new Level-3 track code?"),
  412. "options" => array(
  413. "new" => t("Entering a <b>new</b> track code"),
  414. "none" => t("None - Not adding a track. Leave blank"),
  415. ),
  416. "required" => TRUE,
  417. "weight" => 30,
  418. );
  419. $form["track_code"] = array(
  420. "type" => "textfield",
  421. "size" => 15,
  422. "label" => t("Level-3 Track code:"),
  423. "description" => t("Leave blank if you selected None above. This code must not contain spaces,
  424. and combined with the major code it must not exceed 18 characters."),
  425. "weight" => 40,
  426. "description" => t("Enter only letters, numbers, or dash (-). NO other symbols of any kind."),
  427. );
  428. // Our submit button.
  429. $form["submit"] = array(
  430. "type" => "submit",
  431. "value" => "Submit",
  432. "prefix" => "<hr>",
  433. "weight" => 999,
  434. );
  435. return $form;
  436. }
  437. /**
  438. * Validate handler for add_degree_form
  439. */
  440. function admin_add_degree_form_validate($form, $form_submit) {
  441. $values = $form_submit["values"];
  442. // Make sure neither major code nor track code contains any spaces.
  443. $de_catalog_year = $values["de_catalog_year"];
  444. $major_code = trim(strtoupper($values["major_code"]));
  445. $track_code = trim(strtoupper($values["track_code"]));
  446. $school_id = intval($values["school_id"]);
  447. $new_major = $values["new_major"];
  448. $new_track = $values["new_track"];
  449. if ($major_code != "" && admin_string_contains_illegal_chars($major_code)) {
  450. form_error("major_code", t("The major code may not contain spaces or symbols. Please enter a new one containing only letters, numbers, and -."));
  451. }
  452. if ($track_code != "" && admin_string_contains_illegal_chars($track_code)) {
  453. form_error("track_code", t("The track code may not contain spaces or symbols. Please enter a new one containing only letters, numbers, and -."));
  454. }
  455. // Make sure the major + |_ + track_code doesn't exceed 20 characters.
  456. if (strlen("$major_code|_$track_code") > 20) {
  457. form_error("major_code", t("The major and track code combined may not exceed 18 characters. Please shorten one or the other."));
  458. }
  459. if ($new_track == "new" && $track_code == "") {
  460. form_error("track_code", t("You selected to add a track, but did not specify a track code."));
  461. }
  462. $for_school = $school_name = "";
  463. if (module_enabled("schools")) {
  464. $for_school = " for school %school";
  465. $school_name = schools_get_school_name_for_id($school_id);
  466. }
  467. // Check to see if it already exists...
  468. $res = db_query("SELECT * FROM draft_degrees
  469. WHERE catalog_year = ?
  470. AND major_code = ?
  471. AND school_id = ?", $de_catalog_year, $major_code, $school_id);
  472. if (db_num_rows($res) > 0 && $new_major == "new") {
  473. // Meaning, it already exists, yet we are trying to add it as a new
  474. // major. This is an error!
  475. form_error('major_code', t("The major code %major_code already exists for %year$for_school. You cannot add it as a new major.", array("%major_code" => $major_code, "%year" => $de_catalog_year, "%school" => $school_name)));
  476. }
  477. if (db_num_rows($res) == 0 && $new_major == "existing") {
  478. // This is another error. We are trying to add a track to an existing
  479. // major code, but none was found.
  480. form_error('major_code', t("The major code %major_code could not be found in the system for %year$for_school. Perhaps you need to add it first?", array("%major_code" => $major_code, "%year" => $de_catalog_year, "%school" => $school_name)));
  481. return;
  482. }
  483. }
  484. /**
  485. * Submit handler for the add_degree_form.
  486. */
  487. function admin_add_degree_form_submit($form, $form_submit) {
  488. $values = $form_submit["values"];
  489. $degree_id = -1;
  490. $de_catalog_year = $values["de_catalog_year"];
  491. // This will be used to add a new degree (and possibly track)
  492. // to the database.
  493. $major_code = trim(strtoupper($values["major_code"]));
  494. $track_code = trim(strtoupper($values["track_code"]));
  495. $school_id = intval($values["school_id"]);
  496. $new_major = $values["new_major"];
  497. $new_track = $values["new_track"];
  498. $allow_dynamic = variable_get("admin_degrees_default_allow_dynamic", "1");
  499. $for_school = $school_name = "";
  500. if (module_enabled("schools")) {
  501. $for_school = " for school %school";
  502. $school_name = schools_get_school_name_for_id($school_id);
  503. }
  504. // First, deal with the major/concentration.
  505. if ($new_major == "new") {
  506. // This means we are trying to add a new major to the degrees table.
  507. // We may proceed with this.
  508. $db2 = new DatabaseHandler();
  509. $degree_id = $db2->request_new_degree_id();
  510. $db2->db_query("INSERT INTO draft_degrees
  511. (degree_id, major_code, catalog_year, allow_dynamic, title, school_id)
  512. values (?, ?, ?, ?, ?, ?) ", $degree_id, $major_code, $de_catalog_year, $allow_dynamic, $major_code, $school_id);
  513. }
  514. if ($new_track == "new") {
  515. //////////////////////////////////////////////////
  516. // Now, let's see about adding ourself a track...
  517. // First, check to see if it exists...
  518. $res = db_query("SELECT * FROM draft_degree_tracks
  519. WHERE catalog_year = ?
  520. AND major_code = ?
  521. AND track_code = ? ", $de_catalog_year, $major_code, $track_code);
  522. if (db_num_rows($res) > 0) {
  523. // Meaning, it already existed, so we can't create it.
  524. fp_add_message(t("The major and track code %major_code already exists for %year. You cannot add it as a new major/track code.", array("%major_code" => "$major_code $track_code", "%year" => $de_catalog_year)), "error");
  525. return;
  526. }
  527. else {
  528. // We can add it to the tracks table...
  529. $db2 = new DatabaseHandler();
  530. $db2->db_query("INSERT INTO draft_degree_tracks
  531. (catalog_year, major_code, track_code)
  532. values ('?', '?', '?') ", $de_catalog_year, $major_code, $track_code);
  533. // Now, we also need to add this major & track code to the degrees table.
  534. $new_major_code = $major_code;
  535. if (strstr($major_code, "|")) {
  536. // Already has a pipe, so it has a concentration.
  537. $new_major_code .= "_$track_code";
  538. }
  539. else {
  540. // No concentration...
  541. $new_major_code .= "|_$track_code";
  542. }
  543. $degree_id = $db2->request_new_degree_id();
  544. $db2->db_query("INSERT INTO draft_degrees
  545. (degree_id, major_code, catalog_year, allow_dynamic, title, school_id)
  546. values (?, ?, ?, ?, ?, ?) ", $degree_id, $new_major_code, $de_catalog_year, $allow_dynamic, $new_major_code, $school_id);
  547. }
  548. }
  549. // Let's add some default semester blocks for this degree (0 - 3).
  550. if ($degree_id > 0) {
  551. for ($t = 0; $t <= 3; $t++) {
  552. db_query("INSERT INTO draft_degree_requirements
  553. (degree_id, semester_num, course_id, course_min_grade, course_requirement_type, data_entry_value)
  554. values (?,?,?,?,?,?) ", $degree_id, $t, 0, '', '', "#");
  555. }
  556. }
  557. watchdog("admin", "Degree $major_code $track_code,school id: $school_id, ($de_catalog_year) has been created successfully. Degree id = $degree_id");
  558. // Success! We are done.
  559. fp_add_message(t("The new degree %major_code was added successfully for %year$for_school.
  560. You may add another degree, or use the menu at the top of the page to return to your list
  561. of degrees, so you may begin editing the degree.", array("%major_code" => "$major_code $track_code", "%year" => $de_catalog_year, "%school" => $school_name)));
  562. clear_session_form_values("admin_add_degree_form");
  563. }
  564. /*
  565. * This function lists all of our degrees on the screen, for a given year
  566. */
  567. function admin_display_degrees() {
  568. // Do this using $render array, so it can be altered
  569. // by hook_content_alter
  570. $render = array();
  571. $render['#id'] = 'admin_display_degrees';
  572. $de_catalog_year = admin_get_de_catalog_year();
  573. $rtn = "";
  574. fp_add_css(fp_get_module_path("admin") . "/css/admin.css");
  575. fp_set_title(t("Degrees for @year", array("@year" => $de_catalog_year)));
  576. $render['upper_links'] = array(
  577. 'value' => "<div class='admin-degrees-upper-links'>
  578. " . l("Add new degree plan (major, degree plan, or track)", "admin/degrees/add-degree", "de_catalog_year=$de_catalog_year") . "
  579. &nbsp; &nbsp; | &nbsp; &nbsp;
  580. " . l("Copy a degree plan", "admin/degrees/copy-degree", "de_catalog_year=$de_catalog_year") . "</div>",
  581. );
  582. $html = "";
  583. $html .= "<div class='degrees-filter'>";
  584. $html .= fp_render_form("admin_degrees_list_filter_form");
  585. $html .= "</div>";
  586. $render['degrees_filter'] = array(
  587. 'value' => $html,
  588. );
  589. $render['degrees_table_top'] = array(
  590. 'value' => "<table class='degrees-table' border='0' width='100%' cellpadding='5' cellspacing='0'>
  591. <tr>
  592. <th width='8%'>Type</th>
  593. <th width='8%'>Level</th>
  594. <th width='15%'>Class</th>
  595. <th width='60%'>Title</th>
  596. <th>Code</th>
  597. </tr>",
  598. );
  599. $params = array();
  600. $params[":catalog_year"] = $de_catalog_year;
  601. $filter_class_value = @$_SESSION['degrees_filter_class'];
  602. $filter_level_value = @$_SESSION['degrees_filter_level'];
  603. $filter_school_value = @intval($_SESSION['degrees_filter_school']);
  604. $extra_where_conditions = "";
  605. watchdog("admin", "Viewed admin degree list. Class option: $filter_class_value ($de_catalog_year), School id: $filter_school_value", array(), WATCHDOG_DEBUG);
  606. // Let's adjust the query based on filter selections (if any exist)
  607. if ($filter_class_value) {
  608. $extra_where_conditions .= " AND degree_class = :degree_class ";
  609. $params[":degree_class"] = $filter_class_value;
  610. }
  611. if ($filter_level_value) {
  612. $extra_where_conditions .= " AND degree_level = :degree_level ";
  613. $params[":degree_level"] = $filter_level_value;
  614. }
  615. if (module_enabled('schools')) {
  616. if ($filter_school_value) {
  617. $extra_where_conditions .= " AND school_id = :school_id ";
  618. $params[":school_id"] = $filter_school_value;
  619. }
  620. }
  621. else {
  622. // schools not enabled, so only search for school = 0
  623. $extra_where_conditions .= " AND school_id = 0 ";
  624. }
  625. $res = db_query("SELECT * FROM draft_degrees
  626. WHERE catalog_year = :catalog_year
  627. $extra_where_conditions
  628. ORDER BY degree_type, major_code, title ", $params);
  629. while($cur = db_fetch_array($res)) {
  630. $db_exclude = 0;
  631. extract($cur, 3, "db");
  632. $disp_level = strtoupper($db_degree_level);
  633. if ($db_degree_type == "NA" && strstr($db_major_code, "|")) {
  634. $db_degree_type = " -- ";
  635. }
  636. $extra_class = "";
  637. if ($db_exclude == "1") {
  638. $extra_class = "list-degree-row-excluded";
  639. }
  640. $degree_title = $db_title;
  641. // get JUST the major code...
  642. $temp = explode("|", $db_major_code);
  643. $just_major = trim(@$temp[0]);
  644. $just_conc = trim(@$temp[1]);
  645. $outside = "";
  646. //if ($just_conc != "" && strstr($just_conc, "_"))
  647. if (strstr($just_conc, "_")) {
  648. // If the concentration has an underscore, it's actually
  649. // a track. Let's get the track title...
  650. $temp2 = explode("_",$just_conc);
  651. $just_track = trim($temp2[1]);
  652. // Might need to add the first part BACK onto the major...
  653. if (trim($temp2[0]) != "")
  654. {
  655. $just_major .= "|" . trim($temp2[0]);
  656. }
  657. $res2 = db_query("SELECT * FROM draft_degree_tracks
  658. WHERE catalog_year = ?
  659. AND major_code = ?
  660. AND track_code = ?
  661. AND school_id = ? ", $de_catalog_year, $just_major, $just_track, $db_school_id);
  662. if (db_num_rows($res2) > 0) {
  663. $cur2 = db_fetch_array($res2);
  664. $db_title = trim($cur2["track_title"]);
  665. $outside = "$degree_title &raquo; ";
  666. if (strstr($just_major, "|")) {
  667. // both a conc AND a track. Denote it special.
  668. $outside = ">>" . $outside;
  669. }
  670. $db_degree_type = "";
  671. }
  672. }
  673. else if($just_conc != "") {
  674. // Meaning, this is a concentration, NOT a track.
  675. $db_degree_type = "";
  676. $outside = "&gt;&gt;";
  677. }
  678. $url = fp_url("admin/degrees/edit-degree/$db_degree_id/$de_catalog_year", "de_catalog_year=$de_catalog_year", array("class" => "degree-$db_degree_class"));
  679. $class_details = fp_get_degree_classification_details($db_degree_class);
  680. $disp_class = $class_details["title"];
  681. $on_mouse_over = "
  682. onmouseover='$(this).addClass(\"selection_highlight\");'
  683. onmouseout='$(this).removeClass(\"selection_highlight\");'
  684. ";
  685. $render['degree_row_' . $db_degree_id] = array(
  686. 'value' => "<tr
  687. $on_mouse_over
  688. style='cursor:pointer;'
  689. onClick='window.location=\"$url\"'
  690. class='$extra_class class-$db_degree_class class-level-" . $class_details["level_num"] . " '
  691. >
  692. <td valign='top' class='degree-type'>$db_degree_type</td>
  693. <td valign='top' class='degreee-level'>$disp_level</td>
  694. <td valign='top' class='degreee-class'>$disp_class</td>
  695. <td valign='top' class='degree-title'>$outside$db_title</td>
  696. <td valign='top' class='degree-major-code'>$db_major_code</td>
  697. </tr>
  698. ",
  699. 'data' => array(
  700. 'degree_id' => $db_degree_id,
  701. 'major_code' => $db_major_code,
  702. 'title' => $db_title,
  703. 'catalog_year' => $db_catalog_year,
  704. 'degree_type' => $db_degree_type,
  705. 'degree_class' => $db_degree_class,
  706. 'db_row' => $cur,
  707. ),
  708. );
  709. }
  710. //$rtn .= "</table>";
  711. $render['degrees_table_bottom'] = array(
  712. 'value' => "</table>",
  713. );
  714. $rtn .= fp_render_content($render);
  715. return $rtn;
  716. }
  717. function admin_degrees_list_filter_form() {
  718. $form = array();
  719. $form['mark_top'] = array(
  720. 'type' => 'markup',
  721. 'value' => "<strong>" . t('Filter by...') . "</strong>",
  722. 'weight' => 0,
  723. );
  724. $filter_class_options = array('' => t("- All -"));
  725. $degree_classes = fp_get_degree_classifications();
  726. foreach ($degree_classes["levels"] as $level => $details) {
  727. foreach ($degree_classes["levels"][$level] as $machine_name => $title) {
  728. $filter_class_options[$machine_name] = "$level - $title";
  729. }
  730. }
  731. $filter_class_value = @$_SESSION['degrees_filter_class'];
  732. $form['filter_class'] = array(
  733. 'type' => 'select',
  734. 'label' => t('Class:'),
  735. 'options' => $filter_class_options,
  736. 'value' => $filter_class_value,
  737. 'hide_please_select' => TRUE,
  738. 'weight' => 10,
  739. );
  740. $filter_level_options = array('' => t("- All -"), "UG" => t("Under Grad"), "GR" => t("Grad"));
  741. $filter_level_value = @$_SESSION['degrees_filter_level'];
  742. $form['filter_level'] = array(
  743. 'type' => 'select',
  744. 'label' => t('Level:'),
  745. 'options' => $filter_level_options,
  746. 'value' => $filter_level_value,
  747. 'hide_please_select' => TRUE,
  748. 'weight' => 15,
  749. );
  750. $filter_school_value = 0;
  751. // If we have enabled the schools module, then have a selector for that as well
  752. if (module_enabled('schools')) {
  753. $filter_school_value = @intval($_SESSION['degrees_filter_school']);
  754. $options = schools_get_schools_for_fapi(TRUE, TRUE, 'degree', TRUE);
  755. $options[0] = t('- All / Default -');
  756. $form['filter_school'] = array(
  757. 'type' => 'select',
  758. 'label' => t('School:'),
  759. 'options' => $options,
  760. 'value' => $filter_school_value,
  761. 'weight' => 20,
  762. 'hide_please_select' => TRUE,
  763. );
  764. } // if schools enabled
  765. $form['submit_btn'] = array(
  766. 'type' => 'submit',
  767. 'value' => t('Apply'),
  768. 'weight' => 100,
  769. );
  770. $form['reset_btn'] = array(
  771. 'type' => 'submit',
  772. 'value' => t('Reset'),
  773. 'weight' => 110,
  774. );
  775. return $form;
  776. }
  777. function admin_degrees_list_filter_form_submit($form, $form_state) {
  778. $values = $form_state['values'];
  779. unset($_SESSION['degrees_filter_class']);
  780. unset($_SESSION['degrees_filter_school']);
  781. unset($_SESSION['degrees_filter_level']);
  782. if ($values['submit_btn'] != '') {
  783. $_SESSION['degrees_filter_class'] = trim($values['filter_class']);
  784. $_SESSION['degrees_filter_school'] = $values['filter_school'];
  785. $_SESSION['degrees_filter_level'] = $values['filter_level'];
  786. }
  787. }
  788. /**
  789. * Meant to replace the old-fashioned display_edit_degree function...
  790. */
  791. function admin_edit_degree_form($degree_id, $de_catalog_year) {
  792. $form = array();
  793. $degree = new DegreePlan($degree_id, null, false, false, true);
  794. $degree->load_descriptive_data();
  795. $major_code = $degree->major_code;
  796. fp_set_title(t("Edit Degree") . " $major_code - $de_catalog_year");
  797. // Add in our CSS and JS
  798. fp_add_js(fp_get_module_path("admin") . "/js/admin.js");
  799. fp_add_css(fp_get_module_path("admin") . "/css/admin.css");
  800. $button_msg = trim(addslashes(@$_REQUEST["button_msg"]));
  801. $db = get_global_database_handler();
  802. if (user_has_permission("can_view_advanced")) {
  803. $form["markup_adv"] = array(
  804. "value" => "<span class='tenpt deg-advanced-msg' style='background-color: yellow; margin-left: 20px;'>
  805. Advanced: degree_id = $degree_id. catalog_year: $de_catalog_year
  806. </span>",
  807. );
  808. }
  809. $form["degree_id"] = array(
  810. "type" => "hidden",
  811. "value" => $degree_id,
  812. );
  813. $form["major_code"] = array(
  814. "type" => "hidden",
  815. "value" => $major_code,
  816. );
  817. $form["de_catalog_year"] = array(
  818. "type" => "hidden",
  819. "value" => $de_catalog_year,
  820. );
  821. $form["scroll_top"] = array(
  822. "type" => "hidden",
  823. "value" => '',
  824. );
  825. $form["perform_action2"] = array(
  826. "type" => "hidden",
  827. "value" => '',
  828. );
  829. $form["markup_degree_header"] = array(
  830. "value" => "<h3>$degree->degree_type $degree->title<br>$major_code ($de_catalog_year)</h3>",
  831. "weight" => 1010,
  832. );
  833. //////////////////////////////////////////////////////
  834. // Top part of degree entry....
  835. $form["degree_type"] = array(
  836. "type" => "textfield",
  837. "label" => t("Degree Type:"),
  838. "size" => 3,
  839. "value" => $degree->degree_type,
  840. "popup_description" => t("For example: BS, BA, Ph.D, etc."),
  841. "weight" => 1020,
  842. );
  843. // Display degree_class pulldown.
  844. $options = array();
  845. $degree_classes = fp_get_degree_classifications();
  846. foreach ($degree_classes["levels"] as $level => $details) {
  847. foreach ($degree_classes["levels"][$level] as $machine_name => $title) {
  848. //$rtn .= "<option value='$machine_name' $sel>$level - $title</option>";
  849. $options[$machine_name] = "$level - $title";
  850. }
  851. }
  852. $form["degree_class"] = array(
  853. "type" => "select",
  854. "label" => t("Classification:"),
  855. "options" => $options,
  856. "value" => $degree->degree_class,
  857. "hide_please_select" => TRUE,
  858. "popup_description" => t("Select which classification this degree plan is listed under. The number beside the title is the 'level' of the degree classification.
  859. <br>
  860. <br>1 - Degrees which a student may graduate in. Ex: Majors.
  861. <br>2 - Degree plans which are secondary to top level degree plans. Ex: Minors.
  862. <br>3 - Degree plans which are only selectable as add-ons to an existing degree plan. Ex: Concentrations.
  863. <br><br>
  864. You may edit these classifications in the Configure School Data form, from the Admin Console."),
  865. "weight" => 1030,
  866. );
  867. $form["degree_level"] = array(
  868. "type" => "select",
  869. "label" => t("Level:"),
  870. "size" => 1,
  871. "options" => array('UG' => 'UG - Under Grad', 'GR' => 'GR - Grad'),
  872. "value" => $degree->degree_level,
  873. "hide_please_select" => TRUE,
  874. "popup_description" => t("Select the degree level code in this box. By default, it is assumed to be an \"Undergraduate\" (UG) degree.
  875. Select \"GR\" for a degree which should only be accessible to Graduate students in What If mode.
  876. "),
  877. "weight" => 1040,
  878. );
  879. $form["advising_weight"] = array(
  880. "type" => "textfield",
  881. "label" => t("Advising Weight:"),
  882. "size" => 1,
  883. "value" => $degree->db_advising_weight,
  884. "popup_description" => t("If this degree is ever combined with another degree, this value, the advising weight, determines
  885. the order in which the degrees will be displayed on the View tab and in What If mode.
  886. <br><br>
  887. The default is zero (0). To place this degree above normal degrees, set it to a negative value (ex: -1, -10, etc.).
  888. <br><br>
  889. Set it higher to place it below normal degrees. (Ex: 10, 20, 30, etc).
  890. <br><br>
  891. To prevent confusion, it's recommended that a degree's tracks have the same advising weight as the main degree.
  892. <br><br>
  893. If you are unsure what to enter, leave it set to 0 (zero)."),
  894. "weight" => 1050,
  895. );
  896. $form["title"] = array(
  897. "type" => "textfield",
  898. "label" => t("Title:"),
  899. "size" => 80,
  900. "maxlength" => 100,
  901. "value" => $degree->title,
  902. "popup_description" => t("This is the full title of the degree. Ex: Computer Science, Accounting, etc."),
  903. "weight" => 1060,
  904. );
  905. $form["exclude"] = array(
  906. "type" => "textfield",
  907. "label" => t("Exclude:"),
  908. "size" => 1,
  909. "value" => intval($degree->db_exclude),
  910. "popup_description" => t("If the Exclude value is set to 1 (the number one), then this degree will show up in gray on the list of degrees. It will also not be selectable in What If mode in FlightPath.
  911. <br><br>
  912. If you are not sure what to enter, either leave it blank or enter a 0 (zero)."),
  913. "weight" => 1070,
  914. );
  915. $form["allow_dynamic"] = array(
  916. "type" => "textfield",
  917. "label" => t("Allow Dynamic:"),
  918. "size" => 1,
  919. "value" => intval($degree->db_allow_dynamic),
  920. "popup_description" => t("If this value is set to 1 (the number one), then this degree plan is able to be combined with other degrees which are also set to Allow Dynamic.
  921. <br><br>
  922. If you are unsure what to enter, either leave blank or enter a 0 (the number zero)."),
  923. "weight" => 1080,
  924. );
  925. $form["override_degree_hours"] = array(
  926. "type" => "textfield",
  927. "label" => t("Override Degree Hours:"),
  928. "size" => 1,
  929. "value" => $degree->db_override_degree_hours,
  930. "popup_description" => t("You may specify a number of degree hours here (ex: 125). FlightPath will use this value, instead of calculating the number of hours
  931. required for this degree. If you are unsure what to put here, leave it blank, or enter zero, for FlightPath to calculate hours normally."),
  932. "weight" => 1090,
  933. );
  934. $form['below_degree_details_markup'] = array(
  935. 'value' => "<div style='clear: both;'></div>",
  936. "weight" => 1110,
  937. );
  938. // Is this a "track"?
  939. if (strstr($major_code, "_"))
  940. {
  941. $form['track_info_markup'] = array(
  942. 'value' => "<h3>" . t("Track (Level-3) Information") . "</h3>",
  943. "weight" => 1120,
  944. );
  945. $form['track_title'] = array(
  946. 'type' => 'textfield',
  947. 'label' => t("Track (Level-3) Title:") . "&nbsp;",
  948. 'size' => 60,
  949. 'maxlength' => 100,
  950. 'value' => $degree->track_title,
  951. "weight" => 1130,
  952. );
  953. $form['track_description'] = array(
  954. 'type' => 'textarea',
  955. 'label' => t("Track (Level-3) Description:"),
  956. 'rows' => 4,
  957. 'cols' => 60,
  958. 'value' => $degree->track_description,
  959. 'description' => t("You may enter simple HTML in this field. Ex: &lt;b&gt;bold&lt;/b&gt; or &lt;i&gt;italics&lt;/i&gt;"),
  960. 'popup_description' => t("This is where you can enter a short description of this Level-3 degree track (also called a Degree Option) which will display for the user in a pop-up when they select to change degree options.
  961. <br><br>
  962. To enter a default message, which will display at the top of the selection window, begin the description with:
  963. <br><b>DEFAULT:</b>
  964. (It must be in all caps, and you must have the colon (:) after it.)
  965. <br>By doing this in ANY of the track descriptions for a major, FP will ignore all other track descriptions and ONLY display the default.
  966. <br><br>Example of usage: DEFAULT: You may select any of these degree options."),
  967. "weight" => 1140,
  968. );
  969. }
  970. ///////////////////////////////////////
  971. ///////////////////////////////////////
  972. // Semester Blocks //
  973. //////////////////////////////////////
  974. ///////////////////////////////////////
  975. $groups_counter = 0; // used to create unique variables for groups
  976. $js_existing_semesters = array();
  977. $degree_sort_policy = variable_get_for_school("degree_requirement_sort_policy", "alpha", $degree->school_id);
  978. $form['blocks_top_markup'] = array(
  979. 'type' => 'markup',
  980. 'value' => "<div style='clear: both;'></div>
  981. <hr>
  982. <div class='add-new-sem-block' style='float: right; margin-top: 5px;'>" . fp_render_button(t("Add New Semester Block"), "adminAddNewSemesterBlock();") . "</div>
  983. <h2>Semester Blocks</h2>
  984. ",
  985. "weight" => 2010,
  986. );
  987. $base_weight = 30000;
  988. $first_semester_num = -999;
  989. $degree->list_semesters->reset_counter();
  990. while ($degree->list_semesters->has_more()) {
  991. $semester = $degree->list_semesters->get_next();
  992. if ($semester->semester_num < 0) {
  993. continue;
  994. }
  995. $js_existing_semesters["semester_" . $semester->semester_num] = $semester->semester_num;
  996. // Record what is the first semester num we have...
  997. if ($first_semester_num == -999) {
  998. $first_semester_num = $semester->semester_num;
  999. }
  1000. $sem_default_title = admin_get_semester_name($semester->semester_num);
  1001. if ($semester->title == $sem_default_title) {
  1002. $semester->title = "";
  1003. }
  1004. $form["semester_{$semester->semester_num}_very_top_markup"] = array(
  1005. "value" => "",
  1006. "weight" => $base_weight + ($semester->semester_num * 100) + 10,
  1007. );
  1008. $form['semester_title_' . $semester->semester_num] = array(
  1009. 'type' => 'textfield',
  1010. 'prefix' => "<div style='padding-bottom: 3px; margin-top:20px;'><b>" . t("Block number: ") . ($semester->semester_num + 1) . "</b>
  1011. <a href='javascript:adminEditBlockNumber($semester->semester_num);' title='" . t("Edit block number") . "'><i class='fa fa-pencil'></i></a>
  1012. &nbsp; &nbsp;
  1013. <a href='javascript:adminDeleteSemesterBlock($semester->semester_num);'>Delete?</a>
  1014. &nbsp; &nbsp; &nbsp; Default Title: <em>$sem_default_title</em></div>",
  1015. 'label' => 'Override Title:',
  1016. 'value' => $semester->title,
  1017. 'size' => 20,
  1018. 'popup_description' => t("You may override the default title for a block. For example, if instead of Freshman Year you want it to read Pre-Pharmacy Year 1 in FlightPath,
  1019. then you would enter that in this box and hit save.
  1020. <br><br>
  1021. To change a title back to the default, just leave it blank."),
  1022. "weight" => $base_weight + ($semester->semester_num * 100) + 20,
  1023. );
  1024. // Show the courses for this semester...
  1025. $contents = "";
  1026. if ($degree_sort_policy == 'database') {
  1027. $semester->list_courses->sort_degree_requirement_id();
  1028. }
  1029. else {
  1030. // Default, sort alphabetically
  1031. $semester->list_courses->sort_alphabetical_order();
  1032. }
  1033. $semester->list_courses->reset_counter();
  1034. while($semester->list_courses->has_more()) {
  1035. $course = $semester->list_courses->get_next();
  1036. $course->load_descriptive_data();
  1037. $contents .= "$course->subject_id $course->course_num $course->requirement_type";
  1038. if ($course->min_grade != "D" && $course->min_grade != "") {
  1039. $contents .= " ($course->min_grade)";
  1040. }
  1041. $contents .= "\n";
  1042. }
  1043. $form["semester_{$semester->semester_num}_top_table_markup"] = array(
  1044. "value" => "<div class='edit-degree-semester-block'>
  1045. <table border='1' width='100%' class='edit-degree-semester-block-table'>
  1046. <td valign='top' width='30%'>",
  1047. "weight" => $base_weight + ($semester->semester_num * 100) + 30,
  1048. );
  1049. $form['courses_' . $semester->semester_num] = array(
  1050. 'type' => 'textarea',
  1051. 'prefix' => "",
  1052. 'label' => 'Courses: ',
  1053. 'value' => $contents,
  1054. 'rows' => 10,
  1055. 'cols' => 20,
  1056. 'popup_description' => t("Enter course requirements in this format:
  1057. <br><br> &nbsp; &nbsp; SUBJECT COURSENUM type (MINGRADE)
  1058. <br><br>&bull; type - lowercase character denoting the requirement type of the course. Make sure you have a space between it and the course number. If no type is specified, it is understood to be a major requirement.\n
  1059. <br>&bull; min grade - Place the min grade (if there is one) in parenthesis after the type. Make sure there is a space between the min grade and the type (or course number, if there is no type specified).\n Example: ACCT 110 s (C)\n\n
  1060. <br><br>Repeats require no special characters or symbols. Simply enter the course again."),
  1061. 'suffix' => "",
  1062. "weight" => $base_weight + ($semester->semester_num * 100) + 40,
  1063. );
  1064. // Show the groups (and option for adding groups) for this semester...
  1065. $contents = "";
  1066. $contents .= "</td>
  1067. <td valign='top'>
  1068. <label>" . t("Groups:") . "</label>
  1069. <table width='100%' border='0' cellspacing='5' class='edit-degree-semester-groups-table'>
  1070. <tr>
  1071. <th valign='top' class='tenpt' width='1'>&nbsp;</td>
  1072. <th valign='top' class='tenpt'>" . t("Group") . "</td>
  1073. <th valign='top' class='tenpt' width='10'>" . t("Hrs") . "</td>
  1074. <th valign='top' class='tenpt' width='10'>" . t("Grd") . "</td>
  1075. <th valign='top' class='tenpt' width='10'>" . t("Type") . "</td>
  1076. </tr>
  1077. ";
  1078. $semester->list_groups->sort_alphabetical_order();
  1079. $semester->list_groups->reset_counter();
  1080. while($semester->list_groups->has_more()) {
  1081. $group = $semester->list_groups->get_next();
  1082. $group->load_descriptive_data();
  1083. $ghours = $group->hours_required;
  1084. // If min hours are specified, set to MIN-MAX.
  1085. if ($group->has_min_hours_allowed()) {
  1086. $ghours = $group->min_hours_allowed . "-" . $ghours;
  1087. }
  1088. $contents .= "<tr>
  1089. <td valign='middle'>
  1090. <a href='javascript: adminDelGroup(\"" . $group->get_db_group_id() . "\",\"$semester->semester_num\");' class='delgroup-icon' title='" . t("Remove group?") . "'><i class='fa fa-times-circle'></i></a>
  1091. </td>
  1092. <td valign='top' class='tenpt'>
  1093. $group->title<br><i>$group->group_name</i>
  1094. </td>
  1095. <td valign='top' class='tenpt'>$ghours</td>
  1096. <td valign='top' class='tenpt'>$group->min_grade</td>
  1097. <td valign='top' class='tenpt'>$group->requirement_type
  1098. </td>
  1099. </tr>";
  1100. // Let's also add a hidden form element here, for the existing group.
  1101. $groups_counter++;
  1102. $form['group_' . $group->get_db_group_id() . '_' . $groups_counter] = array(
  1103. 'type' => 'hidden',
  1104. 'value' => $group->get_db_group_id() . "_" . $semester->semester_num . "_" . $ghours . "_" . $group->requirement_type . "_" . $group->min_grade,
  1105. );
  1106. } // while semester->list_groups
  1107. $url = fp_url("admin/degrees/popup-add-group2", "semester_num=$semester->semester_num&de_catalog_year=$de_catalog_year&school_id=$degree->school_id");
  1108. $contents .= "</table>
  1109. <div style='margin-top: 10px; margin-left: 20px; font-size:0.8em;'>
  1110. <a href='javascript: adminPopupWindow(\"$url\");'>" . t("Add an elective group") . "</a>
  1111. </div>";
  1112. // Display our contents in a markup element for this semester
  1113. $form["semester_groups_" . $semester->semester_num . "_markup"] = array(
  1114. 'value' => $contents,
  1115. "weight" => $base_weight + ($semester->semester_num * 100) + 50,
  1116. 'attributes' => array('class' => 'groups-inner'),
  1117. );
  1118. $form["semester_{$semester->semester_num}_table_bottom_markup"] = array(
  1119. "value" => "</table>
  1120. </div> <!-- semester block -->",
  1121. "weight" => $base_weight + ($semester->semester_num * 100) + 60,
  1122. );
  1123. $form["semester_{$semester->semester_num}_below_table_markup"] = array(
  1124. "value" => "",
  1125. "weight" => $base_weight + ($semester->semester_num * 100) + 70,
  1126. );
  1127. $form["semester_{$semester->semester_num}_save_draft_markup"] = array(
  1128. "value" => fp_render_button(t("Save Draft for @year", array("@year" => $de_catalog_year)), "adminSubmitDegreeForm2();"),
  1129. "weight" => $base_weight + ($semester->semester_num * 100) + 80,
  1130. );
  1131. } // while degree->list_semesters
  1132. // Add our js_existing_semesters array to the javascript on this page, so we can check it later.
  1133. fp_add_js($js_existing_semesters, "setting");
  1134. ////////////////////////////////////////////////////////////
  1135. ////////////////////////////////////////////////////////////
  1136. ////////////////////////////////////////////////////////////
  1137. ////////////////////////////////////////////////////////////
  1138. $bool_start_closed = TRUE;
  1139. if (@$degree->public_notes_array[$degree->degree_id] != "") {
  1140. $bool_start_closed = FALSE;
  1141. }
  1142. // Advanced options
  1143. $elements = array();
  1144. $elements['public_note'] = array(
  1145. 'type' => 'textarea',
  1146. 'label' => t('Public Note'),
  1147. 'rows' => 4,
  1148. 'value' => @$degree->public_notes_array[$degree->degree_id],
  1149. 'description' => t("You may enter simple HTML in this field. Ex: &lt;b&gt;bold&lt;/b&gt; or &lt;i&gt;italics&lt;/i&gt;"),
  1150. 'popup_description' => t("A public note will appear at the top of a degree plan when pulled up in FlightPath.
  1151. Use this to pass messages to all students and advisors who pull up this degree plan.
  1152. <br><br>It will begin with the text <b>Important Message:</b> automatically."),
  1153. "weight" => 50010,
  1154. );
  1155. // min/max/default tracks
  1156. $elements['adv_if_tracks_markup'] = array(
  1157. 'type' => 'markup',
  1158. 'value' => t('If this degree has tracks, you may enter rules for track selection below, for each
  1159. type of level 3 degree (tracks). <b>You may skip classifications which do not pertain to this degree.</b>'),
  1160. "weight" => 50020,
  1161. );
  1162. $c = 10;
  1163. $degree_classes = fp_get_degree_classifications();
  1164. foreach ($degree_classes["levels"] as $level => $details) {
  1165. $c = $c + 10;
  1166. if (intval($level) != 3) continue; // we only care about level 3...
  1167. foreach ($degree_classes["levels"][$level] as $machine_name => $title) {
  1168. $min_tracks = @intval($degree->track_selection_config_array[$machine_name]["min_tracks"]);
  1169. $max_tracks = @intval($degree->track_selection_config_array[$machine_name]["max_tracks"]);
  1170. $default_tracks = @trim($degree->track_selection_config_array[$machine_name]["default_tracks"]);
  1171. if ($min_tracks > 0 || $max_tracks > 0 || $default_tracks != "") {
  1172. $bool_start_closed = FALSE;
  1173. }
  1174. $elements["tsc_{$machine_name}_min_tracks"] = array(
  1175. 'type' => 'textfield',
  1176. 'label' => t('Min:'),
  1177. 'size' => 2,
  1178. 'value' => $min_tracks,
  1179. 'prefix' => "<table width='100%' class='admin-degrees-edit-track-rules-table'>
  1180. <tr class='admin-degrees-edit-track-selection-config track-selection-config-$machine_name'>
  1181. <td valign='top' width='30%'>
  1182. <span class='track-selection-config-title'>$title</span>:
  1183. </td>
  1184. <td valign='top'>",
  1185. 'suffix' => "</td>",
  1186. 'popup_description' => t("This is the minimum number of tracks THIS degree must select. For example, if the degree requires at least one track, enter a 1 (one) in this box.
  1187. <br><br>The default is zero (0), which means that no track is required for this degree. The user is not required to select any at all.
  1188. <br><br>If you are unsure what to enter, leave it set to 0 (zero)."),
  1189. "weight" => 60000 + $c + 1,
  1190. );
  1191. $elements["tsc_{$machine_name}_max_tracks"] = array(
  1192. 'type' => 'textfield',
  1193. 'label' => t('Max:'),
  1194. 'size' => 2,
  1195. 'value' => $max_tracks,
  1196. 'prefix' => "<td valign='top'>",
  1197. 'suffix' => "</td>",
  1198. 'popup_description' => t("This is the maximum number of tracks THIS degree may select. For example, if the degree requires the student to have NO MORE than 1 track selected, you would enter 1 (one) in this box.
  1199. <br><br>The default is zero (0), which means that there is no maximum; the user may select as many of this degree's tracks as they wish.
  1200. <br><br>If you are unsure what to enter, leave it set to 0 (zero)."),
  1201. "weight" => 60000 + $c + 5,
  1202. );
  1203. $elements["tsc_{$machine_name}_default_tracks"] = array(
  1204. 'type' => 'textfield',
  1205. 'label' => t('Default Tracks:'),
  1206. 'size' => 25,
  1207. 'value' => $default_tracks,
  1208. 'prefix' => "<td valign='top'>",
  1209. 'suffix' => "</td>
  1210. </tr>
  1211. </table>",
  1212. 'popup_description' => t("If THIS degree has one or more 'default' tracks associated with it (ex: for What If mode), enter the FULL major codes here, separated by comma.
  1213. <br><br>For example: ART|_SCULP, ART|_PAINT
  1214. <br><br>If you are unsure what to enter, leave it blank."),
  1215. "weight" => 60000 + $c + 7,
  1216. );
  1217. } // foreach levels[$level]
  1218. } // foreach levels as level => details
  1219. // Place in our advanced options fs.
  1220. $form['advanced_options_fs'] = array(
  1221. 'type' => 'cfieldset',
  1222. 'label' => t('View advanced options'),
  1223. 'elements' => array($elements),
  1224. 'start_closed' => $bool_start_closed,
  1225. "weight" => 50100,
  1226. );
  1227. // Only show delete option based on permission
  1228. if (user_has_permission("can_delete_data_entry")) {
  1229. $form['markup_bottom_delete'] = array(
  1230. "value" => " <div align='right' class='degrees-delete-degree-wrapper'>
  1231. Delete this degree? <input type='button' value='X'
  1232. onClick='adminDeleteDegree(\"$degree_id\");'>
  1233. </div>
  1234. ",
  1235. "weight" => 90000,
  1236. );
  1237. }
  1238. return $form;
  1239. } // admin_edit_degree_form
  1240. function admin_edit_degree_form_validate($form, &$form_state) {
  1241. $values = $form_state['values'];
  1242. $perform_action2 = trim($values["perform_action2"]);
  1243. $semester_nums_in_use = array();
  1244. $school_id = 0;
  1245. if (isset($values['schools_school'])) { // A school was set from the schools module.
  1246. $school_id = intval($values['schools_school']); // Use our NEW school_id for validating.
  1247. }
  1248. // What courses should have their type overwritten as "x"?
  1249. $ignore_courses = csv_to_array(variable_get_for_school("ignore_courses_from_hour_counts", "", $school_id));
  1250. // One of the things we want to do is make sure that the courses & groups specified actually belong to the school_id for this degree.
  1251. $de_catalog_year = $values["de_catalog_year"];
  1252. $db = get_global_database_handler();
  1253. $degree_id = @intval($form_state['values']['degree_id']);
  1254. // Each degree_id is unique to the catalog year, so we should be good with just the id here.
  1255. if ($degree_id) {
  1256. $degree = new DegreePlan($degree_id, null, false, false, TRUE);
  1257. $degree->load_descriptive_data();
  1258. }
  1259. else {
  1260. // Couldn't find degree_id!
  1261. form_error("", t("There was a problem trying to save this degree. The degree_id could not be found. Contact FlightPath admin if
  1262. this problem persists."));
  1263. return;
  1264. } // else from if(degree_id)
  1265. // At this point, we have a school_id and degree_id.
  1266. if (module_enabled("schools")) {
  1267. $defs = schools_get_school_definitions();
  1268. $school_name = $defs[$school_id];
  1269. }
  1270. // Let's check that all of the courses also belong to this degree and/or can be found at all (no typos).
  1271. foreach($values as $key => $value) {
  1272. if (!strstr($key, "courses_")) {
  1273. continue;
  1274. }
  1275. // Only look at the groups...
  1276. $temp = explode("_", $key);
  1277. $semester_num = trim($temp[1]);
  1278. $semester_nums_in_use[] = $semester_num;
  1279. if ($semester_num > $highest_semester_num) {
  1280. $highest_semester_num = $semester_num;
  1281. }
  1282. $courses = trim(@$values["courses_$semester_num"]);
  1283. // Does it contain a single #? Or, is blank? If so, insert and move on.
  1284. // We do this, so we can have blank semesters until someone deletes them.
  1285. if ($courses == "#" || $courses == "") {
  1286. continue;
  1287. }
  1288. $course_rows = explode("\n",$courses);
  1289. for ($t = 0; $t < count($course_rows); $t++) {
  1290. $line = trim($course_rows[$t]);
  1291. if ($line == "") {
  1292. continue;
  1293. }
  1294. // Take out extra whitespace between tokens.
  1295. $line = str_replace(" ", " ", $line);
  1296. $line = str_replace(" ", " ", $line);
  1297. $line = str_replace(" ", " ", $line);
  1298. $line = str_replace(" ", " ", $line);
  1299. $tokens = explode(" ", $line);
  1300. $subject_id = $tokens[0];
  1301. $course_num = $tokens[1];
  1302. $requirement_type = strtolower(@$tokens[2]);
  1303. if ($requirement_type == "") {
  1304. // major type by default.
  1305. $requirement_type = "m";
  1306. }
  1307. // If this course is in our ignore list, override it's type
  1308. // to be 'x'
  1309. if (in_array("$subject_id $course_num", $ignore_courses)) {
  1310. $requirement_type = "x";
  1311. }
  1312. $min_grade = strtoupper(@$tokens[3]);
  1313. if (strstr($requirement_type, "(")) {
  1314. // This means there was no requirement_type specified, so it's "m",
  1315. // and a min_grade was found in its place.
  1316. $min_grade = strtoupper($requirement_type);
  1317. $requirement_type = "m";
  1318. }
  1319. $min_grade = str_replace("(","",$min_grade);
  1320. $min_grade = str_replace(")","",$min_grade);
  1321. /////////////////////////////////////////////
  1322. // Find out what the course_id is.
  1323. if ($course_id = $db->get_course_id($subject_id, $course_num, "", TRUE, $school_id, TRUE))
  1324. {
  1325. // This was found correctly, do nothing.
  1326. }
  1327. else {
  1328. // The course_id could not be found!
  1329. // Different message if it's a school_id problem.
  1330. if (module_enabled("schools")) {
  1331. form_error("courses_" . $semester_num, t("<strong>Your work has NOT been saved.</strong> Course not found. In block %blocknum, you specified the course %course as a requirement,
  1332. but this course could not be found. This could be due to a typo, or due to the course not belonging to the same school
  1333. as the degree (%schoolname). Please check the course and try again.", array("%blocknum" => ($semester_num+1), "%course" => "$subject_id $course_num", "%schoolname" => $school_name)));
  1334. }
  1335. else {
  1336. // Not related to school (possibly).
  1337. form_error("courses_" . $semester_num, t("<strong>Your work has NOT been saved.</strong> Course not found. In block %blocknum, you specified the course %course as a requirement,
  1338. but this course could not be found. This could be due to a typo.
  1339. Please check the course and try again.", array("%blocknum" => ($semester_num+1), "%course" => "$subject_id $course_num")));
  1340. }
  1341. }
  1342. } // for course_rows
  1343. } // foreach courses
  1344. // Are we trying to ADD a group?
  1345. if (strstr($perform_action2,"addGroup")) {
  1346. $temp = explode("_",$perform_action2);
  1347. $group_id = $temp[1];
  1348. $semester_num = $temp[2];
  1349. $semester_nums_in_use[] = $semester_num;
  1350. $hours = trim($temp[3]);
  1351. $min_hours = $hours;
  1352. if (strstr($hours, "-")) {
  1353. // Hours has a min hour value specified. let's grab it.
  1354. $tt = explode("-", $hours);
  1355. $min_hours = $tt[0];
  1356. $hours = $tt[1];
  1357. }
  1358. $type = $temp[4];
  1359. $min_grade = trim($temp[5]);
  1360. $adding_group = new Group($group_id);
  1361. // If this group is already saved in this degree elsewhere, and it has a different type or min_grade,
  1362. // then we must display a warning message to the user.
  1363. $res = db_query("SELECT * FROM draft_degree_requirements
  1364. WHERE degree_id = '?'
  1365. AND group_id = '?'
  1366. AND (group_min_grade <> '?' OR group_requirement_type <> '?')", $degree_id, $group_id, $min_grade, $type);
  1367. while ($cur = db_fetch_array($res)) {
  1368. form_error("semester_groups_" . $semester_num . "_markup", t("<strong>Your work has NOT been saved.</strong> In block %blocknum, you specified the group %group with a min grade of %mingrade and a requirement type of %req.
  1369. However, the group was previously specified in this degree plan in block %otherblocknum wih a different requirement type or min grade.
  1370. FlightPath will not perform calculations correctly for courses assigned to this group. The duplicate occurance of the group should have the same
  1371. type/min grade, or, you need to create a new group to handle these alternate requirements.</strong>"
  1372. , array("%blocknum" => ($semester_num+1), "%group"=> $adding_group->title, "%mingrade" => $min_grade, "%req" => $type, "%otherblocknum" => ($cur['semester_num'] + 1))));
  1373. } // while
  1374. } // addGroup
  1375. // Now, let's check the groups.
  1376. // Are we trying to DELETE a group, but there might be an error with it? If so, we won't worry about any errors later.
  1377. $del_group = NULL;
  1378. if (strstr($perform_action2, "delGroup")) {
  1379. $temp = explode("_",$perform_action2);
  1380. $del_group = new Group();
  1381. $del_group->bool_use_draft = TRUE;
  1382. $del_group->group_id = $temp[1];
  1383. $del_group->assigned_to_semester_num = $temp[2];
  1384. }
  1385. // Get the groups....
  1386. foreach($values as $key => $value) {
  1387. if (!strstr($key, "group_")) {
  1388. continue;
  1389. }
  1390. // Only look at the groups...
  1391. $temp = explode("_", $value);
  1392. $group_id = $temp[0];
  1393. $semester_num = $temp[1];
  1394. $semester_nums_in_use[] = $semester_num;
  1395. if ($semester_num > $highest_semester_num) {
  1396. $highest_semester_num = $semester_num;
  1397. }
  1398. $hours = $temp[2];
  1399. $min_hours = $hours;
  1400. if (strstr($hours, "-")) {
  1401. // Hours has a min hour value specified. let's grab it.
  1402. $tt = explode("-", $hours);
  1403. $min_hours = $tt[0];
  1404. $hours = $tt[1];
  1405. }
  1406. $type = $temp[3];
  1407. $min_grade = trim($temp[4]);
  1408. // Do not process any further, if we are supposed to be deleting this group!
  1409. if (isset($del_group) && $del_group != NULL && is_object($del_group)) {
  1410. if ($del_group->group_id == $group_id && $del_group->assigned_to_semester_num == $semester_num) {
  1411. continue;
  1412. }
  1413. }
  1414. $adding_group = new Group($group_id);
  1415. // Is this in the right school?
  1416. if ($adding_group->school_id != $school_id && $adding_group->school_id !== 0) {
  1417. form_error("semester_groups_" . $semester_num . "_markup", t("<strong>Your work has NOT been saved.</strong> In block %blocknum, you specified the group %group as a requirement,
  1418. but this group could not be found in the degree's school (%schoolname).<br>You may need to change the degree's school back to its previous value, then remove this group,
  1419. in order to continue.", array("%blocknum" => ($semester_num+1), "%group" => $adding_group->title, "%schoolname" => $school_name)));
  1420. }
  1421. // If this group is already saved in this degree elsewhere, and it has a different type or min_grade,
  1422. // then we must display a warning message to the user.
  1423. $res = db_query("SELECT * FROM draft_degree_requirements
  1424. WHERE degree_id = ?
  1425. AND group_id = ?
  1426. AND (group_min_grade <> ? OR group_requirement_type <> ?)", $degree_id, $group_id, $min_grade, $type);
  1427. while ($cur = db_fetch_array($res)) {
  1428. // Is the group we found the group we are trying to delete? If so, skip it; we're going to delete it later.
  1429. if (isset($del_group) && is_object($del_group)) {
  1430. if (intval($del_group->group_id) == intval($cur['group_id']) && intval($del_group->assigned_to_semester_num) == intval($cur['semester_num'])) {
  1431. continue;
  1432. }
  1433. }
  1434. form_error("semester_groups_" . $semester_num . "_markup", t("<strong>Your work has NOT been saved.</strong> In block %blocknum, you specified the group %group with a min grade of %mingrade and a requirement type of %req.
  1435. However, the group was previously specified in this degree plan in block %otherblocknum wih a different requirement type or min grade.
  1436. FlightPath will not perform calculations correctly for courses assigned to this group. The duplicate occurance of the group should have the same
  1437. type/min grade, or, you need to create a new group to handle these alternate requirements.</strong>"
  1438. , array("%blocknum" => ($semester_num+1), "%group"=> $adding_group->title, "%mingrade" => $min_grade, "%req" => $type, "%otherblocknum" => ($cur['semester_num'] + 1))));
  1439. }
  1440. } // foreach groups
  1441. // Are we trying to change a semester block number?
  1442. if (strstr($perform_action2,"editSemesterBlockNum")) {
  1443. // Make sure we don't already have this number in existence elsewhere in the degree.
  1444. $temp = explode("_",$perform_action2);
  1445. $old_semester_num = $temp[1];
  1446. $new_semester_num = $temp[2];
  1447. if (in_array($new_semester_num, $semester_nums_in_use)) {
  1448. form_error('', t("<strong>Your work has NOT been saved.</strong> Sorry, but you requested to change block number %old to %new, but block number %new
  1449. is already in use. Please make the appropriate changes and try again.", array("%old" => ($old_semester_num + 1), "%new" => ($new_semester_num + 1))));
  1450. }
  1451. } // editSemesterBlockNum
  1452. } // edit_degree_form_validate
  1453. function admin_edit_degree_form_submit($form, $form_state) {
  1454. $values = $form_state['values'];
  1455. // Set the scroll_top position, if it is set.
  1456. $scroll_top = $form_state['values']['scroll_top'];
  1457. if (@$scroll_top != "" && intval($scroll_top) > 0) {
  1458. $_SESSION['scroll_top'] = $scroll_top;
  1459. }
  1460. // Perform actual saves to database
  1461. $de_catalog_year = $values["de_catalog_year"];
  1462. $db = get_global_database_handler();
  1463. // This will UPDATE a degree in the system with the courses
  1464. // and groups that the user selected.
  1465. $perform_action2 = trim($values["perform_action2"]);
  1466. if (strstr($perform_action2, "delGroup")) {
  1467. $temp = explode("_",$perform_action2);
  1468. $del_group = new Group();
  1469. $del_group->bool_use_draft = TRUE;
  1470. $del_group->group_id = $temp[1];
  1471. $del_group->assigned_to_semester_num = $temp[2];
  1472. }
  1473. $major_code = trim($values["major_code"]);
  1474. if ($major_code == ""){ die("Fatal error: major_code not found.");}
  1475. // Since we are making a change to the draft table(s), let's add a row
  1476. // to draft instructions.
  1477. $db->add_draft_instruction("-");
  1478. // Let's assemble the track selection config values into one string. We need to loop through all of the POST
  1479. // values, looking for each type of track.
  1480. $db_track_selection_config = "";
  1481. $degree_classes = fp_get_degree_classifications();
  1482. foreach ($degree_classes["levels"] as $level => $details) {
  1483. if (intval($level) != 3) continue; // we only care about level 3...
  1484. foreach ($degree_classes["levels"][$level] as $machine_name => $title) {
  1485. // Got the machine name, now let's see if we have any values for
  1486. // the track selections...
  1487. $min_tracks = @intval($values["tsc_{$machine_name}_min_tracks"]);
  1488. $max_tracks = @intval($values["tsc_{$machine_name}_max_tracks"]);
  1489. $default_tracks = @trim($values["tsc_{$machine_name}_default_tracks"]);
  1490. $db_track_selection_config .= $machine_name . "~" . $min_tracks . "~" . $max_tracks . "~" . $default_tracks . "\n";
  1491. }
  1492. }
  1493. $school_id = 0;
  1494. if (isset($form_state['values']['school_id'])) {
  1495. $school_id = intval($form_state['values']['school_id']);
  1496. }
  1497. $degree_id = @intval($form_state['values']['degree_id']);
  1498. // If this degree already exists in this
  1499. // catalog year, then we need to delete it first.
  1500. //if ($degree_id = $db->get_degree_id($major_code, $de_catalog_year, true, $school_id)) {
  1501. // Each degree_id is unique to the catalog year, so we should be good with just the id here.
  1502. if ($degree_id) {
  1503. $degree = new DegreePlan($degree_id, null, false, false, true);
  1504. $degree->load_descriptive_data();
  1505. $oschool_id = intval($degree->school_id); // original school_id
  1506. // Delete from degree_requirements WHERE this degree_id exists.
  1507. $res = db_query("DELETE FROM draft_degree_requirements
  1508. WHERE degree_id = ? ", $degree_id);
  1509. ///////////////////////////////
  1510. // Are we trying to DELETE this degree? If so, keep deleting!
  1511. if ($perform_action2 == "delete_degree" && user_has_permission("can_delete_data_entry")) {
  1512. $res = db_query("DELETE FROM draft_degrees
  1513. WHERE degree_id = ? ", $degree_id);
  1514. // Also need to get rid of the track, if there is one for this
  1515. // degree.
  1516. $temp = explode("_", $degree->major_code); // get only the "major" part from the full major_code (might look like ACCT|FINA_TRACK1
  1517. $just_major_part = trim($temp[0]);
  1518. $just_major_part = rtrim($just_major_part, "|"); // if there is now a trailing |, get rid of it. Ex: ACCT|
  1519. $res = db_query("DELETE FROM draft_degree_tracks
  1520. WHERE major_code = ?
  1521. AND track_code = ?
  1522. AND catalog_year = ?
  1523. AND school_id = ?
  1524. LIMIT 1", $just_major_part, $degree->track_code, $de_catalog_year, $oschool_id);
  1525. // Okay, we have deleted everything. We need to go back to
  1526. // just the list of degrees.
  1527. //display_edit_degrees("<font color='green'><b>The degree $major_code ($de_catalog_year) has been deleted.</b></font>");
  1528. //die;
  1529. fp_add_message("The degree $major_code ($de_catalog_year) has been deleted.");
  1530. watchdog("admin", "The degree $major_code ($de_catalog_year) has been deleted.");
  1531. unset($_SESSION['scroll_top']);
  1532. unset($_REQUEST['scroll_top']);
  1533. fp_goto("admin/degrees", "de_catalog_year=$de_catalog_year");
  1534. return;
  1535. } // if perform_action2 == delete_degree
  1536. } // if degree->id
  1537. else {
  1538. // We need to generate a new degreeID for this major_code and catalog_year,
  1539. // because one does not already exist!
  1540. if (!$degree_id = $db->request_new_degree_id()) {
  1541. watchdog("admin", "Could not create new degree.");
  1542. die ("Error. Could not create new degree_id.");
  1543. }
  1544. } // ELSE
  1545. // What courses should have their type overwritten as "x"?
  1546. $ignore_courses = csv_to_array(variable_get_for_school("ignore_courses_from_hour_counts", "", $school_id));
  1547. ///////////////////////////////////////
  1548. // Are we trying to add/edit/delete a semester block?
  1549. if (strstr($perform_action2, "editSemester")) {
  1550. $temp = explode("_",$perform_action2);
  1551. $act = $temp[1];
  1552. $semester_num = $temp[2];
  1553. if ($act == "new") {
  1554. // We will add a comment to the courses box, just to keep it alive, which will be ignored later.
  1555. $values["courses_$semester_num"] = "#";
  1556. } // if act == new
  1557. if ($act == "del") {
  1558. // We will remove data for this semester block.
  1559. unset($values["courses_$semester_num"]);
  1560. unset($values["semester_title_$semester_num"]);
  1561. foreach($values as $key => $value) {
  1562. if (!strstr($key, "group_")) {
  1563. continue;
  1564. }
  1565. // Only look at the groups...
  1566. $temp = explode("_", $value);
  1567. $g_semester_num = $temp[1];
  1568. if ($g_semester_num == $semester_num) {
  1569. unset($values[$key]);
  1570. }
  1571. }
  1572. } // if act == del
  1573. } // if perform_action2 contains editSemester
  1574. ///////////////////////////////////////
  1575. // Okay, time to start actually inserting our data into the db.
  1576. $errors = "";
  1577. $semester_titles_csv = "";
  1578. $highest_semester_num = 0; // What is the largest semester_num in the system?
  1579. // Get the COURSES for each semester
  1580. foreach($values as $key => $value) {
  1581. if (!strstr($key, "courses_")) {
  1582. continue;
  1583. }
  1584. // Only look at the groups...
  1585. $temp = explode("_", $key);
  1586. $semester_num = trim($temp[1]);
  1587. if ($semester_num > $highest_semester_num) {
  1588. $highest_semester_num = $semester_num;
  1589. }
  1590. $courses = trim(@$values["courses_$semester_num"]);
  1591. // Does it contain a single #? Or, is blank? If so, insert and move on.
  1592. // We do this, so we can have blank semesters until someone deletes them.
  1593. if ($courses == "#" || $courses == "") {
  1594. $query = "INSERT INTO draft_degree_requirements
  1595. (degree_id, semester_num, course_id, course_min_grade, course_requirement_type, data_entry_value)
  1596. values (?,?,?,?,?,?) ";
  1597. $res = db_query($query, $degree_id, $semester_num, 0, '', '', "#");
  1598. continue;
  1599. }
  1600. $course_rows = explode("\n",$courses);
  1601. for ($t = 0; $t < count($course_rows); $t++) {
  1602. $line = trim($course_rows[$t]);
  1603. if ($line == "") {
  1604. continue;
  1605. }
  1606. // Take out extra whitespace between tokens.
  1607. $line = str_replace(" ", " ", $line);
  1608. $line = str_replace(" ", " ", $line);
  1609. $line = str_replace(" ", " ", $line);
  1610. $line = str_replace(" ", " ", $line);
  1611. $tokens = explode(" ", $line);
  1612. $subject_id = $tokens[0];
  1613. $course_num = $tokens[1];
  1614. $requirement_type = strtolower(@$tokens[2]);
  1615. if ($requirement_type == "") {
  1616. // major type by default.
  1617. $requirement_type = "m";
  1618. }
  1619. // If this course is in our ignore list, override it's type
  1620. // to be 'x'
  1621. if (in_array("$subject_id $course_num", $ignore_courses)) {
  1622. $requirement_type = "x";
  1623. }
  1624. $min_grade = strtoupper(@$tokens[3]);
  1625. if (strstr($requirement_type, "(")) {
  1626. // This means there was no requirement_type specified, so it's "m",
  1627. // and a min_grade was found in its place.
  1628. $min_grade = strtoupper($requirement_type);
  1629. $requirement_type = "m";
  1630. }
  1631. $min_grade = str_replace("(","",$min_grade);
  1632. $min_grade = str_replace(")","",$min_grade);
  1633. /////////////////////////////////////////////
  1634. // Okay, we now have enough information to insert the course.
  1635. // Find out what the course_id is.
  1636. if ($course_id = $db->get_course_id($subject_id, $course_num, "", TRUE, $school_id, TRUE))
  1637. {
  1638. $query = "INSERT INTO draft_degree_requirements
  1639. (degree_id, semester_num, course_id, course_min_grade, course_requirement_type, data_entry_value)
  1640. values (?,?,?,?,?,?) ";
  1641. $res = db_query($query, $degree_id, $semester_num, $course_id, $min_grade, $requirement_type, "$subject_id~$course_num");
  1642. }
  1643. else {
  1644. // The course_id could not be found!
  1645. $errors .= "<br><span style='color:red;'><b>Course Not Found!</b>
  1646. In Block " . ($semester_num+1) . ", you specified the course
  1647. <b>$subject_id $course_num</b> as a requirement, but this course
  1648. could not be found in the degree's school.
  1649. It was removed from that block.
  1650. Are you sure you typed it correctly? Please go to this
  1651. semester, check your spelling, and add the course again.</span>";
  1652. }
  1653. }
  1654. } // foreach values, looking for courses_
  1655. // Get the groups....
  1656. foreach($values as $key => $value) {
  1657. if (!strstr($key, "group_")) {
  1658. continue;
  1659. }
  1660. // Only look at the groups...
  1661. $temp = explode("_", $value);
  1662. $group_id = $temp[0];
  1663. $semester_num = $temp[1];
  1664. if ($semester_num > $highest_semester_num) {
  1665. $highest_semester_num = $semester_num;
  1666. }
  1667. $hours = $temp[2];
  1668. $min_hours = $hours;
  1669. if (strstr($hours, "-")) {
  1670. // Hours has a min hour value specified. let's grab it.
  1671. $tt = explode("-", $hours);
  1672. $min_hours = $tt[0];
  1673. $hours = $tt[1];
  1674. }
  1675. $type = $temp[3];
  1676. $min_grade = trim($temp[4]);
  1677. // Do not add if we are supposed to be deleting this group!
  1678. if (isset($del_group) && is_object($del_group)) {
  1679. if ($del_group->group_id == $group_id && $del_group->assigned_to_semester_num == $semester_num) {
  1680. continue;
  1681. }
  1682. }
  1683. $adding_group = new Group($group_id);
  1684. // If this group is already saved in this degree elsewhere, and it has a different type or min_grade,
  1685. // then we must display a warning message to the user.
  1686. $res = db_query("SELECT * FROM draft_degree_requirements
  1687. WHERE degree_id = '?'
  1688. AND group_id = '?'
  1689. AND (group_min_grade <> '?' OR group_requirement_type <> '?')", $degree_id, $group_id, $min_grade, $type);
  1690. while ($cur = db_fetch_array($res)) {
  1691. $errors .= "<br><span style='color:red;'><b>Group type or min grade mismatch!</b>
  1692. In Block " . ($semester_num + 1) . ", you specified the group <em>" . $adding_group->title . "</em> ($adding_group->group_name) with a min grade of \"<em>$min_grade</em>\"
  1693. and a requirement type of \"<em>$type</em>\". However, the group was previously specified in this degree plan in Block " . ($cur["semester_num"] + 1) . "
  1694. with a different requirement type and/or min grade requirement. FlightPath will not perform calculations correctly for courses assigned to this group.
  1695. You should either set the duplicate occurances of the group to the same type/min grade, or create a new group to handle these alternate requirements.</span>";
  1696. }
  1697. // We now have enough information to insert this group.
  1698. $query = "INSERT INTO draft_degree_requirements
  1699. (degree_id, semester_num, group_id,
  1700. group_requirement_type, group_hours_required, group_min_hours_allowed, group_min_grade)
  1701. values (?,?,?,?,?,?,?) ";
  1702. $res = db_query($query, $degree_id, $semester_num, $group_id, $type, $hours, $min_hours, $min_grade);
  1703. } // for each values, looking for _group
  1704. // Was there a group added?
  1705. if (strstr($perform_action2,"addGroup")) {
  1706. $temp = explode("_",$perform_action2);
  1707. $group_id = $temp[1];
  1708. $semester_num = $temp[2];
  1709. $hours = trim($temp[3]);
  1710. $min_hours = $hours;
  1711. if (strstr($hours, "-")) {
  1712. // Hours has a min hour value specified. let's grab it.
  1713. $tt = explode("-", $hours);
  1714. $min_hours = $tt[0];
  1715. $hours = $tt[1];
  1716. }
  1717. $type = $temp[4];
  1718. $min_grade = trim($temp[5]);
  1719. $adding_group = new Group($group_id);
  1720. // If this group is already saved in this degree elsewhere, and it has a different type or min_grade,
  1721. // then we must display a warning message to the user.
  1722. $res = db_query("SELECT * FROM draft_degree_requirements
  1723. WHERE degree_id = '?'
  1724. AND group_id = '?'
  1725. AND (group_min_grade <> '?' OR group_requirement_type <> '?')", $degree_id, $group_id, $min_grade, $type);
  1726. while ($cur = db_fetch_array($res)) {
  1727. $errors .= "<br><span style='color:red;'><b>Group type or min grade mismatch!</b>
  1728. In Block " . ($semester_num + 1) . ", you specified the group <em>" . $adding_group->title . "</em> ($adding_group->group_name) with a min grade of \"<em>$min_grade</em>\"
  1729. and a requirement type of \"<em>$type</em>\". However, the group was previously specified in this degree plan in Block " . ($cur["semester_num"] + 1) . "
  1730. with a different requirement type and/or min grade requirement. FlightPath will not perform calculations correctly for courses assigned to this group.
  1731. You should either set the duplicate occurances of the group to the same type/min grade, or create a new group to handle these alternate requirements.</span>";
  1732. }
  1733. $query = "INSERT INTO draft_degree_requirements
  1734. (degree_id,semester_num,group_id,
  1735. group_requirement_type,group_hours_required,group_min_hours_allowed,group_min_grade)
  1736. VALUES (?,?,?,?,?,?,?) ";
  1737. $res = db_query($query, $degree_id, $semester_num, $group_id, $type, $hours, $min_hours, $min_grade);
  1738. } // if perform_action2 == addGroup
  1739. // Are we trying to change a semester block number?
  1740. if (strstr($perform_action2,"editSemesterBlockNum")) {
  1741. // Make sure we don't already have this number in existence elsewhere in the degree.
  1742. $temp = explode("_",$perform_action2);
  1743. $old_semester_num = $temp[1];
  1744. $new_semester_num = $temp[2];
  1745. // Since we have already passed validation, we should be able to simply update the draft table.
  1746. db_query("UPDATE draft_degree_requirements SET semester_num = ?
  1747. WHERE degree_id = ?
  1748. AND semester_num = ?", array($new_semester_num, $degree_id, $old_semester_num));
  1749. // We also need to adjust the semester_title_$semester_num value in the $values, so the title moves over correctly.
  1750. $temp = $values["semester_title_$old_semester_num"];
  1751. unset($values["semester_title_$old_semester_num"]);
  1752. $values["semester_title_$new_semester_num"] = $temp;
  1753. } // editSemesterBlockNum
  1754. // Make the semester_titles_csv...
  1755. for ($semester_num = 0; $semester_num <= 99; $semester_num++) {
  1756. if ($semester_num > 99) break; // some problem. Give up. Don't try to go past 99 semesters!
  1757. $semester_titles_csv .= trim(@$values["semester_title_$semester_num"]) . ",";
  1758. }
  1759. // Before we UPDATE, also grab the degree title, degree_type,
  1760. // and exclude value, etc....
  1761. $degree_title = trim($values["title"]);
  1762. $degree_type = trim($values["degree_type"]);
  1763. $degree_class = trim($values["degree_class"]);
  1764. $degree_level = strtoupper(trim($values["degree_level"]));
  1765. $exclude = intval($values["exclude"]);
  1766. $allow_dynamic = intval($values["allow_dynamic"]);
  1767. $advising_weight = intval($values["advising_weight"]);
  1768. $override_degree_hours = trim($values["override_degree_hours"]);
  1769. $public_note = trim($values["public_note"]);
  1770. $res = db_query("UPDATE draft_degrees
  1771. SET semester_titles_csv = ?,
  1772. title = ?,
  1773. degree_type = ?,
  1774. degree_class = ?,
  1775. degree_level = ?,
  1776. exclude = ?,
  1777. allow_dynamic = ?,
  1778. advising_weight = ?,
  1779. override_degree_hours = ?,
  1780. track_selection_config = ?,
  1781. public_note = ?,
  1782. school_id = ?
  1783. WHERE degree_id = ? ",
  1784. $semester_titles_csv, $degree_title, $degree_type, $degree_class, $degree_level, $exclude, $allow_dynamic, $advising_weight, $override_degree_hours,
  1785. $db_track_selection_config, $public_note, $school_id, $degree_id);
  1786. //// Was there a track title/description? If so, UPDATE that in the tracks
  1787. // table...
  1788. if (strstr($major_code, "_")) {
  1789. // There was a track. Update track description.
  1790. $temp = explode("_",$major_code);
  1791. $major = trim($temp[0]);
  1792. // major might now have a | at the end. If so, take it out.
  1793. if (substr($major, strlen($major)-1, 1) == "|") {
  1794. $major = str_replace("|","",$major);
  1795. }
  1796. $track = trim($temp[1]);
  1797. $track_description = trim($values["track_description"]);
  1798. $track_title = trim($values["track_title"]);
  1799. // Make sure the track exists in our draft_degree_tracks table...
  1800. $track_id = db_result(db_query("SELECT track_id FROM draft_degree_tracks
  1801. WHERE major_code = ?
  1802. AND track_code = ?
  1803. AND catalog_year = ?
  1804. AND school_id = ?", $major, $track, $de_catalog_year, $oschool_id));
  1805. if (!$track_id) {
  1806. // Didn't already exist. Let's insert.
  1807. db_query("INSERT INTO draft_degree_tracks (major_code, track_code, catalog_year, school_id)
  1808. VALUES (?, ?, ?, ?)", $major, $track, $de_catalog_year, $school_id);
  1809. $track_id = db_insert_id();
  1810. }
  1811. $res = db_query("UPDATE draft_degree_tracks
  1812. SET track_description = ?,
  1813. track_title = ?,
  1814. school_id = ?
  1815. WHERE track_id = ? ", $track_description, $track_title, $school_id, $track_id);
  1816. }
  1817. fp_add_message("Degree updated succesfully.");
  1818. watchdog("admin", "$major_code $track ($de_catalog_year) has been updated successfully.");
  1819. $button_msg = urlencode("Degree updated successfully at " . date("H:i:s"));
  1820. $bool_scroll = $bool_button_msg = true;
  1821. if ($errors != "")
  1822. {
  1823. fp_add_message("ERRORS/WARNINGS: $errors");
  1824. $bool_scroll = $bool_button_msg = false;
  1825. $button_msg = urlencode("The degree plan was saved, but an error or warning has occured. Please see error message at the top of the page.");
  1826. $_REQUEST["scroll_top"] = 0;
  1827. $_SESSION["scroll_top"] = 0;
  1828. }
  1829. ///////////////////////////////////////////////////////
  1830. ///////////////////////////////////////////////////////
  1831. ///////////////////////////////////////////////////////
  1832. ///////////////////////////////////////////////////////
  1833. // And we are done with the saving!
  1834. } //edit_degree_form_submit

Functions

Namesort ascending Description
admin_string_contains_illegal_chars
admin_edit_degree_form_validate
admin_edit_degree_form_submit
admin_edit_degree_form Meant to replace the old-fashioned display_edit_degree function...
admin_display_degrees_popup_add_group2
admin_display_degrees
admin_degrees_list_filter_form_submit
admin_degrees_list_filter_form
admin_copy_degree_form_validate Validate handler. Make sure our allow_overwrite setting is working. Check for existing major code.
admin_copy_degree_form_submit
admin_copy_degree_form This form lets the user copy a degree and all of it's tracks & concentrations.
admin_add_degree_form_validate Validate handler for add_degree_form
admin_add_degree_form_submit Submit handler for the add_degree_form.
admin_add_degree_form This form lets the user add a degree to the database.