Commit 770c9cdc authored by Astor Bizard's avatar Astor Bizard
Browse files

Added override options for startdate, duedate, reductionbyevaluation and freeevaluations.

parent 017015fe
<?php
// This file is part of VPL for Moodle - http://vpl.dis.ulpgc.es/
//
// VPL for 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.
//
// VPL for 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 VPL for Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Class for logging of override updated events
*
* @package mod_vpl
* @copyright 2014 onwards Juan Carlos Rodríguez-del-Pino, 2021 Astor Bizard
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_vpl\event;
defined( 'MOODLE_INTERNAL' ) || die();
require_once(dirname( __FILE__ ) . '/../../locallib.php');
class override_base extends base {
public static function get_objectid_mapping() {
return array('db' => VPL_OVERRIDES, 'restore' => VPL_OVERRIDES);
}
public static function get_other_mapping() {
// Nothing to map.
return false;
}
protected function init() {
$this->data ['crud'] = 'u';
$this->data ['edulevel'] = self::LEVEL_TEACHING;
$this->data ['objecttable'] = VPL_OVERRIDES;
}
public static function log($vpl, $overrideid = null) {
if (is_array($vpl)) {
$info = $vpl;
} else {
$vplinstance = $vpl->get_instance();
$info = array (
'objectid' => $overrideid,
'contextid' => $vpl->get_context()->id,
'courseid' => $vplinstance->course,
'other' => array('vplid' => $vplinstance->id),
);
}
parent::log( $info );
}
public function get_url() {
return $this->get_url_base( 'view.php' );
}
public function get_description_mod($mod) {
$desc = 'The user with id ' . $this->userid . ' ' . $mod;
$desc .= ' override with id ' . $this->objectid . ' of VPL activity with id ' . $this->other['vplid'];
if ($this->relateduserid) {
$desc .= ' for user with id ' . $this->relateduserid;
}
return $desc;
}
}
<?php
// This file is part of VPL for Moodle - http://vpl.dis.ulpgc.es/
//
// VPL for 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.
//
// VPL for 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 VPL for Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Class for logging of override created events
*
* @package mod_vpl
* @copyright 2014 onwards Juan Carlos Rodríguez-del-Pino, 2021 Astor Bizard
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_vpl\event;
defined( 'MOODLE_INTERNAL' ) || die();
require_once(dirname( __FILE__ ) . '/../../locallib.php');
class override_created extends override_base {
protected function init() {
parent::init();
$this->data ['crud'] = 'c';
$this->legacyaction = 'created override';
}
public function get_description() {
return $this->get_description_mod( 'created' );
}
}
<?php
// This file is part of VPL for Moodle - http://vpl.dis.ulpgc.es/
//
// VPL for 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.
//
// VPL for 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 VPL for Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Class for logging of override deleted events
*
* @package mod_vpl
* @copyright 2014 onwards Juan Carlos Rodríguez-del-Pino, 2021 Astor Bizard
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_vpl\event;
defined('MOODLE_INTERNAL') || die();
require_once(dirname(__FILE__).'/../../locallib.php');
class override_deleted extends override_base {
protected function init() {
parent::init();
$this->data['crud'] = 'd';
$this->legacyaction = 'deleted override';
}
public function get_description() {
return $this->get_description_mod( 'deleted' );
}
}
<?php
// This file is part of VPL for Moodle - http://vpl.dis.ulpgc.es/
//
// VPL for 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.
//
// VPL for 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 VPL for Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Class for logging of override updated events
*
* @package mod_vpl
* @copyright 2014 onwards Juan Carlos Rodríguez-del-Pino, 2021 Astor Bizard
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_vpl\event;
defined( 'MOODLE_INTERNAL' ) || die();
require_once(dirname( __FILE__ ) . '/../../locallib.php');
class override_updated extends override_base {
protected function init() {
parent::init();
$this->data ['crud'] = 'u';
$this->legacyaction = 'updated override';
}
public function get_description() {
return $this->get_description_mod( 'updated' );
}
}
<?xml version="1.0" encoding="UTF-8" ?>
<XMLDB PATH="mod/vpl/db" VERSION="20171119" COMMENT="XMLDB file for Moodle mod/vpl"
<XMLDB PATH="mod/vpl/db" VERSION="20210526" COMMENT="XMLDB file for Moodle mod/vpl"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../../lib/xmldb/xmldb.xsd"
>
......@@ -22,7 +22,7 @@
<FIELD NAME="visiblegrade" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="1" SEQUENCE="false" COMMENT="0 visible grade no, 1 yes"/>
<FIELD NAME="usevariations" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Boolean to set if use variations or not in this vpl"/>
<FIELD NAME="variationtitle" TYPE="char" LENGTH="255" NOTNULL="false" SEQUENCE="false" COMMENT="Variation tittle, is show with the variation description"/>
<FIELD NAME="usableasbase" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="0" SEQUENCE="false" />
<FIELD NAME="usableasbase" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="basedon" TYPE="int" LENGTH="10" NOTNULL="false" SEQUENCE="false" COMMENT="Optionally, set the VPL id from this will be based on"/>
<FIELD NAME="run" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Let the student Run the program intertive (0=no, 1=yes)"/>
<FIELD NAME="debug" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Let to the student debug the program"/>
......@@ -132,5 +132,20 @@
<INDEX NAME="userid_id" UNIQUE="true" FIELDS="userid, id" COMMENT="Index for userid id"/>
</INDEXES>
</TABLE>
<TABLE NAME="vpl_overrides" COMMENT="Overrides to VPL settings assigned to users">
<FIELDS>
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true"/>
<FIELD NAME="vpl" TYPE="int" LENGTH="10" NOTNULL="false" SEQUENCE="false" COMMENT="VPL id"/>
<FIELD NAME="userids" TYPE="text" NOTNULL="false" SEQUENCE="false" COMMENT="Users this override applies to"/>
<FIELD NAME="groupids" TYPE="text" NOTNULL="false" SEQUENCE="false" COMMENT="Groups this override applies to"/>
<FIELD NAME="startdate" TYPE="int" LENGTH="10" NOTNULL="false" SEQUENCE="false" COMMENT="If set, date the vpl will be available"/>
<FIELD NAME="duedate" TYPE="int" LENGTH="10" NOTNULL="false" SEQUENCE="false" COMMENT="If set, after this date this vpl instance will not be available"/>
<FIELD NAME="freeevaluations" TYPE="int" LENGTH="10" NOTNULL="false" SEQUENCE="false" COMMENT="If set, number of automatic evaluations that do not reduce final score"/>
<FIELD NAME="reductionbyevaluation" TYPE="char" LENGTH="10" NOTNULL="false" SEQUENCE="false" COMMENT="If set, reduce final score by a value or percentage for each automatic evaluation"/>
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
</KEYS>
</TABLE>
</TABLES>
</XMLDB>
</XMLDB>
\ No newline at end of file
......@@ -323,5 +323,31 @@ function xmldb_vpl_upgrade($oldversion = 0) {
// VPL savepoint reached.
upgrade_mod_savepoint( true, 2018011314, 'vpl' );
}
if ($oldversion < 2021052600) {
// Define table vpl_overrides to be created.
$table = new xmldb_table('vpl_overrides');
// Adding fields to table vpl_overrides.
$table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
$table->add_field('vpl', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
$table->add_field('userids', XMLDB_TYPE_TEXT, null, null, null, null, null);
$table->add_field('groupids', XMLDB_TYPE_TEXT, null, null, null, null, null);
$table->add_field('startdate', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
$table->add_field('duedate', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
$table->add_field('freeevaluations', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
$table->add_field('reductionbyevaluation', XMLDB_TYPE_CHAR, '10', null, null, null, null);
// Adding keys to table vpl_overrides.
$table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
// Conditionally launch create table for vpl_overrides.
if (!$dbman->table_exists($table)) {
$dbman->create_table($table);
}
// Vpl savepoint reached.
upgrade_mod_savepoint(true, 2021052600, 'vpl');
}
return true;
}
......@@ -180,9 +180,8 @@ class mod_vpl_edit{
$files = self::get_requested_files( $vpl );
$compilationexecution = new stdClass();
$compilationexecution->nevaluations = 0;
$vplinstance = $vpl->get_instance();
$compilationexecution->freeevaluations = $vplinstance->freeevaluations;
$compilationexecution->reductionbyevaluation = $vplinstance->reductionbyevaluation;
$compilationexecution->freeevaluations = $vpl->get_effective_setting('freeevaluations', $userid);
$compilationexecution->reductionbyevaluation = $vpl->get_effective_setting('reductionbyevaluation', $userid);
}
return $files;
......@@ -227,8 +226,8 @@ class mod_vpl_edit{
$compilationexecution = new stdClass();
$compilationexecution->grade = '';
$compilationexecution->nevaluations = 0;
$compilationexecution->freeevaluations = $vplinstance->freeevaluations;
$compilationexecution->reductionbyevaluation = $vplinstance->reductionbyevaluation;
$compilationexecution->freeevaluations = $vpl->get_effective_setting('freeevaluations', $userid);
$compilationexecution->reductionbyevaluation = $vpl->get_effective_setting('reductionbyevaluation', $userid);
$response->compilationexecution = $compilationexecution;
}
return $response;
......
......@@ -121,9 +121,10 @@ try {
default :
throw new Exception( 'ajax action error: ' + $action );
}
$timeleft = $instance->duedate - time();
$duedate = $vpl->get_effective_setting('duedate', $userid);
$timeleft = $duedate - time();
$hour = 60 * 60;
if ( $instance->duedate > 0 && $timeleft > -$hour ) {
if ( $duedate > 0 && $timeleft > -$hour ) {
$outcome->response->timeLeft = $timeleft;
}
} catch ( Exception $e ) {
......
......@@ -95,9 +95,10 @@ if ( $copy ) {
$options ['loadajaxurl'] = $loadajaxurl . '&action=';
}
$options ['download'] = "../views/downloadsubmission.php?id={$id}&userid={$linkuserid}";
$timeleft = $instance->duedate - time();
$duedate = $vpl->get_effective_setting('duedate', $linkuserid);
$timeleft = $duedate - time();
$hour = 60 * 60;
if ( $instance->duedate > 0 && $timeleft > -$hour ) {
if ( $duedate > 0 && $timeleft > -$hour ) {
$options ['timeLeft'] = $timeleft;
}
if ( $subid ) {
......
<?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/>.
/**
* Override definitions form
*
* @package mod_vpl
* @copyright 2021 Astor Bizard
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require_once(__DIR__ . '/../../../config.php');
require_once(__DIR__ . '/../locallib.php');
require_once(__DIR__ . '/../vpl.class.php');
global $CFG;
require_once($CFG->libdir . '/formslib.php');
function vpl_get_overrideactions($id, $overrideid, $editing) {
global $OUTPUT, $PAGE;
if ($editing == $overrideid) {
vpl_include_jsfile('override.js');
$save = '<span class="btn-link override-action-button" onclick="VPL.submitOverrideForms();">' .
$OUTPUT->pix_icon( 'save', get_string('save'), 'mod_vpl' ) .
'</span>';
$cancel = '<span class="btn-link override-action-button" onclick="VPL.cancelOverrideForms();">' .
$OUTPUT->pix_icon( 'cancel', get_string('cancel'), 'mod_vpl' ) .
'</span>';
return $save . $cancel;
} else if ($editing === null) {
$edit = '<a href="?id=' . $id . '&edit=' . $overrideid . '">' .
$OUTPUT->pix_icon( 'editthis', get_string('edit'), 'mod_vpl' ) .
'</a>';
$deletebuttonid = 'delete_override_' . $overrideid;
$delete = '<a id="' . $deletebuttonid . '" href="?id=' . $id . '&delete=' . $overrideid . '">' .
$OUTPUT->pix_icon( 'delete', get_string('delete'), 'mod_vpl' ) .
'</a>';
$PAGE->requires->event_handler('#' . $deletebuttonid, 'click', 'M.util.show_confirm_dialog',
array('message' => get_string('confirmoverridedeletion', VPL)));
return $edit . $delete;
} else {
return '';
}
}
/**
* TODO
* @param stdClass $override
* @param stdClass $vplinstance
* @param stdClass $oldoverride
* @param boolean $delete
*/
function vpl_update_override_calendar_events($override, $vplinstance, $oldoverride = null, $delete = false) {
global $DB, $CFG;
require_once($CFG->dirroot . '/calendar/lib.php');
$targets = array(
'userid' => CALENDAR_EVENT_USER_OVERRIDE_PRIORITY,
'groupid' => $override->id
);
foreach ($targets as $target => $priority) { // Process once for users and once for groups.
$params = array(
'modulename' => VPL,
'instance' => $vplinstance->id,
'priority' => $priority
);
if ($oldoverride !== null && !empty($oldoverride->{$target . 's'})) {
$oldtargets = array_fill_keys(explode(',', $oldoverride->{$target . 's'}), false);
} else {
$oldtargets = array();
}
if (!empty($override->{$target . 's'})) {
foreach (explode(',', $override->{$target . 's'}) as $userorgroupid) { // Loop over users or groups.
$params[$target] = $userorgroupid;
$currenteventid = $DB->get_field( 'event', 'id', $params ); // Get current calendar event.
if (isset($override->override_duedate) && !$delete) {
if ($target == 'userid') {
$userorgroupname = fullname($DB->get_record( 'user', array('id' => $userorgroupid) ));
} else {
$userorgroupname = groups_get_group($userorgroupid)->name;
}
$newevent = vpl_create_event($vplinstance, $vplinstance->id);
$newevent->name = get_string('overridefor', VPL, array(
'base' => $newevent->name,
'for' => $userorgroupname
));
if ($target == 'userid') {
// User overrides events do not show correctly if courseid is non zero.
$newevent->courseid = 0;
}
$newevent->timestart = $override->duedate;
$newevent->timesort = $override->duedate;
$newevent->{$target} = $userorgroupid;
$newevent->priority = $priority;
if ($currenteventid === false) {
// No event exist for current user or group, create a new one.
calendar_event::create( $newevent );
} else {
// An event already exists, update it.
calendar_event::load( $currenteventid )->update( $newevent );
}
} else {
if ($currenteventid !== false) {
calendar_event::load( $currenteventid )->delete();
}
}
// This user or group is in newly processed data (or has already been removed).
$oldtargets[$userorgroupid] = true;
}
}
// Discard events related to users or groups removed from override.
foreach ($oldtargets as $oldtarget => $tokeep) {
if (!$tokeep) {
$params[$target] = $oldtarget;
$eventid = $DB->get_field( 'event', 'id', $params );
if ($eventid !== false) {
calendar_event::load( $eventid )->delete();
}
}
}
}
}
class vpl_override_users_form extends moodleform {
protected $users;
protected $groups;
public function __construct($users, $groups) {
$this->users = $users;
$this->groups = $groups;
parent::__construct();
$this->_form->updateAttributes(array('id' => 'vpl_override_users_form'));
}
protected function definition() {
global $CFG;
$mform = &$this->_form;
foreach (array('users', 'groups') as $field) {
if ($this->$field !== null) {
$mform->addElement('html', '<div>');
$mform->addElement('autocomplete', $field, get_string($field), $this->$field, array('multiple' => true));
$mform->addElement('html', '</div>');
}
}
}
}
class vpl_override_options_form extends moodleform {
protected $id;
protected $overrideid;
public function __construct($id, $overrideid) {
$this->id = $id;
$this->overrideid = $overrideid;
parent::__construct();
$this->_form->updateAttributes(array('id' => 'vpl_override_options_form'));
}
protected function definition() {
$mform = &$this->_form;
$mform->addElement('hidden', 'id', $this->id);
$mform->setType('id', PARAM_RAW);
$mform->addElement('hidden', 'update', $this->overrideid);
$mform->setType('update', PARAM_RAW);
$mform->addElement('hidden', 'edit', $this->overrideid);
$mform->setType('edit', PARAM_RAW);
$mform->addElement('hidden', 'userids');
$mform->setType('userids', PARAM_RAW);
$mform->addElement('hidden', 'groupids');
$mform->setType('groupids', PARAM_RAW);
foreach (array('startdate', 'duedate') as $datefield) {
$mform->addElement('html', '<div class="override-option">');
$mform->addElement('checkbox', 'override_' . $datefield, get_string( $datefield, VPL ), get_string( 'override', VPL ));
$mform->addHelpButton('override_' . $datefield, 'override', VPL);
$mform->addElement('date_time_selector', $datefield, null, array('optional' => true));
$mform->disabledIf($datefield, 'override_' . $datefield);
$mform->addElement('html', '</div>');
}
foreach (array('reductionbyevaluation', 'freeevaluations') as $textfield) {
$mform->addElement('html', '<div class="override-option">');
$mform->addElement('checkbox', 'override_' . $textfield, get_string( $textfield, VPL ), get_string( 'override', VPL ));
$mform->addHelpButton('override_' . $textfield, 'override', VPL);
$mform->addElement('text', $textfield, null);
$mform->setType($textfield, PARAM_TEXT);
$mform->setDefault($textfield, 0);
$mform->disabledIf($textfield, 'override_' . $textfield);
$mform->addElement('html', '</div>');
}
$this->add_action_buttons();
}
public static function validate($field, $pattern, $message, & $data, & $errors) {
$data[$field] = trim( $data[$field] );
$res = preg_match($pattern, $data[$field]);
if ( $res == 0 || $res == false) {
$errors[$field] = $message;
}
}
public function validation($data, $files) {
$errors = parent::validation($data, $files);
self::validate('freeevaluations', '/^[0-9]*$/', '[0..]', $data, $errors);
self::validate('reductionbyevaluation', '/^[0-9]*(\.[0-9]+)?%?$/', '#[.#][%]', $data, $errors);
return $errors;
}
}
require_login();
global $PAGE, $OUTPUT, $DB;
$id = required_param( 'id', PARAM_INT );
$edit = optional_param('edit', null, PARAM_INT);
$delete = optional_param('delete', null, PARAM_INT);
$update = optional_param('update', null, PARAM_INT);
$vpl = new mod_vpl( $id );
$vpl->require_capability( VPL_MANAGE_CAPABILITY );
$vpl->prepare_page( 'forms/overrides.php', array( 'id' => $id ) );
$overrides = $DB->get_records( VPL_OVERRIDES, array('vpl' => $id) );
$fields = array('startdate', 'duedate', 'reductionbyevaluation', 'freeevaluations');
// Prepare forms if we are editing or submitting an override.
if ($edit !== null || $update !== null) {
// Compute users that are not already affected to another override.
if (!$vpl->is_group_activity()) {
$alreadyassignedusers = array();
foreach ($overrides as $override) {
if ($override->id != $edit && $override->id != $update && !empty($override->userids)) {
$alreadyassignedusers = array_merge($alreadyassignedusers, explode(',', $override->userids));
}
}
$availableusers = array_map('fullname',
array_filter(get_enrolled_users(context_module::instance($id)), function($user) use ($alreadyassignedusers) {
return !in_array($user->id, $alreadyassignedusers);
}
));
} else {
$availableusers = null;
}
// Compute groups that are not already affected to another override.
$groups = groups_get_all_groups($vpl->get_course()->id, 0, $vpl->get_course_module()->groupingid);
if (!empty($groups)) {
$alreadyassignedgroups = array();
foreach ($overrides as $override) {
if ($override->id != $edit && $override->id != $update && !empty($override->groupids)) {
$alreadyassignedgroups = array_merge($alreadyassignedgroups, explode(',', $override->groupids));
}
}
$availablegroups = array_filter($groups, function($group) use ($alreadyassignedgroups) {
return !in_array($group->id, $alreadyassignedgroups);
});
$availablegroups = array_map(function($group) {
return $group->name;
}, $availablegroups);
} else {
$availablegroups = null;
}
// Prepare forms.
$usersform = new vpl_override_users_form($availableusers, $availablegroups);
$overrideid = $edit;
if ($overrideid === null) {
$overrideid = $update;
}
$optionsform = new vpl_override_options_form($id, $overrideid);
}
if ($delete !== null) {
$overrideid = $delete;
$override = $DB->get_record( VPL_OVERRIDES, array('id' => $overrideid) );
if ($override !== false) {
// Delete associated calendar events.
vpl_update_override_calendar_events($override, $vpl->get_instance(), null, true);
// Delete the override.
$DB->delete_records( VPL_OVERRIDES, array('id' => $overrideid) );
\mod_vpl\event\override_deleted::log($vpl, $overrideid);
}
// Properly reload the page.
redirect(new moodle_url('/mod/vpl/forms/overrides.php', array( 'id' => $id )));
}
if ($update !== null) {
// Update or create an override.
$override = $optionsform->get_data();
unset($override->id); // The id field of the form is not the override id - do not use it.
if ($override !== null) {
foreach