Merge branch 'MDL-64173-master' of git://github.com/bmbrands/moodle
[moodle.git] / enrol / renderer.php
bloba1bc2417fbf70e35361599638fbc2b9a9cc76742
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 m-y-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', 'idnumber', 'email', 'phone1', 'phone2', 'institution', 'department', 'lastaccess', 'lastcourseaccess' );
359 * Constructs the table
361 * @param course_enrolment_manager $manager
363 public function __construct(course_enrolment_manager $manager) {
365 $this->manager = $manager;
367 $this->page = optional_param(self::PAGEVAR, 0, PARAM_INT);
368 $this->perpage = optional_param(self::PERPAGEVAR, self::DEFAULTPERPAGE, PARAM_INT);
369 $this->sort = optional_param(self::SORTVAR, self::DEFAULTSORT, PARAM_ALPHANUM);
370 $this->sortdirection = optional_param(self::SORTDIRECTIONVAR, self::DEFAULTSORTDIRECTION, PARAM_ALPHA);
372 $this->attributes = array('class'=>'userenrolment');
373 if (!in_array($this->sort, self::$sortablefields)) {
374 $this->sort = self::DEFAULTSORT;
376 if ($this->page < 0) {
377 $this->page = 0;
379 if ($this->sortdirection !== 'ASC' && $this->sortdirection !== 'DESC') {
380 $this->sortdirection = self::DEFAULTSORTDIRECTION;
383 $this->id = html_writer::random_id();
385 // Collect the bulk operations for the currently filtered plugin if there is one.
386 $plugin = $manager->get_filtered_enrolment_plugin();
387 if ($plugin and enrol_is_enabled($plugin->get_name())) {
388 $this->bulkoperations = $plugin->get_bulk_operations($manager);
393 * Returns an array of enrol_user_buttons that are created by the different
394 * enrolment plugins available.
396 * @return array
398 public function get_manual_enrol_buttons() {
399 return $this->manager->get_manual_enrol_buttons();
403 * Gets the sort direction for a given field
405 * @param string $field
406 * @return string ASC or DESC
408 public function get_field_sort_direction($field) {
409 if ($field == $this->sort) {
410 return ($this->sortdirection == 'ASC')?'DESC':'ASC';
412 return self::DEFAULTSORTDIRECTION;
416 * Sets the fields for this table. These get added to the tables head as well.
418 * You can also use a multi dimensional array for this to have multiple fields
419 * in a single column
421 * @param array $fields An array of fields to set
422 * @param string $output
424 public function set_fields($fields, $output) {
425 $this->fields = $fields;
426 $this->head = array();
427 $this->colclasses = array();
428 $this->align = array();
429 $url = $this->manager->get_moodlepage()->url;
431 if (!empty($this->bulkoperations)) {
432 // If there are bulk operations add a column for checkboxes.
433 $this->head[] = '';
434 $this->colclasses[] = 'field col_bulkops';
437 foreach ($fields as $name => $label) {
438 $newlabel = '';
439 if (is_array($label)) {
440 $bits = array();
441 foreach ($label as $n => $l) {
442 if ($l === false) {
443 continue;
445 if (!in_array($n, self::$sortablefields)) {
446 $bits[] = $l;
447 } else {
448 $sorturl = new moodle_url($url, array(self::SORTVAR => $n, self::SORTDIRECTIONVAR => $this->get_field_sort_direction($n)));
449 $link = html_writer::link($sorturl, $fields[$name][$n]);
450 if ($this->sort == $n) {
451 $link .= $this->get_direction_icon($output, $n);
453 $bits[] = html_writer::tag('span', $link, array('class'=>'subheading_'.$n));
457 $newlabel = join(' / ', $bits);
458 } else {
459 if (!in_array($name, self::$sortablefields)) {
460 $newlabel = $label;
461 } else {
462 $sorturl = new moodle_url($url, array(self::SORTVAR => $name, self::SORTDIRECTIONVAR => $this->get_field_sort_direction($name)));
463 $newlabel = html_writer::link($sorturl, $fields[$name]);
464 if ($this->sort == $name) {
465 $newlabel .= $this->get_direction_icon($output, $name);
469 $this->head[] = $newlabel;
470 $this->colclasses[] = 'field col_'.$name;
474 * Sets the total number of users
476 * @param int $totalusers
478 public function set_total_users($totalusers) {
479 $this->totalusers = $totalusers;
480 $this->pages = ceil($this->totalusers / $this->perpage);
481 if ($this->page > $this->pages) {
482 $this->page = $this->pages;
486 * Sets the users for this table
488 * @param array $users
489 * @return void
491 public function set_users(array $users) {
492 $this->users = $users;
493 $hasbulkops = !empty($this->bulkoperations);
494 foreach ($users as $userid=>$user) {
495 $user = (array)$user;
496 $row = new html_table_row();
497 $row->attributes = array('class' => 'userinforow');
498 $row->id = 'user_'.$userid;
499 $row->cells = array();
500 if ($hasbulkops) {
501 // Add a checkbox into the first column.
502 $input = html_writer::empty_tag('input', array('type' => 'checkbox', 'name' => 'bulkuser[]', 'value' => $userid));
503 $row->cells[] = new html_table_cell($input);
505 foreach ($this->fields as $field => $label) {
506 if (is_array($label)) {
507 $bits = array();
508 foreach (array_keys($label) as $subfield) {
509 if (array_key_exists($subfield, $user)) {
510 $bits[] = html_writer::tag('div', $user[$subfield], array('class'=>'subfield subfield_'.$subfield));
513 if (empty($bits)) {
514 $bits[] = '&nbsp;';
516 $row->cells[] = new html_table_cell(join(' ', $bits));
517 } else {
518 if (!array_key_exists($field, $user)) {
519 $user[$field] = '&nbsp;';
521 $row->cells[] = new html_table_cell($user[$field]);
524 $this->data[] = $row;
528 public function initialise_javascript() {
529 if (has_capability('moodle/role:assign', $this->manager->get_context())) {
530 $this->manager->get_moodlepage()->requires->strings_for_js(array(
531 'assignroles',
532 'confirmunassign',
533 'confirmunassigntitle',
534 'confirmunassignyes',
535 'confirmunassignno'
536 ), 'role');
537 $modules = array('moodle-enrol-rolemanager', 'moodle-enrol-rolemanager-skin');
538 $function = 'M.enrol.rolemanager.init';
539 $arguments = array(
540 'containerId'=>$this->id,
541 'userIds'=>array_keys($this->users),
542 'courseId'=>$this->manager->get_course()->id,
543 'otherusers'=>isset($this->otherusers));
544 $this->manager->get_moodlepage()->requires->yui_module($modules, $function, array($arguments));
549 * Gets the paging bar instance for this table
551 * @return paging_bar
553 public function get_paging_bar() {
554 if ($this->pagingbar == null) {
555 $this->pagingbar = new paging_bar($this->totalusers, $this->page, $this->perpage, $this->manager->get_moodlepage()->url, self::PAGEVAR);
557 return $this->pagingbar;
561 * Gets the direction icon for the sortable field within this table
563 * @param core_renderer $output
564 * @param string $field
565 * @return string
567 protected function get_direction_icon($output, $field) {
568 $direction = self::DEFAULTSORTDIRECTION;
569 if ($this->sort == $field) {
570 $direction = $this->sortdirection;
572 if ($direction === 'ASC') {
573 return $output->pix_icon('t/sort_asc', get_string('sort'));
574 } else {
575 return $output->pix_icon('t/sort_desc', get_string('sort'));
580 * Gets the params that will need to be added to the url in order to return to this page.
582 * @return array
584 public function get_url_params() {
585 return array(
586 self::PAGEVAR => $this->page,
587 self::PERPAGEVAR => $this->perpage,
588 self::SORTVAR => $this->sort,
589 self::SORTDIRECTIONVAR => $this->sortdirection
594 * Returns an array of URL params for both the table and the manager.
596 * @return array
598 public function get_combined_url_params() {
599 return $this->get_url_params() + $this->manager->get_url_params();
603 * Sets the bulk operations for this table.
605 * @param array $bulkoperations
607 public function set_bulk_user_enrolment_operations(array $bulkoperations) {
608 $this->bulkoperations = $bulkoperations;
612 * Returns an array of bulk operations.
614 * @return array
616 public function get_bulk_user_enrolment_operations() {
617 return $this->bulkoperations;
621 * Returns true fi the table is aware of any bulk operations that can be performed on users
622 * selected from the currently filtered enrolment plugins.
624 * @return bool
626 public function has_bulk_user_enrolment_operations() {
627 return !empty($this->bulkoperations);
632 * Table control used for enrolled users
634 * @copyright 2010 Sam Hemelryk
635 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
637 class course_enrolment_users_table extends course_enrolment_table {
642 * Table used for other users
644 * Other users are users who have roles but are not enrolled.
646 * @copyright 2010 Sam Hemelryk
647 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
649 class course_enrolment_other_users_table extends course_enrolment_table {
651 public $otherusers = true;
654 * Constructs the table
656 * @param course_enrolment_manager $manager
658 public function __construct(course_enrolment_manager $manager) {
659 parent::__construct($manager);
660 $this->attributes = array('class'=>'userenrolment otheruserenrolment');
664 * Gets a button to search users and assign them roles in the course.
666 * @staticvar int $count
667 * @param int $page
668 * @return single_button
670 public function get_user_search_button() {
671 static $count = 0;
672 if (!has_capability('moodle/role:assign', $this->manager->get_context())) {
673 return false;
675 $count++;
676 $url = new moodle_url('/admin/roles/assign.php', array('contextid'=>$this->manager->get_context()->id, 'sesskey'=>sesskey()));
677 $control = new single_button($url, get_string('assignroles', 'role'), 'get');
678 $control->class = 'singlebutton assignuserrole instance'.$count;
679 if ($count == 1) {
680 $this->manager->get_moodlepage()->requires->strings_for_js(array(
681 'ajaxoneuserfound',
682 'ajaxxusersfound',
683 'ajaxnext25',
684 'enrol',
685 'enrolmentoptions',
686 'enrolusers',
687 'enrolxusers',
688 'errajaxfailedenrol',
689 'errajaxsearch',
690 'foundxcohorts',
691 'none',
692 'usersearch',
693 'unlimitedduration',
694 'startdatetoday',
695 'durationdays',
696 'enrolperiod'), 'enrol');
697 $this->manager->get_moodlepage()->requires->string_for_js('assignrole', 'role');
699 $modules = array('moodle-enrol-otherusersmanager', 'moodle-enrol-otherusersmanager-skin');
700 $function = 'M.enrol.otherusersmanager.init';
701 $arguments = array(
702 'courseId'=> $this->manager->get_course()->id,
703 'ajaxUrl' => '/enrol/ajax.php',
704 'url' => $this->manager->get_moodlepage()->url->out(false));
705 $this->manager->get_moodlepage()->requires->yui_module($modules, $function, array($arguments));
707 return $control;