Merge branch 'MDL-63375-38' of https://github.com/syxton/moodle into MOODLE_38_STABLE
[moodle.git] / enrol / renderer.php
blobbb88d11bce7d6005707e0be31652fccda9769f72
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.
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/>.
17 /**
18 * This is the main renderer for the enrol section.
20 * @package core_enrol
21 * @copyright 2010 Sam Hemelryk
22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
25 /**
26 * This is the core renderer
28 * @copyright 2010 Sam Hemelryk
29 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
31 class core_enrol_renderer extends plugin_renderer_base {
33 /**
34 * Renderers the enrol_user_button.
36 * @param enrol_user_button $button
37 * @return string XHTML
39 protected function render_enrol_user_button(enrol_user_button $button) {
40 $attributes = array('type' => 'submit',
41 'value' => $button->label,
42 'disabled' => $button->disabled ? 'disabled' : null,
43 'title' => $button->tooltip,
44 'class' => 'btn btn-secondary my-1');
46 if ($button->actions) {
47 $id = html_writer::random_id('single_button');
48 $attributes['id'] = $id;
49 foreach ($button->actions as $action) {
50 $this->add_action_handler($action, $id);
53 $button->initialise_js($this->page);
55 // first the input element
56 $output = html_writer::empty_tag('input', $attributes);
58 // then hidden fields
59 $params = $button->url->params();
60 if ($button->method === 'post') {
61 $params['sesskey'] = sesskey();
63 foreach ($params as $var => $val) {
64 $output .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => $var, 'value' => $val));
67 // then div wrapper for xhtml strictness
68 $output = html_writer::tag('div', $output);
70 // now the form itself around it
71 if ($button->method === 'get') {
72 $url = $button->url->out_omit_querystring(true); // url without params, the anchor part allowed
73 } else {
74 $url = $button->url->out_omit_querystring(); // url without params, the anchor part not allowed
76 if ($url === '') {
77 $url = '#'; // there has to be always some action
79 $attributes = array('method' => $button->method,
80 'action' => $url,
81 'id' => $button->formid);
82 $output = html_writer::tag('form', $output, $attributes);
84 // and finally one more wrapper with class
85 return html_writer::tag('div', $output, array('class' => $button->class));
88 /**
89 * Renders a course enrolment table
91 * @param course_enrolment_table $table
92 * @return string
94 protected function render_course_enrolment_other_users_table(course_enrolment_other_users_table $table) {
96 $table->initialise_javascript();
98 $content = '';
99 $searchbutton = $table->get_user_search_button();
100 if ($searchbutton) {
101 $content .= $this->output->render($searchbutton);
103 $content .= html_writer::tag('div', get_string('otheruserdesc', 'enrol'), array('class'=>'otherusersdesc'));
104 $content .= $this->output->render($table->get_paging_bar());
105 $content .= html_writer::table($table);
106 $content .= $this->output->render($table->get_paging_bar());
107 $searchbutton = $table->get_user_search_button();
108 if ($searchbutton) {
109 $content .= $this->output->render($searchbutton);
111 return $content;
115 * Generates HTML to display the users roles and any available actions
117 * @param int $userid
118 * @param array $roles
119 * @param array $assignableroles
120 * @param moodle_url $pageurl
121 * @return string
123 public function user_roles_and_actions($userid, $roles, $assignableroles, $canassign, $pageurl) {
125 // Get list of roles.
126 $rolesoutput = '';
127 foreach ($roles as $roleid=>$role) {
128 if ($canassign and (is_siteadmin() or isset($assignableroles[$roleid])) and !$role['unchangeable']) {
129 $strunassign = get_string('unassignarole', 'role', $role['text']);
130 $icon = $this->output->pix_icon('t/delete', $strunassign);
131 $url = new moodle_url($pageurl, array('action'=>'unassign', 'roleid'=>$roleid, 'user'=>$userid));
132 $rolesoutput .= html_writer::tag('div', $role['text'] . html_writer::link($url, $icon, array('class'=>'unassignrolelink', 'rel'=>$roleid, 'title'=>$strunassign)), array('class'=>'role role_'.$roleid));
133 } else {
134 $rolesoutput .= html_writer::tag('div', $role['text'], array('class'=>'role unchangeable', 'rel'=>$roleid));
137 $output = '';
138 if (!empty($assignableroles) && $canassign) {
139 $roleids = array_keys($roles);
140 $hasallroles = true;
141 foreach (array_keys($assignableroles) as $key) {
142 if (!in_array($key, $roleids)) {
143 $hasallroles = false;
144 break;
147 if (!$hasallroles) {
148 $url = new moodle_url($pageurl, array('action' => 'assign', 'user' => $userid));
149 $roleicon = $this->output->pix_icon('i/assignroles', get_string('assignroles', 'role'));
150 $link = html_writer::link($url, $roleicon, array('class' => 'assignrolelink'));
151 $output = html_writer::tag('div', $link, array('class'=>'addrole'));
154 $output .= html_writer::tag('div', $rolesoutput, array('class'=>'roles'));
155 return $output;
159 * Generates the HTML to view the users groups and available group actions
161 * @param int $userid
162 * @param array $groups
163 * @param array $allgroups
164 * @param bool $canmanagegroups
165 * @param moodle_url $pageurl
166 * @return string
168 public function user_groups_and_actions($userid, $groups, $allgroups, $canmanagegroups, $pageurl) {
169 $groupicon = $this->output->pix_icon('i/group', get_string('addgroup', 'group'));
171 $groupoutput = '';
172 foreach($groups as $groupid=>$name) {
173 if ($canmanagegroups and groups_remove_member_allowed($groupid, $userid)) {
174 $icon = $this->output->pix_icon('t/delete', get_string('removefromgroup', 'group', $name));
175 $url = new moodle_url($pageurl, array('action'=>'removemember', 'group'=>$groupid, 'user'=>$userid));
176 $groupoutput .= html_writer::tag('div', $name . html_writer::link($url, $icon), array('class'=>'group', 'rel'=>$groupid));
177 } else {
178 $groupoutput .= html_writer::tag('div', $name, array('class'=>'group', 'rel'=>$groupid));
181 $output = '';
182 if ($canmanagegroups && (count($groups) < count($allgroups))) {
183 $url = new moodle_url($pageurl, array('action'=>'addmember', 'user'=>$userid));
184 $output .= html_writer::tag('div', html_writer::link($url, $groupicon), array('class'=>'addgroup'));
186 $output = $output.html_writer::tag('div', $groupoutput, array('class'=>'groups'));
187 return $output;
191 * Generates the HTML for the given enrolments + available actions
193 * @param int $userid
194 * @param array $enrolments
195 * @param moodle_url $pageurl
196 * @return string
198 public function user_enrolments_and_actions($enrolments) {
199 $output = '';
200 foreach ($enrolments as $ue) {
201 $enrolmentoutput = $ue['text'].' '.$ue['period'];
202 if ($ue['dimmed']) {
203 $enrolmentoutput = html_writer::tag('span', $enrolmentoutput, array('class'=>'dimmed_text'));
204 } else {
205 $enrolmentoutput = html_writer::tag('span', $enrolmentoutput);
207 foreach ($ue['actions'] as $action) {
208 $enrolmentoutput .= $this->render($action);
210 $output .= html_writer::tag('div', $enrolmentoutput, array('class'=>'enrolment'));
212 return $output;
216 * Renders a user enrolment action
217 * @param user_enrolment_action $icon
218 * @return string
220 protected function render_user_enrolment_action(user_enrolment_action $icon) {
221 return html_writer::link($icon->get_url(), $this->output->render($icon->get_icon()), $icon->get_attributes());
226 * Main course enrolment table
228 * This table is used to display the enrolment information for a course.
229 * It requires that a course enrolment manager be provided during constuct with
230 * provides all of the information for the table.
231 * The control then produces the table, the paging, and the associated JS actions
232 * for the page.
234 * @package core
235 * @subpackage enrol
236 * @copyright 2010 Sam Hemelryk
237 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
239 class course_enrolment_table extends html_table implements renderable {
242 * The get/post variable that is used to identify the page.
243 * Default: page
245 const PAGEVAR = 'page';
248 * The get/post variable to is used to identify the number of items to display
249 * per page.
250 * Default: perpage
252 const PERPAGEVAR = 'perpage';
255 * The get/post variable that is used to identify the sort field for the table.
256 * Default: sort
258 const SORTVAR = 'sort';
261 * The get/post variable that is used to identify the sort direction for the table.
262 * Default: dir
264 const SORTDIRECTIONVAR = 'dir';
267 * The default number of items per page.
268 * Default: 100
270 const DEFAULTPERPAGE = 100;
273 * The default sort, options are course_enrolment_table::$sortablefields
274 * Default: lastname
276 const DEFAULTSORT = 'lastname';
279 * The default direction
280 * Default: ASC
282 const DEFAULTSORTDIRECTION = 'ASC';
285 * The current page, starting from 0
286 * @var int
288 public $page = 0;
291 * The total number of pages
292 * @var int
294 public $pages = 0;
297 * The number of items to display per page
298 * @var int
300 public $perpage = 0;
303 * The sort field for this table, should be one of course_enrolment_table::$sortablefields
304 * @var string
306 public $sort;
309 * The sort direction, either ASC or DESC
310 * @var string
312 public $sortdirection;
315 * The course manager this table is displaying for
316 * @var course_enrolment_manager
318 protected $manager;
321 * The paging bar that controls the paging for this table
322 * @var paging_bar
324 protected $pagingbar = null;
327 * The total number of users enrolled in the course
328 * @var int
330 protected $totalusers = null;
333 * The users enrolled in this course
334 * @var array
336 protected $users = null;
339 * The fields for this table
340 * @var array
342 protected $fields = array();
345 * An array of bulk user enrolment operations
346 * @var array
348 protected $bulkoperations = array();
351 * An array of sortable fields
352 * @static
353 * @var array
355 protected static $sortablefields = array('firstname', 'lastname', 'firstnamephonetic', 'lastnamephonetic', 'middlename',
356 'alternatename', 'username', 'idnumber', 'email', 'phone1', 'phone2',
357 'institution', 'department', 'lastaccess', 'lastcourseaccess');
360 * Constructs the table
362 * @param course_enrolment_manager $manager
364 public function __construct(course_enrolment_manager $manager) {
366 $this->manager = $manager;
368 $this->page = optional_param(self::PAGEVAR, 0, PARAM_INT);
369 $this->perpage = optional_param(self::PERPAGEVAR, self::DEFAULTPERPAGE, PARAM_INT);
370 $this->sort = optional_param(self::SORTVAR, self::DEFAULTSORT, PARAM_ALPHANUM);
371 $this->sortdirection = optional_param(self::SORTDIRECTIONVAR, self::DEFAULTSORTDIRECTION, PARAM_ALPHA);
373 $this->attributes = array('class'=>'userenrolment');
374 if (!in_array($this->sort, self::$sortablefields)) {
375 $this->sort = self::DEFAULTSORT;
377 if ($this->page < 0) {
378 $this->page = 0;
380 if ($this->sortdirection !== 'ASC' && $this->sortdirection !== 'DESC') {
381 $this->sortdirection = self::DEFAULTSORTDIRECTION;
384 $this->id = html_writer::random_id();
386 // Collect the bulk operations for the currently filtered plugin if there is one.
387 $plugin = $manager->get_filtered_enrolment_plugin();
388 if ($plugin and enrol_is_enabled($plugin->get_name())) {
389 $this->bulkoperations = $plugin->get_bulk_operations($manager);
394 * Returns an array of enrol_user_buttons that are created by the different
395 * enrolment plugins available.
397 * @return array
399 public function get_manual_enrol_buttons() {
400 return $this->manager->get_manual_enrol_buttons();
404 * Gets the sort direction for a given field
406 * @param string $field
407 * @return string ASC or DESC
409 public function get_field_sort_direction($field) {
410 if ($field == $this->sort) {
411 return ($this->sortdirection == 'ASC')?'DESC':'ASC';
413 return self::DEFAULTSORTDIRECTION;
417 * Sets the fields for this table. These get added to the tables head as well.
419 * You can also use a multi dimensional array for this to have multiple fields
420 * in a single column
422 * @param array $fields An array of fields to set
423 * @param string $output
425 public function set_fields($fields, $output) {
426 $this->fields = $fields;
427 $this->head = array();
428 $this->colclasses = array();
429 $this->align = array();
430 $url = $this->manager->get_moodlepage()->url;
432 if (!empty($this->bulkoperations)) {
433 // If there are bulk operations add a column for checkboxes.
434 $this->head[] = '';
435 $this->colclasses[] = 'field col_bulkops';
438 foreach ($fields as $name => $label) {
439 $newlabel = '';
440 if (is_array($label)) {
441 $bits = array();
442 foreach ($label as $n => $l) {
443 if ($l === false) {
444 continue;
446 if (!in_array($n, self::$sortablefields)) {
447 $bits[] = $l;
448 } else {
449 $sorturl = new moodle_url($url, array(self::SORTVAR => $n, self::SORTDIRECTIONVAR => $this->get_field_sort_direction($n)));
450 $link = html_writer::link($sorturl, $fields[$name][$n]);
451 if ($this->sort == $n) {
452 $link .= $this->get_direction_icon($output, $n);
454 $bits[] = html_writer::tag('span', $link, array('class'=>'subheading_'.$n));
458 $newlabel = join(' / ', $bits);
459 } else {
460 if (!in_array($name, self::$sortablefields)) {
461 $newlabel = $label;
462 } else {
463 $sorturl = new moodle_url($url, array(self::SORTVAR => $name, self::SORTDIRECTIONVAR => $this->get_field_sort_direction($name)));
464 $newlabel = html_writer::link($sorturl, $fields[$name]);
465 if ($this->sort == $name) {
466 $newlabel .= $this->get_direction_icon($output, $name);
470 $this->head[] = $newlabel;
471 $this->colclasses[] = 'field col_'.$name;
475 * Sets the total number of users
477 * @param int $totalusers
479 public function set_total_users($totalusers) {
480 $this->totalusers = $totalusers;
481 $this->pages = ceil($this->totalusers / $this->perpage);
482 if ($this->page > $this->pages) {
483 $this->page = $this->pages;
487 * Sets the users for this table
489 * @param array $users
490 * @return void
492 public function set_users(array $users) {
493 $this->users = $users;
494 $hasbulkops = !empty($this->bulkoperations);
495 foreach ($users as $userid=>$user) {
496 $user = (array)$user;
497 $row = new html_table_row();
498 $row->attributes = array('class' => 'userinforow');
499 $row->id = 'user_'.$userid;
500 $row->cells = array();
501 if ($hasbulkops) {
502 // Add a checkbox into the first column.
503 $input = html_writer::empty_tag('input', array('type' => 'checkbox', 'name' => 'bulkuser[]', 'value' => $userid));
504 $row->cells[] = new html_table_cell($input);
506 foreach ($this->fields as $field => $label) {
507 if (is_array($label)) {
508 $bits = array();
509 foreach (array_keys($label) as $subfield) {
510 if (array_key_exists($subfield, $user)) {
511 $bits[] = html_writer::tag('div', $user[$subfield], array('class'=>'subfield subfield_'.$subfield));
514 if (empty($bits)) {
515 $bits[] = '&nbsp;';
517 $row->cells[] = new html_table_cell(join(' ', $bits));
518 } else {
519 if (!array_key_exists($field, $user)) {
520 $user[$field] = '&nbsp;';
522 $row->cells[] = new html_table_cell($user[$field]);
525 $this->data[] = $row;
529 public function initialise_javascript() {
530 if (has_capability('moodle/role:assign', $this->manager->get_context())) {
531 $this->manager->get_moodlepage()->requires->strings_for_js(array(
532 'assignroles',
533 'confirmunassign',
534 'confirmunassigntitle',
535 'confirmunassignyes',
536 'confirmunassignno'
537 ), 'role');
538 $modules = array('moodle-enrol-rolemanager', 'moodle-enrol-rolemanager-skin');
539 $function = 'M.enrol.rolemanager.init';
540 $arguments = array(
541 'containerId'=>$this->id,
542 'userIds'=>array_keys($this->users),
543 'courseId'=>$this->manager->get_course()->id,
544 'otherusers'=>isset($this->otherusers));
545 $this->manager->get_moodlepage()->requires->yui_module($modules, $function, array($arguments));
550 * Gets the paging bar instance for this table
552 * @return paging_bar
554 public function get_paging_bar() {
555 if ($this->pagingbar == null) {
556 $this->pagingbar = new paging_bar($this->totalusers, $this->page, $this->perpage, $this->manager->get_moodlepage()->url, self::PAGEVAR);
558 return $this->pagingbar;
562 * Gets the direction icon for the sortable field within this table
564 * @param core_renderer $output
565 * @param string $field
566 * @return string
568 protected function get_direction_icon($output, $field) {
569 $direction = self::DEFAULTSORTDIRECTION;
570 if ($this->sort == $field) {
571 $direction = $this->sortdirection;
573 if ($direction === 'ASC') {
574 return $output->pix_icon('t/sort_asc', get_string('sort'));
575 } else {
576 return $output->pix_icon('t/sort_desc', get_string('sort'));
581 * Gets the params that will need to be added to the url in order to return to this page.
583 * @return array
585 public function get_url_params() {
586 return array(
587 self::PAGEVAR => $this->page,
588 self::PERPAGEVAR => $this->perpage,
589 self::SORTVAR => $this->sort,
590 self::SORTDIRECTIONVAR => $this->sortdirection
595 * Returns an array of URL params for both the table and the manager.
597 * @return array
599 public function get_combined_url_params() {
600 return $this->get_url_params() + $this->manager->get_url_params();
604 * Sets the bulk operations for this table.
606 * @param array $bulkoperations
608 public function set_bulk_user_enrolment_operations(array $bulkoperations) {
609 $this->bulkoperations = $bulkoperations;
613 * Returns an array of bulk operations.
615 * @return array
617 public function get_bulk_user_enrolment_operations() {
618 return $this->bulkoperations;
622 * Returns true fi the table is aware of any bulk operations that can be performed on users
623 * selected from the currently filtered enrolment plugins.
625 * @return bool
627 public function has_bulk_user_enrolment_operations() {
628 return !empty($this->bulkoperations);
633 * Table control used for enrolled users
635 * @copyright 2010 Sam Hemelryk
636 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
638 class course_enrolment_users_table extends course_enrolment_table {
643 * Table used for other users
645 * Other users are users who have roles but are not enrolled.
647 * @copyright 2010 Sam Hemelryk
648 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
650 class course_enrolment_other_users_table extends course_enrolment_table {
652 public $otherusers = true;
655 * Constructs the table
657 * @param course_enrolment_manager $manager
659 public function __construct(course_enrolment_manager $manager) {
660 parent::__construct($manager);
661 $this->attributes = array('class'=>'userenrolment otheruserenrolment');
665 * Gets a button to search users and assign them roles in the course.
667 * @staticvar int $count
668 * @param int $page
669 * @return single_button
671 public function get_user_search_button() {
672 static $count = 0;
673 if (!has_capability('moodle/role:assign', $this->manager->get_context())) {
674 return false;
676 $count++;
677 $url = new moodle_url('/admin/roles/assign.php', array('contextid'=>$this->manager->get_context()->id, 'sesskey'=>sesskey()));
678 $control = new single_button($url, get_string('assignroles', 'role'), 'get');
679 $control->class = 'singlebutton assignuserrole instance'.$count;
680 if ($count == 1) {
681 $this->manager->get_moodlepage()->requires->strings_for_js(array(
682 'ajaxoneuserfound',
683 'ajaxxusersfound',
684 'ajaxxmoreusersfound',
685 'ajaxnext25',
686 'enrol',
687 'enrolmentoptions',
688 'enrolusers',
689 'enrolxusers',
690 'errajaxfailedenrol',
691 'errajaxsearch',
692 'foundxcohorts',
693 'none',
694 'usersearch',
695 'unlimitedduration',
696 'startdatetoday',
697 'durationdays',
698 'enrolperiod'), 'enrol');
699 $this->manager->get_moodlepage()->requires->string_for_js('assignrole', 'role');
701 $modules = array('moodle-enrol-otherusersmanager', 'moodle-enrol-otherusersmanager-skin');
702 $function = 'M.enrol.otherusersmanager.init';
703 $arguments = array(
704 'courseId'=> $this->manager->get_course()->id,
705 'ajaxUrl' => '/enrol/ajax.php',
706 'url' => $this->manager->get_moodlepage()->url->out(false));
707 $this->manager->get_moodlepage()->requires->yui_module($modules, $function, array($arguments));
709 return $control;