Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 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    mod_reengagement
21
 * @copyright  2018 Catalyst IT
22
 * @author     Dan Marsden <Dan@danmarsden.com>
23
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24
 */
25
 
26
namespace mod_reengagement\table;
27
 
28
use context;
29
use context_module;
30
use core_table\dynamic as dynamic_table;
31
use core_table\local\filter\filterset;
32
use core_user\output\status_field;
33
use DateTime;
34
use moodle_url;
35
 
36
defined('MOODLE_INTERNAL') || die;
37
 
38
global $CFG;
39
 
40
require_once($CFG->libdir . '/tablelib.php');
41
require_once($CFG->dirroot . '/user/lib.php');
42
 
43
/**
44
 * Class for the displaying the participants table.
45
 *
46
 * @package    mod_reengagement
47
 * @copyright  2018 Catalyst IT
48
 * @author     Dan Marsden <Dan@danmarsden.com>
49
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
50
 */
51
class reengagement_participants extends \table_sql implements dynamic_table {
52
 
53
    /**
54
     * @var \stdclass $reengagement The reengagement record
55
     */
56
    protected $reengagement;
57
 
58
    /**
59
     * @var int $cmid The course module id
60
     */
61
    protected $cmid;
62
 
63
    /**
64
     * @var int $courseid The course id
65
     */
66
    protected $courseid;
67
 
68
    /**
69
     * @var int|false False if groups not used, int if groups used, 0 for all groups.
70
     */
71
    protected $currentgroup;
72
 
73
    /**
74
     * @var int $roleid The role we are including, 0 means all enrolled users
75
     */
76
    protected $roleid;
77
 
78
    /**
79
     * @var int $enrolid The applied filter for the user enrolment ID.
80
     */
81
    protected $enrolid;
82
 
83
    /**
84
     * @var int $status The applied filter for the user's enrolment status.
85
     */
86
    protected $status;
87
 
88
    /**
89
     * @var string $search The string being searched.
90
     */
91
    protected $search;
92
 
93
    /**
94
     * @var bool $selectall Has the user selected all users on the page?
95
     */
96
    protected $selectall;
97
 
98
    /**
99
     * @var string[] The list of countries.
100
     */
101
    protected $countries;
102
 
103
    /**
104
     * @var \stdClass[] The list of groups with membership info for the course.
105
     */
106
    protected $groups;
107
 
108
    /**
109
     * @var string[] Extra fields to display.
110
     */
111
    protected $extrafields;
112
 
113
    /**
114
     * @var \stdClass $course The course details.
115
     */
116
    protected $course;
117
 
118
    /**
119
     * @var  context $context The course context.
120
     */
121
    protected $context;
122
 
123
    /**
124
     * @var \stdClass[] List of roles indexed by roleid.
125
     */
126
    protected $allroles;
127
 
128
    /**
129
     * @var \stdClass[] List of roles indexed by roleid.
130
     */
131
    protected $allroleassignments;
132
 
133
    /**
134
     * @var \stdClass[] Assignable roles in this course.
135
     */
136
    protected $assignableroles;
137
 
138
    /**
139
     * @var \stdClass[] Profile roles in this course.
140
     */
141
    protected $profileroles;
142
 
143
    /** @var \stdClass[] $viewableroles */
144
    private $viewableroles;
145
 
146
    /**
147
     * Render the participants table.
148
     *
149
     * @param int $pagesize Size of page for paginated displayed table.
150
     * @param bool $useinitialsbar Whether to use the initials bar which will only be used if there is a fullname column defined.
151
     * @param string $downloadhelpbutton
152
     */
153
    public function out($pagesize, $useinitialsbar, $downloadhelpbutton = '') {
154
        global $CFG, $OUTPUT, $PAGE;
155
 
156
        // Define the headers and columns.
157
        $headers = [];
158
        $columns = [];
159
 
160
        $bulkoperations = has_capability('moodle/course:bulkmessaging', $this->context);
161
        if ($bulkoperations) {
162
            $mastercheckbox = new \core\output\checkbox_toggleall('participants-table', true, [
163
                'id' => 'select-all-reengagement-participants',
164
                'name' => 'select-all-reengagement-participants',
165
                'label' => get_string('selectall'),
166
                'labelclasses' => 'sr-only',
167
                'classes' => 'm-1',
168
                'checked' => false,
169
            ]);
170
            $headers[] = $OUTPUT->render($mastercheckbox);
171
            $columns[] = 'select';
172
        }
173
 
174
        $headers[] = get_string('fullname');
175
        $columns[] = 'fullname';
176
 
177
        $extrafields = \core_user\fields::for_identity($this->context)->get_required_fields();
178
 
179
        foreach ($extrafields as $field) {
180
            $headers[] = \core_user\fields::get_display_name($field);
181
            $columns[] = $field;
182
        }
183
 
184
        $headers[] = get_string('roles');
185
        $columns[] = 'roles';
186
 
187
        // Get the list of fields we have to hide.
188
        $hiddenfields = array();
189
        if (!has_capability('moodle/course:viewhiddenuserfields', $this->context)) {
190
            $hiddenfields = array_flip(explode(',', $CFG->hiddenuserfields));
191
        }
192
 
193
        // Add column for groups if the user can view them.
194
        $canseegroups = !isset($hiddenfields['groups']);
195
        if ($canseegroups) {
196
            $headers[] = get_string('groups');
197
            $columns[] = 'groups';
198
        }
199
 
200
        // Do not show the columns if it exists in the hiddenfields array.
201
        if (!isset($hiddenfields['lastaccess'])) {
202
            if ($this->courseid == SITEID) {
203
                $headers[] = get_string('lastsiteaccess');
204
            } else {
205
                $headers[] = get_string('lastcourseaccess');
206
            }
207
            $columns[] = 'lastaccess';
208
        }
209
 
210
        // Show notify time and Completion time columns.
211
        if (!in_array($this->reengagement->emailuser, array(REENGAGEMENT_EMAILUSER_NEVER, REENGAGEMENT_EMAILUSER_COMPLETION))) {
212
            $headers[] = get_string('emailtime', 'mod_reengagement');
213
            $columns[] = 'emailtime';
214
        }
215
        $headers[] = get_string('completiontime', 'mod_reengagement');
216
        $columns[] = 'completiontime';
217
 
218
        $canreviewenrol = has_capability('moodle/course:enrolreview', $this->context);
219
        if ($canreviewenrol && $this->courseid != SITEID) {
220
            $columns[] = 'status';
221
            $headers[] = get_string('participationstatus', 'enrol');
222
            $this->no_sorting('status');
223
        };
224
 
225
        $this->define_columns($columns);
226
        $this->define_headers($headers);
227
 
228
        // The name column is a header.
229
        $this->define_header_column('fullname');
230
 
231
        // Make this table sorted by last name by default.
232
        $this->sortable(true, 'lastname');
233
 
234
        $this->no_sorting('select');
235
        $this->no_sorting('roles');
236
        if ($canseegroups) {
237
            $this->no_sorting('groups');
238
        }
239
 
240
        $this->set_attribute('id', "reengagement-index-participants-$this->cmid");
241
 
242
        $this->countries = get_string_manager()->get_list_of_countries(true);
243
        $this->extrafields = $extrafields;
244
        if ($canseegroups) {
245
            $this->groups = groups_get_all_groups($this->courseid, 0, 0, 'g.*', true);
246
        }
247
        $this->allroles = role_fix_names(get_all_roles($this->context), $this->context);
248
        $this->assignableroles = get_assignable_roles($this->context, ROLENAME_ALIAS, false);
249
        $this->profileroles = get_profile_roles($this->context);
250
        $this->viewableroles = get_viewable_roles($this->context);
251
 
252
        parent::out($pagesize, $useinitialsbar, $downloadhelpbutton);
253
 
254
        if (has_capability('moodle/course:enrolreview', $this->context)) {
255
            $params = [
256
                'contextid' => $this->context->id,
257
                'uniqueid' => $this->uniqueid,
258
            ];
259
            $PAGE->requires->js_call_amd('core_user/status_field', 'init', [$params]);
260
        }
261
    }
262
 
263
    /**
264
     * Generate the select column.
265
     *
266
     * @param \stdClass $data
267
     * @return string
268
     */
269
    public function col_select($data) {
270
        global $OUTPUT;
271
 
272
        $checkbox = new \core\output\checkbox_toggleall('participants-table', false, [
273
            'classes' => 'usercheckbox m-1',
274
            'id' => 'user' . $data->id,
275
            'name' => 'user' . $data->id,
276
            'checked' => false,
277
            'label' => get_string('selectitem', 'moodle', fullname($data)),
278
            'labelclasses' => 'accesshide',
279
        ]);
280
 
281
        return $OUTPUT->render($checkbox);
282
    }
283
 
284
    /**
285
     * Generate the fullname column.
286
     *
287
     * @param \stdClass $data
288
     * @return string
289
     */
290
    public function col_fullname($data) {
291
        global $OUTPUT;
292
 
293
        return $OUTPUT->user_picture($data, array('size' => 35, 'courseid' => $this->course->id, 'includefullname' => true));
294
    }
295
 
296
    /**
297
     * User roles column.
298
     *
299
     * @param \stdClass $data
300
     * @return string
301
     */
302
    public function col_roles($data) {
303
        global $OUTPUT;
304
 
305
        $roles = $this->allroleassignments[$data->id] ?? [];
306
        $editable = new \core_user\output\user_roles_editable($this->course,
307
            $this->context,
308
            $data,
309
            $this->allroles,
310
            $this->assignableroles,
311
            $this->profileroles,
312
            $roles,
313
            $this->viewableroles);
314
 
315
        return $OUTPUT->render_from_template('core/inplace_editable', $editable->export_for_template($OUTPUT));
316
    }
317
 
318
    /**
319
     * Generate the groups column.
320
     *
321
     * @param \stdClass $data
322
     * @return string
323
     */
324
    public function col_groups($data) {
325
        global $OUTPUT;
326
 
327
        $usergroups = [];
328
        foreach ($this->groups as $coursegroup) {
329
            if (isset($coursegroup->members[$data->id])) {
330
                $usergroups[] = $coursegroup->id;
331
            }
332
        }
333
        $editable = new \core_group\output\user_groups_editable($this->course, $this->context, $data, $this->groups, $usergroups);
334
        return $OUTPUT->render_from_template('core/inplace_editable', $editable->export_for_template($OUTPUT));
335
    }
336
 
337
    /**
338
     * Generate the last access column.
339
     *
340
     * @param \stdClass $data
341
     * @return string
342
     */
343
    public function col_lastaccess($data) {
344
        if ($data->lastaccess) {
345
            return format_time(time() - $data->lastaccess);
346
        }
347
 
348
        return get_string('never');
349
    }
350
 
351
    /**
352
     * Generate the status column.
353
     *
354
     * @param \stdClass $data The data object.
355
     * @return string
356
     */
357
    public function col_status($data) {
358
        global $CFG, $OUTPUT, $PAGE;
359
 
360
        $enrolstatusoutput = '';
361
        $canreviewenrol = has_capability('moodle/course:enrolreview', $this->context);
362
        if ($canreviewenrol) {
363
            $canviewfullnames = has_capability('moodle/site:viewfullnames', $this->context);
364
            $fullname = fullname($data, $canviewfullnames);
365
            $coursename = format_string($this->course->fullname, true, array('context' => $this->context));
366
            require_once($CFG->dirroot . '/enrol/locallib.php');
367
            $manager = new \course_enrolment_manager($PAGE, $this->course);
368
            $userenrolments = $manager->get_user_enrolments($data->id);
369
            foreach ($userenrolments as $ue) {
370
                $timestart = $ue->timestart;
371
                $timeend = $ue->timeend;
372
                $timeenrolled = $ue->timecreated;
373
                $actions = $ue->enrolmentplugin->get_user_enrolment_actions($manager, $ue);
374
                $instancename = $ue->enrolmentinstancename;
375
 
376
                // Default status field label and value.
377
                $status = get_string('participationactive', 'enrol');
378
                $statusval = status_field::STATUS_ACTIVE;
379
                switch ($ue->status) {
380
                    case ENROL_USER_ACTIVE:
381
                        $currentdate = new DateTime();
382
                        $now = $currentdate->getTimestamp();
383
                        $isexpired = $timestart > $now || ($timeend > 0 && $timeend < $now);
384
                        $enrolmentdisabled = $ue->enrolmentinstance->status == ENROL_INSTANCE_DISABLED;
385
                        // If user enrolment status has not yet started/already ended or the enrolment instance is disabled.
386
                        if ($isexpired || $enrolmentdisabled) {
387
                            $status = get_string('participationnotcurrent', 'enrol');
388
                            $statusval = status_field::STATUS_NOT_CURRENT;
389
                        }
390
                        break;
391
                    case ENROL_USER_SUSPENDED:
392
                        $status = get_string('participationsuspended', 'enrol');
393
                        $statusval = status_field::STATUS_SUSPENDED;
394
                        break;
395
                }
396
 
397
                $statusfield = new status_field($instancename, $coursename, $fullname, $status, $timestart, $timeend,
398
                    $actions, $timeenrolled);
399
                $statusfielddata = $statusfield->set_status($statusval)->export_for_template($OUTPUT);
400
                $enrolstatusoutput .= $OUTPUT->render_from_template('core_user/status_field', $statusfielddata);
401
            }
402
        }
403
        return $enrolstatusoutput;
404
    }
405
 
406
    /**
407
     * Generate the notify time column.
408
     *
409
     * @param \stdClass $data The data object.
410
     * @return string
411
     */
412
    public function col_emailtime($data) {
413
        return $data->emailtime ? userdate($data->emailtime, get_string('strftimedatetimeshort', 'langconfig')) : '-';
414
    }
415
 
416
    /**
417
     * Generate the completion time column.
418
     *
419
     * @param \stdClass $data The data object.
420
     * @return string
421
     */
422
    public function col_completiontime($data) {
423
        return $data->completiontime ? userdate($data->completiontime, get_string('strftimedatetimeshort', 'langconfig')) : '-';
424
    }
425
 
426
    /**
427
     * This function is used for the extra user fields.
428
     *
429
     * These are being dynamically added to the table so there are no functions 'col_<userfieldname>' as
430
     * the list has the potential to increase in the future and we don't want to have to remember to add
431
     * a new method to this class. We also don't want to pollute this class with unnecessary methods.
432
     *
433
     * @param string $colname The column name
434
     * @param \stdClass $data
435
     * @return string
436
     */
437
    public function other_cols($colname, $data) {
438
        // Do not process if it is not a part of the extra fields.
439
        if (!in_array($colname, $this->extrafields)) {
440
            return '';
441
        }
442
 
443
        return s($data->{$colname});
444
    }
445
 
446
    /**
447
     * Query the database for results to display in the table.
448
     *
449
     * @param int $pagesize size of page for paginated displayed table.
450
     * @param bool $useinitialsbar do you want to use the initials bar.
451
     */
452
    public function query_db($pagesize, $useinitialsbar = true) {
453
        list($twhere, $tparams) = $this->get_sql_where();
454
        $psearch = new \mod_reengagement\table\reengagement_search($this->course, $this->context, $this->filterset);
455
 
456
        $total = $psearch->get_total_participants_count($twhere, $tparams);
457
 
458
        $this->pagesize($pagesize, $total);
459
 
460
        $sort = $this->get_sql_sort();
461
        if ($sort) {
462
            $sort = 'ORDER BY ' . $sort;
463
        }
464
 
465
        $rawdata = $psearch->get_participants($twhere, $tparams, $sort, $this->get_page_start(), $this->get_page_size());
466
 
467
        $this->rawdata = [];
468
        foreach ($rawdata as $user) {
469
            $this->rawdata[$user->id] = $user;
470
        }
471
        $rawdata->close();
472
 
473
        if ($this->rawdata) {
474
            $this->allroleassignments = get_users_roles($this->context, array_keys($this->rawdata),
475
                true, 'c.contextlevel DESC, r.sortorder ASC');
476
        } else {
477
            $this->allroleassignments = [];
478
        }
479
 
480
        // Set initial bars.
481
        if ($useinitialsbar) {
482
            $this->initialbars(true);
483
        }
484
    }
485
 
486
    /**
487
     * Override the table show_hide_link to not show for select column.
488
     *
489
     * @param string $column the column name, index into various names.
490
     * @param int $index numerical index of the column.
491
     * @return string HTML fragment.
492
     */
493
    protected function show_hide_link($column, $index) {
494
        if ($index > 0) {
495
            return parent::show_hide_link($column, $index);
496
        }
497
        return '';
498
    }
499
 
500
    /**
501
     * Set filters and build table structure.
502
     *
503
     * @param filterset $filterset The filterset object to get the filters from.
504
     */
505
    public function set_filterset(filterset $filterset): void {
506
        global $DB;
507
        // Get the context.
508
        $this->cmid = $filterset->get_filter('courseid')->current();
509
 
510
        // Pretend the courseid is the cmid, as the core participants JS doesn't support additional filters.
511
        $cm = get_coursemodule_from_id('reengagement', $this->cmid, 0, false, MUST_EXIST);
512
        $this->courseid = $cm->course;
513
        $this->course = get_course($this->courseid);
514
        $this->reengagement = $DB->get_record('reengagement', array('id' => $cm->instance), '*', MUST_EXIST);
515
 
516
        $this->context = context_module::instance($this->cmid, MUST_EXIST);
517
 
518
        // Process the filterset.
519
        parent::set_filterset($filterset);
520
    }
521
 
522
    /**
523
     * Guess the base url for the participants table.
524
     */
525
    public function guess_base_url(): void {
526
        $this->baseurl = new moodle_url('/mod/reengagement/view.php', ['id' => $this->cmid]);
527
    }
528
 
529
    /**
530
     * Get the context of the current table.
531
     *
532
     * Note: This function should not be called until after the filterset has been provided.
533
     *
534
     * @return context
535
     */
536
    public function get_context(): context {
537
        return $this->context;
538
    }
539
}