2006-08-08 05:13:06 +00:00
< ? php
2006-08-14 07:15:03 +00:00
/**
* Capability session information format
2006-08-08 05:13:06 +00:00
* 2 x 2 array
* [ context ][ capability ]
* where context is the context id of the table 'context'
* and capability is a string defining the capability
* e . g .
*
* [ Capabilities ] => [ 26 ][ mod / forum : viewpost ] = 1
* [ 26 ][ mod / forum : startdiscussion ] = - 8990
* [ 26 ][ mod / forum : editallpost ] = - 1
* [ 273 ][ moodle : blahblah ] = 1
* [ 273 ][ moodle : blahblahblah ] = 2
*/
2007-02-09 02:24:59 +00:00
require_once $CFG -> dirroot . '/lib/blocklib.php' ;
2006-08-08 05:13:06 +00:00
// permission definitions
2006-09-15 06:07:29 +00:00
define ( 'CAP_INHERIT' , 0 );
2006-08-08 05:13:06 +00:00
define ( 'CAP_ALLOW' , 1 );
define ( 'CAP_PREVENT' , - 1 );
define ( 'CAP_PROHIBIT' , - 1000 );
// context definitions
define ( 'CONTEXT_SYSTEM' , 10 );
define ( 'CONTEXT_PERSONAL' , 20 );
2006-09-15 14:09:16 +00:00
define ( 'CONTEXT_USER' , 30 );
2006-08-08 05:13:06 +00:00
define ( 'CONTEXT_COURSECAT' , 40 );
define ( 'CONTEXT_COURSE' , 50 );
define ( 'CONTEXT_GROUP' , 60 );
define ( 'CONTEXT_MODULE' , 70 );
define ( 'CONTEXT_BLOCK' , 80 );
2006-09-18 21:32:49 +00:00
// capability risks - see http://docs.moodle.org/en/Hardening_new_Roles_system
define ( 'RISK_MANAGETRUST' , 0x0001 );
2006-09-19 07:33:22 +00:00
define ( 'RISK_CONFIG' , 0x0002 );
2006-09-18 21:32:49 +00:00
define ( 'RISK_XSS' , 0x0004 );
define ( 'RISK_PERSONAL' , 0x0008 );
define ( 'RISK_SPAM' , 0x0010 );
2007-01-04 13:15:04 +13:00
require_once ( $CFG -> dirroot . '/group/lib.php' );
2006-09-18 21:32:49 +00:00
2006-08-13 15:48:57 +00:00
$context_cache = array (); // Cache of all used context objects for performance (by level and instance)
$context_cache_id = array (); // Index to above cache by id
2006-08-08 05:13:06 +00:00
2006-09-03 07:56:40 +00:00
2007-03-07 13:45:41 +00:00
function get_role_context_caps ( $roleid , $context ) {
//this is really slow!!!! - do not use above course context level!
$result = array ();
$result [ $context -> id ] = array ();
2006-09-12 06:15:33 +00:00
2007-03-07 13:45:41 +00:00
// first emulate the parent context capabilities merging into context
$searchcontexts = array_reverse ( get_parent_contexts ( $context ));
array_push ( $searchcontexts , $context -> id );
foreach ( $searchcontexts as $cid ) {
if ( $capabilities = get_records_select ( 'role_capabilities' , " roleid = $roleid AND contextid = $cid " )) {
foreach ( $capabilities as $cap ) {
if ( ! array_key_exists ( $cap -> capability , $result [ $context -> id ])) {
$result [ $context -> id ][ $cap -> capability ] = 0 ;
}
$result [ $context -> id ][ $cap -> capability ] += $cap -> permission ;
}
}
}
2006-09-12 06:15:33 +00:00
2007-03-07 13:45:41 +00:00
// now go through the contexts bellow given context
$searchcontexts = get_child_contexts ( $context );
foreach ( $searchcontexts as $cid ) {
if ( $capabilities = get_records_select ( 'role_capabilities' , " roleid = $roleid AND contextid = $cid " )) {
foreach ( $capabilities as $cap ) {
if ( ! array_key_exists ( $cap -> contextid , $result )) {
$result [ $cap -> contextid ] = array ();
}
$result [ $cap -> contextid ][ $cap -> capability ] = $cap -> permission ;
}
}
2006-09-12 06:15:33 +00:00
}
2007-03-07 13:45:41 +00:00
return $result ;
}
function get_role_caps ( $roleid ) {
$result = array ();
if ( $capabilities = get_records_select ( 'role_capabilities' , " roleid = $roleid " )) {
foreach ( $capabilities as $cap ) {
if ( ! array_key_exists ( $cap -> contextid , $result )) {
$result [ $cap -> contextid ] = array ();
}
$result [ $cap -> contextid ][ $cap -> capability ] = $cap -> permission ;
}
2006-09-12 06:15:33 +00:00
}
2007-03-07 13:45:41 +00:00
return $result ;
}
2006-09-12 06:15:33 +00:00
2007-03-07 13:45:41 +00:00
function merge_role_caps ( $caps , $mergecaps ) {
if ( empty ( $mergecaps )) {
return $caps ;
2006-09-12 06:15:33 +00:00
}
2007-03-07 13:45:41 +00:00
if ( empty ( $caps )) {
return $mergecaps ;
2006-09-12 06:15:33 +00:00
}
2007-03-07 13:45:41 +00:00
foreach ( $mergecaps as $contextid => $capabilities ) {
if ( ! array_key_exists ( $contextid , $caps )) {
$caps [ $contextid ] = array ();
}
foreach ( $capabilities as $capability => $permission ) {
if ( ! array_key_exists ( $capability , $caps [ $contextid ])) {
$caps [ $contextid ][ $capability ] = 0 ;
2007-02-14 08:03:40 +00:00
}
2007-03-07 13:45:41 +00:00
$caps [ $contextid ][ $capability ] += $permission ;
2007-02-14 08:03:40 +00:00
}
}
2007-03-07 13:45:41 +00:00
return $caps ;
}
2007-02-09 02:24:59 +00:00
2007-03-07 13:45:41 +00:00
/**
* Loads the capabilities for the default guest role to the current user in a
* specific context .
* @ return object
*/
function load_guest_role ( $return = false ) {
global $USER ;
2007-02-09 02:24:59 +00:00
2007-03-07 13:45:41 +00:00
static $guestrole = false ;
if ( $guestrole === false ) {
if ( ! $guestrole = get_guest_role ()) {
return false ;
2006-09-12 06:15:33 +00:00
}
}
2007-03-07 13:45:41 +00:00
if ( $return ) {
return get_role_caps ( $guestrole -> id );
} else {
2007-01-28 20:52:57 +00:00
has_capability ( 'clearcache' );
2007-03-07 13:45:41 +00:00
$USER -> capabilities = get_role_caps ( $guestrole -> id );
2007-01-28 20:52:57 +00:00
return true ;
}
2006-09-12 06:15:33 +00:00
}
2006-09-03 07:56:40 +00:00
/**
* Load default not logged in role capabilities when user is not logged in
2006-09-20 21:00:45 +00:00
* @ return bool
2006-09-03 07:56:40 +00:00
*/
2007-03-07 13:45:41 +00:00
function load_notloggedin_role ( $return = false ) {
2006-09-01 09:25:34 +00:00
global $CFG , $USER ;
2006-10-25 08:38:14 +00:00
if ( ! $sitecontext = get_context_instance ( CONTEXT_SYSTEM )) {
2006-09-03 07:56:40 +00:00
return false ;
2006-09-02 10:03:30 +00:00
}
2006-09-03 07:56:40 +00:00
if ( empty ( $CFG -> notloggedinroleid )) { // Let's set the default to the guest role
2006-09-14 09:39:23 +00:00
if ( $role = get_guest_role ()) {
2006-09-03 07:56:40 +00:00
set_config ( 'notloggedinroleid' , $role -> id );
} else {
return false ;
}
}
2006-09-01 09:25:34 +00:00
2007-03-07 13:45:41 +00:00
if ( $return ) {
return get_role_caps ( $CFG -> notloggedinroleid );
} else {
2006-12-05 07:17:04 +00:00
has_capability ( 'clearcache' );
2007-03-07 13:45:41 +00:00
$USER -> capabilities = get_role_caps ( $CFG -> notloggedinroleid );
return true ;
2006-09-01 09:25:34 +00:00
}
}
2006-08-14 07:15:03 +00:00
2006-09-14 09:39:23 +00:00
/**
2007-03-07 13:45:41 +00:00
* Load default logged in role capabilities for all logged in users
2006-09-20 21:00:45 +00:00
* @ return bool
2006-09-14 09:39:23 +00:00
*/
2007-01-28 20:52:57 +00:00
function load_defaultuser_role ( $return = false ) {
2006-09-14 09:39:23 +00:00
global $CFG , $USER ;
2006-10-25 08:38:14 +00:00
if ( ! $sitecontext = get_context_instance ( CONTEXT_SYSTEM )) {
2006-09-14 09:39:23 +00:00
return false ;
}
if ( empty ( $CFG -> defaultuserroleid )) { // Let's set the default to the guest role
if ( $role = get_guest_role ()) {
set_config ( 'defaultuserroleid' , $role -> id );
} else {
return false ;
}
}
2007-03-07 13:45:41 +00:00
$capabilities = get_role_caps ( $CFG -> defaultuserroleid );
2007-01-28 20:52:57 +00:00
2007-03-07 13:45:41 +00:00
// fix the guest user heritage:
// If the default role is a guest role, then don't copy legacy:guest,
// otherwise this user could get confused with a REAL guest. Also don't copy
// course:view, which is a hack that's necessary because guest roles are
// not really handled properly (see MDL-7513)
if ( ! empty ( $capabilities [ $sitecontext -> id ][ 'moodle/legacy:guest' ])) {
unset ( $capabilities [ $sitecontext -> id ][ 'moodle/legacy:guest' ]);
unset ( $capabilities [ $sitecontext -> id ][ 'moodle/course:view' ]);
2006-09-14 09:39:23 +00:00
}
2007-01-28 20:52:57 +00:00
if ( $return ) {
2007-03-07 13:45:41 +00:00
return $capabilities ;
2007-01-28 20:52:57 +00:00
} else {
has_capability ( 'clearcache' );
2007-03-07 13:45:41 +00:00
$USER -> capabilities = $capabilities ;
2007-01-28 20:52:57 +00:00
return true ;
}
2006-09-14 09:39:23 +00:00
}
/**
* Get the default guest role
* @ return object role
*/
function get_guest_role () {
2007-02-01 10:24:26 +00:00
global $CFG ;
if ( empty ( $CFG -> guestroleid )) {
if ( $roles = get_roles_with_capability ( 'moodle/legacy:guest' , CAP_ALLOW )) {
$guestrole = array_shift ( $roles ); // Pick the first one
set_config ( 'guestroleid' , $guestrole -> id );
return $guestrole ;
} else {
debugging ( 'Can not find any guest role!' );
return false ;
}
2006-09-14 09:39:23 +00:00
} else {
2007-02-01 10:24:26 +00:00
if ( $guestrole = get_record ( 'role' , 'id' , $CFG -> guestroleid )) {
return $guestrole ;
} else {
//somebody is messing with guest roles, remove incorrect setting and try to find a new one
set_config ( 'guestroleid' , '' );
return get_guest_role ();
}
2006-09-14 09:39:23 +00:00
}
}
2006-08-08 05:13:06 +00:00
/**
* This functions get all the course categories in proper order
2006-11-15 08:23:27 +00:00
* ( ! ) note this only gets course category contexts , and not the site
* context
2006-11-07 03:14:46 +00:00
* @ param object $context
2006-08-08 05:13:06 +00:00
* @ param int $type
* @ return array of contextids
*/
2006-08-14 05:55:40 +00:00
function get_parent_cats ( $context , $type ) {
2006-09-20 21:00:45 +00:00
2006-08-09 13:14:15 +00:00
$parents = array ();
2006-09-20 21:00:45 +00:00
2006-08-31 05:06:30 +00:00
switch ( $type ) {
2006-11-15 08:23:27 +00:00
// a category can be the parent of another category
// there is no limit of depth in this case
2006-08-09 13:14:15 +00:00
case CONTEXT_COURSECAT :
2006-08-31 05:06:30 +00:00
if ( ! $cat = get_record ( 'course_categories' , 'id' , $context -> instanceid )) {
break ;
}
while ( ! empty ( $cat -> parent )) {
if ( ! $context = get_context_instance ( CONTEXT_COURSECAT , $cat -> parent )) {
break ;
}
2006-08-09 13:14:15 +00:00
$parents [] = $context -> id ;
$cat = get_record ( 'course_categories' , 'id' , $cat -> parent );
}
break ;
2006-11-15 08:23:27 +00:00
// a course always fall into a category, unless it's a site course
2007-01-30 10:10:25 +00:00
// this happens when SITEID == $course->id
2006-11-15 08:23:27 +00:00
// in this case the parent of the course is site context
2006-08-09 13:14:15 +00:00
case CONTEXT_COURSE :
2006-08-31 05:06:30 +00:00
if ( ! $course = get_record ( 'course' , 'id' , $context -> instanceid )) {
break ;
}
if ( ! $catinstance = get_context_instance ( CONTEXT_COURSECAT , $course -> category )) {
break ;
}
2006-08-09 13:14:15 +00:00
$parents [] = $catinstance -> id ;
2006-08-31 05:06:30 +00:00
if ( ! $cat = get_record ( 'course_categories' , 'id' , $course -> category )) {
break ;
}
2006-11-15 08:23:27 +00:00
// Yu: Separating site and site course context
if ( $course -> id == SITEID ) {
break ;
}
2006-08-31 05:06:30 +00:00
while ( ! empty ( $cat -> parent )) {
if ( ! $context = get_context_instance ( CONTEXT_COURSECAT , $cat -> parent )) {
break ;
}
2006-08-09 13:14:15 +00:00
$parents [] = $context -> id ;
$cat = get_record ( 'course_categories' , 'id' , $cat -> parent );
}
break ;
2006-09-20 21:00:45 +00:00
2006-08-09 13:14:15 +00:00
default :
break ;
}
return array_reverse ( $parents );
2006-08-08 05:13:06 +00:00
}
2006-08-14 07:15:03 +00:00
2006-08-14 05:55:40 +00:00
/**
* This function checks for a capability assertion being true . If it isn ' t
* then the page is terminated neatly with a standard error message
* @ param string $capability - name of the capability
* @ param object $context - a context object ( record from context table )
* @ param integer $userid - a userid number
2006-09-13 06:35:25 +00:00
* @ param bool $doanything - if false , ignore do anything
2006-08-14 05:55:40 +00:00
* @ param string $errorstring - an errorstring
2006-09-13 06:35:25 +00:00
* @ param string $stringfile - which stringfile to get it from
2006-08-14 05:55:40 +00:00
*/
2006-09-20 21:00:45 +00:00
function require_capability ( $capability , $context = NULL , $userid = NULL , $doanything = true ,
2006-11-02 08:12:54 +00:00
$errormessage = 'nopermissions' , $stringfile = '' ) {
2006-08-31 07:40:48 +00:00
2006-11-02 08:12:54 +00:00
global $USER , $CFG ;
2006-08-31 07:40:48 +00:00
2006-11-02 08:12:54 +00:00
/// If the current user is not logged in, then make sure they are (if needed)
2006-08-31 07:40:48 +00:00
2006-10-29 15:58:21 +00:00
if ( empty ( $userid ) and empty ( $USER -> capabilities )) {
2006-09-22 06:19:32 +00:00
if ( $context && ( $context -> contextlevel == CONTEXT_COURSE )) {
2006-08-31 07:40:48 +00:00
require_login ( $context -> instanceid );
2006-09-24 13:15:13 +00:00
} else if ( $context && ( $context -> contextlevel == CONTEXT_MODULE )) {
if ( $cm = get_record ( 'course_modules' , 'id' , $context -> instanceid )) {
2006-11-02 08:12:54 +00:00
if ( ! $course = get_record ( 'course' , 'id' , $cm -> course )) {
error ( 'Incorrect course.' );
}
require_course_login ( $course , true , $cm );
2006-09-24 13:15:13 +00:00
} else {
require_login ();
}
2006-11-02 08:12:54 +00:00
} else if ( $context && ( $context -> contextlevel == CONTEXT_SYSTEM )) {
if ( ! empty ( $CFG -> forcelogin )) {
require_login ();
}
2006-08-31 07:40:48 +00:00
} else {
require_login ();
}
}
2006-09-20 21:00:45 +00:00
2006-08-31 07:40:48 +00:00
/// OK, if they still don't have the capability then print a nice error message
2006-09-13 06:35:25 +00:00
if ( ! has_capability ( $capability , $context , $userid , $doanything )) {
2006-08-14 05:55:40 +00:00
$capabilityname = get_capability_string ( $capability );
print_error ( $errormessage , $stringfile , '' , $capabilityname );
}
}
2006-08-08 05:13:06 +00:00
/**
* This function returns whether the current user has the capability of performing a function
* For example , we can do has_capability ( 'mod/forum:replypost' , $cm ) in forum
* only one of the 4 ( moduleinstance , courseid , site , userid ) would be set at 1 time
* This is a recursive funciton .
* @ uses $USER
2006-12-05 05:45:08 +00:00
* @ param string $capability - name of the capability ( or debugcache or clearcache )
2006-08-14 05:55:40 +00:00
* @ param object $context - a context object ( record from context table )
* @ param integer $userid - a userid number
2006-09-01 09:25:34 +00:00
* @ param bool $doanything - if false , ignore do anything
2006-08-08 05:13:06 +00:00
* @ return bool
*/
2006-09-13 06:35:25 +00:00
function has_capability ( $capability , $context = NULL , $userid = NULL , $doanything = true ) {
2006-08-08 05:13:06 +00:00
2006-09-01 09:25:34 +00:00
global $USER , $CONTEXT , $CFG ;
2006-08-08 05:13:06 +00:00
2006-10-26 09:43:58 +00:00
static $capcache = array (); // Cache of capabilities
2006-12-05 05:45:08 +00:00
/// Cache management
if ( $capability == 'clearcache' ) {
$capcache = array (); // Clear ALL the capability cache
return false ;
}
2006-10-26 09:43:58 +00:00
/// Some sanity checks
2007-03-06 05:36:19 +00:00
if ( debugging ( '' , DEBUG_DEVELOPER )) {
2006-10-26 09:43:58 +00:00
if ( $capability == 'debugcache' ) {
print_object ( $capcache );
return true ;
}
if ( ! record_exists ( 'capabilities' , 'name' , $capability )) {
debugging ( 'Capability "' . $capability . '" was not found! This should be fixed in code.' );
}
if ( $doanything != true and $doanything != false ) {
debugging ( 'Capability parameter "doanything" is wierd ("' . $doanything . '"). This should be fixed in code.' );
}
if ( ! is_object ( $context ) && $context !== NULL ) {
debugging ( 'Incorrect context parameter "' . $context . '" for has_capability(), object expected! This should be fixed in code.' );
}
2006-09-19 22:57:17 +00:00
}
2006-10-26 09:43:58 +00:00
/// Make sure we know the current context
if ( empty ( $context )) { // Use default CONTEXT if none specified
if ( empty ( $CONTEXT )) {
return false ;
} else {
$context = $CONTEXT ;
}
} else { // A context was given to us
if ( empty ( $CONTEXT )) {
$CONTEXT = $context ; // Store FIRST used context in this global as future default
}
}
/// Check and return cache in case we've processed this one before.
2007-01-28 20:52:57 +00:00
$requsteduser = empty ( $userid ) ? $USER -> id : $userid ; // find out the requested user id, $USER->id might have been changed
$cachekey = $capability . '_' . $context -> id . '_' . intval ( $requsteduser ) . '_' . intval ( $doanything );
2006-12-05 05:45:08 +00:00
2006-10-26 09:43:58 +00:00
if ( isset ( $capcache [ $cachekey ])) {
return $capcache [ $cachekey ];
}
2006-09-01 09:25:34 +00:00
2006-10-26 09:43:58 +00:00
/// Load up the capabilities list or item as necessary
2007-01-28 20:52:57 +00:00
if ( $userid ) {
if ( empty ( $USER -> id ) or ( $userid != $USER -> id ) or empty ( $USER -> capabilities )) {
2007-03-07 13:45:41 +00:00
//caching - helps user switching in cron
static $guestuserid = false ; // guest user id
static $guestcaps = false ; // guest caps
static $defcaps = false ; // default user caps - this might help cron
if ( $guestuserid === false ) {
2007-01-28 20:52:57 +00:00
$guestuserid = get_field ( 'user' , 'id' , 'username' , 'guest' );
}
if ( $userid == $guestuserid ) {
2007-03-07 13:45:41 +00:00
if ( $guestcaps === false ) {
$guestcaps = load_guest_role ( true );
}
$capabilities = $guestcaps ;
2007-01-28 20:52:57 +00:00
} else {
2007-05-07 03:10:22 +00:00
// This big SQL is expensive! We reduce it a little by avoiding checking for changed enrolments (false)
$capabilities = load_user_capability ( $capability , $context , $userid , false );
2007-03-07 13:45:41 +00:00
if ( $defcaps === false ) {
2007-01-28 20:52:57 +00:00
$defcaps = load_defaultuser_role ( true );
}
2007-03-07 13:45:41 +00:00
$capabilities = merge_role_caps ( $capabilities , $defcaps );
2007-01-28 20:52:57 +00:00
}
2007-03-07 13:45:41 +00:00
} else { //$USER->id == $userid and needed capabilities already present
2007-01-28 20:52:57 +00:00
$capabilities = $USER -> capabilities ;
2006-08-25 20:12:12 +00:00
}
2007-03-07 13:45:41 +00:00
2006-08-25 20:12:12 +00:00
} else { // no userid
2007-01-28 20:52:57 +00:00
if ( empty ( $USER -> capabilities )) {
2007-03-07 13:45:41 +00:00
load_all_capabilities (); // expensive - but we have to do it once anyway
2007-01-28 20:52:57 +00:00
}
$capabilities = $USER -> capabilities ;
2006-10-26 09:43:58 +00:00
$userid = $USER -> id ;
2006-08-09 13:14:15 +00:00
}
2006-08-25 20:12:12 +00:00
2006-12-05 05:45:08 +00:00
/// We act a little differently when switchroles is active
$switchroleactive = false ; // Assume it isn't active in this context
2006-08-08 05:13:06 +00:00
2006-10-26 09:43:58 +00:00
/// First deal with the "doanything" capability
2006-10-02 22:10:36 +00:00
2006-09-01 09:25:34 +00:00
if ( $doanything ) {
2006-09-21 15:58:59 +00:00
2006-10-11 05:49:26 +00:00
/// First make sure that we aren't in a "switched role"
if ( ! empty ( $USER -> switchrole )) { // Switchrole is active somewhere!
if ( ! empty ( $USER -> switchrole [ $context -> id ])) { // Because of current context
$switchroleactive = true ;
} else { // Check parent contexts
if ( $parentcontextids = get_parent_contexts ( $context )) {
foreach ( $parentcontextids as $parentcontextid ) {
if ( ! empty ( $USER -> switchrole [ $parentcontextid ])) { // Yep, switchroles active here
$switchroleactive = true ;
break ;
}
}
}
}
}
/// Check the site context for doanything (most common) first
if ( empty ( $switchroleactive )) { // Ignore site setting if switchrole is active
2006-10-25 08:38:14 +00:00
$sitecontext = get_context_instance ( CONTEXT_SYSTEM );
2006-09-21 15:58:59 +00:00
if ( isset ( $capabilities [ $sitecontext -> id ][ 'moodle/site:doanything' ])) {
2006-10-26 09:43:58 +00:00
$result = ( 0 < $capabilities [ $sitecontext -> id ][ 'moodle/site:doanything' ]);
$capcache [ $cachekey ] = $result ;
return $result ;
2006-09-21 15:58:59 +00:00
}
2006-09-01 09:25:34 +00:00
}
2006-11-15 08:23:27 +00:00
/// If it's not set at site level, it is possible to be set on other levels
/// Though this usage is not common and can cause risks
2006-09-22 06:19:32 +00:00
switch ( $context -> contextlevel ) {
2006-09-20 21:00:45 +00:00
2006-09-01 09:25:34 +00:00
case CONTEXT_COURSECAT :
// Check parent cats.
$parentcats = get_parent_cats ( $context , CONTEXT_COURSECAT );
foreach ( $parentcats as $parentcat ) {
if ( isset ( $capabilities [ $parentcat ][ 'moodle/site:doanything' ])) {
2006-10-26 09:43:58 +00:00
$result = ( 0 < $capabilities [ $parentcat ][ 'moodle/site:doanything' ]);
$capcache [ $cachekey ] = $result ;
return $result ;
2006-09-01 09:25:34 +00:00
}
2006-08-14 07:15:03 +00:00
}
2006-09-01 09:25:34 +00:00
break ;
2006-08-08 05:13:06 +00:00
2006-09-01 09:25:34 +00:00
case CONTEXT_COURSE :
// Check parent cat.
$parentcats = get_parent_cats ( $context , CONTEXT_COURSE );
2006-08-09 13:14:15 +00:00
2006-09-01 09:25:34 +00:00
foreach ( $parentcats as $parentcat ) {
if ( isset ( $capabilities [ $parentcat ][ 'do_anything' ])) {
2006-10-26 09:43:58 +00:00
$result = ( 0 < $capabilities [ $parentcat ][ 'do_anything' ]);
$capcache [ $cachekey ] = $result ;
return $result ;
2006-09-01 09:25:34 +00:00
}
2006-08-25 20:12:12 +00:00
}
2006-09-01 09:25:34 +00:00
break ;
2006-08-08 05:13:06 +00:00
2006-09-01 09:25:34 +00:00
case CONTEXT_GROUP :
// Find course.
2007-01-04 13:15:04 +13:00
$courseid = groups_get_course ( $context -> instanceid );
$courseinstance = get_context_instance ( CONTEXT_COURSE , $courseid );
2006-08-25 20:12:12 +00:00
2006-09-01 09:25:34 +00:00
$parentcats = get_parent_cats ( $courseinstance , CONTEXT_COURSE );
foreach ( $parentcats as $parentcat ) {
2006-10-31 20:24:57 +00:00
if ( isset ( $capabilities [ $parentcat ][ 'do_anything' ])) {
$result = ( 0 < $capabilities [ $parentcat ][ 'do_anything' ]);
2006-10-26 09:43:58 +00:00
$capcache [ $cachekey ] = $result ;
return $result ;
2006-09-01 09:25:34 +00:00
}
2006-08-25 20:12:12 +00:00
}
2006-09-01 09:25:34 +00:00
$coursecontext = '' ;
if ( isset ( $capabilities [ $courseinstance -> id ][ 'do_anything' ])) {
2006-10-26 09:43:58 +00:00
$result = ( 0 < $capabilities [ $courseinstance -> id ][ 'do_anything' ]);
$capcache [ $cachekey ] = $result ;
return $result ;
2006-09-01 09:25:34 +00:00
}
2006-08-25 20:12:12 +00:00
2006-09-01 09:25:34 +00:00
break ;
2006-08-08 05:13:06 +00:00
2006-09-01 09:25:34 +00:00
case CONTEXT_MODULE :
// Find course.
$cm = get_record ( 'course_modules' , 'id' , $context -> instanceid );
$courseinstance = get_context_instance ( CONTEXT_COURSE , $cm -> course );
2006-08-25 20:12:12 +00:00
2006-09-01 09:25:34 +00:00
if ( $parentcats = get_parent_cats ( $courseinstance , CONTEXT_COURSE )) {
foreach ( $parentcats as $parentcat ) {
if ( isset ( $capabilities [ $parentcat ][ 'do_anything' ])) {
2006-10-26 09:43:58 +00:00
$result = ( 0 < $capabilities [ $parentcat ][ 'do_anything' ]);
$capcache [ $cachekey ] = $result ;
return $result ;
2006-09-01 09:25:34 +00:00
}
2006-08-14 07:15:03 +00:00
}
2006-08-25 20:12:12 +00:00
}
2006-08-09 13:14:15 +00:00
2006-09-01 09:25:34 +00:00
if ( isset ( $capabilities [ $courseinstance -> id ][ 'do_anything' ])) {
2006-10-26 09:43:58 +00:00
$result = ( 0 < $capabilities [ $courseinstance -> id ][ 'do_anything' ]);
$capcache [ $cachekey ] = $result ;
return $result ;
2006-09-01 09:25:34 +00:00
}
2006-08-08 05:13:06 +00:00
2006-09-01 09:25:34 +00:00
break ;
2006-08-08 05:13:06 +00:00
2006-09-01 09:25:34 +00:00
case CONTEXT_BLOCK :
2006-11-06 06:16:00 +00:00
// not necessarily 1 to 1 to course.
2006-09-01 09:25:34 +00:00
$block = get_record ( 'block_instance' , 'id' , $context -> instanceid );
2006-11-06 06:16:00 +00:00
if ( $block -> pagetype == 'course-view' ) {
$courseinstance = get_context_instance ( CONTEXT_COURSE , $block -> pageid ); // needs check
$parentcats = get_parent_cats ( $courseinstance , CONTEXT_COURSE );
foreach ( $parentcats as $parentcat ) {
if ( isset ( $capabilities [ $parentcat ][ 'do_anything' ])) {
$result = ( 0 < $capabilities [ $parentcat ][ 'do_anything' ]);
$capcache [ $cachekey ] = $result ;
return $result ;
}
}
if ( isset ( $capabilities [ $courseinstance -> id ][ 'do_anything' ])) {
$result = ( 0 < $capabilities [ $courseinstance -> id ][ 'do_anything' ]);
$capcache [ $cachekey ] = $result ;
return $result ;
}
} else { // if not course-view type of blocks, check site
if ( isset ( $capabilities [ $sitecontext -> id ][ 'do_anything' ])) {
$result = ( 0 < $capabilities [ $sitecontext -> id ][ 'do_anything' ]);
2006-10-26 09:43:58 +00:00
$capcache [ $cachekey ] = $result ;
return $result ;
2006-09-01 09:25:34 +00:00
}
}
break ;
2006-08-08 05:13:06 +00:00
2006-09-01 09:25:34 +00:00
default :
2006-09-15 14:09:16 +00:00
// CONTEXT_SYSTEM: CONTEXT_PERSONAL: CONTEXT_USER:
2006-11-15 08:23:27 +00:00
// Do nothing, because the parents are site context
// which has been checked already
2006-09-01 09:25:34 +00:00
break ;
}
2006-08-08 05:13:06 +00:00
2006-09-01 09:25:34 +00:00
// Last: check self.
if ( isset ( $capabilities [ $context -> id ][ 'do_anything' ])) {
2006-10-26 09:43:58 +00:00
$result = ( 0 < $capabilities [ $context -> id ][ 'do_anything' ]);
$capcache [ $cachekey ] = $result ;
return $result ;
2006-09-01 09:25:34 +00:00
}
2006-08-09 13:14:15 +00:00
}
2006-12-05 05:45:08 +00:00
// do_anything has not been set, we now look for it the normal way.
$result = ( 0 < capability_search ( $capability , $context , $capabilities , $switchroleactive ));
2006-10-26 09:43:58 +00:00
$capcache [ $cachekey ] = $result ;
return $result ;
2006-08-08 05:13:06 +00:00
2006-08-25 20:12:12 +00:00
}
2006-08-08 05:13:06 +00:00
/**
* In a separate function so that we won ' t have to deal with do_anything .
2006-11-15 08:23:27 +00:00
* again . Used by function has_capability () .
2006-08-08 05:13:06 +00:00
* @ param $capability - capability string
2006-08-14 05:55:40 +00:00
* @ param $context - the context object
2006-11-15 08:23:27 +00:00
* @ param $capabilities - either $USER -> capability or loaded array ( for other users )
2006-08-08 05:13:06 +00:00
* @ return permission ( int )
*/
2006-12-05 05:45:08 +00:00
function capability_search ( $capability , $context , $capabilities , $switchroleactive = false ) {
2006-09-20 08:30:49 +00:00
2006-08-08 05:13:06 +00:00
global $USER , $CFG ;
2006-08-14 05:55:40 +00:00
2006-09-24 13:15:13 +00:00
if ( ! isset ( $context -> id )) {
return 0 ;
}
2006-11-15 08:23:27 +00:00
// if already set in the array explicitly, no need to look for it in parent
// context any longer
2006-08-14 05:55:40 +00:00
if ( isset ( $capabilities [ $context -> id ][ $capability ])) {
return ( $capabilities [ $context -> id ][ $capability ]);
2006-08-08 05:13:06 +00:00
}
2006-08-25 20:12:12 +00:00
2006-08-08 05:13:06 +00:00
/* Then, we check the cache recursively */
2006-08-25 20:12:12 +00:00
$permission = 0 ;
2006-09-22 06:19:32 +00:00
switch ( $context -> contextlevel ) {
2006-08-08 05:13:06 +00:00
case CONTEXT_SYSTEM : // by now it's a definite an inherit
$permission = 0 ;
break ;
case CONTEXT_PERSONAL :
2006-10-25 08:38:14 +00:00
$parentcontext = get_context_instance ( CONTEXT_SYSTEM );
2007-02-01 08:14:08 +00:00
$permission = capability_search ( $capability , $parentcontext , $capabilities , $switchroleactive );
2006-08-08 05:13:06 +00:00
break ;
2006-08-25 20:12:12 +00:00
2006-09-15 14:09:16 +00:00
case CONTEXT_USER :
2006-10-25 08:38:14 +00:00
$parentcontext = get_context_instance ( CONTEXT_SYSTEM );
2007-02-01 08:14:08 +00:00
$permission = capability_search ( $capability , $parentcontext , $capabilities , $switchroleactive );
2006-08-08 05:13:06 +00:00
break ;
2006-08-25 20:12:12 +00:00
2006-08-08 05:13:06 +00:00
case CONTEXT_COURSECAT : // Coursecat -> coursecat or site
$coursecat = get_record ( 'course_categories' , 'id' , $context -> instanceid );
2006-08-14 05:55:40 +00:00
if ( ! empty ( $coursecat -> parent )) { // return parent value if it exists
$parentcontext = get_context_instance ( CONTEXT_COURSECAT , $coursecat -> parent );
2006-08-08 05:13:06 +00:00
} else { // else return site value
2006-10-25 08:38:14 +00:00
$parentcontext = get_context_instance ( CONTEXT_SYSTEM );
2006-08-08 05:13:06 +00:00
}
2007-02-01 08:14:08 +00:00
$permission = capability_search ( $capability , $parentcontext , $capabilities , $switchroleactive );
2006-08-08 05:13:06 +00:00
break ;
case CONTEXT_COURSE : // 1 to 1 to course cat
2006-12-05 05:45:08 +00:00
if ( empty ( $switchroleactive )) {
// find the course cat, and return its value
$course = get_record ( 'course' , 'id' , $context -> instanceid );
if ( $course -> id == SITEID ) { // In 1.8 we've separated site course and system
$parentcontext = get_context_instance ( CONTEXT_SYSTEM );
} else {
$parentcontext = get_context_instance ( CONTEXT_COURSECAT , $course -> category );
}
2007-02-01 08:14:08 +00:00
$permission = capability_search ( $capability , $parentcontext , $capabilities , $switchroleactive );
2006-11-15 08:23:27 +00:00
}
2006-08-08 05:13:06 +00:00
break ;
case CONTEXT_GROUP : // 1 to 1 to course
2007-01-04 13:15:04 +13:00
$courseid = groups_get_course ( $context -> instanceid );
$parentcontext = get_context_instance ( CONTEXT_COURSE , $courseid );
2007-02-01 08:14:08 +00:00
$permission = capability_search ( $capability , $parentcontext , $capabilities , $switchroleactive );
2006-08-08 05:13:06 +00:00
break ;
case CONTEXT_MODULE : // 1 to 1 to course
$cm = get_record ( 'course_modules' , 'id' , $context -> instanceid );
2006-08-14 05:55:40 +00:00
$parentcontext = get_context_instance ( CONTEXT_COURSE , $cm -> course );
2007-02-01 08:14:08 +00:00
$permission = capability_search ( $capability , $parentcontext , $capabilities , $switchroleactive );
2006-08-08 05:13:06 +00:00
break ;
2006-11-06 06:16:00 +00:00
case CONTEXT_BLOCK : // not necessarily 1 to 1 to course
2006-08-08 05:13:06 +00:00
$block = get_record ( 'block_instance' , 'id' , $context -> instanceid );
2006-11-06 06:16:00 +00:00
if ( $block -> pagetype == 'course-view' ) {
$parentcontext = get_context_instance ( CONTEXT_COURSE , $block -> pageid ); // needs check
} else {
$parentcontext = get_context_instance ( CONTEXT_SYSTEM );
}
2007-02-01 08:14:08 +00:00
$permission = capability_search ( $capability , $parentcontext , $capabilities , $switchroleactive );
2006-08-08 05:13:06 +00:00
break ;
default :
2007-03-01 16:42:36 +00:00
error ( 'This is an unknown context (' . $context -> contextlevel . ') in capability_search!' );
2006-08-08 05:13:06 +00:00
return false ;
}
2006-08-25 20:12:12 +00:00
2006-08-09 13:14:15 +00:00
return $permission ;
2006-08-08 05:13:06 +00:00
}
2006-11-15 08:23:27 +00:00
/**
* auxillary function for load_user_capabilities ()
* checks if context c1 is a parent ( or itself ) of context c2
* @ param int $c1 - context id of context 1
* @ param int $c2 - context id of context 2
* @ return bool
*/
2006-10-25 03:47:59 +00:00
function is_parent_context ( $c1 , $c2 ) {
static $parentsarray ;
// context can be itself and this is ok
if ( $c1 == $c2 ) {
return true ;
}
// hit in cache?
if ( isset ( $parentsarray [ $c1 ][ $c2 ])) {
return $parentsarray [ $c1 ][ $c2 ];
}
if ( ! $co2 = get_record ( 'context' , 'id' , $c2 )) {
return false ;
}
if ( ! $parents = get_parent_contexts ( $co2 )) {
return false ;
}
foreach ( $parents as $parent ) {
$parentsarray [ $parent ][ $c2 ] = true ;
}
if ( in_array ( $c1 , $parents )) {
return true ;
} else { // else not a parent, set the cache anyway
$parentsarray [ $c1 ][ $c2 ] = false ;
return false ;
}
}
2007-03-05 11:27:01 +00:00
/**
2006-10-25 03:47:59 +00:00
* auxillary function for load_user_capabilities ()
* handler in usort () to sort contexts according to level
2006-11-15 08:23:27 +00:00
* @ param object contexta
* @ param object contextb
* @ return int
2006-10-25 03:47:59 +00:00
*/
function roles_context_cmp ( $contexta , $contextb ) {
if ( $contexta -> contextlevel == $contextb -> contextlevel ) {
return 0 ;
}
return ( $contexta -> contextlevel < $contextb -> contextlevel ) ? - 1 : 1 ;
}
2006-08-08 05:13:06 +00:00
/**
* It will build an array of all the capabilities at each level
* i . e . site / metacourse / course_category / course / moduleinstance
* Note we should only load capabilities if they are explicitly assigned already ,
* we should not load all module ' s capability !
2006-10-25 08:38:14 +00:00
*
2006-08-08 05:13:06 +00:00
* [ Capabilities ] => [ 26 ][ forum_post ] = 1
* [ 26 ][ forum_start ] = - 8990
* [ 26 ][ forum_edit ] = - 1
* [ 273 ][ blah blah ] = 1
* [ 273 ][ blah blah blah ] = 2
2006-10-25 08:38:14 +00:00
*
* @ param $capability string - Only get a specific capability ( string )
* @ param $context object - Only get capabilities for a specific context object
* @ param $userid integer - the id of the user whose capabilities we want to load
2007-05-07 08:34:08 +00:00
* @ param $checkenrolments boolean - Should we check enrolment plugins ( potentially expensive )
2006-10-25 08:38:14 +00:00
* @ return array of permissions ( or nothing if they get assigned to $USER )
2006-08-08 05:13:06 +00:00
*/
2007-05-07 03:10:22 +00:00
function load_user_capability ( $capability = '' , $context = NULL , $userid = NULL , $checkenrolments = true ) {
2006-08-21 05:19:16 +00:00
2006-08-09 13:14:15 +00:00
global $USER , $CFG ;
2007-01-12 12:57:50 +00:00
2006-11-15 08:23:27 +00:00
// this flag has not been set!
// (not clean install, or upgraded successfully to 1.7 and up)
2006-10-23 15:17:31 +00:00
if ( empty ( $CFG -> rolesactive )) {
return false ;
}
2006-08-08 05:13:06 +00:00
if ( empty ( $userid )) {
2006-09-03 08:45:41 +00:00
if ( empty ( $USER -> id )) { // We have no user to get capabilities for
2006-09-16 13:54:57 +00:00
debugging ( 'User not logged in for load_user_capability!' );
2006-09-03 08:45:41 +00:00
return false ;
}
2006-09-16 13:54:57 +00:00
unset ( $USER -> capabilities ); // We don't want possible older capabilites hanging around
2007-05-07 03:10:22 +00:00
if ( $checkenrolments ) { // Call "enrol" system to ensure that we have the correct picture
check_enrolment_plugins ( $USER );
}
2006-09-14 09:39:23 +00:00
2006-08-08 05:13:06 +00:00
$userid = $USER -> id ;
2006-09-03 08:45:41 +00:00
$otheruserid = false ;
2006-08-08 05:13:06 +00:00
} else {
2006-09-16 13:54:57 +00:00
if ( ! $user = get_record ( 'user' , 'id' , $userid )) {
debugging ( 'Non-existent userid in load_user_capability!' );
return false ;
}
2007-05-07 03:10:22 +00:00
if ( $checkenrolments ) { // Call "enrol" system to ensure that we have the correct picture
check_enrolment_plugins ( $user );
}
2006-09-16 13:54:57 +00:00
2006-08-25 20:12:12 +00:00
$otheruserid = $userid ;
2006-08-08 05:13:06 +00:00
}
2006-08-25 20:12:12 +00:00
2006-08-31 04:17:51 +00:00
/// First we generate a list of all relevant contexts of the user
$usercontexts = array ();
2006-08-08 05:13:06 +00:00
2006-08-14 05:55:40 +00:00
if ( $context ) { // if context is specified
2006-09-20 21:00:45 +00:00
$usercontexts = get_parent_contexts ( $context );
2006-10-01 05:27:36 +00:00
$usercontexts [] = $context -> id ; // Add the current context as well
2006-08-09 13:14:15 +00:00
} else { // else, we load everything
2006-08-31 04:17:51 +00:00
if ( $userroles = get_records ( 'role_assignments' , 'userid' , $userid )) {
foreach ( $userroles as $userrole ) {
2007-01-12 07:41:33 +00:00
if ( ! in_array ( $userrole -> contextid , $usercontexts )) {
$usercontexts [] = $userrole -> contextid ;
}
2006-08-31 04:17:51 +00:00
}
2006-08-09 13:14:15 +00:00
}
2006-08-31 04:17:51 +00:00
}
/// Set up SQL fragments for searching contexts
if ( $usercontexts ) {
2006-08-14 05:55:40 +00:00
$listofcontexts = '(' . implode ( ',' , $usercontexts ) . ')' ;
2006-08-31 04:17:51 +00:00
$searchcontexts1 = " c1.id IN $listofcontexts AND " ;
} else {
2006-09-25 07:50:03 +00:00
$searchcontexts1 = '' ;
2006-08-08 05:13:06 +00:00
}
2006-09-27 17:50:53 +00:00
2006-09-16 13:54:57 +00:00
if ( $capability ) {
2007-04-09 11:11:31 +00:00
// the doanything may override the requested capability
$capsearch = " AND (rc.capability = ' $capability ' OR rc.capability = 'moodle/site:doanything') " ;
2006-09-16 13:54:57 +00:00
} else {
2006-09-20 21:00:45 +00:00
$capsearch = " " ;
2006-09-16 13:54:57 +00:00
}
2006-08-31 04:17:51 +00:00
/// Then we use 1 giant SQL to bring out all relevant capabilities.
/// The first part gets the capabilities of orginal role.
/// The second part gets the capabilities of overriden roles.
2006-08-08 05:13:06 +00:00
2006-10-25 08:38:14 +00:00
$siteinstance = get_context_instance ( CONTEXT_SYSTEM );
2006-10-25 03:47:59 +00:00
$capabilities = array (); // Reinitialize.
// SQL for normal capabilities
$SQL1 = " SELECT rc.capability, c1.id as id1, c1.id as id2, (c1.contextlevel * 100) AS aggrlevel,
2006-08-08 05:13:06 +00:00
SUM ( rc . permission ) AS sum
FROM
2006-09-20 21:00:45 +00:00
{ $CFG -> prefix } role_assignments ra ,
2006-09-07 20:17:46 +00:00
{ $CFG -> prefix } role_capabilities rc ,
{ $CFG -> prefix } context c1
2006-08-08 05:13:06 +00:00
WHERE
2006-09-06 01:43:54 +00:00
ra . contextid = c1 . id AND
ra . roleid = rc . roleid AND
2006-08-08 05:13:06 +00:00
ra . userid = $userid AND
2006-08-31 04:17:51 +00:00
$searchcontexts1
2006-09-20 21:00:45 +00:00
rc . contextid = $siteinstance -> id
2006-08-09 13:14:15 +00:00
$capsearch
2006-08-08 05:13:06 +00:00
GROUP BY
2007-01-12 12:57:50 +00:00
rc . capability , c1 . id , c1 . contextlevel * 100
2006-08-08 05:13:06 +00:00
HAVING
2006-10-25 03:47:59 +00:00
SUM ( rc . permission ) != 0
2007-01-12 07:41:33 +00:00
UNION ALL
SELECT rc . capability , c1 . id as id1 , c2 . id as id2 , ( c1 . contextlevel * 100 + c2 . contextlevel ) AS aggrlevel ,
SUM ( rc . permission ) AS sum
FROM
{ $CFG -> prefix } role_assignments ra LEFT JOIN
{ $CFG -> prefix } role_capabilities rc on ra . roleid = rc . roleid LEFT JOIN
{ $CFG -> prefix } context c1 on ra . contextid = c1 . id LEFT JOIN
{ $CFG -> prefix } context c2 on rc . contextid = c2 . id LEFT JOIN
{ $CFG -> prefix } context_rel cr on cr . c1 = c2 . id
WHERE
ra . userid = $userid AND
$searchcontexts1
rc . contextid != $siteinstance -> id
$capsearch
AND cr . c2 = c1 . id
GROUP BY
2007-01-12 12:57:50 +00:00
rc . capability , c1 . id , c2 . id , c1 . contextlevel * 100 + c2 . contextlevel
2007-01-12 07:41:33 +00:00
HAVING
SUM ( rc . permission ) != 0
2006-10-25 03:47:59 +00:00
ORDER BY
aggrlevel ASC " ;
2007-01-12 07:41:33 +00:00
2006-10-25 03:47:59 +00:00
if ( ! $rs = get_recordset_sql ( $SQL1 )) {
error ( " Query failed in load_user_capability. " );
}
2006-08-08 05:13:06 +00:00
2006-10-25 03:47:59 +00:00
if ( $rs && $rs -> RecordCount () > 0 ) {
2007-01-29 22:23:58 +00:00
while ( $caprec = rs_fetch_next_record ( $rs )) {
$array = ( array ) $caprec ;
2006-10-25 03:47:59 +00:00
$temprecord = new object ;
foreach ( $array as $key => $val ) {
if ( $key == 'aggrlevel' ) {
$temprecord -> contextlevel = $val ;
} else {
$temprecord -> { $key } = $val ;
}
}
$capabilities [] = $temprecord ;
}
2007-01-29 22:23:58 +00:00
rs_close ( $rs );
2007-01-11 05:52:26 +00:00
}
2007-01-29 22:23:58 +00:00
2006-10-25 03:47:59 +00:00
// SQL for overrides
// this is take out because we have no way of making sure c1 is indeed related to c2 (parent)
// if we do not group by sum, it is possible to have multiple records of rc.capability, c1.id, c2.id, tuple having
// different values, we can maually sum it when we go through the list
2007-01-12 07:41:33 +00:00
/*
2006-10-25 03:47:59 +00:00
$SQL2 = " SELECT rc.capability, c1.id as id1, c2.id as id2, (c1.contextlevel * 100 + c2.contextlevel) AS aggrlevel,
rc . permission AS sum
2006-08-08 05:13:06 +00:00
FROM
2006-09-07 20:17:46 +00:00
{ $CFG -> prefix } role_assignments ra ,
{ $CFG -> prefix } role_capabilities rc ,
{ $CFG -> prefix } context c1 ,
{ $CFG -> prefix } context c2
2006-08-08 05:13:06 +00:00
WHERE
2006-09-06 01:43:54 +00:00
ra . contextid = c1 . id AND
2006-09-20 21:00:45 +00:00
ra . roleid = rc . roleid AND
ra . userid = $userid AND
rc . contextid = c2 . id AND
2006-08-31 04:17:51 +00:00
$searchcontexts1
rc . contextid != $siteinstance -> id
2006-08-08 05:13:06 +00:00
$capsearch
2006-09-20 21:00:45 +00:00
2006-08-08 05:13:06 +00:00
GROUP BY
2006-10-25 08:38:14 +00:00
rc . capability , ( c1 . contextlevel * 100 + c2 . contextlevel ), c1 . id , c2 . id , rc . permission
2006-08-08 05:13:06 +00:00
ORDER BY
2006-08-22 16:18:11 +00:00
aggrlevel ASC
2007-01-12 07:41:33 +00:00
" ;*/
2006-10-25 03:47:59 +00:00
2007-01-12 07:41:33 +00:00
/*
2006-10-25 03:47:59 +00:00
if ( ! $rs = get_recordset_sql ( $SQL2 )) {
2006-08-22 16:18:11 +00:00
error ( " Query failed in load_user_capability. " );
}
2006-08-22 09:04:23 +00:00
2006-08-08 05:13:06 +00:00
if ( $rs && $rs -> RecordCount () > 0 ) {
2007-01-29 22:23:58 +00:00
while ( $caprec = rs_fetch_next_record ( $rs )) {
$array = ( array ) $caprec ;
2006-08-22 16:18:11 +00:00
$temprecord = new object ;
2006-09-20 21:00:45 +00:00
2006-08-09 13:14:15 +00:00
foreach ( $array as $key => $val ) {
2006-08-22 16:18:11 +00:00
if ( $key == 'aggrlevel' ) {
2006-09-22 06:19:32 +00:00
$temprecord -> contextlevel = $val ;
2006-08-22 16:18:11 +00:00
} else {
$temprecord -> { $key } = $val ;
}
2006-08-09 13:14:15 +00:00
}
2006-10-25 03:47:59 +00:00
// for overrides, we have to make sure that context2 is a child of context1
// otherwise the combination makes no sense
2007-01-12 07:41:33 +00:00
//if (is_parent_context($temprecord->id1, $temprecord->id2)) {
2006-10-25 03:47:59 +00:00
$capabilities [] = $temprecord ;
2007-01-12 07:41:33 +00:00
//} // only write if relevant
2006-08-08 05:13:06 +00:00
}
2007-01-29 22:23:58 +00:00
rs_close ( $rs );
2006-08-08 05:13:06 +00:00
}
2007-01-12 07:41:33 +00:00
2006-10-25 03:47:59 +00:00
// this step sorts capabilities according to the contextlevel
// it is very important because the order matters when we
// go through each capabilities later. (i.e. higher level contextlevel
// will override lower contextlevel settings
usort ( $capabilities , 'roles_context_cmp' );
2007-01-12 07:41:33 +00:00
*/
2006-08-08 05:13:06 +00:00
/* so up to this point we should have somethign like this
2006-09-22 06:19:32 +00:00
* $capabilities [ 1 ] -> contextlevel = 1000
2007-01-30 10:10:25 +00:00
-> module = 0 // changed from SITEID in 1.8 (??)
2006-08-08 05:13:06 +00:00
-> capability = do_anything
-> id = 1 ( id is the context id )
-> sum = 0
2006-09-20 21:00:45 +00:00
2006-09-22 06:19:32 +00:00
* $capabilities [ 2 ] -> contextlevel = 1000
2007-01-30 10:10:25 +00:00
-> module = 0 // changed from SITEID in 1.8 (??)
2006-08-08 05:13:06 +00:00
-> capability = post_messages
-> id = 1
-> sum = - 9000
2006-09-22 06:19:32 +00:00
* $capabilittes [ 3 ] -> contextlevel = 3000
2006-08-08 05:13:06 +00:00
-> module = course
-> capability = view_course_activities
-> id = 25
-> sum = 1
2006-09-22 06:19:32 +00:00
* $capabilittes [ 4 ] -> contextlevel = 3000
2006-08-08 05:13:06 +00:00
-> module = course
-> capability = view_course_activities
-> id = 26
-> sum = 0 ( this is another course )
2006-09-20 21:00:45 +00:00
2006-09-22 06:19:32 +00:00
* $capabilities [ 5 ] -> contextlevel = 3050
2006-08-08 05:13:06 +00:00
-> module = course
-> capability = view_course_activities
-> id = 25 ( override in course 25 )
-> sum = - 1
* ....
* now we proceed to write the session array , going from top to bottom
* at anypoint , we need to go up and check parent to look for prohibit
*/
// print_object($capabilities);
/* This is where we write to the actualy capabilities array
* what we need to do from here on is
* going down the array from lowest level to highest level
* 1 ) recursively check for prohibit ,
* if any , we write prohibit
* else , we write the value
* 2 ) at an override level , we overwrite current level
* if it ' s not set to prohibit already , and if different
* ........ that should be it ........
*/
2006-10-26 03:57:34 +00:00
// This is the flag used for detecting the current context level. Since we are going through
// the array in ascending order of context level. For normal capabilities, there should only
// be 1 value per (capability, contextlevel, context), because they are already summed. But,
// for overrides, since we are processing them separate, we need to sum the relevcant entries.
// We set this flag when we hit a new level.
// If the flag is already set, we keep adding (summing), otherwise, we just override previous
// settings (from lower level contexts)
$capflags = array (); // (contextid, contextlevel, capability)
2006-08-09 13:14:15 +00:00
$usercap = array (); // for other user's capabilities
2006-08-08 05:13:06 +00:00
foreach ( $capabilities as $capability ) {
2006-10-25 03:47:59 +00:00
if ( ! $context = get_context_instance_by_id ( $capability -> id2 )) {
2006-09-27 18:11:36 +00:00
continue ; // incorrect stale context
}
2006-08-14 05:55:40 +00:00
2006-08-09 14:16:13 +00:00
if ( ! empty ( $otheruserid )) { // we are pulling out other user's capabilities, do not write to session
2006-09-20 21:00:45 +00:00
2006-08-14 05:55:40 +00:00
if ( capability_prohibits ( $capability -> capability , $context , $capability -> sum , $usercap )) {
2006-10-25 03:47:59 +00:00
$usercap [ $capability -> id2 ][ $capability -> capability ] = CAP_PROHIBIT ;
2006-08-09 13:14:15 +00:00
continue ;
}
2006-10-26 03:57:34 +00:00
if ( isset ( $usercap [ $capability -> id2 ][ $capability -> capability ])) { // use isset because it can be sum 0
if ( ! empty ( $capflags [ $capability -> id2 ][ $capability -> contextlevel ][ $capability -> capability ])) {
$usercap [ $capability -> id2 ][ $capability -> capability ] += $capability -> sum ;
} else { // else we override, and update flag
$usercap [ $capability -> id2 ][ $capability -> capability ] = $capability -> sum ;
$capflags [ $capability -> id2 ][ $capability -> contextlevel ][ $capability -> capability ] = true ;
}
2006-10-25 03:47:59 +00:00
} else {
$usercap [ $capability -> id2 ][ $capability -> capability ] = $capability -> sum ;
2006-10-26 03:57:34 +00:00
$capflags [ $capability -> id2 ][ $capability -> contextlevel ][ $capability -> capability ] = true ;
2006-10-25 03:47:59 +00:00
}
2006-09-20 21:00:45 +00:00
2006-08-09 13:14:15 +00:00
} else {
2006-08-14 05:55:40 +00:00
if ( capability_prohibits ( $capability -> capability , $context , $capability -> sum )) { // if any parent or parent's parent is set to prohibit
2006-10-25 03:47:59 +00:00
$USER -> capabilities [ $capability -> id2 ][ $capability -> capability ] = CAP_PROHIBIT ;
2006-08-09 13:14:15 +00:00
continue ;
}
2006-09-20 21:00:45 +00:00
2006-08-09 13:14:15 +00:00
// if no parental prohibit set
// just write to session, i am not sure this is correct yet
// since 3050 shows up after 3000, and 3070 shows up after 3050,
// it should be ok just to overwrite like this, provided that there's no
// parental prohibits
// we need to write even if it's 0, because it could be an inherit override
2006-10-26 03:57:34 +00:00
if ( isset ( $USER -> capabilities [ $capability -> id2 ][ $capability -> capability ])) {
if ( ! empty ( $capflags [ $capability -> id2 ][ $capability -> contextlevel ][ $capability -> capability ])) {
$USER -> capabilities [ $capability -> id2 ][ $capability -> capability ] += $capability -> sum ;
} else { // else we override, and update flag
$USER -> capabilities [ $capability -> id2 ][ $capability -> capability ] = $capability -> sum ;
$capflags [ $capability -> id2 ][ $capability -> contextlevel ][ $capability -> capability ] = true ;
}
2006-10-25 03:47:59 +00:00
} else {
$USER -> capabilities [ $capability -> id2 ][ $capability -> capability ] = $capability -> sum ;
2006-10-26 03:57:34 +00:00
$capflags [ $capability -> id2 ][ $capability -> contextlevel ][ $capability -> capability ] = true ;
2006-10-25 03:47:59 +00:00
}
2006-08-09 13:14:15 +00:00
}
2006-08-08 05:13:06 +00:00
}
2006-09-20 21:00:45 +00:00
2006-08-08 05:13:06 +00:00
// now we don't care about the huge array anymore, we can dispose it.
unset ( $capabilities );
2006-10-26 03:57:34 +00:00
unset ( $capflags );
2006-09-20 21:00:45 +00:00
2006-09-05 20:45:57 +00:00
if ( ! empty ( $otheruserid )) {
2006-09-20 21:00:45 +00:00
return $usercap ; // return the array
2006-08-08 05:13:06 +00:00
}
2006-10-23 15:17:31 +00:00
}
2007-03-07 13:45:41 +00:00
/**
2006-10-23 15:17:31 +00:00
* A convenience function to completely load all the capabilities
* for the current user . This is what gets called from login , for example .
*/
function load_all_capabilities () {
global $USER ;
2007-03-07 13:45:41 +00:00
//caching - helps user switching in cron
static $defcaps = false ;
2006-08-08 05:13:06 +00:00
2007-01-22 03:24:27 +00:00
unset ( $USER -> mycourses ); // Reset a cache used by get_my_courses
2007-03-07 13:45:41 +00:00
if ( isguestuser ()) {
2006-10-23 15:17:31 +00:00
load_guest_role (); // All non-guest users get this by default
2007-03-07 13:45:41 +00:00
} else if ( isloggedin ()) {
if ( $defcaps === false ) {
$defcaps = load_defaultuser_role ( true );
}
2007-03-20 07:42:41 +00:00
load_user_capability ();
// when in "course login as" - load only course caqpabilitites (it may not always work as expected)
if ( ! empty ( $USER -> realuser ) and $USER -> loginascontext -> contextlevel != CONTEXT_SYSTEM ) {
$children = get_child_contexts ( $USER -> loginascontext );
$children [] = $USER -> loginascontext -> id ;
foreach ( $USER -> capabilities as $conid => $caps ) {
if ( ! in_array ( $conid , $children )) {
unset ( $USER -> capabilities [ $conid ]);
2007-03-19 22:25:13 +00:00
}
2007-03-19 18:54:58 +00:00
}
}
2007-03-07 13:45:41 +00:00
2007-03-20 07:42:41 +00:00
// handle role switching in courses
2007-03-16 20:21:27 +00:00
if ( ! empty ( $USER -> switchrole )) {
foreach ( $USER -> switchrole as $contextid => $roleid ) {
$context = get_context_instance_by_id ( $contextid );
// first prune context and any child contexts
$children = get_child_contexts ( $context );
foreach ( $children as $childid ) {
unset ( $USER -> capabilities [ $childid ]);
}
unset ( $USER -> capabilities [ $contextid ]);
// now merge all switched role caps in context and bellow
$swithccaps = get_role_context_caps ( $roleid , $context );
$USER -> capabilities = merge_role_caps ( $USER -> capabilities , $swithccaps );
}
2007-03-07 13:45:41 +00:00
}
2007-03-20 02:57:57 +00:00
if ( isset ( $USER -> capabilities )) {
$USER -> capabilities = merge_role_caps ( $USER -> capabilities , $defcaps );
} else {
$USER -> capabilities = $defcaps ;
}
2007-03-16 20:21:27 +00:00
2006-10-23 15:17:31 +00:00
} else {
2007-03-07 13:45:41 +00:00
load_notloggedin_role ();
2006-10-23 15:17:31 +00:00
}
2006-08-08 05:13:06 +00:00
}
2006-10-23 15:17:31 +00:00
2007-03-05 11:27:01 +00:00
/**
2006-09-16 13:54:57 +00:00
* Check all the login enrolment information for the given user object
2006-09-20 21:00:45 +00:00
* by querying the enrolment plugins
2006-09-16 13:54:57 +00:00
*/
function check_enrolment_plugins ( & $user ) {
global $CFG ;
2006-09-25 01:34:21 +00:00
static $inprogress ; // To prevent this function being called more than once in an invocation
2006-09-25 01:42:41 +00:00
if ( ! empty ( $inprogress [ $user -> id ])) {
2006-09-25 01:34:21 +00:00
return ;
}
2006-09-25 01:42:41 +00:00
$inprogress [ $user -> id ] = true ; // Set the flag
2006-09-25 01:34:21 +00:00
2006-09-16 13:54:57 +00:00
require_once ( $CFG -> dirroot . '/enrol/enrol.class.php' );
2006-09-20 21:00:45 +00:00
2006-09-16 13:54:57 +00:00
if ( ! ( $plugins = explode ( ',' , $CFG -> enrol_plugins_enabled ))) {
$plugins = array ( $CFG -> enrol );
}
foreach ( $plugins as $plugin ) {
$enrol = enrolment_factory :: factory ( $plugin );
if ( method_exists ( $enrol , 'setup_enrolments' )) { /// Plugin supports Roles (Moodle 1.7 and later)
$enrol -> setup_enrolments ( $user );
} else { /// Run legacy enrolment methods
if ( method_exists ( $enrol , 'get_student_courses' )) {
$enrol -> get_student_courses ( $user );
}
if ( method_exists ( $enrol , 'get_teacher_courses' )) {
$enrol -> get_teacher_courses ( $user );
}
/// deal with $user->students and $user->teachers stuff
unset ( $user -> student );
unset ( $user -> teacher );
}
unset ( $enrol );
}
2006-09-25 01:34:21 +00:00
2006-09-25 01:42:41 +00:00
unset ( $inprogress [ $user -> id ]); // Unset the flag
2006-09-16 13:54:57 +00:00
}
2006-08-08 05:13:06 +00:00
/**
* This is a recursive function that checks whether the capability in this
* context , or the parent capabilities are set to prohibit .
*
* At this point , we can probably just use the values already set in the
* session variable , since we are going down the level . Any prohit set in
* parents would already reflect in the session .
*
* @ param $capability - capability name
* @ param $sum - sum of all capabilities values
2006-08-14 05:55:40 +00:00
* @ param $context - the context object
2006-08-08 05:13:06 +00:00
* @ param $array - when loading another user caps , their caps are not stored in session but an array
*/
2006-08-14 05:55:40 +00:00
function capability_prohibits ( $capability , $context , $sum = '' , $array = '' ) {
2006-08-08 05:13:06 +00:00
global $USER ;
2006-08-14 05:55:40 +00:00
2007-01-12 07:41:33 +00:00
// caching, mainly to save unnecessary sqls
static $prohibits ; //[capability][contextid]
if ( isset ( $prohibits [ $capability ][ $context -> id ])) {
return $prohibits [ $capability ][ $context -> id ];
}
2006-10-21 14:53:47 +00:00
if ( empty ( $context -> id )) {
2007-01-12 07:41:33 +00:00
$prohibits [ $capability ][ $context -> id ] = false ;
2006-10-21 14:53:47 +00:00
return false ;
}
if ( empty ( $capability )) {
2007-01-12 07:41:33 +00:00
$prohibits [ $capability ][ $context -> id ] = false ;
2006-10-21 14:53:47 +00:00
return false ;
}
2006-10-18 06:45:38 +00:00
if ( $sum < ( CAP_PROHIBIT / 2 )) {
2006-08-08 05:13:06 +00:00
// If this capability is set to prohibit.
2007-01-12 07:41:33 +00:00
$prohibits [ $capability ][ $context -> id ] = true ;
2006-08-08 05:13:06 +00:00
return true ;
}
2006-09-20 21:00:45 +00:00
2006-10-18 06:45:38 +00:00
if ( ! empty ( $array )) {
2006-09-20 21:00:45 +00:00
if ( isset ( $array [ $context -> id ][ $capability ])
2006-10-18 06:45:38 +00:00
&& $array [ $context -> id ][ $capability ] < ( CAP_PROHIBIT / 2 )) {
2007-01-12 07:41:33 +00:00
$prohibits [ $capability ][ $context -> id ] = true ;
2006-08-09 13:14:15 +00:00
return true ;
2006-09-20 21:00:45 +00:00
}
2006-08-08 05:13:06 +00:00
} else {
2006-08-09 13:14:15 +00:00
// Else if set in session.
2006-09-20 21:00:45 +00:00
if ( isset ( $USER -> capabilities [ $context -> id ][ $capability ])
2006-10-18 06:45:38 +00:00
&& $USER -> capabilities [ $context -> id ][ $capability ] < ( CAP_PROHIBIT / 2 )) {
2007-01-12 07:41:33 +00:00
$prohibits [ $capability ][ $context -> id ] = true ;
2006-08-09 13:14:15 +00:00
return true ;
}
2006-08-08 05:13:06 +00:00
}
2006-09-22 06:19:32 +00:00
switch ( $context -> contextlevel ) {
2006-09-20 21:00:45 +00:00
2006-08-08 05:13:06 +00:00
case CONTEXT_SYSTEM :
// By now it's a definite an inherit.
return 0 ;
break ;
case CONTEXT_PERSONAL :
2006-10-21 14:53:47 +00:00
$parent = get_context_instance ( CONTEXT_SYSTEM );
2007-01-12 07:41:33 +00:00
$prohibits [ $capability ][ $context -> id ] = capability_prohibits ( $capability , $parent );
return $prohibits [ $capability ][ $context -> id ];
2006-08-08 05:13:06 +00:00
break ;
2006-09-15 14:09:16 +00:00
case CONTEXT_USER :
2006-10-21 14:53:47 +00:00
$parent = get_context_instance ( CONTEXT_SYSTEM );
2007-01-12 07:41:33 +00:00
$prohibits [ $capability ][ $context -> id ] = capability_prohibits ( $capability , $parent );
return $prohibits [ $capability ][ $context -> id ];
2006-08-08 05:13:06 +00:00
break ;
case CONTEXT_COURSECAT :
// Coursecat -> coursecat or site.
2006-10-21 14:53:47 +00:00
if ( ! $coursecat = get_record ( 'course_categories' , 'id' , $context -> instanceid )) {
2007-01-12 07:41:33 +00:00
$prohibits [ $capability ][ $context -> id ] = false ;
2006-10-21 14:53:47 +00:00
return false ;
2006-11-15 08:23:27 +00:00
}
2006-08-09 14:16:13 +00:00
if ( ! empty ( $coursecat -> parent )) {
2006-08-08 05:13:06 +00:00
// return parent value if exist.
$parent = get_context_instance ( CONTEXT_COURSECAT , $coursecat -> parent );
} else {
// Return site value.
2006-10-21 14:53:47 +00:00
$parent = get_context_instance ( CONTEXT_SYSTEM );
2006-08-08 05:13:06 +00:00
}
2007-01-12 07:41:33 +00:00
$prohibits [ $capability ][ $context -> id ] = capability_prohibits ( $capability , $parent );
return $prohibits [ $capability ][ $context -> id ];
2006-08-08 05:13:06 +00:00
break ;
case CONTEXT_COURSE :
// 1 to 1 to course cat.
// Find the course cat, and return its value.
2006-10-21 14:53:47 +00:00
if ( ! $course = get_record ( 'course' , 'id' , $context -> instanceid )) {
2007-01-12 07:41:33 +00:00
$prohibits [ $capability ][ $context -> id ] = false ;
2006-10-21 14:53:47 +00:00
return false ;
}
2006-11-15 08:23:27 +00:00
// Yu: Separating site and site course context
if ( $course -> id == SITEID ) {
$parent = get_context_instance ( CONTEXT_SYSTEM );
} else {
$parent = get_context_instance ( CONTEXT_COURSECAT , $course -> category );
}
2007-01-12 07:41:33 +00:00
$prohibits [ $capability ][ $context -> id ] = capability_prohibits ( $capability , $parent );
return $prohibits [ $capability ][ $context -> id ];
2006-08-08 05:13:06 +00:00
break ;
case CONTEXT_GROUP :
// 1 to 1 to course.
2007-01-04 13:15:04 +13:00
if ( ! $courseid = groups_get_course ( $context -> instanceid )) {
2007-01-12 07:41:33 +00:00
$prohibits [ $capability ][ $context -> id ] = false ;
2006-10-21 14:53:47 +00:00
return false ;
}
2007-01-04 13:15:04 +13:00
$parent = get_context_instance ( CONTEXT_COURSE , $courseid );
2007-01-12 07:41:33 +00:00
$prohibits [ $capability ][ $context -> id ] = capability_prohibits ( $capability , $parent );
return $prohibits [ $capability ][ $context -> id ];
2006-08-08 05:13:06 +00:00
break ;
case CONTEXT_MODULE :
// 1 to 1 to course.
2006-10-21 14:53:47 +00:00
if ( ! $cm = get_record ( 'course_modules' , 'id' , $context -> instanceid )) {
2007-01-12 07:41:33 +00:00
$prohibits [ $capability ][ $context -> id ] = false ;
2006-10-21 14:53:47 +00:00
return false ;
}
2006-08-08 05:13:06 +00:00
$parent = get_context_instance ( CONTEXT_COURSE , $cm -> course );
2007-01-12 07:41:33 +00:00
$prohibits [ $capability ][ $context -> id ] = capability_prohibits ( $capability , $parent );
return $prohibits [ $capability ][ $context -> id ];
2006-08-08 05:13:06 +00:00
break ;
case CONTEXT_BLOCK :
// 1 to 1 to course.
2006-10-21 14:53:47 +00:00
if ( ! $block = get_record ( 'block_instance' , 'id' , $context -> instanceid )) {
2007-01-12 07:41:33 +00:00
$prohibits [ $capability ][ $context -> id ] = false ;
2006-10-21 14:53:47 +00:00
return false ;
}
2007-05-07 03:24:22 +00:00
if ( $block -> pagetype == 'course-view' ) {
$parent = get_context_instance ( CONTEXT_COURSE , $block -> pageid ); // needs check
} else {
$parent = get_context_instance ( CONTEXT_SYSTEM );
}
2007-01-12 07:41:33 +00:00
$prohibits [ $capability ][ $context -> id ] = capability_prohibits ( $capability , $parent );
return $prohibits [ $capability ][ $context -> id ];
2006-08-08 05:13:06 +00:00
break ;
default :
2006-10-21 14:53:47 +00:00
print_error ( 'unknowncontext' );
return false ;
2006-08-08 05:13:06 +00:00
}
}
/**
* A print form function . This should either grab all the capabilities from
* files or a central table for that particular module instance , then present
* them in check boxes . Only relevant capabilities should print for known
* context .
* @ param $mod - module id of the mod
*/
function print_capabilities ( $modid = 0 ) {
global $CFG ;
2006-09-20 21:00:45 +00:00
2006-08-08 05:13:06 +00:00
$capabilities = array ();
if ( $modid ) {
// We are in a module specific context.
// Get the mod's name.
// Call the function that grabs the file and parse.
$cm = get_record ( 'course_modules' , 'id' , $modid );
$module = get_record ( 'modules' , 'id' , $cm -> module );
2006-09-20 21:00:45 +00:00
2006-08-08 05:13:06 +00:00
} else {
// Print all capabilities.
foreach ( $capabilities as $capability ) {
// Prints the check box component.
}
}
}
/**
2006-08-11 02:44:02 +00:00
* Installs the roles system .
* This function runs on a fresh install as well as on an upgrade from the old
* hard - coded student / teacher / admin etc . roles to the new roles system .
2006-08-08 05:13:06 +00:00
*/
2006-08-11 02:44:02 +00:00
function moodle_install_roles () {
2006-08-08 05:13:06 +00:00
2006-08-11 02:44:02 +00:00
global $CFG , $db ;
2006-09-20 21:00:45 +00:00
2006-09-29 05:35:37 +00:00
/// Create a system wide context for assignemnt.
2006-10-25 08:38:14 +00:00
$systemcontext = $context = get_context_instance ( CONTEXT_SYSTEM );
2006-08-08 05:13:06 +00:00
2006-08-11 02:44:02 +00:00
2006-09-29 05:35:37 +00:00
/// Create default/legacy roles and capabilities.
/// (1 legacy capability per legacy role at system level).
2006-11-20 14:08:40 +00:00
$adminrole = create_role ( addslashes ( get_string ( 'administrator' )), 'admin' ,
addslashes ( get_string ( 'administratordescription' )), 'moodle/legacy:admin' );
$coursecreatorrole = create_role ( addslashes ( get_string ( 'coursecreators' )), 'coursecreator' ,
addslashes ( get_string ( 'coursecreatorsdescription' )), 'moodle/legacy:coursecreator' );
$editteacherrole = create_role ( addslashes ( get_string ( 'defaultcourseteacher' )), 'editingteacher' ,
addslashes ( get_string ( 'defaultcourseteacherdescription' )), 'moodle/legacy:editingteacher' );
$noneditteacherrole = create_role ( addslashes ( get_string ( 'noneditingteacher' )), 'teacher' ,
addslashes ( get_string ( 'noneditingteacherdescription' )), 'moodle/legacy:teacher' );
$studentrole = create_role ( addslashes ( get_string ( 'defaultcoursestudent' )), 'student' ,
addslashes ( get_string ( 'defaultcoursestudentdescription' )), 'moodle/legacy:student' );
$guestrole = create_role ( addslashes ( get_string ( 'guest' )), 'guest' ,
addslashes ( get_string ( 'guestdescription' )), 'moodle/legacy:guest' );
2007-01-31 21:05:32 +00:00
$userrole = create_role ( addslashes ( get_string ( 'authenticateduser' )), 'user' ,
addslashes ( get_string ( 'authenticateduserdescription' )), 'moodle/legacy:user' );
2006-10-25 07:20:28 +00:00
2006-10-08 11:00:49 +00:00
/// Now is the correct moment to install capabilities - after creation of legacy roles, but before assigning of roles
2006-09-29 05:35:37 +00:00
2006-08-09 13:14:15 +00:00
if ( ! assign_capability ( 'moodle/site:doanything' , CAP_ALLOW , $adminrole , $systemcontext -> id )) {
2006-08-08 05:13:06 +00:00
error ( 'Could not assign moodle/site:doanything to the admin role' );
}
2006-09-27 22:59:37 +00:00
if ( ! update_capabilities ()) {
error ( 'Had trouble upgrading the core capabilities for the Roles System' );
}
2006-08-11 02:44:02 +00:00
2006-09-29 05:35:37 +00:00
/// Look inside user_admin, user_creator, user_teachers, user_students and
/// assign above new roles. If a user has both teacher and student role,
/// only teacher role is assigned. The assignment should be system level.
2006-08-11 02:44:02 +00:00
$dbtables = $db -> MetaTables ( 'TABLES' );
2006-09-20 21:00:45 +00:00
2006-09-29 06:19:47 +00:00
/// Set up the progress bar
$usertables = array ( 'user_admins' , 'user_coursecreators' , 'user_teachers' , 'user_students' );
$totalcount = $progresscount = 0 ;
foreach ( $usertables as $usertable ) {
if ( in_array ( $CFG -> prefix . $usertable , $dbtables )) {
$totalcount += count_records ( $usertable );
}
}
2006-09-29 06:41:10 +00:00
print_progress ( 0 , $totalcount , 5 , 1 , 'Processing role assignments' );
2006-08-11 02:44:02 +00:00
2006-09-29 05:35:37 +00:00
/// Upgrade the admins.
/// Sort using id ASC, first one is primary admin.
2006-08-11 02:44:02 +00:00
if ( in_array ( $CFG -> prefix . 'user_admins' , $dbtables )) {
2006-09-26 13:31:57 +00:00
if ( $rs = get_recordset_sql ( 'SELECT * from ' . $CFG -> prefix . 'user_admins ORDER BY ID ASC' )) {
2007-01-29 11:24:18 +00:00
while ( $admin = rs_fetch_next_record ( $rs )) {
2006-08-11 02:44:02 +00:00
role_assign ( $adminrole , $admin -> userid , 0 , $systemcontext -> id );
2006-09-29 06:19:47 +00:00
$progresscount ++ ;
2006-09-29 06:41:10 +00:00
print_progress ( $progresscount , $totalcount , 5 , 1 , 'Processing role assignments' );
2006-08-11 02:44:02 +00:00
}
2007-01-29 11:24:18 +00:00
rs_close ( $rs );
2006-08-11 02:44:02 +00:00
}
} else {
// This is a fresh install.
2006-08-08 05:13:06 +00:00
}
2006-08-11 02:44:02 +00:00
2006-09-29 05:35:37 +00:00
/// Upgrade course creators.
2006-08-11 02:44:02 +00:00
if ( in_array ( $CFG -> prefix . 'user_coursecreators' , $dbtables )) {
2006-09-26 13:31:57 +00:00
if ( $rs = get_recordset ( 'user_coursecreators' )) {
2007-01-29 11:24:18 +00:00
while ( $coursecreator = rs_fetch_next_record ( $rs )) {
2006-09-03 21:43:37 +00:00
role_assign ( $coursecreatorrole , $coursecreator -> userid , 0 , $systemcontext -> id );
2006-09-29 06:19:47 +00:00
$progresscount ++ ;
2006-09-29 06:41:10 +00:00
print_progress ( $progresscount , $totalcount , 5 , 1 , 'Processing role assignments' );
2006-08-11 02:44:02 +00:00
}
2007-01-29 11:24:18 +00:00
rs_close ( $rs );
2006-08-11 02:44:02 +00:00
}
2006-08-08 05:13:06 +00:00
}
2006-08-11 02:44:02 +00:00
2006-09-29 05:35:37 +00:00
/// Upgrade editting teachers and non-editting teachers.
2006-08-11 02:44:02 +00:00
if ( in_array ( $CFG -> prefix . 'user_teachers' , $dbtables )) {
2006-09-26 13:31:57 +00:00
if ( $rs = get_recordset ( 'user_teachers' )) {
2007-01-29 11:24:18 +00:00
while ( $teacher = rs_fetch_next_record ( $rs )) {
2006-11-20 03:55:35 +00:00
// removed code here to ignore site level assignments
// since the contexts are separated now
2006-09-13 09:08:14 +00:00
// populate the user_lastaccess table
2006-09-23 12:51:00 +00:00
$access = new object ();
2006-09-13 09:08:14 +00:00
$access -> timeaccess = $teacher -> timeaccess ;
$access -> userid = $teacher -> userid ;
$access -> courseid = $teacher -> course ;
insert_record ( 'user_lastaccess' , $access );
2006-09-26 13:31:57 +00:00
2006-09-13 09:08:14 +00:00
// assign the default student role
2006-08-11 02:44:02 +00:00
$coursecontext = get_context_instance ( CONTEXT_COURSE , $teacher -> course ); // needs cache
2007-03-07 01:35:47 +00:00
// hidden teacher
if ( $teacher -> authority == 0 ) {
$hiddenteacher = 1 ;
} else {
$hiddenteacher = 0 ;
}
2006-08-11 02:44:02 +00:00
if ( $teacher -> editall ) { // editting teacher
2007-03-07 01:35:47 +00:00
role_assign ( $editteacherrole , $teacher -> userid , 0 , $coursecontext -> id , 0 , 0 , $hiddenteacher );
2006-08-11 02:44:02 +00:00
} else {
2007-03-07 01:35:47 +00:00
role_assign ( $noneditteacherrole , $teacher -> userid , 0 , $coursecontext -> id , 0 , 0 , $hiddenteacher );
2006-08-11 02:44:02 +00:00
}
2006-09-29 06:19:47 +00:00
$progresscount ++ ;
2006-09-29 06:41:10 +00:00
print_progress ( $progresscount , $totalcount , 5 , 1 , 'Processing role assignments' );
2006-08-11 02:44:02 +00:00
}
2007-01-29 11:24:18 +00:00
rs_close ( $rs );
2006-08-08 05:13:06 +00:00
}
}
2006-08-11 02:44:02 +00:00
2006-09-29 05:35:37 +00:00
/// Upgrade students.
2006-08-11 02:44:02 +00:00
if ( in_array ( $CFG -> prefix . 'user_students' , $dbtables )) {
2006-09-26 13:31:57 +00:00
if ( $rs = get_recordset ( 'user_students' )) {
2007-01-29 11:24:18 +00:00
while ( $student = rs_fetch_next_record ( $rs )) {
2006-09-26 13:31:57 +00:00
2006-09-13 09:08:14 +00:00
// populate the user_lastaccess table
2006-09-26 13:31:57 +00:00
$access = new object ;
2006-09-13 09:08:14 +00:00
$access -> timeaccess = $student -> timeaccess ;
$access -> userid = $student -> userid ;
$access -> courseid = $student -> course ;
insert_record ( 'user_lastaccess' , $access );
2006-09-26 13:31:57 +00:00
2006-09-13 09:08:14 +00:00
// assign the default student role
2006-08-11 02:44:02 +00:00
$coursecontext = get_context_instance ( CONTEXT_COURSE , $student -> course );
role_assign ( $studentrole , $student -> userid , 0 , $coursecontext -> id );
2006-09-29 06:19:47 +00:00
$progresscount ++ ;
2006-09-29 06:41:10 +00:00
print_progress ( $progresscount , $totalcount , 5 , 1 , 'Processing role assignments' );
2006-08-11 02:44:02 +00:00
}
2007-01-29 11:24:18 +00:00
rs_close ( $rs );
2006-08-11 02:44:02 +00:00
}
2006-08-08 05:13:06 +00:00
}
2006-08-11 02:44:02 +00:00
2006-09-29 05:35:37 +00:00
/// Upgrade guest (only 1 entry).
2006-08-11 02:44:02 +00:00
if ( $guestuser = get_record ( 'user' , 'username' , 'guest' )) {
role_assign ( $guestrole , $guestuser -> id , 0 , $systemcontext -> id );
}
2006-09-29 06:41:10 +00:00
print_progress ( $totalcount , $totalcount , 5 , 1 , 'Processing role assignments' );
2006-08-11 02:44:02 +00:00
2006-09-29 05:35:37 +00:00
/// Insert the correct records for legacy roles
2006-08-23 06:36:08 +00:00
allow_assign ( $adminrole , $adminrole );
allow_assign ( $adminrole , $coursecreatorrole );
allow_assign ( $adminrole , $noneditteacherrole );
2006-09-20 21:00:45 +00:00
allow_assign ( $adminrole , $editteacherrole );
2006-08-23 06:36:08 +00:00
allow_assign ( $adminrole , $studentrole );
allow_assign ( $adminrole , $guestrole );
2006-09-20 21:00:45 +00:00
2006-08-23 06:36:08 +00:00
allow_assign ( $coursecreatorrole , $noneditteacherrole );
allow_assign ( $coursecreatorrole , $editteacherrole );
2006-09-20 21:00:45 +00:00
allow_assign ( $coursecreatorrole , $studentrole );
2006-08-23 06:36:08 +00:00
allow_assign ( $coursecreatorrole , $guestrole );
2006-09-20 21:00:45 +00:00
allow_assign ( $editteacherrole , $noneditteacherrole );
allow_assign ( $editteacherrole , $studentrole );
2006-08-23 06:36:08 +00:00
allow_assign ( $editteacherrole , $guestrole );
2006-09-20 21:00:45 +00:00
2006-09-29 05:35:37 +00:00
/// Set up default permissions for overrides
2006-08-23 06:36:08 +00:00
allow_override ( $adminrole , $adminrole );
allow_override ( $adminrole , $coursecreatorrole );
allow_override ( $adminrole , $noneditteacherrole );
2006-09-20 21:00:45 +00:00
allow_override ( $adminrole , $editteacherrole );
2006-08-23 06:36:08 +00:00
allow_override ( $adminrole , $studentrole );
2006-09-20 21:00:45 +00:00
allow_override ( $adminrole , $guestrole );
2007-01-31 21:05:32 +00:00
allow_override ( $adminrole , $userrole );
2006-08-11 02:44:02 +00:00
2006-09-17 06:37:59 +00:00
2006-09-29 05:35:37 +00:00
/// Delete the old user tables when we are done
2006-10-06 06:47:12 +00:00
drop_table ( new XMLDBTable ( 'user_students' ));
drop_table ( new XMLDBTable ( 'user_teachers' ));
drop_table ( new XMLDBTable ( 'user_coursecreators' ));
drop_table ( new XMLDBTable ( 'user_admins' ));
2006-09-29 05:35:37 +00:00
2006-08-08 05:13:06 +00:00
}
2007-03-03 21:07:07 +00:00
/**
* Returns array of all legacy roles .
*/
function get_legacy_roles () {
return array (
2007-03-03 22:30:35 +00:00
'admin' => 'moodle/legacy:admin' ,
2007-03-03 21:07:07 +00:00
'coursecreator' => 'moodle/legacy:coursecreator' ,
2007-03-03 22:30:35 +00:00
'editingteacher' => 'moodle/legacy:editingteacher' ,
'teacher' => 'moodle/legacy:teacher' ,
'student' => 'moodle/legacy:student' ,
2007-03-05 11:27:01 +00:00
'guest' => 'moodle/legacy:guest' ,
'user' => 'moodle/legacy:user'
2007-03-03 21:07:07 +00:00
);
}
2007-03-06 19:19:19 +00:00
function get_legacy_type ( $roleid ) {
$sitecontext = get_context_instance ( CONTEXT_SYSTEM );
$legacyroles = get_legacy_roles ();
$result = '' ;
foreach ( $legacyroles as $ltype => $lcap ) {
$localoverride = get_local_override ( $roleid , $sitecontext -> id , $lcap );
if ( ! empty ( $localoverride -> permission ) and $localoverride -> permission == CAP_ALLOW ) {
//choose first selected legacy capability - reset the rest
if ( empty ( $result )) {
$result = $ltype ;
} else {
2007-03-07 09:38:21 +00:00
unassign_capability ( $lcap , $roleid );
2007-03-06 19:19:19 +00:00
}
}
}
return $result ;
}
2006-08-08 05:13:06 +00:00
/**
* Assign the defaults found in this capabality definition to roles that have
* the corresponding legacy capabilities assigned to them .
* @ param $legacyperms - an array in the format ( example ) :
* 'guest' => CAP_PREVENT ,
* 'student' => CAP_ALLOW ,
* 'teacher' => CAP_ALLOW ,
* 'editingteacher' => CAP_ALLOW ,
* 'coursecreator' => CAP_ALLOW ,
* 'admin' => CAP_ALLOW
* @ return boolean - success or failure .
*/
function assign_legacy_capabilities ( $capability , $legacyperms ) {
2006-09-20 21:00:45 +00:00
2007-03-03 21:07:07 +00:00
$legacyroles = get_legacy_roles ();
2006-08-08 05:13:06 +00:00
foreach ( $legacyperms as $type => $perm ) {
2006-09-20 21:00:45 +00:00
2006-10-25 08:38:14 +00:00
$systemcontext = get_context_instance ( CONTEXT_SYSTEM );
2006-09-20 21:00:45 +00:00
2007-03-03 21:07:07 +00:00
if ( ! array_key_exists ( $type , $legacyroles )) {
error ( 'Incorrect legacy role definition for type: ' . $type );
}
2006-09-20 21:00:45 +00:00
2007-03-03 21:07:07 +00:00
if ( $roles = get_roles_with_capability ( $legacyroles [ $type ], CAP_ALLOW )) {
2006-09-12 07:07:30 +00:00
foreach ( $roles as $role ) {
// Assign a site level capability.
if ( ! assign_capability ( $capability , $perm , $role -> id , $systemcontext -> id )) {
return false ;
}
2006-08-08 05:13:06 +00:00
}
}
}
return true ;
}
2006-08-14 07:15:03 +00:00
/**
* Checks to see if a capability is a legacy capability .
* @ param $capabilityname
* @ return boolean
*/
2006-08-08 05:13:06 +00:00
function islegacy ( $capabilityname ) {
2007-03-06 22:01:22 +00:00
if ( strpos ( $capabilityname , 'moodle/legacy' ) === 0 ) {
2006-09-20 21:00:45 +00:00
return true ;
2007-03-06 22:01:22 +00:00
} else {
return false ;
2006-08-09 13:14:15 +00:00
}
2006-08-08 05:13:06 +00:00
}
2006-08-14 07:15:03 +00:00
/**********************************
2006-08-08 05:13:06 +00:00
* Context Manipulation functions *
**********************************/
/**
2006-09-23 06:10:48 +00:00
* Create a new context record for use by all roles - related stuff
2006-08-08 05:13:06 +00:00
* @ param $level
* @ param $instanceid
2006-09-27 17:50:53 +00:00
*
* @ return object newly created context ( or existing one with a debug warning )
2006-08-08 05:13:06 +00:00
*/
2006-09-22 06:19:32 +00:00
function create_context ( $contextlevel , $instanceid ) {
2006-09-27 17:50:53 +00:00
if ( ! $context = get_record ( 'context' , 'contextlevel' , $contextlevel , 'instanceid' , $instanceid )) {
if ( ! validate_context ( $contextlevel , $instanceid )) {
debugging ( 'Error: Invalid context creation request for level "' . s ( $contextlevel ) . '", instance "' . s ( $instanceid ) . '".' );
return NULL ;
}
2007-01-30 10:10:25 +00:00
if ( $contextlevel == CONTEXT_SYSTEM ) {
return create_system_context ();
}
2006-09-27 17:50:53 +00:00
$context = new object ();
2006-09-22 06:19:32 +00:00
$context -> contextlevel = $contextlevel ;
2006-08-08 05:13:06 +00:00
$context -> instanceid = $instanceid ;
2006-09-27 17:50:53 +00:00
if ( $id = insert_record ( 'context' , $context )) {
2007-01-12 07:41:33 +00:00
// we need to populate context_rel for every new context inserted
$c = get_record ( 'context' , 'id' , $id );
insert_context_rel ( $c );
return $c ;
2006-09-27 17:50:53 +00:00
} else {
debugging ( 'Error: could not insert new context level "' . s ( $contextlevel ) . '", instance "' . s ( $instanceid ) . '".' );
return NULL ;
}
} else {
debugging ( 'Warning: Context id "' . s ( $context -> id ) . '" not created, because it already exists.' );
return $context ;
2006-08-08 05:13:06 +00:00
}
}
2007-03-05 11:27:01 +00:00
/**
2007-01-30 10:10:25 +00:00
* This hacky function is needed because we can not change system context instanceid using normal upgrade routine .
*/
function create_system_context () {
if ( $context = get_record ( 'context' , 'contextlevel' , CONTEXT_SYSTEM , 'instanceid' , SITEID )) {
// we are going to change instanceid of system context to 0 now
$context -> instanceid = 0 ;
update_record ( 'context' , $context );
//context rel not affected
return $context ;
} else {
$context = new object ();
$context -> contextlevel = CONTEXT_SYSTEM ;
$context -> instanceid = 0 ;
if ( $context -> id = insert_record ( 'context' , $context )) {
// we need not to populate context_rel for system context
return $context ;
} else {
debugging ( 'Can not create system context' );
return NULL ;
}
}
}
2006-09-23 06:10:48 +00:00
/**
* Create a new context record for use by all roles - related stuff
* @ param $level
* @ param $instanceid
2006-09-27 17:50:53 +00:00
*
* @ return true if properly deleted
2006-09-23 06:10:48 +00:00
*/
function delete_context ( $contextlevel , $instanceid ) {
2007-01-12 07:41:33 +00:00
if ( $context = get_context_instance ( $contextlevel , $instanceid )) {
delete_records ( 'context_rel' , 'c2' , $context -> id ); // might not be a parent
2006-09-23 06:10:48 +00:00
return delete_records ( 'context' , 'id' , $context -> id ) &&
delete_records ( 'role_assignments' , 'contextid' , $context -> id ) &&
2007-01-12 07:41:33 +00:00
delete_records ( 'role_capabilities' , 'contextid' , $context -> id ) &&
delete_records ( 'context_rel' , 'c1' , $context -> id );
2006-09-23 06:10:48 +00:00
}
return true ;
}
2006-09-27 17:50:53 +00:00
/**
* Validate that object with instanceid really exists in given context level .
*
* return if instanceid object exists
*/
function validate_context ( $contextlevel , $instanceid ) {
switch ( $contextlevel ) {
case CONTEXT_SYSTEM :
2007-01-30 10:10:25 +00:00
return ( $instanceid == 0 );
2006-09-27 17:50:53 +00:00
case CONTEXT_PERSONAL :
return ( boolean ) count_records ( 'user' , 'id' , $instanceid );
case CONTEXT_USER :
return ( boolean ) count_records ( 'user' , 'id' , $instanceid );
case CONTEXT_COURSECAT :
2006-09-27 20:43:04 +00:00
if ( $instanceid == 0 ) {
return true ; // site course category
}
2006-09-27 17:50:53 +00:00
return ( boolean ) count_records ( 'course_categories' , 'id' , $instanceid );
case CONTEXT_COURSE :
return ( boolean ) count_records ( 'course' , 'id' , $instanceid );
case CONTEXT_GROUP :
2007-01-04 13:15:04 +13:00
return groups_group_exists ( $instanceid );
2006-09-27 17:50:53 +00:00
case CONTEXT_MODULE :
return ( boolean ) count_records ( 'course_modules' , 'id' , $instanceid );
case CONTEXT_BLOCK :
return ( boolean ) count_records ( 'block_instance' , 'id' , $instanceid );
default :
return false ;
}
}
2006-08-08 05:13:06 +00:00
/**
* Get the context instance as an object . This function will create the
* context instance if it does not exist yet .
* @ param $level
* @ param $instance
*/
2007-01-30 10:10:25 +00:00
function get_context_instance ( $contextlevel = NULL , $instance = 0 ) {
2006-08-13 13:28:01 +00:00
2006-08-25 14:15:52 +00:00
global $context_cache , $context_cache_id , $CONTEXT ;
2006-09-27 17:58:17 +00:00
static $allowed_contexts = array ( CONTEXT_SYSTEM , CONTEXT_PERSONAL , CONTEXT_USER , CONTEXT_COURSECAT , CONTEXT_COURSE , CONTEXT_GROUP , CONTEXT_MODULE , CONTEXT_BLOCK );
2006-08-23 01:29:52 +00:00
2007-01-30 10:10:25 +00:00
// Yu: Separating site and site course context - removed CONTEXT_COURSE override when SITEID
2007-03-23 07:21:27 +00:00
// fix for MDL-9016
if ( $contextlevel == 'clearcache' ) {
// Clear ALL cache
$context_cache = array ();
$context_cache_id = array ();
$CONTEXT = '' ;
return false ;
}
2006-10-19 06:16:35 +00:00
2006-08-13 15:48:57 +00:00
/// If no level is supplied then return the current global context if there is one
2006-09-22 06:19:32 +00:00
if ( empty ( $contextlevel )) {
2006-08-13 15:48:57 +00:00
if ( empty ( $CONTEXT )) {
2006-09-27 17:58:17 +00:00
//fatal error, code must be fixed
error ( " Error: get_context_instance() called without a context " );
2006-08-13 15:48:57 +00:00
} else {
return $CONTEXT ;
}
2006-08-13 13:28:01 +00:00
}
2007-01-30 10:10:25 +00:00
/// Backwards compatibility with obsoleted (CONTEXT_SYSTEM, SITEID)
if ( $contextlevel == CONTEXT_SYSTEM ) {
$instance = 0 ;
}
2006-09-27 17:58:17 +00:00
/// check allowed context levels
if ( ! in_array ( $contextlevel , $allowed_contexts )) {
2006-09-27 18:11:36 +00:00
// fatal error, code must be fixed - probably typo or switched parameters
2006-09-27 17:58:17 +00:00
error ( 'Error: get_context_instance() called with incorrect context level "' . s ( $contextlevel ) . '"' );
}
2006-08-13 15:48:57 +00:00
/// Check the cache
2006-09-22 06:19:32 +00:00
if ( isset ( $context_cache [ $contextlevel ][ $instance ])) { // Already cached
return $context_cache [ $contextlevel ][ $instance ];
2006-08-13 13:28:01 +00:00
}
2006-08-13 15:48:57 +00:00
/// Get it from the database, or create it
2006-09-22 06:19:32 +00:00
if ( ! $context = get_record ( 'context' , 'contextlevel' , $contextlevel , 'instanceid' , $instance )) {
create_context ( $contextlevel , $instance );
$context = get_record ( 'context' , 'contextlevel' , $contextlevel , 'instanceid' , $instance );
2006-08-13 13:28:01 +00:00
}
2006-09-08 19:28:03 +00:00
/// Only add to cache if context isn't empty.
if ( ! empty ( $context )) {
2006-09-22 06:19:32 +00:00
$context_cache [ $contextlevel ][ $instance ] = $context ; // Cache it for later
2006-09-08 19:28:03 +00:00
$context_cache_id [ $context -> id ] = $context ; // Cache it for later
}
2006-08-14 05:55:40 +00:00
2006-08-08 05:13:06 +00:00
return $context ;
}
2006-08-14 07:15:03 +00:00
2006-08-13 15:48:57 +00:00
/**
* Get a context instance as an object , from a given id .
* @ param $id
*/
function get_context_instance_by_id ( $id ) {
2006-08-23 01:29:52 +00:00
global $context_cache , $context_cache_id ;
2006-08-13 15:48:57 +00:00
if ( isset ( $context_cache_id [ $id ])) { // Already cached
2006-08-22 16:18:11 +00:00
return $context_cache_id [ $id ];
2006-08-13 15:48:57 +00:00
}
if ( $context = get_record ( 'context' , 'id' , $id )) { // Update the cache and return
2006-09-22 06:19:32 +00:00
$context_cache [ $context -> contextlevel ][ $context -> instanceid ] = $context ;
2006-08-13 15:48:57 +00:00
$context_cache_id [ $context -> id ] = $context ;
return $context ;
}
return false ;
}
2006-08-08 05:13:06 +00:00
2006-08-13 09:25:45 +00:00
/**
* Get the local override ( if any ) for a given capability in a role in a context
* @ param $roleid
2006-08-14 05:55:40 +00:00
* @ param $contextid
* @ param $capability
2006-08-13 09:25:45 +00:00
*/
function get_local_override ( $roleid , $contextid , $capability ) {
return get_record ( 'role_capabilities' , 'roleid' , $roleid , 'capability' , $capability , 'contextid' , $contextid );
}
2006-08-08 05:13:06 +00:00
/************************************
* DB TABLE RELATED FUNCTIONS *
************************************/
2006-08-14 07:15:03 +00:00
/**
2006-08-08 05:13:06 +00:00
* function that creates a role
* @ param name - role name
2006-09-18 17:40:22 +00:00
* @ param shortname - role short name
2006-08-08 05:13:06 +00:00
* @ param description - role description
* @ param legacy - optional legacy capability
* @ return id or false
*/
2006-09-23 10:43:24 +00:00
function create_role ( $name , $shortname , $description , $legacy = '' ) {
2006-09-20 21:00:45 +00:00
2006-08-09 13:14:15 +00:00
// check for duplicate role name
2006-09-20 21:00:45 +00:00
2006-08-09 13:14:15 +00:00
if ( $role = get_record ( 'role' , 'name' , $name )) {
2006-09-20 21:00:45 +00:00
error ( 'there is already a role with this name!' );
2006-08-09 13:14:15 +00:00
}
2006-09-20 21:00:45 +00:00
2006-09-18 17:40:22 +00:00
if ( $role = get_record ( 'role' , 'shortname' , $shortname )) {
2006-09-20 21:00:45 +00:00
error ( 'there is already a role with this shortname!' );
2006-09-18 17:40:22 +00:00
}
2006-09-21 22:34:45 +00:00
$role = new object ();
2006-08-09 13:14:15 +00:00
$role -> name = $name ;
2006-09-18 17:40:22 +00:00
$role -> shortname = $shortname ;
2006-08-09 13:14:15 +00:00
$role -> description = $description ;
2006-09-20 21:00:45 +00:00
2006-09-23 10:43:24 +00:00
//find free sortorder number
$role -> sortorder = count_records ( 'role' );
while ( get_record ( 'role' , 'sortorder' , $role -> sortorder )) {
$role -> sortorder += 1 ;
2006-09-21 22:34:45 +00:00
}
2006-10-25 08:38:14 +00:00
if ( ! $context = get_context_instance ( CONTEXT_SYSTEM )) {
return false ;
}
2006-09-20 21:00:45 +00:00
2006-08-09 13:14:15 +00:00
if ( $id = insert_record ( 'role' , $role )) {
2006-09-20 21:00:45 +00:00
if ( $legacy ) {
assign_capability ( $legacy , CAP_ALLOW , $id , $context -> id );
2006-08-09 13:14:15 +00:00
}
2006-09-20 21:00:45 +00:00
2006-09-07 08:57:56 +00:00
/// By default, users with role:manage at site level
/// should be able to assign users to this new role, and override this new role's capabilities
2006-09-20 21:00:45 +00:00
2006-09-07 08:57:56 +00:00
// find all admin roles
2006-09-10 20:29:44 +00:00
if ( $adminroles = get_roles_with_capability ( 'moodle/role:manage' , CAP_ALLOW , $context )) {
// foreach admin role
foreach ( $adminroles as $arole ) {
// write allow_assign and allow_overrid
allow_assign ( $arole -> id , $id );
2006-09-20 21:00:45 +00:00
allow_override ( $arole -> id , $id );
2006-09-10 20:29:44 +00:00
}
2006-09-07 08:57:56 +00:00
}
2006-09-20 21:00:45 +00:00
2006-08-09 13:14:15 +00:00
return $id ;
} else {
2006-09-20 21:00:45 +00:00
return false ;
2006-08-09 13:14:15 +00:00
}
2006-09-20 21:00:45 +00:00
2006-08-08 05:13:06 +00:00
}
2006-09-23 10:43:24 +00:00
/**
* function that deletes a role and cleanups up after it
* @ param roleid - id of role to delete
* @ return success
*/
function delete_role ( $roleid ) {
$success = true ;
// first unssign all users
if ( ! role_unassign ( $roleid )) {
debugging ( " Error while unassigning all users from role with ID $roleid ! " );
$success = false ;
}
// cleanup all references to this role, ignore errors
if ( $success ) {
delete_records ( 'role_capabilities' , 'roleid' , $roleid );
delete_records ( 'role_allow_assign' , 'roleid' , $roleid );
delete_records ( 'role_allow_assign' , 'allowassign' , $roleid );
delete_records ( 'role_allow_override' , 'roleid' , $roleid );
delete_records ( 'role_allow_override' , 'allowoverride' , $roleid );
delete_records ( 'role_names' , 'roleid' , $roleid );
}
// finally delete the role itself
if ( $success and ! delete_records ( 'role' , 'id' , $roleid )) {
2006-09-23 12:51:00 +00:00
debugging ( " Could not delete role record with ID $roleid ! " );
2006-09-23 10:43:24 +00:00
$success = false ;
}
return $success ;
}
2006-08-08 05:13:06 +00:00
/**
* Function to write context specific overrides , or default capabilities .
* @ param module - string name
* @ param capability - string name
* @ param contextid - context id
* @ param roleid - role id
* @ param permission - int 1 , - 1 or - 1000
2006-10-11 02:18:09 +00:00
* should not be writing if permission is 0
2006-08-08 05:13:06 +00:00
*/
2006-09-12 06:15:33 +00:00
function assign_capability ( $capability , $permission , $roleid , $contextid , $overwrite = false ) {
2006-09-20 21:00:45 +00:00
2006-08-09 13:14:15 +00:00
global $USER ;
2006-09-20 21:00:45 +00:00
2006-10-11 02:18:09 +00:00
if ( empty ( $permission ) || $permission == CAP_INHERIT ) { // if permission is not set
2006-09-20 21:00:45 +00:00
unassign_capability ( $capability , $roleid , $contextid );
2006-10-11 02:18:09 +00:00
return true ;
2006-08-09 13:14:15 +00:00
}
2006-09-20 21:00:45 +00:00
2006-09-12 07:07:30 +00:00
$existing = get_record ( 'role_capabilities' , 'contextid' , $contextid , 'roleid' , $roleid , 'capability' , $capability );
2006-09-12 06:15:33 +00:00
if ( $existing and ! $overwrite ) { // We want to keep whatever is there already
return true ;
}
2006-08-08 05:13:06 +00:00
$cap = new object ;
$cap -> contextid = $contextid ;
$cap -> roleid = $roleid ;
$cap -> capability = $capability ;
$cap -> permission = $permission ;
$cap -> timemodified = time ();
2006-08-14 13:42:34 +00:00
$cap -> modifierid = empty ( $USER -> id ) ? 0 : $USER -> id ;
2006-09-12 06:15:33 +00:00
if ( $existing ) {
$cap -> id = $existing -> id ;
return update_record ( 'role_capabilities' , $cap );
} else {
return insert_record ( 'role_capabilities' , $cap );
}
2006-08-08 05:13:06 +00:00
}
/**
* Unassign a capability from a role .
* @ param $roleid - the role id
* @ param $capability - the name of the capability
* @ return boolean - success or failure
*/
function unassign_capability ( $capability , $roleid , $contextid = NULL ) {
2006-09-20 21:00:45 +00:00
2006-08-09 13:14:15 +00:00
if ( isset ( $contextid )) {
$status = delete_records ( 'role_capabilities' , 'capability' , $capability ,
'roleid' , $roleid , 'contextid' , $contextid );
} else {
$status = delete_records ( 'role_capabilities' , 'capability' , $capability ,
'roleid' , $roleid );
}
return $status ;
2006-08-08 05:13:06 +00:00
}
/**
2006-09-20 08:30:49 +00:00
* Get the roles that have a given capability assigned to it . This function
* does not resolve the actual permission of the capability . It just checks
* for assignment only .
2006-08-08 05:13:06 +00:00
* @ param $capability - capability name ( string )
* @ param $permission - optional , the permission defined for this capability
* either CAP_ALLOW , CAP_PREVENT or CAP_PROHIBIT
* @ return array or role objects
*/
2006-09-07 08:57:56 +00:00
function get_roles_with_capability ( $capability , $permission = NULL , $context = '' ) {
2006-08-08 05:13:06 +00:00
global $CFG ;
2006-09-20 21:00:45 +00:00
2006-09-07 08:57:56 +00:00
if ( $context ) {
if ( $contexts = get_parent_contexts ( $context )) {
$listofcontexts = '(' . implode ( ',' , $contexts ) . ')' ;
} else {
2006-10-25 08:38:14 +00:00
$sitecontext = get_context_instance ( CONTEXT_SYSTEM );
2006-09-20 21:00:45 +00:00
$listofcontexts = '(' . $sitecontext -> id . ')' ; // must be site
}
2006-09-07 20:17:46 +00:00
$contextstr = " AND (rc.contextid = ' $context->id ' OR rc.contextid IN $listofcontexts ) " ;
2006-09-07 08:57:56 +00:00
} else {
$contextstr = '' ;
}
2006-09-20 21:00:45 +00:00
$selectroles = " SELECT r.*
2006-09-07 20:17:46 +00:00
FROM { $CFG -> prefix } role r ,
{ $CFG -> prefix } role_capabilities rc
2006-08-08 05:13:06 +00:00
WHERE rc . capability = '$capability'
2006-09-07 08:57:56 +00:00
AND rc . roleid = r . id $contextstr " ;
2006-08-08 05:13:06 +00:00
if ( isset ( $permission )) {
$selectroles .= " AND rc.permission = ' $permission ' " ;
}
return get_records_sql ( $selectroles );
}
/**
2006-08-31 07:40:48 +00:00
* This function makes a role - assignment ( a role for a user or group in a particular context )
2006-08-08 05:13:06 +00:00
* @ param $roleid - the role of the id
* @ param $userid - userid
* @ param $groupid - group id
* @ param $contextid - id of the context
* @ param $timestart - time this assignment becomes effective
* @ param $timeend - time this assignemnt ceases to be effective
* @ uses $USER
* @ return id - new id of the assigment
*/
2006-08-31 07:58:53 +00:00
function role_assign ( $roleid , $userid , $groupid , $contextid , $timestart = 0 , $timeend = 0 , $hidden = 0 , $enrol = 'manual' ) {
2006-08-09 05:37:31 +00:00
global $USER , $CFG ;
2006-08-08 05:13:06 +00:00
2006-09-23 09:38:39 +00:00
debugging ( " Assign roleid $roleid userid $userid contextid $contextid " , DEBUG_DEVELOPER );
2006-08-08 05:13:06 +00:00
2006-08-31 07:40:48 +00:00
/// Do some data validation
2006-08-08 05:13:06 +00:00
if ( empty ( $roleid )) {
2006-09-22 05:17:57 +00:00
debugging ( 'Role ID not provided' );
2006-08-31 07:40:48 +00:00
return false ;
2006-08-08 05:13:06 +00:00
}
if ( empty ( $userid ) && empty ( $groupid )) {
2006-09-22 05:17:57 +00:00
debugging ( 'Either userid or groupid must be provided' );
2006-08-31 07:40:48 +00:00
return false ;
2006-08-08 05:13:06 +00:00
}
2006-09-20 21:00:45 +00:00
2006-09-03 07:56:40 +00:00
if ( $userid && ! record_exists ( 'user' , 'id' , $userid )) {
2006-09-22 05:23:59 +00:00
debugging ( 'User ID ' . intval ( $userid ) . ' does not exist!' );
2006-09-03 07:56:40 +00:00
return false ;
}
2006-08-08 05:13:06 +00:00
2007-01-04 13:15:04 +13:00
if ( $groupid && ! groups_group_exists ( $groupid )) {
2006-09-22 05:23:59 +00:00
debugging ( 'Group ID ' . intval ( $groupid ) . ' does not exist!' );
2006-09-03 08:45:41 +00:00
return false ;
}
2006-09-03 07:56:40 +00:00
if ( ! $context = get_context_instance_by_id ( $contextid )) {
2006-09-22 05:23:59 +00:00
debugging ( 'Context ID ' . intval ( $contextid ) . ' does not exist!' );
2006-08-31 07:40:48 +00:00
return false ;
2006-08-08 05:13:06 +00:00
}
2006-08-31 07:40:48 +00:00
if (( $timestart and $timeend ) and ( $timestart > $timeend )) {
2006-09-22 05:17:57 +00:00
debugging ( 'The end time can not be earlier than the start time' );
2006-08-31 07:40:48 +00:00
return false ;
}
2006-09-03 07:56:40 +00:00
2006-08-31 07:40:48 +00:00
/// Check for existing entry
if ( $userid ) {
2006-09-03 07:56:40 +00:00
$ra = get_record ( 'role_assignments' , 'roleid' , $roleid , 'contextid' , $context -> id , 'userid' , $userid );
2006-08-31 07:40:48 +00:00
} else {
2006-09-03 07:56:40 +00:00
$ra = get_record ( 'role_assignments' , 'roleid' , $roleid , 'contextid' , $context -> id , 'groupid' , $groupid );
2006-08-31 07:40:48 +00:00
}
2006-09-01 06:30:01 +00:00
2006-08-31 07:40:48 +00:00
$newra = new object ;
2006-08-08 05:13:06 +00:00
2006-08-31 07:40:48 +00:00
if ( empty ( $ra )) { // Create a new entry
$newra -> roleid = $roleid ;
2006-09-03 07:56:40 +00:00
$newra -> contextid = $context -> id ;
2006-08-31 07:40:48 +00:00
$newra -> userid = $userid ;
$newra -> hidden = $hidden ;
2006-08-31 07:58:53 +00:00
$newra -> enrol = $enrol ;
2007-03-07 04:56:07 +00:00
/// Always round timestart downto 100 secs to help DBs to use their own caching algorithms
/// by repeating queries with the same exact parameters in a 100 secs time window
$newra -> timestart = round ( $timestart , - 2 );
2006-08-31 07:40:48 +00:00
$newra -> timeend = $timeend ;
$newra -> timemodified = time ();
2006-11-20 17:47:30 +00:00
$newra -> modifierid = empty ( $USER -> id ) ? 0 : $USER -> id ;
2006-08-31 07:40:48 +00:00
2006-09-01 06:30:01 +00:00
$success = insert_record ( 'role_assignments' , $newra );
2006-08-31 07:40:48 +00:00
} else { // We already have one, just update it
$newra -> id = $ra -> id ;
$newra -> hidden = $hidden ;
2006-08-31 07:58:53 +00:00
$newra -> enrol = $enrol ;
2007-03-07 04:56:07 +00:00
/// Always round timestart downto 100 secs to help DBs to use their own caching algorithms
/// by repeating queries with the same exact parameters in a 100 secs time window
$newra -> timestart = round ( $timestart , - 2 );
2006-08-31 07:40:48 +00:00
$newra -> timeend = $timeend ;
$newra -> timemodified = time ();
2006-11-20 17:47:30 +00:00
$newra -> modifierid = empty ( $USER -> id ) ? 0 : $USER -> id ;
2006-08-31 07:40:48 +00:00
2006-09-01 06:30:01 +00:00
$success = update_record ( 'role_assignments' , $newra );
}
2006-09-03 07:56:40 +00:00
if ( $success ) { /// Role was assigned, so do some other things
/// If the user is the current user, then reload the capabilities too.
if ( ! empty ( $USER -> id ) && $USER -> id == $userid ) {
2006-10-23 15:17:31 +00:00
load_all_capabilities ();
2006-09-03 07:56:40 +00:00
}
2006-10-04 02:43:29 +00:00
2006-09-13 08:07:14 +00:00
/// Ask all the modules if anything needs to be done for this user
if ( $mods = get_list_of_plugins ( 'mod' )) {
foreach ( $mods as $mod ) {
include_once ( $CFG -> dirroot . '/mod/' . $mod . '/lib.php' );
$functionname = $mod . '_role_assign' ;
if ( function_exists ( $functionname )) {
2007-03-21 06:07:46 +00:00
$functionname ( $userid , $context , $roleid );
2006-09-13 08:07:14 +00:00
}
}
}
/// Make sure they have an entry in user_lastaccess for courses they can access
// role_add_lastaccess_entries($userid, $context);
2006-08-31 07:40:48 +00:00
}
2006-09-20 21:00:45 +00:00
2006-09-17 08:42:42 +00:00
/// now handle metacourse role assignments if in course context
2006-09-22 06:19:32 +00:00
if ( $success and $context -> contextlevel == CONTEXT_COURSE ) {
2006-09-17 08:42:42 +00:00
if ( $parents = get_records ( 'course_meta' , 'child_course' , $context -> instanceid )) {
foreach ( $parents as $parent ) {
2006-09-17 22:21:37 +00:00
sync_metacourse ( $parent -> parent_course );
2006-09-17 08:42:42 +00:00
}
}
}
2006-09-03 07:29:06 +00:00
return $success ;
2006-08-08 05:13:06 +00:00
}
/**
2006-09-01 06:10:45 +00:00
* Deletes one or more role assignments . You must specify at least one parameter .
2006-08-08 05:13:06 +00:00
* @ param $roleid
* @ param $userid
* @ param $groupid
* @ param $contextid
2007-03-22 12:27:52 +00:00
* @ param $enrol unassign only if enrolment type matches , NULL means anything
2006-08-08 05:13:06 +00:00
* @ return boolean - success or failure
*/
2007-03-22 12:27:52 +00:00
function role_unassign ( $roleid = 0 , $userid = 0 , $groupid = 0 , $contextid = 0 , $enrol = NULL ) {
2006-09-13 06:35:25 +00:00
global $USER , $CFG ;
2006-09-20 21:00:45 +00:00
2006-09-17 08:42:42 +00:00
$success = true ;
2006-09-13 06:35:25 +00:00
2006-09-01 06:10:45 +00:00
$args = array ( 'roleid' , 'userid' , 'groupid' , 'contextid' );
$select = array ();
foreach ( $args as $arg ) {
if ( $$arg ) {
$select [] = $arg . ' = ' . $$arg ;
}
}
2007-03-22 12:27:52 +00:00
if ( ! empty ( $enrol )) {
$select [] = " enrol=' $enrol ' " ;
}
2006-09-13 06:35:25 +00:00
2006-09-01 06:10:45 +00:00
if ( $select ) {
2006-09-17 08:42:42 +00:00
if ( $ras = get_records_select ( 'role_assignments' , implode ( ' AND ' , $select ))) {
$mods = get_list_of_plugins ( 'mod' );
foreach ( $ras as $ra ) {
2006-09-17 08:53:57 +00:00
/// infinite loop protection when deleting recursively
if ( ! $ra = get_record ( 'role_assignments' , 'id' , $ra -> id )) {
continue ;
}
2006-09-17 08:42:42 +00:00
$success = delete_records ( 'role_assignments' , 'id' , $ra -> id ) and $success ;
2006-09-17 08:53:57 +00:00
2006-09-17 08:42:42 +00:00
/// If the user is the current user, then reload the capabilities too.
if ( ! empty ( $USER -> id ) && $USER -> id == $ra -> userid ) {
2006-10-23 15:17:31 +00:00
load_all_capabilities ();
2006-09-17 08:42:42 +00:00
}
$context = get_record ( 'context' , 'id' , $ra -> contextid );
2006-09-13 08:07:14 +00:00
/// Ask all the modules if anything needs to be done for this user
2006-09-17 08:42:42 +00:00
foreach ( $mods as $mod ) {
include_once ( $CFG -> dirroot . '/mod/' . $mod . '/lib.php' );
$functionname = $mod . '_role_unassign' ;
if ( function_exists ( $functionname )) {
$functionname ( $ra -> userid , $context ); // watch out, $context might be NULL if something goes wrong
}
}
/// now handle metacourse role unassigment and removing from goups if in course context
2006-09-22 06:19:32 +00:00
if ( ! empty ( $context ) and $context -> contextlevel == CONTEXT_COURSE ) {
2006-09-17 08:42:42 +00:00
//remove from groups when user has no role
$roles = get_user_roles ( $context , $ra -> userid , true );
if ( empty ( $roles )) {
if ( $groups = get_groups ( $context -> instanceid , $ra -> userid )) {
foreach ( $groups as $group ) {
delete_records ( 'groups_members' , 'groupid' , $group -> id , 'userid' , $ra -> userid );
}
}
}
2006-09-17 22:21:37 +00:00
//unassign roles in metacourses if needed
2006-09-17 08:42:42 +00:00
if ( $parents = get_records ( 'course_meta' , 'child_course' , $context -> instanceid )) {
foreach ( $parents as $parent ) {
2006-09-17 22:21:37 +00:00
sync_metacourse ( $parent -> parent_course );
2006-09-13 08:07:14 +00:00
}
}
}
}
2006-09-13 06:35:25 +00:00
}
2006-09-01 06:10:45 +00:00
}
2006-09-17 08:42:42 +00:00
return $success ;
2006-08-08 05:13:06 +00:00
}
2007-03-05 11:27:01 +00:00
/**
2006-09-20 21:00:45 +00:00
* A convenience function to take care of the common case where you
2006-09-17 16:06:25 +00:00
* just want to enrol someone using the default role into a course
*
* @ param object $course
* @ param object $user
* @ param string $enrol - the plugin used to do this enrolment
*/
function enrol_into_course ( $course , $user , $enrol ) {
if ( $course -> enrolperiod ) {
$timestart = time ();
$timeend = time () + $course -> enrolperiod ;
} else {
$timestart = $timeend = 0 ;
}
if ( $role = get_default_course_role ( $course )) {
2006-09-20 02:19:08 +00:00
$context = get_context_instance ( CONTEXT_COURSE , $course -> id );
2006-09-22 13:16:32 +00:00
if ( ! role_assign ( $role -> id , $user -> id , 0 , $context -> id , $timestart , $timeend , 0 , $enrol )) {
2006-09-17 16:06:25 +00:00
return false ;
}
2006-09-20 21:00:45 +00:00
2006-09-17 16:06:25 +00:00
email_welcome_message_to_user ( $course , $user );
2006-09-20 21:00:45 +00:00
2006-09-17 16:06:25 +00:00
add_to_log ( $course -> id , 'course' , 'enrol' , 'view.php?id=' . $course -> id , $user -> id );
return true ;
}
return false ;
}
2006-09-13 08:07:14 +00:00
/**
* Add last access times to user_lastaccess as required
* @ param $userid
* @ param $context
* @ return boolean - success or failure
*/
function role_add_lastaccess_entries ( $userid , $context ) {
global $USER , $CFG ;
2006-09-22 06:19:32 +00:00
if ( empty ( $context -> contextlevel )) {
2006-09-13 08:07:14 +00:00
return false ;
}
$lastaccess = new object ; // Reusable object below
$lastaccess -> userid = $userid ;
$lastaccess -> timeaccess = 0 ;
2006-09-22 06:19:32 +00:00
switch ( $context -> contextlevel ) {
2006-09-13 08:07:14 +00:00
case CONTEXT_SYSTEM : // For the whole site
if ( $courses = get_record ( 'course' )) {
foreach ( $courses as $course ) {
$lastaccess -> courseid = $course -> id ;
role_set_lastaccess ( $lastaccess );
}
}
break ;
case CONTEXT_CATEGORY : // For a whole category
if ( $courses = get_record ( 'course' , 'category' , $context -> instanceid )) {
foreach ( $courses as $course ) {
$lastaccess -> courseid = $course -> id ;
role_set_lastaccess ( $lastaccess );
}
}
if ( $categories = get_record ( 'course_categories' , 'parent' , $context -> instanceid )) {
foreach ( $categories as $category ) {
$subcontext = get_context_instance ( CONTEXT_CATEGORY , $category -> id );
role_add_lastaccess_entries ( $userid , $subcontext );
}
}
break ;
2006-09-20 21:00:45 +00:00
2006-09-13 08:07:14 +00:00
case CONTEXT_COURSE : // For a whole course
if ( $course = get_record ( 'course' , 'id' , $context -> instanceid )) {
$lastaccess -> courseid = $course -> id ;
role_set_lastaccess ( $lastaccess );
}
break ;
}
}
/**
* Delete last access times from user_lastaccess as required
* @ param $userid
* @ param $context
* @ return boolean - success or failure
*/
function role_remove_lastaccess_entries ( $userid , $context ) {
global $USER , $CFG ;
}
2006-08-08 05:13:06 +00:00
/**
* Loads the capability definitions for the component ( from file ) . If no
* capabilities are defined for the component , we simply return an empty array .
* @ param $component - examples : 'moodle' , 'mod/forum' , 'block/quiz_results'
* @ return array of capabilities
*/
function load_capability_def ( $component ) {
global $CFG ;
if ( $component == 'moodle' ) {
$defpath = $CFG -> libdir . '/db/access.php' ;
$varprefix = 'moodle' ;
} else {
2006-09-13 03:56:38 +00:00
$compparts = explode ( '/' , $component );
2006-09-20 21:00:45 +00:00
2006-09-13 03:56:38 +00:00
if ( $compparts [ 0 ] == 'block' ) {
// Blocks are an exception. Blocks directory is 'blocks', and not
// 'block'. So we need to jump through hoops.
$defpath = $CFG -> dirroot . '/' . $compparts [ 0 ] .
's/' . $compparts [ 1 ] . '/db/access.php' ;
$varprefix = $compparts [ 0 ] . '_' . $compparts [ 1 ];
2006-12-11 15:47:23 +00:00
} else if ( $compparts [ 0 ] == 'format' ) {
// Similar to the above, course formats are 'format' while they
// are stored in 'course/format'.
$defpath = $CFG -> dirroot . '/course/' . $component . '/db/access.php' ;
$varprefix = $compparts [ 0 ] . '_' . $compparts [ 1 ];
2006-09-13 03:56:38 +00:00
} else {
$defpath = $CFG -> dirroot . '/' . $component . '/db/access.php' ;
$varprefix = str_replace ( '/' , '_' , $component );
}
2006-08-08 05:13:06 +00:00
}
$capabilities = array ();
2006-09-20 21:00:45 +00:00
2006-08-08 05:13:06 +00:00
if ( file_exists ( $defpath )) {
2006-12-12 17:23:31 +00:00
require ( $defpath );
2006-08-08 05:13:06 +00:00
$capabilities = $ { $varprefix . '_capabilities' };
}
return $capabilities ;
}
/**
* Gets the capabilities that have been cached in the database for this
* component .
* @ param $component - examples : 'moodle' , 'mod/forum' , 'block/quiz_results'
* @ return array of capabilities
*/
function get_cached_capabilities ( $component = 'moodle' ) {
if ( $component == 'moodle' ) {
$storedcaps = get_records_select ( 'capabilities' ,
" name LIKE 'moodle/%:%' " );
} else {
$storedcaps = get_records_select ( 'capabilities' ,
" name LIKE ' $component :%' " );
}
return $storedcaps ;
}
2007-03-03 21:07:07 +00:00
/**
* Returns default capabilities for given legacy role type .
*
* @ param string legacy role name
* @ return array
*/
function get_default_capabilities ( $legacyrole ) {
if ( ! $allcaps = get_records ( 'capabilities' )) {
error ( 'Error: no capabilitites defined!' );
}
$alldefs = array ();
$defaults = array ();
$components = array ();
foreach ( $allcaps as $cap ) {
2007-03-05 11:27:01 +00:00
if ( ! in_array ( $cap -> component , $components )) {
2007-03-03 21:07:07 +00:00
$components [] = $cap -> component ;
$alldefs = array_merge ( $alldefs , load_capability_def ( $cap -> component ));
}
}
foreach ( $alldefs as $name => $def ) {
if ( isset ( $def [ 'legacy' ][ $legacyrole ])) {
$defaults [ $name ] = $def [ 'legacy' ][ $legacyrole ];
}
}
//some exceptions
$defaults [ 'moodle/legacy:' . $legacyrole ] = CAP_ALLOW ;
if ( $legacyrole == 'admin' ) {
$defaults [ 'moodle/site:doanything' ] = CAP_ALLOW ;
}
return $defaults ;
}
2006-08-08 05:13:06 +00:00
2007-03-05 11:27:01 +00:00
/**
* Reset role capabilitites to default according to selected legacy capability .
* If several legacy caps selected , use the first from get_default_capabilities .
* If no legacy selected , removes all capabilities .
*
* @ param int @ roleid
*/
function reset_role_capabilities ( $roleid ) {
$sitecontext = get_context_instance ( CONTEXT_SYSTEM );
$legacyroles = get_legacy_roles ();
$defaultcaps = array ();
foreach ( $legacyroles as $ltype => $lcap ) {
$localoverride = get_local_override ( $roleid , $sitecontext -> id , $lcap );
if ( ! empty ( $localoverride -> permission ) and $localoverride -> permission == CAP_ALLOW ) {
//choose first selected legacy capability
$defaultcaps = get_default_capabilities ( $ltype );
break ;
}
}
delete_records ( 'role_capabilities' , 'roleid' , $roleid );
if ( ! empty ( $defaultcaps )) {
foreach ( $defaultcaps as $cap => $permission ) {
assign_capability ( $cap , $permission , $roleid , $sitecontext -> id );
}
}
}
2006-08-08 05:13:06 +00:00
/**
* Updates the capabilities table with the component capability definitions .
* If no parameters are given , the function updates the core moodle
* capabilities .
*
* Note that the absence of the db / access . php capabilities definition file
* will cause any stored capabilities for the component to be removed from
2006-09-20 21:00:45 +00:00
* the database .
2006-08-08 05:13:06 +00:00
*
* @ param $component - examples : 'moodle' , 'mod/forum' , 'block/quiz_results'
* @ return boolean
*/
function update_capabilities ( $component = 'moodle' ) {
2006-09-20 21:00:45 +00:00
2006-08-08 05:13:06 +00:00
$storedcaps = array ();
2006-08-31 08:36:36 +00:00
$filecaps = load_capability_def ( $component );
2006-08-08 05:13:06 +00:00
$cachedcaps = get_cached_capabilities ( $component );
if ( $cachedcaps ) {
foreach ( $cachedcaps as $cachedcap ) {
array_push ( $storedcaps , $cachedcap -> name );
2007-03-14 21:42:38 +00:00
// update risk bitmasks and context levels in existing capabilities if needed
2006-08-31 08:36:36 +00:00
if ( array_key_exists ( $cachedcap -> name , $filecaps )) {
if ( ! array_key_exists ( 'riskbitmask' , $filecaps [ $cachedcap -> name ])) {
2006-08-31 16:01:41 +00:00
$filecaps [ $cachedcap -> name ][ 'riskbitmask' ] = 0 ; // no risk if not specified
2006-08-31 08:36:36 +00:00
}
if ( $cachedcap -> riskbitmask != $filecaps [ $cachedcap -> name ][ 'riskbitmask' ]) {
2007-03-14 21:42:38 +00:00
$updatecap = new object ();
2006-08-31 08:36:36 +00:00
$updatecap -> id = $cachedcap -> id ;
$updatecap -> riskbitmask = $filecaps [ $cachedcap -> name ][ 'riskbitmask' ];
if ( ! update_record ( 'capabilities' , $updatecap )) {
2007-03-14 21:42:38 +00:00
return false ;
}
}
if ( ! array_key_exists ( 'contextlevel' , $filecaps [ $cachedcap -> name ])) {
$filecaps [ $cachedcap -> name ][ 'contextlevel' ] = 0 ; // no context level defined
}
if ( $cachedcap -> contextlevel != $filecaps [ $cachedcap -> name ][ 'contextlevel' ]) {
$updatecap = new object ();
$updatecap -> id = $cachedcap -> id ;
$updatecap -> contextlevel = $filecaps [ $cachedcap -> name ][ 'contextlevel' ];
if ( ! update_record ( 'capabilities' , $updatecap )) {
2006-08-31 08:36:36 +00:00
return false ;
}
}
}
2006-08-08 05:13:06 +00:00
}
}
2006-08-31 08:36:36 +00:00
2006-08-08 05:13:06 +00:00
// Are there new capabilities in the file definition?
$newcaps = array ();
2006-09-20 21:00:45 +00:00
2006-08-08 05:13:06 +00:00
foreach ( $filecaps as $filecap => $def ) {
2006-09-20 21:00:45 +00:00
if ( ! $storedcaps ||
2006-08-08 05:13:06 +00:00
( $storedcaps && in_array ( $filecap , $storedcaps ) === false )) {
2006-08-31 16:01:41 +00:00
if ( ! array_key_exists ( 'riskbitmask' , $def )) {
$def [ 'riskbitmask' ] = 0 ; // no risk if not specified
}
2006-08-08 05:13:06 +00:00
$newcaps [ $filecap ] = $def ;
}
}
// Add new capabilities to the stored definition.
foreach ( $newcaps as $capname => $capdef ) {
$capability = new object ;
$capability -> name = $capname ;
$capability -> captype = $capdef [ 'captype' ];
$capability -> contextlevel = $capdef [ 'contextlevel' ];
$capability -> component = $component ;
2006-08-31 08:36:36 +00:00
$capability -> riskbitmask = $capdef [ 'riskbitmask' ];
2006-09-20 21:00:45 +00:00
2006-08-08 05:13:06 +00:00
if ( ! insert_record ( 'capabilities' , $capability , false , 'id' )) {
return false ;
}
2006-09-20 21:00:45 +00:00
2006-08-08 05:13:06 +00:00
// Do we need to assign the new capabilities to roles that have the
// legacy capabilities moodle/legacy:* as well?
if ( isset ( $capdef [ 'legacy' ]) && is_array ( $capdef [ 'legacy' ]) &&
! assign_legacy_capabilities ( $capname , $capdef [ 'legacy' ])) {
2006-09-12 07:07:30 +00:00
notify ( 'Could not assign legacy capabilities for ' . $capname );
2006-08-08 05:13:06 +00:00
}
}
// Are there any capabilities that have been removed from the file
// definition that we need to delete from the stored capabilities and
// role assignments?
capabilities_cleanup ( $component , $filecaps );
2006-09-20 21:00:45 +00:00
2006-08-08 05:13:06 +00:00
return true ;
}
/**
* Deletes cached capabilities that are no longer needed by the component .
* Also unassigns these capabilities from any roles that have them .
* @ param $component - examples : 'moodle' , 'mod/forum' , 'block/quiz_results'
* @ param $newcapdef - array of the new capability definitions that will be
* compared with the cached capabilities
* @ return int - number of deprecated capabilities that have been removed
*/
function capabilities_cleanup ( $component , $newcapdef = NULL ) {
2006-09-20 21:00:45 +00:00
2006-08-08 05:13:06 +00:00
$removedcount = 0 ;
2006-09-20 21:00:45 +00:00
2006-08-08 05:13:06 +00:00
if ( $cachedcaps = get_cached_capabilities ( $component )) {
foreach ( $cachedcaps as $cachedcap ) {
if ( empty ( $newcapdef ) ||
array_key_exists ( $cachedcap -> name , $newcapdef ) === false ) {
2006-09-20 21:00:45 +00:00
2006-08-08 05:13:06 +00:00
// Remove from capabilities cache.
if ( ! delete_records ( 'capabilities' , 'name' , $cachedcap -> name )) {
error ( 'Could not delete deprecated capability ' . $cachedcap -> name );
} else {
$removedcount ++ ;
}
// Delete from roles.
if ( $roles = get_roles_with_capability ( $cachedcap -> name )) {
foreach ( $roles as $role ) {
2006-09-08 02:33:02 +00:00
if ( ! unassign_capability ( $cachedcap -> name , $role -> id )) {
2006-08-08 05:13:06 +00:00
error ( 'Could not unassign deprecated capability ' .
$cachedcap -> name . ' from role ' . $role -> name );
}
}
}
} // End if.
}
}
return $removedcount ;
}
2006-08-14 07:15:03 +00:00
/****************
* UI FUNCTIONS *
****************/
2006-08-08 05:13:06 +00:00
/**
* prints human readable context identifier .
*/
2006-08-14 05:55:40 +00:00
function print_context_name ( $context ) {
2006-08-13 15:48:57 +00:00
2006-08-09 04:51:05 +00:00
$name = '' ;
2006-09-22 06:19:32 +00:00
switch ( $context -> contextlevel ) {
2006-08-09 04:51:05 +00:00
2006-08-08 05:13:06 +00:00
case CONTEXT_SYSTEM : // by now it's a definite an inherit
2007-03-19 04:49:49 +00:00
$name = get_string ( 'coresystem' );
2006-08-13 15:48:57 +00:00
break ;
2006-08-08 05:13:06 +00:00
case CONTEXT_PERSONAL :
2006-08-09 04:51:05 +00:00
$name = get_string ( 'personal' );
2006-08-13 15:48:57 +00:00
break ;
2006-09-15 14:09:16 +00:00
case CONTEXT_USER :
2006-08-09 04:51:05 +00:00
if ( $user = get_record ( 'user' , 'id' , $context -> instanceid )) {
$name = get_string ( 'user' ) . ': ' . fullname ( $user );
}
2006-08-13 15:48:57 +00:00
break ;
2006-08-08 05:13:06 +00:00
case CONTEXT_COURSECAT : // Coursecat -> coursecat or site
2006-08-09 04:51:05 +00:00
if ( $category = get_record ( 'course_categories' , 'id' , $context -> instanceid )) {
2007-02-28 06:25:22 +00:00
$name = get_string ( 'category' ) . ': ' . format_string ( $category -> name );
2006-08-09 04:51:05 +00:00
}
2006-08-13 15:48:57 +00:00
break ;
2006-08-08 05:13:06 +00:00
case CONTEXT_COURSE : // 1 to 1 to course cat
2006-08-09 04:51:05 +00:00
if ( $course = get_record ( 'course' , 'id' , $context -> instanceid )) {
2007-03-19 04:49:49 +00:00
if ( $context -> instanceid == SITEID ) {
$name = get_string ( 'site' ) . ': ' . format_string ( $course -> fullname );
} else {
$name = get_string ( 'course' ) . ': ' . format_string ( $course -> fullname );
}
2006-08-09 04:51:05 +00:00
}
2006-08-13 15:48:57 +00:00
break ;
2006-08-08 05:13:06 +00:00
case CONTEXT_GROUP : // 1 to 1 to course
2007-01-04 13:15:04 +13:00
if ( $name = groups_get_group_name ( $context -> instanceid )) {
$name = get_string ( 'group' ) . ': ' . $name ;
2006-08-09 04:51:05 +00:00
}
2006-08-13 15:48:57 +00:00
break ;
2006-08-08 05:13:06 +00:00
case CONTEXT_MODULE : // 1 to 1 to course
2006-08-09 13:14:15 +00:00
if ( $cm = get_record ( 'course_modules' , 'id' , $context -> instanceid )) {
if ( $module = get_record ( 'modules' , 'id' , $cm -> module )) {
if ( $mod = get_record ( $module -> name , 'id' , $cm -> instance )) {
2006-08-09 04:51:05 +00:00
$name = get_string ( 'activitymodule' ) . ': ' . $mod -> name ;
2006-08-09 13:14:15 +00:00
}
2006-08-09 04:51:05 +00:00
}
}
2006-08-13 15:48:57 +00:00
break ;
2006-08-08 05:13:06 +00:00
case CONTEXT_BLOCK : // 1 to 1 to course
2006-08-09 13:14:15 +00:00
if ( $blockinstance = get_record ( 'block_instance' , 'id' , $context -> instanceid )) {
if ( $block = get_record ( 'block' , 'id' , $blockinstance -> blockid )) {
2006-09-05 06:30:12 +00:00
global $CFG ;
require_once ( " $CFG->dirroot /blocks/moodleblock.class.php " );
require_once ( " $CFG->dirroot /blocks/ $block->name /block_ $block->name .php " );
$blockname = " block_ $block->name " ;
if ( $blockobject = new $blockname ()) {
$name = $blockobject -> title . ' (' . get_string ( 'block' ) . ')' ;
}
2006-08-09 04:51:05 +00:00
}
}
2006-08-13 15:48:57 +00:00
break ;
2006-08-08 05:13:06 +00:00
default :
2007-03-01 16:42:36 +00:00
error ( 'This is an unknown context (' . $context -> contextlevel . ') in print_context_name!' );
2006-08-13 15:48:57 +00:00
return false ;
}
return $name ;
2006-08-08 05:13:06 +00:00
}
/**
2006-09-20 21:00:45 +00:00
* Extracts the relevant capabilities given a contextid .
2006-08-08 05:13:06 +00:00
* All case based , example an instance of forum context .
* Will fetch all forum related capabilities , while course contexts
* Will fetch all capabilities
2006-08-14 05:55:40 +00:00
* @ param object context
2006-08-08 05:13:06 +00:00
* @ return array ();
*
* capabilities
* `name` varchar ( 150 ) NOT NULL ,
* `captype` varchar ( 50 ) NOT NULL ,
* `contextlevel` int ( 10 ) NOT NULL ,
* `component` varchar ( 100 ) NOT NULL ,
*/
2006-08-14 05:55:40 +00:00
function fetch_context_capabilities ( $context ) {
2006-09-20 21:00:45 +00:00
2006-08-09 13:14:15 +00:00
global $CFG ;
2006-08-08 05:13:06 +00:00
$sort = 'ORDER BY contextlevel,component,id' ; // To group them sensibly for display
2006-09-20 21:00:45 +00:00
2006-09-22 06:19:32 +00:00
switch ( $context -> contextlevel ) {
2006-08-08 05:13:06 +00:00
2006-08-09 13:14:15 +00:00
case CONTEXT_SYSTEM : // all
$SQL = " select * from { $CFG -> prefix } capabilities " ;
2006-08-08 05:13:06 +00:00
break ;
case CONTEXT_PERSONAL :
2006-08-15 08:29:29 +00:00
$SQL = " select * from { $CFG -> prefix } capabilities where contextlevel = " . CONTEXT_PERSONAL ;
2006-08-08 05:13:06 +00:00
break ;
2006-09-20 21:00:45 +00:00
2006-09-15 14:09:16 +00:00
case CONTEXT_USER :
2006-10-02 08:49:07 +00:00
$SQL = " SELECT *
FROM { $CFG -> prefix } capabilities
WHERE contextlevel = " .CONTEXT_USER;
2006-08-08 05:13:06 +00:00
break ;
2006-09-20 21:00:45 +00:00
2006-08-08 05:13:06 +00:00
case CONTEXT_COURSECAT : // all
2006-08-09 13:14:15 +00:00
$SQL = " select * from { $CFG -> prefix } capabilities " ;
2006-08-08 05:13:06 +00:00
break ;
case CONTEXT_COURSE : // all
2006-08-09 13:14:15 +00:00
$SQL = " select * from { $CFG -> prefix } capabilities " ;
2006-08-08 05:13:06 +00:00
break ;
case CONTEXT_GROUP : // group caps
break ;
case CONTEXT_MODULE : // mod caps
2006-08-09 13:14:15 +00:00
$cm = get_record ( 'course_modules' , 'id' , $context -> instanceid );
$module = get_record ( 'modules' , 'id' , $cm -> module );
2006-09-20 21:00:45 +00:00
2006-08-09 13:14:15 +00:00
$SQL = " select * from { $CFG -> prefix } capabilities where contextlevel = " . CONTEXT_MODULE . "
and component = 'mod/$module->name' " ;
2006-08-08 05:13:06 +00:00
break ;
case CONTEXT_BLOCK : // block caps
2006-08-09 13:14:15 +00:00
$cb = get_record ( 'block_instance' , 'id' , $context -> instanceid );
$block = get_record ( 'block' , 'id' , $cb -> blockid );
2006-09-20 21:00:45 +00:00
2006-08-09 13:14:15 +00:00
$SQL = " select * from { $CFG -> prefix } capabilities where contextlevel = " . CONTEXT_BLOCK . "
and component = 'block/$block->name' " ;
2006-08-08 05:13:06 +00:00
break ;
default :
return false ;
}
2006-09-22 21:31:19 +00:00
if ( ! $records = get_records_sql ( $SQL . ' ' . $sort )) {
$records = array ();
}
2006-09-30 20:11:44 +00:00
/// the rest of code is a bit hacky, think twice before modifying it :-(
2006-09-12 19:54:33 +00:00
// special sorting of core system capabiltites and enrollments
2006-10-02 08:57:00 +00:00
if ( in_array ( $context -> contextlevel , array ( CONTEXT_SYSTEM , CONTEXT_COURSECAT , CONTEXT_COURSE ))) {
2006-09-12 19:54:33 +00:00
$first = array ();
foreach ( $records as $key => $record ) {
if ( preg_match ( '|^moodle/|' , $record -> name ) and $record -> contextlevel == CONTEXT_SYSTEM ) {
$first [ $key ] = $record ;
unset ( $records [ $key ]);
} else if ( count ( $first )){
break ;
}
}
if ( count ( $first )) {
$records = $first + $records ; // merge the two arrays keeping the keys
}
2006-09-30 20:11:44 +00:00
} else {
$contextindependentcaps = fetch_context_independent_capabilities ();
$records = array_merge ( $contextindependentcaps , $records );
2006-09-12 19:54:33 +00:00
}
2006-09-30 20:11:44 +00:00
2006-08-08 05:13:06 +00:00
return $records ;
2006-09-20 21:00:45 +00:00
2006-08-08 05:13:06 +00:00
}
2006-09-20 08:30:49 +00:00
/**
* Gets the context - independent capabilities that should be overrridable in
* any context .
* @ return array of capability records from the capabilities table .
*/
function fetch_context_independent_capabilities () {
2006-09-20 21:00:45 +00:00
2006-10-08 11:00:49 +00:00
//only CONTEXT_SYSTEM capabilities here or it will break the hack in fetch_context_capabilities()
2006-09-20 08:30:49 +00:00
$contextindependentcaps = array (
'moodle/site:accessallgroups'
);
$records = array ();
2006-09-20 21:00:45 +00:00
2006-09-20 08:30:49 +00:00
foreach ( $contextindependentcaps as $capname ) {
$record = get_record ( 'capabilities' , 'name' , $capname );
array_push ( $records , $record );
}
return $records ;
}
2006-08-08 05:13:06 +00:00
/**
* This function pulls out all the resolved capabilities ( overrides and
2006-09-20 08:30:49 +00:00
* defaults ) of a role used in capability overrides in contexts at a given
2006-08-08 05:13:06 +00:00
* context .
2006-08-15 08:29:29 +00:00
* @ param obj $context
2006-08-08 05:13:06 +00:00
* @ param int $roleid
2006-09-20 09:00:04 +00:00
* @ param bool self - if set to true , resolve till this level , else stop at immediate parent level
2006-08-08 05:13:06 +00:00
* @ return array
*/
2006-08-28 08:42:30 +00:00
function role_context_capabilities ( $roleid , $context , $cap = '' ) {
2006-09-20 09:00:04 +00:00
global $CFG ;
2006-09-20 21:00:45 +00:00
2006-09-20 06:24:55 +00:00
$contexts = get_parent_contexts ( $context );
$contexts [] = $context -> id ;
2006-08-09 13:14:15 +00:00
$contexts = '(' . implode ( ',' , $contexts ) . ')' ;
2006-09-20 21:00:45 +00:00
2006-08-28 08:42:30 +00:00
if ( $cap ) {
2006-09-05 18:06:53 +00:00
$search = " AND rc.capability = ' $cap ' " ;
2006-08-28 08:42:30 +00:00
} else {
2006-09-20 21:00:45 +00:00
$search = '' ;
2006-08-28 08:42:30 +00:00
}
2006-09-20 21:00:45 +00:00
$SQL = " SELECT rc.*
FROM { $CFG -> prefix } role_capabilities rc ,
2006-09-20 09:00:04 +00:00
{ $CFG -> prefix } context c
WHERE rc . contextid in $contexts
AND rc . roleid = $roleid
AND rc . contextid = c . id $search
2006-09-22 06:19:32 +00:00
ORDER BY c . contextlevel DESC ,
2006-09-20 21:00:45 +00:00
rc . capability DESC " ;
2006-09-20 08:30:49 +00:00
2006-08-09 13:14:15 +00:00
$capabilities = array ();
2006-09-20 21:00:45 +00:00
2006-09-05 03:07:56 +00:00
if ( $records = get_records_sql ( $SQL )) {
// We are traversing via reverse order.
foreach ( $records as $record ) {
// If not set yet (i.e. inherit or not set at all), or currently we have a prohibit
if ( ! isset ( $capabilities [ $record -> capability ]) || $record -> permission <- 500 ) {
$capabilities [ $record -> capability ] = $record -> permission ;
2006-09-20 21:00:45 +00:00
}
2006-09-05 03:07:56 +00:00
}
2006-08-09 13:14:15 +00:00
}
return $capabilities ;
2006-08-08 05:13:06 +00:00
}
/**
2006-09-20 21:00:45 +00:00
* Recursive function which , given a context , find all parent context ids ,
2006-08-08 05:13:06 +00:00
* and return the array in reverse order , i . e . parent first , then grand
* parent , etc .
* @ param object $context
* @ return array ()
*/
function get_parent_contexts ( $context ) {
2006-09-20 08:30:49 +00:00
2007-01-11 06:06:11 +00:00
static $pcontexts ; // cache
if ( isset ( $pcontexts [ $context -> id ])) {
return ( $pcontexts [ $context -> id ]);
}
2006-09-22 06:19:32 +00:00
switch ( $context -> contextlevel ) {
2006-08-08 05:13:06 +00:00
case CONTEXT_SYSTEM : // no parent
2006-09-05 09:30:40 +00:00
return array ();
2006-08-08 05:13:06 +00:00
break ;
case CONTEXT_PERSONAL :
2006-10-25 08:38:14 +00:00
if ( ! $parent = get_context_instance ( CONTEXT_SYSTEM )) {
2006-09-05 09:30:40 +00:00
return array ();
} else {
2007-01-11 06:06:11 +00:00
$res = array ( $parent -> id );
2007-01-11 06:41:38 +00:00
$pcontexts [ $context -> id ] = $res ;
2007-01-11 06:06:11 +00:00
return $res ;
2006-09-05 09:30:40 +00:00
}
2006-08-08 05:13:06 +00:00
break ;
2006-09-20 21:00:45 +00:00
2006-09-15 14:09:16 +00:00
case CONTEXT_USER :
2006-10-25 08:38:14 +00:00
if ( ! $parent = get_context_instance ( CONTEXT_SYSTEM )) {
2006-09-05 09:30:40 +00:00
return array ();
} else {
2007-01-11 06:06:11 +00:00
$res = array ( $parent -> id );
2007-01-11 06:41:38 +00:00
$pcontexts [ $context -> id ] = $res ;
2007-01-11 06:06:11 +00:00
return $res ;
2006-09-05 09:30:40 +00:00
}
2006-08-08 05:13:06 +00:00
break ;
2006-09-20 21:00:45 +00:00
2006-08-08 05:13:06 +00:00
case CONTEXT_COURSECAT : // Coursecat -> coursecat or site
2006-09-05 09:30:40 +00:00
if ( ! $coursecat = get_record ( 'course_categories' , 'id' , $context -> instanceid )) {
return array ();
}
2006-08-31 05:06:30 +00:00
if ( ! empty ( $coursecat -> parent )) { // return parent value if exist
2006-08-08 05:13:06 +00:00
$parent = get_context_instance ( CONTEXT_COURSECAT , $coursecat -> parent );
2007-01-11 06:06:11 +00:00
$res = array_merge ( array ( $parent -> id ), get_parent_contexts ( $parent ));
$pcontexts [ $context -> id ] = $res ;
return $res ;
2006-08-08 05:13:06 +00:00
} else { // else return site value
2006-10-25 08:38:14 +00:00
$parent = get_context_instance ( CONTEXT_SYSTEM );
2007-01-11 06:06:11 +00:00
$res = array ( $parent -> id );
$pcontexts [ $context -> id ] = $res ;
return $res ;
2006-08-08 05:13:06 +00:00
}
break ;
case CONTEXT_COURSE : // 1 to 1 to course cat
2006-09-05 09:30:40 +00:00
if ( ! $course = get_record ( 'course' , 'id' , $context -> instanceid )) {
return array ();
}
2006-11-12 08:55:13 +00:00
if ( $course -> id != SITEID ) {
2006-09-05 09:30:40 +00:00
$parent = get_context_instance ( CONTEXT_COURSECAT , $course -> category );
2007-01-11 06:06:11 +00:00
$res = array_merge ( array ( $parent -> id ), get_parent_contexts ( $parent ));
return $res ;
2006-09-05 09:30:40 +00:00
} else {
2006-11-15 08:23:27 +00:00
// Yu: Separating site and site course context
$parent = get_context_instance ( CONTEXT_SYSTEM );
2007-01-11 06:06:11 +00:00
$res = array ( $parent -> id );
$pcontexts [ $context -> id ] = $res ;
return $res ;
2006-09-05 09:30:40 +00:00
}
2006-08-08 05:13:06 +00:00
break ;
case CONTEXT_GROUP : // 1 to 1 to course
2007-01-04 13:15:04 +13:00
if ( ! $group = groups_get_group ( $context -> instanceid )) {
2006-09-05 09:30:40 +00:00
return array ();
}
if ( $parent = get_context_instance ( CONTEXT_COURSE , $group -> courseid )) {
2007-01-11 06:06:11 +00:00
$res = array_merge ( array ( $parent -> id ), get_parent_contexts ( $parent ));
$pcontexts [ $context -> id ] = $res ;
return $res ;
2006-09-05 09:30:40 +00:00
} else {
return array ();
}
2006-08-08 05:13:06 +00:00
break ;
case CONTEXT_MODULE : // 1 to 1 to course
2006-09-05 09:30:40 +00:00
if ( ! $cm = get_record ( 'course_modules' , 'id' , $context -> instanceid )) {
return array ();
}
if ( $parent = get_context_instance ( CONTEXT_COURSE , $cm -> course )) {
2007-01-11 06:06:11 +00:00
$res = array_merge ( array ( $parent -> id ), get_parent_contexts ( $parent ));
$pcontexts [ $context -> id ] = $res ;
return $res ;
2006-09-05 09:30:40 +00:00
} else {
return array ();
}
2006-08-08 05:13:06 +00:00
break ;
case CONTEXT_BLOCK : // 1 to 1 to course
2006-09-05 09:30:40 +00:00
if ( ! $block = get_record ( 'block_instance' , 'id' , $context -> instanceid )) {
return array ();
}
2007-05-07 03:24:22 +00:00
// fix for MDL-9656, block parents are not necessarily courses
if ( $block -> pagetype == 'course-view' ) {
$parent = get_context_instance ( CONTEXT_COURSE , $block -> pageid );
} else {
$parent = get_context_instance ( CONTEXT_SYSTEM );
}
if ( $parent ) {
2007-01-11 06:06:11 +00:00
$res = array_merge ( array ( $parent -> id ), get_parent_contexts ( $parent ));
$pcontexts [ $context -> id ] = $res ;
return $res ;
2006-09-05 09:30:40 +00:00
} else {
2007-05-07 03:24:22 +00:00
return array ();
2006-09-05 09:30:40 +00:00
}
2006-08-08 05:13:06 +00:00
break ;
default :
2007-03-01 16:42:36 +00:00
error ( 'This is an unknown context (' . $context -> contextlevel . ') in get_parent_contexts!' );
2006-08-08 05:13:06 +00:00
return false ;
}
}
2006-09-20 08:30:49 +00:00
2007-02-09 02:24:59 +00:00
/**
* Recursive function which , given a context , find all its children context ids .
* @ param object $context .
* @ return array of children context ids .
*/
function get_child_contexts ( $context ) {
global $CFG ;
$children = array ();
switch ( $context -> contextlevel ) {
case CONTEXT_BLOCK :
// No children.
return array ();
break ;
case CONTEXT_MODULE :
// No children.
return array ();
break ;
case CONTEXT_GROUP :
// No children.
return array ();
break ;
case CONTEXT_COURSE :
// Find all block instances for the course.
$page = new page_course ;
$page -> id = $context -> instanceid ;
$page -> type = 'course-view' ;
if ( $blocks = blocks_get_by_page_pinned ( $page )) {
foreach ( $blocks [ 'l' ] as $leftblock ) {
2007-02-14 08:03:40 +00:00
if ( $child = get_context_instance ( CONTEXT_BLOCK , $leftblock -> id )) {
2007-02-09 02:24:59 +00:00
array_push ( $children , $child -> id );
}
}
foreach ( $blocks [ 'r' ] as $rightblock ) {
2007-02-14 08:03:40 +00:00
if ( $child = get_context_instance ( CONTEXT_BLOCK , $rightblock -> id )) {
2007-02-09 02:24:59 +00:00
array_push ( $children , $child -> id );
}
}
}
// Find all module instances for the course.
if ( $modules = get_records ( 'course_modules' , 'course' , $context -> instanceid )) {
foreach ( $modules as $module ) {
if ( $child = get_context_instance ( CONTEXT_MODULE , $module -> id )) {
array_push ( $children , $child -> id );
}
}
}
// Find all group instances for the course.
2007-02-14 08:03:40 +00:00
if ( $groupids = groups_get_groups ( $context -> instanceid )) {
foreach ( $groupids as $groupid ) {
if ( $child = get_context_instance ( CONTEXT_GROUP , $groupid )) {
2007-02-09 02:24:59 +00:00
array_push ( $children , $child -> id );
}
}
}
return $children ;
break ;
case CONTEXT_COURSECAT :
// We need to get the contexts for:
// 1) The subcategories of the given category
// 2) The courses in the given category and all its subcategories
// 3) All the child contexts for these courses
$categories = get_all_subcategories ( $context -> instanceid );
// Add the contexts for all the subcategories.
foreach ( $categories as $catid ) {
if ( $catci = get_context_instance ( CONTEXT_COURSECAT , $catid )) {
array_push ( $children , $catci -> id );
}
}
// Add the parent category as well so we can find the contexts
// for its courses.
array_unshift ( $categories , $context -> instanceid );
foreach ( $categories as $catid ) {
// Find all courses for the category.
if ( $courses = get_records ( 'course' , 'category' , $catid )) {
foreach ( $courses as $course ) {
if ( $courseci = get_context_instance ( CONTEXT_COURSE , $course -> id )) {
array_push ( $children , $courseci -> id );
$children = array_merge ( $children , get_child_contexts ( $courseci ));
}
}
}
}
return $children ;
break ;
case CONTEXT_USER :
// No children.
return array ();
break ;
case CONTEXT_PERSONAL :
// No children.
return array ();
break ;
case CONTEXT_SYSTEM :
// Just get all the contexts except for CONTEXT_SYSTEM level.
$sql = 'SELECT c.id ' .
'FROM ' . $CFG -> prefix . 'context AS c ' .
'WHERE contextlevel != ' . CONTEXT_SYSTEM ;
$contexts = get_records_sql ( $sql );
foreach ( $contexts as $cid ) {
array_push ( $children , $cid -> id );
}
return $children ;
break ;
default :
2007-03-01 16:42:36 +00:00
error ( 'This is an unknown context (' . $context -> contextlevel . ') in get_child_contexts!' );
2007-02-09 02:24:59 +00:00
return false ;
}
}
2006-09-20 08:30:49 +00:00
/**
* Gets a string for sql calls , searching for stuff in this context or above
2006-09-14 09:08:07 +00:00
* @ param object $context
* @ return string
*/
function get_related_contexts_string ( $context ) {
if ( $parents = get_parent_contexts ( $context )) {
2006-09-20 21:00:45 +00:00
return ( ' IN (' . $context -> id . ',' . implode ( ',' , $parents ) . ')' );
2006-09-14 09:08:07 +00:00
} else {
return ( ' =' . $context -> id );
}
}
2006-09-20 08:30:49 +00:00
2006-08-08 05:13:06 +00:00
/**
* This function gets the capability of a role in a given context .
* It is needed when printing override forms .
* @ param int $contextid
* @ param string $capability
* @ param array $capabilities - array loaded using role_context_capabilities
* @ return int ( allow , prevent , prohibit , inherit )
*/
function get_role_context_capability ( $contextid , $capability , $capabilities ) {
2006-09-20 08:30:49 +00:00
if ( isset ( $capabilities [ $contextid ][ $capability ])) {
return $capabilities [ $contextid ][ $capability ];
}
else {
return false ;
}
2006-08-08 05:13:06 +00:00
}
2006-08-14 07:15:03 +00:00
/**
* Returns the human - readable , translated version of the capability .
* Basically a big switch statement .
* @ param $capabilityname - e . g . mod / choice : readresponses
*/
2006-08-13 09:11:45 +00:00
function get_capability_string ( $capabilityname ) {
2006-09-20 21:00:45 +00:00
2006-08-14 07:15:03 +00:00
// Typical capabilityname is mod/choice:readresponses
2006-08-13 09:11:45 +00:00
$names = split ( '/' , $capabilityname );
$stringname = $names [ 1 ]; // choice:readresponses
2006-09-20 21:00:45 +00:00
$components = split ( ':' , $stringname );
2006-08-13 09:11:45 +00:00
$componentname = $components [ 0 ]; // choice
2006-08-09 13:14:15 +00:00
switch ( $names [ 0 ]) {
case 'mod' :
2006-08-13 09:11:45 +00:00
$string = get_string ( $stringname , $componentname );
2006-08-09 13:14:15 +00:00
break ;
2006-09-20 21:00:45 +00:00
2006-08-09 13:14:15 +00:00
case 'block' :
2006-08-13 09:11:45 +00:00
$string = get_string ( $stringname , 'block_' . $componentname );
2006-08-09 13:14:15 +00:00
break ;
2006-08-13 09:11:45 +00:00
2006-08-09 13:14:15 +00:00
case 'moodle' :
2006-08-13 09:11:45 +00:00
$string = get_string ( $stringname , 'role' );
2006-08-09 13:14:15 +00:00
break ;
2006-09-20 21:00:45 +00:00
2006-08-09 13:14:15 +00:00
case 'enrol' :
2006-08-13 09:11:45 +00:00
$string = get_string ( $stringname , 'enrol_' . $componentname );
2006-09-20 21:00:45 +00:00
break ;
2006-12-11 15:47:23 +00:00
case 'format' :
$string = get_string ( $stringname , 'format_' . $componentname );
break ;
2006-09-20 21:00:45 +00:00
2006-08-09 13:14:15 +00:00
default :
2006-08-13 09:11:45 +00:00
$string = get_string ( $stringname );
2006-09-20 21:00:45 +00:00
break ;
2006-08-09 13:14:15 +00:00
}
2006-08-13 09:11:45 +00:00
return $string ;
2006-08-08 05:13:06 +00:00
}
2006-08-14 07:15:03 +00:00
/**
* This gets the mod / block / course / core etc strings .
* @ param $component
* @ param $contextlevel
*/
2006-08-08 05:13:06 +00:00
function get_component_string ( $component , $contextlevel ) {
2006-08-09 13:14:15 +00:00
switch ( $contextlevel ) {
2006-08-08 05:13:06 +00:00
2006-08-09 13:14:15 +00:00
case CONTEXT_SYSTEM :
2006-09-12 20:03:08 +00:00
if ( preg_match ( '|^enrol/|' , $component )) {
$langname = str_replace ( '/' , '_' , $component );
$string = get_string ( 'enrolname' , $langname );
2006-09-24 11:32:11 +00:00
} else if ( preg_match ( '|^block/|' , $component )) {
$langname = str_replace ( '/' , '_' , $component );
$string = get_string ( 'blockname' , $langname );
2006-09-12 19:54:33 +00:00
} else {
$string = get_string ( 'coresystem' );
}
2006-08-08 05:13:06 +00:00
break ;
case CONTEXT_PERSONAL :
2006-08-09 13:14:15 +00:00
$string = get_string ( 'personal' );
2006-08-08 05:13:06 +00:00
break ;
2006-09-15 14:09:16 +00:00
case CONTEXT_USER :
2006-08-09 13:14:15 +00:00
$string = get_string ( 'users' );
2006-08-08 05:13:06 +00:00
break ;
case CONTEXT_COURSECAT :
2006-08-09 13:14:15 +00:00
$string = get_string ( 'categories' );
2006-08-08 05:13:06 +00:00
break ;
case CONTEXT_COURSE :
2006-08-09 13:14:15 +00:00
$string = get_string ( 'course' );
2006-08-08 05:13:06 +00:00
break ;
case CONTEXT_GROUP :
2006-08-09 13:14:15 +00:00
$string = get_string ( 'group' );
2006-08-08 05:13:06 +00:00
break ;
case CONTEXT_MODULE :
2006-08-09 13:14:15 +00:00
$string = get_string ( 'modulename' , basename ( $component ));
2006-08-08 05:13:06 +00:00
break ;
case CONTEXT_BLOCK :
2007-02-14 23:00:20 +00:00
$string = get_string ( 'blockname' , 'block_' . basename ( $component ));
2006-08-08 05:13:06 +00:00
break ;
default :
2007-03-01 16:42:36 +00:00
error ( 'This is an unknown context $contextlevel (' . $contextlevel . ') in get_component_string!' );
2006-08-08 05:13:06 +00:00
return false ;
2006-09-20 21:00:45 +00:00
2006-08-09 13:14:15 +00:00
}
return $string ;
2006-08-08 05:13:06 +00:00
}
2006-08-14 07:15:03 +00:00
2006-09-20 08:30:49 +00:00
/**
* Gets the list of roles assigned to this context and up ( parents )
2006-08-23 06:36:08 +00:00
* @ param object $context
2006-11-15 04:28:18 +00:00
* @ param view - set to true when roles are pulled for display only
* this is so that we can filter roles with no visible
* assignment , for example , you might want to " hide " all
* course creators when browsing the course participants
* list .
2006-08-23 06:36:08 +00:00
* @ return array
*/
2006-11-15 04:28:18 +00:00
function get_roles_used_in_context ( $context , $view = false ) {
2006-08-14 08:14:02 +00:00
global $CFG ;
2006-11-15 04:28:18 +00:00
// filter for roles with all hidden assignments
// no need to return when only pulling roles for reviewing
// e.g. participants page.
2006-11-17 08:57:50 +00:00
$hiddensql = ( $view && ! has_capability ( 'moodle/role:viewhiddenassigns' , $context )) ? ' AND ra.hidden = 0 ' : '' ;
2006-09-19 02:47:55 +00:00
$contextlist = get_related_contexts_string ( $context );
2006-09-20 21:00:45 +00:00
2006-09-20 08:30:49 +00:00
$sql = " SELECT DISTINCT r.id,
r . name ,
r . shortname ,
r . sortorder
FROM { $CFG -> prefix } role_assignments ra ,
2006-09-20 21:00:45 +00:00
{ $CFG -> prefix } role r
WHERE r . id = ra . roleid
2006-09-20 08:30:49 +00:00
AND ra . contextid $contextlist
2006-11-15 04:28:18 +00:00
$hiddensql
2006-09-20 08:30:49 +00:00
ORDER BY r . sortorder ASC " ;
2006-09-20 21:00:45 +00:00
2006-09-20 08:30:49 +00:00
return get_records_sql ( $sql );
2006-08-14 08:14:02 +00:00
}
2006-09-20 21:00:45 +00:00
/** this function is used to print roles column in user profile page .
2006-08-23 06:36:08 +00:00
* @ param int userid
* @ param int contextid
* @ return string
*/
2006-08-15 08:29:29 +00:00
function get_user_roles_in_context ( $userid , $contextid ){
global $CFG ;
2006-09-20 21:00:45 +00:00
2006-08-15 08:29:29 +00:00
$rolestring = '' ;
$SQL = 'select * from ' . $CFG -> prefix . 'role_assignments ra, ' . $CFG -> prefix . 'role r where ra.userid=' . $userid . ' and ra.contextid=' . $contextid . ' and ra.roleid = r.id' ;
if ( $roles = get_records_sql ( $SQL )) {
foreach ( $roles as $userrole ) {
$rolestring .= '<a href="' . $CFG -> wwwroot . '/user/index.php?contextid=' . $userrole -> contextid . '&roleid=' . $userrole -> roleid . '">' . $userrole -> name . '</a>, ' ;
2006-09-20 21:00:45 +00:00
}
2006-08-15 08:29:29 +00:00
}
return rtrim ( $rolestring , ', ' );
}
2006-08-18 08:01:16 +00:00
2006-08-23 06:36:08 +00:00
/**
* Checks if a user can override capabilities of a particular role in this context
* @ param object $context
* @ param int targetroleid - the id of the role you want to override
* @ return boolean
*/
2006-08-18 08:01:16 +00:00
function user_can_override ( $context , $targetroleid ) {
// first check if user has override capability
// if not return false;
if ( ! has_capability ( 'moodle/role:override' , $context )) {
2006-09-20 21:00:45 +00:00
return false ;
2006-08-18 08:01:16 +00:00
}
// pull out all active roles of this user from this context(or above)
2006-08-19 08:12:45 +00:00
if ( $userroles = get_user_roles ( $context )) {
foreach ( $userroles as $userrole ) {
// if any in the role_allow_override table, then it's ok
if ( get_record ( 'role_allow_override' , 'roleid' , $userrole -> roleid , 'allowoverride' , $targetroleid )) {
return true ;
}
2006-08-18 08:01:16 +00:00
}
}
2006-09-20 21:00:45 +00:00
2006-08-18 08:01:16 +00:00
return false ;
2006-09-20 21:00:45 +00:00
2006-08-18 08:01:16 +00:00
}
2006-08-23 06:36:08 +00:00
/**
* Checks if a user can assign users to a particular role in this context
* @ param object $context
* @ param int targetroleid - the id of the role you want to assign users to
* @ return boolean
*/
2006-08-18 08:01:16 +00:00
function user_can_assign ( $context , $targetroleid ) {
2006-09-20 21:00:45 +00:00
2006-08-18 08:01:16 +00:00
// first check if user has override capability
// if not return false;
if ( ! has_capability ( 'moodle/role:assign' , $context )) {
2006-09-20 21:00:45 +00:00
return false ;
2006-08-18 08:01:16 +00:00
}
// pull out all active roles of this user from this context(or above)
2006-08-19 08:12:45 +00:00
if ( $userroles = get_user_roles ( $context )) {
foreach ( $userroles as $userrole ) {
// if any in the role_allow_override table, then it's ok
if ( get_record ( 'role_allow_assign' , 'roleid' , $userrole -> roleid , 'allowassign' , $targetroleid )) {
return true ;
}
2006-08-18 08:01:16 +00:00
}
}
2006-09-20 21:00:45 +00:00
return false ;
2006-08-18 08:01:16 +00:00
}
2006-09-23 12:51:00 +00:00
/** Returns all site roles in correct sort order .
*
*/
function get_all_roles () {
return get_records ( 'role' , '' , '' , 'sortorder ASC' );
}
2006-08-23 06:36:08 +00:00
/**
* gets all the user roles assigned in this context , or higher contexts
* this is mainly used when checking if a user can assign a role , or overriding a role
* i . e . we need to know what this user holds , in order to verify against allow_assign and
* allow_override tables
* @ param object $context
* @ param int $userid
2006-11-16 08:29:25 +00:00
* @ param view - set to true when roles are pulled for display only
* this is so that we can filter roles with no visible
* assignment , for example , you might want to " hide " all
* course creators when browsing the course participants
* list .
2006-08-23 06:36:08 +00:00
* @ return array
*/
2006-11-16 08:29:25 +00:00
function get_user_roles ( $context , $userid = 0 , $checkparentcontexts = true , $order = 'c.contextlevel DESC, r.sortorder ASC' , $view = false ) {
2006-08-18 08:01:16 +00:00
global $USER , $CFG , $db ;
2006-08-19 08:12:45 +00:00
if ( empty ( $userid )) {
if ( empty ( $USER -> id )) {
return array ();
}
$userid = $USER -> id ;
}
2006-11-16 08:29:25 +00:00
// set up hidden sql
2006-11-17 08:57:50 +00:00
$hiddensql = ( $view && ! has_capability ( 'moodle/role:viewhiddenassigns' , $context )) ? ' AND ra.hidden = 0 ' : '' ;
2006-08-19 08:12:45 +00:00
2006-09-16 15:22:55 +00:00
if ( $checkparentcontexts && ( $parents = get_parent_contexts ( $context ))) {
$contexts = ' ra.contextid IN (' . implode ( ',' , $parents ) . ',' . $context -> id . ')' ;
2006-08-19 08:12:45 +00:00
} else {
2006-09-16 15:22:55 +00:00
$contexts = ' ra.contextid = \'' . $context -> id . '\'' ;
2006-08-19 08:12:45 +00:00
}
2006-09-18 17:40:22 +00:00
return get_records_sql ( ' SELECT ra .* , r . name , r . shortname
2006-09-16 15:22:55 +00:00
FROM '.$CFG->prefix.' role_assignments ra ,
2006-09-17 03:33:22 +00:00
'.$CFG->prefix.' role r ,
'.$CFG->prefix.' context c
2006-08-19 08:12:45 +00:00
WHERE ra . userid = ' . $userid .
2006-09-16 15:22:55 +00:00
' AND ra . roleid = r . id
2006-09-17 03:33:22 +00:00
AND ra . contextid = c . id
2006-11-16 08:29:25 +00:00
AND ' . $contexts . $hiddensql .
2006-11-16 05:17:43 +00:00
' ORDER BY ' . $order );
2006-08-18 08:01:16 +00:00
}
2006-08-23 06:36:08 +00:00
/**
2006-09-20 21:00:45 +00:00
* Creates a record in the allow_override table
2006-08-23 06:36:08 +00:00
* @ param int sroleid - source roleid
* @ param int troleid - target roleid
* @ return int - id or false
*/
function allow_override ( $sroleid , $troleid ) {
2006-09-23 12:51:00 +00:00
$record = new object ();
2006-08-23 06:36:08 +00:00
$record -> roleid = $sroleid ;
$record -> allowoverride = $troleid ;
return insert_record ( 'role_allow_override' , $record );
}
/**
2006-09-20 21:00:45 +00:00
* Creates a record in the allow_assign table
2006-08-23 06:36:08 +00:00
* @ param int sroleid - source roleid
* @ param int troleid - target roleid
* @ return int - id or false
*/
function allow_assign ( $sroleid , $troleid ) {
2006-09-17 07:00:47 +00:00
$record = new object ;
2006-08-23 06:36:08 +00:00
$record -> roleid = $sroleid ;
$record -> allowassign = $troleid ;
return insert_record ( 'role_allow_assign' , $record );
}
/**
2006-09-17 07:00:47 +00:00
* Gets a list of roles that this user can assign in this context
2006-08-23 06:36:08 +00:00
* @ param object $context
* @ return array
*/
2006-10-03 08:54:46 +00:00
function get_assignable_roles ( $context , $field = " name " ) {
2006-08-23 06:36:08 +00:00
$options = array ();
2006-09-17 07:00:47 +00:00
2006-09-23 12:51:00 +00:00
if ( $roles = get_all_roles ()) {
2006-09-17 07:00:47 +00:00
foreach ( $roles as $role ) {
if ( user_can_assign ( $context , $role -> id )) {
2006-10-03 08:54:46 +00:00
$options [ $role -> id ] = strip_tags ( format_string ( $role -> { $field }, true ));
2006-09-17 07:00:47 +00:00
}
2006-08-23 06:36:08 +00:00
}
}
return $options ;
}
/**
2006-09-17 07:00:47 +00:00
* Gets a list of roles that this user can override in this context
2006-08-23 06:36:08 +00:00
* @ param object $context
* @ return array
*/
2007-03-05 11:27:01 +00:00
function get_overridable_roles ( $context ) {
2006-08-23 06:36:08 +00:00
$options = array ();
2006-09-17 07:00:47 +00:00
2006-09-23 12:51:00 +00:00
if ( $roles = get_all_roles ()) {
2006-09-17 07:00:47 +00:00
foreach ( $roles as $role ) {
if ( user_can_override ( $context , $role -> id )) {
2006-09-23 12:46:53 +00:00
$options [ $role -> id ] = strip_tags ( format_string ( $role -> name , true ));
2006-09-17 07:00:47 +00:00
}
2006-08-23 06:36:08 +00:00
}
2006-09-17 07:00:47 +00:00
}
2006-09-20 21:00:45 +00:00
return $options ;
2006-08-23 06:36:08 +00:00
}
2006-08-28 08:42:30 +00:00
2007-03-05 11:27:01 +00:00
/**
2006-09-17 16:06:25 +00:00
* Returns a role object that is the default role for new enrolments
* in a given course
*
2006-09-20 21:00:45 +00:00
* @ param object $course
2006-09-17 16:06:25 +00:00
* @ return object $role
*/
function get_default_course_role ( $course ) {
global $CFG ;
/// First let's take the default role the course may have
if ( ! empty ( $course -> defaultrole )) {
if ( $role = get_record ( 'role' , 'id' , $course -> defaultrole )) {
return $role ;
}
}
/// Otherwise the site setting should tell us
if ( $CFG -> defaultcourseroleid ) {
if ( $role = get_record ( 'role' , 'id' , $CFG -> defaultcourseroleid )) {
return $role ;
}
}
/// It's unlikely we'll get here, but just in case, try and find a student role
if ( $studentroles = get_roles_with_capability ( 'moodle/legacy:student' , CAP_ALLOW )) {
return array_shift ( $studentroles ); /// Take the first one
}
return NULL ;
}
2006-08-28 08:42:30 +00:00
/**
* who has this capability in this context
* does not handling user level resolving !!!
2006-11-15 08:23:27 +00:00
* ( ! ) pleaes note if $fields is empty this function attempts to get u .*
* which can get rather large .
2006-08-28 08:42:30 +00:00
* i . e 1 person has 2 roles 1 allow , 1 prevent , this will not work properly
* @ param $context - object
* @ param $capability - string capability
* @ param $fields - fields to be pulled
* @ param $sort - the sort order
2006-09-05 18:55:16 +00:00
* @ param $limitfrom - number of records to skip ( offset )
2006-09-20 21:00:45 +00:00
* @ param $limitnum - number of records to fetch
2006-09-11 08:56:23 +00:00
* @ param $groups - single group or array of groups - group ( s ) user is in
2006-09-15 09:08:48 +00:00
* @ param $exceptions - list of users to exclude
2006-11-16 08:29:25 +00:00
* @ param view - set to true when roles are pulled for display only
* this is so that we can filter roles with no visible
* assignment , for example , you might want to " hide " all
* course creators when browsing the course participants
* list .
2006-08-28 08:42:30 +00:00
*/
2006-09-20 21:00:45 +00:00
function get_users_by_capability ( $context , $capability , $fields = '' , $sort = '' ,
2006-11-16 08:29:25 +00:00
$limitfrom = '' , $limitnum = '' , $groups = '' , $exceptions = '' , $doanything = true , $view = false ) {
2006-08-28 08:42:30 +00:00
global $CFG ;
2006-09-20 21:00:45 +00:00
2006-09-16 13:54:57 +00:00
/// Sorting out groups
2006-09-11 08:56:23 +00:00
if ( $groups ) {
2006-09-15 09:08:48 +00:00
$groupjoin = 'INNER JOIN ' . $CFG -> prefix . 'groups_members gm ON gm.userid = ra.userid' ;
2006-09-20 21:00:45 +00:00
2006-09-11 08:56:23 +00:00
if ( is_array ( $groups )) {
2006-09-16 05:56:51 +00:00
$groupsql = 'AND gm.groupid IN (' . implode ( ',' , $groups ) . ')' ;
2006-09-11 08:56:23 +00:00
} else {
2006-09-20 21:00:45 +00:00
$groupsql = 'AND gm.groupid = ' . $groups ;
2006-09-11 08:56:23 +00:00
}
} else {
$groupjoin = '' ;
2006-09-20 21:00:45 +00:00
$groupsql = '' ;
2006-09-11 08:56:23 +00:00
}
2006-09-20 21:00:45 +00:00
2006-09-16 13:54:57 +00:00
/// Sorting out exceptions
2006-09-15 13:51:42 +00:00
$exceptionsql = $exceptions ? " AND u.id NOT IN ( $exceptions ) " : '' ;
2006-09-16 13:54:57 +00:00
/// Set up default fields
if ( empty ( $fields )) {
2006-09-16 15:22:55 +00:00
$fields = 'u.*, ul.timeaccess as lastaccess, ra.hidden' ;
2006-09-16 13:54:57 +00:00
}
/// Set up default sort
if ( empty ( $sort )) {
$sort = 'ul.timeaccess' ;
}
2006-09-20 21:00:45 +00:00
$sortby = $sort ? " ORDER BY $sort " : '' ;
2006-11-16 08:29:25 +00:00
/// Set up hidden sql
2006-11-17 08:57:50 +00:00
$hiddensql = ( $view && ! has_capability ( 'moodle/role:viewhiddenassigns' , $context )) ? ' AND ra.hidden = 0 ' : '' ;
2006-09-20 21:00:45 +00:00
2006-09-16 13:54:57 +00:00
/// If context is a course, then construct sql for ul
2006-09-22 06:19:32 +00:00
if ( $context -> contextlevel == CONTEXT_COURSE ) {
2006-09-15 09:08:48 +00:00
$courseid = $context -> instanceid ;
2006-11-16 05:17:43 +00:00
$coursesql1 = " AND ul.courseid = $courseid " ;
2006-09-15 13:51:42 +00:00
} else {
2006-11-16 05:17:43 +00:00
$coursesql1 = '' ;
2006-09-15 09:08:48 +00:00
}
2006-09-16 13:54:57 +00:00
/// Sorting out roles with this capability set
2006-09-22 05:17:57 +00:00
if ( $possibleroles = get_roles_with_capability ( $capability , CAP_ALLOW , $context )) {
2006-09-25 03:00:50 +00:00
if ( ! $doanything ) {
2006-10-25 08:38:14 +00:00
if ( ! $sitecontext = get_context_instance ( CONTEXT_SYSTEM )) {
2006-09-25 03:00:50 +00:00
return false ; // Something is seriously wrong
}
$doanythingroles = get_roles_with_capability ( 'moodle/site:doanything' , CAP_ALLOW , $sitecontext );
2006-09-24 16:14:39 +00:00
}
2006-09-22 05:17:57 +00:00
$validroleids = array ();
2006-09-24 16:14:39 +00:00
foreach ( $possibleroles as $possiblerole ) {
2006-09-25 03:00:50 +00:00
if ( ! $doanything ) {
if ( isset ( $doanythingroles [ $possiblerole -> id ])) { // We don't want these included
continue ;
}
2006-09-24 16:14:39 +00:00
}
2006-09-27 08:01:22 +00:00
if ( $caps = role_context_capabilities ( $possiblerole -> id , $context , $capability )) { // resolved list
if ( isset ( $caps [ $capability ]) && $caps [ $capability ] > 0 ) { // resolved capability > 0
$validroleids [] = $possiblerole -> id ;
}
2006-09-22 05:17:57 +00:00
}
2006-08-28 08:42:30 +00:00
}
2006-09-25 03:00:50 +00:00
if ( empty ( $validroleids )) {
return false ;
}
2006-09-22 05:17:57 +00:00
$roleids = '(' . implode ( ',' , $validroleids ) . ')' ;
} else {
return false ; // No need to continue, since no roles have this capability set
2006-09-20 21:00:45 +00:00
}
2006-09-16 13:54:57 +00:00
/// Construct the main SQL
2006-09-15 09:08:48 +00:00
$select = " SELECT $fields " ;
2006-09-20 21:00:45 +00:00
$from = " FROM { $CFG -> prefix } user u
INNER JOIN { $CFG -> prefix } role_assignments ra ON ra . userid = u . id
2006-09-25 06:09:06 +00:00
INNER JOIN { $CFG -> prefix } role r ON r . id = ra . roleid
2006-11-16 05:17:43 +00:00
LEFT OUTER JOIN { $CFG -> prefix } user_lastaccess ul ON ( ul . userid = u . id $coursesql1 )
2006-09-15 09:08:48 +00:00
$groupjoin " ;
2006-09-20 21:00:45 +00:00
$where = " WHERE ra.contextid " . get_related_contexts_string ( $context ) . "
AND u . deleted = 0
AND ra . roleid in $roleids
2006-09-15 09:08:48 +00:00
$exceptionsql
2006-11-16 08:29:25 +00:00
$groupsql
$hiddensql " ;
2006-09-20 21:00:45 +00:00
return get_records_sql ( $select . $from . $where . $sortby , $limitfrom , $limitnum );
2006-08-28 08:42:30 +00:00
}
2006-09-03 07:56:40 +00:00
2006-09-12 07:37:23 +00:00
/**
* gets all the users assigned this role in this context or higher
* @ param int roleid
* @ param int contextid
* @ param bool parent if true , get list of users assigned in higher context too
* @ return array ()
*/
2006-11-17 08:57:50 +00:00
function get_role_users ( $roleid , $context , $parent = false , $fields = '' , $sort = 'u.lastname ASC' , $view = false ) {
2006-09-12 07:37:23 +00:00
global $CFG ;
2006-09-20 21:00:45 +00:00
2006-10-25 07:20:28 +00:00
if ( empty ( $fields )) {
$fields = 'u.id, u.confirmed, u.username, u.firstname, u.lastname, ' .
'u.maildisplay, u.mailformat, u.maildigest, u.email, u.city, ' .
'u.country, u.picture, u.idnumber, u.department, u.institution, ' .
'u.emailstop, u.lang, u.timezone' ;
}
2006-11-17 08:57:50 +00:00
// whether this assignment is hidden
$hiddensql = ( $view && ! has_capability ( 'moodle/role:viewhiddenassigns' , $context )) ? ' AND r.hidden = 0 ' : '' ;
2006-09-12 07:37:23 +00:00
if ( $parent ) {
if ( $contexts = get_parent_contexts ( $context )) {
2006-10-01 07:02:53 +00:00
$parentcontexts = ' OR r.contextid IN (' . implode ( ',' , $contexts ) . ')' ;
2006-09-12 07:37:23 +00:00
} else {
2006-09-20 21:00:45 +00:00
$parentcontexts = '' ;
2006-09-12 07:37:23 +00:00
}
} else {
2006-09-20 21:00:45 +00:00
$parentcontexts = '' ;
}
2006-10-01 08:34:36 +00:00
if ( $roleid ) {
$roleselect = " AND r.roleid = $roleid " ;
} else {
$roleselect = '' ;
}
2006-10-01 07:02:53 +00:00
$SQL = " SELECT $fields
FROM { $CFG -> prefix } role_assignments r ,
2006-09-20 21:00:45 +00:00
{ $CFG -> prefix } user u
2006-10-01 07:02:53 +00:00
WHERE ( r . contextid = $context -> id $parentcontexts )
2006-10-01 08:34:36 +00:00
AND u . id = r . userid $roleselect
2006-11-17 08:57:50 +00:00
$hiddensql
2006-10-01 07:02:53 +00:00
ORDER BY $sort
" ; // join now so that we can just use fullname() later
2006-09-20 21:00:45 +00:00
2006-09-12 07:37:23 +00:00
return get_records_sql ( $SQL );
}
2006-09-28 04:42:49 +00:00
/**
* Counts all the users assigned this role in this context or higher
* @ param int roleid
* @ param int contextid
* @ param bool parent if true , get list of users assigned in higher context too
* @ return array ()
*/
function count_role_users ( $roleid , $context , $parent = false ) {
global $CFG ;
if ( $parent ) {
if ( $contexts = get_parent_contexts ( $context )) {
2006-10-01 07:02:53 +00:00
$parentcontexts = ' OR r.contextid IN (' . implode ( ',' , $contexts ) . ')' ;
2006-09-28 04:42:49 +00:00
} else {
$parentcontexts = '' ;
}
} else {
$parentcontexts = '' ;
}
$SQL = " SELECT count(*)
FROM { $CFG -> prefix } role_assignments r
WHERE ( r . contextid = $context -> id $parentcontexts )
AND r . roleid = $roleid " ;
return count_records_sql ( $SQL );
}
2006-09-20 21:00:45 +00:00
/**
2006-09-19 01:44:33 +00:00
* This function gets the list of courses that this user has a particular capability in
* This is not the most efficient way of doing this
* @ param string capability
* @ param int $userid
* @ return array
*/
2007-02-14 22:53:17 +00:00
function get_user_capability_course ( $capability , $userid = NULL ) {
2006-09-20 21:00:45 +00:00
2006-09-19 01:44:33 +00:00
$usercourses = array ();
$courses = get_records_select ( 'course' , '' , '' , 'id, id' );
2006-09-20 21:00:45 +00:00
2006-09-19 01:44:33 +00:00
foreach ( $courses as $course ) {
2007-02-14 22:48:11 +00:00
if ( has_capability ( $capability , get_context_instance ( CONTEXT_COURSE , $course -> id ), $userid )) {
2006-09-19 01:44:33 +00:00
$usercourses [] = $course ;
}
}
2006-09-20 21:00:45 +00:00
return $usercourses ;
2006-09-21 03:21:33 +00:00
}
/** This function finds the roles assigned directly to this context only
* i . e . no parents role
* @ param object $context
* @ return array
*/
function get_roles_on_exact_context ( $context ) {
2006-09-21 22:34:45 +00:00
2006-09-21 03:21:33 +00:00
global $CFG ;
2006-09-21 06:57:14 +00:00
2006-10-20 02:44:22 +00:00
return get_records_sql ( " SELECT r.*
2006-09-21 03:21:33 +00:00
FROM { $CFG -> prefix } role_assignments ra ,
{ $CFG -> prefix } role r
WHERE ra . roleid = r . id
AND ra . contextid = $context -> id " );
2006-09-21 22:34:45 +00:00
2006-09-21 06:57:14 +00:00
}
2007-03-05 11:27:01 +00:00
/**
2006-09-21 09:16:41 +00:00
* Switches the current user to another role for the current session and only
2006-09-21 22:34:45 +00:00
* in the given context . If roleid is not valid ( eg 0 ) or the current user
* doesn 't have permissions to be switching roles then the user' s session
2006-09-21 09:16:41 +00:00
* is compltely reset to have their normal roles .
* @ param integer $roleid
* @ param object $context
* @ return bool
*/
function role_switch ( $roleid , $context ) {
2007-03-16 20:21:27 +00:00
global $USER , $CFG ;
2006-09-21 09:16:41 +00:00
/// If we can't use this or are already using it or no role was specified then bail completely and reset
2006-09-21 22:34:45 +00:00
if ( empty ( $roleid ) || ! has_capability ( 'moodle/role:switchroles' , $context )
2006-09-21 15:58:59 +00:00
|| ! empty ( $USER -> switchrole [ $context -> id ]) || ! confirm_sesskey ()) {
2007-03-16 20:21:27 +00:00
2006-09-21 15:58:59 +00:00
unset ( $USER -> switchrole [ $context -> id ]); // Delete old capabilities
2007-03-16 20:21:27 +00:00
load_all_capabilities (); //reload user caps
2006-09-21 09:16:41 +00:00
return true ;
}
/// We're allowed to switch but can we switch to the specified role? Use assignable roles to check.
if ( ! $roles = get_assignable_roles ( $context )) {
return false ;
}
2007-03-16 20:21:27 +00:00
/// unset default user role - it would not work anyway
unset ( $roles [ $CFG -> defaultuserroleid ]);
2006-09-21 09:16:41 +00:00
2007-03-16 20:21:27 +00:00
if ( empty ( $roles [ $roleid ])) { /// We can't switch to this particular role
2006-09-21 09:16:41 +00:00
return false ;
}
/// We have a valid roleid that this user can switch to, so let's set up the session
2006-09-21 15:58:59 +00:00
$USER -> switchrole [ $context -> id ] = $roleid ; // So we know later what state we are in
2006-09-21 09:16:41 +00:00
2007-03-16 20:21:27 +00:00
load_all_capabilities (); //reload switched role caps
2006-09-21 09:16:41 +00:00
2006-09-21 15:58:59 +00:00
/// Add some permissions we are really going to always need, even if the role doesn't have them!
2006-09-21 09:16:41 +00:00
$USER -> capabilities [ $context -> id ][ 'moodle/course:view' ] = CAP_ALLOW ;
return true ;
}
2006-09-21 06:57:14 +00:00
// get any role that has an override on exact context
function get_roles_with_override_on_context ( $context ) {
2006-09-21 22:34:45 +00:00
2006-09-21 06:57:14 +00:00
global $CFG ;
2006-09-21 22:34:45 +00:00
2006-10-20 02:44:22 +00:00
return get_records_sql ( " SELECT r.*
2006-09-21 06:57:14 +00:00
FROM { $CFG -> prefix } role_capabilities rc ,
{ $CFG -> prefix } role r
WHERE rc . roleid = r . id
AND rc . contextid = $context -> id " );
}
// get all capabilities for this role on this context (overrids)
function get_capabilities_from_role_on_context ( $role , $context ) {
2006-09-21 22:34:45 +00:00
2006-09-21 06:57:14 +00:00
global $CFG ;
2006-09-21 22:34:45 +00:00
return get_records_sql ( " SELECT *
2006-09-21 06:57:14 +00:00
FROM { $CFG -> prefix } role_capabilities
WHERE contextid = $context -> id
AND roleid = $role -> id " );
2006-09-21 09:09:16 +00:00
}
2006-09-22 01:46:45 +00:00
// find out which roles has assignment on this context
function get_roles_with_assignment_on_context ( $context ) {
2006-09-23 12:51:00 +00:00
2006-09-22 01:46:45 +00:00
global $CFG ;
2006-09-23 12:51:00 +00:00
2006-10-20 02:44:22 +00:00
return get_records_sql ( " SELECT r.*
2006-09-22 01:46:45 +00:00
FROM { $CFG -> prefix } role_assignments ra ,
{ $CFG -> prefix } role r
WHERE ra . roleid = r . id
AND ra . contextid = $context -> id " );
}
2007-03-05 11:27:01 +00:00
/**
* Find all user assignemnt of users for this role , on this context
2006-09-21 09:09:16 +00:00
*/
function get_users_from_role_on_context ( $role , $context ) {
2006-09-21 22:34:45 +00:00
2006-09-21 09:09:16 +00:00
global $CFG ;
2006-09-21 22:34:45 +00:00
2006-09-21 09:09:16 +00:00
return get_records_sql ( " SELECT *
FROM { $CFG -> prefix } role_assignments
WHERE contextid = $context -> id
2006-09-21 22:34:45 +00:00
AND roleid = $role -> id " );
2006-09-21 09:09:16 +00:00
}
2006-09-21 09:16:41 +00:00
2007-03-05 11:27:01 +00:00
/**
2006-10-04 07:07:57 +00:00
* Simple function returning a boolean true if roles exist , otherwise false
*/
function user_has_role_assignment ( $userid , $roleid , $contextid = 0 ) {
if ( $contextid ) {
return record_exists ( 'role_assignments' , 'userid' , $userid , 'roleid' , $roleid , 'contextid' , $contextid );
} else {
return record_exists ( 'role_assignments' , 'userid' , $userid , 'roleid' , $roleid );
}
}
2007-01-12 07:41:33 +00:00
2007-03-05 11:27:01 +00:00
/**
* Inserts all parental context and self into context_rel table
*
* @ param object $context - context to be deleted
2007-02-26 02:35:00 +00:00
* @ param bool deletechild - deltes child contexts dependencies
*/
2007-03-02 08:09:21 +00:00
function insert_context_rel ( $context , $deletechild = true , $deleteparent = true ) {
2007-03-27 03:04:15 +00:00
// first check validity
// MDL-9057
if ( ! validate_context ( $context -> contextlevel , $context -> instanceid )) {
debugging ( 'Error: Invalid context creation request for level "' . s ( $contextlevel ) . '", instance "' . s ( $instanceid ) . '".' );
return NULL ;
}
2007-02-26 02:35:00 +00:00
// removes all parents
if ( $deletechild ) {
delete_records ( 'context_rel' , 'c2' , $context -> id );
}
2007-03-02 08:09:21 +00:00
if ( $deleteparent ) {
delete_records ( 'context_rel' , 'c1' , $context -> id );
}
2007-01-12 07:41:33 +00:00
// insert all parents
if ( $parents = get_parent_contexts ( $context )) {
$parents [] = $context -> id ;
foreach ( $parents as $parent ) {
$rec = new object ;
$rec -> c1 = $context -> id ;
$rec -> c2 = $parent ;
insert_record ( 'context_rel' , $rec );
}
}
}
2007-03-05 11:27:01 +00:00
/**
* rebuild context_rel table without deleting
*/
2007-01-12 07:41:33 +00:00
function build_context_rel () {
2007-03-02 08:09:21 +00:00
global $db ;
$savedb = $db -> debug ;
// total number of records
$total = count_records ( 'context' );
// processed records
$done = 0 ;
print_progress ( $done , $total , 10 , 0 , 'Processing context relations' );
$db -> debug = false ;
2007-01-12 07:41:33 +00:00
if ( $contexts = get_records ( 'context' )) {
foreach ( $contexts as $context ) {
2007-03-02 08:09:21 +00:00
// no need to delete because it's all empty
insert_context_rel ( $context , false , false );
$db -> debug = true ;
print_progress ( ++ $done , $total , 10 , 0 , 'Processing context relations' );
$db -> debug = false ;
2007-01-12 07:41:33 +00:00
}
2007-03-02 08:09:21 +00:00
}
$db -> debug = $savedb ;
2007-01-12 07:41:33 +00:00
}
2007-03-22 08:11:30 +00:00
// gets the custom name of the role in course
// TODO: proper documentation
function role_get_name ( $role , $context ) {
if ( $r = get_record ( 'role_names' , 'roleid' , $role -> id , 'contextid' , $context -> id )) {
return format_string ( $r -> text );
} else {
return format_string ( $role -> name );
}
}
2007-05-07 08:34:08 +00:00
?>