Minor fixes for XHTML compliance
[pfb-moodle.git] / calendar / event.php
blob77cec62e2c158e10edc86b57a47e37357977b06b
1 <?php // $Id$
3 /////////////////////////////////////////////////////////////////////////////
4 // //
5 // NOTICE OF COPYRIGHT //
6 // //
7 // Moodle - Calendar extension //
8 // //
9 // Copyright (C) 2003-2004 Greek School Network www.sch.gr //
10 // //
11 // Designed by: //
12 // Avgoustos Tsinakos (tsinakos@teikav.edu.gr) //
13 // Jon Papaioannou (pj@moodle.org) //
14 // //
15 // Programming and development: //
16 // Jon Papaioannou (pj@moodle.org) //
17 // //
18 // For bugs, suggestions, etc contact: //
19 // Jon Papaioannou (pj@moodle.org) //
20 // //
21 // The current module was developed at the University of Macedonia //
22 // (www.uom.gr) under the funding of the Greek School Network (www.sch.gr) //
23 // The aim of this project is to provide additional and improved //
24 // functionality to the Asynchronous Distance Education service that the //
25 // Greek School Network deploys. //
26 // //
27 // This program is free software; you can redistribute it and/or modify //
28 // it under the terms of the GNU General Public License as published by //
29 // the Free Software Foundation; either version 2 of the License, or //
30 // (at your option) any later version. //
31 // //
32 // This program is distributed in the hope that it will be useful, //
33 // but WITHOUT ANY WARRANTY; without even the implied warranty of //
34 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
35 // GNU General Public License for more details: //
36 // //
37 // http://www.gnu.org/copyleft/gpl.html //
38 // //
39 /////////////////////////////////////////////////////////////////////////////
41 require_once('../config.php');
42 require_once($CFG->dirroot.'/calendar/lib.php');
43 require_once($CFG->dirroot.'/course/lib.php');
44 require_once($CFG->dirroot.'/mod/forum/lib.php');
46 require_login();
48 if(isguest()) {
49 // Guests cannot do anything with events
50 redirect(CALENDAR_URL.'view.php?view=upcoming');
53 $action = required_param('action', PARAM_ALPHA);
54 $eventid = optional_param('id', 0, PARAM_INT);
55 $eventtype = optional_param('type', 'select', PARAM_ALPHA);
56 $urlcourse = optional_param('course', 0, PARAM_INT);
57 $cal_y = optional_param('cal_y');
58 $cal_m = optional_param('cal_m');
59 $cal_d = optional_param('cal_d');
61 if(!$site = get_site()) {
62 redirect($CFG->wwwroot.'/'.$CFG->admin.'/index.php');
65 $strcalendar = get_string('calendar', 'calendar');
67 $now = usergetdate(time());
68 $nav = calendar_get_link_tag($strcalendar, CALENDAR_URL.'view.php?view=upcoming&amp;', $now['mday'], $now['mon'], $now['year']);
69 $day = intval($now['mday']);
70 $mon = intval($now['mon']);
71 $yr = intval($now['year']);
73 if ($usehtmleditor = can_use_richtext_editor()) {
74 $defaultformat = FORMAT_HTML;
75 } else {
76 $defaultformat = FORMAT_MOODLE;
79 // If a course has been supplied in the URL, change the filters to show that one
80 if($urlcourse > 0 && record_exists('course', 'id', $urlcourse)) {
81 if($urlcourse == SITEID) {
82 // If coming from the site page, show all courses
83 $SESSION->cal_courses_shown = calendar_get_default_courses(true);
84 calendar_set_referring_course(0);
86 else {
87 // Otherwise show just this one
88 $SESSION->cal_courses_shown = $urlcourse;
89 calendar_set_referring_course($SESSION->cal_courses_shown);
93 switch($action) {
94 case 'delete':
95 $title = get_string('deleteevent', 'calendar');
96 $event = get_record('event', 'id', $eventid);
97 if($event === false) {
98 error('Invalid event');
100 if(!calendar_edit_event_allowed($event)) {
101 error('You are not authorized to do this');
103 break;
105 case 'edit':
106 $title = get_string('editevent', 'calendar');
107 $event = get_record('event', 'id', $eventid);
108 $repeats = optional_param('repeats', 0, PARAM_INT);
110 if($event === false) {
111 error('Invalid event');
113 if(!calendar_edit_event_allowed($event)) {
114 error('You are not authorized to do this');
117 if($form = data_submitted()) {
119 $form->name = clean_param(strip_tags($form->name,'<lang><span>'), PARAM_CLEAN);
121 $form->timestart = make_timestamp($form->startyr, $form->startmon, $form->startday, $form->starthr, $form->startmin);
122 if($form->duration == 1) {
123 $form->timeduration = make_timestamp($form->endyr, $form->endmon, $form->endday, $form->endhr, $form->endmin) - $form->timestart;
124 if($form->timeduration < 0) {
125 $form->timeduration = 0;
128 else if($form->duration == 2) {
129 $form->timeduration = $form->minutes * MINSECS;
131 else {
132 $form->timeduration = 0;
135 validate_form($form, $err);
137 if (count($err) == 0) {
139 if($event->repeatid && $repeats) {
140 // Update all
141 if($form->timestart >= $event->timestart) {
142 $timestartoffset = 'timestart + '.($form->timestart - $event->timestart);
144 else {
145 $timestartoffset = 'timestart - '.($event->timestart - $form->timestart);
148 execute_sql('UPDATE '.$CFG->prefix.'event SET '.
149 'name = '.$db->qstr($form->name).','.
150 'description = '.$db->qstr($form->description).','.
151 'timestart = '.$timestartoffset.','.
152 'timeduration = '.$form->timeduration.','.
153 'timemodified = '.time().' WHERE repeatid = '.$event->repeatid);
155 /// Log the event update.
156 $form->name = stripslashes($form->name); //To avoid double-slashes
157 add_to_log($form->courseid, 'calendar', 'edit all', 'event.php?action=edit&amp;id='.$form->id, $form->name);
160 else {
161 // Update this
162 $form->timemodified = time();
163 update_record('event', $form);
165 /// Log the event update.
166 $form->name = stripslashes($form->name); //To avoid double-slashes
167 add_to_log($form->courseid, 'calendar', 'edit', 'event.php?action=edit&amp;id='.$form->id, $form->name);
170 // OK, now redirect to day view
171 redirect(CALENDAR_URL.'view.php?view=day&cal_d='.$form->startday.'&cal_m='.$form->startmon.'&cal_y='.$form->startyr);
173 else {
174 foreach ($err as $key => $value) {
175 $focus = 'form.'.$key;
179 break;
181 case 'new':
182 $title = get_string('newevent', 'calendar');
183 $form = data_submitted();
184 if(!empty($form) && !empty($form->name)) {
186 $form->name = clean_text(strip_tags($form->name, '<lang><span>'));
188 $form->timestart = make_timestamp($form->startyr, $form->startmon, $form->startday, $form->starthr, $form->startmin);
189 if($form->duration == 1) {
190 $form->timeduration = make_timestamp($form->endyr, $form->endmon, $form->endday, $form->endhr, $form->endmin) - $form->timestart;
191 if($form->timeduration < 0) {
192 $form->timeduration = 0;
195 else if ($form->duration == 2) {
196 $form->timeduration = $form->minutes * MINSECS;
198 else {
199 $form->timeduration = 0;
201 if(!calendar_add_event_allowed($form)) {
202 error('You are not authorized to do this');
204 validate_form($form, $err);
205 if (count($err) == 0) {
206 $form->timemodified = time();
208 if ($form->repeat) {
209 $fetch = get_record_sql('SELECT 1, MAX(repeatid) AS repeatid FROM '.$CFG->prefix.'event');
210 $form->repeatid = empty($fetch) ? 1 : $fetch->repeatid + 1;
213 /// Get the event id for the log record.
214 $eventid = insert_record('event', $form, true);
216 /// Log the event entry.
217 add_to_log($form->courseid, 'calendar', 'add', 'event.php?action=edit&amp;id='.$eventid, stripslashes($form->name));
219 if ($form->repeat) {
220 for($i = 1; $i < $form->repeats; $i++) {
221 // What's the DST offset for the previous repeat?
222 $dst_offset_prev = dst_offset_on($form->timestart);
224 $form->timestart += WEEKSECS;
226 // If the offset has changed in the meantime, update this repeat accordingly
227 $form->timestart += $dst_offset_prev - dst_offset_on($form->timestart);
229 /// Get the event id for the log record.
230 $eventid = insert_record('event', $form, true);
232 /// Log the event entry.
233 add_to_log($form->courseid, 'calendar', 'add', 'event.php?action=edit&amp;id='.$eventid, stripslashes($form->name));
236 // OK, now redirect to day view
237 redirect(CALENDAR_URL.'view.php?view=day&cal_d='.$form->startday.'&cal_m='.$form->startmon.'&cal_y='.$form->startyr);
239 else {
240 foreach ($err as $key => $value) {
241 $focus = 'form.'.$key;
245 break;
246 default: // no action
247 $title='';
248 break;
250 if(empty($focus)) $focus = '';
252 // Let's see if we are supposed to provide a referring course link
253 // but NOT for the "main page" course
254 if($SESSION->cal_course_referer != SITEID &&
255 ($shortname = get_field('course', 'shortname', 'id', $SESSION->cal_course_referer)) !== false) {
256 // If we know about the referring course, show a return link
257 $nav = '<a href="'.$CFG->wwwroot.'/course/view.php?id='.$SESSION->cal_course_referer.'">'.$shortname.'</a> -> '.$nav;
260 if (!empty($SESSION->cal_course_referer)) {
261 // TODO: This is part of the Great $course Hack in Moodle. Replace it at some point.
262 $course = get_record('course', 'id', $SESSION->cal_course_referer);
263 } else {
264 $course = $site;
267 print_header($site->shortname.': '.$strcalendar.': '.$title, $strcalendar, $nav.' -> '.$title,
268 'eventform.name', '', true, '', user_login_string($site));
270 echo calendar_overlib_html();
272 echo '<table id="calendar">';
273 echo '<tr><td class="maincalendar">';
275 switch($action) {
276 case 'delete':
277 $confirm = optional_param('confirm', 0, PARAM_INT);
278 $repeats = optional_param('repeats', 0, PARAM_INT);
279 if($confirm) {
280 // Kill it and redirect to day view
281 if(($event = get_record('event', 'id', $eventid)) !== false) {
283 if($event->repeatid && $repeats) {
284 delete_records('event', 'repeatid', $event->repeatid);
285 add_to_log($event->courseid, 'calendar', 'delete all', '', $event->name);
287 else {
288 delete_records('event', 'id', $eventid);
289 add_to_log($event->courseid, 'calendar', 'delete', '', $event->name);
293 redirect(CALENDAR_URL.'view.php?view=day&cal_d='.$_REQUEST['d'].'&cal_m='.$_REQUEST['m'].'&cal_y='.$_REQUEST['y']);
296 else {
297 $eventtime = usergetdate($event->timestart);
298 $m = $eventtime['mon'];
299 $d = $eventtime['mday'];
300 $y = $eventtime['year'];
302 if($event->repeatid) {
303 $fetch = get_record_sql('SELECT 1, COUNT(id) AS repeatcount FROM '.$CFG->prefix.'event WHERE repeatid = '.$event->repeatid);
304 $repeatcount = $fetch->repeatcount;
306 else {
307 $repeatcount = 0;
310 // Display confirmation form
311 echo '<div class="header">'.get_string('deleteevent', 'calendar').': '.$event->name.'</div>';
312 echo '<h2>'.get_string('confirmeventdelete', 'calendar').'</h2>';
313 if($repeatcount > 1) {
314 echo '<p>'.get_string('youcandeleteallrepeats', 'calendar', $repeatcount).'</p>';
316 echo '<div class="eventlist">';
317 $event->time = calendar_format_event_time($event, time(), '', false);
318 calendar_print_event($event);
319 echo '</div>';
320 include('event_delete.html');
322 break;
324 case 'edit':
325 if(empty($form)) {
326 $form->name = $event->name;
327 $form->courseid = $event->courseid; // Not to update, but for date validation
328 $form->description = $event->description;
329 $form->timestart = $event->timestart;
330 $form->timeduration = $event->timeduration;
331 $form->id = $event->id;
332 $form->format = $defaultformat;
333 if($event->timeduration > HOURSECS) {
334 // More than one hour, so default to normal duration mode
335 $form->duration = 1;
336 $form->minutes = '';
338 else if($event->timeduration) {
339 // Up to one hour, "minutes" mode probably is better here
340 $form->duration = 2;
341 $form->minutes = $event->timeduration / MINSECS;
343 else {
344 // No duration
345 $form->duration = 0;
346 $form->minutes = '';
350 if (!empty($form->courseid)) {
351 // TODO: This is part of the Great $course Hack in Moodle. Replace it at some point.
352 $course = get_record('course', 'id', $form->courseid);
353 } else {
354 $course = $site;
357 if($event->repeatid) {
358 $fetch = get_record_sql('SELECT 1, COUNT(id) AS repeatcount FROM '.$CFG->prefix.'event WHERE repeatid = '.$event->repeatid);
359 $repeatcount = $fetch->repeatcount;
361 else {
362 $repeatcount = 0;
365 echo '<div class="header">'.get_string('editevent', 'calendar').'</div>';
366 include('event_edit.html');
367 if ($usehtmleditor) {
368 use_html_editor("description");
370 break;
372 case 'new':
373 if($cal_y && $cal_m && $cal_d && checkdate($cal_m, $cal_d, $cal_y)) {
374 $form->timestart = make_timestamp($cal_y, $cal_m, $cal_d, 0, 0, 0);
376 else if($cal_y && $cal_m && checkdate($cal_m, 1, $cal_y)) {
377 if($cal_y == $now['year'] && $cal_m == $now['mon']) {
378 $form->timestart = make_timestamp($cal_y, $cal_m, $now['mday'], 0, 0, 0);
380 else {
381 $form->timestart = make_timestamp($cal_y, $cal_m, 1, 0, 0, 0);
384 if(!isset($form->timestart) or $form->timestart < 0) {
385 $form->timestart = time();
388 calendar_get_allowed_types($allowed);
389 if(!$allowed->groups && !$allowed->courses && !$allowed->site) {
390 // Take the shortcut
391 $eventtype = 'user';
394 $header = '';
396 switch($eventtype) {
397 case 'user':
398 $form->name = '';
399 $form->description = '';
400 $form->courseid = 0;
401 $form->groupid = 0;
402 $form->userid = $USER->id;
403 $form->modulename = '';
404 $form->eventtype = '';
405 $form->instance = 0;
406 $form->timeduration = 0;
407 $form->duration = 0;
408 $form->repeat = 0;
409 $form->repeats = '';
410 $form->minutes = '';
411 $form->type = 'user';
412 $header = get_string('typeuser', 'calendar');
413 break;
414 case 'group':
415 $groupid = optional_param('groupid', 0, PARAM_INT);
416 if (! ($group = groups_get_group($groupid))) { //TODO:check.
417 calendar_get_allowed_types($allowed);
418 $eventtype = 'select';
420 else {
421 $form->name = '';
422 $form->description = '';
423 $form->courseid = $group->courseid;
424 $form->groupid = $group->id;
425 $form->userid = $USER->id;
426 $form->modulename = '';
427 $form->eventtype = '';
428 $form->instance = 0;
429 $form->timeduration = 0;
430 $form->duration = 0;
431 $form->repeat = 0;
432 $form->repeats = '';
433 $form->minutes = '';
434 $form->type = 'group';
435 $header = get_string('typegroup', 'calendar');
437 break;
438 case 'course':
439 $courseid = optional_param('courseid', 0, PARAM_INT);
440 if(!record_exists('course', 'id', $courseid)) {
441 calendar_get_allowed_types($allowed);
442 $eventtype = 'select';
444 else {
445 $form->name = '';
446 $form->description = '';
447 $form->courseid = $courseid;
448 $form->groupid = 0;
449 $form->userid = $USER->id;
450 $form->modulename = '';
451 $form->eventtype = '';
452 $form->instance = 0;
453 $form->timeduration = 0;
454 $form->duration = 0;
455 $form->repeat = 0;
456 $form->repeats = '';
457 $form->minutes = '';
458 $form->type = 'course';
459 $header = get_string('typecourse', 'calendar');
461 break;
462 case 'site':
463 $form->name = '';
464 $form->description = '';
465 $form->courseid = SITEID;
466 $form->groupid = 0;
467 $form->userid = $USER->id;
468 $form->modulename = '';
469 $form->eventtype = '';
470 $form->instance = 0;
471 $form->timeduration = 0;
472 $form->duration = 0;
473 $form->repeat = 0;
474 $form->repeats = '';
475 $form->minutes = '';
476 $form->type = 'site';
477 $header = get_string('typesite', 'calendar');
478 break;
479 case 'select':
480 break;
481 default:
482 error('Unsupported event type');
485 $form->format = $defaultformat;
486 if(!empty($header)) {
487 $header = ' ('.$header.')';
490 echo '<div class="header">'.get_string('newevent', 'calendar').$header.'</div>';
492 if($eventtype == 'select') {
493 $courseid = optional_param('courseid', $SESSION->cal_course_referer, PARAM_INT);
494 if ($courseid == 0) { // workaround by Dan for bug #6130
495 $courseid = SITEID;
497 if (!$course = get_record('course', 'id', $courseid)) {
498 error('Incorrect course ID');
500 if ($groupmode = groupmode($course)) { // Groups are being used
501 $changegroup = optional_param('group', -1, PARAM_INT);
502 $groupid = get_and_set_current_group($course, $groupmode, $changegroup);
503 } else {
504 $groupid = 0;
507 echo '<h2>'.get_string('eventkind', 'calendar').':</h2>';
508 echo '<div id="selecteventtype">';
509 include('event_select.html');
510 echo '</div>';
512 else {
513 include('event_new.html');
514 if ($usehtmleditor) {
515 use_html_editor("description");
519 break;
521 echo '</td>';
523 // START: Last column (3-month display)
525 $defaultcourses = calendar_get_default_courses();
526 calendar_set_filters($courses, $groups, $users, $defaultcourses, $defaultcourses);
527 list($prevmon, $prevyr) = calendar_sub_month($mon, $yr);
528 list($nextmon, $nextyr) = calendar_add_month($mon, $yr);
530 echo '<td class="sidecalendar">';
531 echo '<div class="header">'.get_string('monthlyview', 'calendar').'</div>';
532 echo '<div class="filters">';
533 echo calendar_filter_controls('event', 'action='.$action.'&amp;type='.$eventtype.'&amp;id='.$eventid);
534 echo '</div>';
536 echo '<div class="minicalendarblock">';
537 echo calendar_top_controls('display', array('m' => $prevmon, 'y' => $prevyr));
538 echo calendar_get_mini($courses, $groups, $users, $prevmon, $prevyr);
539 echo '</div><div class="minicalendarblock">';
540 echo calendar_top_controls('display', array('m' => $mon, 'y' => $yr));
541 echo calendar_get_mini($courses, $groups, $users, $mon, $yr);
542 echo '</div><div class="minicalendarblock">';
543 echo calendar_top_controls('display', array('m' => $nextmon, 'y' => $nextyr));
544 echo calendar_get_mini($courses, $groups, $users, $nextmon, $nextyr);
545 echo '</div>';
547 echo '</td>';
548 echo '</tr></table>';
550 print_footer();
553 function validate_form(&$form, &$err) {
555 $form->name = trim($form->name);
556 $form->description = trim($form->description);
558 if(empty($form->name)) {
559 $err['name'] = get_string('errornoeventname', 'calendar');
561 if(empty($form->description)) {
562 $err['description'] = get_string('errornodescription', 'calendar');
564 if(!checkdate($form->startmon, $form->startday, $form->startyr)) {
565 $err['timestart'] = get_string('errorinvaliddate', 'calendar');
567 if($form->duration == 2 and !checkdate($form->endmon, $form->endday, $form->endyr)) {
568 $err['timeduration'] = get_string('errorinvaliddate', 'calendar');
570 if($form->duration == 2 and !($form->minutes > 0 and $form->minutes < 1000)) {
571 $err['minutes'] = get_string('errorinvalidminutes', 'calendar');
573 if (!empty($form->repeat) and !($form->repeats > 1 and $form->repeats < 100)) {
574 $err['repeats'] = get_string('errorinvalidrepeats', 'calendar');
576 if(!empty($form->courseid)) {
577 // Timestamps must be >= course startdate
578 $course = get_record('course', 'id', $form->courseid);
579 if($course === false) {
580 error('Event belongs to invalid course');
582 else if($form->timestart < $course->startdate) {
583 $err['timestart'] = get_string('errorbeforecoursestart', 'calendar');
588 function calendar_add_event_allowed($event) {
589 global $USER;
591 // can not be using guest account
592 if (empty($USER->id) or $USER->username == 'guest') {
593 return false;
596 $sitecontext = get_context_instance(CONTEXT_SYSTEM, SITEID);
597 // if user has manageentries at site level, always return true
598 if (has_capability('moodle/calendar:manageentries', $sitecontext)) {
599 return true;
602 switch ($event->type) {
603 case 'course':
604 return has_capability('moodle/calendar:manageentries', get_context_instance(CONTEXT_COURSE, $event->courseid));
606 case 'group':
607 if (! groups_group_exists($event->groupid)) { //TODO:check.
608 return false;
610 // this is ok because if you have this capability at course level, you should be able
611 // to edit group calendar too
612 // there is no need to check membership, because if you have this capability
613 // you will have a role in this group context
614 return has_capability('moodle/calendar:manageentries', get_context_instance(CONTEXT_GROUP, $event->groupid));
616 case 'user':
617 if ($event->userid == $USER->id) {
618 return (has_capability('moodle/calendar:manageownentries', $sitecontext));
620 //there is no 'break;' intentionally
622 case 'site':
623 default:
624 return false; // should already return true above if having moodle/calendar:manageentries
628 function calendar_get_allowed_types(&$allowed) {
629 global $USER, $CFG, $SESSION;
631 $allowed->user = true; // User events always allowed
632 $allowed->groups = false; // This may change just below
633 $allowed->courses = false; // This may change just below
634 $allowed->site = has_capability('moodle/calendar:manageentries', get_context_instance(CONTEXT_SYSTEM, SITEID));
636 if(!empty($SESSION->cal_course_referer) && $SESSION->cal_course_referer != SITEID && has_capability('moodle/calendar:manageentries', get_context_instance(CONTEXT_COURSE, $SESSION->cal_course_referer))) {
637 $course = get_record('course', 'id', $SESSION->cal_course_referer);
639 $allowed->courses = array($course->id => 1);
641 if($course->groupmode != NOGROUPS || !$course->groupmodeforce) {
642 $allowed->groups = get_groups($SESSION->cal_course_referer);