See Release Notes
Long Term Support Release
Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 400 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 * Class for rendering user filters on the course participants page. 19 * 20 * @package core_user 21 * @copyright 2020 Michael Hawkins <michaelh@moodle.com> 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 namespace core_user\output; 25 26 use core_user\fields; 27 use renderer_base; 28 use stdClass; 29 30 /** 31 * Class for rendering user filters on the course participants page. 32 * 33 * @copyright 2020 Michael Hawkins <michaelh@moodle.com> 34 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 35 */ 36 class participants_filter extends \core\output\datafilter { 37 38 /** 39 * Get data for all filter types. 40 * 41 * @return array 42 */ 43 protected function get_filtertypes(): array { 44 $filtertypes = []; 45 46 $filtertypes[] = $this->get_keyword_filter(); 47 48 if ($filtertype = $this->get_enrolmentstatus_filter()) { 49 $filtertypes[] = $filtertype; 50 } 51 52 if ($filtertype = $this->get_roles_filter()) { 53 $filtertypes[] = $filtertype; 54 } 55 56 if ($filtertype = $this->get_enrolments_filter()) { 57 $filtertypes[] = $filtertype; 58 } 59 60 if ($filtertype = $this->get_groups_filter()) { 61 $filtertypes[] = $filtertype; 62 } 63 64 if ($filtertype = $this->get_accesssince_filter()) { 65 $filtertypes[] = $filtertype; 66 } 67 68 if ($filtertype = $this->get_country_filter()) { 69 $filtertypes[] = $filtertype; 70 } 71 72 return $filtertypes; 73 } 74 75 /** 76 * Get data for the enrolment status filter. 77 * 78 * @return stdClass|null 79 */ 80 protected function get_enrolmentstatus_filter(): ?stdClass { 81 if (!has_capability('moodle/course:enrolreview', $this->context)) { 82 return null; 83 } 84 85 return $this->get_filter_object( 86 'status', 87 get_string('participationstatus', 'core_enrol'), 88 false, 89 true, 90 null, 91 [ 92 (object) [ 93 'value' => ENROL_USER_ACTIVE, 94 'title' => get_string('active'), 95 ], 96 (object) [ 97 'value' => ENROL_USER_SUSPENDED, 98 'title' => get_string('inactive'), 99 ], 100 ] 101 ); 102 } 103 104 /** 105 * Get data for the roles filter. 106 * 107 * @return stdClass|null 108 */ 109 protected function get_roles_filter(): ?stdClass { 110 $roles = []; 111 $roles += [-1 => get_string('noroles', 'role')]; 112 $roles += get_viewable_roles($this->context, null, ROLENAME_BOTH); 113 114 if (has_capability('moodle/role:assign', $this->context)) { 115 $roles += get_assignable_roles($this->context, ROLENAME_BOTH); 116 } 117 118 return $this->get_filter_object( 119 'roles', 120 get_string('roles', 'core_role'), 121 false, 122 true, 123 null, 124 array_map(function($id, $title) { 125 return (object) [ 126 'value' => $id, 127 'title' => $title, 128 ]; 129 }, array_keys($roles), array_values($roles)) 130 ); 131 } 132 133 /** 134 * Get data for the roles filter. 135 * 136 * @return stdClass|null 137 */ 138 protected function get_enrolments_filter(): ?stdClass { 139 if (!has_capability('moodle/course:enrolreview', $this->context)) { 140 return null; 141 } 142 143 if ($this->course->id == SITEID) { 144 // No enrolment methods for the site. 145 return null; 146 } 147 148 $instances = enrol_get_instances($this->course->id, true); 149 $plugins = enrol_get_plugins(false); 150 151 return $this->get_filter_object( 152 'enrolments', 153 get_string('enrolmentinstances', 'core_enrol'), 154 false, 155 true, 156 null, 157 array_filter(array_map(function($instance) use ($plugins): ?stdClass { 158 if (!array_key_exists($instance->enrol, $plugins)) { 159 return null; 160 } 161 162 return (object) [ 163 'value' => $instance->id, 164 'title' => $plugins[$instance->enrol]->get_instance_name($instance), 165 ]; 166 }, array_values($instances))) 167 ); 168 } 169 170 /** 171 * Get data for the groups filter. 172 * 173 * @return stdClass|null 174 */ 175 protected function get_groups_filter(): ?stdClass { 176 global $USER; 177 178 // Filter options for groups, if available. 179 $seeallgroups = has_capability('moodle/site:accessallgroups', $this->context); 180 $seeallgroups = $seeallgroups || ($this->course->groupmode != SEPARATEGROUPS); 181 if ($seeallgroups) { 182 $groups = []; 183 $groups += [USERSWITHOUTGROUP => (object) [ 184 'id' => USERSWITHOUTGROUP, 185 'name' => get_string('nogroup', 'group'), 186 ]]; 187 $groups += groups_get_all_groups($this->course->id); 188 } else { 189 // Otherwise, just list the groups the user belongs to. 190 $groups = groups_get_all_groups($this->course->id, $USER->id); 191 } 192 193 // Return no data if no groups found (which includes if the only value is 'No group'). 194 if (empty($groups) || (count($groups) === 1 && array_key_exists(-1, $groups))) { 195 return null; 196 } 197 198 return $this->get_filter_object( 199 'groups', 200 get_string('groups', 'core_group'), 201 false, 202 true, 203 null, 204 array_map(function($group) { 205 return (object) [ 206 'value' => $group->id, 207 'title' => format_string($group->name, true, ['context' => $this->context]), 208 ]; 209 }, array_values($groups)) 210 ); 211 } 212 213 /** 214 * Get data for the accesssince filter. 215 * 216 * @return stdClass|null 217 */ 218 protected function get_accesssince_filter(): ?stdClass { 219 global $CFG, $DB; 220 221 $hiddenfields = []; 222 if (!has_capability('moodle/course:viewhiddenuserfields', $this->context)) { 223 $hiddenfields = array_flip(explode(',', $CFG->hiddenuserfields)); 224 } 225 226 if (array_key_exists('lastaccess', $hiddenfields)) { 227 return null; 228 } 229 230 // Get minimum lastaccess for this course and display a dropbox to filter by lastaccess going back this far. 231 // We need to make it diferently for normal courses and site course. 232 if (!$this->course->id == SITEID) { 233 // Regular course. 234 $params = [ 235 'courseid' => $this->course->id, 236 'timeaccess' => 0, 237 ]; 238 $select = 'courseid = :courseid AND timeaccess != :timeaccess'; 239 $minlastaccess = $DB->get_field_select('user_lastaccess', 'MIN(timeaccess)', $select, $params); 240 $lastaccess0exists = $DB->record_exists('user_lastaccess', $params); 241 } else { 242 // Front page. 243 $params = ['lastaccess' => 0]; 244 $select = 'lastaccess != :lastaccess'; 245 $minlastaccess = $DB->get_field_select('user', 'MIN(lastaccess)', $select, $params); 246 $lastaccess0exists = $DB->record_exists('user', $params); 247 } 248 249 $now = usergetmidnight(time()); 250 $timeoptions = []; 251 $criteria = get_string('usersnoaccesssince'); 252 253 $getoptions = function(int $count, string $singletype, string $type) use ($now, $minlastaccess): array { 254 $values = []; 255 for ($i = 1; $i <= $count; $i++) { 256 $timestamp = strtotime("-{$i} {$type}", $now); 257 if ($timestamp < $minlastaccess) { 258 break; 259 } 260 261 if ($i === 1) { 262 $title = get_string("num{$singletype}", 'moodle', $i); 263 } else { 264 $title = get_string("num{$type}", 'moodle', $i); 265 } 266 267 $values[] = [ 268 'value' => $timestamp, 269 'title' => $title, 270 ]; 271 } 272 273 return $values; 274 }; 275 276 $values = array_merge( 277 $getoptions(6, 'day', 'days'), 278 $getoptions(10, 'week', 'weeks'), 279 $getoptions(11, 'month', 'months'), 280 $getoptions(1, 'year', 'years') 281 ); 282 283 if ($lastaccess0exists) { 284 $values[] = [ 285 'value' => time(), 286 'title' => get_string('never', 'moodle'), 287 ]; 288 } 289 290 if (count($values) <= 1) { 291 // Nothing to show. 292 return null; 293 } 294 295 return $this->get_filter_object( 296 'accesssince', 297 get_string('usersnoaccesssince'), 298 false, 299 false, 300 null, 301 $values 302 ); 303 } 304 305 /** 306 * Get data for the country filter 307 * 308 * @return stdClass|null 309 */ 310 protected function get_country_filter(): ?stdClass { 311 $extrauserfields = fields::get_identity_fields($this->context, false); 312 if (array_search('country', $extrauserfields) === false) { 313 return null; 314 } 315 316 $countries = get_string_manager()->get_list_of_countries(true); 317 318 return $this->get_filter_object( 319 'country', 320 get_string('country'), 321 false, 322 true, 323 'core/datafilter/filtertypes/country', 324 array_map(function(string $code, string $name): stdClass { 325 return (object) [ 326 'value' => $code, 327 'title' => $name, 328 ]; 329 }, array_keys($countries), array_values($countries)) 330 ); 331 } 332 333 /** 334 * Get data for the keywords filter. 335 * 336 * @return stdClass|null 337 */ 338 protected function get_keyword_filter(): ?stdClass { 339 return $this->get_filter_object( 340 'keywords', 341 get_string('filterbykeyword', 'core_user'), 342 true, 343 true, 344 'core/datafilter/filtertypes/keyword', 345 [], 346 true 347 ); 348 } 349 350 /** 351 * Export the renderer data in a mustache template friendly format. 352 * 353 * @param renderer_base $output Unused. 354 * @return stdClass Data in a format compatible with a mustache template. 355 */ 356 public function export_for_template(renderer_base $output): stdClass { 357 return (object) [ 358 'tableregionid' => $this->tableregionid, 359 'courseid' => $this->context->instanceid, 360 'filtertypes' => $this->get_filtertypes(), 361 'rownumber' => 1, 362 ]; 363 364 return $data; 365 } 366 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body