PageRenderTime 26ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/grade/edit/outcome/import.php

https://github.com/tcubansk/moodle
PHP | 246 lines | 160 code | 38 blank | 48 comment | 37 complexity | 6bd81f53a432af022df990cb2aa152bd MD5 | raw file
  1. <?php
  2. // This file is part of Moodle - http://moodle.org/
  3. //
  4. // Moodle is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // Moodle is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License
  15. // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
  16. /**
  17. * Import outcomes from a file
  18. *
  19. * @package core_grades
  20. * @copyright 2008 Moodle Pty Ltd (http://moodle.com)
  21. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  22. */
  23. require_once(dirname(__FILE__).'/../../../config.php');
  24. require_once($CFG->dirroot.'/lib/formslib.php');
  25. require_once($CFG->dirroot.'/grade/lib.php');
  26. require_once($CFG->libdir.'/gradelib.php');
  27. require_once('import_outcomes_form.php');
  28. $courseid = optional_param('courseid', 0, PARAM_INT);
  29. $action = optional_param('action', '', PARAM_ALPHA);
  30. $scope = optional_param('scope', 'global', PARAM_ALPHA);
  31. $PAGE->set_url('/grade/edit/outcome/import.php', array('courseid' => $courseid));
  32. /// Make sure they can even access this course
  33. if ($courseid) {
  34. if (!$course = $DB->get_record('course', array('id' => $courseid))) {
  35. print_error('nocourseid');
  36. }
  37. require_login($course);
  38. $context = get_context_instance(CONTEXT_COURSE, $course->id);
  39. if (empty($CFG->enableoutcomes)) {
  40. redirect('../../index.php?id='.$courseid);
  41. }
  42. } else {
  43. require_once $CFG->libdir.'/adminlib.php';
  44. admin_externalpage_setup('outcomes');
  45. $context = get_context_instance(CONTEXT_SYSTEM);
  46. }
  47. require_capability('moodle/grade:manageoutcomes', $context);
  48. $navigation = grade_build_nav(__FILE__, get_string('outcomes', 'grades'), $courseid);
  49. $upload_form = new import_outcomes_form();
  50. // display import form
  51. if (!$upload_form->get_data()) {
  52. print_grade_page_head($courseid, 'outcome', 'import', get_string('importoutcomes', 'grades'));
  53. $upload_form->display();
  54. echo $OUTPUT->footer();
  55. die;
  56. }
  57. print_grade_page_head($courseid, 'outcome', 'import', get_string('importoutcomes', 'grades'));
  58. $imported_file = $CFG->tempdir . '/outcomeimport/importedfile_'.time().'.csv';
  59. make_temp_directory('outcomeimport');
  60. // copying imported file
  61. if (!$upload_form->save_file('userfile', $imported_file, true)) {
  62. redirect('import.php'. ($courseid ? "?courseid=$courseid" : ''), get_string('importfilemissing', 'grades'));
  63. }
  64. /// which scope are we importing the outcomes in?
  65. if (isset($courseid) && ($scope == 'custom')) {
  66. // custom scale
  67. $local_scope = true;
  68. } elseif (($scope == 'global') && has_capability('moodle/grade:manage', get_context_instance(CONTEXT_SYSTEM))) {
  69. // global scale
  70. $local_scope = false;
  71. } else {
  72. // shouldn't happen .. user might be trying to access this script without the right permissions.
  73. redirect('index.php', get_string('importerror', 'grades'));
  74. }
  75. // open the file, start importing data
  76. if ($handle = fopen($imported_file, 'r')) {
  77. $line = 0; // will keep track of current line, to give better error messages.
  78. $file_headers = '';
  79. // $csv_data needs to have at least these columns, the value is the default position in the data file.
  80. $headers = array('outcome_name' => 0, 'outcome_shortname' => 1, 'scale_name' => 3, 'scale_items' => 4);
  81. $optional_headers = array('outcome_description'=>2, 'scale_description' => 5);
  82. $imported_headers = array(); // will later be initialized with the values found in the file
  83. $fatal_error = false;
  84. // data should be separated by a ';'. *NOT* by a comma! TODO: version 2.0
  85. // or whenever we can depend on PHP5, set the second parameter (8192) to 0 (unlimited line length) : the database can store over 128k per line.
  86. while ( $csv_data = fgetcsv($handle, 8192, ';', '"')) { // if the line is over 8k, it won't work...
  87. $line++;
  88. // be tolerant on input, as fgetcsv returns "an array comprising a single null field" on blank lines
  89. if ($csv_data == array(null)) {
  90. continue;
  91. }
  92. // on first run, grab and analyse the header
  93. if ($file_headers == '') {
  94. $file_headers = array_flip($csv_data); // save the header line ... TODO: use the header line to let import work with columns in arbitrary order
  95. $error = false;
  96. foreach($headers as $key => $value) {
  97. // sanity check #1: make sure the file contains all the mandatory headers
  98. if (!array_key_exists($key, $file_headers)) {
  99. $error = true;
  100. break;
  101. }
  102. }
  103. if ($error) {
  104. echo $OUTPUT->box_start('generalbox importoutcomenofile buttons');
  105. echo get_string('importoutcomenofile', 'grades', $line);
  106. echo $OUTPUT->single_button(new moodle_url('/grade/edit/outcome/import.php', array('courseid'=> $courseid)), get_string('back'), 'get');
  107. echo $OUTPUT->box_end();
  108. $fatal_error = true;
  109. break;
  110. }
  111. foreach(array_merge($headers, $optional_headers) as $header => $position) {
  112. // match given columns to expected columns *into* $headers
  113. $imported_headers[$header] = $file_headers[$header];
  114. }
  115. continue; // we don't import headers
  116. }
  117. // sanity check #2: every line must have the same number of columns as there are
  118. // headers. If not, processing stops.
  119. if ( count($csv_data) != count($file_headers) ) {
  120. echo $OUTPUT->box_start('generalbox importoutcomenofile');
  121. echo get_string('importoutcomenofile', 'grades', $line);
  122. echo $OUTPUT->single_button(new moodle_url('/grade/edit/outcome/import.php', array('courseid'=> $courseid)), get_string('back'), 'get');
  123. echo $OUTPUT->box_end();
  124. $fatal_error = true;
  125. //echo $OUTPUT->box(var_export($csv_data, true) ."<br />". var_export($header, true));
  126. break;
  127. }
  128. // sanity check #3: all required fields must be present on the current line.
  129. foreach ($headers as $header => $position) {
  130. if ($csv_data[$imported_headers[$header]] == '') {
  131. echo $OUTPUT->box_start('generalbox importoutcomenofile');
  132. echo get_string('importoutcomenofile', 'grades', $line);
  133. echo $OUTPUT->single_button(new moodle_url('/grade/edit/outcome/import.php', array('courseid'=> $courseid)), get_string('back'), 'get');
  134. echo $OUTPUT->box_end();
  135. $fatal_error = true;
  136. break;
  137. }
  138. }
  139. // MDL-17273 errors in csv are not preventing import from happening. We break from the while loop here
  140. if ($fatal_error) {
  141. break;
  142. }
  143. $params = array($csv_data[$imported_headers['outcome_shortname']]);
  144. $wheresql = 'shortname = ? ';
  145. if ($local_scope) {
  146. $params[] = $courseid;
  147. $wheresql .= ' AND courseid = ?';
  148. } else {
  149. $wheresql .= ' AND courseid IS NULL';
  150. }
  151. $outcome = $DB->get_records_select('grade_outcomes', $wheresql, $params);
  152. if ($outcome) {
  153. // already exists, print a message and skip.
  154. echo $OUTPUT->box(get_string('importskippedoutcome', 'grades', $csv_data[$imported_headers['outcome_shortname']]));
  155. continue;
  156. }
  157. // new outcome will be added, search for compatible existing scale...
  158. $params = array($csv_data[$imported_headers['scale_name']], $csv_data[$imported_headers['scale_items']], $courseid);
  159. $wheresql = 'name = ? AND scale = ? AND (courseid = ? OR courseid = 0)';
  160. $scale = $DB->get_records_select('scale', $wheresql, $params);
  161. if ($scale) {
  162. // already exists in the right scope: use it.
  163. $scale_id = key($scale);
  164. } else {
  165. if (!has_capability('moodle/course:managescales', $context)) {
  166. echo $OUTPUT->box(get_string('importskippednomanagescale', 'grades', $csv_data[$imported_headers['outcome_shortname']]));
  167. continue;
  168. } else {
  169. // scale doesn't exists : create it.
  170. $scale_data = array('name' => $csv_data[$imported_headers['scale_name']],
  171. 'scale' => $csv_data[$imported_headers['scale_items']],
  172. 'description' => $csv_data[$imported_headers['scale_description']],
  173. 'userid' => $USER->id);
  174. if ($local_scope) {
  175. $scale_data['courseid'] = $courseid;
  176. } else {
  177. $scale_data['courseid'] = 0; // 'global' : scale use '0', outcomes use null
  178. }
  179. $scale = new grade_scale($scale_data);
  180. $scale_id = $scale->insert();
  181. }
  182. }
  183. // add outcome
  184. $outcome_data = array('shortname' => $csv_data[$imported_headers['outcome_shortname']],
  185. 'fullname' => $csv_data[$imported_headers['outcome_name']],
  186. 'scaleid' => $scale_id,
  187. 'description' => $csv_data[$imported_headers['outcome_description']],
  188. 'usermodified' => $USER->id);
  189. if ($local_scope) {
  190. $outcome_data['courseid'] = $courseid;
  191. } else {
  192. $outcome_data['courseid'] = null; // 'global' : scale use '0', outcomes use null
  193. }
  194. $outcome = new grade_outcome($outcome_data);
  195. $outcome_id = $outcome->insert();
  196. $outcome_success_strings = new StdClass();
  197. $outcome_success_strings->name = $outcome_data['fullname'];
  198. $outcome_success_strings->id = $outcome_id;
  199. echo $OUTPUT->box(get_string('importoutcomesuccess', 'grades', $outcome_success_strings));
  200. }
  201. } else {
  202. echo $OUTPUT->box(get_string('importoutcomenofile', 'grades', 0));
  203. }
  204. // finish
  205. fclose($handle);
  206. // delete temp file
  207. unlink($imported_file);
  208. echo $OUTPUT->footer();