diff --git a/mod/assign/feedback/file/importzipform.php b/mod/assign/feedback/file/importzipform.php index d67d3a45afa..98a16f08e50 100644 --- a/mod/assign/feedback/file/importzipform.php +++ b/mod/assign/feedback/file/importzipform.php @@ -62,30 +62,31 @@ class assignfeedback_file_import_zip_form extends moodleform implements renderab $mform->addElement('header', 'uploadzip', get_string('confirmuploadzip', 'assignfeedback_file')); - $currentgroup = groups_get_activity_group($assignment->get_course_module(), true); - $allusers = $assignment->list_participants($currentgroup, false); - $participants = array(); - foreach ($allusers as $user) { - $participants[$assignment->get_uniqueid_for_user($user->id)] = $user; - } + $participants = $importer->get_participant_mapping($assignment); $fs = get_file_storage(); $updates = array(); foreach ($files as $unzippedfile) { - $user = null; + $users = null; $plugin = null; $filename = ''; - if ($importer->is_valid_filename_for_import($assignment, $unzippedfile, $participants, $user, $plugin, $filename)) { - if ($importer->is_file_modified($assignment, $user, $plugin, $filename, $unzippedfile)) { + if ($importer->is_valid_filename_for_import($assignment, $unzippedfile, $participants, $users, $plugin, $filename)) { + if ($importer->is_file_modified($assignment, $users, $plugin, $filename, $unzippedfile)) { // Get a string we can show to identify this user. - $userdesc = fullname($user, has_capability('moodle/site:viewfullnames', $assignment->get_context())); - $path = pathinfo($filename); - if ($assignment->is_blind_marking()) { - $userdesc = get_string('hiddenuser', 'assign') . + $userdescs = []; + foreach ($users as $user) { + if ($assignment->is_blind_marking()) { + $userdescs[] = get_string('hiddenuser', 'assign') . $assignment->get_uniqueid_for_user($user->id); + } else { + $userdescs[] = fullname($user, has_capability('moodle/site:viewfullnames', $assignment->get_context())); + } } + $userdesc = join(", ", $userdescs); + + $path = pathinfo($filename); $grade = $assignment->get_user_grade($user->id, false); $exists = false; diff --git a/mod/assign/feedback/file/importziplib.php b/mod/assign/feedback/file/importziplib.php index 31bd5cec1eb..2627d355e22 100644 --- a/mod/assign/feedback/file/importziplib.php +++ b/mod/assign/feedback/file/importziplib.php @@ -41,13 +41,13 @@ class assignfeedback_file_zip_importer { * * @param assign $assignment - The assignment instance * @param stored_file $fileinfo - The fileinfo - * @param array $participants - A list of valid participants for this module indexed by unique_id - * @param stdClass $user - Set to the user that matches by participant id + * @param array $participants - A list of valid participants for this module indexed by unique_id or group id. + * @param array $users - Set to array with the user(s) that matches by participant id * @param assign_plugin $plugin - Set to the plugin that exported the file * @param string $filename - Set to truncated filename (prefix stripped) - * @return true If the participant Id can be extracted and this is a valid user + * @return bool If the participant Id can be extracted and this is a valid user */ - public function is_valid_filename_for_import($assignment, $fileinfo, $participants, & $user, & $plugin, & $filename) { + public function is_valid_filename_for_import($assignment, $fileinfo, $participants, & $users, & $plugin, & $filename) { if ($fileinfo->is_directory()) { return false; } @@ -91,7 +91,7 @@ class assignfeedback_file_zip_importer { } // Set user, which is by reference, so is used by the calling script. - $user = $participants[$participantid]; + $users = $participants[$participantid]; // Set the plugin. This by reference, and is used by the calling script. $plugin = $assignment->get_plugin_by_type($info[2], $info[3]); @@ -121,17 +121,27 @@ class assignfeedback_file_zip_importer { * Does this file exist in any of the current files supported by this plugin for this user? * * @param assign $assignment - The assignment instance - * @param stdClass $user The user matching this uploaded file + * @param array|stdClass $users The user(s) matching this uploaded file * @param assign_plugin $plugin The matching plugin from the filename * @param string $filename The parsed filename from the zip * @param stored_file $fileinfo The info about the extracted file from the zip * @return bool - True if the file has been modified or is new */ - public function is_file_modified($assignment, $user, $plugin, $filename, $fileinfo) { + public function is_file_modified($assignment, $users, $plugin, $filename, $fileinfo) { $sg = null; + if (is_array($users)) { + $user = $users[0]; + } else { + $user = $users; + } + if ($plugin->get_subtype() == 'assignsubmission') { - $sg = $assignment->get_user_submission($user->id, false); + if ($assignment->get_instance()->teamsubmission) { + $sg = $assignment->get_group_submission($user->id, 0, false); + } else { + $sg = $assignment->get_user_submission($user->id, false); + } } else if ($plugin->get_subtype() == 'assignfeedback') { $sg = $assignment->get_user_grade($user->id, false); } else { @@ -228,6 +238,33 @@ class assignfeedback_file_zip_importer { return $files; } + /** + * Returns a mapping from unique user / group ids in folder names to array of moodle users. + * + * @param assign $assignment - The assignment instance + * @return array the mapping. + */ + public function get_participant_mapping(assign $assignment): array { + $currentgroup = groups_get_activity_group($assignment->get_course_module(), true); + $allusers = $assignment->list_participants($currentgroup, false); + $participants = array(); + foreach ($allusers as $user) { + if ($assignment->get_instance()->teamsubmission) { + $group = $assignment->get_submission_group($user->id); + if (!$group) { + continue; + } + if (!isset($participants[$group->id])) { + $participants[$group->id] = []; + } + $participants[$group->id][] = $user; + } else { + $participants[$assignment->get_uniqueid_for_user($user->id)] = [$user]; + } + } + return $participants; + } + /** * Process an uploaded zip file * @@ -249,67 +286,63 @@ class assignfeedback_file_zip_importer { $fs = get_file_storage(); $files = $this->get_import_files($contextid); - $currentgroup = groups_get_activity_group($assignment->get_course_module(), true); - $allusers = $assignment->list_participants($currentgroup, false); - $participants = array(); - foreach ($allusers as $user) { - $participants[$assignment->get_uniqueid_for_user($user->id)] = $user; - } + $participants = $this->get_participant_mapping($assignment); foreach ($files as $unzippedfile) { - // Set the timeout for unzipping each file. - $user = null; + $users = null; $plugin = null; $filename = ''; - if ($this->is_valid_filename_for_import($assignment, $unzippedfile, $participants, $user, $plugin, $filename)) { - if ($this->is_file_modified($assignment, $user, $plugin, $filename, $unzippedfile)) { - $grade = $assignment->get_user_grade($user->id, true); + if ($this->is_valid_filename_for_import($assignment, $unzippedfile, $participants, $users, $plugin, $filename)) { + if ($this->is_file_modified($assignment, $users, $plugin, $filename, $unzippedfile)) { + foreach ($users as $user) { + $grade = $assignment->get_user_grade($user->id, true); - // In 3.1 the default download structure of the submission files changed so that each student had their own - // separate folder, the files were not renamed and the folder structure was kept. It is possible that - // a user downloaded the submission files in 3.0 (or earlier) and edited the zip to add feedback or - // changed the behavior back to the previous format, the following code means that we will still support the - // old file structure. For more information please see - MDL-52489 / MDL-56022. - $path = pathinfo($filename); - if ($path['dirname'] == '.') { // Student submissions are not in separate folders. - $basename = $filename; - $dirname = "/"; - $dirnamewslash = "/"; - } else { - $basename = $path['basename']; - $dirname = $path['dirname']; - $dirnamewslash = $dirname . "/"; + // In 3.1 the default download structure of the submission files changed so that each student had their own + // separate folder, the files were not renamed and the folder structure was kept. It is possible that + // a user downloaded the submission files in 3.0 (or earlier) and edited the zip to add feedback or + // changed the behavior back to the previous format, the following code means that we will still support the + // old file structure. For more information please see - MDL-52489 / MDL-56022. + $path = pathinfo($filename); + if ($path['dirname'] == '.') { // Student submissions are not in separate folders. + $basename = $filename; + $dirname = "/"; + $dirnamewslash = "/"; + } else { + $basename = $path['basename']; + $dirname = $path['dirname']; + $dirnamewslash = $dirname . "/"; + } + + if ($oldfile = $fs->get_file($contextid, + 'assignfeedback_file', + ASSIGNFEEDBACK_FILE_FILEAREA, + $grade->id, + $dirname, + $basename)) { + // Update existing feedback file. + $oldfile->replace_file_with($unzippedfile); + $feedbackfilesupdated++; + } else { + // Create a new feedback file. + $newfilerecord = new stdClass(); + $newfilerecord->contextid = $contextid; + $newfilerecord->component = 'assignfeedback_file'; + $newfilerecord->filearea = ASSIGNFEEDBACK_FILE_FILEAREA; + $newfilerecord->filename = $basename; + $newfilerecord->filepath = $dirnamewslash; + $newfilerecord->itemid = $grade->id; + $fs->create_file_from_storedfile($newfilerecord, $unzippedfile); + $feedbackfilesadded++; + } + $userswithnewfeedback[$user->id] = 1; + + // Update the number of feedback files for this user. + $fileplugin->update_file_count($grade); + + // Update the last modified time on the grade which will trigger student notifications. + $assignment->notify_grade_modified($grade); } - - if ($oldfile = $fs->get_file($contextid, - 'assignfeedback_file', - ASSIGNFEEDBACK_FILE_FILEAREA, - $grade->id, - $dirname, - $basename)) { - // Update existing feedback file. - $oldfile->replace_file_with($unzippedfile); - $feedbackfilesupdated++; - } else { - // Create a new feedback file. - $newfilerecord = new stdClass(); - $newfilerecord->contextid = $contextid; - $newfilerecord->component = 'assignfeedback_file'; - $newfilerecord->filearea = ASSIGNFEEDBACK_FILE_FILEAREA; - $newfilerecord->filename = $basename; - $newfilerecord->filepath = $dirnamewslash; - $newfilerecord->itemid = $grade->id; - $fs->create_file_from_storedfile($newfilerecord, $unzippedfile); - $feedbackfilesadded++; - } - $userswithnewfeedback[$user->id] = 1; - - // Update the number of feedback files for this user. - $fileplugin->update_file_count($grade); - - // Update the last modified time on the grade which will trigger student notifications. - $assignment->notify_grade_modified($grade); } } }