enrol MDL-22854 New ajaxified enrolment interface
[moodle.git] / enrol / renderer.php
1 <?php
3 // This file is part of Moodle - http://moodle.org/
4 //
5 // Moodle is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // Moodle is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
18 /**
19  * This is the main renderer for the enrol section.
20  *
21  * @package   moodlecore
22  * @copyright 2010 Sam Hemelryk
23  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24  */
26 /**
27  * This is the core renderer
28  *
29  * @copyright 2010 Sam Hemelryk
30  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
31  */
32 class core_enrol_renderer extends plugin_renderer_base {
34     /**
35      * Renders a course enrolment table
36      *
37      * @param course_enrolment_table $table
38      * @return string
39      */
40     protected function render_course_enrolment_table(course_enrolment_table $table) {
41         $content = '';
42         $enrolmentselector = $table->get_enrolment_selector($this->page);
43         if ($enrolmentselector) {
44             $content .= $this->output->render($enrolmentselector);
45         }
46         $content  .= $this->output->render($table->get_enrolment_type_filter());
47         $content .= $this->output->render($table->get_paging_bar());
48         $content .= html_writer::table($table);
49         $content .= $this->output->render($table->get_paging_bar());
50         $enrolmentselector = $table->get_enrolment_selector($this->page);
51         if ($enrolmentselector) {
52             $content .= $this->output->render($enrolmentselector);
53         }
54         return $content;
55     }
57     /**
58      * Generates HTML to display the users roles and any available actions
59      *
60      * @param int $userid
61      * @param array $roles
62      * @param array $assignableroles
63      * @param moodle_url $pageurl
64      * @return string
65      */
66     public function user_roles_and_actions($userid, $roles, $assignableroles, $canassign, $pageurl) {
67         $iconenroladd    = $this->output->pix_url('t/enroladd');
68         $iconenrolremove = $this->output->pix_url('t/delete');
70         // get list of roles
71         $rolesoutput = '';
72         foreach ($roles as $roleid=>$role) {
73             if ($canassign && !$role['unchangeable']) {
74                 $strunassign = get_string('unassignarole', 'role', $role['text']);
75                 $icon = html_writer::empty_tag('img', array('alt'=>$strunassign, 'src'=>$iconenrolremove));
76                 $url = new moodle_url($pageurl, array('action'=>'unassign', 'role'=>$roleid, 'user'=>$userid));
77                 $rolesoutput .= html_writer::tag('div', $role['text'] . html_writer::link($url, $icon, array('class'=>'unassignrolelink', 'rel'=>$roleid, 'title'=>$strunassign)), array('class'=>'role role_'.$roleid));
78             } else {
79                 $rolesoutput .= html_writer::tag('div', $role['text'], array('class'=>'role unchangeable', 'rel'=>$roleid));
80             }
81         }
82         $output = '';
83         if (!empty($assignableroles) && $canassign) {
84             $roleids = array_keys($roles);
85             $hasallroles = true;
86             foreach (array_keys($assignableroles) as $key) {
87                 if (!in_array($key, $roleids)) {
88                     $hasallroles = false;
89                     break;
90                 }
91             }
92             if (!$hasallroles) {
93                 $url = new moodle_url($pageurl, array('action'=>'assign', 'user'=>$userid));
94                 $icon = html_writer::empty_tag('img', array('alt'=>get_string('assignroles', 'role'), 'src'=>$iconenroladd));
95                 $output = html_writer::tag('div', html_writer::link($url, $icon, array('class'=>'assignrolelink', 'title'=>get_string('assignroles', 'role'))), array('class'=>'addrole'));
96             }
97         }
98         $output .= html_writer::tag('div', $rolesoutput, array('class'=>'roles'));
99         return $output;
100     }
102     /**
103      * Generates the HTML to view the users groups and available group actions
104      *
105      * @param int $userid
106      * @param array $groups
107      * @param array $allgroups
108      * @param bool $canmanagegroups
109      * @param moodle_url $pageurl
110      * @return string
111      */
112     public function user_groups_and_actions($userid, $groups, $allgroups, $canmanagegroups, $pageurl) {
113         $iconenroladd    = $this->output->pix_url('t/enroladd');
114         $iconenrolremove = $this->output->pix_url('t/delete');
115         $straddgroup = get_string('addgroup', 'group');
117         $groupoutput = '';
118         foreach($groups as $groupid=>$name) {
119             if ($canmanagegroups) {
120                 $icon = html_writer::empty_tag('img', array('alt'=>get_string('removefromgroup', 'group', $name), 'src'=>$iconenrolremove));
121                 $url = new moodle_url($pageurl, array('action'=>'removemember', 'group'=>$groupid, 'user'=>$userid));
122                 $groupoutput .= html_writer::tag('div', $name . html_writer::link($url, $icon), array('class'=>'group', 'rel'=>$groupid));
123             } else {
124                 $groupoutput .= html_writer::tag('div', $name, array('class'=>'group', 'rel'=>$groupid));
125             }
126         }
127         $groupoutput = html_writer::tag('div', $groupoutput, array('class'=>'groups'));
128         if ($canmanagegroups && (count($groups) < count($allgroups))) {
129             $icon = html_writer::empty_tag('img', array('alt'=>$straddgroup, 'src'=>$iconenroladd));
130             $url = new moodle_url($pageurl, array('action'=>'addmember', 'user'=>$userid));
131             $groupoutput .= html_writer::tag('div', html_writer::link($url, $icon), array('class'=>'addgroup'));
132         }
133         return $groupoutput;
134     }
136     /**
137      * Generates the HTML for the given enrolments + available actions
138      *
139      * @param int $userid
140      * @param array $enrolments
141      * @param moodle_url $pageurl
142      * @return string
143      */
144     public function user_enrolments_and_actions($userid, $enrolments, $pageurl) {
145         $iconedit        = $this->output->pix_url('t/edit');
146         $iconenrolremove = $this->output->pix_url('t/delete');
147         $strunenrol = get_string('unenrol', 'enrol');
148         $stredit = get_string('edit');
150         $output = '';
151         foreach ($enrolments as $ueid=>$enrolment) {
152             $enrolmentoutput = $enrolment['text'].' '.$enrolment['period'];
153             if ($enrolment['dimmed']) {
154                 $enrolmentoutput = html_writer::tag('span', $enrolmentoutput, array('class'=>'dimmed_text'));
155             }
156             if ($enrolment['canunenrol']) {
157                 $icon = html_writer::empty_tag('img', array('alt'=>$strunenrol, 'src'=>$iconenrolremove));
158                 $url = new moodle_url($pageurl, array('action'=>'unenrol', 'ue'=>$ueid));
159                 $enrolmentoutput .= html_writer::link($url, $icon, array('class'=>'unenrollink', 'rel'=>$ueid));
160             }
161             if ($enrolment['canmanage']) {
162                 $icon = html_writer::empty_tag('img', array('alt'=>$stredit, 'src'=>$iconedit));
163                 $url = new moodle_url($url, array('action'=>'edit', 'ue'=>$ueid));
164                 $enrolmentoutput .= html_writer::link($url, $icon, array('class'=>'editenrollink', 'rel'=>$ueid));
165             }
166             $output .= html_writer::tag('div', $enrolmentoutput, array('class'=>'enrolment'));
167         }
168         return $output;
169     }
173 /**
174  * Main course enrolment table
175  *
176  * This table is used to display the enrolment information for a course.
177  * It requires that a course enrolment manager be provided during constuct with
178  * provides all of the information for the table.
179  * The control then produces the table, the paging, and the associated JS actions
180  * for the page.
181  *
182  * @package    core
183  * @subpackage enrol
184  * @copyright  2010 Sam Hemelryk
185  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
186  */
187 class course_enrolment_table extends html_table implements renderable {
189     /**
190      * The get/post variable that is used to identify the page.
191      * Default: page
192      */
193     const PAGEVAR = 'page';
195     /**
196      * The get/post variable to is used to identify the number of items to display
197      * per page.
198      * Default: perpage
199      */
200     const PERPAGEVAR = 'perpage';
202     /**
203      * The get/post variable that is used to identify the sort field for the table.
204      * Default: sort
205      */
206     const SORTVAR = 'sort';
208     /**
209      * The get/post variable that is used to identify the sort direction for the table.
210      * Default: dir
211      */
212     const SORTDIRECTIONVAR = 'dir';
214     /**
215      * The default number of items per page.
216      * Default: 20
217      */
218     const DEFAULTPERPAGE = 20;
220     /**
221      * The default sort, options are course_enrolment_table::$sortablefields
222      * Default: lastname
223      */
224     const DEFAULTSORT = 'lastname';
226     /**
227      * The default direction
228      * Default: ASC
229      */
230     const DEFAULTSORTDIRECTION = 'ASC';
232     /**
233      * The current page, starting from 0
234      * @var int
235      */
236     public $page = 0;
238     /**
239      * The total number of pages
240      * @var int
241      */
242     public $pages = 0;
244     /**
245      * The number of items to display per page
246      * @var int
247      */
248     public $perpage = 0;
250     /**
251      * The URL of the page for this table
252      * @var moodle_url
253      */
254     public $pageurl;
256     /**
257      * The sort field for this table, should be one of course_enrolment_table::$sortablefields
258      * @var string
259      */
260     public $sort;
262     /**
263      * The sort direction, either ASC or DESC
264      * @var string
265      */
266     public $sortdirection;
268     /**
269      * The course manager this table is displaying for
270      * @var course_enrolment_manager
271      */
272     protected $manager;
274     /**
275      * The paging bar that controls the paging for this table
276      * @var paging_bar
277      */
278     protected $pagingbar = null;
280     /**
281      * The total number of users enrolled in the course
282      * @var int
283      */
284     protected $totalusers = null;
286     /**
287      * The users enrolled in this course
288      * @var array
289      */
290     protected $users = null;
292     /**
293      * The fields for this table
294      * @var array
295      */
296     protected $fields = array();
298     protected static $sortablefields = array('firstname', 'lastname', 'email', 'lastaccess');
300     /**
301      * Constructs the table
302      *
303      * @param course_enrolment_manager $manager
304      */
305     public function __construct(course_enrolment_manager $manager, moodle_url $pageurl) {
307         $this->manager = $manager;
308         $this->pageurl = $pageurl;
309         
310         $this->page =           optional_param(self::PAGEVAR, 0, PARAM_INT);
311         $this->perpage =        optional_param(self::PERPAGEVAR, self::DEFAULTPERPAGE, PARAM_INT);
312         $this->sort =           optional_param(self::SORTVAR, self::DEFAULTSORT, PARAM_ALPHA);
313         $this->sortdirection  = optional_param(self::SORTDIRECTIONVAR, self::DEFAULTSORTDIRECTION, PARAM_ALPHA);
315         $this->attributes = array('class'=>'userenrolment');
316         if (!in_array($this->sort, self::$sortablefields)) {
317             $this->sort = self::DEFAULTSORT;
318         }
319         if ($this->page < 0) {
320             $this->page = 0;
321         }
322         if ($this->sortdirection !== 'ASC' && $this->sortdirection !== 'DESC') {
323             $this->sortdirection = self::DEFAULTSORTDIRECTION;
324         }
326         $this->id = html_writer::random_id();
327         $this->set_total_users($manager->get_total_users());
328     }
330     /**
331      * Gets the sort direction for a given field
332      *
333      * @param string $field
334      * @return string ASC or DESC
335      */
336     public function get_field_sort_direction($field) {
337         if ($field == $this->sort) {
338             return ($this->sortdirection == 'ASC')?'DESC':'ASC';
339         }
340         return self::DEFAULTSORTDIRECTION;
341     }
343     /**
344      * Sets the fields for this table. These get added to the tables head as well.
345      *
346      * You can also use a multi dimensional array for this to have multiple fields
347      * in a single column
348      *
349      * @param array $fields An array of fields to set
350      * @param string $output
351      */
352     public function set_fields($fields, $output=null) {
353         global $OUTPUT;
354         if ($output === null) {
355             $output = $OUTPUT;
356         }
357         $this->fields = $fields;
358         $this->head = array();
359         $this->colclasses = array();
360         $this->align = array();
361         $url = new moodle_url($this->pageurl, $this->get_url_params()+$this->manager->get_url_params());
362         foreach ($fields as $name => $label) {
363             $newlabel = '';
364             if (is_array($label)) {
365                 $bits = array();
366                 foreach ($label as $n => $l) {
367                     if ($l === false) {
368                         continue;
369                     }
370                     if (!in_array($n, self::$sortablefields)) {
371                         $bits[] = $l;
372                     } else {
373                         $link = html_writer::link(new moodle_url($url, array(self::SORTVAR=>$n)), $fields[$name][$n]);
374                         if ($this->sort == $n) {
375                             $link .= ' '.html_writer::link(new moodle_url($url, array(self::SORTVAR=>$n, self::SORTDIRECTIONVAR=>$this->get_field_sort_direction($n))), $this->get_direction_icon($output, $n));
376                         }
377                         $bits[] = html_writer::tag('span', $link, array('class'=>'subheading_'.$n));
379                     }
380                 }
381                 $newlabel = join(' / ', $bits);
382             } else {
383                 if (!in_array($name, self::$sortablefields)) {
384                     $newlabel = $label;
385                 } else {
386                     $newlabel  = html_writer::link(new moodle_url($url, array(self::SORTVAR=>$name)), $fields[$name]);
387                     if ($this->sort == $name) {
388                         $newlabel .= ' '.html_writer::link(new moodle_url($url, array(self::SORTVAR=>$name, self::SORTDIRECTIONVAR=>$this->get_field_sort_direction($name))), $this->get_direction_icon($output, $name));
389                     }
390                 }
391             }
392             $this->head[] = $newlabel;
393             $this->colclasses[] = 'field col_'.$name;
394         }
395     }
396     /**
397      * Sets the total number of users
398      *
399      * @param int $totalusers
400      */
401     public function set_total_users($totalusers) {
402         $this->totalusers = $totalusers;
403         $this->pages = ceil($this->totalusers / $this->perpage);
404         if ($this->page > $this->pages) {
405             $this->page = $this->pages;
406         }
407     }
408     /**
409      
410      */
411     /**
412      * Sets the users for this table
413      *
414      * @param array $users
415      * @param moodle_page $page
416      */
417     public function set_users(array $users, moodle_page $page=null) {
418         global $PAGE;
419         if ($page === null) {
420             $page = $PAGE;
421         }
422         foreach ($users as $userid=>$user) {
423             $user = (array)$user;
424             $row = new html_table_row();
425             $row->attributes = array('class' => 'userinforow');
426             $row->id = 'user_'.$userid;
427             $row->cells = array();
428             foreach ($this->fields as $field => $label) {
429                 if (is_array($label)) {
430                     $bits = array();
431                     foreach (array_keys($label) as $subfield) {
432                         if (array_key_exists($subfield, $user)) {
433                             $bits[] = html_writer::tag('div', $user[$subfield], array('class'=>'subfield subfield_'.$subfield));
434                         }
435                     }
436                     if (empty($bits)) {
437                         $bits[] = '&nbsp;';
438                     }
439                     $row->cells[] = new html_table_cell(join(' ', $bits));
440                 } else {
441                     if (!array_key_exists($field, $user)) {
442                         $user[$field] = '&nbsp;';
443                     }
444                     $row->cells[] = new html_table_cell($user[$field]);
445                 }
446             }
447             $this->data[] = $row;
448         }
449         if (has_capability('moodle/role:assign', $this->manager->get_context())) {
450             $arguments = array(array('containerId'=>$this->id, 'userIds'=>array_keys($users), 'courseId'=>$this->manager->get_course()->id));
451             $page->requires->yui_module(array('moodle-enrol-rolemanager', 'moodle-enrol-rolemanager-skin'), 'M.enrol.rolemanager.init', $arguments);
452         }
453     }
454     
455     /**
456      * Gets the paging bar instance for this table
457      *
458      * @return paging_bar
459      */
460     public function get_paging_bar() {
461         if ($this->pagingbar == null) {
462             $this->pagingbar = new paging_bar($this->totalusers, $this->page, $this->perpage, $this->pageurl, self::PAGEVAR);
463         }
464         return $this->pagingbar;
465     }
467     /**
468      * Gets the direction icon for the sortable field within this table
469      *
470      * @param core_renderer $output
471      * @param string $field
472      * @return string
473      */
474     protected function get_direction_icon($output, $field) {
475         $direction = self::DEFAULTSORTDIRECTION;
476         if ($this->sort == $field) {
477             $direction = $this->sortdirection;
478         }
479         if ($direction === 'ASC') {
480             return html_writer::empty_tag('img', array('alt'=>'', 'src'=>$output->pix_url('t/down')));
481         } else {
482             return html_writer::empty_tag('img', array('alt'=>'', 'src'=>$output->pix_url('t/up')));
483         }
484     }
486     /**
487      * Gets the params that will need to be added to the url in order to return to this page.
488      *
489      * @return array
490      */
491     public function get_url_params() {
492         return array(
493             self::PAGEVAR => $this->page,
494             self::PERPAGEVAR => $this->perpage,
495             self::SORTVAR => $this->sort,
496             self::SORTDIRECTIONVAR => $this->sortdirection
497         );
498     }
500     /**
501      * Gets the enrolment type filter control for this table
502      *
503      * @return single_select
504      */
505     public function get_enrolment_type_filter() {
506         $url = new moodle_url($this->pageurl, $this->manager->get_url_params()+$this->get_url_params());
507         $selector = new single_select($url, 'ifilter', array(0=>get_string('all')) + $this->manager->get_enrolment_instance_names(), $this->manager->get_enrolment_filter(), array());
508         $selector->set_label( get_string('enrolmentinstances', 'enrol'));
509         return $selector;
510     }
512     /**
513      * Gets the enrolment selector control for this table and initialises its
514      * JavaScript
515      *
516      * @return single_button|url_select
517      */
518     public function get_enrolment_selector(moodle_page $page) {
519         static $count = 0;
521         $instances  = $this->manager->get_enrolment_instances();
522         $plugins    = $this->manager->get_enrolment_plugins();
523         // print enrol link or selection
524         $links = array();
525         foreach($instances as $instance) {
526             $plugin = $plugins[$instance->enrol];
527             if ($link = $plugin->get_manual_enrol_link($instance)) {
528                 $links[$instance->id] = $link;
529             }
530         }
531         if (!empty($links)) {
532             $arguments = array();
533             $count ++;
534             if (count($links) == 1) {
535                 $control = new single_button(reset($links), get_string('enrolusers', 'enrol_manual'), 'get');
536                 $control->class = 'singlebutton enrolusersbutton instance'.$count;
537                 $control->formid = 'manuallyenrol_single_'+$count;
538                 $arguments[] = array('id'=>key($links), 'name'=>$plugins[$instances[key($links)]->enrol]->get_instance_name($instances[key($links)]));
539             } else if (count($links) > 1) {
540                 $inames     = $this->manager->get_enrolment_instance_names();
541                 $options = array();
542                 foreach ($links as $i=>$link) {
543                     $options[$link->out(false)] = $inames[$i];
544                     $arguments[] = array('id'=>$i, 'name'=>$plugins[$instances[$i]->enrol]->get_instance_name($instances[$i]));
545                 }
546                 $control = new url_select($options, '', array(''=>get_string('enrolusers', 'enrol_manual').'...'));
547                 $control->class = 'singlebutton enrolusersbutton instance'.$count;
548                 $control->formid = 'manuallyenrol_select_'+$count;
549             }
550             $course = $this->manager->get_course();
551             $url = new moodle_url($this->pageurl, $this->manager->get_url_params()+$this->get_url_params());
552             $timeformat = get_string('strftimedatefullshort');
553             $today = time();
554             $today = make_timestamp(date('Y', $today), date('m', $today), date('d', $today), 0, 0, 0);
555             $startdateoptions = array();
556             if ($course->startdate > 0) {
557                 $startdateoptions[2] = get_string('coursestart') . ' (' . userdate($course->startdate, $timeformat) . ')';
558             }
559             $startdateoptions[3] = get_string('today') . ' (' . userdate($today, $timeformat) . ')' ;
561             if ($count == 1) {
562                 $page->requires->strings_for_js(array(
563                     'ajaxoneuserfound',
564                     'ajaxxusersfound',
565                     'ajaxnext25',
566                     'enrol',
567                     'enrolmentoptions',
568                     'enrolusers',
569                     'errajaxfailedenrol',
570                     'errajaxsearch',
571                     'none',
572                     'usersearch',
573                     'unlimitedduration',
574                     'startdatetoday',
575                     'durationdays',
576                     'enrolperiod'), 'enrol');
577                 $page->requires->string_for_js('assignroles', 'role');
578                 $page->requires->string_for_js('startingfrom', 'moodle');
581                 $arguments = array(array(
582                     'instances'=>$arguments,
583                     'courseid'=>$course->id,
584                     'ajaxurl'=>'/enrol/ajax.php',
585                     'url'=>$url->out(false),
586                     'optionsStartDate'=>$startdateoptions));
587                 $page->requires->yui_module(array('moodle-enrol-enrolmentmanager', 'moodle-enrol-enrolmentmanager-skin'), 'M.enrol.enrolmentmanager.init', $arguments);
588             }
589             return $control;
590         }
591         return null;
592     }