diff --git a/conf/defaults.config b/conf/defaults.config index 6bd4f18998..3f117cc694 100644 --- a/conf/defaults.config +++ b/conf/defaults.config @@ -739,6 +739,7 @@ $authen{admin_module} = ['WeBWorK::Authen::Basic_TheLastOption']; change_password => "student", change_email_address => "student", change_pg_display_settings => "student", + view_own_answers_early => "nobody", proctor_quiz_login => "login_proctor", proctor_quiz_grade => "grade_proctor", diff --git a/lib/WeBWorK/ConfigValues.pm b/lib/WeBWorK/ConfigValues.pm index 0b5b785bcc..b5c0d37498 100644 --- a/lib/WeBWorK/ConfigValues.pm +++ b/lib/WeBWorK/ConfigValues.pm @@ -641,6 +641,19 @@ sub getConfigValues ($ce) { ), type => 'permission' }, + { + var => 'permissionLevels{view_own_answers_early}', + doc => x('Allowed to view their own answer key early'), + doc2 => x( + 'Users at this level and higher are given a button on the problem set page that lets them ' + . 'override their own answer date for that set to the current time, immediately making the ' + . 'correct answers to problems in that set available to them. If their close date and/or ' + . 'reduced scoring date for the set are still in the future, those are also moved up to the ' + . 'current time. This cannot be undone by the student. By default this is disabled ' + . '("nobody").' + ), + type => 'permission' + }, { var => 'permissionLevels{navigation_allowed}', doc => x('Allowed to view course home page'), diff --git a/lib/WeBWorK/ContentGenerator/ProblemSet.pm b/lib/WeBWorK/ContentGenerator/ProblemSet.pm index d20438d94d..9c1aaaf2fe 100644 --- a/lib/WeBWorK/ContentGenerator/ProblemSet.pm +++ b/lib/WeBWorK/ContentGenerator/ProblemSet.pm @@ -48,6 +48,46 @@ async sub initialize ($c) { my $effectiveUser = $db->getUser($eUserID); $c->{set} = $authz->{merged_set}; + # Allow a student to view their own answer key early by overriding their answer date to now, if this is + # enabled via the view_own_answers_early permission. If the close date and/or reduced scoring date are still + # in the future, they are moved up to now as well, since they cannot be allowed to remain later than the new + # answer date. + if ($c->param('viewAnswersEarly') + && $authz->hasPermissions($userID, 'view_own_answers_early') + && $userID eq $eUserID + && !$c->{viewSetCheck} + && $c->{set}->assignment_type !~ /gateway/) + { + my $now = time; + if ($now < $c->{set}->answer_date) { + my $userSet = $db->getUserSet($eUserID, $c->{set}->set_id); + if ($userSet) { + my $dueDate = $c->{set}->due_date; + my $reducedScoringDate = $c->{set}->reduced_scoring_date; + + $userSet->answer_date($now); + $userSet->due_date($now) if $dueDate > $now; + $userSet->reduced_scoring_date($now) if $reducedScoringDate && $reducedScoringDate > $now; + + eval { $db->putUserSet($userSet) }; + if ($@) { + $c->log->error("Unable to reveal answers early for set @{[$c->{set}->set_id]} for $eUserID: $@"); + $c->addbadmessage( + $c->maketext( + 'The answer key for this set was not made available due to an internal error.') + ); + } else { + $c->{set}->answer_date($now); + $c->{set}->due_date($now) if $dueDate > $now; + $c->{set}->reduced_scoring_date($now) if $reducedScoringDate && $reducedScoringDate > $now; + $c->addgoodmessage($c->maketext('The answer key for this set is now available.')); + } + } + } else { + $c->addbadmessage($c->maketext('The answer key for this set is already available.')); + } + } + $c->{displayMode} = $user->displayMode || $ce->{pg}{options}{displayMode}; # Import problem records for assignments or test version records for tests now. Then initialize all diff --git a/templates/ContentGenerator/ProblemSet/auxiliary_tools.html.ep b/templates/ContentGenerator/ProblemSet/auxiliary_tools.html.ep index a6f765592b..f54128b1fd 100644 --- a/templates/ContentGenerator/ProblemSet/auxiliary_tools.html.ep +++ b/templates/ContentGenerator/ProblemSet/auxiliary_tools.html.ep @@ -93,6 +93,50 @@ % } % } + % if ( + % $authz->hasPermissions(param('user'), 'view_own_answers_early') + % && $c->{set}->assignment_type !~ /gateway/ + % && param('user') eq param('effectiveUser') + % && time < $c->{set}->answer_date + % ) { + <%= link_to maketext('Show Answers Now') => '#modal_view_answers_early', + role => 'button', + class => 'btn btn-primary', + id => 'popup_view_answers_early', + data => { bs_toggle => 'modal' } + =%> +