diff --git a/grade/import/csv/classes/load_data.php b/grade/import/csv/classes/load_data.php index a099f59d1f1..e9744b1f7ed 100644 --- a/grade/import/csv/classes/load_data.php +++ b/grade/import/csv/classes/load_data.php @@ -577,6 +577,7 @@ class gradeimport_csv_load_data { } else { // The grade item for this is not updated. + $newfeedback->importonlyfeedback = true; $insertid = self::insert_grade_record($newfeedback, $this->studentid); // Check to see if the insert was successful. if (empty($insertid)) { diff --git a/grade/import/csv/tests/load_data_test.php b/grade/import/csv/tests/load_data_test.php index 118906c6629..352365e700c 100644 --- a/grade/import/csv/tests/load_data_test.php +++ b/grade/import/csv/tests/load_data_test.php @@ -210,6 +210,7 @@ Bobby,Bunce,,"Moodle HQ","Rock on!",student5@example.com,75.00,,75.00,{exportdat $testarray[$key]->feedback = $record->feedback; $testarray[$key]->importcode = $testobject->get_importcode(); $testarray[$key]->importer = $USER->id; + $testarray[$key]->importonlyfeedback = 0; // Check that the record was inserted into the database. $this->assertEquals($gradeimportvalues, $testarray); diff --git a/grade/import/lib.php b/grade/import/lib.php index f8d8e5777cb..655c54bb50c 100644 --- a/grade/import/lib.php +++ b/grade/import/lib.php @@ -37,9 +37,10 @@ function get_new_importcode() { * (grade_import_value and grade_import_newitem) * If this function is called, we assume that all data collected * up to this point is fine and we can go ahead and commit - * @param int courseid - id of the course - * @param string importcode - import batch identifier - * @param feedback print feedback and continue button + * @param int $courseid - ID of the course. + * @param int $importcode - Import batch identifier. + * @param bool $importfeedback - Whether to import feedback as well. + * @param bool $verbose - Print feedback and continue button. * @return bool success */ function grade_import_commit($courseid, $importcode, $importfeedback=true, $verbose=true) { @@ -114,6 +115,10 @@ function grade_import_commit($courseid, $importcode, $importfeedback=true, $verb if (!$importfeedback) { $grade->feedback = false; // ignore it } + if ($grade->importonlyfeedback) { + // False means do not change. See grade_itme::update_final_grade(). + $grade->finalgrade = false; + } if (!$gradeitem->update_final_grade($grade->userid, $grade->finalgrade, 'import', $grade->feedback)) { $errordata = new stdClass(); $errordata->itemname = $gradeitem->itemname; diff --git a/grade/tests/importlib_test.php b/grade/tests/importlib_test.php new file mode 100644 index 00000000000..0acea9e6dd9 --- /dev/null +++ b/grade/tests/importlib_test.php @@ -0,0 +1,208 @@ +. + +/** + * Unit tests for grade/import/lib.php. + * + * @package core_grade + * @category phpunit + * @copyright 2015 Adrian Greeve + * @license http://www.gnu.org/copyleft/gpl.html GNU Public License + */ + +defined('MOODLE_INTERNAL') || die(); + +global $CFG; +require_once($CFG->dirroot . '/grade/import/lib.php'); + +/** + * Tests grade_import_lib functions. + */ +class core_grade_import_lib_test extends advanced_testcase { + + /** + * Import grades into 'grade_import_values' table. This is done differently in the various import plugins, + * so there is no direct API to call. + * + * @param array $data Information to be inserted into the table. + * @return int The insert ID of the sql statement. + */ + private function import_grades($data) { + global $DB, $USER; + $graderecord = new stdClass(); + $graderecord->importcode = $data['importcode']; + if (isset($data['itemid'])) { + $graderecord->itemid = $data['itemid']; + } + $graderecord->userid = $data['userid']; + if (isset($data['importer'])) { + $graderecord->importer = $data['importer']; + } else { + $graderecord->importer = $USER->id; + } + if (isset($data['finalgrade'])) { + $graderecord->finalgrade = $data['finalgrade']; + } else { + $graderecord->finalgrade = rand(0, 100); + } + if (isset($data['feedback'])) { + $graderecord->feedback = $data['feedback']; + } + if (isset($data['importonlyfeedback'])) { + $graderecord->importonlyfeedback = $data['importonlyfeedback']; + } else { + $graderecord->importonlyfeedback = false; + } + if (isset($data['newgradeitem'])) { + $graderecord->newgradeitem = $data['newgradeitem']; + } + return $DB->insert_record('grade_import_values', $graderecord); + } + + /** + * 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 ++ +
id\" />
"; + + ob_start(); + $status = grade_import_commit($course->id, $importcode); + $output = ob_get_contents(); + ob_end_clean(); + $this->assertTrue($status); + $this->assertEquals($expectedresponse, $output); + } +} diff --git a/lib/db/install.xml b/lib/db/install.xml index 193dad3d77a..fcc226d84d2 100644 --- a/lib/db/install.xml +++ b/lib/db/install.xml @@ -1,5 +1,5 @@ - @@ -1941,6 +1941,7 @@ + diff --git a/lib/db/upgrade.php b/lib/db/upgrade.php index 10992e88be6..0adf125b2b8 100644 --- a/lib/db/upgrade.php +++ b/lib/db/upgrade.php @@ -4441,5 +4441,20 @@ function xmldb_main_upgrade($oldversion) { upgrade_main_savepoint(true, 2015062500.01); } + if ($oldversion < 2015081300.01) { + + // Define field importtype to be added to grade_import_values. + $table = new xmldb_table('grade_import_values'); + $field = new xmldb_field('importonlyfeedback', XMLDB_TYPE_INTEGER, '1', null, null, null, '0', 'importer'); + + // Conditionally launch add field importtype. + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + // Main savepoint reached. + upgrade_main_savepoint(true, 2015081300.01); + } + return true; } diff --git a/version.php b/version.php index 2bba74c51fc..53f0ce79463 100644 --- a/version.php +++ b/version.php @@ -29,7 +29,7 @@ defined('MOODLE_INTERNAL') || die(); -$version = 2015081300.00; // YYYYMMDD = weekly release date of this DEV branch. +$version = 2015081300.01; // YYYYMMDD = weekly release date of this DEV branch. // RR = release increments - 00 in DEV branches. // .XX = incremental changes.