Skip to content

Commit

Permalink
issue #96: implement restriction by enrolment methods
Browse files Browse the repository at this point in the history
  • Loading branch information
dmitriim committed Oct 23, 2023
1 parent fffeaaf commit bd5ba13
Show file tree
Hide file tree
Showing 11 changed files with 392 additions and 6 deletions.
72 changes: 72 additions & 0 deletions classes/local/restrictions/base.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?php
// This file is part of Moodle - https://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 <https://www.gnu.org/licenses/>.

namespace local_recompletion\local\restrictions;

use admin_settingpage;
use MoodleQuickForm;
use stdClass;

/**
* Base restriction class.
*
* @package local_recompletion
* @author Dmitrii Metelkin <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
abstract class base {

/**
* Check if needs to reset completion for a given user.
*
* @param int $userid - user id.
* @param stdClass $course - course record.
* @param stdClass $config - recompletion config.
*/
abstract public static function should_reset(int $userid, stdClass $course, stdClass $config): bool;

/**
* Add params to form.
*
* @param MoodleQuickForm $mform
*/
public static function editingform(MoodleQuickForm $mform): void {
}

/**
* Set form data after submitting.
*
* @param stdClass $data
*/
public static function set_form_data(stdClass $data): void {
}

/**
* Add site level settings for this plugin.
*
* @param admin_settingpage $settings
*/
public static function settings(admin_settingpage $settings): void {
}

/**
* Get restriction reason.
* @return string
*/
public static function get_restriction_reason(): string {
return get_string('restricted', 'local_recompletion');
}
}
136 changes: 136 additions & 0 deletions classes/local/restrictions/enrol.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
<?php
// This file is part of Moodle - https://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 <https://www.gnu.org/licenses/>.

namespace local_recompletion\local\restrictions;

use admin_settingpage;
use core_component;
use MoodleQuickForm;
use stdClass;

/**
* Enrolment method restriction class.
*
* @package local_recompletion
* @author Dmitrii Metelkin <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class enrol extends base {

/**
* Add params to form.
*
* @param MoodleQuickForm $mform
*/
public static function editingform(MoodleQuickForm $mform): void {
$config = get_config('local_recompletion');
$options = [
'multiple' => true,
'noselectionstring' => get_string('all'),
];

$plugins = array_keys(core_component::get_plugin_list('enrol'));
$enrolplugins = array_map(
fn (string $plugin): string => get_string('pluginname', 'enrol_' . $plugin),
array_combine($plugins, $plugins)
);

$mform->addElement(
'autocomplete',
'restrictenrol',
get_string('restrictenrol', 'local_recompletion'),
$enrolplugins,
$options
);

$mform->setDefault('restrictenrol', $config->restrictenrol);
$mform->addHelpButton('restrictenrol', 'restrictenrol', 'local_recompletion');
}

/**
* Set form data after submitting.
* @param stdClass $data
*/
public static function set_form_data(stdClass $data): void {
if (isset($data->restrictenrol) && is_array($data->restrictenrol)) {
$data->restrictenrol = implode(',', $data->restrictenrol);
}
}

/**
* Add site level settings for this plugin.
*
* @param admin_settingpage $settings
*/
public static function settings(admin_settingpage $settings): void {
$enrolplugins = array_keys(core_component::get_plugin_list('enrol'));
$options = array_map(
fn (string $plugin): string => get_string('pluginname', 'enrol_' . $plugin),
array_combine($enrolplugins, $enrolplugins)
);

$settings->add(new \admin_setting_configmulticheckbox(
'local_recompletion/restrictenrol',
get_string('restrictenrol', 'local_recompletion'),
get_string('restrictenrol_help', 'local_recompletion'),
[],
$options
));
}

