MDL-41257 calendar: Day and Upcoming-Events view not processed through text_filters...
[moodle.git] / calendar / 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 file contains the renderers for the calendar within Moodle
20  *
21  * @copyright 2010 Sam Hemelryk
22  * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23  * @package calendar
24  */
26 if (!defined('MOODLE_INTERNAL')) {
27     die('Direct access to this script is forbidden.');    ///  It must be included from a Moodle page
28 }
30 /**
31  * The primary renderer for the calendar.
32  */
33 class core_calendar_renderer extends plugin_renderer_base {
35     /**
36      * Creates a basic export form
37      *
38      * @param bool $allowthisweek
39      * @param bool $allownextweek
40      * @param bool $allownextmonth
41      * @param int $userid
42      * @param string $authtoken
43      * @return string
44      */
45     public function basic_export_form($allowthisweek, $allownextweek, $allownextmonth, $userid, $authtoken) {
46         global $CFG;
48         $output  = html_writer::tag('div', get_string('export', 'calendar'), array('class'=>'header'));
49         $output .= html_writer::start_tag('fieldset');
50         $output .= html_writer::tag('legend', get_string('commontasks', 'calendar'));
51         $output .= html_writer::start_tag('form', array('action'=>new moodle_url('/calendar/export_execute.php'), 'method'=>'get'));
53         $output .= html_writer::tag('div', get_string('iwanttoexport', 'calendar'));
55         $output .= html_writer::start_tag('div', array('class'=>'indent'));
56         $output .= html_writer::empty_tag('input', array('type'=>'radio', 'name'=>'preset_what', 'id'=>'pw_all', 'value'=>'all', 'checked'=>'checked'));
57         $output .= html_writer::tag('label', get_string('eventsall', 'calendar'), array('for'=>'pw_all'));
58         $output .= html_writer::empty_tag('br');
59         $output .= html_writer::empty_tag('input', array('type'=>'radio', 'name'=>'preset_what', 'id'=>'pw_course', 'value'=>'courses'));
60         $output .= html_writer::tag('label', get_string('eventsrelatedtocourses', 'calendar'), array('for'=>'pw_course'));
61         $output .= html_writer::empty_tag('br');
62         $output .= html_writer::end_tag('div');
64         $output .= html_writer::tag('div', get_string('for', 'calendar').':');
66         $output .= html_writer::start_tag('div', array('class'=>'indent'));
67         if ($allowthisweek) {
68             $output .= html_writer::empty_tag('input', array('type'=>'radio', 'name'=>'preset_time', 'id'=>'pt_wknow', 'value'=>'weeknow', 'checked'=>'checked'));
69             $output .= html_writer::tag('label', get_string('weekthis', 'calendar'), array('for'=>'pt_wknow'));
70             $output .= html_writer::empty_tag('br');
71         }
72         if ($allownextweek) {
73             $output .= html_writer::empty_tag('input', array('type'=>'radio', 'name'=>'preset_time', 'id'=>'pt_wknext', 'value'=>'weeknext'));
74             $output .= html_writer::tag('label', get_string('weeknext', 'calendar'), array('for'=>'pt_wknext'));
75             $output .= html_writer::empty_tag('br');
76         }
77         $output .= html_writer::empty_tag('input', array('type'=>'radio', 'name'=>'preset_time', 'id'=>'pt_monnow', 'value'=>'monthnow'));
78         $output .= html_writer::tag('label', get_string('monththis', 'calendar'), array('for'=>'pt_monnow'));
79         $output .= html_writer::empty_tag('br');
80         if ($allownextmonth) {
81             $output .= html_writer::empty_tag('input', array('type'=>'radio', 'name'=>'preset_time', 'id'=>'pt_monnext', 'value'=>'monthnext'));
82             $output .= html_writer::tag('label', get_string('monthnext', 'calendar'), array('for'=>'pt_monnext'));
83             $output .= html_writer::empty_tag('br');
84         }
85         $output .= html_writer::empty_tag('input', array('type'=>'radio', 'name'=>'preset_time', 'id'=>'pt_recupc', 'value'=>'recentupcoming'));
86         $output .= html_writer::tag('label', get_string('recentupcoming', 'calendar'), array('for'=>'pt_recupc'));
87         $output .= html_writer::empty_tag('br');
89         if ($CFG->calendar_customexport) {
90             $a = new stdClass();
91             $now = time();
92             $time = $now - $CFG->calendar_exportlookback * DAYSECS;
93             $a->timestart = userdate($time, get_string('strftimedatefullshort', 'langconfig'));
94             $time = $now + $CFG->calendar_exportlookahead * DAYSECS;
95             $a->timeend = userdate($time, get_string('strftimedatefullshort', 'langconfig'));
96             $output .= html_writer::empty_tag('input', array('type' => 'radio', 'name' => 'preset_time', 'id' => 'pt_custom', 'value' => 'custom'));
97             $output .= html_writer::tag('label', get_string('customexport', 'calendar', $a), array('for' => 'pt_custom'));
98             $output .= html_writer::empty_tag('br');
99         }
101         $output .= html_writer::end_tag('div');
102         $output .= html_writer::start_tag('div', array('class'=>'rightalign'));
103         $output .= html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>'cal_d', 'value'=>''));
104         $output .= html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>'cal_m', 'value'=>''));
105         $output .= html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>'cal_y', 'value'=>''));
106         $output .= html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>'userid', 'value'=>$userid));
107         $output .= html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>'authtoken', 'value'=>$authtoken));
109         $output .= html_writer::empty_tag('input', array('type'=>'submit', 'name' => 'generateurl', 'id'=>'generateurl', 'value'=>get_string('generateurlbutton', 'calendar')));
110         $output .= html_writer::empty_tag('input', array('type'=>'submit', 'value'=>get_string('exportbutton', 'calendar')));
112         $output .= html_writer::end_tag('div');
114         $output .= html_writer::end_tag('form');
115         $output .= html_writer::end_tag('fieldset');
117         $output .= html_writer::start_tag('div', array('id'=>'urlbox', 'style'=>'display:none;'));
118         $output .= html_writer::tag('p', get_string('urlforical', 'calendar'));
119         $output .= html_writer::tag('div', '', array('id'=>'url', 'style'=>'overflow:scroll;width:650px;'));
120         $output .= html_writer::end_tag('div');
122         return $output;
123     }
125     /**
126      * Starts the standard layout for the page
127      *
128      * @return string
129      */
130     public function start_layout() {
131         return html_writer::start_tag('div', array('class'=>'maincalendar'));
132     }
134     /**
135      * Creates the remainder of the layout
136      *
137      * @return string
138      */
139     public function complete_layout() {
140         return html_writer::end_tag('div');
141     }
143     /**
144      * Produces the content for the filters block (pretend block)
145      *
146      * @param int $courseid
147      * @param int $day
148      * @param int $month
149      * @param int $year
150      * @param int $view
151      * @param int $courses
152      * @return string
153      */
154     public function fake_block_filters($courseid, $day, $month, $year, $view, $courses) {
155         $returnurl = $this->page->url;
156         $returnurl->param('course', $courseid);
157         return html_writer::tag('div', calendar_filter_controls($returnurl), array('class'=>'calendar_filters filters'));
158     }
160     /**
161      * Produces the content for the three months block (pretend block)
162      *
163      * This includes the previous month, the current month, and the next month
164      *
165      * @param calendar_information $calendar
166      * @return string
167      */
168     public function fake_block_threemonths(calendar_information $calendar) {
169         // Get the calendar type we are using.
170         $calendartype = \core_calendar\type_factory::get_calendar_instance();
172         $date = $calendartype->timestamp_to_date_array($calendar->time);
174         $prevmonth = calendar_sub_month($date['mon'], $date['year']);
175         $prevmonthtime = $calendartype->convert_to_gregorian($prevmonth[1], $prevmonth[0], 1);
176         $prevmonthtime = make_timestamp($prevmonthtime['year'], $prevmonthtime['month'], $prevmonthtime['day'],
177             $prevmonthtime['hour'], $prevmonthtime['minute']);
179         $nextmonth = calendar_add_month($date['mon'], $date['year']);
180         $nextmonthtime = $calendartype->convert_to_gregorian($nextmonth[1], $nextmonth[0], 1);
181         $nextmonthtime = make_timestamp($nextmonthtime['year'], $nextmonthtime['month'], $nextmonthtime['day'],
182             $nextmonthtime['hour'], $nextmonthtime['minute']);
184         $content  = html_writer::start_tag('div', array('class' => 'minicalendarblock'));
185         $content .= calendar_get_mini($calendar->courses, $calendar->groups, $calendar->users, false, false, 'display', $calendar->courseid, $prevmonthtime);
186         $content .= html_writer::end_tag('div');
187         $content .= html_writer::start_tag('div', array('class' => 'minicalendarblock'));
188         $content .= calendar_get_mini($calendar->courses, $calendar->groups, $calendar->users, false, false, 'display', $calendar->courseid, $calendar->time);
189         $content .= html_writer::end_tag('div');
190         $content .= html_writer::start_tag('div', array('class' => 'minicalendarblock'));
191         $content .= calendar_get_mini($calendar->courses, $calendar->groups, $calendar->users, false, false, 'display', $calendar->courseid, $nextmonthtime);
192         $content .= html_writer::end_tag('div');
193         return $content;
194     }
196     /**
197      * Adds a pretent calendar block
198      *
199      * @param block_contents $bc
200      * @param mixed $pos BLOCK_POS_RIGHT | BLOCK_POS_LEFT
201      */
202     public function add_pretend_calendar_block(block_contents $bc, $pos=BLOCK_POS_RIGHT) {
203         $this->page->blocks->add_fake_block($bc, $pos);
204     }
206     /**
207      * Creates a button to add a new event
208      *
209      * @param int $courseid
210      * @param int $day
211      * @param int $month
212      * @param int $year
213      * @param int $time the unixtime, used for multiple calendar support. The values $day,
214      *     $month and $year are kept for backwards compatibility.
215      * @return string
216      */
217     protected function add_event_button($courseid, $day = null, $month = null, $year = null, $time = null) {
218         // If a day, month and year were passed then convert it to a timestamp. If these were passed
219         // then we can assume the day, month and year are passed as Gregorian, as no where in core
220         // should we be passing these values rather than the time. This is done for BC.
221         if (!empty($day) && !empty($month) && !empty($year)) {
222             if (checkdate($month, $day, $year)) {
223                 $time = make_timestamp($year, $month, $day);
224             } else {
225                 $time = time();
226             }
227         } else if (empty($time)) {
228             $time = time();
229         }
231         $output = html_writer::start_tag('div', array('class'=>'buttons'));
232         $output .= html_writer::start_tag('form', array('action' => CALENDAR_URL . 'event.php', 'method' => 'get'));
233         $output .= html_writer::start_tag('div');
234         $output .= html_writer::empty_tag('input', array('type'=>'hidden', 'name' => 'action', 'value' => 'new'));
235         $output .= html_writer::empty_tag('input', array('type'=>'hidden', 'name' => 'course', 'value' => $courseid));
236         $output .= html_writer::empty_tag('input', array('type'=>'hidden', 'name' => 'time', 'value' => $time));
237         $output .= html_writer::empty_tag('input', array('type'=>'submit', 'value' => get_string('newevent', 'calendar')));
238         $output .= html_writer::end_tag('div');
239         $output .= html_writer::end_tag('form');
240         $output .= html_writer::end_tag('div');
241         return $output;
242     }
244     /**
245      * Displays the calendar for a single day
246      *
247      * @param calendar_information $calendar
248      * @return string
249      */
250     public function show_day(calendar_information $calendar, moodle_url $returnurl = null) {
252         if ($returnurl === null) {
253             $returnurl = $this->page->url;
254         }
256         $events = calendar_get_upcoming($calendar->courses, $calendar->groups, $calendar->users, 1, 100, $calendar->timestamp_today());
258         $output  = html_writer::start_tag('div', array('class'=>'header'));
259         if (calendar_user_can_add_event($calendar->course)) {
260             $output .= $this->add_event_button($calendar->course->id, 0, 0, 0, $calendar->time);
261         }
262         //$output .= html_writer::tag('label', get_string('dayview', 'calendar'), array('for'=>'cal_course_flt_jump'));
263         $output .= $this->course_filter_selector($returnurl, get_string('dayview', 'calendar'));
264         $output .= html_writer::end_tag('div');
265         // Controls
266         $output .= html_writer::tag('div', calendar_top_controls('day', array('id' => $calendar->courseid, 'time' => $calendar->time)), array('class'=>'controls'));
268         if (empty($events)) {
269             // There is nothing to display today.
270             $output .= $this->output->heading(get_string('daywithnoevents', 'calendar'), 3);
271         } else {
272             $output .= html_writer::start_tag('div', array('class'=>'eventlist'));
273             $underway = array();
274             // First, print details about events that start today
275             foreach ($events as $event) {
276                 $event = new calendar_event($event);
277                 $event->calendarcourseid = $calendar->courseid;
278                 if ($event->timestart >= $calendar->timestamp_today() && $event->timestart <= $calendar->timestamp_tomorrow()-1) {  // Print it now
279                     $event->time = calendar_format_event_time($event, time(), null, false, $calendar->timestamp_today());
280                     $output .= $this->event($event);
281                 } else {                                                                 // Save this for later
282                     $underway[] = $event;
283                 }
284             }
286             // Then, show a list of all events that just span this day
287             if (!empty($underway)) {
288                 $output .= $this->output->heading(get_string('spanningevents', 'calendar'), 3);
289                 foreach ($underway as $event) {
290                     $event->time = calendar_format_event_time($event, time(), null, false, $calendar->timestamp_today());
291                     $output .= $this->event($event);
292                 }
293             }
295             $output .= html_writer::end_tag('div');
296         }
298         return $output;
299     }
301     /**
302      * Displays an event
303      *
304      * @param calendar_event $event
305      * @param bool $showactions
306      * @return string
307      */
308     public function event(calendar_event $event, $showactions=true) {
309         global $CFG;
311         $event = calendar_add_event_metadata($event);
312         $context = $event->context;
314         $anchor  = html_writer::tag('a', '', array('name'=>'event_'.$event->id));
316         $table = new html_table();
317         $table->attributes = array('class'=>'event', 'cellspacing'=>'0');
318         $table->data = array(
319             0 => new html_table_row(),
320             1 => new html_table_row(),
321         );
323         if (!empty($event->icon)) {
324             $table->data[0]->cells[0] = new html_table_cell($anchor.$event->icon);
325         } else {
326             $table->data[0]->cells[0] = new html_table_cell($anchor.$this->output->spacer(array('height'=>16, 'width'=>16, 'br'=>true)));
327         }
328         $table->data[0]->cells[0]->attributes['class'] .= ' picture';
330         $table->data[0]->cells[1] = new html_table_cell();
331         $table->data[0]->cells[1]->attributes['class'] .= ' topic';
332         if (!empty($event->referer)) {
333             $table->data[0]->cells[1]->text .= html_writer::tag('div', $event->referer, array('class'=>'referer'));
334         } else {
335             $table->data[0]->cells[1]->text .= html_writer::tag('div', format_string($event->name, false, array('context' => $context)), array('class'=>'name'));
336         }
337         if (!empty($event->courselink)) {
338             $table->data[0]->cells[1]->text .= html_writer::tag('div', $event->courselink, array('class'=>'course'));
339         }
340         // Show subscription source if needed.
341         if (!empty($event->subscription) && $CFG->calendar_showicalsource) {
342             if (!empty($event->subscription->url)) {
343                 $source = html_writer::link($event->subscription->url, get_string('subsource', 'calendar', $event->subscription));
344             } else {
345                 // File based ical.
346                 $source = get_string('subsource', 'calendar', $event->subscription);
347             }
348             $table->data[0]->cells[1]->text .= html_writer::tag('div', $source, array('class' => 'subscription'));
349         }
350         if (!empty($event->time)) {
351             $table->data[0]->cells[1]->text .= html_writer::tag('span', $event->time, array('class'=>'date'));
352         } else {
353             $table->data[0]->cells[1]->text .= html_writer::tag('span', calendar_time_representation($event->timestart), array('class'=>'date'));
354         }
356         $table->data[1]->cells[0] = new html_table_cell('&nbsp;');
357         $table->data[1]->cells[0]->attributes['class'] .= 'side';
359         $table->data[1]->cells[1] = new html_table_cell(format_text($event->description, $event->format, array('context' => $context)));
360         $table->data[1]->cells[1]->attributes['class'] .= ' description';
361         if (isset($event->cssclass)) {
362             $table->data[1]->cells[1]->attributes['class'] .= ' '.$event->cssclass;
363         }
365         if (calendar_edit_event_allowed($event) && $showactions) {
366             if (empty($event->cmid)) {
367                 $editlink = new moodle_url(CALENDAR_URL.'event.php', array('action'=>'edit', 'id'=>$event->id));
368                 $deletelink = new moodle_url(CALENDAR_URL.'delete.php', array('id'=>$event->id));
369                 if (!empty($event->calendarcourseid)) {
370                     $editlink->param('course', $event->calendarcourseid);
371                     $deletelink->param('course', $event->calendarcourseid);
372                 }
373             } else {
374                 $editlink = new moodle_url('/course/mod.php', array('update'=>$event->cmid, 'return'=>true, 'sesskey'=>sesskey()));
375                 $deletelink = null;
376             }
378             $commands  = html_writer::start_tag('div', array('class'=>'commands'));
379             $commands .= html_writer::start_tag('a', array('href'=>$editlink));
380             $commands .= html_writer::empty_tag('img', array('src'=>$this->output->pix_url('t/edit'), 'alt'=>get_string('tt_editevent', 'calendar'), 'title'=>get_string('tt_editevent', 'calendar')));
381             $commands .= html_writer::end_tag('a');
382             if ($deletelink != null) {
383                 $commands .= html_writer::start_tag('a', array('href'=>$deletelink));
384                 $commands .= html_writer::empty_tag('img', array('src'=>$this->output->pix_url('t/delete'), 'alt'=>get_string('tt_deleteevent', 'calendar'), 'title'=>get_string('tt_deleteevent', 'calendar')));
385                 $commands .= html_writer::end_tag('a');
386             }
387             $commands .= html_writer::end_tag('div');
388             $table->data[1]->cells[1]->text .= $commands;
389         }
390         return html_writer::table($table);
391     }
393     /**
394      * Displays a month in detail
395      *
396      * @param calendar_information $calendar
397      * @param moodle_url $returnurl the url to return to
398      * @return string
399      */
400     public function show_month_detailed(calendar_information $calendar, moodle_url $returnurl  = null) {
401         global $CFG;
403         if (empty($returnurl)) {
404             $returnurl = $this->page->url;
405         }
407         // Get the calendar type we are using.
408         $calendartype = \core_calendar\type_factory::get_calendar_instance();
410         // Store the display settings.
411         $display = new stdClass;
412         $display->thismonth = false;
414         // Get the specified date in the calendar type being used.
415         $date = $calendartype->timestamp_to_date_array($calendar->time);
416         $thisdate = $calendartype->timestamp_to_date_array(time());
417         if ($date['mon'] == $thisdate['mon'] && $date['year'] == $thisdate['year']) {
418             $display->thismonth = true;
419             $date = $thisdate;
420             $calendar->time = time();
421         }
423         // Get Gregorian date for the start of the month.
424         $gregoriandate = $calendartype->convert_to_gregorian($date['year'], $date['mon'], 1);
425         // Store the gregorian date values to be used later.
426         list($gy, $gm, $gd, $gh, $gmin) = array($gregoriandate['year'], $gregoriandate['month'], $gregoriandate['day'],
427             $gregoriandate['hour'], $gregoriandate['minute']);
429         // Get the starting week day for this month.
430         $startwday = dayofweek(1, $date['mon'], $date['year']);
431         // Get the days in a week.
432         $daynames = calendar_get_days();
433         // Store the number of days in a week.
434         $numberofdaysinweek = $calendartype->get_num_weekdays();
436         $display->minwday = calendar_get_starting_weekday();
437         $display->maxwday = $display->minwday + ($numberofdaysinweek - 1);
438         $display->maxdays = calendar_days_in_month($date['mon'], $date['year']);
440         // These are used for DB queries, so we want unixtime, so we need to use Gregorian dates.
441         $display->tstart = make_timestamp($gy, $gm, $gd, $gh, $gmin, 0);
442         $display->tend = $display->tstart + ($display->maxdays * DAYSECS) - 1;
444         // Align the starting weekday to fall in our display range
445         // This is simple, not foolproof.
446         if ($startwday < $display->minwday) {
447             $startwday += $numberofdaysinweek;
448         }
450         // Get events from database
451         $events = calendar_get_events($display->tstart, $display->tend, $calendar->users, $calendar->groups, $calendar->courses);
452         if (!empty($events)) {
453             foreach($events as $eventid => $event) {
454                 $event = new calendar_event($event);
455                 if (!empty($event->modulename)) {
456                     $cm = get_coursemodule_from_instance($event->modulename, $event->instance);
457                     if (!groups_course_module_visible($cm)) {
458                         unset($events[$eventid]);
459                     }
460                 }
461             }
462         }
464         // Extract information: events vs. time
465         calendar_events_by_day($events, $date['mon'], $date['year'], $eventsbyday, $durationbyday, $typesbyday, $calendar->courses);
467         $output  = html_writer::start_tag('div', array('class'=>'header'));
468         if (calendar_user_can_add_event($calendar->course)) {
469             $output .= $this->add_event_button($calendar->course->id, 0, 0, 0, $calendar->time);
470         }
471         $output .= get_string('detailedmonthview', 'calendar').': '.$this->course_filter_selector($returnurl);
472         $output .= html_writer::end_tag('div', array('class'=>'header'));
473         // Controls
474         $output .= html_writer::tag('div', calendar_top_controls('month', array('id' => $calendar->courseid, 'time' => $calendar->time)), array('class' => 'controls'));
476         $table = new html_table();
477         $table->attributes = array('class'=>'calendarmonth calendartable');
478         $table->summary = get_string('calendarheading', 'calendar', userdate($calendar->time, get_string('strftimemonthyear')));
479         $table->data = array();
481         // Get the day names as the header.
482         $header = array();
483         for($i = $display->minwday; $i <= $display->maxwday; ++$i) {
484             $header[] = $daynames[$i % $numberofdaysinweek]['shortname'];
485         }
486         $table->head = $header;
488         // For the table display. $week is the row; $dayweek is the column.
489         $week = 1;
490         $dayweek = $startwday;
492         $row = new html_table_row(array());
494         // Paddding (the first week may have blank days in the beginning)
495         for($i = $display->minwday; $i < $startwday; ++$i) {
496             $cell = new html_table_cell('&nbsp;');
497             $cell->attributes = array('class'=>'nottoday dayblank');
498             $row->cells[] = $cell;
499         }
501         // Now display all the calendar
502         $weekend = CALENDAR_DEFAULT_WEEKEND;
503         if (isset($CFG->calendar_weekend)) {
504             $weekend = intval($CFG->calendar_weekend);
505         }
507         $daytime = $display->tstart - DAYSECS;
508         for ($day = 1; $day <= $display->maxdays; ++$day, ++$dayweek) {
509             $daytime = $daytime + DAYSECS;
510             if($dayweek > $display->maxwday) {
511                 // We need to change week (table row)
512                 $table->data[] = $row;
513                 $row = new html_table_row(array());
514                 $dayweek = $display->minwday;
515                 ++$week;
516             }
518             // Reset vars
519             $cell = new html_table_cell();
520             $dayhref = calendar_get_link_href(new moodle_url(CALENDAR_URL.'view.php', array('view' => 'day', 'course' => $calendar->courseid)), 0, 0, 0, $daytime);
522             $cellclasses = array();
524             if ($weekend & (1 << ($dayweek % $numberofdaysinweek))) {
525                 // Weekend. This is true no matter what the exact range is.
526                 $cellclasses[] = 'weekend';
527             }
529             // Special visual fx if an event is defined
530             if (isset($eventsbyday[$day])) {
531                 if(count($eventsbyday[$day]) == 1) {
532                     $title = get_string('oneevent', 'calendar');
533                 } else {
534                     $title = get_string('manyevents', 'calendar', count($eventsbyday[$day]));
535                 }
536                 $cell->text = html_writer::tag('div', html_writer::link($dayhref, $day, array('title'=>$title)), array('class'=>'day'));
537             } else {
538                 $cell->text = html_writer::tag('div', $day, array('class'=>'day'));
539             }
541             // Special visual fx if an event spans many days
542             $durationclass = false;
543             if (isset($typesbyday[$day]['durationglobal'])) {
544                 $durationclass = 'duration_global';
545             } else if (isset($typesbyday[$day]['durationcourse'])) {
546                 $durationclass = 'duration_course';
547             } else if (isset($typesbyday[$day]['durationgroup'])) {
548                 $durationclass = 'duration_group';
549             } else if (isset($typesbyday[$day]['durationuser'])) {
550                 $durationclass = 'duration_user';
551             }
552             if ($durationclass) {
553                 $cellclasses[] = 'duration';
554                 $cellclasses[] = $durationclass;
555             }
557             // Special visual fx for today
558             if ($display->thismonth && $day == $date['mday']) {
559                 $cellclasses[] = 'day today';
560             } else {
561                 $cellclasses[] = 'day nottoday';
562             }
563             $cell->attributes = array('class'=>join(' ',$cellclasses));
565             if (isset($eventsbyday[$day])) {
566                 $cell->text .= html_writer::start_tag('ul', array('class'=>'events-new'));
567                 foreach($eventsbyday[$day] as $eventindex) {
568                     // If event has a class set then add it to the event <li> tag
569                     $attributes = array();
570                     if (!empty($events[$eventindex]->class)) {
571                         $attributes['class'] = $events[$eventindex]->class;
572                     }
573                     $dayhref->set_anchor('event_'.$events[$eventindex]->id);
574                     $link = html_writer::link($dayhref, format_string($events[$eventindex]->name, true));
575                     $cell->text .= html_writer::tag('li', $link, $attributes);
576                 }
577                 $cell->text .= html_writer::end_tag('ul');
578             }
579             if (isset($durationbyday[$day])) {
580                 $cell->text .= html_writer::start_tag('ul', array('class'=>'events-underway'));
581                 foreach($durationbyday[$day] as $eventindex) {
582                     $cell->text .= html_writer::tag('li', '['.format_string($events[$eventindex]->name,true).']', array('class'=>'events-underway'));
583                 }
584                 $cell->text .= html_writer::end_tag('ul');
585             }
586             $row->cells[] = $cell;
587         }
589         // Paddding (the last week may have blank days at the end)
590         for($i = $dayweek; $i <= $display->maxwday; ++$i) {
591             $cell = new html_table_cell('&nbsp;');
592             $cell->attributes = array('class'=>'nottoday dayblank');
593             $row->cells[] = $cell;
594         }
595         $table->data[] = $row;
596         $output .= html_writer::table($table);
598         return $output;
599     }
601     /**
602      * Displays a filter selection table
603      *
604      * @param calendar_information $calendar
605      * @return string
606      * @deprecated since Moodle 2.4 MDL-32309
607      * @see calendar_filter_controls()
608      */
609     protected function filter_selection_table(calendar_information $calendar, moodle_url $returnurl = null) {
610         global $SESSION;
611         debugging('Method core_calendar_renderer::filter_selection_table() is deprecated, please use '.
612                 'calendar_filter_controls() instead', DEBUG_DEVELOPER);
614         if ($returnurl === null) {
615             $returnurl = $this->page->url;
616         }
618         $output  = html_writer::start_tag('div', array('class'=>'filters'));
619         $output .= html_writer::start_tag('table');
620         $output .= html_writer::start_tag('tr');
622         // Global events
623         $link = new moodle_url(CALENDAR_URL.'set.php', array('var' => 'showglobal', 'return' => base64_encode($returnurl->out(false)), 'sesskey'=>sesskey()));
624         $strglobalevents = get_string('globalevents', 'calendar');
625         if (calendar_show_event_type(CALENDAR_EVENT_GLOBAL)) {
626             $output .= html_writer::tag('td', '', array('class'=>'calendar_event_global', 'style'=>'width:8px;'));
627             $output .= html_writer::tag('td', html_writer::tag('strong', $strglobalevents).' '.get_string('shown', 'calendar').' ('.html_writer::link($link, get_string('clickhide', 'calendar').'<span class="accesshide">'.$strglobalevents.'</span>').')');
628         } else {
629             $output .= html_writer::tag('td', '', array('style'=>'width:8px;'));
630             $output .= html_writer::tag('td', html_writer::tag('strong', $strglobalevents).' '.get_string('hidden', 'calendar').' ('.html_writer::link($link, get_string('clickshow', 'calendar').'<span class="accesshide">'.$strglobalevents.'</span>').')');
631         }
633         // Course events
634         $link = new moodle_url(CALENDAR_URL.'set.php', array('var'=>'showcourses', 'return' => base64_encode($returnurl->out(false)), 'sesskey'=>sesskey()));
635         $strcourseevents = get_string('courseevents', 'calendar');
636         if (calendar_show_event_type(CALENDAR_EVENT_COURSE)) {
637             $output .= html_writer::tag('td', '', array('class'=>'calendar_event_course', 'style'=>'width:8px;'));
638             $output .= html_writer::tag('td', html_writer::tag('strong', $strcourseevents).' '.get_string('shown', 'calendar').' ('.html_writer::link($link, get_string('clickhide', 'calendar').'<span class="accesshide">'.$strcourseevents.'</span>').')');
639         } else {
640             $output .= html_writer::tag('td', '', array('style'=>'width:8px;'));
641             $output .= html_writer::tag('td', html_writer::tag('strong', $strcourseevents).' '.get_string('hidden', 'calendar').' ('.html_writer::link($link, get_string('clickshow', 'calendar').'<span class="accesshide">'.$strcourseevents.'</span>').')');
642         }
643         $output .= html_writer::end_tag('tr');
645         if(isloggedin() && !isguestuser()) {
646             $output .= html_writer::start_tag('tr');
647             // Group events
648             $link = new moodle_url(CALENDAR_URL.'set.php', array('var'=>'showgroups', 'return' => base64_encode($returnurl->out(false)), 'sesskey'=>sesskey()));
649             $strgroupevents = get_string('groupevents', 'calendar');
650             if (calendar_show_event_type(CALENDAR_EVENT_GROUP)) {
651                 $output .= html_writer::tag('td', '', array('class'=>'calendar_event_group', 'style'=>'width:8px;'));
652                 $output .= html_writer::tag('td', html_writer::tag('strong', $strgroupevents).' '.get_string('shown', 'calendar').' ('.html_writer::link($link, get_string('clickhide', 'calendar').'<span class="accesshide">'.$strgroupevents.'</span>').')');
653             } else {
654                 $output .= html_writer::tag('td', '', array('style'=>'width:8px;'));
655                 $output .= html_writer::tag('td', html_writer::tag('strong', $strgroupevents).' '.get_string('hidden', 'calendar').' ('.html_writer::link($link, get_string('clickshow', 'calendar').'<span class="accesshide">'.$strgroupevents.'</span>').')');
656             }
657             // User events
658             $link = new moodle_url(CALENDAR_URL.'set.php', array('var'=>'showuser', 'return' => base64_encode($returnurl->out(false)), 'sesskey'=>sesskey()));
659             $struserevents = get_string('userevents', 'calendar');
660             if (calendar_show_event_type(CALENDAR_EVENT_USER)) {
661                 $output .= html_writer::tag('td', '', array('class'=>'calendar_event_user', 'style'=>'width:8px;'));
662                 $output .= html_writer::tag('td', html_writer::tag('strong', $struserevents).' '.get_string('shown', 'calendar').' ('.html_writer::link($link, get_string('clickhide', 'calendar').'<span class="accesshide">'.$struserevents.'</span>').')');
663             } else {
664                 $output .= html_writer::tag('td', '', array('style'=>'width:8px;'));
665                 $output .= html_writer::tag('td', html_writer::tag('strong', $struserevents).' '.get_string('hidden', 'calendar').' ('.html_writer::link($link, get_string('clickshow', 'calendar').'<span class="accesshide">'.$struserevents.'</span>').')');
666             }
667             $output .= html_writer::end_tag('tr');
668         }
669         $output .= html_writer::end_tag('table');
670         $output .= html_writer::end_tag('div');
671         return $output;
672     }
674     /**
675      * Displays upcoming events
676      *
677      * @param calendar_information $calendar
678      * @param int $futuredays
679      * @param int $maxevents
680      * @return string
681      */
682     public function show_upcoming_events(calendar_information $calendar, $futuredays, $maxevents, moodle_url $returnurl = null) {
684         if ($returnurl === null) {
685             $returnurl = $this->page->url;
686         }
688         $events = calendar_get_upcoming($calendar->courses, $calendar->groups, $calendar->users, $futuredays, $maxevents);
690         $output  = html_writer::start_tag('div', array('class'=>'header'));
691         if (calendar_user_can_add_event($calendar->course)) {
692             $output .= $this->add_event_button($calendar->course->id);
693         }
694         $output .= html_writer::tag('label', get_string('upcomingevents', 'calendar'), array('for'=>'cal_course_flt_jump'));
695         $output .= $this->course_filter_selector($returnurl);
696         $output .= html_writer::end_tag('div');
698         if ($events) {
699             $output .= html_writer::start_tag('div', array('class'=>'eventlist'));
700             foreach ($events as $event) {
701                 // Convert to calendar_event object so that we transform description
702                 // accordingly
703                 $event = new calendar_event($event);
704                 $event->calendarcourseid = $calendar->courseid;
705                 $output .= $this->event($event);
706             }
707             $output .= html_writer::end_tag('div');
708         } else {
709             $output .= $this->output->heading(get_string('noupcomingevents', 'calendar'));
710         }
712         return $output;
713     }
715     /**
716      * Displays a course filter selector
717      *
718      * @param array $getvars
719      * @return string
720      */
721     protected function course_filter_selector(moodle_url $returnurl, $label=null) {
722         global $USER, $SESSION, $CFG;
724         if (!isloggedin() or isguestuser()) {
725             return '';
726         }
728         if (has_capability('moodle/calendar:manageentries', context_system::instance()) && !empty($CFG->calendar_adminseesall)) {
729             $courses = get_courses('all', 'c.shortname','c.id,c.shortname');
730         } else {
731             $courses = enrol_get_my_courses();
732         }
734         unset($courses[SITEID]);
736         $courseoptions = array();
737         $courseoptions[SITEID] = get_string('fulllistofcourses');
738         foreach ($courses as $course) {
739             $coursecontext = context_course::instance($course->id);
740             $courseoptions[$course->id] = format_string($course->shortname, true, array('context' => $coursecontext));
741         }
743         if ($this->page->course->id !== SITEID) {
744             $selected = $this->page->course->id;
745         } else {
746             $selected = '';
747         }
748         $select = new single_select(new moodle_url(CALENDAR_URL.'set.php', array('return' => base64_encode($returnurl->out(false)), 'var' => 'setcourse', 'sesskey'=>sesskey())), 'id', $courseoptions, $selected, null);
749         $select->class = 'cal_courses_flt';
750         if ($label !== null) {
751             $select->set_label($label);
752         } else {
753             $select->set_label(get_string('listofcourses'), array('class' => 'accesshide'));
754         }
755         return $this->output->render($select);
756     }
758     /**
759      * Renders a table containing information about calendar subscriptions.
760      *
761      * @param int $courseid
762      * @param array $subscriptions
763      * @param string $importresults
764      * @return string
765      */
766     public function subscription_details($courseid, $subscriptions, $importresults = '') {
767         $table = new html_table();
768         $table->head  = array(
769             get_string('colcalendar', 'calendar'),
770             get_string('collastupdated', 'calendar'),
771             get_string('eventkind', 'calendar'),
772             get_string('colpoll', 'calendar'),
773             get_string('colactions', 'calendar')
774         );
775         $table->align = array('left', 'left', 'left', 'center');
776         $table->width = '100%';
777         $table->data  = array();
779         if (empty($subscriptions)) {
780             $cell = new html_table_cell(get_string('nocalendarsubscriptions', 'calendar'));
781             $cell->colspan = 4;
782             $table->data[] = new html_table_row(array($cell));
783         }
784         $strnever = new lang_string('never', 'calendar');
785         foreach ($subscriptions as $sub) {
786             $label = $sub->name;
787             if (!empty($sub->url)) {
788                 $label = html_writer::link($sub->url, $label);
789             }
790             if (empty($sub->lastupdated)) {
791                 $lastupdated = $strnever->out();
792             } else {
793                 $lastupdated = userdate($sub->lastupdated, get_string('strftimedatetimeshort', 'langconfig'));
794             }
796             $cell = new html_table_cell($this->subscription_action_form($sub, $courseid));
797             $cell->colspan = 2;
798             $type = $sub->eventtype . 'events';
800             $table->data[] = new html_table_row(array(
801                 new html_table_cell($label),
802                 new html_table_cell($lastupdated),
803                 new html_table_cell(get_string($type, 'calendar')),
804                 $cell
805             ));
806         }
808         $out  = $this->output->box_start('generalbox calendarsubs');
810         $out .= $importresults;
811         $out .= html_writer::table($table);
812         $out .= $this->output->box_end();
813         return $out;
814     }
816     /**
817      * Creates a form to perform actions on a given subscription.
818      *
819      * @param stdClass $subscription
820      * @param int $courseid
821      * @return string
822      */
823     protected function subscription_action_form($subscription, $courseid) {
824         // Assemble form for the subscription row.
825         $html = html_writer::start_tag('form', array('action' => new moodle_url('/calendar/managesubscriptions.php'), 'method' => 'post'));
826         if (empty($subscription->url)) {
827             // Don't update an iCal file, which has no URL.
828             $html .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'pollinterval', 'value' => '0'));
829         } else {
830             // Assemble pollinterval control.
831             $html .= html_writer::start_tag('div', array('style' => 'float:left;'));
832             $html .= html_writer::start_tag('select', array('name' => 'pollinterval'));
833             foreach (calendar_get_pollinterval_choices() as $k => $v) {
834                 $attributes = array();
835                 if ($k == $subscription->pollinterval) {
836                     $attributes['selected'] = 'selected';
837                 }
838                 $attributes['value'] = $k;
839                 $html .= html_writer::tag('option', $v, $attributes);
840             }
841             $html .= html_writer::end_tag('select');
842             $html .= html_writer::end_tag('div');
843         }
844         $html .= html_writer::start_tag('div', array('style' => 'float:right;'));
845         $html .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'sesskey', 'value' => sesskey()));
846         $html .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'course', 'value' => $courseid));
847         $html .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'id', 'value' => $subscription->id));
848         if (!empty($subscription->url)) {
849             $html .= html_writer::tag('button', get_string('update'), array('type'  => 'submit', 'name' => 'action',
850                                                                             'value' => CALENDAR_SUBSCRIPTION_UPDATE));
851         }
852         $html .= html_writer::tag('button', get_string('remove'), array('type'  => 'submit', 'name' => 'action',
853                                                                         'value' => CALENDAR_SUBSCRIPTION_REMOVE));
854         $html .= html_writer::end_tag('div');
855         $html .= html_writer::end_tag('form');
856         return $html;
857     }