$newgrade->userid = $studentid; $newgrade->importer = $USER->id; $DB->insert_record('grade_import_values', $newgrade); } } // updating/inserting all comments here if ($status and !empty($newfeedbacks)) { foreach ($newfeedbacks as $newfeedback) { $sql = "SELECT *\n FROM {grade_import_values}\n WHERE importcode=? AND userid=? AND itemid=? AND importer=?"; if ($feedback = $DB->get_record_sql($sql, array($importcode, $studentid, $newfeedback->itemid, $USER->id))) { $newfeedback->id = $feedback->id; $DB->update_record('grade_import_values', $newfeedback); } else { // the grade item for this is not updated $newfeedback->importcode = $importcode; $newfeedback->userid = $studentid; $newfeedback->importer = $USER->id; $DB->insert_record('grade_import_values', $newfeedback); } } } } /// at this stage if things are all ok, we commit the changes from temp table if ($status) { grade_import_commit($course->id, $importcode); } } else { // If data hasn't been submitted then display the data mapping form. $mform2->display(); echo $OUTPUT->footer(); }
require_capability('gradeimport/xml:view', $context); // 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. @set_time_limit(0); raise_memory_limit(MEMORY_EXTRA); $text = download_file_content($url); if ($text === false) { print_error('cannotreadfile'); } $error = ''; $importcode = import_xml_grades($text, $course, $error); if ($importcode !== false) { /// commit the code if we are up this far if (defined('USER_KEY_LOGIN')) { if (grade_import_commit($id, $importcode, $feedback, false)) { echo 'ok'; die; } else { print_error('cannotimportgrade'); //TODO: localize } } else { print_grade_page_head($course->id, 'import', 'xml', get_string('importxml', 'grades')); grade_import_commit($id, $importcode, $feedback, true); echo $OUTPUT->footer(); die; } } else { print_error('error', 'gradeimport_xml'); }
/** * 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); }
public function test_force_import_option() { // Need to add users into the system. $user = new stdClass(); $user->firstname = 'Anne'; $user->lastname = 'Able'; $user->email = '*****@*****.**'; $user->id_number = 1; $user1 = $this->getDataGenerator()->create_user($user); $user = new stdClass(); $user->firstname = 'Bobby'; $user->lastname = 'Bunce'; $user->email = '*****@*****.**'; $user->id_number = 2; $user2 = $this->getDataGenerator()->create_user($user); // Create a new grade item. $params = array('itemtype' => 'manual', 'itemname' => 'Grade item 1', 'gradetype' => GRADE_TYPE_VALUE, 'courseid' => $this->courseid); $gradeitem = new grade_item($params, false); $gradeitemid = $gradeitem->insert(); $importcode = 01; $verbosescales = 0; // Form data object. $formdata = new stdClass(); $formdata->mapfrom = 5; $formdata->mapto = 'useremail'; $formdata->mapping_0 = 0; $formdata->mapping_1 = 0; $formdata->mapping_2 = 0; $formdata->mapping_3 = 0; $formdata->mapping_4 = 0; $formdata->mapping_5 = 0; $formdata->mapping_6 = $gradeitemid; $formdata->mapping_7 = 'feedback_2'; $formdata->mapping_8 = 0; $formdata->mapping_9 = 0; $formdata->map = 1; $formdata->id = 2; $formdata->iid = $this->iid; $formdata->importcode = $importcode; $formdata->forceimport = false; // Add last download from this course column to csv content. $exportdate = time(); $newcsvdata = str_replace('{exportdate}', $exportdate, $this->csvtext); $this->csv_load($newcsvdata); $testobject = new phpunit_gradeimport_csv_load_data(); $dataloaded = $testobject->prepare_import_grade_data($this->columns, $formdata, $this->csvimport, $this->courseid, '', '', $verbosescales); $this->assertTrue($dataloaded); // We must update the last modified date. grade_import_commit($this->courseid, $importcode, false, false); // Test using force import disabled and a date in the past. $pastdate = strtotime('-1 day', time()); $newcsvdata = str_replace('{exportdate}', $pastdate, $this->csvtext); $this->csv_load($newcsvdata); $testobject = new phpunit_gradeimport_csv_load_data(); $dataloaded = $testobject->prepare_import_grade_data($this->columns, $formdata, $this->csvimport, $this->courseid, '', '', $verbosescales); $this->assertFalse($dataloaded); $errors = $testobject->get_gradebookerrors(); $this->assertEquals($errors[0], get_string('gradealreadyupdated', 'grades', fullname($user1))); // Test using force import enabled and a date in the past. $formdata->forceimport = true; $testobject = new phpunit_gradeimport_csv_load_data(); $dataloaded = $testobject->prepare_import_grade_data($this->columns, $formdata, $this->csvimport, $this->courseid, '', '', $verbosescales); $this->assertTrue($dataloaded); // Test importing using an old exported file (2 years ago). $formdata->forceimport = false; $twoyearsago = strtotime('-2 year', time()); $newcsvdata = str_replace('{exportdate}', $twoyearsago, $this->csvtext); $this->csv_load($newcsvdata); $testobject = new phpunit_gradeimport_csv_load_data(); $dataloaded = $testobject->prepare_import_grade_data($this->columns, $formdata, $this->csvimport, $this->courseid, '', '', $verbosescales); $this->assertFalse($dataloaded); $errors = $testobject->get_gradebookerrors(); $this->assertEquals($errors[0], get_string('invalidgradeexporteddate', 'grades')); // Test importing using invalid exported date. $baddate = '0123A56B89'; $newcsvdata = str_replace('{exportdate}', $baddate, $this->csvtext); $this->csv_load($newcsvdata); $formdata->mapping_6 = $gradeitemid; $testobject = new phpunit_gradeimport_csv_load_data(); $dataloaded = $testobject->prepare_import_grade_data($this->columns, $formdata, $this->csvimport, $this->courseid, '', '', $verbosescales); $this->assertFalse($dataloaded); $errors = $testobject->get_gradebookerrors(); $this->assertEquals($errors[0], get_string('invalidgradeexporteddate', 'grades')); // Test importing using date in the future. $oneyearahead = strtotime('+1 year', time()); $oldcsv = str_replace('{exportdate}', $oneyearahead, $this->csvtext); $this->csv_load($oldcsv); $formdata->mapping_6 = $gradeitemid; $testobject = new phpunit_gradeimport_csv_load_data(); $dataloaded = $testobject->prepare_import_grade_data($this->columns, $formdata, $this->csvimport, $this->courseid, '', '', $verbosescales); $this->assertFalse($dataloaded); $errors = $testobject->get_gradebookerrors(); $this->assertEquals($errors[0], get_string('invalidgradeexporteddate', 'grades')); }
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); }