| [ Index ] |
PHP Cross Reference of Moodle 1.9.3 [Build 15-Oct-2008] |
[Summary view] [Print] [Text view]
1 <?php // $Id: lib.php,v 1.206.2.13 2008/04/30 04:45:23 dongsheng Exp $ 2 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 ///////////////////////////////////////////////////////////////////////////// 40 41 // These are read by the administration component to provide default values 42 define('CALENDAR_DEFAULT_UPCOMING_LOOKAHEAD', 21); 43 define('CALENDAR_DEFAULT_UPCOMING_MAXEVENTS', 10); 44 define('CALENDAR_DEFAULT_STARTING_WEEKDAY', 1); 45 // This is a packed bitfield: day X is "weekend" if $field & (1 << X) is true 46 // Default value = 65 = 64 + 1 = 2^6 + 2^0 = Saturday & Sunday 47 define('CALENDAR_DEFAULT_WEEKEND', 65); 48 49 // Fetch the correct values from admin settings/lang pack 50 // If no such settings found, use the above defaults 51 $firstday = isset($CFG->calendar_startwday) ? $CFG->calendar_startwday : get_string('firstdayofweek'); 52 if(!is_numeric($firstday)) { 53 define ('CALENDAR_STARTING_WEEKDAY', CALENDAR_DEFAULT_STARTING_WEEKDAY); 54 } 55 else { 56 define ('CALENDAR_STARTING_WEEKDAY', intval($firstday) % 7); 57 } 58 define ('CALENDAR_UPCOMING_DAYS', isset($CFG->calendar_lookahead) ? intval($CFG->calendar_lookahead) : CALENDAR_DEFAULT_UPCOMING_LOOKAHEAD); 59 define ('CALENDAR_UPCOMING_MAXEVENTS', isset($CFG->calendar_maxevents) ? intval($CFG->calendar_maxevents) : CALENDAR_DEFAULT_UPCOMING_MAXEVENTS); 60 define ('CALENDAR_WEEKEND', isset($CFG->calendar_weekend) ? intval($CFG->calendar_weekend) : CALENDAR_DEFAULT_WEEKEND); 61 define ('CALENDAR_URL', $CFG->wwwroot.'/calendar/'); 62 define ('CALENDAR_TF_24', '%H:%M'); 63 define ('CALENDAR_TF_12', '%I:%M %p'); 64 65 $CALENDARDAYS = array('sunday','monday','tuesday','wednesday','thursday','friday','saturday'); 66 67 68 69 function calendar_get_mini($courses, $groups, $users, $cal_month = false, $cal_year = false) { 70 global $CFG, $USER; 71 72 $display = new stdClass; 73 $display->minwday = get_user_preferences('calendar_startwday', CALENDAR_STARTING_WEEKDAY); 74 $display->maxwday = $display->minwday + 6; 75 76 $content = ''; 77 78 if(!empty($cal_month) && !empty($cal_year)) { 79 $thisdate = usergetdate(time()); // Date and time the user sees at his location 80 if($cal_month == $thisdate['mon'] && $cal_year == $thisdate['year']) { 81 // Navigated to this month 82 $date = $thisdate; 83 $display->thismonth = true; 84 } 85 else { 86 // Navigated to other month, let's do a nice trick and save us a lot of work... 87 if(!checkdate($cal_month, 1, $cal_year)) { 88 $date = array('mday' => 1, 'mon' => $thisdate['mon'], 'year' => $thisdate['year']); 89 $display->thismonth = true; 90 } 91 else { 92 $date = array('mday' => 1, 'mon' => $cal_month, 'year' => $cal_year); 93 $display->thismonth = false; 94 } 95 } 96 } 97 else { 98 $date = usergetdate(time()); // Date and time the user sees at his location 99 $display->thismonth = true; 100 } 101 102 // Fill in the variables we 're going to use, nice and tidy 103 list($d, $m, $y) = array($date['mday'], $date['mon'], $date['year']); // This is what we want to display 104 $display->maxdays = calendar_days_in_month($m, $y); 105 106 if (get_user_timezone_offset() < 99) { 107 // We 'll keep these values as GMT here, and offset them when the time comes to query the db 108 $display->tstart = gmmktime(0, 0, 0, $m, 1, $y); // This is GMT 109 $display->tend = gmmktime(23, 59, 59, $m, $display->maxdays, $y); // GMT 110 } else { 111 // no timezone info specified 112 $display->tstart = mktime(0, 0, 0, $m, 1, $y); 113 $display->tend = mktime(23, 59, 59, $m, $display->maxdays, $y); 114 } 115 116 $startwday = dayofweek(1, $m, $y); 117 118 // Align the starting weekday to fall in our display range 119 // This is simple, not foolproof. 120 if($startwday < $display->minwday) { 121 $startwday += 7; 122 } 123 124 // TODO: THIS IS TEMPORARY CODE! 125 // [pj] I was just reading through this and realized that I when writing this code I was probably 126 // asking for trouble, as all these time manipulations seem to be unnecessary and a simple 127 // make_timestamp would accomplish the same thing. So here goes a test: 128 //$test_start = make_timestamp($y, $m, 1); 129 //$test_end = make_timestamp($y, $m, $display->maxdays, 23, 59, 59); 130 //if($test_start != usertime($display->tstart) - dst_offset_on($display->tstart)) { 131 //notify('Failed assertion in calendar/lib.php line 126; display->tstart = '.$display->tstart.', dst_offset = '.dst_offset_on($display->tstart).', usertime = '.usertime($display->tstart).', make_t = '.$test_start); 132 //} 133 //if($test_end != usertime($display->tend) - dst_offset_on($display->tend)) { 134 //notify('Failed assertion in calendar/lib.php line 130; display->tend = '.$display->tend.', dst_offset = '.dst_offset_on($display->tend).', usertime = '.usertime($display->tend).', make_t = '.$test_end); 135 //} 136 137 138 // Get the events matching our criteria. Don't forget to offset the timestamps for the user's TZ! 139 $events = calendar_get_events( 140 usertime($display->tstart) - dst_offset_on($display->tstart), 141 usertime($display->tend) - dst_offset_on($display->tend), 142 $users, $groups, $courses); 143 144 // Set event course class for course events 145 if (!empty($events)) { 146 foreach ($events as $eventid => $event) { 147 if (!empty($event->modulename)) { 148 $cm = get_coursemodule_from_instance($event->modulename, $event->instance); 149 if (!groups_course_module_visible($cm)) { 150 unset($events[$eventid]); 151 } 152 } 153 } 154 } 155 156 // This is either a genius idea or an idiot idea: in order to not complicate things, we use this rule: if, after 157 // possibly removing SITEID from $courses, there is only one course left, then clicking on a day in the month 158 // will also set the $SESSION->cal_courses_shown variable to that one course. Otherwise, we 'd need to add extra 159 // arguments to this function. 160 161 $morehref = ''; 162 if(!empty($courses)) { 163 $courses = array_diff($courses, array(SITEID)); 164 if(count($courses) == 1) { 165 $morehref = '&course='.reset($courses); 166 } 167 } 168 169 // We want to have easy access by day, since the display is on a per-day basis. 170 // Arguments passed by reference. 171 //calendar_events_by_day($events, $display->tstart, $eventsbyday, $durationbyday, $typesbyday); 172 calendar_events_by_day($events, $m, $y, $eventsbyday, $durationbyday, $typesbyday, $courses); 173 174 //Accessibility: added summary and <abbr> elements. 175 ///global $CALENDARDAYS; appears to be broken. 176 $days_title = array('sunday','monday','tuesday','wednesday','thursday','friday','saturday'); 177 178 $summary = get_string('calendarheading', 'calendar', userdate(make_timestamp($y, $m), get_string('strftimemonthyear'))); 179 $summary = get_string('tabledata', 'access', $summary); 180 $content .= '<table class="minicalendar" summary="'.$summary.'">'; // Begin table 181 $content .= '<tr class="weekdays">'; // Header row: day names 182 183 // Print out the names of the weekdays 184 $days = array('sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'); 185 for($i = $display->minwday; $i <= $display->maxwday; ++$i) { 186 // This uses the % operator to get the correct weekday no matter what shift we have 187 // applied to the $display->minwday : $display->maxwday range from the default 0 : 6 188 $content .= '<th scope="col"><abbr title="'. get_string($days_title[$i % 7], 'calendar') .'">'. 189 get_string($days[$i % 7], 'calendar') ."</abbr></th>\n"; 190 } 191 192 $content .= '</tr><tr>'; // End of day names; prepare for day numbers 193 194 // For the table display. $week is the row; $dayweek is the column. 195 $dayweek = $startwday; 196 197 // Paddding (the first week may have blank days in the beginning) 198 for($i = $display->minwday; $i < $startwday; ++$i) { 199 $content .= '<td class="dayblank"> </td>'."\n"; 200 } 201 202 // Now display all the calendar 203 for($day = 1; $day <= $display->maxdays; ++$day, ++$dayweek) { 204 if($dayweek > $display->maxwday) { 205 // We need to change week (table row) 206 $content .= '</tr><tr>'; 207 $dayweek = $display->minwday; 208 } 209 210 // Reset vars 211 $cell = ''; 212 if(CALENDAR_WEEKEND & (1 << ($dayweek % 7))) { 213 // Weekend. This is true no matter what the exact range is. 214 $class = 'weekend day'; 215 } 216 else { 217 // Normal working day. 218 $class = 'day'; 219 } 220 221 // Special visual fx if an event is defined 222 if(isset($eventsbyday[$day])) { 223 $dayhref = calendar_get_link_href(CALENDAR_URL.'view.php?view=day'.$morehref.'&', $day, $m, $y); 224 225 // OverLib popup 226 $popupcontent = ''; 227 foreach($eventsbyday[$day] as $eventid) { 228 if (!isset($events[$eventid])) { 229 continue; 230 } 231 $event = $events[$eventid]; 232 if(!empty($event->modulename)) { 233 $popupicon = $CFG->modpixpath.'/'.$event->modulename.'/icon.gif'; 234 $popupalt = $event->modulename; 235 236 } else if ($event->courseid == SITEID) { // Site event 237 $popupicon = $CFG->pixpath.'/c/site.gif'; 238 $popupalt = ''; 239 } else if ($event->courseid != 0 && $event->courseid != SITEID && $event->groupid == 0) { // Course event 240 $popupicon = $CFG->pixpath.'/c/course.gif'; 241 $popupalt = ''; 242 } else if ($event->groupid) { // Group event 243 $popupicon = $CFG->pixpath.'/c/group.gif'; 244 $popupalt = ''; 245 } else if ($event->userid) { // User event 246 $popupicon = $CFG->pixpath.'/c/user.gif'; 247 $popupalt = ''; 248 } 249 $popupcontent .= '<div><img class="icon" src="'.$popupicon.'" alt="'.$popupalt.'" /><a href="'.$dayhref.'#event_'.$event->id.'">'.format_string($event->name, true).'</a></div>'; 250 } 251 252 //Accessibility: functionality moved to calendar_get_popup. 253 if($display->thismonth && $day == $d) { 254 $popup = calendar_get_popup(true, $events[$eventid]->timestart, $popupcontent); 255 } else { 256 $popup = calendar_get_popup(false, $events[$eventid]->timestart, $popupcontent); 257 } 258 259 // Class and cell content 260 if(isset($typesbyday[$day]['startglobal'])) { 261 $class .= ' event_global'; 262 } 263 else if(isset($typesbyday[$day]['startcourse'])) { 264 $class .= ' event_course'; 265 } 266 else if(isset($typesbyday[$day]['startgroup'])) { 267 $class .= ' event_group'; 268 } 269 else if(isset($typesbyday[$day]['startuser'])) { 270 $class .= ' event_user'; 271 } 272 $cell = '<a href="'.$dayhref.'" '.$popup.'>'.$day.'</a>'; 273 } 274 else { 275 $cell = $day; 276 } 277 278 if(isset($typesbyday[$day]['durationglobal'])) { 279 $class .= ' duration_global'; 280 } 281 else if(isset($typesbyday[$day]['durationcourse'])) { 282 $class .= ' duration_course'; 283 } 284 else if(isset($typesbyday[$day]['durationgroup'])) { 285 $class .= ' duration_group'; 286 } 287 else if(isset($typesbyday[$day]['durationuser'])) { 288 $class .= ' duration_user'; 289 } 290 291 // If event has a class set then add it to the table day <td> tag 292 // Note: only one colour for minicalendar 293 if(isset($eventsbyday[$day])) { 294 foreach($eventsbyday[$day] as $eventid) { 295 if (!isset($events[$eventid])) { 296 continue; 297 } 298 $event = $events[$eventid]; 299 if (!empty($event->class)) { 300 $class .= ' '.$event->class; 301 } 302 break; 303 } 304 } 305 306 // Special visual fx for today 307 //Accessibility: hidden text for today, and popup. 308 if($display->thismonth && $day == $d) { 309 $class .= ' today'; 310 $today = get_string('today', 'calendar').' '.userdate(time(), get_string('strftimedayshort')); 311 312 if(! isset($eventsbyday[$day])) { 313 $class .= ' eventnone'; 314 $popup = calendar_get_popup(true, false); 315 $cell = '<a href="#" '.$popup.'>'.$day.'</a>'; 316 } 317 $cell = get_accesshide($today.' ').$cell; 318 } 319 320 // Just display it 321 if(!empty($class)) { 322 $class = ' class="'.$class.'"'; 323 } 324 $content .= '<td'.$class.'>'.$cell."</td>\n"; 325 } 326 327 // Paddding (the last week may have blank days at the end) 328 for($i = $dayweek; $i <= $display->maxwday; ++$i) { 329 $content .= '<td class="dayblank"> </td>'; 330 } 331 $content .= '</tr>'; // Last row ends 332 333 $content .= '</table>'; // Tabular display of days ends 334 335 return $content; 336 } 337 338 /** 339 * calendar_get_popup, called at multiple points in from calendar_get_mini. 340 * Copied and modified from calendar_get_mini. 341 * @uses OverLib popup. 342 * @param $is_today bool, false except when called on the current day. 343 * @param $event_timestart mixed, $events[$eventid]->timestart, OR false if there are no events. 344 * @param $popupcontent string. 345 * @return $popup string, contains onmousover and onmouseout events. 346 */ 347 function calendar_get_popup($is_today, $event_timestart, $popupcontent='') { 348 $popupcaption = ''; 349 if($is_today) { 350 $popupcaption = get_string('today', 'calendar').' '; 351 } 352 if (false === $event_timestart) { 353 $popupcaption .= userdate(time(), get_string('strftimedayshort')); 354 $popupcontent = get_string('eventnone', 'calendar'); 355 356 } else { 357 $popupcaption .= get_string('eventsfor', 'calendar', userdate($event_timestart, get_string('strftimedayshort'))); 358 } 359 $popupcontent = str_replace("'", "\'", htmlspecialchars($popupcontent)); 360 $popupcaption = str_replace("'", "\'", htmlspecialchars($popupcaption)); 361 $popup = 'onmouseover="return overlib(\''.$popupcontent.'\', CAPTION, \''.$popupcaption.'\');" onmouseout="return nd();"'; 362 return $popup; 363 } 364 365 function calendar_get_upcoming($courses, $groups, $users, $daysinfuture, $maxevents, $fromtime=0) { 366 global $CFG, $COURSE; 367 368 $display = new stdClass; 369 $display->range = $daysinfuture; // How many days in the future we 'll look 370 $display->maxevents = $maxevents; 371 372 $output = array(); 373 374 // Prepare "course caching", since it may save us a lot of queries 375 $coursecache = array(); 376 377 $processed = 0; 378 $now = time(); // We 'll need this later 379 $usermidnighttoday = usergetmidnight($now); 380 381 if ($fromtime) { 382 $display->tstart = $fromtime; 383 } else { 384 $display->tstart = $usermidnighttoday; 385 } 386 387 // This works correctly with respect to the user's DST, but it is accurate 388 // only because $fromtime is always the exact midnight of some day! 389 $display->tend = usergetmidnight($display->tstart + DAYSECS * $display->range + 3 * HOURSECS) - 1; 390 391 // Get the events matching our criteria 392 $events = calendar_get_events($display->tstart, $display->tend, $users, $groups, $courses); 393 394 // This is either a genius idea or an idiot idea: in order to not complicate things, we use this rule: if, after 395 // possibly removing SITEID from $courses, there is only one course left, then clicking on a day in the month 396 // will also set the $SESSION->cal_courses_shown variable to that one course. Otherwise, we 'd need to add extra 397 // arguments to this function. 398 399 $morehref = ''; 400 if(!empty($courses)) { 401 $courses = array_diff($courses, array(SITEID)); 402 if(count($courses) == 1) { 403 $morehref = '&course='.reset($courses); 404 } 405 } 406 407 if ($events !== false) { 408 409 $modinfo =& get_fast_modinfo($COURSE); 410 411 foreach($events as $event) { 412 413 414 if (!empty($event->modulename)) { 415 if ($event->courseid == $COURSE->id) { 416 if (isset($modinfo->instances[$event->modulename][$event->instance])) { 417 $cm = $modinfo->instances[$event->modulename][$event->instance]; 418 if (!$cm->uservisible) { 419 continue; 420 } 421 } 422 } else { 423 if (!$cm = get_coursemodule_from_instance($event->modulename, $event->instance)) { 424 continue; 425 } 426 if (!coursemodule_visible_for_user($cm)) { 427 continue; 428 } 429 } 430 if ($event->modulename == 'assignment'){ 431 // TODO: rewrite this hack somehow 432 if (!calendar_edit_event_allowed($event)){ // cannot manage entries, eg. student 433 if(!$assignment = get_record('assignment','id',$event->instance)){ 434 // error("assignment ID was incorrect"); 435 continue; 436 } 437 // assign assignment to assignment object to use hidden_is_hidden method 438 require_once($CFG->dirroot.'/mod/assignment/lib.php'); 439 440 if (!file_exists($CFG->dirroot.'/mod/assignment/type/'.$assignment->assignmenttype.'/assignment.class.php')) { 441 continue; 442 } 443 require_once ($CFG->dirroot.'/mod/assignment/type/'.$assignment->assignmenttype.'/assignment.class.php'); 444 445 $assignmentclass = 'assignment_'.$assignment->assignmenttype; 446 $assignmentinstance = new $assignmentclass($cm->id, $assignment, $cm); 447 448 if ($assignmentinstance->description_is_hidden()){//force not to show description before availability 449 $event->description = get_string('notavailableyet', 'assignment'); 450 } 451 } 452 } 453 } 454 455 if ($processed >= $display->maxevents) { 456 break; 457 } 458 459 $event->time = calendar_format_event_time($event, $now, $morehref); 460 $output[] = $event; 461 ++$processed; 462 } 463 } 464 return $output; 465 } 466 467 function calendar_add_event_metadata($event) { 468 global $CFG; 469 470 //Support multilang in event->name 471 $event->name = format_string($event->name,true); 472 473 if(!empty($event->modulename)) { // Activity event 474 // The module name is set. I will assume that it has to be displayed, and 475 // also that it is an automatically-generated event. And of course that the 476 // fields for get_coursemodule_from_instance are set correctly. 477 $module = calendar_get_module_cached($coursecache, $event->modulename, $event->instance); 478 479 if ($module === false) { 480 return; 481 } 482 483 $modulename = get_string('modulename', $event->modulename); 484 $eventtype = get_string($event->eventtype, $event->modulename); 485 $icon = $CFG->modpixpath.'/'.$event->modulename.'/icon.gif'; 486 487 $event->icon = '<img height="16" width="16" src="'.$icon.'" alt="'.$eventtype.'" title="'.$modulename.'" style="vertical-align: middle;" />'; 488 $event->referer = '<a href="'.$CFG->wwwroot.'/mod/'.$event->modulename.'/view.php?id='.$module->id.'">'.$event->name.'</a>'; 489 $event->courselink = '<a href="'.$CFG->wwwroot.'/course/view.php?id='.$module->course.'">'.$coursecache[$module->course]->fullname.'</a>'; 490 $event->cmid = $module->id; 491 492 493 } else if($event->courseid == SITEID) { // Site event 494 $event->icon = '<img height="16" width="16" src="'.$CFG->pixpath.'/c/site.gif" alt="'.get_string('globalevent', 'calendar').'" style="vertical-align: middle;" />'; 495 $event->cssclass = 'event_global'; 496 } else if($event->courseid != 0 && $event->courseid != SITEID && $event->groupid == 0) { // Course event 497 calendar_get_course_cached($coursecache, $event->courseid); 498 $event->icon = '<img height="16" width="16" src="'.$CFG->pixpath.'/c/course.gif" alt="'.get_string('courseevent', 'calendar').'" style="vertical-align: middle;" />'; 499 $event->courselink = '<a href="'.$CFG->wwwroot.'/course/view.php?id='.$event->courseid.'">'.$coursecache[$event->courseid]->fullname.'</a>'; 500 $event->cssclass = 'event_course'; 501 } else if ($event->groupid) { // Group event 502 $event->icon = '<img height="16" width="16" src="'.$CFG->pixpath.'/c/group.gif" alt="'.get_string('groupevent', 'calendar').'" style="vertical-align: middle;" />'; 503 $event->cssclass = 'event_group'; 504 } else if($event->userid) { // User event 505 $event->icon = '<img height="16" width="16" src="'.$CFG->pixpath.'/c/user.gif" alt="'.get_string('userevent', 'calendar').'" style="vertical-align: middle;" />'; 506 $event->cssclass = 'event_user'; 507 } 508 return $event; 509 } 510 511 function calendar_print_event($event) { 512 global $CFG, $USER; 513 514 static $strftimetime; 515 516 $event = calendar_add_event_metadata($event); 517 echo '<a name="event_'.$event->id.'"></a><table class="event" cellspacing="0">'; 518 echo '<tr><td class="picture">'; 519 if (!empty($event->icon)) { 520 echo $event->icon; 521 } else { 522 print_spacer(16,16); 523 } 524 echo '</td>'; 525 echo '<td class="topic">'; 526 527 if (!empty($event->referer)) { 528 echo '<div class="referer">'.$event->referer.'</div>'; 529 } else { 530 echo '<div class="name">'.$event->name."</div>"; 531 } 532 if (!empty($event->courselink)) { 533 echo '<div class="course">'.$event->courselink.' </div>'; 534 } 535 if (!empty($event->time)) { 536 echo '<span class="date">'.$event->time.'</span>'; 537 } else { 538 echo '<span class="date">'.calendar_time_representation($event->timestart).'</span>'; 539 } 540 541 echo '</td></tr>'; 542 echo '<tr><td class="side"> </td>'; 543 if (isset($event->cssclass)) { 544 echo '<td class="description '.$event->cssclass.'">'; 545 } else { 546 echo '<td class="description">'; 547 } 548 echo format_text($event->description, FORMAT_HTML); 549 if (calendar_edit_event_allowed($event)) { 550 echo '<div class="commands">'; 551 $calendarcourseid = ''; 552 if (!empty($event->calendarcourseid)) { 553 $calendarcourseid = '&course='.$event->calendarcourseid; 554 } 555 if (empty($event->cmid)) { 556 $editlink = CALENDAR_URL.'event.php?action=edit&id='.$event->id.$calendarcourseid; 557 $deletelink = CALENDAR_URL.'event.php?action=delete&id='.$event->id.$calendarcourseid; 558 } else { 559 $editlink = $CFG->wwwroot.'/course/mod.php?update='.$event->cmid.'&return=true&sesskey='.$USER->sesskey; 560 $deletelink = ''; // deleting activities directly from calendar is dangerous/confusing - see MDL-11843 561 } 562 echo ' <a href="'.$editlink.'"><img 563 src="'.$CFG->pixpath.'/t/edit.gif" alt="'.get_string('tt_editevent', 'calendar').'" 564 title="'.get_string('tt_editevent', 'calendar').'" /></a>'; 565 if ($deletelink) { 566 echo ' <a href="'.$deletelink.'"><img 567 src="'.$CFG->pixpath.'/t/delete.gif" alt="'.get_string('tt_deleteevent', 'calendar').'" 568 title="'.get_string('tt_deleteevent', 'calendar').'" /></a>'; 569 } 570 echo '</div>'; 571 } 572 echo '</td></tr></table>'; 573 574 } 575 576 /** 577 * Get calendar events 578 * @param int $tstart Start time of time range for events 579 * @param int $tend End time of time range for events 580 * @param array/int/boolean $users array of users, user id or boolean for all/no user events 581 * @param array/int/boolean $groups array of groups, group id or boolean for all/no group events 582 * @param array/int/boolean $courses array of courses, course id or boolean for all/no course events 583 * @param boolean $withduration whether only events starting within time range selected 584 * or events in progress/already started selected as well 585 * @param boolean $ignorehidden whether to select only visible events or all events 586 * @return array of selected events or an empty array if there aren't any (or there was an error) 587 */ 588 function calendar_get_events($tstart, $tend, $users, $groups, $courses, $withduration=true, $ignorehidden=true) { 589 $whereclause = ''; 590 // Quick test 591 if(is_bool($users) && is_bool($groups) && is_bool($courses)) { 592 return array(); 593 } 594 595 if(is_array($users) && !empty($users)) { 596 // Events from a number of users 597 if(!empty($whereclause)) $whereclause .= ' OR'; 598 $whereclause .= ' (userid IN ('.implode(',', $users).') AND courseid = 0 AND groupid = 0)'; 599 } 600 else if(is_numeric($users)) { 601 // Events from one user 602 if(!empty($whereclause)) $whereclause .= ' OR'; 603 $whereclause .= ' (userid = '.$users.' AND courseid = 0 AND groupid = 0)'; 604 } 605 else if($users === true) { 606 // Events from ALL users 607 if(!empty($whereclause)) $whereclause .= ' OR'; 608 $whereclause .= ' (userid != 0 AND courseid = 0 AND groupid = 0)'; 609 } 610 else if($users === false) { 611 // No user at all, do nothing 612 } 613 614 if(is_array($groups) && !empty($groups)) { 615 // Events from a number of groups 616 if(!empty($whereclause)) $whereclause .= ' OR'; 617 $whereclause .= ' groupid IN ('.implode(',', $groups).')'; 618 } 619 else if(is_numeric($groups)) { 620 // Events from one group 621 if(!empty($whereclause)) $whereclause .= ' OR '; 622 $whereclause .= ' groupid = '.$groups; 623 } 624 else if($groups === true) { 625 // Events from ALL groups 626 if(!empty($whereclause)) $whereclause .= ' OR '; 627 $whereclause .= ' groupid != 0'; 628 } 629 // boolean false (no groups at all): we don't need to do anything 630 631 if(is_array($courses)) { 632 // A number of courses (maybe none at all!) 633 if(!empty($courses)) { 634 if(!empty($whereclause)) { 635 $whereclause .= ' OR'; 636 } 637 $whereclause .= ' (groupid = 0 AND courseid IN ('.implode(',', $courses).'))'; 638 } 639 else { 640 // This means NO courses, not that we don't care! 641 // No need to do anything 642 } 643 } 644 else if(is_numeric($courses)) { 645 // One course 646 if(!empty($whereclause)) $whereclause .= ' OR'; 647 $whereclause .= ' (groupid = 0 AND courseid = '.$courses.')'; 648 } 649 else if($courses === true) { 650 // Events from ALL courses 651 if(!empty($whereclause)) $whereclause .= ' OR'; 652 $whereclause .= ' (groupid = 0 AND courseid != 0)'; 653 } 654 655 // Security check: if, by now, we have NOTHING in $whereclause, then it means 656 // that NO event-selecting clauses were defined. Thus, we won't be returning ANY 657 // events no matter what. Allowing the code to proceed might return a completely 658 // valid query with only time constraints, thus selecting ALL events in that time frame! 659 if(empty($whereclause)) { 660 return array(); 661 } 662 663 if($withduration) { 664 $timeclause = '(timestart >= '.$tstart.' OR timestart + timeduration > '.$tstart.') AND timestart <= '.$tend; 665 } 666 else { 667 $timeclause = 'timestart >= '.$tstart.' AND timestart <= '.$tend; 668 } 669 if(!empty($whereclause)) { 670 // We have additional constraints 671 $whereclause = $timeclause.' AND ('.$whereclause.')'; 672 } 673 else { 674 // Just basic time filtering 675 $whereclause = $timeclause; 676 } 677 678 if ($ignorehidden) { 679 $whereclause .= ' AND visible = 1'; 680 } 681 682 $events = get_records_select('event', $whereclause, 'timestart'); 683 if ($events === false) { 684 $events = array(); 685 } 686 return $events; 687 } 688 689 function calendar_top_controls($type, $data) { 690 global $CFG, $CALENDARDAYS, $THEME; 691 $content = ''; 692 if(!isset($data['d'])) { 693 $data['d'] = 1; 694 } 695 696 // Ensure course id passed if relevant 697 // Required due to changes in view/lib.php mainly (calendar_session_vars()) 698 $courseid = ''; 699 if (!empty($data['id'])) { 700 $courseid = '&course='.$data['id']; 701 } 702 703 if(!checkdate($data['m'], $data['d'], $data['y'])) { 704 $time = time(); 705 } 706 else { 707 $time = make_timestamp($data['y'], $data['m'], $data['d']); 708 } 709 $date = usergetdate($time); 710 711 $data['m'] = $date['mon']; 712 $data['y'] = $date['year']; 713 714 //Accessibility: calendar block controls, replaced <table> with <div>. 715 //$nexttext = link_arrow_right(get_string('monthnext', 'access'), $url='', $accesshide=true); 716 //$prevtext = link_arrow_left(get_string('monthprev', 'access'), $url='', $accesshide=true); 717 718 switch($type) { 719 case 'frontpage': 720 list($prevmonth, $prevyear) = calendar_sub_month($data['m'], $data['y']); 721 list($nextmonth, $nextyear) = calendar_add_month($data['m'], $data['y']); 722 $nextlink = calendar_get_link_next(get_string('monthnext', 'access'), 'index.php?', 0, $nextmonth, $nextyear, $accesshide=true); 723 $prevlink = calendar_get_link_previous(get_string('monthprev', 'access'), 'index.php?', 0, $prevmonth, $prevyear, true); 724 $content .= "\n".'<div class="calendar-controls">'. $prevlink; 725 $content .= '<span class="hide"> | </span><span class="current"><a href="'.calendar_get_link_href(CALENDAR_URL.'view.php?view=month'.$courseid.'&', 1, $data['m'], $data['y']).'">'.userdate($time, get_string('strftimemonthyear')).'</a></span>'; 726 $content .= '<span class="hide"> | </span>'. $nextlink ."\n"; 727 $content .= "<span class=\"clearer\"><!-- --></span></div>\n"; 728 break; 729 case 'course': 730 list($prevmonth, $prevyear) = calendar_sub_month($data['m'], $data['y']); 731 list($nextmonth, $nextyear) = calendar_add_month($data['m'], $data['y']); 732 $nextlink = calendar_get_link_next(get_string('monthnext', 'access'), 'view.php?id='.$data['id'].'&', 0, $nextmonth, $nextyear, $accesshide=true); 733 $prevlink = calendar_get_link_previous(get_string('monthprev', 'access'), 'view.php?id='.$data['id'].'&', 0, $prevmonth, $prevyear, true); 734 $content .= "\n".'<div class="calendar-controls">'. $prevlink; 735 $content .= '<span class="hide"> | </span><span class="current"><a href="'.calendar_get_link_href(CALENDAR_URL.'view.php?view=month'.$courseid.'&', 1, $data['m'], $data['y']).'">'.userdate($time, get_string('strftimemonthyear')).'</a></span>'; 736 $content .= '<span class="hide"> | </span>'. $nextlink ."\n"; 737 $content .= "<span class=\"clearer\"><!-- --></span></div>\n"; 738 break; 739 case 'upcoming': 740 $content .= '<div style="text-align: center;"><a href="'.CALENDAR_URL.'view.php?view=upcoming"'.$courseid.'>'.userdate($time, get_string('strftimemonthyear'))."</a></div>\n"; 741 break; 742 case 'display': 743 $content .= '<div style="text-align: center;"><a href="'.calendar_get_link_href(CALENDAR_URL.'view.php?view=month'.$courseid.'&', 1, $data['m'], $data['y']).'">'.userdate($time, get_string('strftimemonthyear'))."</a></div>\n"; 744 break; 745 case 'month': 746 list($prevmonth, $prevyear) = calendar_sub_month($data['m'], $data['y']); 747 list($nextmonth, $nextyear) = calendar_add_month($data['m'], $data['y']); 748 $prevdate = make_timestamp($prevyear, $prevmonth, 1); 749 $nextdate = make_timestamp($nextyear, $nextmonth, 1); 750 $content .= "\n".'<div class="calendar-controls">'; 751 $content .= calendar_get_link_previous(userdate($prevdate, get_string('strftimemonthyear')), 'view.php?view=month'.$courseid.'&', 1, $prevmonth, $prevyear); 752 $content .= '<span class="hide"> | </span><span class="current">'.userdate($time, get_string('strftimemonthyear'))."</span>\n"; 753 $content .= '<span class="hide"> | </span>'.calendar_get_link_next(userdate($nextdate, get_string('strftimemonthyear')), 'view.php?view=month'.$courseid.'&', 1, $nextmonth, $nextyear); 754 $content .= "<span class=\"clearer\"><!-- --></span></div>\n"; 755 break; 756 case 'day': 757 $data['d'] = $date['mday']; // Just for convenience 758 $prevdate = usergetdate(make_timestamp($data['y'], $data['m'], $data['d'] - 1)); 759 $nextdate = usergetdate(make_timestamp($data['y'], $data['m'], $data['d'] + 1)); 760 $prevname = calendar_wday_name($CALENDARDAYS[$prevdate['wday']]); 761 $nextname = calendar_wday_name($CALENDARDAYS[$nextdate['wday']]); 762 $content .= "\n".'<div class="calendar-controls">'; 763 $content .= calendar_get_link_previous($prevname, 'view.php?view=day'.$courseid.'&', $prevdate['mday'], $prevdate['mon'], $prevdate['year']); 764 765 // Get the format string 766 $text = get_string('strftimedaydate'); 767 /* 768 // Regexp hackery to make a link out of the month/year part 769 $text = ereg_replace('(%B.+%Y|%Y.+%B|%Y.+%m[^ ]+)', '<a href="'.calendar_get_link_href('view.php?view=month&', 1, $data['m'], $data['y']).'">\\1</a>', $text); 770 $text = ereg_replace('(F.+Y|Y.+F|Y.+m[^ ]+)', '<a href="'.calendar_get_link_href('view.php?view=month&', 1, $data['m'], $data['y']).'">\\1</a>', $text); 771 */ 772 // Replace with actual values and lose any day leading zero 773 $text = userdate($time, $text); 774 // Print the actual thing 775 $content .= '<span class="hide"> | </span><span class="current">'.$text.'</span>'; 776 777 $content .= '<span class="hide"> | </span>'. calendar_get_link_next($nextname, 'view.php?view=day'.$courseid.'&', $nextdate['mday'], $nextdate['mon'], $nextdate['year']); 778 $content .= "<span class=\"clearer\"><!-- --></span></div>\n"; 779 break; 780 } 781 return $content; 782 } 783 784 function calendar_filter_controls($type, $vars = NULL, $course = NULL, $courses = NULL) { 785 global $CFG, $SESSION, $USER; 786 787 $groupevents = true; 788 $getvars = ''; 789 790 $id = optional_param( 'id',0,PARAM_INT ); 791 792 switch($type) { 793 case 'event': 794 case 'upcoming': 795 case 'day': 796 case 'month': 797 $getvars = '&from='.$type; 798 break; 799 case 'course': 800 if ($id > 0) { 801 $getvars = '&from=course&id='.$id; 802 } else { 803 $getvars = '&from=course'; 804 } 805 if (isset($course->groupmode) and $course->groupmode == NOGROUPS and $course->groupmodeforce) { 806 $groupevents = false; 807 } 808 break; 809 } 810 811 if (!empty($vars)) { 812 $getvars .= '&'.$vars; 813 } 814 815 $content = '<table>'; 816 817 $content .= '<tr>'; 818 if($SESSION->cal_show_global) { 819 $content .= '<td class="eventskey event_global" style="width: 11px;"><img src="'.$CFG->pixpath.'/t/hide.gif" class="iconsmall" alt="'.get_string('hide').'" title="'.get_string('tt_hideglobal', 'calendar').'" style="cursor:pointer" onclick="location.href='."'".CALENDAR_URL.'set.php?var=showglobal'.$getvars."'".'" /></td>'; 820 $content .= '<td><a href="'.CALENDAR_URL.'set.php?var=showglobal'.$getvars.'" title="'.get_string('tt_hideglobal', 'calendar').'">'.get_string('global', 'calendar').'</a></td>'."\n"; 821 } else { 822 $content .= '<td style="width: 11px;"><img src="'.$CFG->pixpath.'/t/show.gif" class="iconsmall" alt="'.get_string('show').'" title="'.get_string('tt_showglobal', 'calendar').'" style="cursor:pointer" onclick="location.href='."'".CALENDAR_URL.'set.php?var=showglobal'.$getvars."'".'" /></td>'; 823 $content .= '<td><a href="'.CALENDAR_URL.'set.php?var=showglobal'.$getvars.'" title="'.get_string('tt_showglobal', 'calendar').'">'.get_string('global', 'calendar').'</a></td>'."\n"; 824 } 825 if($SESSION->cal_show_course) { 826 $content .= '<td class="eventskey event_course" style="width: 11px;"><img src="'.$CFG->pixpath.'/t/hide.gif" class="iconsmall" alt="'.get_string('hide').'" title="'.get_string('tt_hidecourse', 'calendar').'" style="cursor:pointer" onclick="location.href='."'".CALENDAR_URL.'set.php?var=showcourses'.$getvars."'".'" /></td>'; 827 $content .= '<td><a href="'.CALENDAR_URL.'set.php?var=showcourses'.$getvars.'" title="'.get_string('tt_hidecourse', 'calendar').'">'.get_string('course', 'calendar').'</a></td>'."\n"; 828 } else { 829 $content .= '<td style="width: 11px;"><img src="'.$CFG->pixpath.'/t/show.gif" class="iconsmall" alt="'.get_string('hide').'" title="'.get_string('tt_showcourse', 'calendar').'" style="cursor:pointer" onclick="location.href='."'".CALENDAR_URL.'set.php?var=showcourses'.$getvars."'".'" /></td>'; 830 $content .= '<td><a href="'.CALENDAR_URL.'set.php?var=showcourses'.$getvars.'" title="'.get_string('tt_showcourse', 'calendar').'">'.get_string('course', 'calendar').'</a></td>'."\n"; 831 832 } 833 834 835 if(!empty($USER->id) && !isguest()) { 836 $content .= "</tr>\n<tr>"; 837 838 if($groupevents) { 839 // This course MIGHT have group events defined, so show the filter 840 if($SESSION->cal_show_groups) { 841 $content .= '<td class="eventskey event_group" style="width: 11px;"><img src="'.$CFG->pixpath.'/t/hide.gif" class="iconsmall" alt="'.get_string('hide').'" title="'.get_string('tt_hidegroups', 'calendar').'" style="cursor:pointer" onclick="location.href='."'".CALENDAR_URL.'set.php?var=showgroups'.$getvars."'".'" /></td>'; 842 $content .= '<td><a href="'.CALENDAR_URL.'set.php?var=showgroups'.$getvars.'" title="'.get_string('tt_hidegroups', 'calendar').'">'.get_string('group', 'calendar').'</a></td>'."\n"; 843 } else { 844 $content .= '<td style="width: 11px;"><img src="'.$CFG->pixpath.'/t/show.gif" class="iconsmall" alt="'.get_string('show').'" title="'.get_string('tt_showgroups', 'calendar').'" style="cursor:pointer" onclick="location.href='."'".CALENDAR_URL.'set.php?var=showgroups'.$getvars."'".'" /></td>'; 845 $content .= '<td><a href="'.CALENDAR_URL.'set.php?var=showgroups'.$getvars.'" title="'.get_string('tt_showgroups', 'calendar').'">'.get_string('group', 'calendar').'</a></td>'."\n"; 846 } 847 } else { 848 // This course CANNOT have group events, so lose the filter 849 $content .= '<td style="width: 11px;"></td><td> </td>'."\n"; 850 } 851 if($SESSION->cal_show_user) { 852 $content .= '<td class="eventskey event_user" style="width: 11px;"><img src="'.$CFG->pixpath.'/t/hide.gif" class="iconsmall" alt="'.get_string('hide').'" title="'.get_string('tt_hideuser', 'calendar').'" style="cursor:pointer" onclick="location.href='."'".CALENDAR_URL.'set.php?var=showuser'.$getvars."'".'" /></td>'; 853 $content .= '<td><a href="'.CALENDAR_URL.'set.php?var=showuser'.$getvars.'" title="'.get_string('tt_hideuser', 'calendar').'">'.get_string('user', 'calendar').'</a></td>'."\n"; 854 } else { 855 $content .= '<td style="width: 11px;"><img src="'.$CFG->pixpath.'/t/show.gif" class="iconsmall" alt="'.get_string('show').'" title="'.get_string('tt_showuser', 'calendar').'" style="cursor:pointer" onclick="location.href='."'".CALENDAR_URL.'set.php?var=showuser'.$getvars."'".'" /></td>'; 856 $content .= '<td><a href="'.CALENDAR_URL.'set.php?var=showuser'.$getvars.'" title="'.get_string('tt_showuser', 'calendar').'">'.get_string('user', 'calendar').'</a></td>'."\n"; 857 } 858 } 859 $content .= "</tr>\n</table>\n"; 860 861 return $content; 862 } 863 864 function calendar_day_representation($tstamp, $now = false, $usecommonwords = true) { 865 866 static $shortformat; 867 if(empty($shortformat)) { 868 $shortformat = get_string('strftimedayshort'); 869 } 870 871 if($now === false) { 872 $now = time(); 873 } 874 875 // To have it in one place, if a change is needed 876 $formal = userdate($tstamp, $shortformat); 877 878 $datestamp = usergetdate($tstamp); 879 $datenow = usergetdate($now); 880 881 if($usecommonwords == false) { 882 // We don't want words, just a date 883 return $formal; 884 } 885 else if($datestamp['year'] == $datenow['year'] && $datestamp['yday'] == $datenow['yday']) { 886 // Today 887 return get_string('today', 'calendar'); 888 } 889 else if( 890 ($datestamp['year'] == $datenow['year'] && $datestamp['yday'] == $datenow['yday'] - 1 ) || 891 ($datestamp['year'] == $datenow['year'] - 1 && $datestamp['mday'] == 31 && $datestamp['mon'] == 12 && $datenow['yday'] == 1) 892 ) { 893 // Yesterday 894 return get_string('yesterday', 'calendar'); 895 } 896 else if( 897 ($datestamp['year'] == $datenow['year'] && $datestamp['yday'] == $datenow['yday'] + 1 ) || 898 ($datestamp['year'] == $datenow['year'] + 1 && $datenow['mday'] == 31 && $datenow['mon'] == 12 && $datestamp['yday'] == 1) 899 ) { 900 // Tomorrow 901 return get_string('tomorrow', 'calendar'); 902 } 903 else { 904 return $formal; 905 } 906 } 907 908 function calendar_time_representation($time) { 909 static $langtimeformat = NULL; 910 if($langtimeformat === NULL) { 911 $langtimeformat = get_string('strftimetime'); 912 } 913 $timeformat = get_user_preferences('calendar_timeformat'); 914 if(empty($timeformat)){ 915 $timeformat = get_config(NULL,'calendar_site_timeformat'); 916 } 917 // The ? is needed because the preference might be present, but empty 918 return userdate($time, empty($timeformat) ? $langtimeformat : $timeformat); 919 } 920 921 /** 922 * TODO document 923 */ 924 function calendar_get_link_href($linkbase, $d, $m, $y) { 925 if(empty($linkbase)) return ''; 926 $paramstr = ''; 927 if(!empty($d)) $paramstr .= '&cal_d='.$d; 928 if(!empty($m)) $paramstr .= '&cal_m='.$m; 929 if(!empty($y)) $paramstr .= '&cal_y='.$y; 930 if(!empty($paramstr)) $paramstr = substr($paramstr, 5); 931 return $linkbase.$paramstr; 932 } 933 934 /** 935 * TODO document 936 */ 937 function calendar_get_link_tag($text, $linkbase, $d, $m, $y) { 938 $href = calendar_get_link_href($linkbase, $d, $m, $y); 939 if(empty($href)) return $text; 940 return '<a href="'.$href.'">'.$text.'</a>'; 941 } 942 943 /** 944 * Build and return a previous month HTML link, with an arrow. 945 * @param string $text The text label. 946 * @param string $linkbase The URL stub. 947 * @param int $d $m $y Day of month, month and year numbers. 948 * @param bool $accesshide Default visible, or hide from all except screenreaders. 949 * @return string HTML string. 950 */ 951 function calendar_get_link_previous($text, $linkbase, $d, $m, $y, $accesshide=false) { 952 $href = calendar_get_link_href($linkbase, $d, $m, $y); 953 if(empty($href)) return $text; 954 return link_arrow_left($text, $href, $accesshide, 'previous'); 955 } 956 957 /** 958 * Build and return a next month HTML link, with an arrow. 959 * @param string $text The text label. 960 * @param string $linkbase The URL stub. 961 * @param int $d $m $y Day of month, month and year numbers. 962 * @param bool $accesshide Default visible, or hide from all except screenreaders. 963 * @return string HTML string. 964 */ 965 function calendar_get_link_next($text, $linkbase, $d, $m, $y, $accesshide=false) { 966 $href = calendar_get_link_href($linkbase, $d, $m, $y); 967 if(empty($href)) return $text; 968 return link_arrow_right($text, $href, $accesshide, 'next'); 969 } 970 971 function calendar_wday_name($englishname) { 972 return get_string(strtolower($englishname), 'calendar'); 973 } 974 975 function calendar_days_in_month($month, $year) { 976 return intval(date('t', mktime(0, 0, 0, $month, 1, $year))); 977 } 978 979 function calendar_get_sideblock_upcoming($events, $linkhref = NULL) { 980 $content = ''; 981 $lines = count($events); 982 if (!$lines) { 983 return $content; 984 } 985 986 for ($i = 0; $i < $lines; ++$i) { 987 if (!isset($events[$i]->time)) { // Just for robustness 988 continue; 989 } 990 $events[$i] = calendar_add_event_metadata($events[$i]); 991 $content .= '<div class="event"><span class="icon c0">'.$events[$i]->icon.'</span> '; 992 if (!empty($events[$i]->referer)) { 993 // That's an activity event, so let's provide the hyperlink 994 $content .= $events[$i]->referer; 995 } else { 996 if(!empty($linkhref)) { 997 $ed = usergetdate($events[$i]->timestart); 998 $href = calendar_get_link_href(CALENDAR_URL.$linkhref, $ed['mday'], $ed['mon'], $ed['year']); 999 $content .= '<a href="'.$href.'#event_'.$events[$i]->id.'">'.$events[$i]->name.'</a>'; 1000 } 1001 else { 1002 $content .= $events[$i]->name; 1003 } 1004 } 1005 $events[$i]->time = str_replace('»', '<br />»', $events[$i]->time); 1006 $content .= '<div class="date">'.$events[$i]->time.'</div></div>'; 1007 if ($i < $lines - 1) $content .= '<hr />'; 1008 } 1009 1010 return $content; 1011 } 1012 1013 function calendar_add_month($month, $year) { 1014 if($month == 12) { 1015 return array(1, $year + 1); 1016 } 1017 else { 1018 return array($month + 1, $year); 1019 } 1020 } 1021 1022 function calendar_sub_month($month, $year) { 1023 if($month == 1) { 1024 return array(12, $year - 1); 1025 } 1026 else { 1027 return array($month - 1, $year); 1028 } 1029 } 1030 1031 function calendar_events_by_day($events, $month, $year, &$eventsbyday, &$durationbyday, &$typesbyday, &$courses) { 1032 $eventsbyday = array(); 1033 $typesbyday = array(); 1034 $durationbyday = array(); 1035 1036 if($events === false) { 1037 return; 1038 } 1039 1040 foreach($events as $event) { 1041 1042 $startdate = usergetdate($event->timestart); 1043 // Set end date = start date if no duration 1044 if ($event->timeduration) { 1045 $enddate = usergetdate($event->timestart + $event->timeduration - 1); 1046 } else { 1047 $enddate = $startdate; 1048 } 1049 1050 // Simple arithmetic: $year * 13 + $month is a distinct integer for each distinct ($year, $month) pair 1051 if(!($startdate['year'] * 13 + $startdate['mon'] <= $year * 13 + $month) && ($enddate['year'] * 13 + $enddate['mon'] >= $year * 13 + $month)) { 1052 // Out of bounds 1053 continue; 1054 } 1055 1056 $eventdaystart = intval($startdate['mday']); 1057 1058 if($startdate['mon'] == $month && $startdate['year'] == $year) { 1059 // Give the event to its day 1060 $eventsbyday[$eventdaystart][] = $event->id; 1061 1062 // Mark the day as having such an event 1063 if($event->courseid == SITEID && $event->groupid == 0) { 1064 $typesbyday[$eventdaystart]['startglobal'] = true; 1065 // Set event class for global event 1066 $events[$event->id]->class = 'event_global'; 1067 } 1068 else if($event->courseid != 0 && $event->courseid != SITEID && $event->groupid == 0) { 1069 $typesbyday[$eventdaystart]['startcourse'] = true; 1070 // Set event class for course event 1071 $events[$event->id]->class = 'event_course'; 1072 } 1073 else if($event->groupid) { 1074 $typesbyday[$eventdaystart]['startgroup'] = true; 1075 // Set event class for group event 1076 $events[$event->id]->class = 'event_group'; 1077 } 1078 else if($event->userid) { 1079 $typesbyday[$eventdaystart]['startuser'] = true; 1080 // Set event class for user event 1081 $events[$event->id]->class = 'event_user'; 1082 } 1083 } 1084 1085 if($event->timeduration == 0) { 1086 // Proceed with the next 1087 continue; 1088 } 1089 1090 // The event starts on $month $year or before. So... 1091 $lowerbound = $startdate['mon'] == $month && $startdate['year'] == $year ? intval($startdate['mday']) : 0; 1092 1093 // Also, it ends on $month $year or later... 1094 $upperbound = $enddate['mon'] == $month && $enddate['year'] == $year ? intval($enddate['mday']) : calendar_days_in_month($month, $year); 1095 1096 // Mark all days between $lowerbound and $upperbound (inclusive) as duration 1097 for($i = $lowerbound + 1; $i <= $upperbound; ++$i) { 1098 $durationbyday[$i][] = $event->id; 1099 if($event->courseid == SITEID && $event->groupid == 0) { 1100 $typesbyday[$i]['durationglobal'] = true; 1101 } 1102 else if($event->courseid != 0 && $event->courseid != SITEID && $event->groupid == 0) { 1103 $typesbyday[$i]['durationcourse'] = true; 1104 } 1105 else if($event->groupid) { 1106 $typesbyday[$i]['durationgroup'] = true; 1107 } 1108 else if($event->userid) { 1109 $typesbyday[$i]['durationuser'] = true; 1110 } 1111 } 1112 1113 } 1114 return; 1115 } 1116 1117 function calendar_get_module_cached(&$coursecache, $modulename, $instance) { 1118 $module = get_coursemodule_from_instance($modulename, $instance); 1119 1120 if($module === false) return false; 1121 if(!calendar_get_course_cached($coursecache, $module->course)) { 1122 return false; 1123 } 1124 return $module; 1125 } 1126 1127 function calendar_get_course_cached(&$coursecache, $courseid) { 1128 global $COURSE; 1129 if (!isset($coursecache[$courseid])) { 1130 if ($courseid == $COURSE->id) { 1131 $coursecache[$courseid] = $COURSE; 1132 } else { 1133 $coursecache[$courseid] = get_record('course', 'id', $courseid); 1134 } 1135 } 1136 return $coursecache[$courseid]; 1137 } 1138 1139 function calendar_session_vars($course=null) { 1140 global $SESSION, $USER; 1141 1142 if(!empty($USER->id) && isset($USER->realuser) && !isset($SESSION->cal_loggedinas)) { 1143 // We just logged in as someone else, update the filtering 1144 unset($SESSION->cal_users_shown); 1145 unset($SESSION->cal_courses_shown); 1146 $SESSION->cal_loggedinas = true; 1147 if(intval(get_user_preferences('calendar_persistflt', 0))) { 1148 calendar_set_filters_status(get_user_preferences('calendar_savedflt', 0xff)); 1149 } 1150 } 1151 else if(!empty($USER->id) && !isset($USER->realuser) && isset($SESSION->cal_loggedinas)) { 1152 // We just logged back to our real self, update again 1153 unset($SESSION->cal_users_shown); 1154 unset($SESSION->cal_courses_shown); 1155 unset($SESSION->cal_loggedinas); 1156 if(intval(get_user_preferences('calendar_persistflt', 0))) { 1157 calendar_set_filters_status(get_user_preferences('calendar_savedflt', 0xff)); 1158 } 1159 } 1160 1161 if(!isset($SESSION->cal_course_referer)) { 1162 $SESSION->cal_course_referer = 0; 1163 } 1164 if(!isset($SESSION->cal_show_global)) { 1165 $SESSION->cal_show_global = true; 1166 } 1167 if(!isset($SESSION->cal_show_groups)) { 1168 $SESSION->cal_show_groups = true; 1169 } 1170 if(!isset($SESSION->cal_show_course)) { 1171 $SESSION->cal_show_course = true; 1172 } 1173 if(!isset($SESSION->cal_show_user)) { 1174 $SESSION->cal_show_user = true; 1175 } 1176 if (isset($course)) { 1177 // speedup hack for calendar related blocks 1178 $SESSION->cal_courses_shown = array($course->id => $course); 1179 } else { 1180 $SESSION->cal_courses_shown = calendar_get_default_courses(true); 1181 } 1182 if(empty($SESSION->cal_users_shown)) { 1183 // The empty() instead of !isset() here makes a whole world of difference, 1184 // as it will automatically change to the user's id when the user first logs 1185 // in. With !isset(), it would never do that. 1186 $SESSION->cal_users_shown = !empty($USER->id) ? $USER->id : false; 1187 } 1188 else if(is_numeric($SESSION->cal_users_shown) && !empty($USER->id) && $SESSION->cal_users_shown != $USER->id) { 1189 // Follow the white rabbit, for example if a teacher logs in as a student 1190 $SESSION->cal_users_shown = $USER->id; 1191 } 1192 } 1193 1194 function calendar_overlib_html() { 1195 return '<div id="overDiv" style="position: absolute; visibility: hidden; z-index:1000;"></div>' 1196 .'<script type="text/javascript" src="'.CALENDAR_URL.'overlib.cfg.php"></script>'; 1197 } 1198 1199 function calendar_set_referring_course($courseid) { 1200 global $SESSION; 1201 $SESSION->cal_course_referer = intval($courseid); 1202 } 1203 1204 function calendar_set_filters(&$courses, &$group, &$user, $courseeventsfrom = NULL, $groupeventsfrom = NULL, $ignorefilters = false) { 1205 global $SESSION, $USER, $CFG; 1206 1207 // Insidious bug-wannabe: setting $SESSION->cal_courses_shown to $course->id would cause 1208 // the code to function incorrectly UNLESS we convert it to an integer. One case where 1209 // PHP's loose type system works against us. 1210 if(is_string($SESSION->cal_courses_shown)) { 1211 $SESSION->cal_courses_shown = intval($SESSION->cal_courses_shown); 1212 } 1213 if($courseeventsfrom === NULL) { 1214 $courseeventsfrom = $SESSION->cal_courses_shown; 1215 } 1216 1217 // MDL-9059, $courseeventsfrom can be an int, or an array of ints, or an array of course objects 1218 // convert all to array of objects 1219 // we probably should do some clean up and make sure that session is set to use the proper form 1220 if (is_int($courseeventsfrom)) { // case of an int, e.g. calendar view page 1221 $c = array(); 1222 $c[$courseeventsfrom] = get_record('course', 'id', $courseeventsfrom); 1223 $courseeventsfrom = $c; 1224 } else if (is_array($courseeventsfrom)) { // case of an array of ints, e.g. course home page 1225 foreach ($courseeventsfrom as $i=>$courseid) { // TODO: this seems wrong, the array is often constructed as [courseid] => 1 ??? 1226 if (is_int($courseid)) { 1227 $courseeventsfrom[$i] = get_record('course', 'id', $courseid); 1228 } 1229 } 1230 } 1231 1232 if($groupeventsfrom === NULL) { 1233 $groupeventsfrom = $SESSION->cal_courses_shown; 1234 } 1235 1236 if(($SESSION->cal_show_course && $SESSION->cal_show_global) || $ignorefilters) { 1237 if(is_int($courseeventsfrom)) { 1238 $courses = array(SITEID, $courseeventsfrom); 1239 } 1240 else if(is_array($courseeventsfrom)) { 1241 $courses = array_keys($courseeventsfrom); 1242 $courses[] = SITEID; 1243 } 1244 } 1245 else if($SESSION->cal_show_course) { 1246 if(is_int($courseeventsfrom)) { 1247 $courses = array($courseeventsfrom); 1248 } 1249 else if(is_array($courseeventsfrom)) { 1250 $courses = array_keys($courseeventsfrom); 1251 } 1252 $courses = array_diff($courses, array(SITEID)); 1253 } 1254 else if($SESSION->cal_show_global) { 1255 $courses = array(SITEID); 1256 } 1257 else { 1258 $courses = false; 1259 } 1260 //BUG 6130 clean $courses array as SESSION has bad entries. 1261 // [pj] TODO: See if this has to do with my new change in get_default_courses and can be taken out 1262 if (is_array($courses)) { 1263 foreach ($courses as $index => $value) { 1264 if (empty($value)) unset($courses[$index]); 1265 } 1266 1267 // Sort courses for consistent colour highlighting 1268 // Effectively ignoring SITEID as setting as last course id 1269 $key = array_search(SITEID, $courses); 1270 if ($key !== false) { 1271 unset($courses[$key]); 1272 sort($courses); 1273 $courses[] = SITEID; 1274 } else { 1275 sort($courses); 1276 } 1277 } 1278 1279 if($SESSION->cal_show_user || $ignorefilters) { 1280 // This doesn't work for arrays yet (maybe someday it will) 1281 $user = $SESSION->cal_users_shown; 1282 } 1283 else { 1284 $user = false; 1285 } 1286 if($SESSION->cal_show_groups || $ignorefilters) { 1287 if(is_int($groupeventsfrom)) { 1288 $groupcourses = array($groupeventsfrom); 1289 } 1290 else if(is_array($groupeventsfrom)) { 1291 $groupcourses = array_keys($groupeventsfrom); 1292 } 1293 1294 // XXX TODO: not sure how to replace $CFG->calendar_adminseesall 1295 if(has_capability('moodle/calendar:manageentries', get_context_instance(CONTEXT_SYSTEM)) && !empty($CFG->calendar_adminseesall)) { 1296 $group = true; 1297 } 1298 else { 1299 $grouparray = array(); 1300 1301 // We already have the courses to examine in $courses 1302 // For each course... 1303 1304 foreach($groupcourses as $courseid) { 1305 1306 if (!isset($courseeventsfrom[$courseid]->context)) { // SHOULD be set MDL-11221 1307 if (is_object($courseeventsfrom[$courseid])) { 1308 $courseeventsfrom[$courseid]->context = get_context_instance(CONTEXT_COURSE, $courseid); 1309 } 1310 } 1311 1312 // If the user is an editing teacher in there, 1313 if (!empty($USER->id) && isset($courseeventsfrom[$courseid]->context) && has_capability('moodle/calendar:manageentries', $courseeventsfrom[$courseid]->context)) { 1314 // If this course has groups, show events from all of them 1315 if(is_int($groupeventsfrom)) { 1316 if (is_object($courseeventsfrom[$courseid])) { // SHOULD be set MDL-11221 1317 $courserecord = $courseeventsfrom[$courseid]; 1318 } else { 1319 $courserecord = get_record('course', 'id', $courseid); 1320 } 1321 $courserecord = get_record('course', 'id', $courseid); 1322 if ($courserecord->groupmode != NOGROUPS || !$courserecord->groupmodeforce) { 1323 $groupids[] = $courseid; 1324 } 1325 } 1326 else if(isset($SESSION->cal_courses_shown[$courseid]) && ($SESSION->cal_courses_shown[$courseid]->groupmode != NOGROUPS || !$SESSION->cal_courses_shown[$courseid]->groupmodeforce)) { 1327 $groupids[] = $courseid; 1328 } 1329 } 1330 1331 // Otherwise (not editing teacher) show events from the group he is a member of 1332 else if(isset($USER->groupmember[$courseid])) { 1333 //changed to 2D array 1334 foreach ($USER->groupmember[$courseid] as $groupid){ 1335 $grouparray[] = $groupid; 1336 } 1337 } 1338 } 1339 1340 if (!empty($groupids)) { 1341 $sql = "SELECT * 1342 FROM {$CFG->prefix}groups 1343 WHERE courseid IN (".implode(',', $groupids).')'; 1344 1345 if ($grouprecords= get_records_sql($sql)) { 1346 foreach ($grouprecords as $grouprecord) { 1347 $grouparray[] = $grouprecord->id; 1348 } 1349 } 1350 } 1351 1352 if(empty($grouparray)) { 1353 $group = false; 1354 } 1355 else { 1356 $group = $grouparray; 1357 } 1358 } 1359 1360 } 1361 else { 1362 $group = false; 1363 } 1364 } 1365 1366 function calendar_edit_event_allowed($event) { 1367 1368 global $USER; 1369 1370 // Must be logged in 1371 if (!isloggedin()) { 1372 return false; 1373 } 1374 1375 // can not be using guest account 1376 if ($USER->username == "guest") { 1377 return false; 1378 } 1379 1380 $sitecontext = get_context_instance(CONTEXT_SYSTEM); 1381 // if user has manageentries at site level, return true 1382 if (has_capability('moodle/calendar:manageentries', $sitecontext)) { 1383 return true; 1384 } 1385 1386 // if groupid is set, it's definitely a group event 1387 if ($event->groupid) { 1388 // Allow users to add/edit group events if: 1389 // 1) They have manageentries (= entries for whole course) 1390 // 2) They have managegroupentries AND are in the group 1391 $group = get_record('groups', 'id', $event->groupid); 1392 return $group && ( 1393 has_capability('moodle/calendar:manageentries', get_context_instance(CONTEXT_COURSE, $group->courseid)) || 1394 (has_capability('moodle/calendar:managegroupentries', get_context_instance(CONTEXT_COURSE, $group->courseid)) 1395 && groups_is_member($event->groupid))); 1396 } else if ($event->courseid) { 1397 // if groupid is not set, but course is set, 1398 // it's definiely a course event 1399 return has_capability('moodle/calendar:manageentries', get_context_instance(CONTEXT_COURSE, $event->courseid)); 1400 } else if ($event->userid && $event->userid == $USER->id) { 1401 // if course is not set, but userid id set, it's a user event 1402 return (has_capability('moodle/calendar:manageownentries', $sitecontext)); 1403 } 1404 return false; 1405 } 1406 1407 function calendar_get_default_courses($ignoreref = false) { 1408 global $USER, $CFG, $SESSION; 1409 1410 if(!empty($SESSION->cal_course_referer) && !$ignoreref) { 1411 return array($SESSION->cal_course_referer => 1); 1412 } 1413 1414 if(empty($USER->id)) { 1415 return array(); 1416 } 1417 1418 $courses = array(); 1419 if (has_capability('moodle/calendar:manageentries', get_context_instance(CONTEXT_SYSTEM))) { 1420 if (!empty($CFG->calendar_adminseesall)) { 1421 $courses = get_records_sql('SELECT id, 1 FROM '.$CFG->prefix.'course'); 1422 return $courses; 1423 } 1424 } 1425 1426 if (isset($CFG->adminseesall)) { 1427 $courses = get_my_courses($USER->id, null, null, $CFG->adminseesall); 1428 } 1429 else { 1430 $courses = get_my_courses($USER->id, null, null, false); 1431 } 1432 1433 return $courses; 1434 } 1435 1436 function calendar_preferences_button() { 1437 global $CFG, $USER; 1438 1439 // Guests have no preferences 1440 if (empty($USER->id) || isguest()) { 1441 return ''; 1442 } 1443 1444 return "<form $CFG->frametarget method=\"get\" ". 1445 " action=\"$CFG->wwwroot/calendar/preferences.php\">". 1446 "<div><input type=\"submit\" value=\"".get_string("preferences", "calendar")." ...\" /></div></form>"; 1447 } 1448 1449 function calendar_format_event_time($event, $now, $morehref, $usecommonwords = true, $showtime=0) { 1450 $startdate = usergetdate($event->timestart); 1451 $enddate = usergetdate($event->timestart + $event->timeduration); 1452 $usermidnightstart = usergetmidnight($event->timestart); 1453 1454 if($event->timeduration) { 1455 // To avoid doing the math if one IF is enough :) 1456 $usermidnightend = usergetmidnight($event->timestart + $event->timeduration); 1457 } 1458 else { 1459 $usermidnightend = $usermidnightstart; 1460 } 1461 1462 // OK, now to get a meaningful display... 1463 // First of all we have to construct a human-readable date/time representation 1464 1465 if($event->timeduration) { 1466 // It has a duration 1467 if($usermidnightstart == $usermidnightend || 1468 ($event->timestart == $usermidnightstart) && ($event->timeduration == 86400 || $event->timeduration == 86399) || 1469 ($event->timestart + $event->timeduration <= $usermidnightstart + 86400)) { 1470 // But it's all on the same day 1471 $timestart = calendar_time_representation($event->timestart); 1472 $timeend = calendar_time_representation($event->timestart + $event->timeduration); 1473 $time = $timestart.' <strong>»</strong> '.$timeend; 1474 1475 if ($event->timestart == $usermidnightstart && ($event->timeduration == 86400 || $event->timeduration == 86399)) { 1476 $time = get_string('allday', 'calendar'); 1477 } 1478 1479 // Set printable representation 1480 if (!$showtime) { 1481 $day = calendar_day_representation($event->timestart, $now, $usecommonwords); 1482 $eventtime = calendar_get_link_tag($day, CALENDAR_URL.'view.php?view=day'.$morehref.'&', $enddate['mday'], $enddate['mon'], $enddate['year']).', '.$time; 1483 } else { 1484 $eventtime = $time; 1485 } 1486 } else { 1487 // It spans two or more days 1488 $daystart = calendar_day_representation($event->timestart, $now, $usecommonwords).', '; 1489 if ($showtime == $usermidnightstart) { 1490 $daystart = ''; 1491 } 1492 $timestart = calendar_time_representation($event->timestart); 1493 $dayend = calendar_day_representation($event->timestart + $event->timeduration, $now, $usecommonwords).', '; 1494 if ($showtime == $usermidnightend) { 1495 $dayend = ''; 1496 } 1497 $timeend = calendar_time_representation($event->timestart + $event->timeduration); 1498 1499 // Set printable representation 1500 if ($now >= $usermidnightstart && $now < ($usermidnightstart + 86400)) { 1501 $eventtime = $timestart.' <strong>»</strong> '.calendar_get_link_tag($dayend, CALENDAR_URL.'view.php?view=day'.$morehref.'&', $enddate['mday'], $enddate['mon'], $enddate['year']). 1502 $timeend; 1503 } else { 1504 $eventtime = calendar_get_link_tag($daystart, CALENDAR_URL.'view.php?view=day'.$morehref.'&', $startdate['mday'], $startdate['mon'], $startdate['year']). 1505 $timestart.' <strong>»</strong> '.calendar_get_link_tag($dayend, CALENDAR_URL.'view.php?view=day'.$morehref.'&', $enddate['mday'], $enddate['mon'], $enddate['year']). 1506 $timeend; 1507 } 1508 } 1509 } else { 1510 $time = ' '; 1511 1512 // Set printable representation 1513 if (!$showtime) { 1514 $day = calendar_day_representation($event->timestart, $now, $usecommonwords); 1515 $eventtime = calendar_get_link_tag($day, CALENDAR_URL.'view.php?view=day'.$morehref.'&', $startdate['mday'], $startdate['mon'], $startdate['year']).trim($time); 1516 } else { 1517 $eventtime = $time; 1518 } 1519 } 1520 1521 if($event->timestart + $event->timeduration < $now) { 1522 // It has expired 1523 $eventtime = '<span class="dimmed_text">'.str_replace(' href=', ' class="dimmed" href=', $eventtime).'</span>'; 1524 } 1525 1526 return $eventtime; 1527 } 1528 1529 function calendar_print_month_selector($name, $selected) { 1530 1531 $months = array(); 1532 1533 for ($i=1; $i<=12; $i++) { 1534 $months[$i] = userdate(gmmktime(12, 0, 0, $i, 15, 2000), '%B'); 1535 } 1536 1537 choose_from_menu($months, $name, $selected, ''); 1538 } 1539 1540 function calendar_get_filters_status() { 1541 global $SESSION; 1542 1543 $status = 0; 1544 if($SESSION->cal_show_global) { 1545 $status += 1; 1546 } 1547 if($SESSION->cal_show_course) { 1548 $status += 2; 1549 } 1550 if($SESSION->cal_show_groups) { 1551 $status += 4; 1552 } 1553 if($SESSION->cal_show_user) { 1554 $status += 8; 1555 } 1556 return $status; 1557 } 1558 1559 function calendar_set_filters_status($packed_bitfield) { 1560 global $SESSION, $USER; 1561 1562 if(!isset($USER) || empty($USER->id)) { 1563 return false; 1564 } 1565 1566 $SESSION->cal_show_global = ($packed_bitfield & 1); 1567 $SESSION->cal_show_course = ($packed_bitfield & 2); 1568 $SESSION->cal_show_groups = ($packed_bitfield & 4); 1569 $SESSION->cal_show_user = ($packed_bitfield & 8); 1570 1571 return true; 1572 } 1573 1574 function calendar_get_allowed_types(&$allowed) { 1575 global $USER, $CFG, $SESSION; 1576 $sitecontext = get_context_instance(CONTEXT_SYSTEM); 1577 $allowed->user = has_capability('moodle/calendar:manageownentries', $sitecontext); 1578 $allowed->groups = false; // This may change just below 1579 $allowed->courses = false; // This may change just below 1580 $allowed->site = has_capability('moodle/calendar:manageentries', get_context_instance(CONTEXT_COURSE, SITEID)); 1581 1582 if(!empty($SESSION->cal_course_referer) && $SESSION->cal_course_referer != SITEID) { 1583 $course = get_record('course', 'id', $SESSION->cal_course_referer); 1584 $coursecontext = get_context_instance(CONTEXT_COURSE, $SESSION->cal_course_referer); 1585 1586 if(has_capability('moodle/calendar:manageentries', $coursecontext)) { 1587 $allowed->courses = array($course->id => 1); 1588 1589 if($course->groupmode != NOGROUPS || !$course->groupmodeforce) { 1590 $allowed->groups = groups_get_all_groups($SESSION->cal_course_referer); 1591 } 1592 } else if(has_capability('moodle/calendar:managegroupentries', $coursecontext)) { 1593 if($course->groupmode != NOGROUPS || !$course->groupmodeforce) { 1594 $allowed->groups = groups_get_all_groups($SESSION->cal_course_referer, $USER->id); 1595 } 1596 } 1597 } 1598 } 1599 1600 /** 1601 * see if user can add calendar entries at all 1602 * used to print the "New Event" button 1603 * @return bool 1604 */ 1605 function calendar_user_can_add_event() { 1606 calendar_get_allowed_types($allowed); 1607 return (bool)($allowed->user || $allowed->groups || $allowed->courses || $allowed->site); 1608 } 1609 ?>