Skip to content

Commit

Permalink
MDL-82120 core_grades: Add before penalty recalculation hook
Browse files Browse the repository at this point in the history
  • Loading branch information
Fragonite authored and Nathan Nguyen committed Nov 24, 2024
1 parent 404afb4 commit a849a1d
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 0 deletions.
66 changes: 66 additions & 0 deletions grade/classes/hook/before_penalty_recalculation.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?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 core_grades\hook;

use core\context\module;
use core\hook\stoppable_trait;
use Psr\EventDispatcher\StoppableEventInterface;

/**
* Hook before grade penalty recalculation is applied.
*
* This hook will be dispatched before the penalty recalculation is applied to the grade.
* Allow plugins to do penalty recalculation.
*
* @package core_grades
* @copyright 2024 Catalyst IT Australia Pty Ltd
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
#[\core\attribute\label('Notify plugins that grade penalty recalculation is needed.')]
#[\core\attribute\tags('grade')]
class before_penalty_recalculation implements StoppableEventInterface {
use stoppable_trait;

/** @var \context $context The context in which the recalculation applies. */
public readonly \context $context;

/** @var int $usermodified The user who triggered the event. */
public readonly int $usermodified;

/** @var int $timestamp The timestamp when the event was triggered. */
public readonly int $timestamp;

/**
* Constructor for the hook.
*
* @param \context $context The context object
* @param int|null $userid The user who triggered the event
*/
public function __construct(\context $context, ?int $userid = null) {
global $USER;

// Throw error if context is not a module context or course context.
// We do not allow recalculation at system level, at it is risky and may cause performance issue.
if ($context->contextlevel !== CONTEXT_MODULE && $context->contextlevel !== CONTEXT_COURSE) {
throw new \coding_exception('Invalid context level for grade penalty recalculation.');
}

$this->context = $context;
$this->usermodified = $userid ?? $USER->id;
$this->timestamp = time();
}
}
5 changes: 5 additions & 0 deletions grade/penalty/duedate/lang/en/gradepenalty_duedate.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,9 @@
$string['pluginname'] = 'Late submission penalties';
$string['privacy:metadata:gradepenalty_duedate_rule'] = 'Grade penalty due date table';
$string['privacy:metadata:gradepenalty_duedate_rule:usermodified'] = 'User who modified the rule';
$string['recalculatepenalty'] = 'Penalty recalculation';
$string['resetconfirm'] = 'This will remove all rules set up for this context. Are you sure you want to continue?';
$string['recalculatepenalty_help'] = 'Recalculate and apply penalties for all submissions in this context.';
$string['recalculatepenaltybutton'] = 'Update grades';
$string['recalculatepenaltyconfirm'] = 'This will recalculate and apply penalties for all submissions in this context. Are you sure you want to continue?';
$string['recalculatepenaltysuccess'] = 'Successfully initiated penalty recalculation. There may be a delay before grades are updated.';
38 changes: 38 additions & 0 deletions grade/penalty/duedate/manage_penalty_rule.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
*/

use core\output\notification;
use core_grades\hook\before_penalty_recalculation;
use gradepenalty_duedate\output\form\edit_penalty_form;
use gradepenalty_duedate\output\view_penalty_rule_action_bar;
use gradepenalty_duedate\output\edit_penalty_rule_action_bar;
Expand All @@ -37,6 +38,7 @@
$returnurl = optional_param('returnurl', '', PARAM_LOCALURL);
$edit = optional_param('edit', 0, PARAM_INT);
$reset = optional_param('reset', 0, PARAM_INT);
$recalculate = optional_param('recalculate', 0, PARAM_INT);
$deleteeall = optional_param('deleteallrules', 0, PARAM_INT);

// Check login and permissions.
Expand Down Expand Up @@ -96,6 +98,26 @@
penalty_rule::reset_rules($contextid);
}

// Check if the recalculate button is clicked.
if ($recalculate) {
// Show message for user confirmation.
$confirmurl = new moodle_url($url->out(), [
'contextid' => $contextid,
'recalculateconfirm' => 1,
'sesskey' => sesskey(),
]);
echo $OUTPUT->header();
echo $OUTPUT->confirm(get_string('recalculatepenaltyconfirm', 'gradepenalty_duedate'), $confirmurl, $url);
echo $OUTPUT->footer();
die;

} else if (optional_param('recalculateconfirm', 0, PARAM_INT) && confirm_sesskey()) {
// Create and dispatch the recalculation event.
$hook = new before_penalty_recalculation($context);
\core\di::get(\core\hook\manager::class)->dispatch($hook);
redirect($url, get_string('recalculatepenaltysuccess', 'gradepenalty_duedate'), 0, notification::NOTIFY_SUCCESS);
}

// Only initialize the form if we are in edit mode.
if ($edit) {
// Create a form to add / edit penalty rules.
Expand Down Expand Up @@ -123,6 +145,22 @@
$renderer = $PAGE->get_renderer('core_grades');
echo $renderer->render_action_bar($actionbar);

// Display the penalty recalculation button at course/module context.
if ($context->contextlevel == CONTEXT_COURSE || $context->contextlevel == CONTEXT_MODULE) {
echo $OUTPUT->heading_with_help(get_string('recalculatepenalty', 'gradepenalty_duedate'),
'recalculatepenalty',
'gradepenalty_duedate',
'',
'',
5);
$buttonurl = $url;
$buttonurl->params(['contextid' => $contextid, 'recalculate' => 1]);
echo $OUTPUT->single_button($buttonurl, get_string('recalculatepenaltybutton', 'gradepenalty_duedate'), 'get',
['type' => 'primary']);
// The empty paragraph is used as a spacer.
echo $OUTPUT->paragraph('');
}

// Display the penalty table.
echo $OUTPUT->heading(get_string('existingrule', 'gradepenalty_duedate'), 5);
$penaltytable = new penalty_rule_table('penalty_rule_table', $contextid);
Expand Down

0 comments on commit a849a1d

Please sign in to comment.