If you want to create a new page for developers, you should create it on the Moodle Developer Resource site.

Roles and modules

From MoodleDocs
Warning: This page is no longer in use. The information contained on the page should NOT be seen as relevant or reliable.

This is a page for developers that describes how to make Moodle modules work under 1.7 roles system. =) For more background information, please read Roles. For any clarifications please post to the Roles and Capabilities forum.


Moodle 1.6 and below uses 7 default roles, namely primary admin, admin, editing teachers, non-editing teachers, students and guests. The set of capabilities that users associated to these roles can perform is fixed. To check permissions, we normally use isteacheredit($courseid), isguest() etc.

Under the new 1.7 system, roles do not have a fixed set of capabilities anymore. We use a different function called has_capability() to check for specific capabilities, more on this later.


Context is an important concept to make roles work. There are currently 6 levels:

define('CONTEXT_SYSTEM', 10);
define('CONTEXT_USER', 30);
define('CONTEXT_COURSECAT', 40);
define('CONTEXT_COURSE', 50);
define('CONTEXT_MODULE', 70);
define('CONTEXT_BLOCK', 80);

They are stored as a tuple [contextlevel][instanceid]. For example course with id =2 would be [50][2]. Module with id 495 would be [70][495].

At module level, you only need to worry about CONTEXT_MODULE. Normally, foreach page accessible in your module you would need to load the module using context_module::instance(). The way to use it for modules is $context = context_module::instance($cm->id); where $cm is the course module object that you would normally have anyway. The contextid is needed for every permission check later on in all your pages.

Please note that CONTEXT_PERSONAL (present in 1.7-1.8) was never implemented and was removed in 1.9. CONTEXT_GROUP is also not implemented and can not be used.

has_capability ($capability, $contextid, $kill)

Parameters for this function:

  • $capability is the name of the capability
  • $contextid is normally $context->id, the module context id
  • $kill: Set to 1 if you want to kill the page, it will throw an error and inform the user that required permission is missing.

For example you place has_capability('forum_read', $context->id, true) at the top of the page to prevent users from reading the whole page.

This function looks up a capability for a given context and associated parents recursively. We are pretty much relying on this function alone to resolve all capability issues. Legacy functions isteacher(), isadmin(), isstudent() etc. should all be changed accordingly.

Loading capabilities

(for now, this plan might change later)

Loading capabilities is done when a user first log in. Because it is quite an expensive call, we only load it once and stores everything in the session. So when has_capability() is called, it looks for the values stored in the session variable.

Code rewrite

Some modules might require some tiny rewrites because permission is only checked once at the top, for example some scripts only checks for isstudent() at the top. Now we are able to refine those capabilities, so we need to put the required code changes (add has_capability()) to where the specific capability is needed. For example, in a forum we check to see if user is a student before displaying a discussion page, now we need to check individual permissions for forum_read and forum_reply.

Sample code

// somewhere at the top, after getting $cm, load context

$context = context_module::instance($cm->id); 


  has_capability('forum_read', $context, $userid, TRUE); 
  // kills this page if user is not allowed to read


if (has_capability('forum_reply', $context)) {

Core API

The core API is located at lib/accesslib, if you would like to read it :-)

See also