/**
* Check if needs to reset completion for a given user.
*
* @param int $userid - user id.
* @param stdClass $course - course record.
* @param stdClass $config - recompletion config.
*/
public static function should_reset(int $userid, stdClass $course, stdClass $config): bool {
global $DB;

// Not restricted to any enrol methods.
if (empty($config->restrictenrol) || !is_string($config->restrictenrol)) {
return true;
}

$allowedenrols = explode(',', $config->restrictenrol);
$courseinstances = enrol_get_instances($course->id, false);

$courseallowedinstances = array_filter($courseinstances, function ($courseinstance) use ($allowedenrols){
return in_array($courseinstance->enrol, $allowedenrols);
});

// Course doesn't have allowed enrolment methods.
if (empty($courseallowedinstances)) {
return false;
}

// Check if a user is enrolled using one of the allowed instances.
list($sql, $params) = $DB->get_in_or_equal(array_keys($courseallowedinstances), SQL_PARAMS_NAMED);
$params['userid'] = $userid;
$userenrolments = $DB->get_records_select('user_enrolments', "enrolid $sql AND userid = :userid", $params);

return !empty($userenrolments);
}

/**
* Get restriction reason.
* @return string
*/
public static function get_restriction_reason(): string {
return get_string('restrictedbyenrol', 'local_recompletion');
}
}
6 changes: 6 additions & 0 deletions classes/recompletion_form.php
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,12 @@ public function definition() {
$fqn::editingform($mform);
}

