Merge branch 'MDL-81399' of https://github.com/paulholden/moodle
[moodle.git] / enrol / renderer.php
blobb5423ae8b9eb8e61b184dff956892d24b0b88f83
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 $buttoninfo = $button->export_for_template($this->output);
42 $attributes = [
43 'type' => 'submit',
44 'value' => $buttoninfo->label,
45 'disabled' => $buttoninfo->disabled ? 'disabled' : null,
46 'title' => $buttoninfo->tooltip,
47 'class' => 'btn ' . "btn-{$buttoninfo->type}",
49 if ($button->actions) {
50 $id = html_writer::random_id('single_button');
51 $attributes['id'] = $id;
52 foreach ($button->actions as $action) {
53 $this->add_action_handler($action, $id);
56 $button->initialise_js($this->page);
58 // first the input element
59 $output = html_writer::empty_tag('input', $attributes);
61 // then hidden fields
62 $params = $button->url->params();
63 if ($button->method === 'post') {
64 $params['sesskey'] = sesskey();
66 foreach ($params as $var => $val) {
67 $output .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => $var, 'value' => $val));
70 // then div wrapper for xhtml strictness
71 $output = html_writer::tag('div', $output);
73 // now the form itself around it
74 if ($button->method === 'get') {
75 $url = $button->url->out_omit_querystring(true); // url without params, the anchor part allowed
76 } else {
77 $url = $button->url->out_omit_querystring(); // url without params, the anchor part not allowed
79 if ($url === '') {
80 $url = '#'; // there has to be always some action
82 $attributes = array('method' => $button->method,
83 'action' => $url,
84 'id' => $button->formid);
85 $output = html_writer::tag('form', $output, $attributes);
87 // and finally one more wrapper with class
88 return html_writer::tag('div', $output, array('class' => $button->class));
91 /**
92 * Renders a course enrolment table
94 * @param course_enrolment_table $table
95 * @return string
97 protected function render_course_enrolment_other_users_table(course_enrolment_other_users_table $table) {
99 $table->initialise_javascript();
101 $content = '';
102 $content .= html_writer::tag('div', get_string('otheruserdesc', 'enrol'), array('class'=>'otherusersdesc'));
103 $content .= $this->output->render($table->get_paging_bar());
104 $content .= html_writer::table($table);
105 $content .= $this->output->render($table->get_paging_bar());
106 return $content;
110 * Generates HTML to display the users roles and any available actions
112 * @param int $userid
113 * @param array $roles
114 * @param array $assignableroles
115 * @param moodle_url $pageurl
116 * @return string
118 public function user_roles_and_actions($userid, $roles, $assignableroles, $canassign, $pageurl) {
120 // Get list of roles.
121 $rolesoutput = '';
122 foreach ($roles as $roleid=>$role) {
123 if ($canassign and (is_siteadmin() or isset($assignableroles[$roleid])) and !$role['unchangeable']) {
124 $strunassign = get_string('unassignarole', 'role', $role['text']);
125 $icon = $this->output->pix_icon('t/delete', $strunassign);
126 $url = new moodle_url($pageurl, array('action'=>'unassign', 'roleid'=>$roleid, 'user'=>$userid));
127 $rolesoutput .= html_writer::tag('div', $role['text'] . html_writer::link($url, $icon, array('class'=>'unassignrolelink', 'rel'=>$roleid, 'title'=>$strunassign)), array('class'=>'role role_'.$roleid));
128 } else {
129 $rolesoutput .= html_writer::tag('div', $role['text'], array('class'=>'role unchangeable', 'rel'=>$roleid));
132 $output = '';
133 if (!empty($assignableroles) && $canassign) {
134 $roleids = array_keys($roles);
135 $hasallroles = true;
136 foreach (array_keys($assignableroles) as $key) {
137 if (!in_array($key, $roleids)) {
138 $hasallroles = false;
139 break;
142 if (!$hasallroles) {
143 $url = new moodle_url($pageurl, array('action' => 'assign', 'user' => $userid));
144 $roleicon = $this->output->pix_icon('i/assignroles', get_string('assignroles', 'role'));
145 $link = html_writer::link($url, $roleicon, array('class' => 'assignrolelink'));
146 $output = html_writer::tag('div', $link, array('class'=>'addrole'));
149 $output .= html_writer::tag('div', $rolesoutput, array('class'=>'roles'));
150 return $output;
154 * Generates the HTML to view the users groups and available group actions
156 * @param int $userid
157 * @param array $groups
158 * @param array $allgroups
159 * @param bool $canmanagegroups
160 * @param moodle_url $pageurl
161 * @return string
163 public function user_groups_and_actions($userid, $groups, $allgroups, $canmanagegroups, $pageurl) {
164 $groupicon = $this->output->pix_icon('i/group', get_string('addgroup', 'group'));
166 $groupoutput = '';
167 foreach($groups as $groupid=>$name) {
168 if ($canmanagegroups and groups_remove_member_allowed($groupid, $userid)) {
169 $icon = $this->output->pix_icon('t/delete', get_string('removefromgroup', 'group', $name));
170 $url = new moodle_url($pageurl, array('action'=>'removemember', 'group'=>$groupid, 'user'=>$userid));
171 $groupoutput .= html_writer::tag('div', $name . html_writer::link($url, $icon), array('class'=>'group', 'rel'=>$groupid));
172 } else {
173 $groupoutput .= html_writer::tag('div', $name, array('class'=>'group', 'rel'=>$groupid));
176 $output = '';
177 if ($canmanagegroups && (count($groups) < count($allgroups))) {
178 $url = new moodle_url($pageurl, array('action'=>'addmember', 'user'=>$userid));
179 $output .= html_writer::tag('div', html_writer::link($url, $groupicon), array('class'=>'addgroup'));
181 $output = $output.html_writer::tag('div', $groupoutput, array('class'=>'groups'));
182 return $output;
186 * Generates the HTML for the given enrolments + available actions
188 * @param int $userid
189 * @param array $enrolments
190 * @param moodle_url $pageurl
191 * @return string
193 public function user_enrolments_and_actions($enrolments) {
194 $output = '';
195 foreach ($enrolments as $ue) {
196 $enrolmentoutput = $ue['text'].' '.$ue['period'];
197 if ($ue['dimmed']) {
198 $enrolmentoutput = html_writer::tag('span', $enrolmentoutput, array('class'=>'dimmed_text'));
199 } else {
200 $enrolmentoutput = html_writer::tag('span', $enrolmentoutput);
202 foreach ($ue['actions'] as $action) {
203 $enrolmentoutput .= $this->render($action);
205 $output .= html_writer::tag('div', $enrolmentoutput, array('class'=>'enrolment'));
207 return $output;
211 * Renders a user enrolment action
212 * @param user_enrolment_action $icon
213 * @return string
215 protected function render_user_enrolment_action(user_enrolment_action $icon) {
216 return html_writer::link($icon->get_url(), $this->output->render($icon->get_icon()), $icon->get_attributes());
221 * Main course enrolment table
223 * This table is used to display the enrolment information for a course.
224 * It requires that a course enrolment manager be provided during constuct with
225 * provides all of the information for the table.
226 * The control then produces the table, the paging, and the associated JS actions
227 * for the page.
229 * @package core
230 * @subpackage enrol
231 * @copyright 2010 Sam Hemelryk
232 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
234 class course_enrolment_table extends html_table implements renderable {
237 * The get/post variable that is used to identify the page.
238 * Default: page
240 const PAGEVAR = 'page';
243 * The get/post variable to is used to identify the number of items to display
244 * per page.
245 * Default: perpage
247 const PERPAGEVAR = 'perpage';
250 * The get/post variable that is used to identify the sort field for the table.
251 * Default: sort
253 const SORTVAR = 'sort';
256 * The get/post variable that is used to identify the sort direction for the table.
257 * Default: dir
259 const SORTDIRECTIONVAR = 'dir';
262 * The default number of items per page.
263 * Default: 100
265 const DEFAULTPERPAGE = 100;
268 * The default sort, options are course_enrolment_table::$sortablefields
269 * Default: lastname
271 const DEFAULTSORT = 'lastname';
274 * The default direction
275 * Default: ASC
277 const DEFAULTSORTDIRECTION = 'ASC';
280 * The current page, starting from 0
281 * @var int
283 public $page = 0;
286 * The total number of pages
287 * @var int
289 public $pages = 0;
292 * The number of items to display per page
293 * @var int
295 public $perpage = 0;
298 * The sort field for this table, should be one of course_enrolment_table::$sortablefields
299 * @var string
301 public $sort;
304 * The sort direction, either ASC or DESC
305 * @var string
307 public $sortdirection;
310 * The course manager this table is displaying for
311 * @var course_enrolment_manager
313 protected $manager;
316 * The paging bar that controls the paging for this table
317 * @var paging_bar
319 protected $pagingbar = null;
322 * The total number of users enrolled in the course
323 * @var int
325 protected $totalusers = null;
328 * The users enrolled in this course
329 * @var array
331 protected $users = null;
334 * The fields for this table
335 * @var array
337 protected $fields = array();
340 * An array of bulk user enrolment operations
341 * @var array
343 protected $bulkoperations = array();
346 * An array of sortable fields
347 * @static
348 * @var array
350 protected static $sortablefields = array('firstname', 'lastname', 'firstnamephonetic', 'lastnamephonetic', 'middlename',
351 'alternatename', 'username', 'idnumber', 'email', 'phone1', 'phone2',
352 'institution', 'department', 'lastaccess', 'lastcourseaccess');
354 /** @var bool To store status of Other users page. */
355 public $otherusers;
358 * Constructs the table
360 * @param course_enrolment_manager $manager
362 public function __construct(course_enrolment_manager $manager) {
364 $this->manager = $manager;
366 $this->page = optional_param(self::PAGEVAR, 0, PARAM_INT);
367 $this->perpage = optional_param(self::PERPAGEVAR, self::DEFAULTPERPAGE, PARAM_INT);
368 $this->sort = optional_param(self::SORTVAR, self::DEFAULTSORT, PARAM_ALPHANUM);
369 $this->sortdirection = optional_param(self::SORTDIRECTIONVAR, self::DEFAULTSORTDIRECTION, PARAM_ALPHA);
371 $this->attributes = array('class' => 'userenrolment table-striped');
372 if (!in_array($this->sort, self::$sortablefields)) {
373 $this->sort = self::DEFAULTSORT;
375 if ($this->page < 0) {
376 $this->page = 0;
378 if ($this->sortdirection !== 'ASC' && $this->sortdirection !== 'DESC') {
379 $this->sortdirection = self::DEFAULTSORTDIRECTION;
382 $this->id = html_writer::random_id();
384 // Collect the bulk operations for the currently filtered plugin if there is one.
385 $plugin = $manager->get_filtered_enrolment_plugin();
386 if ($plugin and enrol_is_enabled($plugin->get_name())) {
387 $this->bulkoperations = $plugin->get_bulk_operations($manager);
392 * Returns an array of enrol_user_buttons that are created by the different
393 * enrolment plugins available.
395 * @return array
397 public function get_manual_enrol_buttons() {
398 return $this->manager->get_manual_enrol_buttons();
402 * Gets the sort direction for a given field
404 * @param string $field
405 * @return string ASC or DESC
407 public function get_field_sort_direction($field) {
408 if ($field == $this->sort) {
409 return ($this->sortdirection == 'ASC')?'DESC':'ASC';
411 return self::DEFAULTSORTDIRECTION;
415 * Sets the fields for this table. These get added to the tables head as well.
417 * You can also use a multi dimensional array for this to have multiple fields
418 * in a single column
420 * @param array $fields An array of fields to set
421 * @param string $output
423 public function set_fields($fields, $output) {
424 $this->fields = $fields;
425 $this->head = array();
426 $this->colclasses = array();
427 $this->align = array();
428 $url = $this->manager->get_moodlepage()->url;
430 if (!empty($this->bulkoperations)) {
431 // If there are bulk operations add a column for checkboxes.
432 $this->head[] = '';
433 $this->colclasses[] = 'field col_bulkops';
436 foreach ($fields as $name => $label) {
437 $newlabel = '';
438 if (is_array($label)) {
439 $bits = array();
440 foreach ($label as $n => $l) {
441 if ($l === false) {
442 continue;
444 if (!in_array($n, self::$sortablefields)) {
445 $bits[] = $l;
446 } else {
447 $sorturl = new moodle_url($url, array(self::SORTVAR => $n, self::SORTDIRECTIONVAR => $this->get_field_sort_direction($n)));
448 $link = html_writer::link($sorturl, $fields[$name][$n]);
449 if ($this->sort == $n) {
450 $link .= $this->get_direction_icon($output, $n);
452 $bits[] = html_writer::tag('span', $link, array('class'=>'subheading_'.$n));
456 $newlabel = join(' / ', $bits);
457 } else {
458 if (!in_array($name, self::$sortablefields)) {
459 $newlabel = $label;
460 } else {
461 $sorturl = new moodle_url($url, array(self::SORTVAR => $name, self::SORTDIRECTIONVAR => $this->get_field_sort_direction($name)));
462 $newlabel = html_writer::link($sorturl, $fields[$name]);
463 if ($this->sort == $name) {
464 $newlabel .= $this->get_direction_icon($output, $name);
468 $this->head[] = $newlabel;
469 $this->colclasses[] = 'field col_'.$name;
473 * Sets the total number of users
475 * @param int $totalusers
477 public function set_total_users($totalusers) {
478 $this->totalusers = $totalusers;
479 $this->pages = ceil($this->totalusers / $this->perpage);
480 if ($this->page > $this->pages) {
481 $this->page = $this->pages;
485 * Sets the users for this table
487 * @param array $users
488 * @return void
490 public function set_users(array $users) {
491 $this->users = $users;
492 $hasbulkops = !empty($this->bulkoperations);
493 foreach ($users as $userid=>$user) {
494 $user = (array)$user;
495 $row = new html_table_row();
496 $row->attributes = array('class' => 'userinforow');
497 $row->id = 'user_'.$userid;
498 $row->cells = array();
499 if ($hasbulkops) {
500 // Add a checkbox into the first column.
501 $input = html_writer::empty_tag('input', array('type' => 'checkbox', 'name' => 'bulkuser[]', 'value' => $userid));
502 $row->cells[] = new html_table_cell($input);
504 foreach ($this->fields as $field => $label) {
505 if (is_array($label)) {
506 $bits = array();
507 foreach (array_keys($label) as $subfield) {
508 if (array_key_exists($subfield, $user)) {
509 $bits[] = html_writer::tag('div', $user[$subfield], array('class'=>'subfield subfield_'.$subfield));
512 if (empty($bits)) {
513 $bits[] = '&nbsp;';
515 $row->cells[] = new html_table_cell(join(' ', $bits));
516 } else {
517 if (!array_key_exists($field, $user)) {
518 $user[$field] = '&nbsp;';
520 $row->cells[] = new html_table_cell($user[$field]);
523 $this->data[] = $row;
527 public function initialise_javascript() {
528 if (has_capability('moodle/role:assign', $this->manager->get_context())) {
529 $this->manager->get_moodlepage()->requires->strings_for_js(array(
530 'assignroles',
531 'confirmunassign',
532 'confirmunassigntitle',
533 'confirmunassignyes',
534 'confirmunassignno'
535 ), 'role');
536 $modules = array('moodle-enrol-rolemanager', 'moodle-enrol-rolemanager-skin');
537 $function = 'M.enrol.rolemanager.init';
538 $arguments = array(
539 'containerId'=>$this->id,
540 'userIds'=>array_keys($this->users),
541 'courseId'=>$this->manager->get_course()->id,
542 'otherusers'=>isset($this->otherusers));
543 $this->manager->get_moodlepage()->requires->yui_module($modules, $function, array($arguments));
548 * Gets the paging bar instance for this table
550 * @return paging_bar
552 public function get_paging_bar() {
553 if ($this->pagingbar == null) {
554 $this->pagingbar = new paging_bar($this->totalusers, $this->page, $this->perpage, $this->manager->get_moodlepage()->url, self::PAGEVAR);
556 return $this->pagingbar;
560 * Gets the direction icon for the sortable field within this table
562 * @param core_renderer $output
563 * @param string $field
564 * @return string
566 protected function get_direction_icon($output, $field) {
567 $direction = self::DEFAULTSORTDIRECTION;
568 if ($this->sort == $field) {
569 $direction = $this->sortdirection;
571 if ($direction === 'ASC') {
572 return $output->pix_icon('t/sort_asc', get_string('sort'));
573 } else {
574 return $output->pix_icon('t/sort_desc', get_string('sort'));
579 * Gets the params that will need to be added to the url in order to return to this page.
581 * @return array
583 public function get_url_params() {
584 return array(
585 self::PAGEVAR => $this->page,
586 self::PERPAGEVAR => $this->perpage,
587 self::SORTVAR => $this->sort,
588 self::SORTDIRECTIONVAR => $this->sortdirection
593 * Returns an array of URL params for both the table and the manager.
595 * @return array
597 public function get_combined_url_params() {
598 return $this->get_url_params() + $this->manager->get_url_params();
602 * Sets the bulk operations for this table.
604 * @param array $bulkoperations
606 public function set_bulk_user_enrolment_operations(array $bulkoperations) {
607 $this->bulkoperations = $bulkoperations;
611 * Returns an array of bulk operations.
613 * @return array
615 public function get_bulk_user_enrolment_operations() {
616 return $this->bulkoperations;
620 * Returns true fi the table is aware of any bulk operations that can be performed on users
621 * selected from the currently filtered enrolment plugins.
623 * @return bool
625 public function has_bulk_user_enrolment_operations() {
626 return !empty($this->bulkoperations);
631 * Table control used for enrolled users
633 * @copyright 2010 Sam Hemelryk
634 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
636 class course_enrolment_users_table extends course_enrolment_table {
641 * Table used for other users
643 * Other users are users who have roles but are not enrolled.
645 * @copyright 2010 Sam Hemelryk
646 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
648 class course_enrolment_other_users_table extends course_enrolment_table {
651 * Constructs the table
653 * @param course_enrolment_manager $manager
655 public function __construct(course_enrolment_manager $manager) {
656 parent::__construct($manager);
657 $this->attributes = array('class'=>'userenrolment otheruserenrolment');
661 * Gets a button to search users and assign them roles in the course.
663 * @staticvar int $count
664 * @param int $page
665 * @return single_button
667 public function get_user_search_button() {
668 static $count = 0;
669 if (!has_capability('moodle/role:assign', $this->manager->get_context())) {
670 return false;
672 $count++;
673 $url = new moodle_url('/admin/roles/assign.php', array('contextid'=>$this->manager->get_context()->id, 'sesskey'=>sesskey()));
674 $control = new single_button($url, get_string('assignroles', 'role'), 'get');
675 $control->class = 'singlebutton assignuserrole instance'.$count;
676 if ($count == 1) {
677 $this->manager->get_moodlepage()->requires->strings_for_js(array(
678 'ajaxoneuserfound',
679 'ajaxxusersfound',
680 'ajaxxmoreusersfound',
681 'ajaxnext25',
682 'enrol',
683 'enrolmentoptions',
684 'enrolusers',
685 'enrolxusers',
686 'errajaxfailedenrol',
687 'errajaxsearch',
688 'foundxcohorts',
689 'none',
690 'usersearch',
691 'unlimitedduration',
692 'startdatetoday',
693 'durationdays',
694 'enrolperiod'), 'enrol');
695 $this->manager->get_moodlepage()->requires->string_for_js('assignrole', 'role');
697 $modules = array('moodle-enrol-otherusersmanager', 'moodle-enrol-otherusersmanager-skin');
698 $function = 'M.enrol.otherusersmanager.init';
699 $arguments = array(
700 'courseId'=> $this->manager->get_course()->id,
701 'ajaxUrl' => '/enrol/ajax.php',
702 'url' => $this->manager->get_moodlepage()->url->out(false));
703 $this->manager->get_moodlepage()->requires->yui_module($modules, $function, array($arguments));
705 return $control;