MDL-48159 mod_assign: Added setting preventsubmissionnotingroup

If enabled a user will be unable to make a submission unless they are a
member of a group.
This commit is contained in:
Andrew Hancox 2015-03-13 11:23:35 +00:00
parent beaceef9ee
commit e528997a4a
15 changed files with 274 additions and 38 deletions

View File

@ -67,7 +67,8 @@ class backup_assign_activity_structure_step extends backup_activity_structure_st
'attemptreopenmethod',
'maxattempts',
'markingworkflow',
'markingallocation'));
'markingallocation',
'preventsubmissionnotingroup'));
$userflags = new backup_nested_element('userflags');

View File

@ -110,6 +110,9 @@ class restore_assign_activity_structure_step extends restore_activity_structure_
if (!isset($data->markingallocation)) {
$data->markingallocation = 0;
}
if (!isset($data->preventsubmissionnotingroup)) {
$data->preventsubmissionnotingroup = 0;
}
if (!empty($data->preventlatesubmissions)) {
$data->cutoffdate = $data->duedate;

View File

@ -33,6 +33,7 @@
<FIELD NAME="markingworkflow" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="If enabled, marking workflow features will be used in this assignment."/>
<FIELD NAME="markingallocation" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="If enabled, marking allocation features will be used in this assignment"/>
<FIELD NAME="sendstudentnotifications" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="1" SEQUENCE="false" COMMENT="Default for send student notifications checkbox when grading."/>
<FIELD NAME="preventsubmissionnotingroup" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="If enabled a user will be unable to make a submission unless they are a member of a group."/>
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id" COMMENT="The unique id for this assignment instance."/>

View File

@ -616,5 +616,27 @@ function xmldb_assign_upgrade($oldversion) {
upgrade_mod_savepoint(true, 2014122600, 'assign');
}
if ($oldversion < 2015022300) {
// Define field preventsubmissionnotingroup to be added to assign.
$table = new xmldb_table('assign');
$field = new xmldb_field('preventsubmissionnotingroup',
XMLDB_TYPE_INTEGER,
'2',
null,
XMLDB_NOTNULL,
null,
'0',
'sendstudentnotifications');
// Conditionally launch add field preventsubmissionnotingroup.
if (!$dbman->field_exists($table, $field)) {
$dbman->add_field($table, $field);
}
// Assign savepoint reached.
upgrade_mod_savepoint(true, 2015022300, 'assign');
}
return true;
}

View File

