See Release Notes
Long Term Support Release
Differences Between: [Versions 39 and 401]
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 * Condition main class. 19 * 20 * @package availability_group 21 * @copyright 2014 The Open University 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 25 namespace availability_group; 26 27 defined('MOODLE_INTERNAL') || die(); 28 29 /** 30 * Condition main class. 31 * 32 * @package availability_group 33 * @copyright 2014 The Open University 34 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 35 */ 36 class condition extends \core_availability\condition { 37 /** @var array Array from group id => name */ 38 protected static $groupnames = array(); 39 40 /** @var int ID of group that this condition requires, or 0 = any group */ 41 protected $groupid; 42 43 /** 44 * Constructor. 45 * 46 * @param \stdClass $structure Data structure from JSON decode 47 * @throws \coding_exception If invalid data structure. 48 */ 49 public function __construct($structure) { 50 // Get group id. 51 if (!property_exists($structure, 'id')) { 52 $this->groupid = 0; 53 } else if (is_int($structure->id)) { 54 $this->groupid = $structure->id; 55 } else { 56 throw new \coding_exception('Invalid ->id for group condition'); 57 } 58 } 59 60 public function save() { 61 $result = (object)array('type' => 'group'); 62 if ($this->groupid) { 63 $result->id = $this->groupid; 64 } 65 return $result; 66 } 67 68 public function is_available($not, \core_availability\info $info, $grabthelot, $userid) { 69 $course = $info->get_course(); 70 $context = \context_course::instance($course->id); 71 $allow = true; 72 if (!has_capability('moodle/site:accessallgroups', $context, $userid)) { 73 // Get all groups the user belongs to. 74 $groups = $info->get_modinfo()->get_groups(); 75 if ($this->groupid) { 76 $allow = in_array($this->groupid, $groups); 77 } else { 78 // No specific group. Allow if they belong to any group at all. 79 $allow = $groups ? true : false; 80 } 81 82 // The NOT condition applies before accessallgroups (i.e. if you 83 // set something to be available to those NOT in group X, 84 // people with accessallgroups can still access it even if 85 // they are in group X). 86 if ($not) { 87 $allow = !$allow; 88 } 89 } 90 return $allow; 91 } 92 93 public function get_description($full, $not, \core_availability\info $info) { 94 global $DB; 95 96 if ($this->groupid) { 97 // Need to get the name for the group. Unfortunately this requires 98 // a database query. To save queries, get all groups for course at 99 // once in a static cache. 100 $course = $info->get_course(); 101 if (!array_key_exists($this->groupid, self::$groupnames)) { 102 $coursegroups = $DB->get_records( 103 'groups', array('courseid' => $course->id), '', 'id, name'); 104 foreach ($coursegroups as $rec) { 105 self::$groupnames[$rec->id] = $rec->name; 106 } 107 } 108 109 // If it still doesn't exist, it must have been misplaced. 110 if (!array_key_exists($this->groupid, self::$groupnames)) { 111 $name = get_string('missing', 'availability_group'); 112 } else { 113 // Not safe to call format_string here; use the special function to call it later. 114 $name = self::description_format_string(self::$groupnames[$this->groupid]); 115 } 116 } else { 117 return get_string($not ? 'requires_notanygroup' : 'requires_anygroup', 118 'availability_group'); 119 } 120 121 return get_string($not ? 'requires_notgroup' : 'requires_group', 122 'availability_group', $name); 123 } 124 125 protected function get_debug_string() { 126 return $this->groupid ? '#' . $this->groupid : 'any'; 127 } 128 129 /** 130 * Include this condition only if we are including groups in restore, or 131 * if it's a generic 'same activity' one. 132 * 133 * @param int $restoreid The restore Id. 134 * @param int $courseid The ID of the course. 135 * @param base_logger $logger The logger being used. 136 * @param string $name Name of item being restored. 137 * @param base_task $task The task being performed. 138 * 139 * @return Integer groupid 140 */ 141 public function include_after_restore($restoreid, $courseid, \base_logger $logger, 142 $name, \base_task $task) { 143 return !$this->groupid || $task->get_setting_value('groups'); 144 } 145 146 public function update_after_restore($restoreid, $courseid, \base_logger $logger, $name) { 147 global $DB; 148 if (!$this->groupid) { 149 return false; 150 } 151 $rec = \restore_dbops::get_backup_ids_record($restoreid, 'group', $this->groupid); 152 if (!$rec || !$rec->newitemid) { 153 // If we are on the same course (e.g. duplicate) then we can just 154 // use the existing one. 155 if ($DB->record_exists('groups', 156 array('id' => $this->groupid, 'courseid' => $courseid))) { 157 return false; 158 } 159 // Otherwise it's a warning. 160 $this->groupid = -1; 161 $logger->process('Restored item (' . $name . 162 ') has availability condition on group that was not restored', 163 \backup::LOG_WARNING); 164 } else { 165 $this->groupid = (int)$rec->newitemid; 166 } 167 return true; 168 } 169 170 public function update_dependency_id($table, $oldid, $newid) { 171 if ($table === 'groups' && (int)$this->groupid === (int)$oldid) { 172 $this->groupid = $newid; 173 return true; 174 } else { 175 return false; 176 } 177 } 178 179 /** 180 * Wipes the static cache used to store grouping names. 181 */ 182 public static function wipe_static_cache() { 183 self::$groupnames = array(); 184 } 185 186 public function is_applied_to_user_lists() { 187 // Group conditions are assumed to be 'permanent', so they affect the 188 // display of user lists for activities. 189 return true; 190 } 191 192 public function filter_user_list(array $users, $not, \core_availability\info $info, 193 \core_availability\capability_checker $checker) { 194 global $CFG, $DB; 195 196 // If the array is empty already, just return it. 197 if (!$users) { 198 return $users; 199 } 200 201 require_once($CFG->libdir . '/grouplib.php'); 202 $course = $info->get_course(); 203 204 // List users for this course who match the condition. 205 if ($this->groupid) { 206 $groupusers = groups_get_members($this->groupid, 'u.id', 'u.id ASC'); 207 } else { 208 $groupusers = $DB->get_records_sql(" 209 SELECT DISTINCT gm.userid 210 FROM {groups} g 211 JOIN {groups_members} gm ON gm.groupid = g.id 212 WHERE g.courseid = ?", array($course->id)); 213 } 214 215 // List users who have access all groups. 216 $aagusers = $checker->get_users_by_capability('moodle/site:accessallgroups'); 217 218 // Filter the user list. 219 $result = array(); 220 foreach ($users as $id => $user) { 221 // Always include users with access all groups. 222 if (array_key_exists($id, $aagusers)) { 223 $result[$id] = $user; 224 continue; 225 } 226 // Other users are included or not based on group membership. 227 $allow = array_key_exists($id, $groupusers); 228 if ($not) { 229 $allow = !$allow; 230 } 231 if ($allow) { 232 $result[$id] = $user; 233 } 234 } 235 return $result; 236 } 237 238 /** 239 * Returns a JSON object which corresponds to a condition of this type. 240 * 241 * Intended for unit testing, as normally the JSON values are constructed 242 * by JavaScript code. 243 * 244 * @param int $groupid Required group id (0 = any group) 245 * @return stdClass Object representing condition 246 */ 247 public static function get_json($groupid = 0) { 248 $result = (object)array('type' => 'group'); 249 // Id is only included if set. 250 if ($groupid) { 251 $result->id = (int)$groupid; 252 } 253 return $result; 254 } 255 256 public function get_user_list_sql($not, \core_availability\info $info, $onlyactive) { 257 global $DB; 258 259 // Get enrolled users with access all groups. These always are allowed. 260 list($aagsql, $aagparams) = get_enrolled_sql( 261 $info->get_context(), 'moodle/site:accessallgroups', 0, $onlyactive); 262 263 // Get all enrolled users. 264 list ($enrolsql, $enrolparams) = 265 get_enrolled_sql($info->get_context(), '', 0, $onlyactive); 266 267 // Condition for specified or any group. 268 $matchparams = array(); 269 if ($this->groupid) { 270 $matchsql = "SELECT 1 271 FROM {groups_members} gm 272 WHERE gm.userid = userids.id 273 AND gm.groupid = " . 274 self::unique_sql_parameter($matchparams, $this->groupid); 275 } else { 276 $matchsql = "SELECT 1 277 FROM {groups_members} gm 278 JOIN {groups} g ON g.id = gm.groupid 279 WHERE gm.userid = userids.id 280 AND g.courseid = " . 281 self::unique_sql_parameter($matchparams, $info->get_course()->id); 282 } 283 284 // Overall query combines all this. 285 $condition = $not ? 'NOT' : ''; 286 $sql = "SELECT userids.id 287 FROM ($enrolsql) userids 288 WHERE (userids.id IN ($aagsql)) OR $condition EXISTS ($matchsql)"; 289 return array($sql, array_merge($enrolparams, $aagparams, $matchparams)); 290 } 291 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body