|
Moodle
2.2.1
http://www.collinsharper.com
|
00001 <?php 00002 00004 // // 00005 // NOTICE OF COPYRIGHT // 00006 // // 00007 // Moodle - Calendar extension // 00008 // // 00009 // Copyright (C) 2003-2004 Greek School Network www.sch.gr // 00010 // // 00011 // Designed by: // 00012 // Avgoustos Tsinakos (tsinakos@teikav.edu.gr) // 00013 // Jon Papaioannou (pj@moodle.org) // 00014 // // 00015 // Programming and development: // 00016 // Jon Papaioannou (pj@moodle.org) // 00017 // // 00018 // For bugs, suggestions, etc contact: // 00019 // Jon Papaioannou (pj@moodle.org) // 00020 // // 00021 // The current module was developed at the University of Macedonia // 00022 // (www.uom.gr) under the funding of the Greek School Network (www.sch.gr) // 00023 // The aim of this project is to provide additional and improved // 00024 // functionality to the Asynchronous Distance Education service that the // 00025 // Greek School Network deploys. // 00026 // // 00027 // This program is free software; you can redistribute it and/or modify // 00028 // it under the terms of the GNU General Public License as published by // 00029 // the Free Software Foundation; either version 2 of the License, or // 00030 // (at your option) any later version. // 00031 // // 00032 // This program is distributed in the hope that it will be useful, // 00033 // but WITHOUT ANY WARRANTY; without even the implied warranty of // 00034 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // 00035 // GNU General Public License for more details: // 00036 // // 00037 // http://www.gnu.org/copyleft/gpl.html // 00038 // // 00040 00041 // These are read by the administration component to provide default values 00042 define('CALENDAR_DEFAULT_UPCOMING_LOOKAHEAD', 21); 00043 define('CALENDAR_DEFAULT_UPCOMING_MAXEVENTS', 10); 00044 define('CALENDAR_DEFAULT_STARTING_WEEKDAY', 1); 00045 // This is a packed bitfield: day X is "weekend" if $field & (1 << X) is true 00046 // Default value = 65 = 64 + 1 = 2^6 + 2^0 = Saturday & Sunday 00047 define('CALENDAR_DEFAULT_WEEKEND', 65); 00048 define('CALENDAR_URL', $CFG->wwwroot.'/calendar/'); 00049 define('CALENDAR_TF_24', '%H:%M'); 00050 define('CALENDAR_TF_12', '%I:%M %p'); 00051 00052 define('CALENDAR_EVENT_GLOBAL', 1); 00053 define('CALENDAR_EVENT_COURSE', 2); 00054 define('CALENDAR_EVENT_GROUP', 4); 00055 define('CALENDAR_EVENT_USER', 8); 00056 00061 define('CALENDAR_STARTING_WEEKDAY', CALENDAR_DEFAULT_STARTING_WEEKDAY); 00062 00068 function calendar_get_days() { 00069 return array('sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday'); 00070 } 00071 00079 function calendar_get_starting_weekday() { 00080 global $CFG; 00081 00082 if (isset($CFG->calendar_startwday)) { 00083 $firstday = $CFG->calendar_startwday; 00084 } else { 00085 $firstday = get_string('firstdayofweek', 'langconfig'); 00086 } 00087 00088 if(!is_numeric($firstday)) { 00089 return CALENDAR_DEFAULT_STARTING_WEEKDAY; 00090 } else { 00091 return intval($firstday) % 7; 00092 } 00093 } 00094 00106 function calendar_get_mini($courses, $groups, $users, $cal_month = false, $cal_year = false) { 00107 global $CFG, $USER, $OUTPUT; 00108 00109 $display = new stdClass; 00110 $display->minwday = get_user_preferences('calendar_startwday', calendar_get_starting_weekday()); 00111 $display->maxwday = $display->minwday + 6; 00112 00113 $content = ''; 00114 00115 if(!empty($cal_month) && !empty($cal_year)) { 00116 $thisdate = usergetdate(time()); // Date and time the user sees at his location 00117 if($cal_month == $thisdate['mon'] && $cal_year == $thisdate['year']) { 00118 // Navigated to this month 00119 $date = $thisdate; 00120 $display->thismonth = true; 00121 } else { 00122 // Navigated to other month, let's do a nice trick and save us a lot of work... 00123 if(!checkdate($cal_month, 1, $cal_year)) { 00124 $date = array('mday' => 1, 'mon' => $thisdate['mon'], 'year' => $thisdate['year']); 00125 $display->thismonth = true; 00126 } else { 00127 $date = array('mday' => 1, 'mon' => $cal_month, 'year' => $cal_year); 00128 $display->thismonth = false; 00129 } 00130 } 00131 } else { 00132 $date = usergetdate(time()); // Date and time the user sees at his location 00133 $display->thismonth = true; 00134 } 00135 00136 // Fill in the variables we 're going to use, nice and tidy 00137 list($d, $m, $y) = array($date['mday'], $date['mon'], $date['year']); // This is what we want to display 00138 $display->maxdays = calendar_days_in_month($m, $y); 00139 00140 if (get_user_timezone_offset() < 99) { 00141 // We 'll keep these values as GMT here, and offset them when the time comes to query the db 00142 $display->tstart = gmmktime(0, 0, 0, $m, 1, $y); // This is GMT 00143 $display->tend = gmmktime(23, 59, 59, $m, $display->maxdays, $y); // GMT 00144 } else { 00145 // no timezone info specified 00146 $display->tstart = mktime(0, 0, 0, $m, 1, $y); 00147 $display->tend = mktime(23, 59, 59, $m, $display->maxdays, $y); 00148 } 00149 00150 $startwday = dayofweek(1, $m, $y); 00151 00152 // Align the starting weekday to fall in our display range 00153 // This is simple, not foolproof. 00154 if($startwday < $display->minwday) { 00155 $startwday += 7; 00156 } 00157 00158 // TODO: THIS IS TEMPORARY CODE! 00159 // [pj] I was just reading through this and realized that I when writing this code I was probably 00160 // asking for trouble, as all these time manipulations seem to be unnecessary and a simple 00161 // make_timestamp would accomplish the same thing. So here goes a test: 00162 //$test_start = make_timestamp($y, $m, 1); 00163 //$test_end = make_timestamp($y, $m, $display->maxdays, 23, 59, 59); 00164 //if($test_start != usertime($display->tstart) - dst_offset_on($display->tstart)) { 00165 //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); 00166 //} 00167 //if($test_end != usertime($display->tend) - dst_offset_on($display->tend)) { 00168 //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); 00169 //} 00170 00171 00172 // Get the events matching our criteria. Don't forget to offset the timestamps for the user's TZ! 00173 $events = calendar_get_events( 00174 usertime($display->tstart) - dst_offset_on($display->tstart), 00175 usertime($display->tend) - dst_offset_on($display->tend), 00176 $users, $groups, $courses); 00177 00178 // Set event course class for course events 00179 if (!empty($events)) { 00180 foreach ($events as $eventid => $event) { 00181 if (!empty($event->modulename)) { 00182 $cm = get_coursemodule_from_instance($event->modulename, $event->instance); 00183 if (!groups_course_module_visible($cm)) { 00184 unset($events[$eventid]); 00185 } 00186 } 00187 } 00188 } 00189 00190 // This is either a genius idea or an idiot idea: in order to not complicate things, we use this rule: if, after 00191 // possibly removing SITEID from $courses, there is only one course left, then clicking on a day in the month 00192 // will also set the $SESSION->cal_courses_shown variable to that one course. Otherwise, we 'd need to add extra 00193 // arguments to this function. 00194 00195 $hrefparams = array(); 00196 if(!empty($courses)) { 00197 $courses = array_diff($courses, array(SITEID)); 00198 if(count($courses) == 1) { 00199 $hrefparams['course'] = reset($courses); 00200 } 00201 } 00202 00203 // We want to have easy access by day, since the display is on a per-day basis. 00204 // Arguments passed by reference. 00205 //calendar_events_by_day($events, $display->tstart, $eventsbyday, $durationbyday, $typesbyday); 00206 calendar_events_by_day($events, $m, $y, $eventsbyday, $durationbyday, $typesbyday, $courses); 00207 00208 //Accessibility: added summary and <abbr> elements. 00209 $days_title = calendar_get_days(); 00210 00211 $summary = get_string('calendarheading', 'calendar', userdate(make_timestamp($y, $m), get_string('strftimemonthyear'))); 00212 $summary = get_string('tabledata', 'access', $summary); 00213 $content .= '<table class="minicalendar calendartable" summary="'.$summary.'">'; // Begin table 00214 $content .= '<tr class="weekdays">'; // Header row: day names 00215 00216 // Print out the names of the weekdays 00217 $days = array('sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'); 00218 for($i = $display->minwday; $i <= $display->maxwday; ++$i) { 00219 // This uses the % operator to get the correct weekday no matter what shift we have 00220 // applied to the $display->minwday : $display->maxwday range from the default 0 : 6 00221 $content .= '<th scope="col"><abbr title="'. get_string($days_title[$i % 7], 'calendar') .'">'. 00222 get_string($days[$i % 7], 'calendar') ."</abbr></th>\n"; 00223 } 00224 00225 $content .= '</tr><tr>'; // End of day names; prepare for day numbers 00226 00227 // For the table display. $week is the row; $dayweek is the column. 00228 $dayweek = $startwday; 00229 00230 // Paddding (the first week may have blank days in the beginning) 00231 for($i = $display->minwday; $i < $startwday; ++$i) { 00232 $content .= '<td class="dayblank"> </td>'."\n"; 00233 } 00234 00235 $weekend = CALENDAR_DEFAULT_WEEKEND; 00236 if (isset($CFG->calendar_weekend)) { 00237 $weekend = intval($CFG->calendar_weekend); 00238 } 00239 00240 // Now display all the calendar 00241 for($day = 1; $day <= $display->maxdays; ++$day, ++$dayweek) { 00242 if($dayweek > $display->maxwday) { 00243 // We need to change week (table row) 00244 $content .= '</tr><tr>'; 00245 $dayweek = $display->minwday; 00246 } 00247 00248 // Reset vars 00249 $cell = ''; 00250 if ($weekend & (1 << ($dayweek % 7))) { 00251 // Weekend. This is true no matter what the exact range is. 00252 $class = 'weekend day'; 00253 } else { 00254 // Normal working day. 00255 $class = 'day'; 00256 } 00257 00258 // Special visual fx if an event is defined 00259 if(isset($eventsbyday[$day])) { 00260 $class .= ' hasevent'; 00261 $hrefparams['view'] = 'day'; 00262 $dayhref = calendar_get_link_href(new moodle_url(CALENDAR_URL.'view.php', $hrefparams), $day, $m, $y); 00263 00264 $popupcontent = ''; 00265 foreach($eventsbyday[$day] as $eventid) { 00266 if (!isset($events[$eventid])) { 00267 continue; 00268 } 00269 $event = $events[$eventid]; 00270 $popupalt = ''; 00271 $component = 'moodle'; 00272 if(!empty($event->modulename)) { 00273 $popupicon = 'icon'; 00274 $popupalt = $event->modulename; 00275 $component = $event->modulename; 00276 } else if ($event->courseid == SITEID) { // Site event 00277 $popupicon = 'c/site'; 00278 } else if ($event->courseid != 0 && $event->courseid != SITEID && $event->groupid == 0) { // Course event 00279 $popupicon = 'c/course'; 00280 } else if ($event->groupid) { // Group event 00281 $popupicon = 'c/group'; 00282 } else if ($event->userid) { // User event 00283 $popupicon = 'c/user'; 00284 } 00285 00286 $dayhref->set_anchor('event_'.$event->id); 00287 00288 $popupcontent .= html_writer::start_tag('div'); 00289 $popupcontent .= $OUTPUT->pix_icon($popupicon, $popupalt, $component); 00290 $popupcontent .= html_writer::link($dayhref, format_string($event->name, true)); 00291 $popupcontent .= html_writer::end_tag('div'); 00292 } 00293 00294 //Accessibility: functionality moved to calendar_get_popup. 00295 if($display->thismonth && $day == $d) { 00296 $popup = calendar_get_popup(true, $events[$eventid]->timestart, $popupcontent); 00297 } else { 00298 $popup = calendar_get_popup(false, $events[$eventid]->timestart, $popupcontent); 00299 } 00300 00301 // Class and cell content 00302 if(isset($typesbyday[$day]['startglobal'])) { 00303 $class .= ' calendar_event_global'; 00304 } else if(isset($typesbyday[$day]['startcourse'])) { 00305 $class .= ' calendar_event_course'; 00306 } else if(isset($typesbyday[$day]['startgroup'])) { 00307 $class .= ' calendar_event_group'; 00308 } else if(isset($typesbyday[$day]['startuser'])) { 00309 $class .= ' calendar_event_user'; 00310 } 00311 $cell = '<a href="'.(string)$dayhref.'" '.$popup.'>'.$day.'</a>'; 00312 } else { 00313 $cell = $day; 00314 } 00315 00316 $durationclass = false; 00317 if (isset($typesbyday[$day]['durationglobal'])) { 00318 $durationclass = ' duration_global'; 00319 } else if(isset($typesbyday[$day]['durationcourse'])) { 00320 $durationclass = ' duration_course'; 00321 } else if(isset($typesbyday[$day]['durationgroup'])) { 00322 $durationclass = ' duration_group'; 00323 } else if(isset($typesbyday[$day]['durationuser'])) { 00324 $durationclass = ' duration_user'; 00325 } 00326 if ($durationclass) { 00327 $class .= ' duration '.$durationclass; 00328 } 00329 00330 // If event has a class set then add it to the table day <td> tag 00331 // Note: only one colour for minicalendar 00332 if(isset($eventsbyday[$day])) { 00333 foreach($eventsbyday[$day] as $eventid) { 00334 if (!isset($events[$eventid])) { 00335 continue; 00336 } 00337 $event = $events[$eventid]; 00338 if (!empty($event->class)) { 00339 $class .= ' '.$event->class; 00340 } 00341 break; 00342 } 00343 } 00344 00345 // Special visual fx for today 00346 //Accessibility: hidden text for today, and popup. 00347 if($display->thismonth && $day == $d) { 00348 $class .= ' today'; 00349 $today = get_string('today', 'calendar').' '.userdate(time(), get_string('strftimedayshort')); 00350 00351 if(! isset($eventsbyday[$day])) { 00352 $class .= ' eventnone'; 00353 $popup = calendar_get_popup(true, false); 00354 $cell = '<a href="#" '.$popup.'>'.$day.'</a>'; 00355 } 00356 $cell = get_accesshide($today.' ').$cell; 00357 } 00358 00359 // Just display it 00360 if(!empty($class)) { 00361 $class = ' class="'.$class.'"'; 00362 } 00363 $content .= '<td'.$class.'>'.$cell."</td>\n"; 00364 } 00365 00366 // Paddding (the last week may have blank days at the end) 00367 for($i = $dayweek; $i <= $display->maxwday; ++$i) { 00368 $content .= '<td class="dayblank"> </td>'; 00369 } 00370 $content .= '</tr>'; // Last row ends 00371 00372 $content .= '</table>'; // Tabular display of days ends 00373 00374 return $content; 00375 } 00376 00386 function calendar_get_popup($is_today, $event_timestart, $popupcontent='') { 00387 global $PAGE; 00388 static $popupcount; 00389 if ($popupcount === null) { 00390 $popupcount = 1; 00391 } 00392 $popupcaption = ''; 00393 if($is_today) { 00394 $popupcaption = get_string('today', 'calendar').' '; 00395 } 00396 if (false === $event_timestart) { 00397 $popupcaption .= userdate(time(), get_string('strftimedayshort')); 00398 $popupcontent = get_string('eventnone', 'calendar'); 00399 00400 } else { 00401 $popupcaption .= get_string('eventsfor', 'calendar', userdate($event_timestart, get_string('strftimedayshort'))); 00402 } 00403 $id = 'calendar_tooltip_'.$popupcount; 00404 $PAGE->requires->yui_module('moodle-calendar-eventmanager', 'M.core_calendar.add_event', array(array('eventId'=>$id,'title'=>$popupcaption, 'content'=>$popupcontent))); 00405 00406 $popupcount++; 00407 return 'id="'.$id.'"'; 00408 } 00409 00410 function calendar_get_upcoming($courses, $groups, $users, $daysinfuture, $maxevents, $fromtime=0) { 00411 global $CFG, $COURSE, $DB; 00412 00413 $display = new stdClass; 00414 $display->range = $daysinfuture; // How many days in the future we 'll look 00415 $display->maxevents = $maxevents; 00416 00417 $output = array(); 00418 00419 // Prepare "course caching", since it may save us a lot of queries 00420 $coursecache = array(); 00421 00422 $processed = 0; 00423 $now = time(); // We 'll need this later 00424 $usermidnighttoday = usergetmidnight($now); 00425 00426 if ($fromtime) { 00427 $display->tstart = $fromtime; 00428 } else { 00429 $display->tstart = $usermidnighttoday; 00430 } 00431 00432 // This works correctly with respect to the user's DST, but it is accurate 00433 // only because $fromtime is always the exact midnight of some day! 00434 $display->tend = usergetmidnight($display->tstart + DAYSECS * $display->range + 3 * HOURSECS) - 1; 00435 00436 // Get the events matching our criteria 00437 $events = calendar_get_events($display->tstart, $display->tend, $users, $groups, $courses); 00438 00439 // This is either a genius idea or an idiot idea: in order to not complicate things, we use this rule: if, after 00440 // possibly removing SITEID from $courses, there is only one course left, then clicking on a day in the month 00441 // will also set the $SESSION->cal_courses_shown variable to that one course. Otherwise, we 'd need to add extra 00442 // arguments to this function. 00443 00444 $hrefparams = array(); 00445 if(!empty($courses)) { 00446 $courses = array_diff($courses, array(SITEID)); 00447 if(count($courses) == 1) { 00448 $hrefparams['course'] = reset($courses); 00449 } 00450 } 00451 00452 if ($events !== false) { 00453 00454 $modinfo =& get_fast_modinfo($COURSE); 00455 00456 foreach($events as $event) { 00457 00458 00459 if (!empty($event->modulename)) { 00460 if ($event->courseid == $COURSE->id) { 00461 if (isset($modinfo->instances[$event->modulename][$event->instance])) { 00462 $cm = $modinfo->instances[$event->modulename][$event->instance]; 00463 if (!$cm->uservisible) { 00464 continue; 00465 } 00466 } 00467 } else { 00468 if (!$cm = get_coursemodule_from_instance($event->modulename, $event->instance)) { 00469 continue; 00470 } 00471 if (!coursemodule_visible_for_user($cm)) { 00472 continue; 00473 } 00474 } 00475 if ($event->modulename == 'assignment'){ 00476 // create calendar_event to test edit_event capability 00477 // this new event will also prevent double creation of calendar_event object 00478 $checkevent = new calendar_event($event); 00479 // TODO: rewrite this hack somehow 00480 if (!calendar_edit_event_allowed($checkevent)){ // cannot manage entries, eg. student 00481 if (!$assignment = $DB->get_record('assignment', array('id'=>$event->instance))) { 00482 // print_error("invalidid", 'assignment'); 00483 continue; 00484 } 00485 // assign assignment to assignment object to use hidden_is_hidden method 00486 require_once($CFG->dirroot.'/mod/assignment/lib.php'); 00487 00488 if (!file_exists($CFG->dirroot.'/mod/assignment/type/'.$assignment->assignmenttype.'/assignment.class.php')) { 00489 continue; 00490 } 00491 require_once ($CFG->dirroot.'/mod/assignment/type/'.$assignment->assignmenttype.'/assignment.class.php'); 00492 00493 $assignmentclass = 'assignment_'.$assignment->assignmenttype; 00494 $assignmentinstance = new $assignmentclass($cm->id, $assignment, $cm); 00495 00496 if ($assignmentinstance->description_is_hidden()){//force not to show description before availability 00497 $event->description = get_string('notavailableyet', 'assignment'); 00498 } 00499 } 00500 } 00501 } 00502 00503 if ($processed >= $display->maxevents) { 00504 break; 00505 } 00506 00507 $event->time = calendar_format_event_time($event, $now, $hrefparams); 00508 $output[] = $event; 00509 ++$processed; 00510 } 00511 } 00512 return $output; 00513 } 00514 00515 function calendar_add_event_metadata($event) { 00516 global $CFG, $OUTPUT; 00517 00518 //Support multilang in event->name 00519 $event->name = format_string($event->name,true); 00520 00521 if(!empty($event->modulename)) { // Activity event 00522 // The module name is set. I will assume that it has to be displayed, and 00523 // also that it is an automatically-generated event. And of course that the 00524 // fields for get_coursemodule_from_instance are set correctly. 00525 $module = calendar_get_module_cached($coursecache, $event->modulename, $event->instance); 00526 00527 if ($module === false) { 00528 return; 00529 } 00530 00531 $modulename = get_string('modulename', $event->modulename); 00532 if (get_string_manager()->string_exists($event->eventtype, $event->modulename)) { 00533 // will be used as alt text if the event icon 00534 $eventtype = get_string($event->eventtype, $event->modulename); 00535 } else { 00536 $eventtype = ''; 00537 } 00538 $icon = $OUTPUT->pix_url('icon', $event->modulename) . ''; 00539 00540 $context = get_context_instance(CONTEXT_COURSE, $module->course); 00541 $fullname = format_string($coursecache[$module->course]->fullname, true, array('context' => $context)); 00542 00543 $event->icon = '<img height="16" width="16" src="'.$icon.'" alt="'.$eventtype.'" title="'.$modulename.'" style="vertical-align: middle;" />'; 00544 $event->referer = '<a href="'.$CFG->wwwroot.'/mod/'.$event->modulename.'/view.php?id='.$module->id.'">'.$event->name.'</a>'; 00545 $event->courselink = '<a href="'.$CFG->wwwroot.'/course/view.php?id='.$module->course.'">'.$fullname.'</a>'; 00546 $event->cmid = $module->id; 00547 00548 00549 } else if($event->courseid == SITEID) { // Site event 00550 $event->icon = '<img height="16" width="16" src="'.$OUTPUT->pix_url('c/site') . '" alt="'.get_string('globalevent', 'calendar').'" style="vertical-align: middle;" />'; 00551 $event->cssclass = 'calendar_event_global'; 00552 } else if($event->courseid != 0 && $event->courseid != SITEID && $event->groupid == 0) { // Course event 00553 calendar_get_course_cached($coursecache, $event->courseid); 00554 00555 $context = get_context_instance(CONTEXT_COURSE, $event->courseid); 00556 $fullname = format_string($coursecache[$event->courseid]->fullname, true, array('context' => $context)); 00557 00558 $event->icon = '<img height="16" width="16" src="'.$OUTPUT->pix_url('c/course') . '" alt="'.get_string('courseevent', 'calendar').'" style="vertical-align: middle;" />'; 00559 $event->courselink = '<a href="'.$CFG->wwwroot.'/course/view.php?id='.$event->courseid.'">'.$fullname.'</a>'; 00560 $event->cssclass = 'calendar_event_course'; 00561 } else if ($event->groupid) { // Group event 00562 $event->icon = '<img height="16" width="16" src="'.$OUTPUT->pix_url('c/group') . '" alt="'.get_string('groupevent', 'calendar').'" style="vertical-align: middle;" />'; 00563 $event->cssclass = 'calendar_event_group'; 00564 } else if($event->userid) { // User event 00565 $event->icon = '<img height="16" width="16" src="'.$OUTPUT->pix_url('c/user') . '" alt="'.get_string('userevent', 'calendar').'" style="vertical-align: middle;" />'; 00566 $event->cssclass = 'calendar_event_user'; 00567 } 00568 return $event; 00569 } 00570 00576 function calendar_print_event($event, $showactions=true) { 00577 global $CFG, $USER, $OUTPUT, $PAGE; 00578 debugging('calendar_print_event is deprecated please update your code', DEBUG_DEVELOPER); 00579 $renderer = $PAGE->get_renderer('core_calendar'); 00580 if (!($event instanceof calendar_event)) { 00581 $event = new calendar_event($event); 00582 } 00583 echo $renderer->event($event); 00584 } 00585 00598 function calendar_get_events($tstart, $tend, $users, $groups, $courses, $withduration=true, $ignorehidden=true) { 00599 global $DB; 00600 00601 $whereclause = ''; 00602 // Quick test 00603 if(is_bool($users) && is_bool($groups) && is_bool($courses)) { 00604 return array(); 00605 } 00606 00607 if(is_array($users) && !empty($users)) { 00608 // Events from a number of users 00609 if(!empty($whereclause)) $whereclause .= ' OR'; 00610 $whereclause .= ' (userid IN ('.implode(',', $users).') AND courseid = 0 AND groupid = 0)'; 00611 } else if(is_numeric($users)) { 00612 // Events from one user 00613 if(!empty($whereclause)) $whereclause .= ' OR'; 00614 $whereclause .= ' (userid = '.$users.' AND courseid = 0 AND groupid = 0)'; 00615 } else if($users === true) { 00616 // Events from ALL users 00617 if(!empty($whereclause)) $whereclause .= ' OR'; 00618 $whereclause .= ' (userid != 0 AND courseid = 0 AND groupid = 0)'; 00619 } else if($users === false) { 00620 // No user at all, do nothing 00621 } 00622 00623 if(is_array($groups) && !empty($groups)) { 00624 // Events from a number of groups 00625 if(!empty($whereclause)) $whereclause .= ' OR'; 00626 $whereclause .= ' groupid IN ('.implode(',', $groups).')'; 00627 } else if(is_numeric($groups)) { 00628 // Events from one group 00629 if(!empty($whereclause)) $whereclause .= ' OR '; 00630 $whereclause .= ' groupid = '.$groups; 00631 } else if($groups === true) { 00632 // Events from ALL groups 00633 if(!empty($whereclause)) $whereclause .= ' OR '; 00634 $whereclause .= ' groupid != 0'; 00635 } 00636 // boolean false (no groups at all): we don't need to do anything 00637 00638 if(is_array($courses) && !empty($courses)) { 00639 if(!empty($whereclause)) { 00640 $whereclause .= ' OR'; 00641 } 00642 $whereclause .= ' (groupid = 0 AND courseid IN ('.implode(',', $courses).'))'; 00643 } else if(is_numeric($courses)) { 00644 // One course 00645 if(!empty($whereclause)) $whereclause .= ' OR'; 00646 $whereclause .= ' (groupid = 0 AND courseid = '.$courses.')'; 00647 } else if ($courses === true) { 00648 // Events from ALL courses 00649 if(!empty($whereclause)) $whereclause .= ' OR'; 00650 $whereclause .= ' (groupid = 0 AND courseid != 0)'; 00651 } 00652 00653 // Security check: if, by now, we have NOTHING in $whereclause, then it means 00654 // that NO event-selecting clauses were defined. Thus, we won't be returning ANY 00655 // events no matter what. Allowing the code to proceed might return a completely 00656 // valid query with only time constraints, thus selecting ALL events in that time frame! 00657 if(empty($whereclause)) { 00658 return array(); 00659 } 00660 00661 if($withduration) { 00662 $timeclause = '(timestart >= '.$tstart.' OR timestart + timeduration > '.$tstart.') AND timestart <= '.$tend; 00663 } 00664 else { 00665 $timeclause = 'timestart >= '.$tstart.' AND timestart <= '.$tend; 00666 } 00667 if(!empty($whereclause)) { 00668 // We have additional constraints 00669 $whereclause = $timeclause.' AND ('.$whereclause.')'; 00670 } 00671 else { 00672 // Just basic time filtering 00673 $whereclause = $timeclause; 00674 } 00675 00676 if ($ignorehidden) { 00677 $whereclause .= ' AND visible = 1'; 00678 } 00679 00680 $events = $DB->get_records_select('event', $whereclause, null, 'timestart'); 00681 if ($events === false) { 00682 $events = array(); 00683 } 00684 return $events; 00685 } 00686 00687 function calendar_top_controls($type, $data) { 00688 global $CFG; 00689 $content = ''; 00690 if(!isset($data['d'])) { 00691 $data['d'] = 1; 00692 } 00693 00694 // Ensure course id passed if relevant 00695 // Required due to changes in view/lib.php mainly (calendar_session_vars()) 00696 $courseid = ''; 00697 if (!empty($data['id'])) { 00698 $courseid = '&course='.$data['id']; 00699 } 00700 00701 if(!checkdate($data['m'], $data['d'], $data['y'])) { 00702 $time = time(); 00703 } 00704 else { 00705 $time = make_timestamp($data['y'], $data['m'], $data['d']); 00706 } 00707 $date = usergetdate($time); 00708 00709 $data['m'] = $date['mon']; 00710 $data['y'] = $date['year']; 00711 00712 //Accessibility: calendar block controls, replaced <table> with <div>. 00713 //$nexttext = link_arrow_right(get_string('monthnext', 'access'), $url='', $accesshide=true); 00714 //$prevtext = link_arrow_left(get_string('monthprev', 'access'), $url='', $accesshide=true); 00715 00716 switch($type) { 00717 case 'frontpage': 00718 list($prevmonth, $prevyear) = calendar_sub_month($data['m'], $data['y']); 00719 list($nextmonth, $nextyear) = calendar_add_month($data['m'], $data['y']); 00720 $nextlink = calendar_get_link_next(get_string('monthnext', 'access'), 'index.php?', 0, $nextmonth, $nextyear, $accesshide=true); 00721 $prevlink = calendar_get_link_previous(get_string('monthprev', 'access'), 'index.php?', 0, $prevmonth, $prevyear, true); 00722 00723 $calendarlink = calendar_get_link_href(new moodle_url(CALENDAR_URL.'view.php', array('view'=>'month')), 1, $data['m'], $data['y']); 00724 if (!empty($data['id'])) { 00725 $calendarlink->param('course', $data['id']); 00726 } 00727 00728 if (right_to_left()) { 00729 $left = $nextlink; 00730 $right = $prevlink; 00731 } else { 00732 $left = $prevlink; 00733 $right = $nextlink; 00734 } 00735 00736 $content .= html_writer::start_tag('div', array('class'=>'calendar-controls')); 00737 $content .= $left.'<span class="hide"> | </span>'; 00738 $content .= html_writer::tag('span', html_writer::link($calendarlink, userdate($time, get_string('strftimemonthyear')), array('title'=>get_string('monththis','calendar'))), array('class'=>'current')); 00739 $content .= '<span class="hide"> | </span>'. $right; 00740 $content .= "<span class=\"clearer\"><!-- --></span>\n"; 00741 $content .= html_writer::end_tag('div'); 00742 00743 break; 00744 case 'course': 00745 list($prevmonth, $prevyear) = calendar_sub_month($data['m'], $data['y']); 00746 list($nextmonth, $nextyear) = calendar_add_month($data['m'], $data['y']); 00747 $nextlink = calendar_get_link_next(get_string('monthnext', 'access'), 'view.php?id='.$data['id'].'&', 0, $nextmonth, $nextyear, $accesshide=true); 00748 $prevlink = calendar_get_link_previous(get_string('monthprev', 'access'), 'view.php?id='.$data['id'].'&', 0, $prevmonth, $prevyear, true); 00749 00750 $calendarlink = calendar_get_link_href(new moodle_url(CALENDAR_URL.'view.php', array('view'=>'month')), 1, $data['m'], $data['y']); 00751 if (!empty($data['id'])) { 00752 $calendarlink->param('course', $data['id']); 00753 } 00754 00755 if (right_to_left()) { 00756 $left = $nextlink; 00757 $right = $prevlink; 00758 } else { 00759 $left = $prevlink; 00760 $right = $nextlink; 00761 } 00762 00763 $content .= html_writer::start_tag('div', array('class'=>'calendar-controls')); 00764 $content .= $left.'<span class="hide"> | </span>'; 00765 $content .= html_writer::tag('span', html_writer::link($calendarlink, userdate($time, get_string('strftimemonthyear')), array('title'=>get_string('monththis','calendar'))), array('class'=>'current')); 00766 $content .= '<span class="hide"> | </span>'. $right; 00767 $content .= "<span class=\"clearer\"><!-- --></span>"; 00768 $content .= html_writer::end_tag('div'); 00769 break; 00770 case 'upcoming': 00771 $calendarlink = calendar_get_link_href(new moodle_url(CALENDAR_URL.'view.php', array('view'=>'upcoming')), 1, $data['m'], $data['y']); 00772 if (!empty($data['id'])) { 00773 $calendarlink->param('course', $data['id']); 00774 } 00775 $calendarlink = html_writer::link($calendarlink, userdate($time, get_string('strftimemonthyear'))); 00776 $content .= html_writer::tag('div', $calendarlink, array('class'=>'centered')); 00777 break; 00778 case 'display': 00779 $calendarlink = calendar_get_link_href(new moodle_url(CALENDAR_URL.'view.php', array('view'=>'month')), 1, $data['m'], $data['y']); 00780 if (!empty($data['id'])) { 00781 $calendarlink->param('course', $data['id']); 00782 } 00783 $calendarlink = html_writer::link($calendarlink, userdate($time, get_string('strftimemonthyear'))); 00784 $content .= html_writer::tag('h3', $calendarlink); 00785 break; 00786 case 'month': 00787 list($prevmonth, $prevyear) = calendar_sub_month($data['m'], $data['y']); 00788 list($nextmonth, $nextyear) = calendar_add_month($data['m'], $data['y']); 00789 $prevdate = make_timestamp($prevyear, $prevmonth, 1); 00790 $nextdate = make_timestamp($nextyear, $nextmonth, 1); 00791 $prevlink = calendar_get_link_previous(userdate($prevdate, get_string('strftimemonthyear')), 'view.php?view=month'.$courseid.'&', 1, $prevmonth, $prevyear); 00792 $nextlink = calendar_get_link_next(userdate($nextdate, get_string('strftimemonthyear')), 'view.php?view=month'.$courseid.'&', 1, $nextmonth, $nextyear); 00793 00794 if (right_to_left()) { 00795 $left = $nextlink; 00796 $right = $prevlink; 00797 } else { 00798 $left = $prevlink; 00799 $right = $nextlink; 00800 } 00801 00802 $content .= html_writer::start_tag('div', array('class'=>'calendar-controls')); 00803 $content .= $left . '<span class="hide"> | </span><h1 class="current">'.userdate($time, get_string('strftimemonthyear'))."</h1>"; 00804 $content .= '<span class="hide"> | </span>' . $right; 00805 $content .= '<span class="clearer"><!-- --></span>'; 00806 $content .= html_writer::end_tag('div')."\n"; 00807 break; 00808 case 'day': 00809 $days = calendar_get_days(); 00810 $data['d'] = $date['mday']; // Just for convenience 00811 $prevdate = usergetdate(make_timestamp($data['y'], $data['m'], $data['d'] - 1)); 00812 $nextdate = usergetdate(make_timestamp($data['y'], $data['m'], $data['d'] + 1)); 00813 $prevname = calendar_wday_name($days[$prevdate['wday']]); 00814 $nextname = calendar_wday_name($days[$nextdate['wday']]); 00815 $prevlink = calendar_get_link_previous($prevname, 'view.php?view=day'.$courseid.'&', $prevdate['mday'], $prevdate['mon'], $prevdate['year']); 00816 $nextlink = calendar_get_link_next($nextname, 'view.php?view=day'.$courseid.'&', $nextdate['mday'], $nextdate['mon'], $nextdate['year']); 00817 00818 if (right_to_left()) { 00819 $left = $nextlink; 00820 $right = $prevlink; 00821 } else { 00822 $left = $prevlink; 00823 $right = $nextlink; 00824 } 00825 00826 $content .= html_writer::start_tag('div', array('class'=>'calendar-controls')); 00827 $content .= $left; 00828 $content .= '<span class="hide"> | </span><span class="current">'.userdate($time, get_string('strftimedaydate')).'</span>'; 00829 $content .= '<span class="hide"> | </span>'. $right; 00830 $content .= "<span class=\"clearer\"><!-- --></span>"; 00831 $content .= html_writer::end_tag('div')."\n"; 00832 00833 break; 00834 } 00835 return $content; 00836 } 00837 00838 function calendar_filter_controls(moodle_url $returnurl) { 00839 global $CFG, $USER, $OUTPUT; 00840 00841 $groupevents = true; 00842 00843 $id = optional_param( 'id',0,PARAM_INT ); 00844 00845 $seturl = new moodle_url('/calendar/set.php', array('return' => base64_encode($returnurl->out(false)), 'sesskey'=>sesskey())); 00846 00847 $content = '<table>'; 00848 $content .= '<tr>'; 00849 00850 $seturl->param('var', 'showglobal'); 00851 if (calendar_show_event_type(CALENDAR_EVENT_GLOBAL)) { 00852 $content .= '<td class="eventskey calendar_event_global" style="width: 11px;"><img src="'.$OUTPUT->pix_url('t/hide') . '" class="iconsmall" alt="'.get_string('hide').'" title="'.get_string('tt_hideglobal', 'calendar').'" style="cursor:pointer" onclick="location.href='."'".$seturl."'".'" /></td>'; 00853 $content .= '<td><a href="'.$seturl.'" title="'.get_string('tt_hideglobal', 'calendar').'">'.get_string('global', 'calendar').'</a></td>'."\n"; 00854 } else { 00855 $content .= '<td style="width: 11px;"><img src="'.$OUTPUT->pix_url('t/show') . '" class="iconsmall" alt="'.get_string('show').'" title="'.get_string('tt_showglobal', 'calendar').'" style="cursor:pointer" onclick="location.href='."'".$seturl."'".'" /></td>'; 00856 $content .= '<td><a href="'.$seturl.'" title="'.get_string('tt_showglobal', 'calendar').'">'.get_string('global', 'calendar').'</a></td>'."\n"; 00857 } 00858 00859 $seturl->param('var', 'showcourses'); 00860 if (calendar_show_event_type(CALENDAR_EVENT_COURSE)) { 00861 $content .= '<td class="eventskey calendar_event_course" style="width: 11px;"><img src="'.$OUTPUT->pix_url('t/hide') . '" class="iconsmall" alt="'.get_string('hide').'" title="'.get_string('tt_hidecourse', 'calendar').'" style="cursor:pointer" onclick="location.href='."'".$seturl."'".'" /></td>'; 00862 $content .= '<td><a href="'.$seturl.'" title="'.get_string('tt_hidecourse', 'calendar').'">'.get_string('course', 'calendar').'</a></td>'."\n"; 00863 } else { 00864 $content .= '<td style="width: 11px;"><img src="'.$OUTPUT->pix_url('t/show') . '" class="iconsmall" alt="'.get_string('hide').'" title="'.get_string('tt_showcourse', 'calendar').'" style="cursor:pointer" onclick="location.href='."'".$seturl."'".'" /></td>'; 00865 $content .= '<td><a href="'.$seturl.'" title="'.get_string('tt_showcourse', 'calendar').'">'.get_string('course', 'calendar').'</a></td>'."\n"; 00866 } 00867 00868 if (isloggedin() && !isguestuser()) { 00869 $content .= "</tr>\n<tr>"; 00870 00871 if ($groupevents) { 00872 // This course MIGHT have group events defined, so show the filter 00873 $seturl->param('var', 'showgroups'); 00874 if (calendar_show_event_type(CALENDAR_EVENT_GROUP)) { 00875 $content .= '<td class="eventskey calendar_event_group" style="width: 11px;"><img src="'.$OUTPUT->pix_url('t/hide') . '" class="iconsmall" alt="'.get_string('hide').'" title="'.get_string('tt_hidegroups', 'calendar').'" style="cursor:pointer" onclick="location.href='."'".$seturl."'".'" /></td>'; 00876 $content .= '<td><a href="'.$seturl.'" title="'.get_string('tt_hidegroups', 'calendar').'">'.get_string('group', 'calendar').'</a></td>'."\n"; 00877 } else { 00878 $content .= '<td style="width: 11px;"><img src="'.$OUTPUT->pix_url('t/show') . '" class="iconsmall" alt="'.get_string('show').'" title="'.get_string('tt_showgroups', 'calendar').'" style="cursor:pointer" onclick="location.href='."'".$seturl."'".'" /></td>'; 00879 $content .= '<td><a href="'.$seturl.'" title="'.get_string('tt_showgroups', 'calendar').'">'.get_string('group', 'calendar').'</a></td>'."\n"; 00880 } 00881 } else { 00882 // This course CANNOT have group events, so lose the filter 00883 $content .= '<td style="width: 11px;"></td><td> </td>'."\n"; 00884 } 00885 00886 $seturl->param('var', 'showuser'); 00887 if (calendar_show_event_type(CALENDAR_EVENT_USER)) { 00888 $content .= '<td class="eventskey calendar_event_user" style="width: 11px;"><img src="'.$OUTPUT->pix_url('t/hide') . '" class="iconsmall" alt="'.get_string('hide').'" title="'.get_string('tt_hideuser', 'calendar').'" style="cursor:pointer" onclick="location.href='."'".$seturl."'".'" /></td>'; 00889 $content .= '<td><a href="'.$seturl.'" title="'.get_string('tt_hideuser', 'calendar').'">'.get_string('user', 'calendar').'</a></td>'."\n"; 00890 } else { 00891 $content .= '<td style="width: 11px;"><img src="'.$OUTPUT->pix_url('t/show') . '" class="iconsmall" alt="'.get_string('show').'" title="'.get_string('tt_showuser', 'calendar').'" style="cursor:pointer" onclick="location.href='."'".$seturl."'".'" /></td>'; 00892 $content .= '<td><a href="'.$seturl.'" title="'.get_string('tt_showuser', 'calendar').'">'.get_string('user', 'calendar').'</a></td>'."\n"; 00893 } 00894 } 00895 $content .= "</tr>\n</table>\n"; 00896 00897 return $content; 00898 } 00899 00900 function calendar_day_representation($tstamp, $now = false, $usecommonwords = true) { 00901 00902 static $shortformat; 00903 if(empty($shortformat)) { 00904 $shortformat = get_string('strftimedayshort'); 00905 } 00906 00907 if($now === false) { 00908 $now = time(); 00909 } 00910 00911 // To have it in one place, if a change is needed 00912 $formal = userdate($tstamp, $shortformat); 00913 00914 $datestamp = usergetdate($tstamp); 00915 $datenow = usergetdate($now); 00916 00917 if($usecommonwords == false) { 00918 // We don't want words, just a date 00919 return $formal; 00920 } 00921 else if($datestamp['year'] == $datenow['year'] && $datestamp['yday'] == $datenow['yday']) { 00922 // Today 00923 return get_string('today', 'calendar'); 00924 } 00925 else if( 00926 ($datestamp['year'] == $datenow['year'] && $datestamp['yday'] == $datenow['yday'] - 1 ) || 00927 ($datestamp['year'] == $datenow['year'] - 1 && $datestamp['mday'] == 31 && $datestamp['mon'] == 12 && $datenow['yday'] == 1) 00928 ) { 00929 // Yesterday 00930 return get_string('yesterday', 'calendar'); 00931 } 00932 else if( 00933 ($datestamp['year'] == $datenow['year'] && $datestamp['yday'] == $datenow['yday'] + 1 ) || 00934 ($datestamp['year'] == $datenow['year'] + 1 && $datenow['mday'] == 31 && $datenow['mon'] == 12 && $datestamp['yday'] == 1) 00935 ) { 00936 // Tomorrow 00937 return get_string('tomorrow', 'calendar'); 00938 } 00939 else { 00940 return $formal; 00941 } 00942 } 00943 00944 function calendar_time_representation($time) { 00945 static $langtimeformat = NULL; 00946 if($langtimeformat === NULL) { 00947 $langtimeformat = get_string('strftimetime'); 00948 } 00949 $timeformat = get_user_preferences('calendar_timeformat'); 00950 if(empty($timeformat)){ 00951 $timeformat = get_config(NULL,'calendar_site_timeformat'); 00952 } 00953 // The ? is needed because the preference might be present, but empty 00954 return userdate($time, empty($timeformat) ? $langtimeformat : $timeformat); 00955 } 00956 00966 function calendar_get_link_href($linkbase, $d, $m, $y) { 00967 if (empty($linkbase)) { 00968 return ''; 00969 } 00970 if (!($linkbase instanceof moodle_url)) { 00971 $linkbase = new moodle_url(); 00972 } 00973 if (!empty($d)) { 00974 $linkbase->param('cal_d', $d); 00975 } 00976 if (!empty($m)) { 00977 $linkbase->param('cal_m', $m); 00978 } 00979 if (!empty($y)) { 00980 $linkbase->param('cal_y', $y); 00981 } 00982 return $linkbase; 00983 } 00984 00998 function calendar_get_link_tag($text, $linkbase, $d, $m, $y) { 00999 $url = calendar_get_link_href(new moodle_url($linkbase), $d, $m, $y); 01000 if (empty($url)) { 01001 return $text; 01002 } 01003 return html_writer::link($url, $text); 01004 } 01005 01015 function calendar_get_link_previous($text, $linkbase, $d, $m, $y, $accesshide=false) { 01016 $href = calendar_get_link_href(new moodle_url($linkbase), $d, $m, $y); 01017 if (empty($href)) { 01018 return $text; 01019 } 01020 return link_arrow_left($text, (string)$href, $accesshide, 'previous'); 01021 } 01022 01032 function calendar_get_link_next($text, $linkbase, $d, $m, $y, $accesshide=false) { 01033 $href = calendar_get_link_href(new moodle_url($linkbase), $d, $m, $y); 01034 if (empty($href)) { 01035 return $text; 01036 } 01037 return link_arrow_right($text, (string)$href, $accesshide, 'next'); 01038 } 01039 01040 function calendar_wday_name($englishname) { 01041 return get_string(strtolower($englishname), 'calendar'); 01042 } 01043 01044 function calendar_days_in_month($month, $year) { 01045 return intval(date('t', mktime(0, 0, 0, $month, 1, $year))); 01046 } 01047 01048 function calendar_get_block_upcoming($events, $linkhref = NULL) { 01049 $content = ''; 01050 $lines = count($events); 01051 if (!$lines) { 01052 return $content; 01053 } 01054 01055 for ($i = 0; $i < $lines; ++$i) { 01056 if (!isset($events[$i]->time)) { // Just for robustness 01057 continue; 01058 } 01059 $events[$i] = calendar_add_event_metadata($events[$i]); 01060 $content .= '<div class="event"><span class="icon c0">'.$events[$i]->icon.'</span> '; 01061 if (!empty($events[$i]->referer)) { 01062 // That's an activity event, so let's provide the hyperlink 01063 $content .= $events[$i]->referer; 01064 } else { 01065 if(!empty($linkhref)) { 01066 $ed = usergetdate($events[$i]->timestart); 01067 $href = calendar_get_link_href(new moodle_url(CALENDAR_URL.$linkhref), $ed['mday'], $ed['mon'], $ed['year']); 01068 $href->set_anchor('event_'.$events[$i]->id); 01069 $content .= html_writer::link($href, $events[$i]->name); 01070 } 01071 else { 01072 $content .= $events[$i]->name; 01073 } 01074 } 01075 $events[$i]->time = str_replace('»', '<br />»', $events[$i]->time); 01076 $content .= '<div class="date">'.$events[$i]->time.'</div></div>'; 01077 if ($i < $lines - 1) $content .= '<hr />'; 01078 } 01079 01080 return $content; 01081 } 01082 01083 function calendar_add_month($month, $year) { 01084 if($month == 12) { 01085 return array(1, $year + 1); 01086 } 01087 else { 01088 return array($month + 1, $year); 01089 } 01090 } 01091 01092 function calendar_sub_month($month, $year) { 01093 if($month == 1) { 01094 return array(12, $year - 1); 01095 } 01096 else { 01097 return array($month - 1, $year); 01098 } 01099 } 01100 01101 function calendar_events_by_day($events, $month, $year, &$eventsbyday, &$durationbyday, &$typesbyday, &$courses) { 01102 $eventsbyday = array(); 01103 $typesbyday = array(); 01104 $durationbyday = array(); 01105 01106 if($events === false) { 01107 return; 01108 } 01109 01110 foreach($events as $event) { 01111 01112 $startdate = usergetdate($event->timestart); 01113 // Set end date = start date if no duration 01114 if ($event->timeduration) { 01115 $enddate = usergetdate($event->timestart + $event->timeduration - 1); 01116 } else { 01117 $enddate = $startdate; 01118 } 01119 01120 // Simple arithmetic: $year * 13 + $month is a distinct integer for each distinct ($year, $month) pair 01121 if(!($startdate['year'] * 13 + $startdate['mon'] <= $year * 13 + $month) && ($enddate['year'] * 13 + $enddate['mon'] >= $year * 13 + $month)) { 01122 // Out of bounds 01123 continue; 01124 } 01125 01126 $eventdaystart = intval($startdate['mday']); 01127 01128 if($startdate['mon'] == $month && $startdate['year'] == $year) { 01129 // Give the event to its day 01130 $eventsbyday[$eventdaystart][] = $event->id; 01131 01132 // Mark the day as having such an event 01133 if($event->courseid == SITEID && $event->groupid == 0) { 01134 $typesbyday[$eventdaystart]['startglobal'] = true; 01135 // Set event class for global event 01136 $events[$event->id]->class = 'calendar_event_global'; 01137 } 01138 else if($event->courseid != 0 && $event->courseid != SITEID && $event->groupid == 0) { 01139 $typesbyday[$eventdaystart]['startcourse'] = true; 01140 // Set event class for course event 01141 $events[$event->id]->class = 'calendar_event_course'; 01142 } 01143 else if($event->groupid) { 01144 $typesbyday[$eventdaystart]['startgroup'] = true; 01145 // Set event class for group event 01146 $events[$event->id]->class = 'calendar_event_group'; 01147 } 01148 else if($event->userid) { 01149 $typesbyday[$eventdaystart]['startuser'] = true; 01150 // Set event class for user event 01151 $events[$event->id]->class = 'calendar_event_user'; 01152 } 01153 } 01154 01155 if($event->timeduration == 0) { 01156 // Proceed with the next 01157 continue; 01158 } 01159 01160 // The event starts on $month $year or before. So... 01161 $lowerbound = $startdate['mon'] == $month && $startdate['year'] == $year ? intval($startdate['mday']) : 0; 01162 01163 // Also, it ends on $month $year or later... 01164 $upperbound = $enddate['mon'] == $month && $enddate['year'] == $year ? intval($enddate['mday']) : calendar_days_in_month($month, $year); 01165 01166 // Mark all days between $lowerbound and $upperbound (inclusive) as duration 01167 for($i = $lowerbound + 1; $i <= $upperbound; ++$i) { 01168 $durationbyday[$i][] = $event->id; 01169 if($event->courseid == SITEID && $event->groupid == 0) { 01170 $typesbyday[$i]['durationglobal'] = true; 01171 } 01172 else if($event->courseid != 0 && $event->courseid != SITEID && $event->groupid == 0) { 01173 $typesbyday[$i]['durationcourse'] = true; 01174 } 01175 else if($event->groupid) { 01176 $typesbyday[$i]['durationgroup'] = true; 01177 } 01178 else if($event->userid) { 01179 $typesbyday[$i]['durationuser'] = true; 01180 } 01181 } 01182 01183 } 01184 return; 01185 } 01186 01187 function calendar_get_module_cached(&$coursecache, $modulename, $instance) { 01188 $module = get_coursemodule_from_instance($modulename, $instance); 01189 01190 if($module === false) return false; 01191 if(!calendar_get_course_cached($coursecache, $module->course)) { 01192 return false; 01193 } 01194 return $module; 01195 } 01196 01197 function calendar_get_course_cached(&$coursecache, $courseid) { 01198 global $COURSE, $DB; 01199 01200 if (!isset($coursecache[$courseid])) { 01201 if ($courseid == $COURSE->id) { 01202 $coursecache[$courseid] = $COURSE; 01203 } else { 01204 $coursecache[$courseid] = $DB->get_record('course', array('id'=>$courseid)); 01205 } 01206 } 01207 return $coursecache[$courseid]; 01208 } 01209 01218 function calendar_set_filters(array $courseeventsfrom, $ignorefilters = false) { 01219 global $USER, $CFG, $DB; 01220 01221 // For backwards compatability we have to check whether the courses array contains 01222 // just id's in which case we need to load course objects. 01223 $coursestoload = array(); 01224 foreach ($courseeventsfrom as $id => $something) { 01225 if (!is_object($something)) { 01226 $coursestoload[] = $id; 01227 unset($courseeventsfrom[$id]); 01228 } 01229 } 01230 if (!empty($coursestoload)) { 01231 // TODO remove this in 2.2 01232 debugging('calendar_set_filters now preferes an array of course objects with preloaded contexts', DEBUG_DEVELOPER); 01233 $courseeventsfrom = array_merge($courseeventsfrom, $DB->get_records_list('course', 'id', $coursestoload)); 01234 } 01235 01236 $courses = array(); 01237 $user = false; 01238 $group = false; 01239 01240 $isloggedin = isloggedin(); 01241 01242 if ($ignorefilters || calendar_show_event_type(CALENDAR_EVENT_COURSE)) { 01243 $courses = array_keys($courseeventsfrom); 01244 } 01245 if ($ignorefilters || calendar_show_event_type(CALENDAR_EVENT_GLOBAL)) { 01246 $courses[] = SITEID; 01247 } 01248 $courses = array_unique($courses); 01249 sort($courses); 01250 01251 if (!empty($courses) && in_array(SITEID, $courses)) { 01252 // Sort courses for consistent colour highlighting 01253 // Effectively ignoring SITEID as setting as last course id 01254 $key = array_search(SITEID, $courses); 01255 unset($courses[$key]); 01256 $courses[] = SITEID; 01257 } 01258 01259 if ($ignorefilters || ($isloggedin && calendar_show_event_type(CALENDAR_EVENT_USER))) { 01260 $user = $USER->id; 01261 } 01262 01263 if (!empty($courseeventsfrom) && (calendar_show_event_type(CALENDAR_EVENT_GROUP) || $ignorefilters)) { 01264 01265 if (!empty($CFG->calendar_adminseesall) && has_capability('moodle/calendar:manageentries', get_system_context())) { 01266 $group = true; 01267 } else if ($isloggedin) { 01268 $groupids = array(); 01269 01270 // We already have the courses to examine in $courses 01271 // For each course... 01272 foreach ($courseeventsfrom as $courseid => $course) { 01273 // If the user is an editing teacher in there, 01274 if (!empty($USER->groupmember[$course->id])) { 01275 // We've already cached the users groups for this course so we can just use that 01276 $groupids = array_merge($groupids, $USER->groupmember[$course->id]); 01277 } else if (($course->groupmode != NOGROUPS || !$course->groupmodeforce) && has_capability('moodle/calendar:manageentries', get_context_instance(CONTEXT_COURSE, $course->id))) { 01278 // If this course has groups, show events from all of them 01279 $coursegroups = groups_get_user_groups($course->id, $USER->id); 01280 $groupids = array_merge($groupids, $coursegroups['0']); 01281 } 01282 } 01283 if (!empty($groupids)) { 01284 $group = $groupids; 01285 } 01286 } 01287 } 01288 if (empty($courses)) { 01289 $courses = false; 01290 } 01291 01292 return array($courses, $group, $user); 01293 } 01294 01295 function calendar_edit_event_allowed($event) { 01296 global $USER, $DB; 01297 01298 // Must be logged in 01299 if (!isloggedin()) { 01300 return false; 01301 } 01302 01303 // can not be using guest account 01304 if (isguestuser()) { 01305 return false; 01306 } 01307 01308 $sitecontext = get_context_instance(CONTEXT_SYSTEM); 01309 // if user has manageentries at site level, return true 01310 if (has_capability('moodle/calendar:manageentries', $sitecontext)) { 01311 return true; 01312 } 01313 01314 // if groupid is set, it's definitely a group event 01315 if (!empty($event->groupid)) { 01316 // Allow users to add/edit group events if: 01317 // 1) They have manageentries (= entries for whole course) 01318 // 2) They have managegroupentries AND are in the group 01319 $group = $DB->get_record('groups', array('id'=>$event->groupid)); 01320 return $group && ( 01321 has_capability('moodle/calendar:manageentries', $event->context) || 01322 (has_capability('moodle/calendar:managegroupentries', $event->context) 01323 && groups_is_member($event->groupid))); 01324 } else if (!empty($event->courseid)) { 01325 // if groupid is not set, but course is set, 01326 // it's definiely a course event 01327 return has_capability('moodle/calendar:manageentries', $event->context); 01328 } else if (!empty($event->userid) && $event->userid == $USER->id) { 01329 // if course is not set, but userid id set, it's a user event 01330 return (has_capability('moodle/calendar:manageownentries', $event->context)); 01331 } else if (!empty($event->userid)) { 01332 return (has_capability('moodle/calendar:manageentries', $event->context)); 01333 } 01334 return false; 01335 } 01336 01344 function calendar_get_default_courses() { 01345 global $CFG, $DB; 01346 01347 if (!isloggedin()) { 01348 return array(); 01349 } 01350 01351 $courses = array(); 01352 if (!empty($CFG->calendar_adminseesall) && has_capability('moodle/calendar:manageentries', get_context_instance(CONTEXT_SYSTEM))) { 01353 list ($select, $join) = context_instance_preload_sql('c.id', CONTEXT_COURSE, 'ctx'); 01354 $sql = "SELECT c.* $select 01355 FROM {course} c 01356 JOIN {event} e ON e.courseid = c.id 01357 $join"; 01358 $courses = $DB->get_records_sql($sql, null, 0, 20); 01359 foreach ($courses as $course) { 01360 context_instance_preload($course); 01361 } 01362 return $courses; 01363 } 01364 01365 $courses = enrol_get_my_courses(); 01366 01367 return $courses; 01368 } 01369 01370 function calendar_preferences_button(stdClass $course) { 01371 global $OUTPUT; 01372 01373 // Guests have no preferences 01374 if (!isloggedin() || isguestuser()) { 01375 return ''; 01376 } 01377 01378 return $OUTPUT->single_button(new moodle_url('/calendar/preferences.php', array('course' => $course->id)), get_string("preferences", "calendar")); 01379 } 01380 01381 function calendar_format_event_time($event, $now, $linkparams = null, $usecommonwords = true, $showtime=0) { 01382 $startdate = usergetdate($event->timestart); 01383 $enddate = usergetdate($event->timestart + $event->timeduration); 01384 $usermidnightstart = usergetmidnight($event->timestart); 01385 01386 if($event->timeduration) { 01387 // To avoid doing the math if one IF is enough :) 01388 $usermidnightend = usergetmidnight($event->timestart + $event->timeduration); 01389 } 01390 else { 01391 $usermidnightend = $usermidnightstart; 01392 } 01393 01394 if (empty($linkparams) || !is_array($linkparams)) { 01395 $linkparams = array(); 01396 } 01397 $linkparams['view'] = 'day'; 01398 01399 // OK, now to get a meaningful display... 01400 // First of all we have to construct a human-readable date/time representation 01401 01402 if($event->timeduration) { 01403 // It has a duration 01404 if($usermidnightstart == $usermidnightend || 01405 ($event->timestart == $usermidnightstart) && ($event->timeduration == 86400 || $event->timeduration == 86399) || 01406 ($event->timestart + $event->timeduration <= $usermidnightstart + 86400)) { 01407 // But it's all on the same day 01408 $timestart = calendar_time_representation($event->timestart); 01409 $timeend = calendar_time_representation($event->timestart + $event->timeduration); 01410 $time = $timestart.' <strong>»</strong> '.$timeend; 01411 01412 if ($event->timestart == $usermidnightstart && ($event->timeduration == 86400 || $event->timeduration == 86399)) { 01413 $time = get_string('allday', 'calendar'); 01414 } 01415 01416 // Set printable representation 01417 if (!$showtime) { 01418 $day = calendar_day_representation($event->timestart, $now, $usecommonwords); 01419 $url = calendar_get_link_href(new moodle_url(CALENDAR_URL.'view.php', $linkparams), $enddate['mday'], $enddate['mon'], $enddate['year']); 01420 $eventtime = html_writer::link($url, $day).', '.$time; 01421 } else { 01422 $eventtime = $time; 01423 } 01424 } else { 01425 // It spans two or more days 01426 $daystart = calendar_day_representation($event->timestart, $now, $usecommonwords).', '; 01427 if ($showtime == $usermidnightstart) { 01428 $daystart = ''; 01429 } 01430 $timestart = calendar_time_representation($event->timestart); 01431 $dayend = calendar_day_representation($event->timestart + $event->timeduration, $now, $usecommonwords).', '; 01432 if ($showtime == $usermidnightend) { 01433 $dayend = ''; 01434 } 01435 $timeend = calendar_time_representation($event->timestart + $event->timeduration); 01436 01437 // Set printable representation 01438 if ($now >= $usermidnightstart && $now < ($usermidnightstart + 86400)) { 01439 $url = calendar_get_link_href(new moodle_url(CALENDAR_URL.'view.php', $linkparams), $enddate['mday'], $enddate['mon'], $enddate['year']); 01440 $eventtime = $timestart.' <strong>»</strong> '.html_writer::link($url, $dayend).$timeend; 01441 } else { 01442 $url = calendar_get_link_href(new moodle_url(CALENDAR_URL.'view.php', $linkparams), $enddate['mday'], $enddate['mon'], $enddate['year']); 01443 $eventtime = html_writer::link($url, $daystart).$timestart.' <strong>»</strong> '; 01444 01445 $url = calendar_get_link_href(new moodle_url(CALENDAR_URL.'view.php', $linkparams), $startdate['mday'], $startdate['mon'], $startdate['year']); 01446 $eventtime .= html_writer::link($url, $dayend).$timeend; 01447 } 01448 } 01449 } else { 01450 $time = ' '; 01451 01452 // Set printable representation 01453 if (!$showtime) { 01454 $day = calendar_day_representation($event->timestart, $now, $usecommonwords); 01455 $url = calendar_get_link_href(new moodle_url(CALENDAR_URL.'view.php', $linkparams), $startdate['mday'], $startdate['mon'], $startdate['year']); 01456 $eventtime = html_writer::link($url, $day).trim($time); 01457 } else { 01458 $eventtime = $time; 01459 } 01460 } 01461 01462 if($event->timestart + $event->timeduration < $now) { 01463 // It has expired 01464 $eventtime = '<span class="dimmed_text">'.str_replace(' href=', ' class="dimmed" href=', $eventtime).'</span>'; 01465 } 01466 01467 return $eventtime; 01468 } 01469 01470 function calendar_print_month_selector($name, $selected) { 01471 $months = array(); 01472 for ($i=1; $i<=12; $i++) { 01473 $months[$i] = userdate(gmmktime(12, 0, 0, $i, 15, 2000), '%B'); 01474 } 01475 echo html_writer::select($months, $name, $selected, false); 01476 } 01477 01486 function calendar_show_event_type($type, $user = null) { 01487 $default = CALENDAR_EVENT_GLOBAL + CALENDAR_EVENT_COURSE + CALENDAR_EVENT_GROUP + CALENDAR_EVENT_USER; 01488 if (get_user_preferences('calendar_persistflt', 0, $user) === 0) { 01489 global $SESSION; 01490 if (!isset($SESSION->calendarshoweventtype)) { 01491 $SESSION->calendarshoweventtype = $default; 01492 } 01493 return $SESSION->calendarshoweventtype & $type; 01494 } else { 01495 return get_user_preferences('calendar_savedflt', $default, $user) & $type; 01496 } 01497 } 01498 01509 function calendar_set_event_type_display($type, $display = null, $user = null) { 01510 $persist = get_user_preferences('calendar_persistflt', 0, $user); 01511 $default = CALENDAR_EVENT_GLOBAL + CALENDAR_EVENT_COURSE + CALENDAR_EVENT_GROUP + CALENDAR_EVENT_USER; 01512 if ($persist === 0) { 01513 global $SESSION; 01514 if (!isset($SESSION->calendarshoweventtype)) { 01515 $SESSION->calendarshoweventtype = $default; 01516 } 01517 $preference = $SESSION->calendarshoweventtype; 01518 } else { 01519 $preference = get_user_preferences('calendar_savedflt', $default, $user); 01520 } 01521 $current = $preference & $type; 01522 if ($display === null) { 01523 $display = !$current; 01524 } 01525 if ($display && !$current) { 01526 $preference += $type; 01527 } else if (!$display && $current) { 01528 $preference -= $type; 01529 } 01530 if ($persist === 0) { 01531 $SESSION->calendarshoweventtype = $preference; 01532 } else { 01533 if ($preference == $default) { 01534 unset_user_preference('calendar_savedflt', $user); 01535 } else { 01536 set_user_preference('calendar_savedflt', $preference, $user); 01537 } 01538 } 01539 } 01540 01541 function calendar_get_allowed_types(&$allowed, $course = null) { 01542 global $USER, $CFG, $DB; 01543 $allowed = new stdClass(); 01544 $allowed->user = has_capability('moodle/calendar:manageownentries', get_system_context()); 01545 $allowed->groups = false; // This may change just below 01546 $allowed->courses = false; // This may change just below 01547 $allowed->site = has_capability('moodle/calendar:manageentries', get_context_instance(CONTEXT_COURSE, SITEID)); 01548 01549 if (!empty($course)) { 01550 if (!is_object($course)) { 01551 $course = $DB->get_record('course', array('id' => $course), '*', MUST_EXIST); 01552 } 01553 if ($course->id != SITEID) { 01554 $coursecontext = get_context_instance(CONTEXT_COURSE, $course->id); 01555 01556 if (has_capability('moodle/calendar:manageentries', $coursecontext)) { 01557 $allowed->courses = array($course->id => 1); 01558 01559 if ($course->groupmode != NOGROUPS || !$course->groupmodeforce) { 01560 $allowed->groups = groups_get_all_groups($course->id); 01561 } 01562 } else if (has_capability('moodle/calendar:managegroupentries', $coursecontext)) { 01563 if($course->groupmode != NOGROUPS || !$course->groupmodeforce) { 01564 $allowed->groups = groups_get_all_groups($course->id); 01565 } 01566 } 01567 } 01568 } 01569 } 01570 01576 function calendar_user_can_add_event($course) { 01577 if (!isloggedin() || isguestuser()) { 01578 return false; 01579 } 01580 calendar_get_allowed_types($allowed, $course); 01581 return (bool)($allowed->user || $allowed->groups || $allowed->courses || $allowed->site); 01582 } 01583 01590 function calendar_add_event_allowed($event) { 01591 global $USER, $DB; 01592 01593 // can not be using guest account 01594 if (!isloggedin() or isguestuser()) { 01595 return false; 01596 } 01597 01598 $sitecontext = get_context_instance(CONTEXT_SYSTEM); 01599 // if user has manageentries at site level, always return true 01600 if (has_capability('moodle/calendar:manageentries', $sitecontext)) { 01601 return true; 01602 } 01603 01604 switch ($event->eventtype) { 01605 case 'course': 01606 return has_capability('moodle/calendar:manageentries', $event->context); 01607 01608 case 'group': 01609 // Allow users to add/edit group events if: 01610 // 1) They have manageentries (= entries for whole course) 01611 // 2) They have managegroupentries AND are in the group 01612 $group = $DB->get_record('groups', array('id'=>$event->groupid)); 01613 return $group && ( 01614 has_capability('moodle/calendar:manageentries', $event->context) || 01615 (has_capability('moodle/calendar:managegroupentries', $event->context) 01616 && groups_is_member($event->groupid))); 01617 01618 case 'user': 01619 if ($event->userid == $USER->id) { 01620 return (has_capability('moodle/calendar:manageownentries', $event->context)); 01621 } 01622 //there is no 'break;' intentionally 01623 01624 case 'site': 01625 return has_capability('moodle/calendar:manageentries', $event->context); 01626 01627 default: 01628 return has_capability('moodle/calendar:manageentries', $event->context); 01629 } 01630 } 01631 01659 class calendar_event { 01660 01666 protected $properties = null; 01672 protected $_description = null; 01677 protected $editoroptions = array( 01678 'subdirs'=>false, 01679 'forcehttps'=>false, 01680 'maxfiles'=>-1, 01681 'maxbytes'=>null, 01682 'trusttext'=>false); 01687 protected $editorcontext = null; 01688 01696 public function __construct($data=null) { 01697 global $CFG, $USER; 01698 01699 // First convert to object if it is not already (should either be object or assoc array) 01700 if (!is_object($data)) { 01701 $data = (object)$data; 01702 } 01703 01704 $this->editoroptions['maxbytes'] = $CFG->maxbytes; 01705 01706 $data->eventrepeats = 0; 01707 01708 if (empty($data->id)) { 01709 $data->id = null; 01710 } 01711 01712 // Default to a user event 01713 if (empty($data->eventtype)) { 01714 $data->eventtype = 'user'; 01715 } 01716 01717 // Default to the current user 01718 if (empty($data->userid)) { 01719 $data->userid = $USER->id; 01720 } 01721 01722 if (!empty($data->timeduration) && is_array($data->timeduration)) { 01723 $data->timeduration = make_timestamp($data->timeduration['year'], $data->timeduration['month'], $data->timeduration['day'], $data->timeduration['hour'], $data->timeduration['minute']) - $data->timestart; 01724 } 01725 if (!empty($data->description) && is_array($data->description)) { 01726 $data->format = $data->description['format']; 01727 $data->description = $data->description['text']; 01728 } else if (empty($data->description)) { 01729 $data->description = ''; 01730 $data->format = editors_get_preferred_format(); 01731 } 01732 // Ensure form is defaulted correctly 01733 if (empty($data->format)) { 01734 $data->format = editors_get_preferred_format(); 01735 } 01736 01737 if (empty($data->context)) { 01738 $data->context = $this->calculate_context($data); 01739 } 01740 $this->properties = $data; 01741 } 01742 01752 public function __set($key, $value) { 01753 if (method_exists($this, 'set_'.$key)) { 01754 $this->{'set_'.$key}($value); 01755 } 01756 $this->properties->{$key} = $value; 01757 } 01758 01768 public function __get($key) { 01769 if (method_exists($this, 'get_'.$key)) { 01770 return $this->{'get_'.$key}(); 01771 } 01772 if (!isset($this->properties->{$key})) { 01773 throw new coding_exception('Undefined property requested'); 01774 } 01775 return $this->properties->{$key}; 01776 } 01777 01785 public function __isset($key) { 01786 return !empty($this->properties->{$key}); 01787 } 01788 01798 protected function calculate_context(stdClass $data) { 01799 global $USER, $DB; 01800 01801 $context = null; 01802 if (isset($data->courseid) && $data->courseid > 0) { 01803 $context = get_context_instance(CONTEXT_COURSE, $data->courseid); 01804 } else if (isset($data->course) && $data->course > 0) { 01805 $context = get_context_instance(CONTEXT_COURSE, $data->course); 01806 } else if (isset($data->groupid) && $data->groupid > 0) { 01807 $group = $DB->get_record('groups', array('id'=>$data->groupid)); 01808 $context = get_context_instance(CONTEXT_COURSE, $group->courseid); 01809 } else if (isset($data->userid) && $data->userid > 0 && $data->userid == $USER->id) { 01810 $context = get_context_instance(CONTEXT_USER, $data->userid); 01811 } else if (isset($data->userid) && $data->userid > 0 && $data->userid != $USER->id && 01812 isset($data->instance) && $data->instance > 0) { 01813 $cm = get_coursemodule_from_instance($data->modulename, $data->instance, 0, false, MUST_EXIST); 01814 $context = get_context_instance(CONTEXT_COURSE, $cm->course); 01815 } else { 01816 $context = get_context_instance(CONTEXT_USER); 01817 } 01818 01819 return $context; 01820 } 01821 01827 protected function get_editoroptions() { 01828 return $this->editoroptions; 01829 } 01830 01837 protected function get_description() { 01838 global $CFG; 01839 01840 require_once($CFG->libdir . '/filelib.php'); 01841 01842 if ($this->_description === null) { 01843 // Check if we have already resolved the context for this event 01844 if ($this->editorcontext === null) { 01845 // Switch on the event type to decide upon the appropriate context 01846 // to use for this event 01847 $this->editorcontext = $this->properties->context; 01848 if ($this->properties->eventtype != 'user' && $this->properties->eventtype != 'course' 01849 && $this->properties->eventtype != 'site' && $this->properties->eventtype != 'group') { 01850 return clean_text($this->properties->description, $this->properties->format); 01851 } 01852 } 01853 01854 // Work out the item id for the editor, if this is a repeated event then the files will 01855 // be associated with the original 01856 if (!empty($this->properties->repeatid) && $this->properties->repeatid > 0) { 01857 $itemid = $this->properties->repeatid; 01858 } else { 01859 $itemid = $this->properties->id; 01860 } 01861 01862 // Convert file paths in the description so that things display correctly 01863 $this->_description = file_rewrite_pluginfile_urls($this->properties->description, 'pluginfile.php', $this->editorcontext->id, 'calendar', 'event_description', $itemid); 01864 // Clean the text so no nasties get through 01865 $this->_description = clean_text($this->_description, $this->properties->format); 01866 } 01867 // Finally return the description 01868 return $this->_description; 01869 } 01870 01876 public function count_repeats() { 01877 global $DB; 01878 if (!empty($this->properties->repeatid)) { 01879 $this->properties->eventrepeats = $DB->count_records('event', array('repeatid'=>$this->properties->repeatid)); 01880 // We don't want to count ourselves 01881 $this->properties->eventrepeats--; 01882 } 01883 return $this->properties->eventrepeats; 01884 } 01885 01898 public function update($data, $checkcapability=true) { 01899 global $CFG, $DB, $USER; 01900 01901 foreach ($data as $key=>$value) { 01902 $this->properties->$key = $value; 01903 } 01904 01905 $this->properties->timemodified = time(); 01906 $usingeditor = (!empty($this->properties->description) && is_array($this->properties->description)); 01907 01908 if (empty($this->properties->id) || $this->properties->id < 1) { 01909 01910 if ($checkcapability) { 01911 if (!calendar_add_event_allowed($this->properties)) { 01912 print_error('nopermissiontoupdatecalendar'); 01913 } 01914 } 01915 01916 if ($usingeditor) { 01917 switch ($this->properties->eventtype) { 01918 case 'user': 01919 $this->editorcontext = $this->properties->context; 01920 $this->properties->courseid = 0; 01921 $this->properties->groupid = 0; 01922 $this->properties->userid = $USER->id; 01923 break; 01924 case 'site': 01925 $this->editorcontext = $this->properties->context; 01926 $this->properties->courseid = SITEID; 01927 $this->properties->groupid = 0; 01928 $this->properties->userid = $USER->id; 01929 break; 01930 case 'course': 01931 $this->editorcontext = $this->properties->context; 01932 $this->properties->groupid = 0; 01933 $this->properties->userid = $USER->id; 01934 break; 01935 case 'group': 01936 $this->editorcontext = $this->properties->context; 01937 $this->properties->userid = $USER->id; 01938 break; 01939 default: 01940 // Ewww we should NEVER get here, but just incase we do lets 01941 // fail gracefully 01942 $usingeditor = false; 01943 break; 01944 } 01945 01946 $editor = $this->properties->description; 01947 $this->properties->format = $this->properties->description['format']; 01948 $this->properties->description = $this->properties->description['text']; 01949 } 01950 01951 // Insert the event into the database 01952 $this->properties->id = $DB->insert_record('event', $this->properties); 01953 01954 if ($usingeditor) { 01955 $this->properties->description = file_save_draft_area_files( 01956 $editor['itemid'], 01957 $this->editorcontext->id, 01958 'calendar', 01959 'event_description', 01960 $this->properties->id, 01961 $this->editoroptions, 01962 $editor['text'], 01963 $this->editoroptions['forcehttps']); 01964 01965 $DB->set_field('event', 'description', $this->properties->description, array('id'=>$this->properties->id)); 01966 } 01967 01968 // Log the event entry. 01969 add_to_log($this->properties->courseid, 'calendar', 'add', 'event.php?action=edit&id='.$this->properties->id, $this->properties->name); 01970 01971 $repeatedids = array(); 01972 01973 if (!empty($this->properties->repeat)) { 01974 $this->properties->repeatid = $this->properties->id; 01975 $DB->set_field('event', 'repeatid', $this->properties->repeatid, array('id'=>$this->properties->id)); 01976 01977 $eventcopy = clone($this->properties); 01978 unset($eventcopy->id); 01979 01980 for($i = 1; $i < $eventcopy->repeats; $i++) { 01981 01982 $eventcopy->timestart = ($eventcopy->timestart+WEEKSECS) + dst_offset_on($eventcopy->timestart) - dst_offset_on($eventcopy->timestart+WEEKSECS); 01983 01984 // Get the event id for the log record. 01985 $eventcopyid = $DB->insert_record('event', $eventcopy); 01986 01987 // If the context has been set delete all associated files 01988 if ($usingeditor) { 01989 $fs = get_file_storage(); 01990 $files = $fs->get_area_files($this->editorcontext->id, 'calendar', 'event_description', $this->properties->id); 01991 foreach ($files as $file) { 01992 $fs->create_file_from_storedfile(array('itemid'=>$eventcopyid), $file); 01993 } 01994 } 01995 01996 $repeatedids[] = $eventcopyid; 01997 // Log the event entry. 01998 add_to_log($eventcopy->courseid, 'calendar', 'add', 'event.php?action=edit&id='.$eventcopyid, $eventcopy->name); 01999 } 02000 } 02001 02002 // Hook for tracking added events 02003 self::calendar_event_hook('add_event', array($this->properties, $repeatedids)); 02004 return true; 02005 } else { 02006 02007 if ($checkcapability) { 02008 if(!calendar_edit_event_allowed($this->properties)) { 02009 print_error('nopermissiontoupdatecalendar'); 02010 } 02011 } 02012 02013 if ($usingeditor) { 02014 if ($this->editorcontext !== null) { 02015 $this->properties->description = file_save_draft_area_files( 02016 $this->properties->description['itemid'], 02017 $this->editorcontext->id, 02018 'calendar', 02019 'event_description', 02020 $this->properties->id, 02021 $this->editoroptions, 02022 $this->properties->description['text'], 02023 $this->editoroptions['forcehttps']); 02024 } else { 02025 $this->properties->format = $this->properties->description['format']; 02026 $this->properties->description = $this->properties->description['text']; 02027 } 02028 } 02029 02030 $event = $DB->get_record('event', array('id'=>$this->properties->id)); 02031 02032 $updaterepeated = (!empty($this->properties->repeatid) && !empty($this->properties->repeateditall)); 02033 02034 if ($updaterepeated) { 02035 // Update all 02036 if ($this->properties->timestart != $event->timestart) { 02037 $timestartoffset = $this->properties->timestart - $event->timestart; 02038 $sql = "UPDATE {event} 02039 SET name = ?, 02040 description = ?, 02041 timestart = timestart + ?, 02042 timeduration = ?, 02043 timemodified = ? 02044 WHERE repeatid = ?"; 02045 $params = array($this->properties->name, $this->properties->description, $timestartoffset, $this->properties->timeduration, time(), $event->repeatid); 02046 } else { 02047 $sql = "UPDATE {event} SET name = ?, description = ?, timeduration = ?, timemodified = ? WHERE repeatid = ?"; 02048 $params = array($this->properties->name, $this->properties->description, $this->properties->timeduration, time(), $event->repeatid); 02049 } 02050 $DB->execute($sql, $params); 02051 02052 // Log the event update. 02053 add_to_log($this->properties->courseid, 'calendar', 'edit all', 'event.php?action=edit&id='.$this->properties->id, $this->properties->name); 02054 } else { 02055 $DB->update_record('event', $this->properties); 02056 $event = calendar_event::load($this->properties->id); 02057 $this->properties = $event->properties(); 02058 add_to_log($this->properties->courseid, 'calendar', 'edit', 'event.php?action=edit&id='.$this->properties->id, $this->properties->name); 02059 } 02060 02061 // Hook for tracking event updates 02062 self::calendar_event_hook('update_event', array($this->properties, $updaterepeated)); 02063 return true; 02064 } 02065 } 02066 02078 public function delete($deleterepeated=false) { 02079 global $DB; 02080 02081 // If $this->properties->id is not set then something is wrong 02082 if (empty($this->properties->id)) { 02083 debugging('Attempting to delete an event before it has been loaded', DEBUG_DEVELOPER); 02084 return false; 02085 } 02086 02087 // Delete the event 02088 $DB->delete_records('event', array('id'=>$this->properties->id)); 02089 02090 // If the editor context hasn't already been set then set it now 02091 if ($this->editorcontext === null) { 02092 $this->editorcontext = $this->properties->context; 02093 } 02094 02095 // If the context has been set delete all associated files 02096 if ($this->editorcontext !== null) { 02097 $fs = get_file_storage(); 02098 $files = $fs->get_area_files($this->editorcontext->id, 'calendar', 'event_description', $this->properties->id); 02099 foreach ($files as $file) { 02100 $file->delete(); 02101 } 02102 } 02103 02104 // Fire the event deleted hook 02105 self::calendar_event_hook('delete_event', array($this->properties->id, $deleterepeated)); 02106 02107 // If we need to delete repeated events then we will fetch them all and delete one by one 02108 if ($deleterepeated && !empty($this->properties->repeatid) && $this->properties->repeatid > 0) { 02109 // Get all records where the repeatid is the same as the event being removed 02110 $events = $DB->get_records('event', array('repeatid'=>$this->properties->repeatid)); 02111 // For each of the returned events populate a calendar_event object and call delete 02112 // make sure the arg passed is false as we are already deleting all repeats 02113 foreach ($events as $event) { 02114 $event = new calendar_event($event); 02115 $event->delete(false); 02116 } 02117 } 02118 02119 return true; 02120 } 02121 02134 public function properties($prepareeditor=false) { 02135 global $USER, $CFG, $DB; 02136 02137 // First take a copy of the properties. We don't want to actually change the 02138 // properties or we'd forever be converting back and forwards between an 02139 // editor formatted description and not 02140 $properties = clone($this->properties); 02141 // Clean the description here 02142 $properties->description = clean_text($properties->description, $properties->format); 02143 02144 // If set to true we need to prepare the properties for use with an editor 02145 // and prepare the file area 02146 if ($prepareeditor) { 02147 02148 // We may or may not have a property id. If we do then we need to work 02149 // out the context so we can copy the existing files to the draft area 02150 if (!empty($properties->id)) { 02151 02152 if ($properties->eventtype === 'site') { 02153 // Site context 02154 $this->editorcontext = $this->properties->context; 02155 } else if ($properties->eventtype === 'user') { 02156 // User context 02157 $this->editorcontext = $this->properties->context; 02158 } else if ($properties->eventtype === 'group' || $properties->eventtype === 'course') { 02159 // First check the course is valid 02160 $course = $DB->get_record('course', array('id'=>$properties->courseid)); 02161 if (!$course) { 02162 print_error('invalidcourse'); 02163 } 02164 // Course context 02165 $this->editorcontext = $this->properties->context; 02166 // We have a course and are within the course context so we had 02167 // better use the courses max bytes value 02168 $this->editoroptions['maxbytes'] = $course->maxbytes; 02169 } else { 02170 // If we get here we have a custom event type as used by some 02171 // modules. In this case the event will have been added by 02172 // code and we won't need the editor 02173 $this->editoroptions['maxbytes'] = 0; 02174 $this->editoroptions['maxfiles'] = 0; 02175 } 02176 02177 if (empty($this->editorcontext) || empty($this->editorcontext->id)) { 02178 $contextid = false; 02179 } else { 02180 // Get the context id that is what we really want 02181 $contextid = $this->editorcontext->id; 02182 } 02183 } else { 02184 02185 // If we get here then this is a new event in which case we don't need a 02186 // context as there is no existing files to copy to the draft area. 02187 $contextid = null; 02188 } 02189 02190 // If the contextid === false we don't support files so no preparing 02191 // a draft area 02192 if ($contextid !== false) { 02193 // Just encase it has already been submitted 02194 $draftiddescription = file_get_submitted_draft_itemid('description'); 02195 // Prepare the draft area, this copies existing files to the draft area as well 02196 $properties->description = file_prepare_draft_area($draftiddescription, $contextid, 'calendar', 'event_description', $properties->id, $this->editoroptions, $properties->description); 02197 } else { 02198 $draftiddescription = 0; 02199 } 02200 02201 // Structure the description field as the editor requires 02202 $properties->description = array('text'=>$properties->description, 'format'=>$properties->format, 'itemid'=>$draftiddescription); 02203 } 02204 02205 // Finally return the properties 02206 return $properties; 02207 } 02208 02216 public function toggle_visibility($force=null) { 02217 global $CFG, $DB; 02218 02219 // Set visible to the default if it is not already set 02220 if (empty($this->properties->visible)) { 02221 $this->properties->visible = 1; 02222 } 02223 02224 if ($force === true || ($force !== false && $this->properties->visible == 0)) { 02225 // Make this event visible 02226 $this->properties->visible = 1; 02227 // Fire the hook 02228 self::calendar_event_hook('show_event', array($this->properties)); 02229 } else { 02230 // Make this event hidden 02231 $this->properties->visible = 0; 02232 // Fire the hook 02233 self::calendar_event_hook('hide_event', array($this->properties)); 02234 } 02235 02236 // Update the database to reflect this change 02237 return $DB->set_field('event', 'visible', $this->properties->visible, array('id'=>$this->properties->id)); 02238 } 02239 02250 public static function calendar_event_hook($action, array $args) { 02251 global $CFG; 02252 static $extcalendarinc; 02253 if ($extcalendarinc === null) { 02254 if (!empty($CFG->calendar) && file_exists($CFG->dirroot .'/calendar/'. $CFG->calendar .'/lib.php')) { 02255 include_once($CFG->dirroot .'/calendar/'. $CFG->calendar .'/lib.php'); 02256 $extcalendarinc = true; 02257 } else { 02258 $extcalendarinc = false; 02259 } 02260 } 02261 if($extcalendarinc === false) { 02262 return false; 02263 } 02264 $hook = $CFG->calendar .'_'.$action; 02265 if (function_exists($hook)) { 02266 call_user_func_array($hook, $args); 02267 return true; 02268 } 02269 return false; 02270 } 02271 02281 public static function load($param) { 02282 global $DB; 02283 if (is_object($param)) { 02284 $event = new calendar_event($param); 02285 } else { 02286 $event = $DB->get_record('event', array('id'=>(int)$param), '*', MUST_EXIST); 02287 $event = new calendar_event($event); 02288 } 02289 return $event; 02290 } 02291 02298 public static function create($properties) { 02299 if (is_array($properties)) { 02300 $properties = (object)$properties; 02301 } 02302 if (!is_object($properties)) { 02303 throw new coding_exception('When creating an event properties should be either an object or an assoc array'); 02304 } 02305 $event = new calendar_event($properties); 02306 if ($event->update($properties)) { 02307 return $event; 02308 } else { 02309 return false; 02310 } 02311 } 02312 } 02313 02320 class calendar_information { 02325 public $day; 02330 public $month; 02335 public $year; 02336 02341 public $courseid = null; 02346 public $courses = array(); 02351 public $groups = array(); 02356 public $users = array(); 02357 02365 public function __construct($day=0, $month=0, $year=0) { 02366 02367 $date = usergetdate(time()); 02368 02369 if (empty($day)) { 02370 $day = $date['mday']; 02371 } 02372 02373 if (empty($month)) { 02374 $month = $date['mon']; 02375 } 02376 02377 if (empty($year)) { 02378 $year = $date['year']; 02379 } 02380 02381 $this->day = $day; 02382 $this->month = $month; 02383 $this->year = $year; 02384 } 02385 02392 public function prepare_for_view(stdClass $course, array $coursestoload, $ignorefilters = false) { 02393 $this->courseid = $course->id; 02394 $this->course = $course; 02395 list($courses, $group, $user) = calendar_set_filters($coursestoload, $ignorefilters); 02396 $this->courses = $courses; 02397 $this->groups = $group; 02398 $this->users = $user; 02399 } 02400 02408 public function checkdate($defaultonow = true) { 02409 if (!checkdate($this->month, $this->day, $this->year)) { 02410 if ($defaultonow) { 02411 $now = usergetdate(time()); 02412 $this->day = intval($now['mday']); 02413 $this->month = intval($now['mon']); 02414 $this->year = intval($now['year']); 02415 return true; 02416 } else { 02417 throw new moodle_exception('invaliddate'); 02418 } 02419 } 02420 return true; 02421 } 02426 public function timestamp_today() { 02427 return make_timestamp($this->year, $this->month, $this->day); 02428 } 02433 public function timestamp_tomorrow() { 02434 return make_timestamp($this->year, $this->month, $this->day+1); 02435 } 02443 public function add_sidecalendar_blocks(core_calendar_renderer $renderer, $showfilters=false, $view=null) { 02444 if ($showfilters) { 02445 $filters = new block_contents(); 02446 $filters->content = $renderer->fake_block_filters($this->courseid, $this->day, $this->month, $this->year, $view, $this->courses); 02447 $filters->footer = ''; 02448 $filters->title = get_string('eventskey', 'calendar'); 02449 $renderer->add_pretend_calendar_block($filters, BLOCK_POS_RIGHT); 02450 } 02451 $block = new block_contents; 02452 $block->content = $renderer->fake_block_threemonths($this); 02453 $block->footer = ''; 02454 $block->title = get_string('monthlyview', 'calendar'); 02455 $renderer->add_pretend_calendar_block($block, BLOCK_POS_RIGHT); 02456 } 02457 }