MDL-64231 mod_assign: download submissions with group folder

This commit is contained in:
Ferran Recio
2022-10-27 11:11:12 +02:00
parent 35f39c45b7
commit b9900c2b45
5 changed files with 762 additions and 163 deletions
+289
View File
@@ -0,0 +1,289 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace mod_assign;
use assign;
use core_php_time_limit;
use mod_assign\event\all_submissions_downloaded;
use core\session\manager as sessionmanager;
use core_files\archive_writer;
use stdClass;
use assign_plugin;
use stored_file;
/**
* Class to download user submissions.
*
* @package mod_assign
* @copyright 2022 Ferran Recio <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class downloader {
/** @var assign the module manager instance. */
private $manager;
/** @var stdClass the assign instance record. */
private $instance;
/** @var array|null the selected user ids, if any. */
private $userids = null;
/** @var int $groupmode the activity group mode. */
private $groupmode = '';
/** @var int $groupid the exported groupid. */
private $groupid = 0;
/** @var array $filesforzipping the files to zipo (path => file) */
protected $filesforzipping;
/** @var array $prefixes all loaded the student prefixes.
*
* A prefix will be converted into a file prefix or a folder name (depends on downloadasfolders).
*/
private $prefixes;
/** @var int $downloadasfolders the files to zipo (path => file) */
private $downloadasfolders;
/**
* Class constructor.
*
* @param assign $manager the instance manager
* @param array|null $userids the user ids to download.
*/
public function __construct(assign $manager, ?array $userids = null) {
$this->manager = $manager;
$this->userids = $userids;
$this->instance = $manager->get_instance();
$this->downloadasfolders = get_user_preferences('assign_downloadasfolders', 1);
$cm = $manager->get_course_module();
$this->groupmode = groups_get_activity_groupmode($cm);
if ($this->groupmode) {
$this->groupid = groups_get_activity_group($cm, true);
}
}
/**
* Load the filelist.
*
* @return bool true if there are some files to zip.
*/
public function load_filelist(): bool {
$manager = $this->manager;
$groupid = $this->groupid;
// Increase the server timeout to handle the creation and sending of large zip files.
core_php_time_limit::raise();
$manager->require_view_grades();
// Load all users with submit.
$students = get_enrolled_users(
$manager->get_context(),
"mod/assign:submit",
0,
'u.*',
null,
0,
0,
$manager->show_only_active_users()
);
// Build a list of files to zip.
$this->filesforzipping = [];
// Get all the files for each student.
foreach ($students as $student) {
// Download all assigments submission or only selected users.
if ($this->userids && !in_array($student->id, $this->userids)) {
continue;
}
if (!groups_is_member($groupid, $student->id) && $this->groupmode && $groupid) {
continue;
}
$this->load_student_filelist($student);
}
return !empty($this->filesforzipping);
}
/**
* Load an individual student filelist.
*
* @param stdClass $student the user record
*/
private function load_student_filelist(stdClass $student) {
$submission = $this->get_student_submission($student);
if (!$submission) {
return;
}
$prefix = $this->get_student_prefix($student);
if (isset($this->prefixes[$prefix])) {
// We already send that file (in group mode).
return;
}
$this->prefixes[$prefix] = $student->id;
foreach ($this->manager->get_submission_plugins() as $plugin) {
if (!$plugin->is_enabled() || !$plugin->is_visible()) {
continue;
}
$this->load_submissionplugin_filelist($student, $plugin, $submission, $prefix);
}
}
/**
* Return the student submission if any.
*
* @param stdClass $student the user record
* @return stdClass|null the user submission or null if none
*/
private function get_student_submission(stdClass $student): ?stdClass {
if ($this->instance->teamsubmission) {
$submission = $this->manager->get_group_submission($student->id, 0, false);
} else {
$submission = $this->manager->get_user_submission($student->id, false);
}
return $submission ?: null;
}
/**
* Return the file prefix used to generate the each submission folder or file.
*
* @param stdClass $student the user record
* @return string the submission prefix
*/
private function get_student_prefix(stdClass $student): string {
$manager = $this->manager;
// Team submissions are by group, not by student.
if ($this->instance->teamsubmission) {
$submissiongroup = $manager->get_submission_group($student->id);
if ($submissiongroup) {
$groupname = $submissiongroup->name;
$groupinfo = '_' . $submissiongroup->id;
} else {
$groupname = get_string('defaultteam', 'mod_assign');
$groupinfo = '';
}
$prefix = str_replace('_', ' ', $groupname);
return clean_filename($prefix . $groupinfo);
}
// Individual submissions are by user.
if ($manager->is_blind_marking()) {
$fullname = get_string('participant', 'mod_assign');
} else {
$fullname = fullname($student, has_capability('moodle/site:viewfullnames', $manager->get_context()));
}
$prefix = str_replace('_', ' ', $fullname);
$prefix = clean_filename($prefix . '_' . $manager->get_uniqueid_for_user($student->id));
return $prefix;
}
/**
* Load a submission plugin filelist for a specific user.
*
* @param stdClass $student the user record
* @param assign_plugin $plugin the submission plugin instance
* @param stdClass $submission the submission object
* @param string $prefix the files prefix
*/
private function load_submissionplugin_filelist(
stdClass $student,
assign_plugin $plugin,
stdClass $submission,
string $prefix
) {
$subtype = $plugin->get_subtype();
$type = $plugin->get_type();
if ($this->downloadasfolders) {
// Create a folder for each user for each assignment plugin.
// This is the default behavior for version of Moodle >= 3.1.
$submission->exportfullpath = true;
$pluginfiles = $plugin->get_files($submission, $student);
foreach ($pluginfiles as $zipfilepath => $file) {
$zipfilename = basename($zipfilepath);
$prefixedfilename = clean_filename($prefix . '_' . $subtype . '_' . $type);
if ($type == 'file') {
$pathfilename = $prefixedfilename . $file->get_filepath() . $zipfilename;
} else {
$pathfilename = $prefixedfilename . '/' . $zipfilename;
}
$pathfilename = clean_param($pathfilename, PARAM_PATH);
$this->filesforzipping[$pathfilename] = $file;
}
} else {
// Create a single folder for all users of all assignment plugins.
// This was the default behavior for version of Moodle < 3.1.
$submission->exportfullpath = false;
$pluginfiles = $plugin->get_files($submission, $student);
foreach ($pluginfiles as $zipfilename => $file) {
$prefixedfilename = clean_filename($prefix . '_' . $subtype . '_' . $type . '_' . $zipfilename);
$this->filesforzipping[$prefixedfilename] = $file;
}
}
}
/**
* Download the exported zip.
*
* This method will terminate the current script when the file is send.
*/
public function download_zip() {
$filename = $this->get_zip_filename();
all_submissions_downloaded::create_from_assign($this->manager)->trigger();
sessionmanager::write_close();
$zipwriter = archive_writer::get_stream_writer($filename, archive_writer::ZIP_WRITER);
// Stream the files into the zip.
foreach ($this->filesforzipping as $pathinzip => $file) {
if ($file instanceof stored_file) {
// Most of cases are stored_file.
$zipwriter->add_file_from_stored_file($pathinzip, $file);
} else if (is_array($file)) {
// Save $file as contents, from onlinetext subplugin.
$content = reset($file);
$zipwriter->add_file_from_string($pathinzip, $content);
}
}
// Finish the archive.
$zipwriter->finish();
exit();
}
/**
* Generate the zip filename.
*
* @return string the zip filename
*/
private function get_zip_filename(): string {
$manager = $this->manager;
$filenameparts = [
$manager->get_course()->shortname,
$this->instance->name,
];
if (!empty($this->groupid)) {
$filenameparts[] = groups_get_group_name($this->groupid);
}
$filenameparts[] = $manager->get_course_module()->id;
return clean_filename(implode('-', $filenameparts). '.zip');
}
}
+24 -163
View File
@@ -98,6 +98,7 @@ use \mod_assign\output\grading_app;
use \mod_assign\output\assign_header;
use \mod_assign\output\assign_submission_status;
use mod_assign\output\timelimit_panel;
use mod_assign\downloader;
/**
* Standard base class for mod_assign (assignment types).
@@ -3103,7 +3104,7 @@ class assign {
* @param bool $create If set to true a new submission object will be created in the database
* with the status set to "new".
* @param int $attemptnumber - -1 means the latest attempt
* @return stdClass The submission
* @return stdClass|false The submission
*/
public function get_group_submission($userid, $groupid, $create, $attemptnumber=-1) {
global $DB;
@@ -3661,170 +3662,30 @@ class assign {
/**
* Download a zip file of all assignment submissions.
*
* @param array $userids Array of user ids to download assignment submissions in a zip file
* @param array|null $userids Array of user ids to download assignment submissions in a zip file
* @return string - If an error occurs, this will contain the error page.
*/
protected function download_submissions($userids = false) {
global $CFG, $DB;
// More efficient to load this here.
require_once($CFG->libdir.'/filelib.php');
// Increase the server timeout to handle the creation and sending of large zip files.
core_php_time_limit::raise();
$this->require_view_grades();
// Load all users with submit.
$students = get_enrolled_users($this->context, "mod/assign:submit", null, 'u.*', null, null, null,
$this->show_only_active_users());
// Build a list of files to zip.
$filesforzipping = array();
$fs = get_file_storage();
$groupmode = groups_get_activity_groupmode($this->get_course_module());
// All users.
$groupid = 0;
$groupname = '';
if ($groupmode) {
$groupid = groups_get_activity_group($this->get_course_module(), true);
if (!empty($groupid)) {
$groupname = groups_get_group_name($groupid) . '-';
}
protected function download_submissions($userids = null) {
$downloader = new downloader($this, $userids ?: null);
if ($downloader->load_filelist()) {
$downloader->download_zip();
}
// Construct the zip file name.
$filename = clean_filename($this->get_course()->shortname . '-' .
$this->get_instance()->name . '-' .
$groupname.$this->get_course_module()->id . '.zip');
// Get all the files for each student.
foreach ($students as $student) {
$userid = $student->id;
// Download all assigments submission or only selected users.
if ($userids and !in_array($userid, $userids)) {
continue;
}
if ((groups_is_member($groupid, $userid) or !$groupmode or !$groupid)) {
// Get the plugins to add their own files to the zip.
$submissiongroup = false;
$groupname = '';
if ($this->get_instance()->teamsubmission) {
$submission = $this->get_group_submission($userid, 0, false);
$submissiongroup = $this->get_submission_group($userid);
if ($submissiongroup) {
$groupname = $submissiongroup->name . '-';
} else {
$groupname = get_string('defaultteam', 'assign') . '-';
}
} else {
$submission = $this->get_user_submission($userid, false);
}
if ($this->is_blind_marking()) {
$prefix = str_replace('_', ' ', $groupname . get_string('participant', 'assign'));
$prefix = clean_filename($prefix . '_' . $this->get_uniqueid_for_user($userid));
} else {
$fullname = fullname($student, has_capability('moodle/site:viewfullnames', $this->get_context()));
$prefix = str_replace('_', ' ', $groupname . $fullname);
$prefix = clean_filename($prefix . '_' . $this->get_uniqueid_for_user($userid));
}
if ($submission) {
$downloadasfolders = get_user_preferences('assign_downloadasfolders', 1);
foreach ($this->submissionplugins as $plugin) {
if ($plugin->is_enabled() && $plugin->is_visible()) {
if ($downloadasfolders) {
// Create a folder for each user for each assignment plugin.
// This is the default behavior for version of Moodle >= 3.1.
$submission->exportfullpath = true;
$pluginfiles = $plugin->get_files($submission, $student);
foreach ($pluginfiles as $zipfilepath => $file) {
$subtype = $plugin->get_subtype();
$type = $plugin->get_type();
$zipfilename = basename($zipfilepath);
$prefixedfilename = clean_filename($prefix .
'_' .
$subtype .
'_' .
$type .
'_');
if ($type == 'file') {
$pathfilename = $prefixedfilename . $file->get_filepath() . $zipfilename;
} else if ($type == 'onlinetext') {
$pathfilename = $prefixedfilename . '/' . $zipfilename;
} else {
$pathfilename = $prefixedfilename . '/' . $zipfilename;
}
$pathfilename = clean_param($pathfilename, PARAM_PATH);
$filesforzipping[$pathfilename] = $file;
}
} else {
// Create a single folder for all users of all assignment plugins.
// This was the default behavior for version of Moodle < 3.1.
$submission->exportfullpath = false;
$pluginfiles = $plugin->get_files($submission, $student);
foreach ($pluginfiles as $zipfilename => $file) {
$subtype = $plugin->get_subtype();
$type = $plugin->get_type();
$prefixedfilename = clean_filename($prefix .
'_' .
$subtype .
'_' .
$type .
'_' .
$zipfilename);
$filesforzipping[$prefixedfilename] = $file;
}
}
}
}
}
}
}
$result = '';
if (count($filesforzipping) == 0) {
$header = new assign_header($this->get_instance(),
$this->get_context(),
'',
$this->get_course_module()->id,
get_string('downloadall', 'assign'));
$result .= $this->get_renderer()->render($header);
$result .= $this->get_renderer()->notification(get_string('nosubmission', 'assign'));
$url = new moodle_url('/mod/assign/view.php', array('id'=>$this->get_course_module()->id,
'action'=>'grading'));
$result .= $this->get_renderer()->continue_button($url);
$result .= $this->view_footer();
return $result;
}
// Log zip as downloaded.
\mod_assign\event\all_submissions_downloaded::create_from_assign($this)->trigger();
// Close the session.
\core\session\manager::write_close();
$zipwriter = \core_files\archive_writer::get_stream_writer($filename, \core_files\archive_writer::ZIP_WRITER);
// Stream the files into the zip.
foreach ($filesforzipping as $pathinzip => $file) {
if ($file instanceof \stored_file) {
// Most of cases are \stored_file.
$zipwriter->add_file_from_stored_file($pathinzip, $file);
} else if (is_array($file)) {
// Save $file as contents, from onlinetext subplugin.
$content = reset($file);
$zipwriter->add_file_from_string($pathinzip, $content);
}
}
// Finish the archive.
$zipwriter->finish();
exit();
// Show some notification if we have nothing to download.
$cm = $this->get_course_module();
$renderer = $this->get_renderer();
$header = new assign_header(
$this->get_instance(),
$this->get_context(),
'',
$cm->id,
get_string('downloadall', 'mod_assign')
);
$result = $renderer->render($header);
$result .= $renderer->notification(get_string('nosubmission', 'mod_assign'));
$url = new moodle_url('/mod/assign/view.php', ['id' => $cm->id, 'action' => 'grading']);
$result .= $renderer->continue_button($url);
$result .= $this->view_footer();
return $result;
}
/**
@@ -3890,7 +3751,7 @@ class assign {
* @param int $userid The id of the user whose submission we want or 0 in which case USER->id is used
* @param bool $create If set to true a new submission object will be created in the database with the status set to "new".
* @param int $attemptnumber - -1 means the latest attempt
* @return stdClass The submission
* @return stdClass|false The submission
*/
public function get_user_submission($userid, $create, $attemptnumber=-1) {
global $DB, $USER;
+447
View File
@@ -0,0 +1,447 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace mod_assign;
use context_module;
use assign;
/**
* Downloader tests class for mod_assign.
*
* @package mod_assign
* @category test
* @copyright 2022 Ferran Recio <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @coversDefaultClass \mod_assign\downloader
*/
class downloader_test extends \advanced_testcase {
/**
* Setup to ensure that fixtures are loaded.
*/
public static function setupBeforeClass(): void {
global $CFG;
require_once($CFG->dirroot . '/mod/assign/locallib.php');
}
/**
* Test for load_filelist method.
*
* @covers ::load_filelist
* @dataProvider load_filelist_provider
*
* @param bool $teamsubmission if the assign must have team submissions
* @param array $groupmembers the groups definition
* @param array|null $filterusers the filtered users (null for all users)
* @param bool $blindmarking if the assign has blind marking
* @param bool $downloadasfolder if the download as folder preference is set
* @param array $expected the expected file list
*/
public function test_load_filelist(
bool $teamsubmission,
array $groupmembers,
?array $filterusers,
bool $blindmarking,
bool $downloadasfolder,
array $expected
) {
global $CFG;
$this->resetAfterTest();
$this->setAdminUser();
if (!$downloadasfolder) {
set_user_preference('assign_downloadasfolders', 0);
}
// Create course and enrols.
$course = $this->getDataGenerator()->create_course();
$users = [
'student1' => $this->getDataGenerator()->create_and_enrol($course, 'student'),
'student2' => $this->getDataGenerator()->create_and_enrol($course, 'student'),
'student3' => $this->getDataGenerator()->create_and_enrol($course, 'student'),
'student4' => $this->getDataGenerator()->create_and_enrol($course, 'student'),
'student5' => $this->getDataGenerator()->create_and_enrol($course, 'student'),
];
// Generate groups.
$groups = [];
foreach ($groupmembers as $groupname => $groupusers) {
$group = $this->getDataGenerator()->create_group(['courseid' => $course->id, 'name' => $groupname]);
foreach ($groupusers as $user) {
groups_add_member($group, $users[$user]);
}
$groups[$groupname] = $group;
}
// Create activity.
$params = [
'course' => $course,
'assignsubmission_file_enabled' => 1,
'assignsubmission_file_maxfiles' => 12,
'assignsubmission_file_maxsizebytes' => 1024 * 1024,
];
if ($teamsubmission) {
$params['teamsubmission'] = 1;
$params['preventsubmissionnotingroup'] = false;
}
if ($blindmarking) {
$params['blindmarking'] = 1;
}
$activity = $this->getDataGenerator()->create_module('assign', $params);
$cm = get_coursemodule_from_id('assign', $activity->cmid, 0, false, MUST_EXIST);
$context = context_module::instance($cm->id);
// Generate submissions.
$datagenerator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
$files = [
"mod/assign/tests/fixtures/submissionsample01.txt",
"mod/assign/tests/fixtures/submissionsample02.txt"
];
foreach ($users as $key => $user) {
if ($key == 'student5') {
continue;
}
$datagenerator->create_submission([
'userid' => $user->id,
'assignid' => $cm->id,
'file' => implode(',', $files),
]);
}
// Generate file list.
if ($filterusers) {
foreach ($filterusers as $key => $identifier) {
$filterusers[$key] = $users[$identifier]->id;
}
}
$manager = new assign($context, $cm, $course);
$downloader = new downloader($manager, $filterusers);
$hasfiles = $downloader->load_filelist();
// Expose protected filelist attribute.
$rc = new \ReflectionClass(downloader::class);
$rcp = $rc->getProperty('filesforzipping');
$rcp->setAccessible(true);
// Add some replacements.
$search = ['PARTICIPANT', 'DEFAULTTEAM'];
$replace = [get_string('participant', 'mod_assign'), get_string('defaultteam', 'mod_assign')];
foreach ($users as $identifier => $user) {
$search[] = strtoupper($identifier . '.ID');
$replace[] = $manager->get_uniqueid_for_user($user->id);
$search[] = strtoupper($identifier);
$replace[] = $this->prepare_filename_text(fullname($user));
}
foreach ($groups as $identifier => $group) {
$search[] = strtoupper($identifier . '.ID');
$replace[] = strtoupper($group->id);
$search[] = strtoupper($identifier);
$replace[] = $this->prepare_filename_text($group->name);
}
// Validate values.
$filelist = $rcp->getValue($downloader);
$result = array_keys($filelist);
$this->assertEquals($hasfiles, !empty($expected));
$this->assertCount(count($expected), $result);
foreach ($expected as $path) {
$value = str_replace($search, $replace, $path);
$this->assertTrue(in_array($value, $result));
}
}
/**
* Internal helper to clean a filename text.
*
* @param string $text the text to transform
* @return string the clean string
*/
private function prepare_filename_text(string $text): string {
return clean_filename(str_replace('_', ' ', $text));
}
/**
* Data provider for test_load_filelist().
*
* @return array of scenarios
*/
public function load_filelist_provider(): array {
$downloadasfoldertests = $this->load_filelist_downloadasfolder_scenarios();
$downloadasfilestests = $this->load_filelist_downloadasfiles_scenarios();
return array_merge(
$downloadasfoldertests,
$downloadasfilestests,
);
}
/**
* Generate the standard test scenarios for load_filelist with download as file.
*
* The scenarios are the same as download as folder but replacing the "/" of the files
* by a "_" and setting the downloadasfolder to false.
*
* @return array of scenarios
*/
private function load_filelist_downloadasfiles_scenarios(): array {
$result = $this->load_filelist_downloadasfolder_scenarios("Download as files:");
// Transform paths from files.
foreach ($result as $scenario => $info) {
$info['downloadasfolder'] = false;
foreach ($info['expected'] as $key => $path) {
$info['expected'][$key] = str_replace('/', '_', $path);
}
$result[$scenario] = $info;
}
return $result;
}
/**
* Generate the standard test scenarios for load_filelist with download as folder.
*
* @param string $prefix the scenarios prefix
* @return array of scenarios
*/
private function load_filelist_downloadasfolder_scenarios(string $prefix = "Download as folders:"): array {
return [
// Test without team submissions.
$prefix . ' All users without groups' => [
'teamsubmission' => false,
'groupmembers' => [],
'filterusers' => null,
'blindmarking' => false,
'downloadasfolder' => true,
'expected' => [
'STUDENT1_STUDENT1.ID_assignsubmission_file/submissionsample01.txt',
'STUDENT1_STUDENT1.ID_assignsubmission_file/submissionsample02.txt',
'STUDENT2_STUDENT2.ID_assignsubmission_file/submissionsample01.txt',
'STUDENT2_STUDENT2.ID_assignsubmission_file/submissionsample02.txt',
'STUDENT3_STUDENT3.ID_assignsubmission_file/submissionsample01.txt',
'STUDENT3_STUDENT3.ID_assignsubmission_file/submissionsample02.txt',
'STUDENT4_STUDENT4.ID_assignsubmission_file/submissionsample01.txt',
'STUDENT4_STUDENT4.ID_assignsubmission_file/submissionsample02.txt',
],
],
$prefix . ' Filtered users' => [
'teamsubmission' => false,
'groupmembers' => [],
'filterusers' => ['student1', 'student2'],
'blindmarking' => false,
'downloadasfolder' => true,
'expected' => [
'STUDENT1_STUDENT1.ID_assignsubmission_file/submissionsample01.txt',
'STUDENT1_STUDENT1.ID_assignsubmission_file/submissionsample02.txt',
'STUDENT2_STUDENT2.ID_assignsubmission_file/submissionsample01.txt',
'STUDENT2_STUDENT2.ID_assignsubmission_file/submissionsample02.txt',
],
],
$prefix . ' Filtering users without submissions' => [
'teamsubmission' => false,
'groupmembers' => [],
'filterusers' => ['student1', 'student5'],
'blindmarking' => false,
'downloadasfolder' => true,
'expected' => [
'STUDENT1_STUDENT1.ID_assignsubmission_file/submissionsample01.txt',
'STUDENT1_STUDENT1.ID_assignsubmission_file/submissionsample02.txt',
],
],
$prefix . ' Asking only for users without submissions' => [
'teamsubmission' => false,
'groupmembers' => [],
'filterusers' => ['student5'],
'blindmarking' => false,
'downloadasfolder' => true,
'expected' => [],
],
// Test with team submissions and no default team.
$prefix . ' All users with all users in groups' => [
'teamsubmission' => true,
'groupmembers' => [
'group1' => ['student1'],
'group2' => ['student2', 'student3'],
'group3' => ['student4', 'student5'],
],
'filterusers' => null,
'blindmarking' => false,
'downloadasfolder' => true,
'expected' => [
'GROUP1_GROUP1.ID_assignsubmission_file/submissionsample01.txt',
'GROUP1_GROUP1.ID_assignsubmission_file/submissionsample02.txt',
'GROUP2_GROUP2.ID_assignsubmission_file/submissionsample01.txt',
'GROUP2_GROUP2.ID_assignsubmission_file/submissionsample02.txt',
'GROUP3_GROUP3.ID_assignsubmission_file/submissionsample01.txt',
'GROUP3_GROUP3.ID_assignsubmission_file/submissionsample02.txt',
],
],
$prefix . ' Filtering users with disjoined groups' => [
'teamsubmission' => true,
'groupmembers' => [
'group1' => ['student1'],
'group2' => ['student2', 'student3'],
'group3' => ['student4', 'student5'],
],
'filterusers' => ['student1', 'student2'],
'blindmarking' => false,
'downloadasfolder' => true,
'expected' => [
'GROUP1_GROUP1.ID_assignsubmission_file/submissionsample01.txt',
'GROUP1_GROUP1.ID_assignsubmission_file/submissionsample02.txt',
'GROUP2_GROUP2.ID_assignsubmission_file/submissionsample01.txt',
'GROUP2_GROUP2.ID_assignsubmission_file/submissionsample02.txt',
],
],
$prefix . ' Filtering users with default teams who does not do a submission' => [
'teamsubmission' => true,
'groupmembers' => [
'group1' => ['student1'],
'group2' => ['student2', 'student3'],
'group3' => ['student4', 'student5'],
],
'filterusers' => ['student1', 'student5'],
'blindmarking' => false,
'downloadasfolder' => true,
'expected' => [
'GROUP1_GROUP1.ID_assignsubmission_file/submissionsample01.txt',
'GROUP1_GROUP1.ID_assignsubmission_file/submissionsample02.txt',
'GROUP3_GROUP3.ID_assignsubmission_file/submissionsample01.txt',
'GROUP3_GROUP3.ID_assignsubmission_file/submissionsample02.txt',
],
],
$prefix . ' Filtering users without submission but member of a group' => [
'teamsubmission' => true,
'groupmembers' => [
'group1' => ['student1'],
'group2' => ['student2', 'student3'],
'group3' => ['student4', 'student5'],
],
'filterusers' => [
'student5'
],
'blindmarking' => false,
'downloadasfolder' => true,
'expected' => [
'GROUP3_GROUP3.ID_assignsubmission_file/submissionsample01.txt',
'GROUP3_GROUP3.ID_assignsubmission_file/submissionsample02.txt',
],
],
// Test with default team.
$prefix . ' All users with users in the default team' => [
'teamsubmission' => true,
'groupmembers' => [
'group1' => ['student1', 'student2'],
],
'filterusers' => null,
'blindmarking' => false,
'downloadasfolder' => true,
'expected' => [
'GROUP1_GROUP1.ID_assignsubmission_file/submissionsample01.txt',
'GROUP1_GROUP1.ID_assignsubmission_file/submissionsample02.txt',
'DEFAULTTEAM_assignsubmission_file/submissionsample01.txt',
'DEFAULTTEAM_assignsubmission_file/submissionsample02.txt',
],
],
$prefix . ' Filtered users in groups with users in the default team' => [
'teamsubmission' => true,
'groupmembers' => [
'group1' => ['student1', 'student2'],
],
'filterusers' => ['student1', 'student2'],
'blindmarking' => false,
'downloadasfolder' => true,
'expected' => [
'GROUP1_GROUP1.ID_assignsubmission_file/submissionsample01.txt',
'GROUP1_GROUP1.ID_assignsubmission_file/submissionsample02.txt',
],
],
$prefix . ' Filtered users without groups with users in the default team' => [
'teamsubmission' => true,
'groupmembers' => [
'group1' => ['student1', 'student2'],
],
'filterusers' => ['student3', 'student4'],
'blindmarking' => false,
'downloadasfolder' => true,
'expected' => [
'DEFAULTTEAM_assignsubmission_file/submissionsample01.txt',
'DEFAULTTEAM_assignsubmission_file/submissionsample02.txt',
],
],
$prefix . ' Filtered users with some users in the default team' => [
'teamsubmission' => true,
'groupmembers' => [
'group1' => ['student1', 'student2'],
],
'filterusers' => ['student1', 'student3'],
'blindmarking' => false,
'downloadasfolder' => true,
'expected' => [
'GROUP1_GROUP1.ID_assignsubmission_file/submissionsample01.txt',
'GROUP1_GROUP1.ID_assignsubmission_file/submissionsample02.txt',
'DEFAULTTEAM_assignsubmission_file/submissionsample01.txt',
'DEFAULTTEAM_assignsubmission_file/submissionsample02.txt',
],
],
$prefix . ' Filtering users with joined groups' => [
'teamsubmission' => true,
'groupmembers' => [
'group1' => ['student1', 'student2'],
'group2' => ['student2', 'student3'],
],
'filterusers' => ['student1', 'student2'],
'blindmarking' => false,
'downloadasfolder' => true,
'expected' => [
'GROUP1_GROUP1.ID_assignsubmission_file/submissionsample01.txt',
'GROUP1_GROUP1.ID_assignsubmission_file/submissionsample02.txt',
'DEFAULTTEAM_assignsubmission_file/submissionsample01.txt',
'DEFAULTTEAM_assignsubmission_file/submissionsample02.txt',
],
],
// Tests with blind marking.
$prefix . ' All users without groups and blindmarking' => [
'teamsubmission' => false,
'groupmembers' => [],
'filterusers' => null,
'blindmarking' => true,
'downloadasfolder' => true,
'expected' => [
'PARTICIPANT_STUDENT1.ID_assignsubmission_file/submissionsample01.txt',
'PARTICIPANT_STUDENT1.ID_assignsubmission_file/submissionsample02.txt',
'PARTICIPANT_STUDENT2.ID_assignsubmission_file/submissionsample01.txt',
'PARTICIPANT_STUDENT2.ID_assignsubmission_file/submissionsample02.txt',
'PARTICIPANT_STUDENT3.ID_assignsubmission_file/submissionsample01.txt',
'PARTICIPANT_STUDENT3.ID_assignsubmission_file/submissionsample02.txt',
'PARTICIPANT_STUDENT4.ID_assignsubmission_file/submissionsample01.txt',
'PARTICIPANT_STUDENT4.ID_assignsubmission_file/submissionsample02.txt',
],
],
$prefix . ' Filtered users without groups and blindmarking' => [
'teamsubmission' => false,
'groupmembers' => [],
'filterusers' => ['student1', 'student2'],
'blindmarking' => true,
'downloadasfolder' => true,
'expected' => [
'PARTICIPANT_STUDENT1.ID_assignsubmission_file/submissionsample01.txt',
'PARTICIPANT_STUDENT1.ID_assignsubmission_file/submissionsample02.txt',
'PARTICIPANT_STUDENT2.ID_assignsubmission_file/submissionsample01.txt',
'PARTICIPANT_STUDENT2.ID_assignsubmission_file/submissionsample02.txt',
],
],
];
}
}
+1
View File
@@ -0,0 +1 @@
This is just a submission testing sample.
+1
View File
@@ -0,0 +1 @@
This is just a submission testing sample.