MDL-46599 gradebook: Added a time exported column to grade export via csv.
authorAdrian Greeve <adrian@moodle.com>
Wed, 8 Oct 2014 03:25:09 +0000 (11:25 +0800)
committerSimey Lameze <simey@moodle.com>
Thu, 16 Oct 2014 02:31:10 +0000 (10:31 +0800)
This will be useful for checking if a csv import is trying to overwrite
new grade updates.

grade/export/txt/grade_export_txt.php
grade/export/txt/lang/en/gradeexport_txt.php
grade/import/csv/classes/load_data.php
grade/import/csv/index.php
grade/import/csv/tests/load_data_test.php
grade/import/direct/classes/import_form.php
grade/import/direct/classes/mapping_form.php
grade/import/direct/index.php
grade/import/grade_import_form.php
lang/en/grades.php

index 109bce6..7ec6aa4 100644 (file)
@@ -76,6 +76,8 @@ class grade_export_txt extends grade_export {
                 $exporttitle[] = $this->format_column_name($grade_item, true);
             }
         }
+        // Last downloaded column header.
+        $exporttitle[] = get_string('timeexported', 'gradeexport_txt');
         $csvexport->add_data($exporttitle);
 
         // Print all the lines of data.
@@ -110,6 +112,8 @@ class grade_export_txt extends grade_export {
                     $exportdata[] = $this->format_feedback($userdata->feedbacks[$itemid]);
                 }
             }
+            // Time exported.
+            $exportdata[] = time();
             $csvexport->add_data($exportdata);
         }
         $gui->close();
index d2d0ec0..db10755 100644 (file)
@@ -24,5 +24,6 @@
  */
 
 $string['pluginname'] = 'Plain text file';
+$string['timeexported'] = 'Last downloaded from this course';
 $string['txt:publish'] = 'Publish TXT grade export';
 $string['txt:view'] = 'Use text grade export';
index 080c77e..5d4c227 100644 (file)
@@ -531,15 +531,25 @@ class gradeimport_csv_load_data {
                             $this->cleanup_import(get_string('gradelocked', 'grades'));
                             return $this->status;
                         }
+                        // Check if the force import option is disabled and the last exported date column is present.
+                        if (!$forceimport && !empty($timeexportkey)) {
+                            $exportedtime = $line[$timeexportkey];
+                            if (clean_param($exportedtime, PARAM_INT) != $exportedtime || $exportedtime > time() ||
+                                    $exportedtime < strtotime("-1 year", time())) {
+                                // The date is invalid, or in the future, or more than a year old.
+                                $this->cleanup_import(get_string('invalidgradeexporteddate', 'grades'));
+                                return $this->status;
+
+                            }
+                            $timemodified = $gradegrade->get_dategraded();
+                            if (!empty($timemodified) && ($exportedtime < $timemodified)) {
+                                // The item was graded after we exported it, we return here not to override it.
+                                $user = core_user::get_user($this->studentid);
+                                $this->cleanup_import(get_string('gradealreadyupdated', 'grades', fullname($user)));
+                                return $this->status;
+                            }
+                        }
                     }
