admin.module

  1. 6.x modules/admin/admin.module
  2. 4.x modules/admin/admin.module
  3. 5.x modules/admin/admin.module

The administrative configurations for FlightPath.

File

modules/admin/admin.module
View source
  1. <?php
  2. /**
  3. * @file
  4. * The administrative configurations for FlightPath.
  5. *
  6. *
  7. */
  8. /**
  9. * Implementation of hook_menu
  10. *
  11. */
  12. function admin_menu() {
  13. $items = array();
  14. $items["admin-tools"] = array(
  15. "title" => "Admin Tools",
  16. "page_callback" => "admin_display_tools_screen",
  17. "access_arguments" => array("can_access_admin_tools"),
  18. "tab_family" => "admin",
  19. "page_settings" => array(
  20. "page_hide_report_error" => TRUE,
  21. ),
  22. "type" => MENU_TYPE_NORMAL_ITEM,
  23. );
  24. $items["admin-tools/admin"] = array(
  25. "title" => t("FlightPath Admin Console"),
  26. "description" => t("This area contains the bulk of settings, degree entry, and other configurations for FlightPath."),
  27. "page_callback" => "admin_display_main",
  28. "access_arguments" => array("can_access_admin"),
  29. "page_settings" => array(
  30. "menu_links" => array(
  31. 0 => array(
  32. "text" => "Admin Tools",
  33. "path" => "admin-tools",
  34. ),
  35. ),
  36. "menu_icon" => fp_get_module_path('system') . "/icons/FlightPath_Academics_plane_only.png",
  37. ),
  38. 'weight' => 999,
  39. "type" => MENU_TYPE_NORMAL_ITEM,
  40. );
  41. $items["admin/config/urgent-message"] = array(
  42. "title" => "Edit urgent message",
  43. "description" => "Set a message which will be displayed to all users on every page",
  44. "page_callback" => "fp_render_form",
  45. "page_arguments" => array("admin_urgent_message_form", "system_settings"),
  46. "access_arguments" => array("can_edit_urgent_message"),
  47. "page_settings" => array(
  48. "menu_icon" => fp_get_module_path('admin') . "/icons/error.png",
  49. "page_hide_report_error" => TRUE,
  50. "menu_links" => array(
  51. 0 => array(
  52. "text" => "Admin Console",
  53. "path" => "admin-tools/admin",
  54. "query" => "de_catalog_year=%DE_CATALOG_YEAR%",
  55. ),
  56. ),
  57. ),
  58. "type" => MENU_TYPE_NORMAL_ITEM,
  59. );
  60. $items["admin/config/watchdog"] = array(
  61. "title" => "Watchdog (logs)",
  62. "description" => "View log messages from throughout the system",
  63. "page_callback" => "admin_display_watchdog",
  64. "access_arguments" => array("display_watchdog"),
  65. "page_settings" => array(
  66. "menu_icon" => fp_get_module_path('system') . "/icons/application_view_list.png",
  67. "page_show_title" => TRUE,
  68. "page_hide_report_error" => TRUE,
  69. "menu_links" => array(
  70. 0 => array(
  71. "text" => "Admin Console",
  72. "path" => "admin-tools/admin",
  73. "query" => "de_catalog_year=%DE_CATALOG_YEAR%",
  74. ),
  75. ),
  76. ),
  77. "type" => MENU_TYPE_NORMAL_ITEM,
  78. );
  79. $items["admin/config/watchdog/%"] = array(
  80. "title" => "View Watchdog Entry",
  81. "page_callback" => "admin_display_watchdog_entry",
  82. "page_arguments" => array(3),
  83. "access_arguments" => array("display_watchdog"),
  84. "page_settings" => array(
  85. "page_show_title" => TRUE,
  86. "page_hide_report_error" => TRUE,
  87. "menu_links" => array(
  88. 0 => array(
  89. "text" => "Admin Console",
  90. "path" => "admin-tools/admin",
  91. "query" => "de_catalog_year=%DE_CATALOG_YEAR%",
  92. ),
  93. 1 => array(
  94. "text" => "Watchdog",
  95. "path" => "admin/config/watchdog",
  96. "query" => "de_catalog_year=%DE_CATALOG_YEAR%&sev_filter=%SEV_FILTER%&page=%PAGE%&type_filter=%TYPE_FILTER%",
  97. ),
  98. ),
  99. ),
  100. "type" => MENU_TYPE_CALLBACK,
  101. );
  102. $items["admin/duplicate-year"] = array(
  103. "title" => "Duplicate entire catalog year",
  104. "page_callback" => "fp_render_form",
  105. "page_arguments" => array("admin_duplicate_year_form"),
  106. "access_arguments" => array("can_edit_data_entry"),
  107. "page_settings" => array(
  108. "page_hide_report_error" => TRUE,
  109. "menu_links" => array(
  110. 0 => array(
  111. "text" => "Admin Console",
  112. "path" => "admin-tools/admin",
  113. "query" => "de_catalog_year=%DE_CATALOG_YEAR%",
  114. ),
  115. ),
  116. ),
  117. "type" => MENU_TYPE_NORMAL_ITEM,
  118. "tab_parent" => "admin-tools/admin",
  119. );
  120. $items["admin/edit-advising-settings"] = array(
  121. "title" => "Edit advising settings",
  122. "page_callback" => "fp_render_form",
  123. "page_arguments" => array("admin_advising_settings_form", "system_settings"),
  124. "access_arguments" => array("can_edit_advising_settings"),
  125. "page_settings" => array(
  126. "page_hide_report_error" => TRUE,
  127. "menu_links" => array(
  128. 0 => array(
  129. "text" => "Admin Console",
  130. "path" => "admin-tools/admin",
  131. "query" => "de_catalog_year=%DE_CATALOG_YEAR%",
  132. ),
  133. ),
  134. ),
  135. "type" => MENU_TYPE_NORMAL_ITEM,
  136. "tab_parent" => "admin-tools/admin",
  137. );
  138. $items["admin/apply-draft-changes"] = array(
  139. "title" => "Apply draft changes",
  140. "page_callback" => "fp_render_form",
  141. "page_arguments" => array("admin_apply_draft_changes_form"),
  142. "access_arguments" => array("can_apply_draft_changes"),
  143. "page_settings" => array(
  144. "page_hide_report_error" => TRUE,
  145. "menu_links" => array(
  146. 0 => array(
  147. "text" => "Admin Console",
  148. "path" => "admin-tools/admin",
  149. "query" => "de_catalog_year=%DE_CATALOG_YEAR%",
  150. ),
  151. ),
  152. ),
  153. "type" => MENU_TYPE_NORMAL_ITEM,
  154. "tab_parent" => "admin-tools/admin",
  155. );
  156. ///////////////////////////////////////////////////////
  157. ////////////////////// Degree Editing ///////////////////
  158. $items["admin/degrees"] = array(
  159. "title" => "Degrees",
  160. "page_callback" => "admin_display_degrees",
  161. "access_arguments" => array("can_access_data_entry"),
  162. "page_settings" => array(
  163. "page_hide_report_error" => TRUE,
  164. "menu_links" => array(
  165. 0 => array(
  166. "text" => "Admin Console",
  167. "path" => "admin-tools/admin",
  168. "query" => "de_catalog_year=%DE_CATALOG_YEAR%",
  169. ),
  170. ),
  171. ),
  172. "file" => menu_get_module_path("admin") . "/admin.degrees.inc",
  173. "type" => MENU_TYPE_NORMAL_ITEM,
  174. );
  175. $items["admin/degrees/edit-degree/%/%"] = array(
  176. "title" => "Edit Degree",
  177. "page_callback" => "fp_render_form",
  178. "page_arguments" => array("admin_edit_degree_form", "normal", 3, 4),
  179. "access_arguments" => array("can_edit_data_entry"),
  180. "page_settings" => array(
  181. "page_hide_report_error" => TRUE,
  182. "menu_links" => array(
  183. 0 => array(
  184. "text" => "Admin Console",
  185. "path" => "admin-tools/admin",
  186. "query" => "de_catalog_year=%DE_CATALOG_YEAR%",
  187. ),
  188. 1 => array(
  189. "text" => "Degrees",
  190. "path" => "admin/degrees",
  191. "query" => "de_catalog_year=%DE_CATALOG_YEAR%",
  192. ),
  193. ),
  194. ),
  195. "file" => menu_get_module_path("admin") . "/admin.degrees.inc",
  196. "type" => MENU_TYPE_NORMAL_ITEM,
  197. );
  198. $items["admin/degrees/popup-add-group"] = array(
  199. "title" => "Add Group",
  200. "page_callback" => "admin_display_degrees_popup_add_group",
  201. "access_arguments" => array("can_edit_data_entry"),
  202. "page_settings" => array(
  203. "page_is_popup" => TRUE,
  204. "page_hide_report_error" => TRUE,
  205. ),
  206. "file" => menu_get_module_path("admin") . "/admin.degrees.inc",
  207. "type" => MENU_TYPE_CALLBACK,
  208. );
  209. $items["admin/degrees/popup-add-group2"] = array(
  210. "title" => "Add Group",
  211. "page_callback" => "admin_display_degrees_popup_add_group2",
  212. "access_arguments" => array("can_edit_data_entry"),
  213. "page_settings" => array(
  214. "page_is_popup" => TRUE,
  215. "page_hide_report_error" => TRUE,
  216. ),
  217. "file" => menu_get_module_path("admin") . "/admin.degrees.inc",
  218. "type" => MENU_TYPE_CALLBACK,
  219. );
  220. $items["admin/degrees/add-degree"] = array(
  221. "title" => "Add Degree",
  222. "page_callback" => "fp_render_form",
  223. "page_arguments" => array("admin_add_degree_form"),
  224. "access_arguments" => array("can_edit_data_entry"),
  225. "page_settings" => array(
  226. "page_hide_report_error" => TRUE,
  227. "menu_links" => array(
  228. 0 => array(
  229. "text" => "Admin Console",
  230. "path" => "admin-tools/admin",
  231. "query" => "de_catalog_year=%DE_CATALOG_YEAR%",
  232. ),
  233. 1 => array(
  234. "text" => "Degrees",
  235. "path" => "admin/degrees",
  236. "query" => "de_catalog_year=%DE_CATALOG_YEAR%",
  237. ),
  238. ),
  239. ),
  240. "file" => menu_get_module_path("admin") . "/admin.degrees.inc",
  241. "type" => MENU_TYPE_NORMAL_ITEM,
  242. );
  243. $items["admin/degrees/copy-degree"] = array(
  244. "title" => "Copy Degree",
  245. "page_callback" => "fp_render_form",
  246. "page_arguments" => array("admin_copy_degree_form"),
  247. "access_arguments" => array("can_edit_data_entry"),
  248. "page_settings" => array(
  249. "page_hide_report_error" => TRUE,
  250. "menu_links" => array(
  251. 0 => array(
  252. "text" => "Admin Console",
  253. "path" => "admin-tools/admin",
  254. "query" => "de_catalog_year=%DE_CATALOG_YEAR%",
  255. ),
  256. 1 => array(
  257. "text" => "Degrees",
  258. "path" => "admin/degrees",
  259. "query" => "de_catalog_year=%DE_CATALOG_YEAR%",
  260. ),
  261. ),
  262. ),
  263. "file" => menu_get_module_path("admin") . "/admin.degrees.inc",
  264. "type" => MENU_TYPE_CALLBACK,
  265. );
  266. ///////////////////////////////////////////////////////
  267. ////////////////////// Group Editing ///////////////////
  268. $items["admin/groups"] = array(
  269. "title" => "Groups",
  270. "page_callback" => "admin_display_groups",
  271. "access_arguments" => array("can_access_data_entry"),
  272. "page_settings" => array(
  273. "page_hide_report_error" => TRUE,
  274. "menu_links" => array(
  275. 0 => array(
  276. "text" => "Admin Console",
  277. "path" => "admin-tools/admin",
  278. "query" => "de_catalog_year=%DE_CATALOG_YEAR%",
  279. ),
  280. ),
  281. ),
  282. "file" => menu_get_module_path("admin") . "/admin.groups.inc",
  283. "type" => MENU_TYPE_NORMAL_ITEM
  284. );
  285. $items["admin/groups/edit-group"] = array(
  286. "title" => "Edit Group",
  287. "page_callback" => "fp_render_form",
  288. "page_arguments" => array("admin_edit_group_form"),
  289. "access_arguments" => array("can_edit_data_entry"),
  290. "page_settings" => array(
  291. "page_hide_report_error" => TRUE,
  292. "menu_links" => array(
  293. 0 => array(
  294. "text" => "Admin Console",
  295. "path" => "admin-tools/admin",
  296. "query" => "de_catalog_year=%DE_CATALOG_YEAR%",
  297. ),
  298. 1 => array(
  299. "text" => "Groups",
  300. "path" => "admin/groups",
  301. "query" => "de_catalog_year=%DE_CATALOG_YEAR%",
  302. ),
  303. ),
  304. ),
  305. "file" => menu_get_module_path("admin") . "/admin.groups.inc",
  306. "type" => MENU_TYPE_NORMAL_ITEM,
  307. );
  308. $items["admin/groups/popup-select-icon"] = array(
  309. "title" => "Select Icon",
  310. "page_callback" => "admin_display_groups_popup_select_icon",
  311. "access_arguments" => array("can_edit_data_entry"),
  312. "page_settings" => array(
  313. "page_is_popup" => TRUE,
  314. "page_hide_report_error" => TRUE,
  315. ),
  316. "file" => menu_get_module_path("admin") . "/admin.groups.inc",
  317. "type" => MENU_TYPE_CALLBACK,
  318. );
  319. $items["admin/groups/popup-edit-definition"] = array(
  320. "title" => "Edit Definition",
  321. "page_callback" => "admin_display_groups_popup_edit_definition",
  322. "access_arguments" => array("can_edit_data_entry"),
  323. "page_settings" => array(
  324. "page_is_popup" => TRUE,
  325. "page_hide_report_error" => TRUE,
  326. ),
  327. "file" => menu_get_module_path("admin") . "/admin.groups.inc",
  328. "type" => MENU_TYPE_CALLBACK,
  329. );
  330. $items["admin/groups/popup-show-group-use"] = array(
  331. "title" => "Group Use",
  332. "page_callback" => "admin_display_groups_popup_show_group_use",
  333. "access_arguments" => array("can_edit_data_entry"),
  334. "page_settings" => array(
  335. "page_is_popup" => TRUE,
  336. "page_hide_report_error" => TRUE,
  337. ),
  338. "file" => menu_get_module_path("admin") . "/admin.groups.inc",
  339. "type" => MENU_TYPE_CALLBACK,
  340. );
  341. $items["admin/groups/process-all-definitions"] = array(
  342. "title" => "Process all Definitions",
  343. "page_callback" => "fp_render_form",
  344. "page_arguments" => array("admin_process_all_definitions_form"),
  345. "access_arguments" => array("can_edit_data_entry"),
  346. "page_settings" => array(
  347. "page_hide_report_error" => TRUE,
  348. "menu_links" => array(
  349. 0 => array(
  350. "text" => "Admin Console",
  351. "path" => "admin-tools/admin",
  352. "query" => "de_catalog_year=%DE_CATALOG_YEAR%",
  353. ),
  354. 1 => array(
  355. "text" => "Groups",
  356. "path" => "admin/groups",
  357. "query" => "de_catalog_year=%DE_CATALOG_YEAR%",
  358. ),
  359. ),
  360. ),
  361. "file" => menu_get_module_path("admin") . "/admin.groups.inc",
  362. "type" => MENU_TYPE_NORMAL_ITEM,
  363. );
  364. /////////////////////////////////////////////////
  365. /////////////////// Courses editing ////////////////
  366. $items["admin/courses"] = array(
  367. "title" => "Courses",
  368. "page_callback" => "admin_display_courses",
  369. "access_arguments" => array("can_access_data_entry"),
  370. "page_settings" => array(
  371. "page_hide_report_error" => TRUE,
  372. "menu_links" => array(
  373. 0 => array(
  374. "text" => "Admin Console",
  375. "path" => "admin-tools/admin",
  376. "query" => "de_catalog_year=%DE_CATALOG_YEAR%",
  377. ),
  378. ),
  379. ),
  380. "file" => menu_get_module_path("admin") . "/admin.courses.inc",
  381. "type" => MENU_TYPE_NORMAL_ITEM,
  382. );
  383. $items["admin/courses/edit-course"] = array(
  384. "title" => "Edit Course",
  385. "page_callback" => "fp_render_form",
  386. "page_arguments" => array("admin_edit_course_form"),
  387. "access_arguments" => array("can_edit_data_entry"),
  388. "page_settings" => array(
  389. "page_hide_report_error" => TRUE,
  390. "menu_links" => array(
  391. 0 => array(
  392. "text" => "Admin Console",
  393. "path" => "admin-tools/admin",
  394. "query" => "de_catalog_year=%DE_CATALOG_YEAR%",
  395. ),
  396. 1 => array(
  397. "text" => "Courses",
  398. "path" => "admin/courses",
  399. "query" => "de_catalog_year=%DE_CATALOG_YEAR%",
  400. ),
  401. ),
  402. ),
  403. "file" => menu_get_module_path("admin") . "/admin.courses.inc",
  404. "type" => MENU_TYPE_NORMAL_ITEM,
  405. );
  406. return $items;
  407. }
  408. /**
  409. * This page displays all the tools that the user has access to use.
  410. */
  411. function admin_display_tools_screen() {
  412. fp_add_css(fp_get_module_path("admin") . '/css/admin.css');
  413. $rtn = "";
  414. $rtn .= "<div class='display-admin-tools-page'>";
  415. $rtn .= fp_render_menu_block("", "admin-tools");
  416. $rtn .= "</div>";
  417. return $rtn;
  418. }
  419. /**
  420. * hook_cron
  421. */
  422. function admin_cron() {
  423. // Delete courses and groups which has been marked with "delete_flag = 1"
  424. $last_run = intval(variable_get("admin_last_run_delete_flag_removal", 0));
  425. $check_against = strtotime("NOW - 7 DAYS"); // don't run any more often than once every 7 days
  426. $c = 0;
  427. if ($check_against > $last_run) {
  428. $res = db_query("DELETE FROM draft_courses
  429. WHERE delete_flag = 1 ");
  430. $c = db_affected_rows($res);
  431. watchdog("admin", "Delete from flagged draft_courses db complete. $c items removed.", array(), WATCHDOG_DEBUG);
  432. $res = db_query("SELECT * FROM draft_groups
  433. WHERE delete_flag = 1 ");
  434. while ($cur = db_fetch_object($res)) {
  435. $group_id = $cur->group_id;
  436. $res2 = db_query("DELETE FROM draft_group_requirements WHERE group_id = ?", array($group_id));
  437. db_query("DELETE FROM draft_groups WHERE group_id = ?", array($group_id));
  438. $c++;
  439. }
  440. watchdog("admin", "Delete from flagged draft_groups db complete. $c items removed.", array(), WATCHDOG_DEBUG);
  441. variable_set("admin_last_run_delete_flag_removal", time());
  442. } // check against > last_run, so we should do it.
  443. } // hook_cron
  444. /**
  445. * This form will allow the user to duplicate an entire year's worth of data to a new
  446. * catalog year.
  447. *
  448. */
  449. function admin_duplicate_year_form() {
  450. $form = array();
  451. $m = 0;
  452. $form["mark" . $m++] = array(
  453. "value" => "<p>" . t("This form will allow you to duplicate an entire year's worth of data
  454. (courses, degrees, groups) into a new year. This is used to create a new
  455. year of data, based on the previous year, for example. <b>It will completely
  456. delete the 'destination' year data, if it already exists!</b> Use carefully.
  457. <br><br>
  458. The new year will be placed in DRAFT, and will not be visible in FlightPath
  459. until draft changes are applied.
  460. <br><br>
  461. <u>It would be wise</u> to back up your database before proceeding.") . "</p><hr>",
  462. );
  463. $form["source_year"] = array(
  464. "type" => "textfield",
  465. "label" => t("Source year:"),
  466. "size" => 10,
  467. "required" => TRUE,
  468. "description" => t("Enter the 4-digit source year you are copying FROM. For example,
  469. 2007. If you are copying from '2007-2008' then just enter
  470. 2007."),
  471. );
  472. $form["destination_year"] = array(
  473. "type" => "textfield",
  474. "label" => t("Destination year:"),
  475. "size" => 10,
  476. "required" => TRUE,
  477. "description" => t("Enter the 4-digit source year you are copying TO. <b><u>If this year
  478. all ready exists in the system, all data for this year will be DELETED.</u></b>
  479. If you are copying to '2009-2010' then just enter
  480. 2009."),
  481. );
  482. $form["passcode"] = array(
  483. "type" => "password",
  484. "label" => t("For added security, you must enter the Apply Draft Changes password:"),
  485. "required" => TRUE,
  486. "description" => t("This is a password set up in FlightPath's settings, to provide an extra layer
  487. of security for this powerful action. Draft changes will not actually be applied,
  488. this is simply used as an added layer of security."),
  489. );
  490. $form["submit"] = array(
  491. "type" => "submit",
  492. "value" => t("Submit"),
  493. "spinner" => TRUE,
  494. "description" => t("This action may take <b><u>several moments</u></b> to complete."),
  495. "prefix" => "<hr>",
  496. );
  497. return $form;
  498. }
  499. /**
  500. * Before we duplicate the year, make sure the password is correct.
  501. */
  502. function admin_duplicate_year_form_validate($form, &$form_state) {
  503. $values = $form_state["values"];
  504. // Check to make sure they entered the transfer passcode correctly.
  505. if ($values["passcode"] != variable_get("admin_transfer_passcode", sha1(mt_rand()))) {
  506. form_error("passcode", t("Sorry, but the password you entered is not correct. Check with the FlightPath administrator
  507. (or check the admin settings pages) to learn the password."));
  508. return;
  509. }
  510. }
  511. /**
  512. * This function should perform the actual copy of data!
  513. *
  514. * @param unknown_type $form
  515. * @param unknown_type $form_state
  516. */
  517. function admin_duplicate_year_form_submit($form, &$form_state) {
  518. set_time_limit (300); // Extend time limit since this may take a little while.
  519. $values = $form_state["values"];
  520. // Check to make sure they entered the transfer passcode correctly.
  521. $db = get_global_database_handler();
  522. // Okay, we made it this far, let's proceed with the copy!
  523. $new_year = $values["destination_year"];
  524. $old_year = $values["source_year"];
  525. $form_state['duplication']['src_catalog_year'] = $old_year;
  526. $form_state['duplication']['dest_catalog_year'] = $new_year;
  527. /////////////////////////////////////////////////////////////////////
  528. // We must first begin by deleting any entries for the new_year
  529. // from our tables. This is because we may have to run the parser
  530. // more than once while debugging and such.
  531. $res = db_query("DELETE FROM draft_courses WHERE `catalog_year`= ? ", $new_year);
  532. $res = db_query("DELETE FROM draft_degree_tracks WHERE `catalog_year` = ? ", $new_year);
  533. // For degrees, we first need to select all of the new_year degrees.
  534. $res = db_query("SELECT * FROM draft_degrees WHERE `catalog_year` = ? ", $new_year);
  535. while ($cur = db_fetch_array($res)) {
  536. $res2 = db_query("DELETE FROM draft_degree_requirements WHERE `degree_id`='{$cur["degree_id"]}' ");
  537. }
  538. $res = db_query("DELETE FROM draft_degrees WHERE `catalog_year`=? ", $new_year);
  539. // For groups, begin by selecting all the groups in that year...
  540. $res = db_query("SELECT * FROM draft_groups WHERE `catalog_year`=? ", $new_year);
  541. while ($cur = db_fetch_array($res))
  542. {
  543. // Now, select all the requirements and see if there are any sub groups...
  544. $res2 = db_query("SELECT * FROM draft_group_requirements WHERE `group_id`='{$cur["group_id"]}' ");
  545. while ($cur2 = db_fetch_array($res2))
  546. {
  547. if ($cur2["child_group_id"] > 0)
  548. {
  549. // Delete the child group.
  550. $res3 = db_query("DELETE FROM draft_group_requirements WHERE `group_id`='{$cur2["child_group_id"]}' ");
  551. }
  552. }
  553. // Now, delete the original requirement.
  554. $res3 = db_query("DELETE FROM draft_group_requirements WHERE `group_id`='{$cur["group_id"]}' ");
  555. }
  556. $res = db_query("DELETE FROM draft_groups WHERE `catalog_year`=? ", $new_year);
  557. //////////////////////////////////////////////////////////////////////////
  558. // Okay, we have deleted any possible old entries for the new year.
  559. /////////////////////////////////////////////////////////////////////////
  560. // Our first step is to copy all of the courses from the old_year to the new_year.
  561. $res = db_query("SELECT * FROM draft_courses WHERE `catalog_year`=? ", $old_year);
  562. while ($cur = db_fetch_array($res))
  563. {
  564. extract($cur, 3, "db");
  565. $course = new Course($db_course_id, false, $db, false, $old_year);
  566. $course->subject_id = $db_subject_id;
  567. $course->course_num = $db_course_num;
  568. $course->db_exclude = $db_exclude;
  569. $course->min_hours = $db_min_hours;
  570. $course->max_hours = $db_max_hours;
  571. $course->repeat_hours = $db_repeat_hours;
  572. $course->school_id = $db_school_id;
  573. // Now, duplicate it for the new_year.
  574. $db->duplicate_course_for_year($course, $new_year);
  575. // Store what courses we are working on, for other modules.
  576. $form_state['courses'][] = $db_course_id;
  577. }
  578. //////////////////////////////////////////////////////////////////////////
  579. // Now, let's copy over the groups.
  580. $group_id_array = array();
  581. $subgroup_id_array = array();
  582. $res = db_query("SELECT * FROM draft_groups WHERE `catalog_year`=? ", $old_year);
  583. while ($cur = db_fetch_array($res))
  584. {
  585. extract($cur, 3, "db");
  586. // First, let's request a new group ID for this new group.
  587. $new_group_id = $db->request_new_group_id();
  588. $group_id_array[$db_group_id] = $new_group_id;
  589. //$db_data_entry_comment = mysql_real_escape_string($db_data_entry_comment);
  590. // Now, let's insert this top-level group back into the table
  591. // as the new_year, with the new_group_id.
  592. $query = "INSERT INTO draft_groups(`group_id`,`group_name`,
  593. `title`,`public_note`,`definition`,`icon_filename`,`catalog_year`,
  594. `priority`,`delete_flag`,`data_entry_comment`, `catalog_repeat`,school_id)
  595. VALUES (?,?,?,?,?,?,?,?,?,?,?,?) ";
  596. $res2 = db_query($query, $new_group_id,$db_group_name,$db_title,$db_public_note,
  597. $db_definition,$db_icon_filename,$new_year,
  598. $db_priority,$db_delete_flag,$db_data_entry_comment,$db_catalog_repeat,$db_school_id);
  599. // Okay, now we need to go through the requirements for the group, and copy
  600. // those over to the new_year.
  601. $res3 = db_query("SELECT * FROM draft_group_requirements
  602. WHERE `group_id`='$db_group_id' ");
  603. while($cur3 = db_fetch_array($res3))
  604. {
  605. extract($cur3, 3, "db3");
  606. $child_group_id = 0;
  607. // Was there a child_group (a branch)? If so, we need to copy that
  608. // over too, with a new child_group_id.
  609. if ($db3_child_group_id > 0)
  610. {
  611. // First, create the child group...
  612. $new_sub_group_id = $db->request_new_group_id();
  613. $subgroup_id_array[$db3_child_group_id] = $new_sub_group_id;
  614. $res4 = db_query("SELECT * FROM draft_group_requirements
  615. WHERE `group_id`='$db3_child_group_id' ");
  616. while($cur4 = db_fetch_array($res4))
  617. {
  618. extract($cur4, 3, "db4");
  619. $res5 = db_query("INSERT INTO draft_group_requirements
  620. (`group_id`,`course_id`,`course_min_grade`,
  621. `course_repeats`,`attributes`,`data_entry_value`)
  622. VALUES (?,?,?,?,?,?) ",
  623. $new_sub_group_id,$db4_course_id,
  624. $db4_course_min_grade,$db4_course_repeats,$db4_attributes,
  625. $db4_data_entry_value);
  626. }
  627. // Now, add the replace the db3_child_group_id with this new id
  628. // so it will get added as a requirement.
  629. $child_group_id = $new_sub_group_id;
  630. }
  631. // Add the row into the table...
  632. $res5 = db_query("INSERT INTO draft_group_requirements
  633. (`group_id`,`course_id`,`course_min_grade`,
  634. `course_repeats`,`attributes`,`data_entry_value`,`child_group_id`)
  635. VALUES (?,?,?,?,?,?,?) ",
  636. array($new_group_id,$db3_course_id,
  637. $db3_course_min_grade,$db3_course_repeats,$db3_attributes,
  638. $db3_data_entry_value,$child_group_id));
  639. }
  640. }
  641. // Store what groups we are working on, for other modules.
  642. $form_state['groups'] = $group_id_array;
  643. /////////////////////////////////////////////////////////////////////
  644. // Now, on to transfering the degrees.
  645. // We will have to use the groupIDArray we constructed earlier, which
  646. // looks like $arr[old_id] = new_id.
  647. // Do the tracks first, since they are easier and straight forward...
  648. $res = db_query("SELECT * FROM draft_degree_tracks WHERE `catalog_year`='$old_year' ");
  649. while ($cur = db_fetch_array($res))
  650. {
  651. extract($cur, 3, "db");
  652. $res2 = db_query("INSERT INTO draft_degree_tracks
  653. (`catalog_year`,`major_code`,`track_code`,`track_title`,
  654. `track_short_title`,`track_description`,school_id)
  655. VALUES
  656. (?,?,?,?,?,?,?) ",
  657. $new_year,$db_major_code,$db_track_code,$db_track_title,
  658. $db_track_short_title,$db_track_description,$db_school_id);
  659. }
  660. // Now, let's do the degrees themselves.
  661. $res = db_query("SELECT * FROM draft_degrees WHERE `catalog_year`='$old_year' ");
  662. while ($cur = db_fetch_array($res))
  663. {
  664. extract($cur, 3, "db");
  665. $new_degree_id = $db->request_new_degree_id();
  666. // Store what degrees we are working on, for other modules.
  667. $form_state['degrees'][] = array(
  668. 'src' => $db_degree_id,
  669. 'src_catalog_year' => $old_year,
  670. 'school_id' => $db_school_id,
  671. 'dest' => $new_degree_id,
  672. 'dest_major_code' => $db_major_code,
  673. 'dest_catalog_year' => $new_year,
  674. );
  675. // add in the top-level degree to the table.
  676. $res2 = db_query("INSERT INTO draft_degrees
  677. (degree_id, major_code, degree_type, degree_level, degree_class, title,
  678. semester_titles_csv, catalog_year, exclude, public_note,
  679. allow_dynamic, advising_weight, override_degree_hours, min_tracks, max_tracks, default_tracks, track_selection_config, school_id)
  680. VALUES
  681. (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
  682. ", $new_degree_id,$db_major_code,$db_degree_type, $db_degree_level, $db_degree_class, $db_title,
  683. $db_semester_titles_csv, $new_year, $db_exclude, $db_public_note,
  684. $db_allow_dynamic, $db_advising_weight, $db_override_degree_hours, $db_min_tracks, $db_max_tracks, $db_default_tracks, $db_track_selection_config,$db_school_id);
  685. // now, pull out all of the degree_requirements.
  686. $res3 = db_query("SELECT * FROM draft_degree_requirements
  687. WHERE degree_id = ? ", array($db_degree_id));
  688. while($cur3 = db_fetch_array($res3))
  689. {
  690. extract($cur3, 3, "db3");
  691. // If there is a required group, we must convert it to the
  692. // new groupID !
  693. $required_group_id = intval($db3_group_id);
  694. if ($db3_group_id > 0 && trim($db3_group_id) != "")
  695. {
  696. $required_group_id = $group_id_array[$db3_group_id];
  697. if ($required_group_id < 1 || $required_group_id == "")
  698. {
  699. //die("could not find new group for $old_year $db3_group_id! Group id is $required_group_id");
  700. fp_add_message(t("Couldn't find the specified group with ID $db3_group_id in catalog year $old_year, required by degree with ID $db_degree_id ($db_major_code). The group was possibly deleted?
  701. Be aware that any degrees in the new year will be missing this group requirement."), 'error');
  702. }
  703. }
  704. $res4 = db_query("INSERT INTO draft_degree_requirements
  705. (degree_id, semester_num, group_id, group_requirement_type,
  706. group_hours_required, group_min_hours_allowed, group_min_grade, course_id,
  707. course_min_grade, course_requirement_type, data_entry_value)
  708. VALUES
  709. (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
  710. ", $new_degree_id, $db3_semester_num, $required_group_id, $db3_group_requirement_type,
  711. $db3_group_hours_required, $db3_group_min_hours_allowed, $db3_group_min_grade, $db3_course_id,
  712. $db3_course_min_grade, $db3_course_requirement_type, $db3_data_entry_value);
  713. }
  714. }
  715. watchdog("admin", "Duplicated all degree/group/courses data from $old_year to $new_year");
  716. fp_add_message(t("The copy operation is now completed. You may view the new year
  717. by using the Data Entry links on the admin main menu. Remember, you must
  718. apply draft changes before they will be visible in FlightPath."));
  719. }
  720. /**
  721. * This is a systems settings form, which lets
  722. * the user edit advising variabled for FlightPath.
  723. */
  724. function admin_advising_settings_form($school_id = 0) {
  725. $form = array();
  726. $school_id = intval($school_id);
  727. $fs = ""; // The field name suffix. We will add this to the end of all of our field names. If this is the default school, leave blank.
  728. if (module_enabled("schools")) {
  729. $school_name = schools_get_school_name_for_id($school_id);
  730. fp_set_title(t("Edit %school school advising settings", array('%school' => $school_name)));
  731. if ($school_id !== 0) {
  732. $fs = "~~school_" . $school_id;
  733. }
  734. }
  735. $form['school_id'] = array(
  736. 'type' => 'hidden',
  737. 'value' => $school_id,
  738. );
  739. $form["available_advising_term_ids" . $fs] = array(
  740. "type" => "textarea",
  741. "rows" => 2,
  742. "label" => t("Available advising term id(s)"),
  743. "value" => fp_space_csv(variable_get_for_school("available_advising_term_ids", "", $school_id, TRUE)),
  744. "description" => t("These are the terms for which advisors may advise a student to take
  745. a course. They should follow the structure established on the
  746. school data settings page.
  747. Separate term id's by commas. Ex: 200940, 200941, 200960. Make sure to enter
  748. in the order that they should appear in FlightPath."),
  749. );
  750. $form["advising_term_id" . $fs] = array(
  751. "type" => "textarea",
  752. "rows" => 2,
  753. "label" => t("Default advising term id"),
  754. "value" => fp_space_csv(variable_get_for_school("advising_term_id", "", $school_id, TRUE)),
  755. "description" => t("Of the available term ids above, this is the default that FlightPath
  756. is set to when an advisor logs in. Ex: 200940.
  757. <br><strong>Only enter one Term ID in this box.</strong>"),
  758. );
  759. $form["current_catalog_year" . $fs] = array(
  760. "type" => "textfield",
  761. "size" => 10,
  762. "label" => t("Current catalog year"),
  763. "value" => variable_get_for_school("current_catalog_year", "", $school_id, TRUE),
  764. "description" => t("This is the year which What If loads degrees from, as well as other important functions.
  765. Only change this once you have fully loaded a new catalog year."),
  766. );
  767. $form["current_draft_catalog_year" . $fs] = array(
  768. "type" => "textfield",
  769. "size" => 10,
  770. "label" => t("Current DRAFT catalog year"),
  771. "value" => variable_get_for_school("current_draft_catalog_year", "", $school_id, TRUE),
  772. "description" => t("While in Draft mode, this is the year which Blank Degree Search loads degrees from. What If
  773. mode will always use the Current catalog year, set above.
  774. You may change this while working on a new catalog. It will not affect any other
  775. users of the system. While not working on a new catalog, set this
  776. to the same as the Current catalog year."),
  777. );
  778. $form["not_released_grades_terms" . $fs] = array(
  779. "type" => "textarea",
  780. "rows" => 2,
  781. "label" => t("NOT released grades terms"),
  782. "value" => fp_space_csv(variable_get_for_school("not_released_grades_terms", "", $school_id, TRUE)),
  783. "description" => t("Enter the term_id's, separated by commas,
  784. which are NOT released and should NOT be visible to either advisors or students.
  785. Coures in these terms will only show midterm grades or no grades at all.
  786. Ex: 201240, 201240:S1") . "<br>" . t("If left blank, grades will be visible to
  787. students and advisors as soon as they appear in the database."),
  788. );
  789. return $form;
  790. }
  791. /**
  792. * Convienence function to get semester's default regular name.
  793. */
  794. function admin_get_semester_name($semester_num) {
  795. $semester = new Semester($semester_num);
  796. $title = $semester->title;
  797. /**
  798. $ar = array(t("Freshman Year"), t("Sophomore Year"), t("Junior Year"), t("Senior Year"));
  799. $s = $ar[$semester_num];
  800. if ($s == "")
  801. {
  802. $s = t("Year") . " " . ($semester_num + 1);
  803. }
  804. */
  805. return $title;
  806. }
  807. /**
  808. * This form lets the user apply draft changes (if they can supply the passcode)
  809. */
  810. function admin_apply_draft_changes_form() {
  811. $form = array();
  812. $m = 0;
  813. $form["mark" . $m++] = array(
  814. "type" => "markup",
  815. "value" => t("You can use this form to apply your draft changes to the production database, making changes
  816. to degrees, courses, and groups visible to all users of the system."),
  817. );
  818. $form["passcode"] = array(
  819. "type" => "password",
  820. "label" => t("For added security, you must enter the Apply Draft Changes password:"),
  821. "required" => TRUE,
  822. "description" => t("This is a password set up in FlightPath's System Settings, to provide an extra layer
  823. of security for this powerful action."),
  824. );
  825. $form["submit"] = array(
  826. "type" => "submit",
  827. "value" => t("Submit"),
  828. "spinner" => TRUE,
  829. "description" => t("Note: This action may take several seconds to complete. Do not close this tab or refresh the browser."),
  830. "prefix" => "<hr>",
  831. );
  832. return $form;
  833. }
  834. /**
  835. * Before we apply changes, make sure the password is correct.
  836. */
  837. function admin_apply_draft_changes_form_validate($form, &$form_state) {
  838. $values = $form_state["values"];
  839. // Check to make sure they entered the transfer passcode correctly.
  840. if ($values["passcode"] != variable_get("admin_transfer_passcode", sha1(mt_rand()))) {
  841. form_error("passcode", t("Sorry, but the password you entered is not correct. Check with the FlightPath administrator
  842. (or check the admin settings pages) to learn the password."));
  843. return;
  844. }
  845. }
  846. /**
  847. * Handles the actual moving of draft courses into production.
  848. */
  849. function admin_apply_draft_changes_form_submit($form, $form_submit) {
  850. $values = $form_submit["values"];
  851. $db = get_global_database_handler();
  852. $de_catalog_year = admin_get_de_catalog_year();
  853. // Keep the script from timing out prematurely...
  854. set_time_limit(99999); // around 27 hours (so it runs a really long time).
  855. // First, set maintenance mode...
  856. variable_set("maintenance_mode", TRUE);
  857. // Okay, so what we gotta do is truncate the production tables,
  858. // then copy the draft tables in.
  859. $table_array = array(
  860. "courses",
  861. "degree_requirements",
  862. "degree_tracks",
  863. "degrees",
  864. "group_requirements",
  865. "groups",
  866. );
  867. foreach($table_array as $table_name) {
  868. $draft_table_name = "draft_$table_name";
  869. // First, truncate existing...
  870. $query = "truncate table `$table_name`";
  871. $res = db_query($query);
  872. // Now, copy in draft changes...
  873. $query = "INSERT INTO `$table_name`
  874. SELECT * FROM `$draft_table_name` ";
  875. $res = db_query($query);
  876. }
  877. $db2 = new DatabaseHandler();
  878. // Now, we need to go through the draft_instructions table,
  879. // and perform each instruction one at a time.
  880. $res = db_query("SELECT * FROM draft_instructions
  881. ORDER BY `id` ");
  882. while($cur = db_fetch_array($res))
  883. {
  884. $instruction = trim($cur["instruction"]);
  885. $temp = explode(",",$instruction);
  886. if (trim($temp[0]) == "update_course_id") {
  887. $db2->update_course_id(trim($temp[1]), trim($temp[2]), trim($temp[3]));
  888. }
  889. if (trim($temp[0]) == "update_course_requirement_from_name") {
  890. $db2->update_course_requirement_from_name(trim($temp[1]), trim($temp[2]), trim($temp[3]), trim($temp[4]));
  891. }
  892. // TODO: Maybe invoke another hook here, to let other modules act on the instruction?
  893. }
  894. // Once this is done, truncate the draft_instructions table.
  895. $res = db_query("TRUNCATE TABLE draft_instructions");
  896. // Invoke a hook to allow other modules to apply_draft_changes as well
  897. invoke_hook("apply_draft_changes");
  898. // Rebuild our course cache file.
  899. unset($_SESSION['fp_cache_course_inventory_last_generated']);
  900. if (file_exists(fp_get_files_path() . "/cache_data/courses_serialized.info")) {
  901. $x = unlink(fp_get_files_path() . "/cache_data/courses_serialized.info");
  902. if (!$x) {
  903. fpm("Cannot delete cache_data/courses_serialized.info under custom/files. Permission error or file does not exist?");
  904. watchdog("system", "Cannot delete cache_data/courses_serialized.info under custom/files. Permission error or file does not exist?", array(), WATCHDOG_ERROR);
  905. }
  906. }
  907. variable_set('cache_course_inventory_last_generated', 0); // reset this so it will be regenerated.
  908. // Builds new courses cache file on the hard drive.
  909. system_reload_and_cache_course_inventory();
  910. // And we are done! Set maintenance mode back to none
  911. variable_set("maintenance_mode", FALSE);
  912. // Send emails to notify programmers...
  913. $notify = variable_get("notify_apply_draft_changes_email_address", "");
  914. if ($notify != "") {
  915. mail($notify, "FlightPath Apply Draft Changes", "Someone has applied draft changes to FlightPath, which updated degree plans, groups, and courses.");
  916. }
  917. fp_add_message(t("Successfully updated the production database with draft changes. Your changes are now live and visible on production for all users."));
  918. watchdog("admin", "Draft changes applied.");
  919. }
  920. /**
  921. * Get the "de_catalog_year" from the REQUEST.
  922. * If it's not there or invalid, pull it from our system settings.
  923. */
  924. function admin_get_de_catalog_year($bool_set_earliest_if_blank = TRUE, $school_id = 0) {
  925. global $current_student_id;
  926. $db = get_global_database_handler();
  927. if ($current_student_id) {
  928. $school_id = $db->get_school_id_for_student_id($current_student_id);
  929. }
  930. $de_catalog_year = @$_REQUEST["de_catalog_year"];
  931. if ($bool_set_earliest_if_blank) {
  932. if (!$de_catalog_year || $de_catalog_year < variable_get_for_school("earliest_catalog_year", 2006, $school_id)) {
  933. $de_catalog_year = variable_get_for_school("earliest_catalog_year", 2006, $school_id);
  934. }
  935. }
  936. return $de_catalog_year;
  937. }
  938. /**
  939. * This is an implementation of hook_menu_handle_replacement_pattern.
  940. * It will search for and replace replacement patterns which we are aware of it in $str.
  941. */
  942. function admin_menu_handle_replacement_pattern($str) {
  943. if (strpos($str, "%DE_CATALOG_YEAR%") !== 0) {
  944. // It contains this replacement pattern!
  945. $str = str_replace("%DE_CATALOG_YEAR%", admin_get_de_catalog_year(), $str);
  946. }
  947. if (strpos($str, "%SEV_FILTER%") !== 0) {
  948. // It contains this replacement pattern!
  949. $str = str_replace("%SEV_FILTER%", @$_GET["sev_filter"], $str);
  950. }
  951. if (strpos($str, "%TYPE_FILTER%") !== 0) {
  952. // It contains this replacement pattern!
  953. $str = str_replace("%TYPE_FILTER%", @$_GET["type_filter"], $str);
  954. }
  955. if (strpos($str, "%PAGE%") !== 0) {
  956. // It contains this replacement pattern!
  957. $str = str_replace("%PAGE%", @$_GET["page"], $str);
  958. }
  959. return $str;
  960. }
  961. function admin_perm() {
  962. return array(
  963. "can_access_admin_tools" => array(
  964. "title" => t("Access Admin Tools"),
  965. "description" => t("Allow the user to access the Admin Tools screen."),
  966. ),
  967. "can_access_admin" => array(
  968. "title" => t("Access administrative console"),
  969. "description" => t("This is a powerful permission! This allows a
  970. user to access the 'admin console' for FlightPath."),
  971. ),
  972. "can_edit_urgent_message" => array(
  973. "title" => t("Edit urgent message"),
  974. "description" => t("The user may edit the 'Urgent Message' which appears at the top of every page, if set."),
  975. ),
  976. "can_access_data_entry" => array(
  977. "title" => t("Access Data Entry"),
  978. "description" => t("The user can access (view) the data-entry portion of the admin console. Degree plans, groups, and courses."),
  979. ),
  980. "can_edit_data_entry" => array(
  981. "title" => t("Edit Data Entry"),
  982. "description" => t("This is a powerful permission! The user can edit degree plans, groups, and courses."),
  983. ),
  984. "can_delete_data_entry" => array(
  985. "title" => t("Delete Data Entry items"),
  986. "description" => t("This is a VERY powerful permission! The user can delete degree plans, groups, and courses."),
  987. ),
  988. "can_view_advanced" => array(
  989. "title" => t("View advanced"),
  990. "description" => t("The user may see advanced information on-screen, for example, internal ID numbers for degrees and courses."),
  991. ),
  992. "can_apply_draft_changes" => array(
  993. "title" => t("Apply draft changes"),
  994. "description" => t("The user may move draft changes into production."),
  995. ),
  996. "can_edit_advising_settings" => array(
  997. "title" => t("Edit advising settings"),
  998. "description" => t("The user may edit advising settings, like available term IDs and the current catalog year."),
  999. ),
  1000. "display_watchdog" => array(
  1001. "title" => t("View watchdog (log) entries"),
  1002. "description" => t("The user may view the recent watchdog log entries. This represents a security concern, so give this only to trusted users."),
  1003. ),
  1004. );
  1005. }
  1006. /**
  1007. * Meant to be fed into "fp_system_settings_form()", this function
  1008. * returns an array which will automatically save values to our "variables" table.
  1009. */
  1010. function admin_urgent_message_form() {
  1011. $form = array();
  1012. $form["mark_top"] = array(
  1013. "type" => "markup",
  1014. "value" => "<p>" . t("Any message you enter here will be displayed at the top of every page <b>for all users</b> in the system.
  1015. This is used to alert users that the system is about to be taken offline, or any other urgently-needed information.") . "</p>",
  1016. );
  1017. $form["urgent_msg"] = array(
  1018. "type" => "textarea",
  1019. "label" => "Global Urgent Message:",
  1020. "value" => variable_get("urgent_msg", ""),
  1021. 'description' => t("To delete this message, simple delete all the text in this box and save."),
  1022. );
  1023. return $form;
  1024. }
  1025. /**
  1026. * Display the details of a particular watchdog entry, specified by its table id.
  1027. */
  1028. function admin_display_watchdog_entry($wid) {
  1029. $rtn = "";
  1030. fp_add_css(fp_get_module_path("admin") . '/css/admin.css');
  1031. $severity_array = array(
  1032. 5 => "notice",
  1033. 1 => "alert",
  1034. 3 => "error",
  1035. 7 => "debug",
  1036. );
  1037. $res = db_query("SELECT * FROM watchdog WHERE wid = '?' ", $wid);
  1038. $cur = db_fetch_object($res);
  1039. $msg = t($cur->message, unserialize($cur->variables));
  1040. $severity = $severity_array[$cur->severity];
  1041. $when = format_date(convert_time($cur->timestamp), "short");
  1042. // Display
  1043. $rtn .= "
  1044. <br>
  1045. <div class='watchdog-entry'>
  1046. <div class='watchdog-field'>
  1047. <label>ID:</label>
  1048. $cur->wid
  1049. </div>
  1050. <div class='watchdog-field'>
  1051. <label>Type:</label>
  1052. $cur->type
  1053. </div>
  1054. <div class='watchdog-field'>
  1055. <label>Time:</label>
  1056. $when ($cur->timestamp)
  1057. </div>
  1058. <div class='watchdog-field'>
  1059. <label>Severity:</label>
  1060. $severity
  1061. </div>
  1062. <div class='watchdog-field'>
  1063. <label>User:</label>
  1064. $cur->user_name | id: $cur->user_id | cwid: $cur->cwid | is_student: $cur->is_student | is_faculty: $cur->is_faculty
  1065. </div>
  1066. <div class='watchdog-field'>
  1067. <label>IP:</label>
  1068. $cur->ip
  1069. </div>
  1070. <div class='watchdog-field'>
  1071. <label>Location:</label>
  1072. $cur->location
  1073. </div>
  1074. <div class='watchdog-field'>
  1075. <label>Ref:</label>
  1076. $cur->referer
  1077. </div>
  1078. <hr>
  1079. <div class='watchdog-field'>
  1080. <label class='block'>Message:</label>
  1081. $msg
  1082. </div>
  1083. <div class='watchdog-field'>
  1084. <label class='block'>Extra:</label>
  1085. $cur->extra_data
  1086. </div>
  1087. </div>
  1088. ";
  1089. return $rtn;
  1090. }
  1091. /**
  1092. * Displays recent watchdog entries, from the watchdog table
  1093. *
  1094. */
  1095. function z__admin_display_watchdog() {
  1096. fp_add_css(fp_get_module_path("admin") . '/css/admin.css');
  1097. $rtn = "";
  1098. $rtn .= "<p>View recent watchdog entries</p>";
  1099. $severity_array = array(
  1100. 5 => "notice",
  1101. 1 => "alert",
  1102. 3 => "error",
  1103. 7 => "debug",
  1104. );
  1105. $results_per_page = 50;
  1106. $type_line = $severity_line = $limit_start = "";
  1107. @$sev_filter = $_GET["sev_filter"];
  1108. @$type_filter = $_GET["type_filter"];
  1109. @$page = $_GET["page"];
  1110. $limit_start = 0;
  1111. if ($page != "" && is_numeric($page)) {
  1112. $limit_start = $results_per_page * ($page - 1);
  1113. }
  1114. else {
  1115. $page = 1;
  1116. }
  1117. // Filters:
  1118. $rtn .= "<form method='GET' action='" . fp_url("admin/config/watchdog") . "' class='watchdog-filters'>
  1119. ";
  1120. $rtn .= "Filter by:
  1121. <span class='type-filter'>
  1122. Type:
  1123. <select name='type_filter'>
  1124. <option value=''>-Any-</option>";
  1125. $res = db_query("SELECT distinct(type) as type
  1126. FROM watchdog
  1127. ORDER BY type");
  1128. while ($cur = db_fetch_object($res)) {
  1129. $sel = ($type_filter == $cur->type) ? "selected" : "";
  1130. $rtn .= "<option value='$cur->type' $sel>$cur->type</option>";
  1131. }
  1132. $rtn .= "</select>
  1133. </span>";
  1134. $rtn .= "
  1135. <span class='severity-filter'>
  1136. Severity:
  1137. <select name='sev_filter'>
  1138. <option value=''>-Any-</option>";
  1139. foreach ($severity_array as $key => $value) {
  1140. $sel = "";
  1141. if ($sev_filter == $key) $sel = "selected";
  1142. $rtn .= "<option value='$key' $sel>$value</option>";
  1143. }
  1144. $rtn .= "</select>
  1145. </span>";
  1146. $rtn .= "<input type='submit' value='&gt;'>";
  1147. // Hack if clean URLs are not enabled:
  1148. $rtn .= "<input type='hidden' name='q' value='admin/config/watchdog'>";
  1149. $rtn .= "</form>";
  1150. $params = array();
  1151. if (@$_GET["type_filter"] != "") {
  1152. //$type_line = " AND type = '" . mysql_real_escape_string($_GET["type_filter"]) . "' ";
  1153. $type_line = " AND `type` = :type ";
  1154. $params[":type"] = $_GET["type_filter"];
  1155. }
  1156. if (@$_GET["sev_filter"] != "") {
  1157. //$severity_line = " AND severity = '" . mysql_real_escape_string($_GET["sev_filter"]) . "' ";
  1158. $severity_line = " AND severity = :sev ";
  1159. $params[":sev"] = $_GET["sev_filter"];
  1160. }
  1161. $pol = "even";
  1162. $rtn .= "<table class='watchdog-table' cellspacing='0' cellpadding='4'>
  1163. <tr>
  1164. <th>ID</th>
  1165. <th>When</th>
  1166. <th>Type</th>
  1167. <th>Msg</th>
  1168. <th>Severity</th>
  1169. <th>User</th>
  1170. </tr>";
  1171. // Okay, let's display the recent watchdog entries.
  1172. $query = "SELECT * FROM watchdog
  1173. WHERE 1
  1174. $type_line
  1175. $severity_line
  1176. ORDER BY wid DESC
  1177. ";
  1178. $res = db_query($query . " LIMIT $limit_start, $results_per_page", $params);
  1179. while ($cur = db_fetch_object($res)) {
  1180. $pol = ($pol == "even") ? "odd" : "even";
  1181. $o_msg = t($cur->message, unserialize($cur->variables));
  1182. $o_type = $cur->type;
  1183. // shorten msg if necessary
  1184. $msg = substr(strip_tags($o_msg), 0, 130);
  1185. if ($msg != $o_msg) {
  1186. $msg = trim($msg) . "...";
  1187. }
  1188. $type = substr($o_type, 0, 20);
  1189. if ($type != $o_type) {
  1190. $type = trim($type) . "...";
  1191. }
  1192. $severity = $severity_array[$cur->severity];
  1193. $when = format_date(convert_time($cur->timestamp), "short");
  1194. $rtn .= "
  1195. <tr class='row-$pol row-$severity'>
  1196. <td valign='top'>" . l($cur->wid, "admin/config/watchdog/$cur->wid", "sev_filter=$sev_filter&type_filter=$type_filter&page=$page") . "</td>
  1197. <td valign='top'>$when</td>
  1198. <td valign='top'>$type</td>
  1199. <td valign='top'>$msg</td>
  1200. <td valign='top'>$severity</td>
  1201. <td valign='top'>$cur->user_name</td>
  1202. </tr>
  1203. ";
  1204. }
  1205. $rtn .= "</table>";
  1206. // Now, do the page
  1207. // Figure out the total number of results
  1208. $total = db_result(db_query("SELECT count(wid) as count
  1209. FROM watchdog WHERE 1
  1210. $type_line
  1211. $severity_line", $params));
  1212. // Now, divide by the number of results per page.
  1213. $pages = ceil($total / $results_per_page);
  1214. $base_query = "sev_filter=$sev_filter&type_filter=$type_filter";
  1215. $rtn .= "<div class='fp-pager'>";
  1216. if ($page > 1) {
  1217. $rtn .= "<span class='pager-link pager-first'>" . l("&laquo; first", "admin/config/watchdog", $base_query . "&page=1") . "</span>";
  1218. $rtn .= "<span class='pager-link pager-prev'>" . l("&lt; prev", "admin/config/watchdog", $base_query . "&page=" . ($page - 1)) . "</span>";
  1219. }
  1220. else {
  1221. $rtn .= "<span class='pager-link pager-first'>&laquo; first</span>";
  1222. $rtn .= "<span class='pager-link pager-prev'>&lt; prev</span>";
  1223. }
  1224. // page numbers here
  1225. // Let's get the previous X page numbers, and next X (if possible)
  1226. $start_page_num = $page - 5;
  1227. if ($start_page_num < 1) $start_page_num = 1;
  1228. $end_page_num = $page + 5;
  1229. if ($end_page_num > $pages) $end_page_num = $pages;
  1230. if ($start_page_num > 1) {
  1231. $rtn .= "<span class='pager-elip'>...</span>";
  1232. }
  1233. for ($t = $start_page_num; $t <= $end_page_num; $t++) {
  1234. if ($page == $t) {
  1235. // current page
  1236. $rtn .= "<span class='pager-link pager-number pager-current'>$t</span>";
  1237. }
  1238. else {
  1239. $rtn .= "<span class='pager-link pager-number'>" . l($t, "admin/config/watchdog", $base_query . "&page=$t") . "</span>";
  1240. }
  1241. }
  1242. if ($end_page_num < $pages) {
  1243. $rtn .= "<span class='pager-elip'>...</span>";
  1244. }
  1245. if ($page < $pages) {
  1246. $rtn .= "<span class='pager-link pager-next'>" . l("next &gt;", "admin/config/watchdog", $base_query . "&page=" . ($page + 1)) . "</span>";
  1247. $rtn .= "<span class='pager-link pager-last'>" . l("last &raquo;", "admin/config/watchdog", $base_query . "&page=$pages") . "</span>";
  1248. }
  1249. else {
  1250. $rtn .= "<span class='pager-link pager-next'>next &gt;</span>";
  1251. $rtn .= "<span class='pager-link pager-last'>last &raquo;</span>";
  1252. }
  1253. $rtn .= "</div>";
  1254. return $rtn;
  1255. }
  1256. function admin_display_watchdog() {
  1257. fp_add_css(fp_get_module_path("admin") . '/css/admin.css');
  1258. $rtn = "";
  1259. $rtn .= "<p>View recent watchdog entries</p>";
  1260. $severity_array = array(
  1261. 5 => "notice",
  1262. 1 => "alert",
  1263. 3 => "error",
  1264. 7 => "debug",
  1265. );
  1266. $results_per_page = 50;
  1267. $type_line = $severity_line = $limit_start = "";
  1268. @$sev_filter = $_GET["sev_filter"];
  1269. @$type_filter = $_GET["type_filter"];
  1270. @$page = intval($_GET["page"]);
  1271. $limit_start = 0;
  1272. if ($page > 0) {
  1273. $limit_start = $results_per_page * ($page - 1);
  1274. }
  1275. // Filters:
  1276. $rtn .= "<form method='GET' action='" . fp_url("admin/config/watchdog") . "' class='watchdog-filters'>
  1277. ";
  1278. $rtn .= "Filter by:
  1279. <span class='type-filter'>
  1280. Type:
  1281. <select name='type_filter'>
  1282. <option value=''>-Any-</option>";
  1283. $res = db_query("SELECT distinct(type) as type
  1284. FROM watchdog
  1285. ORDER BY type");
  1286. while ($cur = db_fetch_object($res)) {
  1287. $sel = ($type_filter == $cur->type) ? "selected" : "";
  1288. $rtn .= "<option value='$cur->type' $sel>$cur->type</option>";
  1289. }
  1290. $rtn .= "</select>
  1291. </span>";
  1292. $rtn .= "
  1293. <span class='severity-filter'>
  1294. Severity:
  1295. <select name='sev_filter'>
  1296. <option value=''>-Any-</option>";
  1297. foreach ($severity_array as $key => $value) {
  1298. $sel = "";
  1299. if ($sev_filter == $key) $sel = "selected";
  1300. $rtn .= "<option value='$key' $sel>$value</option>";
  1301. }
  1302. $rtn .= "</select>
  1303. </span>";
  1304. $rtn .= "<input type='submit' value='&gt;'>";
  1305. // Hack if clean URLs are not enabled:
  1306. $rtn .= "<input type='hidden' name='q' value='admin/config/watchdog'>";
  1307. $rtn .= "</form>";
  1308. $params = array();
  1309. if (@$_GET["type_filter"] != "") {
  1310. //$type_line = " AND type = '" . mysql_real_escape_string($_GET["type_filter"]) . "' ";
  1311. $type_line = " AND `type` = :type ";
  1312. $params[":type"] = $_GET["type_filter"];
  1313. }
  1314. if (@$_GET["sev_filter"] != "") {
  1315. //$severity_line = " AND severity = '" . mysql_real_escape_string($_GET["sev_filter"]) . "' ";
  1316. $severity_line = " AND severity = :sev ";
  1317. $params[":sev"] = $_GET["sev_filter"];
  1318. }
  1319. $pol = "even";
  1320. $table_headers = array();
  1321. $table_headers[] = array("label" => "ID", "field" => "wid");
  1322. $table_headers[] = array("label" => "When", "field" => "a.timestamp");
  1323. $table_headers[] = array("label" => "Type", "field" => "a.type");
  1324. $table_headers[] = array("label" => "Msg");
  1325. $table_headers[] = array("label" => "Severity", "field" => "a.severity");
  1326. $table_headers[] = array("label" => "User", "field" => "user_name");
  1327. // Set our initial sort, if none is already set.
  1328. theme_table_header_sortable_set_initial_sort("wid", 'DESC');
  1329. $rtn .= "<table class='watchdog-table' cellspacing='0' cellpadding='4'>";
  1330. // Draw our our table headers, with links....
  1331. $rtn .= theme_table_header_sortable($table_headers);
  1332. // Get our order by clause based on selected table header, if any.
  1333. $order_by = theme_table_header_sortable_order_by($table_headers);
  1334. $res = pager_query("SELECT * FROM watchdog a
  1335. WHERE 1
  1336. $type_line
  1337. $severity_line
  1338. $order_by", $params, 50, 0, "SELECT COUNT(wid) FROM watchdog a
  1339. WHERE 1
  1340. $type_line
  1341. $severity_line
  1342. $order_by", $params);
  1343. while ($cur = db_fetch_object($res)) {
  1344. $pol = ($pol == "even") ? "odd" : "even";
  1345. $o_msg = t($cur->message, unserialize($cur->variables));
  1346. $o_type = $cur->type;
  1347. // shorten msg if necessary
  1348. $msg = substr(strip_tags($o_msg), 0, 130);
  1349. if ($msg != $o_msg) {
  1350. $msg = trim($msg) . "...";
  1351. }
  1352. $type = substr($o_type, 0, 20);
  1353. if ($type != $o_type) {
  1354. $type = trim($type) . "...";
  1355. }
  1356. $severity = $severity_array[$cur->severity];
  1357. $when = format_date(convert_time($cur->timestamp), "short");
  1358. $rtn .= "
  1359. <tr class='row-$pol row-$severity'>
  1360. <td valign='top'>" . l($cur->wid, "admin/config/watchdog/$cur->wid", "sev_filter=$sev_filter&type_filter=$type_filter&page=$page") . "</td>
  1361. <td valign='top'>$when</td>
  1362. <td valign='top'>$type</td>
  1363. <td valign='top'>$msg</td>
  1364. <td valign='top'>$severity</td>
  1365. <td valign='top'>$cur->user_name</td>
  1366. </tr>
  1367. ";
  1368. }
  1369. $rtn .= "</table>";
  1370. // Display the pager that was generated by the pager_query above!
  1371. $rtn .= theme_pager();
  1372. return $rtn;
  1373. } // admin display watchdog
  1374. /**
  1375. * This is the "main" page for the admin module. It's what the user
  1376. * first sees when the click to go to the Admin page.
  1377. */
  1378. function admin_display_main() {
  1379. // Use default_school.
  1380. $de_catalog_year = admin_get_de_catalog_year(FALSE, 0);
  1381. // Has the system cron been run recently?
  1382. $cron_last_run = variable_get("cron_last_run", 0);
  1383. if ($cron_last_run < strtotime("-7 DAY")) {
  1384. // Warn admin that they need to have cron set up! It's been over a week!
  1385. fpm(t("Your system's cron process hasn't run in over a week. In order for FlightPath
  1386. to continue to function properly, a cron process much be configured.
  1387. You may @run_link or see the @status_link page for instructions.",
  1388. array("@status_link" => l(t("System status"), "admin/config/status"),
  1389. "@run_link" => l(t("run cron now"), "admin/config/run-cron"))));
  1390. }
  1391. $rtn = "";
  1392. fp_add_css(fp_get_module_path("admin") . "/css/admin.css");
  1393. fp_add_js(fp_get_module_path("admin") . "/js/admin.js");
  1394. $rtn .= "<table class='fp-semester-table admin-display-main-table' cellpadding='5'>
  1395. <tr>
  1396. <td valign='top' class='system-configuration-left'>
  1397. " . fp_render_menu_block(t("System Configuration"), "admin/config") . "
  1398. </td>
  1399. <td valign='top' class='advising-settings-right'>
  1400. ";
  1401. // Advising Settings
  1402. $rtn .= fp_render_section_title("Advising Settings", "admin-advising-settings");
  1403. $defs = array(0 => '');
  1404. if (module_enabled("schools")) {
  1405. $defs = schools_get_school_definitions();
  1406. }
  1407. foreach ($defs as $school_id => $school_name) {
  1408. $rtn .= "<div class='admin-advising-settings'><!--SCHOOL_NAME-->
  1409. <ul>
  1410. <li>" . t("Available terms for advising: %v", array("%v" => fp_space_csv(variable_get_for_school("available_advising_term_ids", "", $school_id)))) . "</li>
  1411. <li>" . t("Default advising term(s): %v", array("%v" => fp_space_csv(variable_get_for_school("advising_term_id", "", $school_id)))) . "</li>
  1412. <li>" . t("Current catalog year: %v", array("%v" => variable_get_for_school("current_catalog_year", "", $school_id))) . "</li>
  1413. <li>" . t("Current draft catalog year: %v", array("%v" => variable_get_for_school("current_draft_catalog_year", "", $school_id))) . "</li>
  1414. <li>" . t("Not released grades terms: %v", array("%v" => fp_space_csv(variable_get_for_school("not_released_grades_terms", "", $school_id)))) . "</li>
  1415. </ul>";
  1416. $url_suffix = "";
  1417. if (intval($school_id) != 0) {
  1418. $url_suffix .= "/" . $school_id;
  1419. }
  1420. if (user_has_permission("can_edit_advising_settings")) {
  1421. $rtn .= l("<i class='fa fa-pencil'></i> " . t("Edit Advising Settings") . "<!--SCHOOL_EDIT_LINK-->", "admin/edit-advising-settings" . $url_suffix);
  1422. }
  1423. if ($school_name) {
  1424. $rtn = str_replace("<!--SCHOOL_NAME-->", "<label>" . $school_name . "</label>", $rtn);
  1425. $rtn = str_replace("<!--SCHOOL_EDIT_LINK-->", t(" for ") . "<em>$school_name</em>", $rtn);
  1426. }
  1427. $rtn .= "</div>";
  1428. } // foreach
  1429. $rtn .= "</td>
  1430. </tr>";
  1431. $rtn .= "</table><br>"; // close table
  1432. // TODO: Similar to the advising settings, do we just loop for each school?
  1433. $current_catalog_year = variable_get("current_catalog_year", 2006); // TODO: how to figure out school?
  1434. $earliest_catalog_year = variable_get("earliest_catalog_year", 2006); // TODO: how to figure out school?
  1435. if (user_has_permission("can_access_data_entry")) {
  1436. $rtn .= fp_render_section_title("Degree & Course Management", "degree-course-management");
  1437. $rtn .= "<div class='data-entry-cats'>";
  1438. // Have a pulldown here of years, then use javascript to hide/show relavant groups.
  1439. $rtn .= "&nbsp; &nbsp; &nbsp; " . t("Select a catalog year") . ": <select id='data-entry-select-cats' onChange='adminHideDECats();'>";
  1440. $selected_cat = ($de_catalog_year != "") ? $de_catalog_year : $current_catalog_year;
  1441. for ($t = $current_catalog_year +1; $t >= $earliest_catalog_year; $t--) {
  1442. $sel = ($t == $selected_cat) ? "selected" : "";
  1443. $rtn .= "<option value='$t' $sel>$t-" . ($t+1) . "</option>";
  1444. }
  1445. $rtn .= "</select>";
  1446. for ($t = $current_catalog_year +1; $t >= $earliest_catalog_year; $t--) {
  1447. $rtn .= "<ul class='data-entry-for-cat data-entry-for-cat-$t'>";
  1448. $rtn .= "<li>" . l(t("Degree plans for @year", array("@year" => "$t-" . ($t+1))), "admin/degrees", "de_catalog_year=$t") . "</li>";
  1449. $rtn .= "<li>" . l(t("Groups for @year", array("@year" => "$t-" . ($t+1))), "admin/groups", "de_catalog_year=$t") . "</li>";
  1450. $rtn .= "<li>" . l(t("Courses for @year", array("@year" => "$t-" . ($t+1))), "admin/courses", "de_catalog_year=$t") . "</li>";
  1451. $rtn .= "</ul>";
  1452. }
  1453. if (user_has_permission("can_edit_data_entry")) {
  1454. $rtn .= "<b>" . t("Administrator function:") . "</b><ul>
  1455. <li>" . l(t("Duplicate entire year worth of data to new year"), "admin/duplicate-year") . "</li>
  1456. </ul>";
  1457. }
  1458. $rtn .= "</div>";
  1459. // Draft changes?
  1460. $res = db_query("SELECT * FROM draft_instructions");
  1461. if (db_num_rows($res) > 0) {
  1462. $rtn .= "<div class='draft-changes-waiting-msg'>
  1463. " . t("Draft changes have been made which have yet to be applied.
  1464. When you are ready for your draft changes to appear in
  1465. production, click the link below.") . "</div>";
  1466. }
  1467. $rtn .= "<ul class='data-entry-draft-waiting'>
  1468. <li>" . l(t("Apply draft changes"), "admin/apply-draft-changes") . "</li>
  1469. </ul>";
  1470. }
  1471. return $rtn;
  1472. }

Functions

Namesort descending Description
admin_advising_settings_form This is a systems settings form, which lets the user edit advising variabled for FlightPath.
admin_apply_draft_changes_form This form lets the user apply draft changes (if they can supply the passcode)
admin_apply_draft_changes_form_submit Handles the actual moving of draft courses into production.
admin_apply_draft_changes_form_validate Before we apply changes, make sure the password is correct.
admin_cron hook_cron
admin_display_main This is the "main" page for the admin module. It's what the user first sees when the click to go to the Admin page.
admin_display_tools_screen This page displays all the tools that the user has access to use.
admin_display_watchdog
admin_display_watchdog_entry Display the details of a particular watchdog entry, specified by its table id.
admin_duplicate_year_form This form will allow the user to duplicate an entire year's worth of data to a new catalog year.
admin_duplicate_year_form_submit This function should perform the actual copy of data!
admin_duplicate_year_form_validate Before we duplicate the year, make sure the password is correct.
admin_get_de_catalog_year Get the "de_catalog_year" from the REQUEST. If it's not there or invalid, pull it from our system settings.
admin_get_semester_name Convienence function to get semester's default regular name.
admin_menu Implementation of hook_menu
admin_menu_handle_replacement_pattern This is an implementation of hook_menu_handle_replacement_pattern. It will search for and replace replacement patterns which we are aware of it in $str.
admin_perm
admin_urgent_message_form Meant to be fed into "fp_system_settings_form()", this function returns an array which will automatically save values to our "variables" table.
z__admin_display_watchdog Displays recent watchdog entries, from the watchdog table