1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 /** 18 * Local stuff for category enrolment plugin. 19 * 20 * @package enrol_category 21 * @copyright 2010 Petr Skoda {@link http://skodak.org} 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 25 defined('MOODLE_INTERNAL') || die(); 26 27 28 /** 29 * Event handler for category enrolment plugin. 30 * 31 * We try to keep everything in sync via listening to events, 32 * it may fail sometimes, so we always do a full sync in cron too. 33 */ 34 class enrol_category_observer { 35 /** 36 * Triggered when user is assigned a new role. 37 * 38 * @param \core\event\role_assigned $event 39 */ 40 public static function role_assigned(\core\event\role_assigned $event) { 41 global $DB; 42 43 if (!enrol_is_enabled('category')) { 44 return; 45 } 46 47 $ra = new stdClass(); 48 $ra->roleid = $event->objectid; 49 $ra->userid = $event->relateduserid; 50 $ra->contextid = $event->contextid; 51 52 //only category level roles are interesting 53 $parentcontext = context::instance_by_id($ra->contextid); 54 if ($parentcontext->contextlevel != CONTEXT_COURSECAT) { 55 return; 56 } 57 58 // Make sure the role is to be actually synchronised, 59 // please note we are ignoring overrides of the synchronised capability (for performance reasons in full sync). 60 $syscontext = context_system::instance(); 61 if (!$DB->record_exists('role_capabilities', array('contextid'=>$syscontext->id, 'roleid'=>$ra->roleid, 'capability'=>'enrol/category:synchronised', 'permission'=>CAP_ALLOW))) { 62 return; 63 } 64 65 // Add necessary enrol instances. 66 $plugin = enrol_get_plugin('category'); 67 $sql = "SELECT c.* 68 FROM {course} c 69 JOIN {context} ctx ON (ctx.instanceid = c.id AND ctx.contextlevel = :courselevel AND ctx.path LIKE :match) 70 LEFT JOIN {enrol} e ON (e.courseid = c.id AND e.enrol = 'category') 71 WHERE e.id IS NULL"; 72 $params = array('courselevel'=>CONTEXT_COURSE, 'match'=>$parentcontext->path.'/%'); 73 $rs = $DB->get_recordset_sql($sql, $params); 74 foreach ($rs as $course) { 75 $plugin->add_instance($course); 76 } 77 $rs->close(); 78 79 // Now look for missing enrolments. 80 $sql = "SELECT e.* 81 FROM {course} c 82 JOIN {context} ctx ON (ctx.instanceid = c.id AND ctx.contextlevel = :courselevel AND ctx.path LIKE :match) 83 JOIN {enrol} e ON (e.courseid = c.id AND e.enrol = 'category') 84 LEFT JOIN {user_enrolments} ue ON (ue.enrolid = e.id AND ue.userid = :userid) 85 WHERE ue.id IS NULL"; 86 $params = array('courselevel'=>CONTEXT_COURSE, 'match'=>$parentcontext->path.'/%', 'userid'=>$ra->userid); 87 $rs = $DB->get_recordset_sql($sql, $params); 88 foreach ($rs as $instance) { 89 $plugin->enrol_user($instance, $ra->userid, null, time()); 90 } 91 $rs->close(); 92 } 93 94 /** 95 * Triggered when user role is unassigned. 96 * 97 * @param \core\event\role_unassigned $event 98 */ 99 public static function role_unassigned(\core\event\role_unassigned $event) { 100 global $DB; 101 102 if (!enrol_is_enabled('category')) { 103 return; 104 } 105 106 $ra = new stdClass(); 107 $ra->userid = $event->relateduserid; 108 $ra->contextid = $event->contextid; 109 110 // only category level roles are interesting 111 $parentcontext = context::instance_by_id($ra->contextid); 112 if ($parentcontext->contextlevel != CONTEXT_COURSECAT) { 113 return; 114 } 115 116 // Now this is going to be a bit slow, take all enrolments in child courses and verify each separately. 117 $syscontext = context_system::instance(); 118 if (!$roles = get_roles_with_capability('enrol/category:synchronised', CAP_ALLOW, $syscontext)) { 119 return; 120 } 121 122 $plugin = enrol_get_plugin('category'); 123 124 $sql = "SELECT e.* 125 FROM {course} c 126 JOIN {context} ctx ON (ctx.instanceid = c.id AND ctx.contextlevel = :courselevel AND ctx.path LIKE :match) 127 JOIN {enrol} e ON (e.courseid = c.id AND e.enrol = 'category') 128 JOIN {user_enrolments} ue ON (ue.enrolid = e.id AND ue.userid = :userid)"; 129 $params = array('courselevel'=>CONTEXT_COURSE, 'match'=>$parentcontext->path.'/%', 'userid'=>$ra->userid); 130 $rs = $DB->get_recordset_sql($sql, $params); 131 132 list($roleids, $params) = $DB->get_in_or_equal(array_keys($roles), SQL_PARAMS_NAMED, 'r'); 133 $params['userid'] = $ra->userid; 134 135 foreach ($rs as $instance) { 136 $coursecontext = context_course::instance($instance->courseid); 137 $contextids = $coursecontext->get_parent_context_ids(); 138 array_pop($contextids); // Remove system context, we are interested in categories only. 139 140 list($contextids, $contextparams) = $DB->get_in_or_equal($contextids, SQL_PARAMS_NAMED, 'c'); 141 $params = array_merge($params, $contextparams); 142 143 $sql = "SELECT ra.id 144 FROM {role_assignments} ra 145 WHERE ra.userid = :userid AND ra.contextid $contextids AND ra.roleid $roleids"; 146 if (!$DB->record_exists_sql($sql, $params)) { 147 // User does not have any interesting role in any parent context, let's unenrol. 148 $plugin->unenrol_user($instance, $ra->userid); 149 } 150 } 151 $rs->close(); 152 } 153 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body