-
-                    // The grade was modified since the export.
-                    if ($forceimport === 0 && !empty($timeexportkey) && ($line[$timeexportkey] < $gradegrade->get_dategraded())) {
-                        $user = core_user::get_user($this->studentid);
-                        $this->cleanup_import(get_string('gradealreadyupdated', 'grades', fullname($user)));
-                        break;
-                    }
-
                     $insertid = self::insert_grade_record($newgrade, $this->studentid);
                     // Check to see if the insert was successful.
                     if (empty($insertid)) {
index 0c2a5d2..e2426f0 100644 (file)
@@ -27,7 +27,7 @@ $separator     = optional_param('separator', '', PARAM_ALPHA);
 $verbosescales = optional_param('verbosescales', 1, PARAM_BOOL);
 $iid           = optional_param('iid', null, PARAM_INT);
 $importcode    = optional_param('importcode', '', PARAM_FILE);
-$forceimport   = optional_param('forceimport', 0, PARAM_BOOL);
+$forceimport   = optional_param('forceimport', false, PARAM_BOOL);
 
 $url = new moodle_url('/grade/import/csv/index.php', array('id'=>$id));
 if ($separator !== '') {
@@ -68,7 +68,6 @@ if (!$iid) {
 
     // If the import form has been submitted.
     if ($formdata = $mform->get_data()) {
-
         $text = $mform->get_file_content('userfile');
         $csvimport = new gradeimport_csv_load_data();
         $csvimport->load_csv_content($text, $formdata->encoding, $separator, $formdata->previewrows);
index 5c13a03..a0d019e 100644 (file)
@@ -41,15 +41,20 @@ require_once($CFG->libdir . '/grade/tests/fixtures/lib.php');
 class gradeimport_csv_load_data_testcase extends grade_base_testcase {
 
     /** @var string $oktext Text to be imported. This data should have no issues being imported. */
-    protected $oktext = '"First name",Surname,"ID number",Institution,Department,"Email address","Assignment: Assignment for grape group", "Feedback: Assignment for grape group","Course total","Last downloaded from this course"
-Anne,Able,1,"Moodle HQ","Rock on!",student7@mail.com,56.00,"We welcome feedback",56.00,1412327067
-Bobby,Bunce,2,"Moodle HQ","Rock on!",student5@mail.com,75.00,,75.00,1412327067';
+    protected $oktext = '"First name",Surname,"ID number",Institution,Department,"Email address","Assignment: Assignment for grape group", "Feedback: Assignment for grape group","Course total"
+Anne,Able,,"Moodle HQ","Rock on!",student7@mail.com,56.00,"We welcome feedback",56.00
+Bobby,Bunce,,"Moodle HQ","Rock on!",student5@mail.com,75.00,,75.00';
 
     /** @var string $badtext Text to be imported. This data has an extra column and should not succeed in being imported. */
     protected $badtext = '"First name",Surname,"ID number",Institution,Department,"Email address","Assignment: Assignment for grape group","Course total"
 Anne,Able,,"Moodle HQ","Rock on!",student7@mail.com,56.00,56.00,78.00
 Bobby,Bunce,,"Moodle HQ","Rock on!",student5@mail.com,75.00,75.00';
 
+    /** @var string $csvtext CSV data to be imported with Last download from this course column. */
+    protected $csvtext = '"First name",Surname,"ID number",Institution,Department,"Email address","Assignment: Assignment for grape group", "Feedback: Assignment for grape group","Course total","Last downloaded from this course"
+Anne,Able,,"Moodle HQ","Rock on!",student7@mail.com,56.00,"We welcome feedback",56.00,{exportdate}
+Bobby,Bunce,,"Moodle HQ","Rock on!",student5@mail.com,75.00,,75.00,{exportdate}';
+
     /** @var int $iid Import ID. */
     protected $iid;
 
@@ -94,26 +99,24 @@ Bobby,Bunce,,"Moodle HQ","Rock on!",student5@mail.com,75.00,75.00';
         $expecteddata = array(array(
                 'Anne',
                 'Able',
-                '1',
+                '',
                 'Moodle HQ',
                 'Rock on!',
                 'student7@mail.com',
                 56.00,
                 'We welcome feedback',
-                56.00,
-                1412327067
+                56.00
             ),
             array(
                 'Bobby',
                 'Bunce',
-                '2',
+                '',
                 'Moodle HQ',
                 'Rock on!',
                 'student5@mail.com',
                 75.00,
                 '',
-                75.00,
-                1412327067
+                75.00
             )
         );
 
@@ -126,10 +129,8 @@ Bobby,Bunce,,"Moodle HQ","Rock on!",student5@mail.com,75.00,75.00';
             'Email address',
             'Assignment: Assignment for grape group',
             'Feedback: Assignment for grape group',
-            'Course total',
-            'Last downloaded from this course'
+            'Course total'
         );
-
         // Check that general data is returned as expected.
         $this->assertEquals($csvpreview->get_previewdata(), $expecteddata);
         // Check that headers are returned as expected.
@@ -386,29 +387,22 @@ Bobby,Bunce,,"Moodle HQ","Rock on!",student5@mail.com,75.00,75.00';
      */
     public function test_prepare_import_grade_data() {
         global $DB;
-        $course1 = $this->getDataGenerator()->create_course();
+
         // Need to add one of the users into the system.
         $user = new stdClass();
         $user->firstname = 'Anne';
         $user->lastname = 'Able';
         $user->email = 'student7@mail.com';
-        $user->id_number = 1;
         // Insert user 1.
-        $user1 = $this->getDataGenerator()->create_user($user);
-        $this->getDataGenerator()->enrol_user($user1->id, $course1->id);
-
+        $this->getDataGenerator()->create_user($user);
         $user = new stdClass();
         $user->firstname = 'Bobby';
         $user->lastname = 'Bunce';
         $user->email = 'student5@mail.com';
-        $user->id_number = 2;
         // Insert user 2.
-        $user2 = $this->getDataGenerator()->create_user($user);
-        $this->getDataGenerator()->enrol_user($user2->id, $course1->id);
+        $this->getDataGenerator()->create_user($user);
 
-       $assign1 = $this->getDataGenerator()->create_module('assign', array('course' => $course1->id, 'itemid' => 1));
-
-        $csvdata =$this->csv_load($this->oktext);
+        $this->csv_load($this->oktext);
 
         $importcode = 007;
         $verbosescales = 0;
@@ -431,7 +425,7 @@ Bobby,Bunce,,"Moodle HQ","Rock on!",student5@mail.com,75.00,75.00';
         $formdata->id = 2;
         $formdata->iid = $this->iid;
         $formdata->importcode = $importcode;
-        $formdata->forceimport = 1;
+        $formdata->forceimport = false;
 
         // Blam go time.
         $testobject = new phpunit_gradeimport_csv_load_data();
@@ -439,30 +433,124 @@ Bobby,Bunce,,"Moodle HQ","Rock on!",student5@mail.com,75.00,75.00';
                 $verbosescales);
         // If everything inserted properly then this should be true.
         $this->assertTrue($dataloaded);
-        grade_import_commit($this->courseid, $importcode, false, false);
+    }
+
+    /*
+     * Test importing csv data into the gradebook using "Last downloaded from this course" column and force import option.
+     */
+    public function test_force_import_option () {
+
+        // Need to add users into the system.
+        $user = new stdClass();
+        $user->firstname = 'Anne';
+        $user->lastname = 'Able';
+        $user->email = 'student7@mail.com';
+        $user->id_number = 1;
+        $user1 = $this->getDataGenerator()->create_user($user);
+        $user = new stdClass();
+        $user->firstname = 'Bobby';
+        $user->lastname = 'Bunce';
+        $user->email = 'student5@mail.com';
+        $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 = 001;
+        $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;
 
-        // Test using force import disabled.
-        $formdata->mapping_6 = $assign1->id;
-        $formdata->forceimport = 0;
-        $csvdata[0][6] = '76.00';
+        // 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);
+        $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 last exported date.
-        $formdata->mapping_6 = $assign1->id;
-        $formdata->forceimport = 0;
-        $csvdata[0][6] = '77.00';
+        // 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);
-        // Should return false now, since the grade were updated since last export.
+        $dataloaded = $testobject->prepare_import_grade_data($this->columns, $formdata, $this->csvimport,
+                $this->courseid, '', '', $verbosescales);
         $this->assertFalse($dataloaded);
-
-        // Make sure we get a error message.
         $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'));
     }
 }
index 0a10b11..f157b8c 100644 (file)
@@ -68,7 +68,7 @@ class gradeimport_direct_import_form extends moodleform {
         $mform->setType('groupid', PARAM_INT);
         $mform->addElement('advcheckbox', 'forceimport', get_string('forceimport', 'grades'));
         $mform->addHelpButton('forceimport', 'forceimport', 'grades');
-        $mform->setDefault('forceimport', 0);
+        $mform->setDefault('forceimport', false);
         $this->add_action_buttons(false, get_string('uploadgrades', 'grades'));
     }
 }
index a097332..136b45c 100644 (file)
@@ -107,7 +107,7 @@ class gradeimport_direct_mapping_form extends moodleform {
         $mform->setType('groupid', PARAM_INT);
         $mform->setConstant('groupid', groups_get_course_group($COURSE));
         $mform->addElement('hidden', 'forceimport', $this->_customdata['forceimport']);
-        $mform->setType('forceimport', PARAM_INT);
+        $mform->setType('forceimport', PARAM_BOOL);
         $mform->setConstant('forceimport', $this->_customdata['forceimport']);
         $this->add_action_buttons(false, get_string('uploadgrades', 'grades'));
     }
index c620e6f..fdd3759 100644 (file)
@@ -24,7 +24,7 @@ $id            = required_param('id', PARAM_INT); // Course id.
 $verbosescales = optional_param('verbosescales', 1, PARAM_BOOL);
 $iid           = optional_param('iid', null, PARAM_INT);
 $importcode    = optional_param('importcode', '', PARAM_FILE);
-$forceimport   = optional_param('forceimport', null, PARAM_INT);
+$forceimport   = optional_param('forceimport', false, PARAM_BOOL);
 
 $url = new moodle_url('/grade/import/direct/index.php', array('id' => $id));
 
index 7ce9c94..4894a08 100644 (file)
@@ -72,7 +72,8 @@ class grade_import_form extends moodleform {
         $mform->setType('previewrows', PARAM_INT);
         $mform->addElement('checkbox', 'forceimport', get_string('forceimport', 'grades'));
         $mform->addHelpButton('forceimport', 'forceimport', 'grades');
-        $mform->setDefault('forceimport', 0);
+        $mform->setDefault('forceimport', false);
+        $mform->setType('forceimport', PARAM_BOOL);
         $mform->addElement('hidden', 'groupid', groups_get_course_group($COURSE));
         $mform->setType('groupid', PARAM_INT);
         $this->add_action_buttons(false, get_string('uploadgrades', 'grades'));
index fce2324..5749629 100644 (file)
@@ -394,6 +394,7 @@ $string['incorrectcustomscale'] = '(Incorrect custom scale, please change.)';
 $string['incorrectminmax'] = 'The minimum must be lower than the maximum';
 $string['inherit'] = 'Inherit';
 $string['intersectioninfo'] = 'Student/Grade info';
+$string['invalidgradeexporteddate'] = 'The export date is invalid because it is more than a year ago, or in the future, or because the format is invalid.';
 $string['item'] = 'Item';
 $string['iteminfo'] = 'Item info';
 $string['iteminfo_help'] = 'This setting provides space for entering information about the item. The information is not displayed anywhere else.';