MDL-59369 enrol: Introduce data-action attribute for enrol action links
[moodle.git] / user / classes / participants_table.php
CommitLineData
bc47b706
MN
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 * Contains the class used for the displaying the participants table.
19 *
20 * @package core_user
21 * @copyright 2017 Mark Nelson <markn@moodle.com>
22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 */
24
25namespace core_user;
26
fb792967
JP
27use context;
28use DateTime;
29use html_writer;
30
bc47b706
MN
31defined('MOODLE_INTERNAL') || die;
32
33global $CFG;
34
35require_once($CFG->libdir . '/tablelib.php');
36require_once($CFG->dirroot . '/user/lib.php');
37
38/**
39 * Class for the displaying the participants table.
40 *
41 * @package core_user
42 * @copyright 2017 Mark Nelson <markn@moodle.com>
43 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
44 */
45class participants_table extends \table_sql {
46
47 /**
48 * @var int $courseid The course id
49 */
50 protected $courseid;
51
52 /**
53 * @var int|false False if groups not used, int if groups used, 0 for all groups.
54 */
55 protected $currentgroup;
56
57 /**
58 * @var int $accesssince The time the user last accessed the site
59 */
60 protected $accesssince;
61
62 /**
63 * @var int $roleid The role we are including, 0 means all enrolled users
64 */
65 protected $roleid;
66
67 /**
68 * @var string $search The string being searched.
69 */
70 protected $search;
71
72 /**
73 * @var bool $selectall Has the user selected all users on the page?
74 */
75 protected $selectall;
76
77 /**
78 * @var string[] The list of countries.
79 */
80 protected $countries;
81
2fa35b8d 82 /**
f3ecea3a 83 * @var \stdClass[] The list of groups with membership info for the course.
2fa35b8d
DW
84 */
85 protected $groups;
86
bc47b706
MN
87 /**
88 * @var string[] Extra fields to display.
89 */
90 protected $extrafields;
91
2fa35b8d 92 /**
fb792967 93 * @var \stdClass $course The course details.
2fa35b8d
DW
94 */
95 protected $course;
96
97 /**
fb792967 98 * @var context $context The course context.
2fa35b8d
DW
99 */
100 protected $context;
101
73d0d562
DW
102 /**
103 * @var \stdClass[] List of roles indexed by roleid.
104 */
105 protected $allroles;
106
107 /**
108 * @var \stdClass[] Assignable roles in this course.
109 */
110 protected $assignableroles;
111
bc47b706
MN
112 /**
113 * Sets up the table.
114 *
115 * @param int $courseid
116 * @param int|false $currentgroup False if groups not used, int if groups used, 0 for all groups.
117 * @param int $accesssince The time the user last accessed the site
118 * @param int $roleid The role we are including, 0 means all enrolled users
119 * @param string $search The string being searched
120 * @param bool $bulkoperations Is the user allowed to perform bulk operations?
121 * @param bool $selectall Has the user selected all users on the page?
122 */
123 public function __construct($courseid, $currentgroup, $accesssince, $roleid, $search,
124 $bulkoperations, $selectall) {
125 global $CFG;
126
127 parent::__construct('user-index-participants-' . $courseid);
128
129 // Get the context.
2fa35b8d 130 $this->course = get_course($courseid);
bc47b706 131 $context = \context_course::instance($courseid, MUST_EXIST);
fb792967 132 $this->context = $context;
bc47b706
MN
133
134 // Define the headers and columns.
135 $headers = [];
136 $columns = [];
137
138 if ($bulkoperations) {
139 $headers[] = get_string('select');
140 $columns[] = 'select';
141 }
142
143 $headers[] = get_string('fullname');
144 $columns[] = 'fullname';
145
146 $extrafields = get_extra_user_fields($context);
147 foreach ($extrafields as $field) {
148 $headers[] = get_user_field_name($field);
149 $columns[] = $field;
150 }
151
5d0b4765
DW
152 $headers[] = get_string('roles');
153 $columns[] = 'roles';
154
2fa35b8d 155 // Load and cache the course groupinfo.
2fa35b8d
DW
156 // Add column for groups.
157 $headers[] = get_string('groups');
158 $columns[] = 'groups';
159
bc47b706
MN
160 // Get the list of fields we have to hide.
161 $hiddenfields = array();
162 if (!has_capability('moodle/course:viewhiddenuserfields', $context)) {
163 $hiddenfields = array_flip(explode(',', $CFG->hiddenuserfields));
164 }
165
166 // Do not show the columns if it exists in the hiddenfields array.
bc47b706
MN
167 if (!isset($hiddenfields['lastaccess'])) {
168 if ($courseid == SITEID) {
169 $headers[] = get_string('lastsiteaccess');
170 } else {
171 $headers[] = get_string('lastcourseaccess');
172 }
173 $columns[] = 'lastaccess';
174 }
175
fb792967
JP
176 $canreviewenrol = has_capability('moodle/course:enrolreview', $context);
177 if ($canreviewenrol) {
178 $columns[] = 'status';
179 $headers[] = get_string('participationstatus', 'enrol');
180 $this->no_sorting('status');
181 };
182
bc47b706
MN
183 $this->define_columns($columns);
184 $this->define_headers($headers);
185
f7cd3bc0
JP
186 // Make this table sorted by first name by default.
187 $this->sortable(true, 'firstname');
188
bc47b706
MN
189 $this->no_sorting('select');
190
191 $this->set_attribute('id', 'participants');
192
193 // Set the variables we need to use later.
bc47b706
MN
194 $this->currentgroup = $currentgroup;
195 $this->accesssince = $accesssince;
196 $this->roleid = $roleid;
197 $this->search = $search;
198 $this->selectall = $selectall;
199 $this->countries = get_string_manager()->get_list_of_countries();
200 $this->extrafields = $extrafields;
f3ecea3a
DW
201 $this->context = $context;
202 $this->groups = groups_get_all_groups($courseid, 0, 0, 'g.*', true);
5d0b4765
DW
203 $this->allroles = role_fix_names(get_all_roles($this->context), $this->context);
204 $this->assignableroles = get_assignable_roles($this->context, ROLENAME_ALIAS, false);
bc47b706
MN
205 }
206
207 /**
208 * Generate the select column.
209 *
210 * @param \stdClass $data
211 * @return string
212 */
213 public function col_select($data) {
214 if ($this->selectall) {
215 $checked = 'checked="true"';
216 } else {
217 $checked = '';
218 }
219 return '<input type="checkbox" class="usercheckbox" name="user' . $data->id . '" ' . $checked . '/>';
220 }
221
222 /**
223 * Generate the fullname column.
224 *
225 * @param \stdClass $data
226 * @return string
227 */
228 public function col_fullname($data) {
229 global $OUTPUT;
230
c5d59db9 231 return $OUTPUT->user_picture($data, array('size' => 35, 'courseid' => $this->course->id, 'includefullname' => true));
bc47b706
MN
232 }
233
5d0b4765
DW
234 /**
235 * User roles column.
236 *
237 * @param \stdClass $data
238 * @return string
239 */
240 public function col_roles($data) {
241 global $OUTPUT;
242
243 $roles = get_user_roles($this->context, $data->id, true, 'c.contextlevel DESC, r.sortorder ASC');
244 $getrole = function($role) {
245 return $role->roleid;
246 };
73d0d562 247 $ids = array_values(array_unique(array_map($getrole, $roles)));
5d0b4765
DW
248
249 $editable = new \core_user\output\user_roles_editable($this->course,
250 $this->context,
251 $data,
252 $this->allroles,
253 $this->assignableroles,
254 $ids);
255
256 return $OUTPUT->render_from_template('core/inplace_editable', $editable->export_for_template($OUTPUT));
257 }
258
2fa35b8d
DW
259 /**
260 * Generate the groups column.
261 *
f3ecea3a 262 * @param \stdClass $data
2fa35b8d
DW
263 * @return string
264 */
f3ecea3a 265 public function col_groups($data) {
2fa35b8d
DW
266 global $OUTPUT;
267
268 $usergroups = [];
269 foreach ($this->groups as $coursegroup) {
f3ecea3a 270 if (isset($coursegroup->members[$data->id])) {
2fa35b8d
DW
271 $usergroups[] = $coursegroup->id;
272 }
273 }
f3ecea3a 274 $editable = new \core_group\output\user_groups_editable($this->course, $this->context, $data, $this->groups, $usergroups);
2fa35b8d
DW
275 return $OUTPUT->render_from_template('core/inplace_editable', $editable->export_for_template($OUTPUT));
276 }
277
bc47b706
MN
278 /**
279 * Generate the country column.
280 *
281 * @param \stdClass $data
282 * @return string
283 */
284 public function col_country($data) {
285 if (!empty($this->countries[$data->country])) {
286 return $this->countries[$data->country];
287 }
288 return '';
289 }
290
291 /**
292 * Generate the last access column.
293 *
294 * @param \stdClass $data
295 * @return string
296 */
297 public function col_lastaccess($data) {
298 if ($data->lastaccess) {
299 return format_time(time() - $data->lastaccess);
300 }
301
302 return get_string('never');
303 }
304
fb792967
JP
305 /**
306 * Generate the status column.
307 *
308 * @param stdClass $data The data object.
309 * @return string
310 */
311 public function col_status($data) {
312 global $CFG, $OUTPUT, $PAGE;
313
314 $enrolstatusoutput = '';
315 $canreviewenrol = has_capability('moodle/course:enrolreview', $this->context);
316 if ($canreviewenrol) {
317 $fullname = fullname($data);
318 require_once($CFG->dirroot . '/enrol/locallib.php');
319 $manager = new \course_enrolment_manager($PAGE, $this->course);
320 $userenrolments = $manager->get_user_enrolments($data->id);
321 foreach ($userenrolments as $ue) {
322 $enrolactions = $ue->enrolmentplugin->get_user_enrolment_actions($manager, $ue);
323 $timestart = $ue->timestart;
324 $timeend = $ue->timeend;
325 $status = '';
326 $dimmed = '';
327 switch ($ue->status) {
328 case ENROL_USER_ACTIVE:
329 $currentdate = new DateTime();
330 $now = $currentdate->getTimestamp();
331 if ($timestart <= $now && ($timeend == 0 || $timeend >= $now)) {
332 $status = get_string('participationactive', 'enrol');
333 } else {
334 $status = get_string('participationnotcurrent', 'enrol');
335 $dimmed = 'dimmed_text';
336 }
337 break;
338 case ENROL_USER_SUSPENDED:
339 $status = get_string('participationsuspended', 'enrol');
340 $dimmed = 'dimmed_text';
341 break;
342 }
343 $statusout = html_writer::span($status, $dimmed, ['title' => "{$ue->enrolmentinstancename}: {$status}"]);
344 $enrolactionsout = '';
345 foreach ($enrolactions as $action) {
346 $icon = $OUTPUT->render($action->get_icon());
347 $attributes = $action->get_attributes();
348 $attributes['data-fullname'] = $fullname;
349 $attributes['data-coursename'] = $this->course->fullname;
350 $enrolactionsout .= html_writer::link($action->get_url(), $icon, $attributes);
351 }
352 $enrolstatusoutput .= html_writer::div($statusout . $enrolactionsout);
353 }
354 }
355 return $enrolstatusoutput;
356 }
357
bc47b706
MN
358 /**
359 * This function is used for the extra user fields.
360 *
361 * These are being dynamically added to the table so there are no functions 'col_<userfieldname>' as
362 * the list has the potential to increase in the future and we don't want to have to remember to add
363 * a new method to this class. We also don't want to pollute this class with unnecessary methods.
364 *
365 * @param string $colname The column name
366 * @param \stdClass $data
367 * @return string
368 */
369 public function other_cols($colname, $data) {
370 // Do not process if it is not a part of the extra fields.
371 if (!in_array($colname, $this->extrafields)) {
372 return '';
373 }
374
375 return s($data->{$colname});
376 }
377
378 /**
379 * Query the database for results to display in the table.
380 *
381 * @param int $pagesize size of page for paginated displayed table.
382 * @param bool $useinitialsbar do you want to use the initials bar.
383 */
384 public function query_db($pagesize, $useinitialsbar = true) {
385 list($twhere, $tparams) = $this->get_sql_where();
386
f3ecea3a 387 $total = user_get_total_participants($this->course->id, $this->currentgroup, $this->accesssince,
bc47b706
MN
388 $this->roleid, $this->search, $twhere, $tparams);
389
390 $this->pagesize($pagesize, $total);
391
392 $sort = $this->get_sql_sort();
393 if ($sort) {
394 $sort = 'ORDER BY ' . $sort;
395 }
396
f3ecea3a 397 $this->rawdata = user_get_participants($this->course->id, $this->currentgroup, $this->accesssince,
bc47b706
MN
398 $this->roleid, $this->search, $twhere, $tparams, $sort, $this->get_page_start(),
399 $this->get_page_size());
400
401 // Set initial bars.
402 if ($useinitialsbar) {
403 $this->initialbars(true);
404 }
405 }
406}
407