function import_xml_grades($text, $course, &$error) { global $USER; $importcode = get_new_importcode(); $status = true; $content = xmlize($text); if (!empty($content['results']['#']['result'])) { $results = $content['results']['#']['result']; foreach ($results as $i => $result) { $gradeidnumber = $result['#']['assignment'][0]['#']; if (!($grade_items = grade_item::fetch_all(array('idnumber' => $gradeidnumber, 'courseid' => $course->id)))) { // gradeitem does not exist // no data in temp table so far, abort $status = false; $error = get_string('errincorrectgradeidnumber', 'gradeimport_xml', $gradeidnumber); break; } else { if (count($grade_items) != 1) { $status = false; $error = get_string('errduplicategradeidnumber', 'gradeimport_xml', $gradeidnumber); break; } else { $grade_item = reset($grade_items); } } // grade item locked, abort if ($grade_item->is_locked()) { $status = false; $error = get_string('gradeitemlocked', 'grades'); break; } // check if user exist and convert idnumber to user id $useridnumber = $result['#']['student'][0]['#']; if (!($user = get_record('user', 'idnumber', addslashes($useridnumber)))) { // no user found, abort $status = false; $error = get_string('errincorrectuseridnumber', 'gradeimport_xml', $useridnumber); break; } // check if grade_grade is locked and if so, abort if ($grade_grade = new grade_grade(array('itemid' => $grade_item->id, 'userid' => $user->id))) { $grade_grade->grade_item =& $grade_item; if ($grade_grade->is_locked()) { // individual grade locked, abort $status = false; $error = get_string('gradegradeslocked', 'grades'); break; } } $newgrade = new object(); $newgrade->itemid = $grade_item->id; $newgrade->userid = $user->id; $newgrade->importcode = $importcode; $newgrade->importer = $USER->id; // check grade value exists and is a numeric grade if (isset($result['#']['score'][0]['#'])) { if (is_numeric($result['#']['score'][0]['#'])) { $newgrade->finalgrade = $result['#']['score'][0]['#']; } else { $status = false; $error = get_string('badgrade', 'grades'); break; } } else { $newgrade->finalgrade = NULL; } // check grade feedback exists if (isset($result['#']['feedback'][0]['#'])) { $newgrade->feedback = $result['#']['feedback'][0]['#']; } else { $newgrade->feedback = NULL; } // insert this grade into a temp table if (!insert_record('grade_import_values', addslashes_recursive($newgrade))) { $status = false; // could not insert into temp table $error = get_string('importfailed', 'grades'); break; } } } else { // no results section found in xml, // assuming bad format, abort import $status = false; $error = get_string('errbadxmlformat', 'gradeimport_xml'); } if ($status) { return $importcode; } else { import_cleanup($importcode); return false; } }
/** * Tests for importing grades from an external source. */ public function test_grade_import_commit() { global $USER, $DB, $CFG; $this->resetAfterTest(); $importcode = get_new_importcode(); $user1 = $this->getDataGenerator()->create_user(); $user2 = $this->getDataGenerator()->create_user(); $course = $this->getDataGenerator()->create_course(); $assign = $this->getDataGenerator()->create_module('assign', array('course' => $course->id)); $itemname = $assign->name; $modulecontext = context_module::instance($assign->cmid); // The generator returns a dummy object, lets get the real assign object. $assign = new assign($modulecontext, false, false); $cm = $assign->get_course_module(); // Enrol users in the course. $this->getDataGenerator()->enrol_user($user1->id, $course->id); $this->getDataGenerator()->enrol_user($user2->id, $course->id); // Enter a new grade into an existing grade item. $gradeitem = grade_item::fetch(array('courseid' => $course->id, 'itemtype' => 'mod')); // Keep this value around for a test further down. $originalgrade = 55; $this->import_grades(array('importcode' => $importcode, 'itemid' => $gradeitem->id, 'userid' => $user1->id, 'finalgrade' => $originalgrade)); $status = grade_import_commit($course->id, $importcode, false, false); $this->assertTrue($status); // Get imported grade_grade. $gradegrade = grade_grade::fetch(array('itemid' => $gradeitem->id, 'userid' => $user1->id)); $this->assertEquals($originalgrade, $gradegrade->finalgrade); // Overriden field will be a timestamp and will evaluate out to true. $this->assertTrue($gradegrade->is_overridden()); // Create a new grade item and import into that. $importcode = get_new_importcode(); $record = new stdClass(); $record->itemname = 'New grade item'; $record->importcode = $importcode; $record->importer = $USER->id; $insertid = $DB->insert_record('grade_import_newitem', $record); $finalgrade = 75; $this->import_grades(array('importcode' => $importcode, 'userid' => $user1->id, 'finalgrade' => $finalgrade, 'newgradeitem' => $insertid)); $status = grade_import_commit($course->id, $importcode, false, false); $this->assertTrue($status); // Check that we have a new grade_item. $gradeitem = grade_item::fetch(array('courseid' => $course->id, 'itemtype' => 'manual')); $this->assertEquals($record->itemname, $gradeitem->itemname); // Grades were imported. $gradegrade = grade_grade::fetch(array('itemid' => $gradeitem->id, 'userid' => $user1->id)); $this->assertEquals($finalgrade, $gradegrade->finalgrade); // As this is a new item the grade has not been overridden. $this->assertFalse($gradegrade->is_overridden()); // Import feedback only. $importcode = get_new_importcode(); $gradeitem = grade_item::fetch(array('courseid' => $course->id, 'itemtype' => 'mod')); $originalfeedback = 'feedback can be useful'; $this->import_grades(array('importcode' => $importcode, 'userid' => $user1->id, 'itemid' => $gradeitem->id, 'feedback' => $originalfeedback, 'importonlyfeedback' => true)); $status = grade_import_commit($course->id, $importcode, true, false); $this->assertTrue($status); $gradegrade = grade_grade::fetch(array('itemid' => $gradeitem->id, 'userid' => $user1->id)); // The final grade should be the same as the first record further up. We are only altering the feedback. $this->assertEquals($originalgrade, $gradegrade->finalgrade); $this->assertTrue($gradegrade->is_overridden()); // Import grades only. $importcode = get_new_importcode(); $gradeitem = grade_item::fetch(array('courseid' => $course->id, 'itemtype' => 'mod')); $finalgrade = 60; $this->import_grades(array('importcode' => $importcode, 'userid' => $user1->id, 'itemid' => $gradeitem->id, 'finalgrade' => $finalgrade, 'feedback' => 'feedback can still be useful')); $status = grade_import_commit($course->id, $importcode, false, false); $this->assertTrue($status); $gradegrade = grade_grade::fetch(array('itemid' => $gradeitem->id, 'userid' => $user1->id)); $this->assertEquals($finalgrade, $gradegrade->finalgrade); // The final feedback should not have changed. $this->assertEquals($originalfeedback, $gradegrade->feedback); $this->assertTrue($gradegrade->is_overridden()); // Check that printing of import status is correct. $importcode = get_new_importcode(); $gradeitem = grade_item::fetch(array('courseid' => $course->id, 'itemtype' => 'mod')); $this->import_grades(array('importcode' => $importcode, 'userid' => $user1->id, 'itemid' => $gradeitem->id)); $url = $CFG->wwwroot . '/grade/index.php'; $expectedresponse = "++ Grade import success ++\n<div class=\"continuebutton\"><form method=\"get\" action=\"{$url}\"><div><input type=\"submit\" value=\"Continue\" /><input type=\"hidden\" name=\"id\" value=\"{$course->id}\" /></div></form></div>"; ob_start(); $status = grade_import_commit($course->id, $importcode); $output = ob_get_contents(); ob_end_clean(); $this->assertTrue($status); $this->assertEquals($expectedresponse, $output); }
} } // Set up the import form. $mform = new grade_import_form(null, array('includeseparator' => true, 'verbosescales' => true)); // If the csv file hasn't been imported yet then look for a form submission or // show the initial submission form. if (!$iid) { // If the import form has been submitted. if ($formdata = $mform->get_data()) { // Large files are likely to take their time and memory. Let PHP know // that we'll take longer, and that the process should be recycled soon // to free up memory. core_php_time_limit::raise(); raise_memory_limit(MEMORY_EXTRA); // Use current (non-conflicting) time stamp. $importcode = get_new_importcode(); $text = $mform->get_file_content('userfile'); $iid = csv_import_reader::get_new_iid('grade'); $csvimport = new csv_import_reader($iid, 'grade'); $csvimport->load_csv_content($text, $formdata->encoding, $separator); // --- get header (field names) --- $header = $csvimport->get_columns(); // Print a preview of the data. $numlines = 0; // 0 lines previewed so far. echo $OUTPUT->heading(get_string('importpreview', 'grades')); foreach ($header as $i => $h) { $h = trim($h); // Remove whitespace. $h = clean_param($h, PARAM_RAW); // Clean the header.
public function execute() { global $CFG, $DB, $USER; require_once $CFG->dirroot . '/course/lib.php'; require_once $CFG->libdir . '/gradelib.php'; require_once $CFG->dirroot . '/grade/lib.php'; require_once $CFG->dirroot . '/grade/import/lib.php'; require_once $CFG->libdir . '/csvlib.class.php'; $options = $this->expandedOptions; $USER = $this->user; $text = file_get_contents($this->arguments[0]); if (!$text) { cli_error("No data in file '{$this->arguments[0]}''"); } if ($options['course-idnumber']) { $course = $DB->get_record('course', array('idnumber' => $this->arguments[1]), '*', MUST_EXIST); } else { $course = $DB->get_record('course', array('id' => $this->arguments[1]), '*', MUST_EXIST); } $iid = \csv_import_reader::get_new_iid('moosh-gradebook'); $csvimport = new \csv_import_reader($iid, 'moosh-gradebook'); $csvimport->load_csv_content($text, 'utf-8', 'comma'); $header = $csvimport->get_columns(); //use "Email address" or "ID number" for mapping users if ($options['map-users-by'] == 'idnumber') { $usermap = array_search('ID number', $header); if ($usermap === false) { cli_error("Didn't find column called 'ID number' for mapping users"); } } elseif ($options['map-users-by'] == 'email') { $usermap = array_search('Email address', $header); if ($usermap === false) { cli_error("Didn't find column called 'Email address' for mapping users"); } } else { cli_error(' Wrong map-users-by value'); } $map = array(); //Try to automatically map columns in CSV file onto activities with the same name $grade_items = \grade_item::fetch_all(array('courseid' => $course->id)); foreach ($grade_items as $grade_item) { // Skip course type and category type. if ($grade_item->itemtype == 'course' || $grade_item->itemtype == 'category') { continue; } $displaystring = null; if (!empty($grade_item->itemmodule)) { $displaystring = get_string('modulename', $grade_item->itemmodule) . ': ' . $grade_item->get_name(); } else { $displaystring = $grade_item->get_name(); } //echo $displaystring . "\n"; $pos = array_search($displaystring, $header); if ($pos !== false) { $map[$pos] = $grade_item->id; echo "CSV column '{$header[$pos]}' will be mapped to grade item '{$displaystring}'\n"; } else { echo "No mapping for gradebook item '{$displaystring}'\n"; } } //iterate over all CSV records $csvimport->init(); $newgrades = array(); while ($line = $csvimport->next()) { //first find user if ($options['map-users-by'] == 'idnumber') { if (!($user = $DB->get_record('user', array('idnumber' => $line[$usermap])))) { cli_error("Couldn't find user with idnumber '{$line[$usermap]}'"); } } elseif ($options['map-users-by'] == 'email') { if (!($user = $DB->get_record('user', array('email' => $line[$usermap])))) { cli_error("Couldn't find user with email '{$line[$usermap]}'"); } } echo "Processing user {$user->email} ({$user->id},{$user->idnumber})\n"; foreach ($map as $k => $v) { $gradeitem = $grade_items[$v]; $value = $line[$k]; $newgrade = new \stdClass(); $newgrade->itemid = $gradeitem->id; //handle scales if ($gradeitem->gradetype == GRADE_TYPE_SCALE) { $scale = $gradeitem->load_scale(); $scales = explode(',', $scale->scale); $scales = array_map('trim', $scales); //hack - trim whitespace around scale options array_unshift($scales, '-'); // scales start at key 1 $key = array_search($value, $scales); if ($key === false) { echo "\tThe correct scale value '{$value}' for item '{$gradeitem->get_name()}' could not be found.\n"; } else { echo "\tMapped value '{$value}' to '{$key}' as scale is used for '{$gradeitem->get_name()}'\n"; $value = $key; } } else { if ($value === '' or $value == '-') { $value = null; // no grade } } echo "\tGrade for '{$gradeitem->get_name()}', type {$gradeitem->gradetype} will be set to '{$value}'\n"; $newgrade->finalgrade = $value; $newgrade->userid = $user->id; $newgrade->importer = $USER->id; $newgrades[] = $newgrade; } } if ($options['test']) { echo "Test mode - exiting without performing import.\n"; } //we will use safer method of importing useing temporary table $importcode = get_new_importcode(); foreach ($newgrades as $newgrade) { $newgrade->importcode = $importcode; $DB->insert_record('grade_import_values', $newgrade); } grade_import_commit($course->id, $importcode); }