@ -915,7 +915,12 @@ class assign_grading_table extends table_sql implements renderable {
$group = false;
$submission = false;
$this->get_group_and_submission($row->id, $group, $submission, -1);
if ($submission) {
if ($instance->teamsubmission && !$group && !$instance->preventsubmissionnotingroup) {
$group = true;
}
if ($group && $submission) {
$timesubmitted = $submission->timemodified;
$status = $submission->status;
} else {

View File

@ -289,6 +289,7 @@ $string['noonlinesubmissions'] = 'This assignment does not require you to submit
$string['nosavebutnext'] = 'Next';
$string['nosubmission'] = 'Nothing has been submitted for this assignment';
$string['nosubmissionsacceptedafter'] = 'No submissions accepted after ';
$string['noteam'] = 'You\'re not a member of any group, please contact your teacher.';
$string['notgraded'] = 'Not graded';
$string['notgradedyet'] = 'Not graded yet';
$string['notsubmittedyet'] = 'Not submitted yet';
@ -309,6 +310,8 @@ $string['page-mod-assign-view'] = 'Assignment module main and submission page';
$string['participant'] = 'Participant';
$string['pluginadministration'] = 'Assignment administration';
$string['pluginname'] = 'Assignment';
$string['preventsubmissionnotingroup'] = 'Require group to make submission';
$string['preventsubmissionnotingroup_help'] = 'If enabled, users who are not members of a group will be unable to make submissions.';
$string['preventsubmissions'] = 'Prevent the user from making any more submissions to this assignment.';
$string['preventsubmissionsshort'] = 'Prevent submission changes';
$string['previous'] = 'Previous';
@ -431,6 +434,7 @@ $string['teamsubmissiongroupingid_help'] = 'This is the grouping that the assign
$string['textinstructions'] = 'Assignment instructions';
$string['timemodified'] = 'Last modified';
$string['timeremaining'] = 'Time remaining';
$string['ungroupedusers'] = 'The setting \'Require group to make submission\' is turned on and some users are not allocated to groups, this will prevent them from submitting assignments.';
$string['unlocksubmissionforstudent'] = 'Allow submissions for student: (id={$a->id}, fullname={$a->fullname}).';
$string['unlocksubmissions'] = 'Unlock submissions';
$string['unlimitedattempts'] = 'Unlimited';

View File

@ -609,6 +609,9 @@ class assign {
if (!empty($formdata->maxattempts)) {
$update->maxattempts = $formdata->maxattempts;
}
if (isset($formdata->preventsubmissionnotingroup)) {
$update->preventsubmissionnotingroup = $formdata->preventsubmissionnotingroup;
}
$update->markingworkflow = $formdata->markingworkflow;
$update->markingallocation = $formdata->markingallocation;
if (empty($update->markingworkflow)) { // If marking workflow is disabled, make sure allocation is disabled.
@ -970,6 +973,9 @@ class assign {
if (!empty($formdata->maxattempts)) {
$update->maxattempts = $formdata->maxattempts;
}
if (isset($formdata->preventsubmissionnotingroup)) {
$update->preventsubmissionnotingroup = $formdata->preventsubmissionnotingroup;
}
$update->markingworkflow = $formdata->markingworkflow;
$update->markingallocation = $formdata->markingallocation;
if (empty($update->markingworkflow)) { // If marking workflow is disabled, make sure allocation is disabled.
@ -1443,11 +1449,12 @@ class assign {
// When a specific group is selected we don't count the default group users.
if ($activitygroup == 0) {
// See if there are any users in the default group.
$defaultusers = $this->get_submission_group_members(0, true);
if (count($defaultusers) > 0) {
$count += 1;
if (empty($this->get_instance()->preventsubmissionnotingroup)) {
// See if there are any users in the default group.
$defaultusers = $this->get_submission_group_members(0, true);
if (count($defaultusers) > 0) {
$count += 1;
}
}
}
} else {
@ -1456,7 +1463,7 @@ class assign {
foreach ($participants as $participant) {
if ($group = $this->get_submission_group($participant->id)) {
$groups[$group->id] = true;
} else {
} else if (empty($this->get_instance()->preventsubmissionnotingroup)) {
$groups[0] = true;
}
}
@ -3054,7 +3061,8 @@ class assign {
'',
$instance->attemptreopenmethod,
$instance->maxattempts,
$this->get_grading_status($userid));
$this->get_grading_status($userid),
$instance->preventsubmissionnotingroup);
$o .= $this->get_renderer()->render($submissionstatus);
}
@ -3465,6 +3473,9 @@ class assign {
$userid = optional_param('userid', $USER->id, PARAM_INT);
$user = $DB->get_record('user', array('id'=>$userid), '*', MUST_EXIST);
if ($userid == $USER->id) {
if (!$this->can_edit_submission($userid, $USER->id)) {
print_error('nopermission');
}
// User is editing their own submission.
require_capability('mod/assign:submit', $this->context);
$title = get_string('editsubmission', 'assign');
@ -3907,7 +3918,7 @@ class assign {
}
$showsubmit = ($showlinks && $this->submissions_open($user->id));
$showsubmit = ($showsubmit && $this->show_submit_button($submission, $teamsubmission));
$showsubmit = ($showsubmit && $this->show_submit_button($submission, $teamsubmission, $user->id));
$extensionduedate = null;
if ($flags) {
@ -3943,7 +3954,8 @@ class assign {
$gradingcontrollerpreview,
$instance->attemptreopenmethod,
$instance->maxattempts,
$gradingstatus);
$gradingstatus,
$instance->preventsubmissionnotingroup);
if (has_capability('mod/assign:submit', $this->get_context(), $user)) {
$o .= $this->get_renderer()->render($submissionstatus);
}
@ -4048,9 +4060,10 @@ class assign {
*
* @param stdClass $submission The users own submission record.
* @param stdClass $teamsubmission The users team submission record if there is one
* @param int $userid The user
* @return bool
*/
protected function show_submit_button($submission = null, $teamsubmission = null) {
protected function show_submit_button($submission = null, $teamsubmission = null, $userid = null) {
if ($teamsubmission) {
if ($teamsubmission->status === ASSIGN_SUBMISSION_STATUS_SUBMITTED) {
// The assignment submission has been completed.
@ -4061,6 +4074,11 @@ class assign {
} else if ($submission && $submission->status === ASSIGN_SUBMISSION_STATUS_SUBMITTED) {
// The user has already clicked the submit button on the team submission.
return false;
} else if (
!empty($this->get_instance()->preventsubmissionnotingroup)
&& $this->get_submission_group($userid) == false
) {
return false;
}
} else if ($submission) {
if ($submission->status === ASSIGN_SUBMISSION_STATUS_SUBMITTED) {
@ -4220,6 +4238,9 @@ class assign {
$activitygroup = groups_get_activity_group($this->get_course_module());
if ($instance->teamsubmission) {
$defaultteammembers = $this->get_submission_group_members(0, true);
$warnofungroupedusers = (count($defaultteammembers) > 0 && $instance->preventsubmissionnotingroup);
$summary = new assign_grading_summary($this->count_teams($activitygroup),
$instance->submissiondrafts,
$this->count_submissions_with_status($draft),
@ -4229,7 +4250,8 @@ class assign {
$instance->duedate,
$this->get_course_module()->id,
$this->count_submissions_need_grading(),
$instance->teamsubmission);
$instance->teamsubmission,
$warnofungroupedusers);
$o .= $this->get_renderer()->render($summary);
} else {
// The active group has already been updated in groups_print_activity_menu().
@ -4243,7 +4265,8 @@ class assign {
$instance->duedate,
$this->get_course_module()->id,
$this->count_submissions_need_grading(),
$instance->teamsubmission);
$instance->teamsubmission,
false);
$o .= $this->get_renderer()->render($summary);
}
}
@ -4584,6 +4607,14 @@ class assign {
$graderid = $USER->id;
}
$instance = $this->get_instance();
if ($userid == $graderid &&
$instance->teamsubmission &&
$instance->preventsubmissionnotingroup &&
$this->get_submission_group($userid) == false) {
return false;
}
if ($userid == $graderid &&
$this->submissions_open($userid) &&
has_capability('mod/assign:submit', $this->context, $graderid)) {

View File

@ -138,6 +138,13 @@ class mod_assign_mod_form extends moodleform_mod {
$mform->freeze('teamsubmission');
}
$name = get_string('preventsubmissionnotingroup', 'assign');
$mform->addElement('selectyesno', 'preventsubmissionnotingroup', $name);
$mform->addHelpButton('preventsubmissionnotingroup',
'preventsubmissionnotingroup',
'assign');
$mform->setType('preventsubmissionnotingroup', PARAM_BOOL);
$name = get_string('requireallteammemberssubmit', 'assign');
$mform->addElement('selectyesno', 'requireallteammemberssubmit', $name);
$mform->addHelpButton('requireallteammemberssubmit', 'requireallteammemberssubmit', 'assign');

View File

@ -386,6 +386,8 @@ class assign_submission_status implements renderable {
public $maxattempts = -1;
/** @var string gradingstatus */
public $gradingstatus = '';
/** @var bool preventsubmissionnotingroup */
public $preventsubmissionnotingroup = 0;
/**
@ -419,6 +421,7 @@ class assign_submission_status implements renderable {
* @param string $attemptreopenmethod - The method of reopening student attempts.
* @param int $maxattempts - How many attempts can a student make?
* @param string $gradingstatus - The submission status (ie. Graded, Not Released etc).
* @param bool $preventsubmissionnotingroup - Prevent submission if user is not in a group
*/
public function __construct($allowsubmissionsfromdate,
$alwaysshowdescription,
@ -447,7 +450,8 @@ class assign_submission_status implements renderable {
$gradingcontrollerpreview,
$attemptreopenmethod,
$maxattempts,
$gradingstatus) {
$gradingstatus,
$preventsubmissionnotingroup) {
$this->allowsubmissionsfromdate = $allowsubmissionsfromdate;
$this->alwaysshowdescription = $alwaysshowdescription;
$this->submission = $submission;
@ -476,6 +480,7 @@ class assign_submission_status implements renderable {
$this->attemptreopenmethod = $attemptreopenmethod;
$this->maxattempts = $maxattempts;
$this->gradingstatus = $gradingstatus;
$this->preventsubmissionnotingroup = $preventsubmissionnotingroup;
}
}
@ -642,6 +647,8 @@ class assign_grading_summary implements renderable {
public $coursemoduleid = 0;
/** @var boolean teamsubmission - Are team submissions enabled for this assignment */
public $teamsubmission = false;
/** @var boolean warnofungroupedusers - Do we need to warn people that there are users without groups */
public $warnofungroupedusers = false;
/**
* constructor
@ -666,7 +673,8 @@ class assign_grading_summary implements renderable {
$duedate,
$coursemoduleid,
$submissionsneedgradingcount,
$teamsubmission) {
$teamsubmission,
$warnofungroupedusers) {
$this->participantcount = $participantcount;
$this->submissiondraftsenabled = $submissiondraftsenabled;
$this->submissiondraftscount = $submissiondraftscount;
@ -677,6 +685,7 @@ class assign_grading_summary implements renderable {
$this->coursemoduleid = $coursemoduleid;
$this->submissionsneedgradingcount = $submissionsneedgradingcount;
$this->teamsubmission = $teamsubmission;
$this->warnofungroupedusers = $warnofungroupedusers;
}
}

View File

@ -271,6 +271,10 @@ class mod_assign_renderer extends plugin_renderer_base {
// Status.
if ($summary->teamsubmission) {
if ($summary->warnofungroupedusers) {
$o .= $this->output->notification(get_string('ungroupedusers', 'assign'));
}
$this->add_table_row_tuple($t, get_string('numberofteams', 'assign'),
$summary->participantcount);
} else {
@ -447,6 +451,8 @@ class mod_assign_renderer extends plugin_renderer_base {
$group = $status->submissiongroup;
if ($group) {
$cell2 = new html_table_cell(format_string($group->name, false, $status->context));
} else if ($status->preventsubmissionnotingroup) {
$cell2 = new html_table_cell(get_string('noteam', 'assign'));
} else {
$cell2 = new html_table_cell(get_string('defaultteam', 'assign'));
}
@ -499,7 +505,10 @@ class mod_assign_renderer extends plugin_renderer_base {
} else {
$row = new html_table_row();
$cell1 = new html_table_cell(get_string('submissionstatus', 'assign'));
if ($status->teamsubmission && $status->teamsubmission->status != ASSIGN_SUBMISSION_STATUS_NEW) {
$group = $status->submissiongroup;
if (!$group && $status->preventsubmissionnotingroup) {
$cell2 = new html_table_cell(get_string('nosubmission', 'assign'));
} else if ($status->teamsubmission && $status->teamsubmission->status != ASSIGN_SUBMISSION_STATUS_NEW) {
$teamstatus = $status->teamsubmission->status;
$submissionsummary = get_string('submissionstatus_' . $teamstatus, 'assign');
$groupid = 0;
@ -667,25 +676,28 @@ class mod_assign_renderer extends plugin_renderer_base {
$row->cells = array($cell1, $cell2);
$t->data[] = $row;
foreach ($status->submissionplugins as $plugin) {
$pluginshowsummary = !$plugin->is_empty($submission) || !$plugin->allow_submissions();
if ($plugin->is_enabled() &&
$plugin->is_visible() &&
$plugin->has_user_summary() &&
$pluginshowsummary) {
if (!$status->teamsubmission || $status->submissiongroup != false || !$status->preventsubmissionnotingroup) {
foreach ($status->submissionplugins as $plugin) {
$pluginshowsummary = !$plugin->is_empty($submission) || !$plugin->allow_submissions();
if ($plugin->is_enabled() &&
$plugin->is_visible() &&
$plugin->has_user_summary() &&
$pluginshowsummary
) {
$row = new html_table_row();
$cell1 = new html_table_cell($plugin->get_name());
$displaymode = assign_submission_plugin_submission::SUMMARY;
$pluginsubmission = new assign_submission_plugin_submission($plugin,
$submission,
$displaymode,
$status->coursemoduleid,
$status->returnaction,
$status->returnparams);
$cell2 = new html_table_cell($this->render($pluginsubmission));
$row->cells = array($cell1, $cell2);
$t->data[] = $row;
$row = new html_table_row();
$cell1 = new html_table_cell($plugin->get_name());
$displaymode = assign_submission_plugin_submission::SUMMARY;
$pluginsubmission = new assign_submission_plugin_submission($plugin,
$submission,
$displaymode,
$status->coursemoduleid,
$status->returnaction,
$status->returnparams);
$cell2 = new html_table_cell($this->render($pluginsubmission));
$row->cells = array($cell1, $cell2);
$t->data[] = $row;
}
}
}
}

View File

@ -252,6 +252,16 @@ if ($ADMIN->fulltree) {
$setting->set_advanced_flag_options(admin_setting_flag::ENABLED, false);
$setting->set_locked_flag_options(admin_setting_flag::ENABLED, false);
$settings->add($setting);
$name = new lang_string('preventsubmissionnotingroup', 'mod_assign');
$description = new lang_string('preventsubmissionnotingroup_help', 'mod_assign');
$setting = new admin_setting_configcheckbox('assign/preventsubmissionnotingroup',
$name,
$description,
0);
$setting->set_advanced_flag_options(admin_setting_flag::ENABLED, false);
$setting->set_locked_flag_options(admin_setting_flag::ENABLED, false);
$settings->add($setting);
}
$ADMIN->add('modassignfolder', $settings);

View File

@ -100,6 +100,7 @@ Feature: Group assignment submissions
| assignsubmission_file_enabled | 0 |
| Students submit in groups | Yes |
| Group mode | No groups |
| Require group to make submission | No |
And I log out
And I log in as "student1"
And I follow "Course 1"

View File

@ -0,0 +1,117 @@
@mod @mod_assign
Feature: Submit assignment without group
As a teacher
I should be able to prevent students submitting team assignments as members of the default group
@javascript
Scenario: Switch between group modes
Given the following "courses" exist:
| fullname | shortname | category | groupmode |
| Course 1 | C1 | 0 | 1 |
| Course 2 | C2 | 0 | 1 |
And the following "activities" exist:
| activity | course | idnumber | name | intro | assignsubmission_onlinetext_enabled | preventsubmissionnotingroup | teamsubmission |
| assign | C1 | assign1 | Allow default group | Test assignment description | 1 | 0 | 1 |
| assign | C1 | assign2 | Require group membership | Test assignment description | 1 | 1 | 1 |
| assign | C2 | assign2 | Require group membership | Test assignment description | 1 | 1 | 1 |
And the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@asd.com |
| student1 | Student | 1 | student1@asd.com |
| student2 | Student | 2 | student2@asd.com |
And the following "groups" exist:
| name | course | idnumber |
| Group 1 | C2 | G1 |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
| student2 | C1 | student |
| teacher1 | C2 | editingteacher |
| student1 | C2 | student |
| student2 | C2 | student |
And I log in as "teacher1"
And I follow "Course 2"
And I expand "Users" node
And I follow "Groups"
And I add "Student 1 (student1@asd.com)" user to "Group 1" group members
And I add "Student 2 (student2@asd.com)" user to "Group 1" group members
And I log out
When I log in as "student1"
And I follow "Course 1"
And I follow "Allow default group"
Then I should not see "You're not a member of any group, please contact your teacher."
And I should see "Nothing has been submitted for this assignment"
And I press "Add submission"
And I set the following fields to these values:
| Online text | I'm the student submission |
And I press "Save changes"
And I press "Submit assignment"
And I press "Continue"
Then I should see "Submitted for grading"
And I follow "Course 1"
And I follow "Require group membership"
Then I should see "You're not a member of any group, please contact your teacher."
And I should see "Nothing has been submitted for this assignment"
And I should not see "Add submission"
And I follow "Home"
And I follow "Course 2"
And I follow "Require group membership"
Then I should not see "You're not a member of any group, please contact your teacher."
And I should see "Nothing has been submitted for this assignment"
And I press "Add submission"
And I set the following fields to these values:
| Online text | I'm the student submission |
And I press "Save changes"
And I press "Submit assignment"
And I press "Continue"
Then I should see "Submitted for grading"
And I log out
When I log in as "student2"
And I follow "Course 1"
And I follow "Allow default group"
Then I should see "Submitted for grading"
And I follow "Home"
And I follow "Course 2"
And I follow "Require group membership"
Then I should see "Submitted for grading"
And I log out
And I log in as "teacher1"
And I follow "Course 1"
And I follow "Allow default group"
And I should see "1" in the "Groups" "table_row"
And I should not see "The setting 'Require group to make submission' is turned on and some users are not allocated to groups, this will prevent them from submitting assignments."
And I follow "View/grade all submissions"
And I should see "Default group" in the "Student 1" "table_row"
And I should see "Default group" in the "Student 2" "table_row"
And I should see "Submitted for grading" in the "Student 1" "table_row"
And I should see "Submitted for grading" in the "Student 2" "table_row"
And I follow "Require group membership"
And I should see "0" in the "Groups" "table_row"
And I should see "The setting 'Require group to make submission' is turned on and some users are not allocated to groups, this will prevent them from submitting assignments."
And I follow "View/grade all submissions"
And I should see "Default group" in the "Student 1" "table_row"
And I should see "Default group" in the "Student 2" "table_row"
And I should not see "Submitted for grading" in the "Student 1" "table_row"
And I should not see "Submitted for grading" in the "Student 2" "table_row"
And I follow "Home"
And I follow "Course 2"
And I follow "Require group membership"
And I should see "1" in the "Groups" "table_row"
And I should not see "The setting 'Require group to make submission' is turned on and some users are not allocated to groups, this will prevent them from submitting assignments."
And I follow "View/grade all submissions"
And I should see "Group 1" in the "Student 1" "table_row"
And I should see "Group 1" in the "Student 2" "table_row"
And I should see "Submitted for grading" in the "Student 1" "table_row"
And I should see "Submitted for grading" in the "Student 2" "table_row"

View File

@ -640,12 +640,25 @@ class mod_assign_locallib_testcase extends mod_assign_base_testcase {
$this->getDataGenerator()->create_grouping_group(array('groupid' => $this->groups[0]->id, 'groupingid' => $grouping->id));
$this->getDataGenerator()->create_grouping_group(array('groupid' => $this->groups[1]->id, 'groupingid' => $grouping->id));
// No active group => 2 groups + the default one.
$assign2 = $this->create_instance(array('teamsubmission' => 1, 'teamsubmissiongroupingid' => $grouping->id));
// No active group and non group submissions allowed => 2 groups + the default one.
$params = array(
'teamsubmission' => 1,
'teamsubmissiongroupingid' => $grouping->id,
'preventsubmissionnotingroup' => false
);
$assign2 = $this->create_instance($params);
$this->assertEquals(3, $assign2->count_teams());
// An active group => Just the selected one.
$this->assertEquals(1, $assign2->count_teams($this->groups[0]->id));
// No active group and non group submissions allowed => 2 groups + no default one.
$params = array('teamsubmission' => 1, 'teamsubmissiongroupingid' => $grouping->id, 'preventsubmissionnotingroup' => true);
$assign3 = $this->create_instance($params);
$this->assertEquals(2, $assign3->count_teams());
$assign4 = $this->create_instance(array('teamsubmission' => 1, 'preventsubmissionnotingroup' => true));
$this->assertEquals(self::GROUP_COUNT, $assign4->count_teams());
}
public function test_submit_to_default_group() {

View File

@ -25,6 +25,6 @@
defined('MOODLE_INTERNAL') || die();
$plugin->component = 'mod_assign'; // Full name of the plugin (used for diagnostics).
$plugin->version = 2014122600; // The current module version (Date: YYYYMMDDXX).
$plugin->version = 2015022300; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2014110400; // Requires this Moodle version.
$plugin->cron = 60;