Checking in latest calendar code! Looking great, Jon!
[moodle.git] / calendar / lib.php
CommitLineData
7423f116 1<?php // $Id$
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@uom.gr) //
13// Jon Papaioannou (pj@uom.gr) //
14// //
15// Programming and development: //
16// Jon Papaioannou (pj@uom.gr) //
17// //
18// For bugs, suggestions, etc contact: //
19// Jon Papaioannou (pj@uom.gr) //
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
41define ('SECS_IN_DAY', 86400);
42define ('CALENDAR_UPCOMING_DAYS', 14);
43define ('CALENDAR_UPCOMING_MAXEVENTS', 10);
44define ('CALENDAR_STARTING_WEEKDAY', 1);
45define ('CALENDAR_URL', $CFG->wwwroot.'/calendar/');
46
47function calendar_get_mini($courses, $groups, $users, $cal_month = false, $cal_year = false) {
48 global $CFG, $USER;
49
50 $display = &New object;
51 $display->minwday = get_user_preferences('calendar_startwday', CALENDAR_STARTING_WEEKDAY);
52 $display->maxwday = $display->minwday + 6;
53
54 $content = '';
55
56 if(!empty($cal_month) && !empty($cal_year)) {
57 $thisdate = usergetdate(time()); // Date and time the user sees at his location
58 if($cal_month == $thisdate['mon'] && $cal_year == $thisdate['year']) {
59 // Navigated to this month
60 $date = $thisdate;
61 $display->thismonth = true;
62 }
63 else {
64 // Navigated to other month, let's do a nice trick and save us a lot of work...
65 if(!checkdate($cal_month, 1, $cal_year)) {
66 $date = array('mday' => 1, 'mon' => $thisdate['mon'], 'year' => $thisdate['year']);
67 $display->thismonth = true;
68 }
69 else {
70 $date = array('mday' => 1, 'mon' => $cal_month, 'year' => $cal_year);
71 $display->thismonth = false;
72 }
73 }
74 }
75 else {
76 $date = usergetdate(time()); // Date and time the user sees at his location
77 $display->thismonth = true;
78 }
79
80 // Fill in the variables we 're going to use, nice and tidy
81 list($d, $m, $y) = array($date['mday'], $date['mon'], $date['year']); // This is what we want to display
82 $display->maxdays = calendar_days_in_month($m, $y);
83
84 // We 'll keep these values as GMT here, and offset them when the time comes to query the db
85 $display->tstart = gmmktime(0, 0, 0, $m, 1, $y); // This is GMT
86 $display->tend = gmmktime(23, 59, 59, $m, $display->maxdays, $y); // GMT
87
88 $startwday = gmdate('w', $display->tstart); // $display->tstart is already GMT, so don't use date(): messes with server's TZ
89
90 // Align the starting weekday to fall in our display range
91 // This is simple, not foolproof.
92 if($startwday < $display->minwday) {
93 $startwday += 7;
94 }
95
96 // Get the events matching our criteria. Don't forget to offset the timestamps for the user's TZ!
97 $whereclause = calendar_sql_where(usertime($display->tstart), usertime($display->tend), $users, $groups, $courses);
98
99 if($whereclause === false) {
100 $events = array();
101 }
102 else {
103 $events = get_records_select('event', $whereclause);
104 }
105
106 // We want to have easy access by day, since the display is on a per-day basis.
107 // Arguments passed by reference.
108 calendar_events_by_day($events, $display->tstart, $eventsbyday, $durationbyday, $typesbyday);
109
110 $content .= '<table class="calendarmini"><tr>'; // Begin table. First row: day names
111
112 // Print out the names of the weekdays
113 $days = array('sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat');
114 for($i = $display->minwday; $i <= $display->maxwday; ++$i) {
115 // This uses the % operator to get the correct weekday no matter what shift we have
116 // applied to the $display->minwday : $display->maxwday range from the default 0 : 6
117 $content .= '<td class="calendarheader">'.get_string($days[$i % 7], 'calendar')."</td>\n";
118 }
119
120 $content .= '</tr><tr>'; // End of day names; prepare for day numbers
121
122 // For the table display. $week is the row; $dayweek is the column.
123 $week = 1;
124 $dayweek = $startwday;
125
126 // Paddding (the first week may have blank days in the beginning)
127 for($i = $display->minwday; $i < $startwday; ++$i) {
128 $content .= '<td class="calendardaymini">&nbsp;</td>'."\n";
129 }
130
131 // Now display all the calendar
132 for($day = 1; $day <= $display->maxdays; ++$day, ++$dayweek) {
133 if($dayweek > $display->maxwday) {
134 // We need to change week (table row)
135 $content .= "</tr>\n<tr>";
136 $dayweek = $display->minwday;
137 ++$week;
138 }
139 // Reset vars
140 $class = '';
141 $cell = '';
142 if($dayweek % 7 == 0 || $dayweek % 7 == 6) {
143 // Weekend. This is true no matter what the exact range is.
144 $class = 'cal_day_mini calendarweekend';
145 }
146 else {
147 // Normal working day.
148 $class = 'cal_day_mini';
149 }
150
151 // Special visual fx if an event is defined
152 if(isset($eventsbyday[$day])) {
153 // OverLib popup
154 $popupcontent = '';
155 foreach($eventsbyday[$day] as $eventid) {
156 $popupcontent .= '<div><a href=\\\''.CALENDAR_URL.'view.php?view=event&amp;id='.$events[$eventid]->id.'\\\'>'.addslashes(htmlspecialchars($events[$eventid]->name)).'</a></div>';
157 }
158
159 $popupcaption = get_string('eventsfor', 'calendar', calendar_month_name(intval($date['mon'])).' '.$day);
160 $popup = 'onmouseover="return overlib(\''.$popupcontent.'\', CAPTION, \''.$popupcaption.'\');" onmouseout="return nd();"';
161
162 // Class and cell content
163 if(isset($typesbyday[$day]['startglobal'])) {
164 $class .= ' cal_event_global';
165 }
166 else if(isset($typesbyday[$day]['startcourse'])) {
167 $class .= ' cal_event_course';
168 }
169 else if(isset($typesbyday[$day]['startgroup'])) {
170 $class .= ' cal_event_group';
171 }
172 else if(isset($typesbyday[$day]['startuser'])) {
173 $class .= ' cal_event_user';
174 }
175 if(count($eventsbyday[$day]) == 1) {
176 $title = get_string('oneevent', 'calendar');
177 }
178 else {
179 $title = get_string('manyevents', 'calendar', count($eventsbyday[$day]));
180 }
181 $cell = '<strong><a href="'.calendar_get_link_href(CALENDAR_URL.'view.php?view=day&amp;', $day, $m, $y).'" '.$popup.'">'.$day.'</a></strong>';
182 }
183 else {
184 $cell = $day;
185 }
186
187 if(isset($typesbyday[$day]['durationglobal'])) {
188 $class .= ' cal_duration_global';
189 }
190 else if(isset($typesbyday[$day]['durationcourse'])) {
191 $class .= ' cal_duration_course';
192 }
193 else if(isset($typesbyday[$day]['durationgroup'])) {
194 $class .= ' cal_duration_group';
195 }
196 else if(isset($typesbyday[$day]['durationuser'])) {
197 $class .= ' cal_duration_user';
198 }
199
200 // Special visual fx for today
201 if($display->thismonth && $day == $d) {
202 $class .= ' cal_today';
203 }
204
205 // Just display it
206 $content .= '<td class="'.$class.'">'.$cell."</td>\n";
207 }
208
209 // Paddding (the last week may have blank days at the end)
210 for($i = $dayweek; $i <= $display->maxwday; ++$i) {
211 $content .= '<td class="calendardaymini">&nbsp;</td>';
212 }
213 $content .= '</tr>'; // Last row ends
214
215 $content .= '</table>'; // Tabular display of days ends
216
217 return $content;
218}
219
220function calendar_get_upcoming($courses, $groups, $users, $daysinfuture, $maxevents) {
221
222 global $CFG;
223
224 $display = &New object;
225 $display->range = $daysinfuture; // How many days in the future we 'll look
226 $display->maxevents = $maxevents;
227
228 $output = array();
229
230 // Prepare "course caching", since it may save us a lot of queries
231 $coursecache = array();
232
233 $processed = 0;
234 $now = time(); // We 'll need this later
235 $nowsecs = $now % SECS_IN_DAY; // this too
236 $nowdays = $now - $nowsecs; // and this
237 $date = usergetdate($now); // Nominal datetime
238
239 // Fill in the variables we 're going to use, nice and tidy
240 list($d, $m, $y) = array($date['mday'], $date['mon'], $date['year']);
241 $display->tstart = gmmktime(0, 0, 0, $m, $d, $y);
242
243 // This effectively adds as many days as needed, and the final SECS_IN_DAY - 1
244 // serves to cover the duration until the end of the final day. We could
245 // just do another gmmktime() and an addition, but this is "faster" :)
246 $display->tend = $display->tstart + (SECS_IN_DAY * $display->range) - 1;
247
248 // Get the events matching our criteria
249 $whereclause = calendar_sql_where($display->tstart, $display->tend, $users, $groups, $courses);
250 if($whereclause === false) {
251 $events = false;
252 }
253 else {
254 $whereclause .= ' ORDER BY timestart'; // We want them this way
255 $events = get_records_select('event', $whereclause);
256 }
257
258 if($events !== false) {
259 foreach($events as $event) {
260 if($processed >= $display->maxevents) break;
261
262 // Important note: these timestamps will receive an offset before being converted
263 // to human-readable form in the calendar_get_XXX_representation() functions.
264 $startdate = usergetdate($event->timestart);
265 $enddate = usergetdate($event->timestart + $event->timeduration);
266
267 // It is equally important that we offset them manually to get the correct dates
268 // for the link URL parameters before creating the links!
269 $tzfix = calendar_get_tz_offset();
270 $linkstartdate = usergetdate($event->timestart + $tzfix);
271 $linkenddate = usergetdate($event->timestart + $event->timeduration + $tzfix);
272
273 $starttimesecs = $event->timestart % SECS_IN_DAY; // Seconds after that day's midnight
274 $starttimedays = $event->timestart - $starttimesecs; // Timestamp of midnight of that day
275
276 if($event->timeduration) {
277 // To avoid doing the math if one IF is enough :)
278 $endtimesecs = ($event->timestart + $event->timeduration) % SECS_IN_DAY; // Seconds after that day's midnight
279 $endtimedays = ($event->timestart + $event->timeduration) - $endtimesecs; // Timestamp of midnight of that day
280 }
281 else {
282 $endtimesecs = $starttimesecs;
283 $endtimedays = $starttimedays;
284 }
285
286 // Keep in mind: $starttimeXXX, $endtimeXXX and $nowXXX are all in GMT-based
287 // OK, now to get a meaningful display...
288
289 // First of all we have to construct a human-readable date/time representation
290 if($endtimedays < $nowdays || $endtimedays == $nowdays && $endtimesecs <= $nowsecs) {
291 // It has expired, so we don't care about duration
292 $day = calendar_day_representation($event->timestart + $event->timeduration, $now);
293 $time = calendar_time_representation($event->timestart + $event->timeduration);
294
295 // This var always has the printable time representation
296 $eventtime = '<span class="calendarexpired">'.get_string('expired', 'calendar').' '.
297 calendar_get_link_tag($day, CALENDAR_URL.'view.php?view=day&amp;', $linkenddate['mday'], $linkenddate['mon'], $linkenddate['year']).'</span> ('.$time.')';
298 }
299 else if($event->timeduration) {
300 // It has a duration
301 if($starttimedays == $endtimedays) {
302 // But it's all on one day
303 $day = calendar_day_representation($event->timestart, $now);
304 $timestart = calendar_time_representation($event->timestart);
305 $timeend = calendar_time_representation($event->timestart + $event->timeduration);
306
307 // Set printable representation
308 $eventtime = calendar_get_link_tag($day, CALENDAR_URL.'view.php?view=day&amp;', $linkenddate['mday'], $linkenddate['mon'], $linkenddate['year']).
309 ' ('.$timestart.' - '.$timeend.')';
310 }
311 else {
312 // It spans two or more days
313 $daystart = calendar_day_representation($event->timestart, $now);
314 $dayend = calendar_day_representation($event->timestart + $event->timeduration, $now);
315 $timestart = calendar_time_representation($event->timestart);
316 $timeend = calendar_time_representation($event->timestart + $event->timeduration);
317
318 // Set printable representation
319 $eventtime = calendar_get_link_tag($daystart, CALENDAR_URL.'view.php?view=day&amp;', $linkstartdate['mday'], $linkstartdate['mon'], $linkstartdate['year']).
320 ' ('.$timestart.') - '.calendar_get_link_tag($dayend, CALENDAR_URL.'view.php?view=day&amp;', $linkenddate['mday'], $linkenddate['mon'], $linkenddate['year']).
321 ' ('.$timeend.')';
322 }
323 }
324 else {
325 // It's an "instantaneous" event
326 $day = calendar_day_representation($event->timestart, $now);
327 $time = calendar_time_representation($event->timestart);
328
329 // Set printable representation
330 $eventtime = calendar_get_link_tag($day, CALENDAR_URL.'view.php?view=day&amp;', $linkstartdate['mday'], $linkstartdate['mon'], $linkstartdate['year']).' ('.$time.')';
331 }
332
333 $outkey = count($output);
334
335 // Now we know how to display the time, we have to see how to display the event
336 if(!empty($event->modulename)) {
337
338 // The module name is set. I will assume that it has to be displayed, and
339 // also that it is an automatically-generated event. And of course that the
340 // three fields for get_coursemodule_from_instance are set correctly.
341
342 $module = calendar_get_module_cached($coursecache, $event->modulename, $event->instance, $event->courseid);
343
344 if($module === false) {
345 // This shouldn't have happened. What to do now?
346 // Just ignore it
347 continue;
348 }
349
350 $modulename = get_string('modulename', $event->modulename);
351 $eventtype = get_string($event->eventtype, $event->modulename);
352 $icon = $CFG->modpixpath.'/'.$event->modulename.'/icon.gif';
353 $output[$outkey]->referer = '<a href="'.$CFG->wwwroot.'/mod/'.$event->modulename.'/view.php?id='.$module->id.'">'.$module->name.'</a>';
354 $output[$outkey]->icon = '<img src="'.$icon.'" title="'.$modulename.'" style="vertical-align: middle;" />';
355 $output[$outkey]->name = $event->name;
356 $output[$outkey]->time = $eventtime;
357 $output[$outkey]->description = $event->description;
358 }
359 else if($event->courseid == 1) {
360 // Global event
361 global $site;
362 $output[$outkey]->referer = '<a href="'.$CFG->wwwroot.'">'.$site->shortname.'</a>';
363 $output[$outkey]->icon = '';
364 $output[$outkey]->name = $event->name;
365 $output[$outkey]->time = $eventtime;
366 $output[$outkey]->description = $event->description;
367 }
368 else if($event->courseid > 1) {
369 // Course event
370 calendar_get_course_cached($coursecache, $event->courseid);
371
372 $output[$outkey]->referer = '<a href="'.$CFG->wwwroot.'/course/view.php?id='.$coursecache[$event->courseid]->id.'">'.$coursecache[$event->courseid]->fullname.'</a>';
373 $output[$outkey]->icon = '';
374 $output[$outkey]->name = $event->name;
375 $output[$outkey]->time = $eventtime;
376 $output[$outkey]->description = $event->description;
377 }
378 else if($event->groupid) {
379 // Group event
380 $output[$outkey]->icon = '';
381 $output[$outkey]->name = $event->name;
382 $output[$outkey]->time = $eventtime;
383 $output[$outkey]->description = $event->description;
384 }
385 else if($event->userid) {
386 // User event
387 $output[$outkey]->icon = '';
388 $output[$outkey]->name = $event->name;
389 $output[$outkey]->time = $eventtime;
390 $output[$outkey]->description = $event->description;
391 }
392 ++$processed;
393 }
394 }
395 return $output;
396}
397
398function calendar_sql_where($tstart, $tend, $users, $groups, $courses, $withduration = true) {
399 $whereclause = '';
400 // Quick test
401 if(is_bool($users) && is_bool($groups) && is_bool($courses)) {
402 return false;
403 }
404
405 if(is_array($users) && !empty($users)) {
406 // Events from a number of users
407 if(!empty($whereclause)) $whereclause .= ' OR';
408 $whereclause .= ' userid IN ('.implode(',', $users).') AND courseid = 0 AND groupid = 0';
409 }
410 else if(is_numeric($users)) {
411 // Events from one user
412 if(!empty($whereclause)) $whereclause .= ' OR';
413 $whereclause .= ' userid = '.$users.' AND courseid = 0 AND groupid = 0';
414 }
415 else if($users === true) {
416 // Events from ALL users
417 if(!empty($whereclause)) $whereclause .= ' OR';
418 $whereclause .= ' userid != 0 AND courseid = 0 AND groupid = 0';
419 }
420 if(is_array($groups) && !empty($groups)) {
421 // Events from a number of groups
422 if(!empty($whereclause)) $whereclause .= ' OR';
423 $whereclause .= ' groupid IN ('.implode(',', $groups).')';
424 }
425 else if(is_numeric($groups)) {
426 // Events from one group
427 if(!empty($whereclause)) $whereclause .= ' OR ';
428 $whereclause .= ' groupid = '.$groups;
429 }
430 else if($groups === true) {
431 // Events from ALL groups
432 if(!empty($whereclause)) $whereclause .= ' OR ';
433 $whereclause .= ' groupid != 0';
434 }
435 if(is_array($courses) && !empty($courses)) {
436 // A number of courses
437 if(!empty($whereclause)) $whereclause .= ' OR';
438 $whereclause .= ' groupid = 0 AND courseid IN ('.implode(',', $courses).')';
439 }
440 else if(is_numeric($courses)) {
441 // One course
442 if(!empty($whereclause)) $whereclause .= ' OR';
443 $whereclause .= ' groupid = 0 AND courseid = '.$courses;
444 }
445 else if($courses === true) {
446 // Events from ALL courses
447 if(!empty($whereclause)) $whereclause .= ' OR';
448 $whereclause .= ' groupid = 0 AND courseid != 0';
449 }
450 if($withduration) {
451 $timeclause = 'timestart + timeduration >= '.$tstart.' AND timestart <= '.$tend;
452 }
453 else {
454 $timeclause = 'timestart >= '.$tstart.' AND timestart <= '.$tend;
455 }
456 if(!empty($whereclause)) {
457 // We have additional constraints
458 $whereclause = $timeclause.' AND ('.$whereclause.')';
459 }
460 else {
461 // Just basic time filtering
462 $whereclause = $timeclause;
463 }
464 return $whereclause;
465}
466
467function calendar_top_controls($type, $data) {
468 global $CFG;
469 $content = '';
470 if(!isset($data['d'])) {
471 $data['d'] = 1;
472 }
473 $time = calendar_mktime_check($data['m'], $data['d'], $data['y']);
474 $date = getdate($time);
475 $data['m'] = $date['mon'];
476 $data['y'] = $date['year'];
477 $monthname = calendar_month_name($date['month']);
478
479 switch($type) {
480 case 'frontpage':
481 list($prevmonth, $prevyear) = calendar_sub_month($data['m'], $data['y']);
482 list($nextmonth, $nextyear) = calendar_add_month($data['m'], $data['y']);
483 $nextlink = calendar_get_link_tag('&gt;&gt;', 'index.php?id='.$data['id'].'&amp;', 0, $nextmonth, $nextyear);
484 $prevlink = calendar_get_link_tag('&lt;&lt;', 'index.php?id='.$data['id'].'&amp;', 0, $prevmonth, $prevyear);
485 $content .= '<table class="generaltable" style="width: 100%;"><tr>';
486 $content .= '<td style="text-align: left; width: 12%;">'.$prevlink."</td>\n";
487 $content .= '<td style="text-align: center;"><a href="'.calendar_get_link_href(CALENDAR_URL.'view.php?view=month&amp;', 1, $data['m'], $data['y']).'">'.$monthname.' '.$data['y']."</a></td>\n";
488 $content .= '<td style="text-align: right; width: 12%;">'.$nextlink."</td>\n";
489 $content .= '</tr></table>';
490 break;
491 case 'course':
492 list($prevmonth, $prevyear) = calendar_sub_month($data['m'], $data['y']);
493 list($nextmonth, $nextyear) = calendar_add_month($data['m'], $data['y']);
494 $nextlink = calendar_get_link_tag('&gt;&gt;', 'view.php?id='.$data['id'].'&amp;', 0, $nextmonth, $nextyear);
495 $prevlink = calendar_get_link_tag('&lt;&lt;', 'view.php?id='.$data['id'].'&amp;', 0, $prevmonth, $prevyear);
496 $content .= '<table class="generaltable" style="width: 100%;"><tr>';
497 $content .= '<td style="text-align: left; width: 12%;">'.$prevlink."</td>\n";
498 $content .= '<td style="text-align: center;"><a href="'.calendar_get_link_href(CALENDAR_URL.'view.php?view=month&amp;', 1, $data['m'], $data['y']).'">'.$monthname.' '.$data['y']."</a></td>\n";
499 $content .= '<td style="text-align: right; width: 12%;">'.$nextlink."</td>\n";
500 $content .= '</tr></table>';
501 break;
502 case 'upcoming':
503 // A quick check reveals that this is not used at all
504 /*
505 list($prevmonth, $prevyear) = calendar_sub_month($data['m'], $data['y']);
506 list($nextmonth, $nextyear) = calendar_add_month($data['m'], $data['y']);
507 $prevdate = getdate(calendar_mktime_check($prevmonth, 1, $prevyear));
508 $nextdate = getdate(calendar_mktime_check($nextmonth, 1, $nextyear));
509 $prevname = calendar_month_name($prevdate['month']);
510 $nextname = calendar_month_name($nextdate['month']);
511 $content .= "<tr>\n";
512 $content .= '<td style="text-align: center"><a href="'.calendar_get_link_href(CALENDAR_URL.'view.php?view=month&amp;', 1, $prevmonth, $prevyear).'">'.$prevname.' '.$prevyear."</a></td>\n";
513 $content .= '<td style="text-align: center"><a href="'.calendar_get_link_href(CALENDAR_URL.'view.php?view=month&amp;', 1, $data['m'], $data['y']).'">'.$monthname.' '.$data['y']."</a></td>\n";
514 $content .= '<td style="text-align: center"><a href="'.calendar_get_link_href(CALENDAR_URL.'view.php?view=month&amp;', 1, $nextmonth, $nextyear).'">'.$nextname.' '.$nextyear."</a></td>\n";
515 $content .= "</tr>\n";
516 */
517 break;
518 case 'display':
519 $content .= '<div style="text-align: center;"><a href="'.calendar_get_link_href(CALENDAR_URL.'view.php?view=month&amp;', 1, $data['m'], $data['y']).'">'.$monthname.' '.$data['y']."</a></div>\n";
520 break;
521 case 'month':
522 list($prevmonth, $prevyear) = calendar_sub_month($data['m'], $data['y']);
523 list($nextmonth, $nextyear) = calendar_add_month($data['m'], $data['y']);
524 $prevdate = getdate(calendar_mktime_check($prevmonth, 1, $prevyear));
525 $nextdate = getdate(calendar_mktime_check($nextmonth, 1, $nextyear));
526 $prevname = calendar_month_name($prevdate['month']);
527 $nextname = calendar_month_name($nextdate['month']);
528 $content .= "<table style='width: 100%;'><tr>\n";
529 $content .= '<td style="text-align: left; width: 30%;"><a href="'.calendar_get_link_href('view.php?view=month&amp;', 1, $prevmonth, $prevyear).'">&lt;&lt; '.$prevname.' '.$prevyear."</a></td>\n";
530 $content .= '<td style="text-align: center"><strong>'.$monthname.' '.$data['y']."</strong></td>\n";
531 $content .= '<td style="text-align: right; width: 30%;"><a href="'.calendar_get_link_href('view.php?view=month&amp;', 1, $nextmonth, $nextyear).'">'.$nextname.' '.$nextyear." &gt;&gt;</a></td>\n";
532 $content .= "</tr></table>\n";
533 break;
534 case 'day':
535 $data['d'] = $date['mday']; // Just for convenience
536 $dayname = calendar_wday_name($date['weekday']);
537 $prevdate = getdate($time - SECS_IN_DAY);
538 $nextdate = getdate($time + SECS_IN_DAY);
539 $prevname = calendar_wday_name($prevdate['weekday']);
540 $nextname = calendar_wday_name($nextdate['weekday']);
541 $content .= "<table style='width: 100%;'><tr>\n";
542 $content .= '<td style="text-align: left; width: 20%;"><a href="'.calendar_get_link_href('view.php?view=day&amp;', $prevdate['mday'], $prevdate['mon'], $prevdate['year']).'">&lt;&lt; '.$prevname.' '.$prevyear."</a></td>\n";
543 $content .= '<td style="text-align: center"><strong>'.$dayname.', '.$data['d'].' <a href="'.calendar_get_link_href('view.php?view=month&amp;', 1, $data['m'], $data['y']).'">'.$monthname.' '.$data['y']."</a></strong></td>\n";
544 $content .= '<td style="text-align: right; width: 20%;"><a href="'.calendar_get_link_href('view.php?view=day&amp;', $nextdate['mday'], $nextdate['mon'], $nextdate['year']).'">'.$nextname.' '.$nextyear." &gt;&gt;</a></td>\n";
545 $content .= "</tr></table>\n";
546 break;
547 }
548 return $content;
549}
550
551function calendar_filter_controls($type) {
552 global $CFG, $SESSION;
553
554 $content = '';
555 switch($type) {
556 // A quick check reveals this is not used at all
557 // case 'upcoming':
558 // if(!isset($getvars)) {
559 // global $day, $mon, $yr;
560 // $getvars = 'from=upcoming&amp;cal_d='.$day.'&amp;cal_m='.$mon.'&amp;cal_y='.$yr;
561 // }
562
563 case 'event':
564 if(!isset($getvars)) {
565 global $day, $mon, $yr;
566 $getvars = 'from=event&amp;id='.$_GET['id'];
567 }
568
569 case 'day':
570 if(!isset($getvars)) {
571 global $day, $mon, $yr;
572 $getvars = 'from=day&amp;cal_d='.$day.'&amp;cal_m='.$mon.'&amp;cal_y='.$yr;
573 }
574
575 case 'course':
576 if(!isset($getvars)) {
577 global $course;
578 $getvars = 'from=course&amp;id='.$course->id;
579 }
580
581 $content .= '<table class="cal_controls" style="width: 98%;">';
582
583 $content .= '<tr>';
584 if($SESSION->cal_show_global) {
585 $content .= '<td class="cal_event_global" style="width: 8px;"></td><td><a href="'.CALENDAR_URL.'set.php?var=showglobal&amp;'.$getvars.'" title="'.get_string('tt_hideglobal', 'calendar').'">'.get_string('globalevents', 'calendar').'</a></td>'."\n";
586 }
587 else {
588 $content .= '<td style="width: 8px;"></td><td><a href="'.CALENDAR_URL.'set.php?var=showglobal&amp;'.$getvars.'" title="'.get_string('tt_showglobal', 'calendar').'">'.get_string('globalevents', 'calendar').'</a></td>'."\n";
589 }
590 if($SESSION->cal_show_course) {
591 $content .= '<td class="cal_event_course" style="width: 8px;"></td><td><a href="'.CALENDAR_URL.'set.php?var=showcourses&amp;'.$getvars.'" title="'.get_string('tt_hidecourse', 'calendar').'">'.get_string('courseevents', 'calendar').'</a></td>'."\n";
592 }
593 else {
594 $content .= '<td style="width: 8px;"></td><td><a href="'.CALENDAR_URL.'set.php?var=showcourses&amp;'.$getvars.'" title="'.get_string('tt_showcourse', 'calendar').'">'.get_string('courseevents', 'calendar').'</a></td>'."\n";
595 }
596 $content .= "</tr>\n";
597 $content .= '<tr>';
598 if($SESSION->cal_show_groups) {
599 $content .= '<td class="cal_event_group" style="width: 8px;"></td><td><a href="'.CALENDAR_URL.'set.php?var=showgroups&amp;'.$getvars.'" title="'.get_string('tt_hidegroups', 'calendar').'">'.get_string('groupevents', 'calendar').'</a></td>'."\n";
600 }
601 else {
602 $content .= '<td style="width: 8px;"></td><td><a href="'.CALENDAR_URL.'set.php?var=showgroups&amp;'.$getvars.'" title="'.get_string('clickshowgroups', 'calendar').'">'.get_string('groupevents', 'calendar').'</a></td>'."\n";
603 }
604 if($SESSION->cal_show_user) {
605 $content .= '<td class="cal_event_user" style="width: 8px;"></td><td><a href="'.CALENDAR_URL.'set.php?var=showuser&amp;'.$getvars.'" title="'.get_string('tt_hideuser', 'calendar').'">'.get_string('userevents', 'calendar').'</a></td>'."\n";
606 }
607 else {
608 $content .= '<td style="width: 8px;"></td><td><a href="'.CALENDAR_URL.'set.php?var=showuser&amp;'.$getvars.'" title="'.get_string('clickshowuser', 'calendar').'">'.get_string('userevents', 'calendar').'</a></td>'."\n";
609 }
610 $content .= "</tr>\n</table>\n";
611 break;
612 }
613 return $content;
614}
615
616function calendar_day_representation($tstamp, $now = false, $usecommonwords = true) {
617
618 $days = array('sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday');
619 if($now === false) {
620 $now = time();
621 }
622
623 // To have it in one place, if a change is needed
624 $formal = get_string($days[userdate($tstamp, '%w')], 'calendar') . userdate($tstamp,' %d %b');
625
626 // Reverse TZ compensation: make GMT stamps correspond to user's TZ
627 $tzfix = calendar_get_tz_offset();
628 $tstamp += $tzfix;
629 $now += $tzfix;
630
631 $eventdays = intval($tstamp / SECS_IN_DAY);
632 $nowdays = intval($now / SECS_IN_DAY);
633
634 if($usecommonwords == false) {
635 // We don't want words, just a date
636 return $formal;
637 }
638 else if($eventdays == $nowdays) {
639 // Today
640 return get_string('today', 'calendar');
641 }
642 else if($eventdays == $nowdays - 1) {
643 // Yesterday
644 return get_string('yesterday', 'calendar');
645 }
646 else if($eventdays == $nowdays + 1) {
647 // Tomorrow
648 return get_string('tomorrow', 'calendar');
649 }
650 else {
651 return $formal;
652 }
653}
654
655function calendar_time_representation($time) {
656 return userdate($time, '%H:%M');
657}
658
659function calendar_get_link_href($linkbase, $d, $m, $y) {
660 if(empty($linkbase)) return '';
661 $paramstr = '';
662 if(!empty($d)) $paramstr .= '&amp;cal_d='.$d;
663 if(!empty($m)) $paramstr .= '&amp;cal_m='.$m;
664 if(!empty($y)) $paramstr .= '&amp;cal_y='.$y;
665 if(!empty($paramstr)) $paramstr = substr($paramstr, 5);
666 return $linkbase.$paramstr;
667}
668
669function calendar_get_link_tag($text, $linkbase, $d, $m, $y) {
670 $href = calendar_get_link_href($linkbase, $d, $m, $y);
671 if(empty($href)) return $text;
672 return '<a href="'.$href.'">'.$text.'</a>';
673}
674
675function calendar_gmmktime_check($m, $d, $y, $default = false) {
676 if($default === false) $default = time();
677 if(!checkdate($m, $d, $y)) {
678 return $default;
679 }
680 else {
681 return gmmktime(0, 0, 0, $m, $d, $y);
682 }
683}
684
685function calendar_mktime_check($m, $d, $y, $default = false) {
686 if($default === false) $default = time();
687 if(!checkdate($m, $d, $y)) {
688 return $default;
689 }
690 else {
691 return mktime(0, 0, 0, $m, $d, $y);
692 }
693}
694
695function calendar_month_name($month) {
696 if(is_int($month)) {
697 // 1 ... 12 integer converted to month name
698 $months = array('january', 'february', 'march', 'april', 'may', 'june', 'july', 'august', 'september', 'october', 'november', 'december');
699 return get_string($months[$month - 1], 'calendar');
700 }
701 else {
702 return get_string(strtolower($month), 'calendar');
703 }
704}
705
706function calendar_wday_name($englishname) {
707 return get_string(strtolower($englishname), 'calendar');
708}
709
710function calendar_days_in_month($month, $year) {
711 return date('t', mktime(0, 0, 0, $month, 1, $year));
712}
713
714function calendar_get_sideblock_upcoming($courses, $groups, $users, $daysinfuture, $maxevents) {
715 $events = calendar_get_upcoming($courses, $groups, $users, $daysinfuture, $maxevents);
716
717 $content = '';
718 $lines = count($events);
719 if(!$lines) return $content;
720
721 for($i = 0; $i < $lines; ++$i) {
722 $content .= '<div class="cal_event">'.$events[$i]->icon.' ';
723 $content .= $events[$i]->name.':';
724 if(!empty($events[$i]->icon)) {
725 // That's an activity event, so let's provide the hyperlink
726 $content .= ' '.$events[$i]->referer;
727 }
728 $content .= '</div><div class="cal_event_date">'.$events[$i]->time.'</div>';
729 if($i < $lines - 1) $content .= '<hr />';
730 }
731
732 return $content;
733
734}
735
736function calendar_add_month($month, $year) {
737 if($month == 12) {
738 return array(1, $year + 1);
739 }
740 else {
741 return array($month + 1, $year);
742 }
743}
744
745function calendar_sub_month($month, $year) {
746 if($month == 1) {
747 return array(12, $year - 1);
748 }
749 else {
750 return array($month - 1, $year);
751 }
752}
753
754function calendar_events_by_day($events, $starttime, &$eventsbyday, &$durationbyday, &$typesbyday) {
755 $eventsbyday = array();
756 $typesbyday = array();
757 $durationbyday = array();
758
759 if($events === false) {
760 return;
761 }
762
763 // Reverse TZ compensation: make GMT stamps (from event table) correspond to user's TZ
764 $tzfix = calendar_get_tz_offset();
765
766 foreach($events as $event) {
767 $eventdaystart = 1 + floor(($event->timestart + $tzfix - $starttime) / SECS_IN_DAY);
768 $eventdayend = 1 + floor(($event->timestart + $event->timeduration + $tzfix - $starttime) / SECS_IN_DAY);
769
770 // Give the event to its day
771 $eventsbyday[$eventdaystart][] = $event->id;
772
773 // Mark the day as having such an event
774 if($event->courseid == 1 && $event->groupid == 0) {
775 $typesbyday[$eventdaystart]['startglobal'] = true;
776 }
777 else if($event->courseid > 1 && $event->groupid == 0) {
778 $typesbyday[$eventdaystart]['startcourse'] = true;
779 }
780 else if($event->groupid) {
781 $typesbyday[$eventdaystart]['startgroup'] = true;
782 }
783 else if($event->userid) {
784 $typesbyday[$eventdaystart]['startuser'] = true;
785 }
786
787 // Mark all days up to and including ending day as duration
788 if($eventdaystart < $eventdayend) {
789
790 // Normally this should be
791
792 // $bound = min($eventdayend, $display->maxdays);
793 // for($i = $eventdaystart + 1; $i <= $bound; ++$i) {
794
795 // So that we don't go on marking days after the end of
796 // the month if the event continues. However, this code
797 // has moved and now we don't have access to $display->maxdays.
798 // In order to save the overhead of recomputing it, we just
799 // use this "dumb" approach. Anyway, the function that called
800 // us already knows up to what day it should display.
801
802 for($i = $eventdaystart + 1; $i <= $eventdayend; ++$i) {
803 $durationbyday[$i][] = $event->id;
804 if($event->courseid == 1 && $event->groupid == 0) {
805 $typesbyday[$i]['durationglobal'] = true;
806 }
807 else if($event->courseid > 1 && $event->groupid == 0) {
808 $typesbyday[$i]['durationcourse'] = true;
809 }
810 else if($event->groupid) {
811 $typesbyday[$i]['durationgroup'] = true;
812 }
813 else if($event->userid) {
814 $typesbyday[$i]['durationuser'] = true;
815 }
816 }
817 }
818 }
819 return;
820}
821
822function calendar_get_module_cached(&$coursecache, $modulename, $instance, $courseid) {
823 $module = get_coursemodule_from_instance($modulename, $instance, $courseid);
824
825 if($module === false) return false;
826 if(!calendar_get_course_cached($coursecache, $courseid)) {
827 return false;
828 }
829 return $module;
830}
831
832function calendar_get_course_cached(&$coursecache, $courseid) {
833 if(!isset($coursecache[$courseid])) {
834 $coursecache[$courseid] = get_record('course', 'id', $courseid);
835 }
836 return $coursecache[$courseid];
837}
838
839function calendar_session_vars() {
840 global $SESSION, $USER;
841
842 if(!isset($SESSION->cal_course_referer)) {
843 $SESSION->cal_course_referer = 0;
844 }
845 if(!isset($SESSION->cal_show_global)) {
846 $SESSION->cal_show_global = true;
847 }
848 if(!isset($SESSION->cal_show_groups)) {
849 $SESSION->cal_show_groups = true;
850 }
851 if(!isset($SESSION->cal_show_course)) {
852 $SESSION->cal_show_course = true;
853 }
854 if(!isset($SESSION->cal_show_user)) {
855 $SESSION->cal_show_user = $USER->id;
856 }
857}
858
859function calendar_overlib_html() {
860 global $CFG;
861
862 $html = '';
863 $html .= '<div id="overDiv" style="position: absolute; visibility: hidden; z-index:1000;"></div>';
864 $html .= '<script type="text/javascript" src="'.CALENDAR_URL.'overlib.cfg.php"></script>';
865
866 return $html;
867}
868
869function calendar_print_side_blocks($forcecourse = NULL) {
870 // WARNING: Keep in mind that using $forcecourse will override the $SESSION
871 // filters, and thus not respect the user's filter settings. Use it sparingly.
872
873 global $USER, $CFG, $SESSION, $course;
874 optional_variable($_GET['cal_m']);
875 optional_variable($_GET['cal_y']);
876
877 calendar_session_vars();
878
879 if(is_int($forcecourse)) {
880 // Overrides the course to use
881 $courseshown = $forcecourse;
882 $defaultcourses = array($courseshown => 1);
883 }
884 else if($forcecourse === false) {
885 // Overrides: use no course at all
886 $courseshown = false;
887 $defaultcourses = NULL;
888 }
889 else {
890 // Normal behavior: use displayed course, or front page if no course
891 $courseshown = ($course === NULL) ? 1 : $course->id;
892 $defaultcourses = array($courseshown => 1);
893 }
894
895 // I 'm not really sure if this belongs here...
896 calendar_set_referring_course($courseshown);
897
898 if($courseshown !== false && is_int($SESSION->cal_show_course) && $SESSION->cal_show_course != $courseshown) {
899 // There is a filter in action that shows events from a course other than the current
900 // Obviously we have to cut it out
901 $SESSION->cal_show_course = true;
902 }
903 else if($courseshown !== false && is_array($SESSION->cal_show_course) && !in_array($courseshown, $SESSION->cal_show_course)) {
904 // Same as above, only there are many courses being shown. Unfortunately, not this one.
905 $SESSION->cal_show_course = true;
906 }
907
908 // Be VERY careful with the format for default courses arguments!
909 // Correct formatting is [courseid] => 1 to be concise with moodlelib.php functions.
910
911 calendar_set_filters($courses, $group, $user, $defaultcourses, $defaultcourses);
912
913 if(get_user_preferences('calendar_showmonth', true)) {
914 if($courseshown == 1) {
915 // For the front page
916 echo calendar_overlib_html();
917 print_side_block_start(get_string('calendar', 'calendar'));
918 echo calendar_top_controls('frontpage', array('m' => $_GET['cal_m'], 'y' => $_GET['cal_y']));
919 echo calendar_get_mini($courses, $group, $user, $_GET['cal_m'], $_GET['cal_y']);
920 // No filters for now
921 print_side_block_end();
922 }
923 else {
924 // For any other course
925 echo calendar_overlib_html();
926 print_side_block_start(get_string('calendar', 'calendar'));
927 echo calendar_top_controls('course', array('id' => $courseshown, 'm' => $_GET['cal_m'], 'y' => $_GET['cal_y']));
928 echo calendar_get_mini($courses, $group, $user, $_GET['cal_m'], $_GET['cal_y']);
929 echo calendar_filter_controls('course');
930 print_side_block_end();
931 }
932 }
933 if(get_user_preferences('calendar_showupcoming', true)) {
934 $block = calendar_get_sideblock_upcoming($courses, $group, $user, get_user_preferences('calendar_lookahead', CALENDAR_UPCOMING_DAYS), get_user_preferences('calendar_maxevents', CALENDAR_UPCOMING_MAXEVENTS));
935 if(!empty($block)) {
936 print_side_block_start(get_string('upcomingevents', 'calendar'));
937 echo $block;
938 print_side_block_end();
939 }
940 }
941}
942
943function calendar_set_referring_course($courseid) {
944 global $SESSION;
945 $SESSION->cal_course_referer = intval($courseid);
946}
947
948function calendar_set_filters(&$courses, &$group, &$user, $defaultcourses = NULL, $groupcourses = NULL) {
949 global $SESSION, $USER;
950
951 // WARNING: When calling this function, be VERY careful with the format for default courses arguments!
952 // Correct formatting is [courseid] => 1 to be concise with moodlelib.php functions.
953
954 $showcourse = (
955 (is_int($SESSION->cal_show_course) && $SESSION->cal_show_course) ||
956 (is_array($SESSION->cal_show_course) && count($SESSION->cal_show_course)) ||
957 ($SESSION->cal_show_course === true)
958 );
959 if($defaultcourses === NULL) {
960 $defaultcourses = array();
961 }
962 if($groupcourses === NULL) {
963 $groupcourses = array();
964 }
965
966 if(is_array($defaultcourses) && array_key_exists(1, $defaultcourses)) {
967 // This should never happen, so let's be sure just in case
968 $defaultcourses = array_diff_assoc($defaultcourses, array(1 => 1));
969 }
970
971 if($showcourse && $SESSION->cal_show_global) {
972 if(is_int($SESSION->cal_show_course)) {
973 $courses = array(1, $SESSION->cal_show_course);
974 }
975 else if(is_array($SESSION->cal_show_course)) {
976 $courses = array(1) + $SESSION->cal_show_course;
977
978 }
979 else {
980 $courses = array_keys($defaultcourses);
981 $courses[] = 1;
982 }
983 }
984 else if($showcourse) {
985 if(is_int($SESSION->cal_show_course)) {
986 $courses = array($SESSION->cal_show_course);
987 }
988 else if(is_array($SESSION->cal_show_course)) {
989 $courses = $SESSION->cal_show_course;
990 }
991 else {
992 $courses = array_keys($defaultcourses);
993 if(empty($courses)) $courses = false;
994 }
995 }
996 else if($SESSION->cal_show_global) {
997 $courses = array(1);
998 }
999 else {
1000 $courses = false;
1001 }
1002
1003 if($SESSION->cal_show_user) {
1004 $user = $SESSION->cal_show_user;
1005 }
1006 else {
1007 $user = false;
1008 }
1009 if($SESSION->cal_show_groups) {
1010 if(is_int($groupcourses)) {
1011 // One course, whatever group the user is in that course
1012 if(mygroupid($groupcourses)) {
1013 $group = mygroupid($groupcourses);
1014 }
1015 else {
1016 $group = false;
1017 }
1018 }
1019 else if(is_array($groupcourses)) {
1020 // Many courses, we want all of them
1021 if(empty($USER->groupmember)) {
1022 $group = false;
1023 }
1024 else {
1025 $grouparray = array();
1026 foreach ($USER->groupmember as $courseid => $mgroupid) {
1027 if (in_array($courseid, $groupcourses)) {
1028 $grouparray[] = $mgroupid;
1029 }
1030 }
1031 if(!empty($grouparray)) {
1032 // We got some groups at the least
1033 $group = $grouparray;
1034 }
1035 else {
1036 // No groups in these courses
1037 $group = false;
1038 }
1039 }
1040 }
1041 else if(is_bool($groupcourses)) {
1042 // Override
1043 $group = $groupcourses;
1044 }
1045 else {
1046 // Sanity
1047 $group = false;
1048 }
1049 }
1050 else {
1051 $group = false;
1052 }
1053}
1054
1055function calendar_edit_event_allowed($event) {
1056 global $USER;
1057
1058 if(isadmin($USER->id)) return true; // Admins are allowed anything
1059
1060 if($event->courseid > 1) {
1061 // Course event, only editing teachers may... edit :P
1062 if(isteacheredit($event->courseid)) {
1063 return true;
1064 }
1065 }
1066 else if($event->courseid == 0 && $event->groupid != 0) {
1067 // Group event
1068 $group = get_record('groups', 'id', $event->groupid);
1069 if($group === false) return false;
1070 if(isteacheredit($group->courseid)) {
1071 return true;
1072 }
1073 }
1074 else if($event->courseid == 0 && $event->groupid == 0 && $event->userid == $USER->id) {
1075 // User event, owned by this user
1076 return true;
1077 }
1078
1079 return false;
1080}
1081
1082function calendar_get_default_courses() {
1083 global $USER;
1084
1085 $courses = array();
1086 if(is_array($USER->student)) {
1087 $courses = $USER->student + $courses;
1088 }
1089 if(is_array($USER->teacher)) {
1090 $courses = $USER->teacher + $courses;
1091 }
1092 return $courses;
1093}
1094
1095// NOTE: This function is obsolete. But let's not kill it just yet.
1096/*
1097function calendar_print_preferences_menu() {
1098
1099 // Guests have no preferences
1100 if(isguest()) {
1101 return;
1102 }
1103
1104 print_side_block_start(get_string('preferences', 'calendar'), '', 'mycalendar');
1105 echo '<div style="text-align: center;"><table style="margin: auto; text-align: center;"><tr>';
1106 $prefs = array(
1107 'startwday' => get_string('pref_startwday', 'calendar'),
1108 'maxevents' => get_string('pref_maxevents', 'calendar'),
1109 'lookahead' => get_string('pref_lookahead', 'calendar'),
1110 );
1111 foreach($prefs as $name => $description) {
1112 echo '<td style="padding: 0px 20px;"><a href="preferences.php?edit='.$name.'"><img src="images/'.$name.'.gif" alt="'.$description.'" title="'.$description.'" /><div style="font-size: 0.6em;">'.$description.'</div></a></td>';
1113 }
1114 echo '</tr></table></div>';
1115 print_side_block_end();
1116}
1117*/
1118
1119function calendar_get_tz_offset() {
1120 global $USER, $CFG;
1121 static $tzfix;
1122
1123 // Caching
1124 if(isset($tzfix)) {
1125 return $tzfix;
1126 }
1127
1128 if(empty($USER)) {
1129 // Don't forget that there are users which have NOT logged in, even as guests
1130 $timezone = $CFG->timezone;
1131 }
1132 else {
1133 // If, on the other hand, we do have a user...
1134 $timezone = $USER->timezone;
1135 if(abs($timezone > 13)) {
1136 // But if the user has specified 'server default' time,
1137 // don't get the server's; get the Moodle $CFG setting
1138 // (Martin's help text on site cfg implies this)
1139 $timezone = $CFG->timezone;
1140 }
1141 }
1142
1143 if(abs($timezone) <= 13) {
1144 $tzfix = $timezone * 3600;
1145 }
1146 else {
1147 $tzfix = date('Z', $starttime);
1148 }
1149
1150 return $tzfix;
1151}
1152
1153function calendar_preferences_array() {
1154 return array(
1155 'startwday' => get_string('pref_startwday', 'calendar'),
1156 'maxevents' => get_string('pref_maxevents', 'calendar'),
1157 'lookahead' => get_string('pref_lookahead', 'calendar'),
1158 );
1159}
1160
1161function calendar_get_preferences_menu() {
1162
1163 // Guests have no preferences
1164 if(isguest()) {
1165 return '';
1166 }
1167
1168 $str = '<form style="display: inline;" name="cal_pref_form" method="get" action="preferences.php">';
1169 $str .= '<select id="cal_pref" name="edit" onchange="self.location=\'preferences.php?edit=\'+document.cal_pref_form.cal_pref.options[document.cal_pref_form.cal_pref.options.selectedIndex].value; ">';
1170 $str .= '<option value="" selected="selected">'.get_string('preferences', 'calendar').'...</option>';
1171 $prefs = calendar_preferences_array();
1172
1173 foreach($prefs as $name => $description) {
1174 $str .= '<option value="'.$name.'">'.$description.'</option>';
1175 }
1176 $str .= '</select>';
1177 $str .= '<noscript id="cal_noscript" style="display: inline;"> <input type="submit" value=" &gt; " /></noscript>';
1178 $str .= '<script type="text/javascript">document.getElementById("cal_noscript").style.display = "none";</script>';
1179 $str .= '</form>';
1180
1181 return $str;
1182}
1183
1184if(!function_exists('array_diff_assoc')) {
1185 // PHP < 4.3.0
1186 function array_diff_assoc($source, $diff) {
1187 $res = $source;
1188 foreach ($diff as $key=>$data) {
1189 unset($res[$key]);
1190 }
1191 return $res;
1192 }
1193}
1194
1195?>