$mform->addElement('header', 'restrictionsheader', get_string('restrictionsheader', 'local_recompletion'));
$restrictions = local_recompletion_get_supported_restrictions();
foreach ($restrictions as $plugin) {
$fqn = 'local_recompletion\\local\\restrictions\\' . $plugin;
$fqn::editingform($mform);
}
$mform->disabledIf('deletegradedata', 'recompletiontype', 'eq', '');
$mform->disabledIf('archivecompletiondata', 'recompletiontype', 'eq', '');
$mform->disabledIf('archivecompletiondata', 'forcearchive', 'eq');
Expand Down
14 changes: 13 additions & 1 deletion classes/task/check_recompletion.php
Original file line number Diff line number Diff line change
Expand Up @@ -195,13 +195,26 @@ protected function notify_user($userid, $course, $config) {
*/
public function reset_user($userid, $course, $config = null) {
global $CFG, $DB;

$errors = [];

if (empty($config)) {
$config = (object) $DB->get_records_menu('local_recompletion_config',
['course' => $course->id], '', 'name, value');
}
if (empty($config->recompletiontype)) {
throw new \moodle_exception('recompletionnotenabled', 'local_recompletion');
}

$restrictions = local_recompletion_get_supported_restrictions();
foreach ($restrictions as $plugin) {
$fqn = 'local_recompletion\\local\\restrictions\\' . $plugin;
if (!$fqn::should_reset($userid, $course, $config)) {
$errors[] = $fqn::get_restriction_reason();
return $errors;
}
}

// Archive and delete course completion.
$this->reset_completions($userid, $course, $config);

Expand All @@ -219,7 +232,6 @@ public function reset_user($userid, $course, $config = null) {
}

$plugins = local_recompletion_get_supported_plugins();
$errors = [];
foreach ($plugins as $plugin) {
$fqn = 'local_recompletion\\plugins\\' . $plugin;
$error = $fqn::reset($userid, $course, $config);
Expand Down
7 changes: 7 additions & 0 deletions lang/en/local_recompletion.php
Original file line number Diff line number Diff line change
Expand Up @@ -196,3 +196,10 @@
$string['h5pattempts'] = 'H5P attempts (mod_h5pactivity)';
$string['h5pattempts_help'] = 'How to handle H5P attempts within the course. If archive is selected, the old H5P attempts will be archived in the local_recompletion_h5p and local_recompletion_h5pr tables.';
$string['archiveh5p'] = 'Archive old H5P attempts (mod_h5pactivity)';
$string['pluginssettings'] = 'Plugins settings';
$string['restrictionsettings'] = 'Restrictions settings';
$string['restrictenrol'] = 'Enrol method';
$string['restrictenrol_help'] = 'Ony users enrolled with selected enrol methods will be included in resetting completion data. If none selected, that means no restrictions on enrolment method for users.';
$string['restrictionsheader'] = 'Restrictions';
$string['restricted'] = 'Resetting completion for a given user is restricted';
$string['restrictedbyenrol'] = 'Resetting completion for a given user is restricted by enrolment method';
26 changes: 26 additions & 0 deletions locallib.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,39 @@ function local_recompletion_get_supported_plugins() {
return $plugins;
}

/**
* Get list of supported restriction classes.
* @return array
*/
function local_recompletion_get_supported_restrictions(): array {
global $CFG;

$restrictions = [];
$files = scandir($CFG->dirroot. '/local/recompletion/classes/local/restrictions');
foreach ($files as $file) {
$class = clean_param(str_replace('.php', '', $file), PARAM_ALPHANUMEXT);
if (!empty($class) && $class !== 'base') {
$restrictions[] = $class;
}
}

return $restrictions;
}

/**
* Loads form data.
*
* @param string[] $mformdata
* @return object
*/
function local_recompletion_set_form_data($mformdata) {

$restrictions = local_recompletion_get_supported_restrictions();
foreach ($restrictions as $plugin) {
$fqn = 'local_recompletion\\local\\restrictions\\' . $plugin;
$fqn::set_form_data($mformdata);
}

$data = (array)$mformdata;
if (key_exists('recompletionemailbody', $data)) {
$recompletionemailbody = $data['recompletionemailbody'];
Expand Down
7 changes: 6 additions & 1 deletion recompletion.php
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,11 @@
$setnames[] = 'archive'.$plugin;
}

$restrictions = local_recompletion_get_supported_restrictions();
foreach ($restrictions as $plugin) {
$setnames[] = 'restrict' . $plugin;
}

// Create the settings form instance.
$form = new local_recompletion_recompletion_form('recompletion.php?id='.$id, array('course' => $course));

Expand Down Expand Up @@ -121,7 +126,7 @@
}
}
// Redirect to the course main page.
$url = new moodle_url('/course/view.php', array('id' => $course->id));
$url = new moodle_url('/local/recompletion/recompletion.php', array('id' => $course->id));
redirect($url, get_string('recompletionsettingssaved', 'local_recompletion'));
} else if (!empty($config)) {
$form->set_data(local_recompletion_get_data($config));
Expand Down
5 changes: 3 additions & 2 deletions resetcompletion.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,11 @@

$context = context_course::instance($course->id);
if ($USER->id <> $userid) {
$cancelurl = new moodle_url('/local/recompletion/participants.php', array('id' => $course->id));
require_capability('local/recompletion:manage', $context);
$user = $DB->get_record('user', array('id' => $userid));
} else {
$cancelurl = course_get_url($course);
require_capability('local/recompletion:resetmycompletion', $context);
$user = $USER;
}
Expand All @@ -63,7 +65,7 @@
$returnurl = course_get_url($course);
}
if (!empty($errors)) {
redirect($returnurl, explode(',', $errors), '', \core\output\notification::NOTIFY_WARNING);
redirect($returnurl, implode(', ', $errors), '', \core\output\notification::NOTIFY_WARNING);
} else {
redirect($returnurl, get_string('completionresetuser', 'local_recompletion', fullname($user)));
}
Expand All @@ -80,7 +82,6 @@
echo $OUTPUT->header();
echo $OUTPUT->heading(get_string("resetcompletionfor", "local_recompletion", fullname($user)));

$cancelurl = course_get_url($course);
$confirmurl = $PAGE->url;
$confirmurl->param('confirm', 1);
$confirmurl->param('user', $userid);
Expand Down
17 changes: 17 additions & 0 deletions settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,26 @@
new lang_string('forcearchivecompletiondata', 'local_recompletion'),
new lang_string('forcearchivecompletiondata_help', 'local_recompletion'), 0));

$settings->add(new admin_setting_heading('local_recompletion/pluginsettings',
get_string('pluginssettings', 'local_recompletion'),
''
));

$plugins = local_recompletion_get_supported_plugins();
foreach ($plugins as $plugin) {
$fqn = 'local_recompletion\\plugins\\' . $plugin;
$fqn::settings($settings);
}

$settings->add(new admin_setting_heading('local_recompletion/restrictionsettings',
get_string('restrictionsettings', 'local_recompletion'),
''
));

$restrictions = local_recompletion_get_supported_restrictions();
foreach ($restrictions as $plugin) {
$fqn = 'local_recompletion\\local\\restrictions\\' . $plugin;
$fqn::settings($settings);
}

}
Loading

0 comments on commit bd5ba13

Please sign in to comment.