[ Index ] |
PHP Cross Reference of moodle-2.8 |
[Summary view] [Print] [Text view]
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_grouping 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_grouping; 26 27 defined('MOODLE_INTERNAL') || die(); 28 29 /** 30 * Condition main class. 31 * 32 * @package availability_grouping 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 grouping id => name */ 38 protected static $groupingnames = array(); 39 40 /** @var int ID of grouping that this condition requires */ 41 protected $groupingid = 0; 42 43 /** @var bool If true, indicates that activity $cm->grouping is used */ 44 protected $activitygrouping = false; 45 46 /** 47 * Constructor. 48 * 49 * @param \stdClass $structure Data structure from JSON decode 50 * @throws \coding_exception If invalid data structure. 51 */ 52 public function __construct($structure) { 53 // Get grouping id. 54 if (isset($structure->id)) { 55 if (is_int($structure->id)) { 56 $this->groupingid = $structure->id; 57 } else { 58 throw new \coding_exception('Invalid ->id for grouping condition'); 59 } 60 } else if (isset($structure->activity)) { 61 if (is_bool($structure->activity) && $structure->activity) { 62 $this->activitygrouping = true; 63 } else { 64 throw new \coding_exception('Invalid ->activity for grouping condition'); 65 } 66 } else { 67 throw new \coding_exception('Missing ->id / ->activity for grouping condition'); 68 } 69 } 70 71 public function save() { 72 $result = (object)array('type' => 'grouping'); 73 if ($this->groupingid) { 74 $result->id = $this->groupingid; 75 } else { 76 $result->activity = true; 77 } 78 return $result; 79 } 80 81 public function is_available($not, \core_availability\info $info, $grabthelot, $userid) { 82 $context = \context_course::instance($info->get_course()->id); 83 $allow = true; 84 if (!has_capability('moodle/site:accessallgroups', $context, $userid)) { 85 // If the activity has 'group members only' and you don't have accessallgroups... 86 $groups = $info->get_modinfo()->get_groups($this->get_grouping_id($info)); 87 if (!$groups) { 88 // ...and you don't belong to a group, then set it so you can't see/access it. 89 $allow = false; 90 } 91 92 // The NOT condition applies before accessallgroups (i.e. if you 93 // set something to be available to those NOT in grouping X, 94 // people with accessallgroups can still access it even if 95 // they are in grouping X). 96 if ($not) { 97 $allow = !$allow; 98 } 99 } 100 return $allow; 101 } 102 103 /** 104 * Gets the actual grouping id for the condition. This is either a specified 105 * id, or a special flag indicating that we use the one for the current cm. 106 * 107 * @param \core_availability\info $info Info about context cm 108 * @return int Grouping id 109 * @throws \coding_exception If it's set to use a cm but there isn't grouping 110 */ 111 protected function get_grouping_id(\core_availability\info $info) { 112 if ($this->activitygrouping) { 113 $groupingid = $info->get_course_module()->groupingid; 114 if (!$groupingid) { 115 throw new \coding_exception( 116 'Not supposed to be able to turn on activitygrouping when no grouping'); 117 } 118 return $groupingid; 119 } else { 120 return $this->groupingid; 121 } 122 } 123 124 public function get_description($full, $not, \core_availability\info $info) { 125 global $DB; 126 $course = $info->get_course(); 127 128 // Need to get the name for the grouping. Unfortunately this requires 129 // a database query. To save queries, get all groupings for course at 130 // once in a static cache. 131 $groupingid = $this->get_grouping_id($info); 132 if (!array_key_exists($groupingid, self::$groupingnames)) { 133 $coursegroupings = $DB->get_records( 134 'groupings', array('courseid' => $course->id), '', 'id, name'); 135 foreach ($coursegroupings as $rec) { 136 self::$groupingnames[$rec->id] = $rec->name; 137 } 138 } 139 140 // If it still doesn't exist, it must have been misplaced. 141 if (!array_key_exists($groupingid, self::$groupingnames)) { 142 $name = get_string('missing', 'availability_grouping'); 143 } else { 144 $context = \context_course::instance($course->id); 145 $name = format_string(self::$groupingnames[$groupingid], true, 146 array('context' => $context)); 147 } 148 149 return get_string($not ? 'requires_notgrouping' : 'requires_grouping', 150 'availability_grouping', $name); 151 } 152 153 protected function get_debug_string() { 154 if ($this->activitygrouping) { 155 return 'CM'; 156 } else { 157 return '#' . $this->groupingid; 158 } 159 } 160 161 public function update_after_restore($restoreid, $courseid, \base_logger $logger, $name) { 162 global $DB; 163 if (!$this->groupingid) { 164 // If using 'same as activity' option, no need to change it. 165 return false; 166 } 167 $rec = \restore_dbops::get_backup_ids_record($restoreid, 'grouping', $this->groupingid); 168 if (!$rec || !$rec->newitemid) { 169 // If we are on the same course (e.g. duplicate) then we can just 170 // use the existing one. 171 if ($DB->record_exists('groupings', 172 array('id' => $this->groupingid, 'courseid' => $courseid))) { 173 return false; 174 } 175 // Otherwise it's a warning. 176 $this->groupingid = -1; 177 $logger->process('Restored item (' . $name . 178 ') has availability condition on grouping that was not restored', 179 \backup::LOG_WARNING); 180 } else { 181 $this->groupingid = (int)$rec->newitemid; 182 } 183 return true; 184 } 185 186 public function update_dependency_id($table, $oldid, $newid) { 187 if ($table === 'groupings' && (int)$this->groupingid === (int)$oldid) { 188 $this->groupingid = $newid; 189 return true; 190 } else { 191 return false; 192 } 193 } 194 195 /** 196 * Wipes the static cache used to store grouping names. 197 */ 198 public static function wipe_static_cache() { 199 self::$groupingnames = array(); 200 } 201 202 public function is_applied_to_user_lists() { 203 // Grouping conditions are assumed to be 'permanent', so they affect the 204 // display of user lists for activities. 205 return true; 206 } 207 208 public function filter_user_list(array $users, $not, \core_availability\info $info, 209 \core_availability\capability_checker $checker) { 210 global $CFG, $DB; 211 212 // If the array is empty already, just return it. 213 if (!$users) { 214 return $users; 215 } 216 217 // List users for this course who match the condition. 218 $groupingusers = $DB->get_records_sql(" 219 SELECT DISTINCT gm.userid 220 FROM {groupings_groups} gg 221 JOIN {groups_members} gm ON gm.groupid = gg.groupid 222 WHERE gg.groupingid = ?", 223 array($this->get_grouping_id($info))); 224 225 // List users who have access all groups. 226 $aagusers = $checker->get_users_by_capability('moodle/site:accessallgroups'); 227 228 // Filter the user list. 229 $result = array(); 230 foreach ($users as $id => $user) { 231 // Always include users with access all groups. 232 if (array_key_exists($id, $aagusers)) { 233 $result[$id] = $user; 234 continue; 235 } 236 // Other users are included or not based on grouping membership. 237 $allow = array_key_exists($id, $groupingusers); 238 if ($not) { 239 $allow = !$allow; 240 } 241 if ($allow) { 242 $result[$id] = $user; 243 } 244 } 245 return $result; 246 } 247 248 /** 249 * Returns a JSON object which corresponds to a condition of this type. 250 * 251 * Intended for unit testing, as normally the JSON values are constructed 252 * by JavaScript code. 253 * 254 * @param int $groupingid Required grouping id (0 = grouping linked to activity) 255 * @return stdClass Object representing condition 256 */ 257 public static function get_json($groupingid = 0) { 258 $result = (object)array('type' => 'grouping'); 259 if ($groupingid) { 260 $result->id = (int)$groupingid; 261 } else { 262 $result->activity = true; 263 } 264 return $result; 265 } 266 267 public function get_user_list_sql($not, \core_availability\info $info, $onlyactive) { 268 global $DB; 269 270 // Get enrolled users with access all groups. These always are allowed. 271 list($aagsql, $aagparams) = get_enrolled_sql( 272 $info->get_context(), 'moodle/site:accessallgroups', 0, $onlyactive); 273 274 // Get all enrolled users. 275 list ($enrolsql, $enrolparams) = 276 get_enrolled_sql($info->get_context(), '', 0, $onlyactive); 277 278 // Condition for specified or any group. 279 $matchparams = array(); 280 $matchsql = "SELECT 1 281 FROM {groups_members} gm 282 JOIN {groupings_groups} gg ON gg.groupid = gm.groupid 283 WHERE gm.userid = userids.id 284 AND gg.groupingid = " . 285 self::unique_sql_parameter($matchparams, $this->get_grouping_id($info)); 286 287 // Overall query combines all this. 288 $condition = $not ? 'NOT' : ''; 289 $sql = "SELECT userids.id 290 FROM ($enrolsql) userids 291 WHERE (userids.id IN ($aagsql)) OR $condition EXISTS ($matchsql)"; 292 return array($sql, array_merge($enrolparams, $aagparams, $matchparams)); 293 } 294 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 20:29:05 2014 | Cross-referenced by PHPXref 0.7.1 |