diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..6817050
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+.remote-sync.json
diff --git a/README.md b/README.md
index 07b251f..9b4bfad 100644
--- a/README.md
+++ b/README.md
@@ -1,9 +1,9 @@
moodle-availability_role
========================
-[![Moodle Plugin CI](https://github.com/moodle-an-hochschulen/moodle-availability_role/workflows/Moodle%20Plugin%20CI/badge.svg?branch=master)](https://github.com/moodle-an-hochschulen/moodle-availability_role/actions?query=workflow%3A%22Moodle+Plugin+CI%22+branch%3Amaster)
+[![Moodle Plugin CI](https://github.com/moodle-an-hochschulen/moodle-availability_role/workflows/Moodle%20Plugin%20CI/badge.svg?branch=MOODLE_402_STABLE)](https://github.com/moodle-an-hochschulen/moodle-availability_role/actions?query=workflow%3A%22Moodle+Plugin+CI%22+branch%3AMOODLE_402_STABLE)
-Moodle availability plugin which lets users restrict resources, activities and sections based on roles
+Moodle availability plugin which lets users restrict resources, activities and sections based on roles.
Requirements
@@ -15,7 +15,7 @@ This plugin requires Moodle 4.3+
Motivation for this plugin
--------------------------
-If your teachers want to restrict activities / resources / sections in their course to a subset of the course participants and these course participants share a common course role, this plugin is for you.
+If your teachers want to restrict activities / resources / sections in their course to a subset of the course participants and these course participants share a common course role, a course category role or global role, this plugin is for you.
Have a look at an example:
diff --git a/classes/condition.php b/classes/condition.php
index 4ae6cd5..b37ddc0 100644
--- a/classes/condition.php
+++ b/classes/condition.php
@@ -36,6 +36,11 @@
class condition extends \core_availability\condition {
/** @var int ID of role that this condition requires */
protected $roleid = 0;
+ /** @var int ID of type that this condition requires */
+ protected $typeid = 0;
+ public const ROLETYPE_COURSE = 0;
+ public const ROLETYPE_COURSECAT = 1;
+ public const ROLETYPE_CORE = 2;
/**
* Constructor.
@@ -50,6 +55,11 @@ public function __construct($structure) {
} else {
throw new \coding_exception('Invalid ->id for role condition');
}
+ if (!empty($structure->typeid)) {
+ $this->typeid = $structure->typeid;
+ } else {
+ $this->typeid = self::ROLETYPE_COURSE;
+ }
}
/**
@@ -61,6 +71,7 @@ public function save() {
$result = (object)['type' => 'role'];
if ($this->roleid) {
$result->id = $this->roleid;
+ $result->typeid = $this->typeid;
} else {
$result->activity = true;
}
@@ -115,40 +126,63 @@ public function update_after_restore($restoreid, $courseid, \base_logger $logger
*/
public function is_available($not, \core_availability\info $info, $grabthelot, $userid) {
global $USER, $CFG;
- $context = \context_course::instance($info->get_course()->id);
$allow = false;
- // Is the user's course role switched?
- if (!empty($USER->access['rsw'][$context->path])) {
- // Check only switched role.
- if ($USER->access['rsw'][$context->path] == $this->roleid) {
- $allow = true;
- }
- // Or is the user currently having his own role(s)?
- } else {
- // Check all of the user's course roles.
- foreach (get_user_roles($context, $userid) as $role) {
- if ($role->roleid == $this->roleid) {
- $allow = true;
- break;
+ switch($this->typeid) {
+ case self::ROLETYPE_CORE:
+ $context = \context_system::instance();
+ foreach (get_user_roles($context, $userid) as $role) {
+ if ($role->roleid == $this->roleid) {
+ $allow = true;
+ break;
+ }
}
- }
+ break;
+ case self::ROLETYPE_COURSECAT:
+ $context = \context_coursecat::instance($info->get_course()->category);
+ // Check all of the user's course roles.
+ foreach (get_user_roles($context, $userid) as $role) {
+ if ($role->roleid == $this->roleid) {
+ $allow = true;
+ break;
+ }
+ }
+ break;
+ default:
+ $context = \context_course::instance($info->get_course()->id);
+ // Is the user's course role switched?
+ if (!empty($USER->access['rsw'][$context->path])) {
+ // Check only switched role.
+ if ($USER->access['rsw'][$context->path] == $this->roleid) {
+ $allow = true;
+ }
+ // Or is the user currently having his own role(s)?
+ } else {
+ // Check all of the user's course roles.
+ foreach (get_user_roles($context, $userid) as $role) {
+ if ($role->roleid == $this->roleid) {
+ $allow = true;
+ break;
+ }
+ }
+ }
+ }
- // As get_user_roles only returns roles for enrolled users, we have to check whether a user
- // is viewing the course as guest or is not logged in separately.
+ // As get_user_roles only returns roles for enrolled users, we have to check whether a user
+ // is viewing the course as guest or is not logged in separately.
- // Is the user not logged in?
- if (empty($userid) || isguestuser($userid)) {
- if ($CFG->notloggedinroleid == $this->roleid) {
- $allow = true;
- }
+ // Is the user not logged in?
+ if (empty($userid) || isguestuser($userid)) {
+ if ($CFG->notloggedinroleid == $this->roleid) {
+ $allow = true;
}
+ }
- // Is the user viewing the course as guest?
- if (is_guest($context, $userid)) {
- if (get_guest_role()->id == $this->roleid) {
- $allow = true;
- }
+ // Is the user viewing the course as guest?
+ $context = \context_course::instance($info->get_course()->id);
+ if (is_guest($context, $userid)) {
+ if (get_guest_role()->id == $this->roleid) {
+ $allow = true;
}
}
diff --git a/classes/frontend.php b/classes/frontend.php
index f72a438..eb8c8bd 100644
--- a/classes/frontend.php
+++ b/classes/frontend.php
@@ -45,21 +45,56 @@ class frontend extends \core_availability\frontend {
* @return array
*/
protected function get_javascript_init_params($course, \cm_info $cm = null, \section_info $section = null) {
+ global $CFG, $DB;
+ require_once($CFG->dirroot . '/availability/condition/role/classes/condition.php');
+
// Change to JS array format and return.
- $jsarray = [];
- $context = \context_course::instance($course->id);
+ $idcourse = get_string('course');
+ $idcoursecat = get_string('coursecategory');
+ $idglobal = get_string('coresystem');
+ $jsarray = array();
// Get all roles for course.
+ $context = \context_course::instance($course->id);
$roles = $this->get_course_roles($context);
+ foreach ($roles as $rec) {
+ $jsarray[] = (object)array(
+ 'id' => $rec->id,
+ 'name' => (!empty($rec->name) ? $rec->name : $rec->localname),
+ 'type' => $idcourse,
+ 'typeid' => \availability_role\condition::ROLETYPE_COURSE,
+ );
+ }
+
+ $roles = explode(',', get_config('availability_role', 'coursecatroles'));
+ foreach ($roles as $rec) {
+ $rec = $DB->get_record('role', array('id' => $rec));
+ if (empty($rec->id)) {
+ continue;
+ }
+ $jsarray[] = (object)array(
+ 'id' => $rec->id,
+ 'name' => (!empty($rec->name) ? $rec->name : $rec->shortname),
+ 'type' => $idcoursecat,
+ 'typeid' => \availability_role\condition::ROLETYPE_COURSECAT,
+ );
+ }
+ $roles = explode(',', get_config('availability_role', 'globalroles'));
foreach ($roles as $rec) {
- $jsarray[] = (object)[
+ $rec = $DB->get_record('role', array('id' => $rec));
+ if (empty($rec->id)) {
+ continue;
+ }
+ $jsarray[] = (object)array(
'id' => $rec->id,
- 'name' => $rec->localname,
- ];
+ 'name' => (!empty($rec->name) ? $rec->name : $rec->shortname),
+ 'type' => $idglobal,
+ 'typeid' => \availability_role\condition::ROLETYPE_CORE,
+ );
}
- return [$jsarray];
+ return array($jsarray);
}
/**
diff --git a/lang/en/availability_role.php b/lang/en/availability_role.php
index d017aa2..557c62a 100644
--- a/lang/en/availability_role.php
+++ b/lang/en/availability_role.php
@@ -33,6 +33,10 @@
$string['privacy:metadata'] = 'The Restriction by course role plugin does not store any personal data.';
$string['requires_role'] = 'You are a(n) {$a}';
$string['requires_notrole'] = 'You are not a(n) {$a}';
+$string['setting_coursecatroles'] = 'Supported roles';
+$string['setting_coursecatroles:description'] = 'Specify which courecategory roles are selectable by users to restrict access.';
+$string['setting_globalroles'] = 'Supported roles';
+$string['setting_globalroles:description'] = 'Specify which global roles are selectable by users to restrict access.';
$string['setting_supportedrolesheading'] = 'Supported roles';
$string['setting_supportguestrole'] = 'Guest role';
$string['setting_supportguestrole_desc'] = 'If activated, the availability of activities can be restricted to or forbidden for users that are viewing a course as guest.';
diff --git a/settings.php b/settings.php
index c57aae3..6ff01be 100644
--- a/settings.php
+++ b/settings.php
@@ -45,5 +45,48 @@
$description = get_string('setting_supportnotloggedinrole_desc', 'availability_role', null, true);
$setting = new admin_setting_configcheckbox($name, $title, $description, 0);
$settings->add($setting);
-}
+ // Course category roles.
+ $sql = "SELECT r.*
+ FROM {role} AS r, {role_context_levels} AS rcl
+ WHERE r.id=rcl.roleid
+ AND rcl.contextlevel = ?
+ ORDER BY r.name ASC";
+ $roles = $DB->get_records_sql($sql, array(CONTEXT_COURSECAT));
+ $options = array();
+ foreach ($roles as $role) {
+ $options[$role->id] = (!empty($role->name) ? $role->name : $role->shortname);
+ }
+
+ $settings->add(
+ new admin_setting_configmultiselect(
+ 'availability_role/coursecatroles',
+ get_string('setting_coursecatroles', 'availability_role'),
+ get_string('setting_coursecatroles:description', 'availability_role'),
+ get_config('availability_role', 'coursecatroles'),
+ $options
+ )
+ );
+
+ // Global roles.
+ $sql = "SELECT r.*
+ FROM {role} AS r, {role_context_levels} AS rcl
+ WHERE r.id=rcl.roleid
+ AND rcl.contextlevel = ?
+ ORDER BY r.name ASC";
+ $roles = $DB->get_records_sql($sql, array(CONTEXT_SYSTEM));
+ $options = array();
+ foreach ($roles as $role) {
+ $options[$role->id] = (!empty($role->name) ? $role->name : $role->shortname);
+ }
+
+ $settings->add(
+ new admin_setting_configmultiselect(
+ 'availability_role/globalroles',
+ get_string('setting_globalroles', 'availability_role'),
+ get_string('setting_globalroles:description', 'availability_role'),
+ get_config('availability_role', 'globalroles'),
+ $options
+ )
+ );
+}
diff --git a/version.php b/version.php
index d7317ed..cc3268b 100644
--- a/version.php
+++ b/version.php
@@ -20,14 +20,16 @@
* @package availability_role
* @copyright 2015 Bence Laky, Synergy Learning UK
* on behalf of Alexander Bias, Ulm University
+ * extended to coursecat- and global roles
+ * by Robert Schrenk, Center for Learningmanagement
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
$plugin->component = 'availability_role';
-$plugin->version = 2023102000;
-$plugin->release = 'v4.3-r1';
-$plugin->requires = 2023100900;
-$plugin->supported = [403, 403];
+$plugin->version = 2023090100;
+$plugin->release = 'v4.2-r1';
+$plugin->requires = 2023042400;
+$plugin->supported = [402, 402];
$plugin->maturity = MATURITY_STABLE;
diff --git a/yui/build/moodle-availability_role-form/moodle-availability_role-form-debug.js b/yui/build/moodle-availability_role-form/moodle-availability_role-form-debug.js
index 15de974..61f7716 100644
--- a/yui/build/moodle-availability_role-form/moodle-availability_role-form-debug.js
+++ b/yui/build/moodle-availability_role-form/moodle-availability_role-form-debug.js
@@ -29,16 +29,29 @@ M.availability_role.form.getNode = function(json) {
'' +
'';
var node = Y.Node.create('' + html + '');
// Set initial value if specified.
if (json.id !== undefined &&
- node.one('select[name=id] > option[value=' + json.id + ']')) {
- node.one('select[name=id]').set('value', '' + json.id);
+ node.one('select[name=id] option[value=' + json.typeid + '_' + json.id + ']')) {
+ node.one('select[name=id]').set('value', json.typeid + '_' + json.id);
}
// Add event handlers (first time only).
@@ -59,7 +72,9 @@ M.availability_role.form.fillValue = function(value, node) {
if (selected === 'choose') {
value.id = 'choose';
} else {
- value.id = parseInt(selected, 10);
+ selected = selected.split('_');
+ value.typeid = parseInt(selected[0], 10);
+ value.id = parseInt(selected[1], 10);
}
};
diff --git a/yui/build/moodle-availability_role-form/moodle-availability_role-form-min.js b/yui/build/moodle-availability_role-form/moodle-availability_role-form-min.js
index c18e1fa..fae5599 100644
--- a/yui/build/moodle-availability_role-form/moodle-availability_role-form-min.js
+++ b/yui/build/moodle-availability_role-form/moodle-availability_role-form-min.js
@@ -1 +1 @@
-YUI.add("moodle-availability_role-form",function(a,e){M.availability_role=M.availability_role||{},M.availability_role.form=a.Object(M.core_availability.plugin),M.availability_role.form.roles=null,M.availability_role.form.initInner=function(e){this.roles=e},M.availability_role.form.getNode=function(e){var i,l='",i=a.Node.create(""+l+""),e.id!==undefined&&i.one("select[name=id] > option[value="+e.id+"]")&&i.one("select[name=id]").set("value",""+e.id),M.availability_role.form.addedEvents||(M.availability_role.form.addedEvents=!0,a.one(".availability-field").delegate("change",function(){M.core_availability.form.update()},".availability_role select")),i},M.availability_role.form.fillValue=function(e,i){i=i.one("select[name=id]").get("value");e.id="choose"===i?"choose":parseInt(i,10)},M.availability_role.form.fillErrors=function(e,i){var l={};this.fillValue(l,i),"choose"===l.id&&e.push("availability_role:error_selectrole")}},"@VERSION@",{requires:["base","node","event","moodle-core_availability-form"]});
\ No newline at end of file
+YUI.add("moodle-availability_role-form",function(b,a){M.availability_role=M.availability_role||{};M.availability_role.form=b.Object(M.core_availability.plugin);M.availability_role.form.roles=null;M.availability_role.form.initInner=function(c){this.roles=c};M.availability_role.form.getNode=function(g){var f='";var h=b.Node.create(""+f+"");if(g.id!==undefined&&h.one("select[name=id] option[value="+g.typeid+"_"+g.id+"]")){h.one("select[name=id]").set("value",g.typeid+"_"+g.id)}if(!M.availability_role.form.addedEvents){M.availability_role.form.addedEvents=true;var d=b.one(".availability-field");d.delegate("change",function(){M.core_availability.form.update()},".availability_role select")}return h};M.availability_role.form.fillValue=function(e,d){var c=d.one("select[name=id]").get("value");if(c==="choose"){e.id="choose"}else{c=c.split("_");e.typeid=parseInt(c[0],10);e.id=parseInt(c[1],10)}};M.availability_role.form.fillErrors=function(e,c){var d={};this.fillValue(d,c);if(d.id==="choose"){e.push("availability_role:error_selectrole")}}},"@VERSION@",{requires:["base","node","event","moodle-core_availability-form"]});
\ No newline at end of file
diff --git a/yui/build/moodle-availability_role-form/moodle-availability_role-form.js b/yui/build/moodle-availability_role-form/moodle-availability_role-form.js
index 15de974..61f7716 100644
--- a/yui/build/moodle-availability_role-form/moodle-availability_role-form.js
+++ b/yui/build/moodle-availability_role-form/moodle-availability_role-form.js
@@ -29,16 +29,29 @@ M.availability_role.form.getNode = function(json) {
'' +
'';
var node = Y.Node.create('' + html + '');
// Set initial value if specified.
if (json.id !== undefined &&
- node.one('select[name=id] > option[value=' + json.id + ']')) {
- node.one('select[name=id]').set('value', '' + json.id);
+ node.one('select[name=id] option[value=' + json.typeid + '_' + json.id + ']')) {
+ node.one('select[name=id]').set('value', json.typeid + '_' + json.id);
}
// Add event handlers (first time only).
@@ -59,7 +72,9 @@ M.availability_role.form.fillValue = function(value, node) {
if (selected === 'choose') {
value.id = 'choose';
} else {
- value.id = parseInt(selected, 10);
+ selected = selected.split('_');
+ value.typeid = parseInt(selected[0], 10);
+ value.id = parseInt(selected[1], 10);
}
};
diff --git a/yui/src/form/js/form.js b/yui/src/form/js/form.js
index 88f1c13..2b4fa0d 100644
--- a/yui/src/form/js/form.js
+++ b/yui/src/form/js/form.js
@@ -27,16 +27,29 @@ M.availability_role.form.getNode = function(json) {
'' +
'';
var node = Y.Node.create('' + html + '');
// Set initial value if specified.
if (json.id !== undefined &&
- node.one('select[name=id] > option[value=' + json.id + ']')) {
- node.one('select[name=id]').set('value', '' + json.id);
+ node.one('select[name=id] option[value=' + json.typeid + '_' + json.id + ']')) {
+ node.one('select[name=id]').set('value', json.typeid + '_' + json.id);
}
// Add event handlers (first time only).
@@ -57,7 +70,9 @@ M.availability_role.form.fillValue = function(value, node) {
if (selected === 'choose') {
value.id = 'choose';
} else {
- value.id = parseInt(selected, 10);
+ selected = selected.split('_');
+ value.typeid = parseInt(selected[0], 10);
+ value.id = parseInt(selected[1], 10);
}
};