[ Index ]

PHP Cross Reference of Moodle 1.9.3 [Build 15-Oct-2008]

title

Body

[close]

/calendar/ -> lib.php (source)

   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 = '&amp;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">&nbsp;</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.'&amp;', $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">&nbsp;</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 = '&amp;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">&nbsp;</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 = '&amp;course='.$event->calendarcourseid;
 554          }
 555          if (empty($event->cmid)) {
 556              $editlink   = CALENDAR_URL.'event.php?action=edit&amp;id='.$event->id.$calendarcourseid;
 557              $deletelink = CALENDAR_URL.'event.php?action=delete&amp;id='.$event->id.$calendarcourseid;
 558          } else {
 559              $editlink   = $CFG->wwwroot.'/course/mod.php?update='.$event->cmid.'&amp;return=true&amp;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 = '&amp;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.'&amp;', 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'].'&amp;', 0, $nextmonth, $nextyear, $accesshide=true);
 733              $prevlink = calendar_get_link_previous(get_string('monthprev', 'access'), 'view.php?id='.$data['id'].'&amp;', 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.'&amp;', 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.'&amp;', 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.'&amp;', 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.'&amp;', 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.'&amp;', $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&amp;', 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&amp;', 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.'&amp;', $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 = '&amp;from='.$type;
 798          break;
 799          case 'course':
 800              if ($id > 0) {
 801                  $getvars = '&amp;from=course&amp;id='.$id;
 802              } else {
 803                  $getvars = '&amp;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 .= '&amp;'.$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>&nbsp;</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 .= '&amp;cal_d='.$d;
 928      if(!empty($m)) $paramstr .= '&amp;cal_m='.$m;
 929      if(!empty($y)) $paramstr .= '&amp;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('&raquo;', '<br />&raquo;', $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>&raquo;</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.'&amp;', $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>&raquo;</strong> '.calendar_get_link_tag($dayend, CALENDAR_URL.'view.php?view=day'.$morehref.'&amp;', $enddate['mday'], $enddate['mon'], $enddate['year']).
1502                  $timeend;
1503              } else {
1504                  $eventtime = calendar_get_link_tag($daystart, CALENDAR_URL.'view.php?view=day'.$morehref.'&amp;', $startdate['mday'], $startdate['mon'], $startdate['year']).
1505                  $timestart.' <strong>&raquo;</strong> '.calendar_get_link_tag($dayend, CALENDAR_URL.'view.php?view=day'.$morehref.'&amp;', $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.'&amp;', $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  ?>