1<?php
2# =================================================================================================
3# gCalendar "gcal_show.php" - responsible for displaying the calendar-data
4# =================================================================================================
5
6
7/**
8 * show the data of the gCal_data-array for a given date-range
9 *
10 * @author Frank Hinkel <frank@hi-sys.de>
11 *
12 * @param  array  options      options from the command "<gcal ....>"
13 * @param  array  pages        the columns to show the data for
14 * @param  string start_date
15 * @param  string end_date
16 *
17 */
18function show_gCal_page(&$options,&$pages,$start_date,$end_date) {
19  global $lang;
20  global $conf;
21  global $ID;
22
23  $act_date = getdate($start_date);
24
25  # calculate some variables depending on parameter mode
26  switch(strtolower($options['mode'])) {
27     case 'day'   : $header = $header = $lang['gCal_day'];
28                    $day_shift=1;
29                    if(isset($options['days'])) $day_shift=$options['days'];
30                    $month_shift=0;
31                    $date_format=$lang['gCal_dv_day'];
32                    break;
33
34     case 'week'  : $header = $header = $lang["gCal_weekofyear"].date('W',$start_date)."/".$act_date["year"];
35                    $day_shift=7;
36                    $month_shift=0;
37                    $date_format=$lang['gCal_wv_day'];
38                    break;
39
40     case 'month' : $header = $lang['gCal_month_'.$act_date["mon"]]." ".$act_date["year"];
41                    $lang['gCal_month_'.$act_date["mon"]]." ".$act_date["year"];
42                    $day_shift=0;
43                    $month_shift=1;
44                    $date_format=$lang['gCal_mv_day'];
45                    break;
46
47     default      : return;
48  }
49
50  # generate link to current_date. preserve mbdo-mode
51  $curr_link_options = array();
52  if(isset($_REQUEST['mbdo'])) $curr_link_options['mbdo']=$_REQUEST['mbdo'];
53  $curr_link = wl($ID,$curr_link_options);
54
55  # generate link to previus page
56  $prev_link_options = $curr_link_options;
57  $prev_link_options["day"  ] = $act_date["mday"] - $day_shift;
58  $prev_link_options["month"] = $act_date["mon"]  - $month_shift;
59  $prev_link_options["year" ] = $act_date["year"];
60  $prev_link = wl( $ID, $prev_link_options );
61
62  # generate link to next page
63  $next_link_options = $curr_link_options;
64  $next_link_options["day"  ] = $act_date["mday"] + $day_shift;
65  $next_link_options["month"] = $act_date["mon"]  + $month_shift;
66  $next_link_options["year" ] = $act_date["year"];
67  $next_link = wl( $ID, $next_link_options );
68
69  # check for fontsize
70  if(isset($options['fontsize']))$fontsize = " style='font-size:".$options['fontsize'].";'";
71
72  # show month/week-table ----------------------------------------------------------------------------
73  echo "</p><table class='gCal_table' $fontsize>\n";
74  show_column_groups($pages,$options);
75
76  if(!isset($options['nonav']) && !isset($options['noheader'])) {
77      echo "<tr><th colspan='".(count($pages)+1)."'>"; # the header span over all columns
78
79      # show navigation-table @todo : add better navigation
80      echo "<table class='gCal_naviTable'><tr><td class='gCal_header gCal_link_prev'>";
81      echo "<a href='$prev_link'>&lt;&lt;&lt;</a>";
82      echo "</td><td class='gCal_header'><a href='$curr_link'>$header</a>";
83      echo "<br/><span class='gCal_currentDate'>".date($conf['dformat'])."</span>";
84      echo "</td><td class='gCal_header gCal_link_next'>";
85      echo "<a href='$next_link'>&gt;&gt;&gt;</a>";
86      echo "</td></tr></table>";
87
88      echo "</th></tr>\n";
89
90      # show table-header with clickable titles------------------------------------------------------
91  }
92
93  if(!isset($options['nohead']) && !isset($options['noheader'])) {
94      show_column_headers($pages,$options);
95  }
96
97  # create table-body -----------------------------------------------------------------------------
98
99  for($i=$start_date ; $i <= $end_date ; $i = strtotime ( "+1 days", $i ) ) {
100    show_day($options,$i,$pages,$date_format);
101  }
102
103
104  # create table-footer with clickable titles------------------------------------------------------
105
106  if($options['mode']!='day' && !isset($options['nofoot']) && !isset($options['noheader'])) {
107    show_column_headers($pages,$options);
108  }
109
110  # end of table ----------------------------------------------------------------------------------
111
112  echo "</table><p>\n";
113}
114
115
116/**
117 * Show the data of the given day.
118 *
119 * @author Frank Hinkel <frank@hi-sys.de>
120 *
121 * @param  array  options      options from the command "<gcal ....>"
122 * @param  day                 the day to be displayed
123 * @param  array pages         the columns to show the data for
124 * @param  string date_format  to format the date in the first column
125 *
126 */
127function show_day(&$options,$day,&$pages,$date_format) {
128  global $gCal_data; # this array contains all the date-entries
129  global $lang;
130  global $ID;
131
132  $date = date("Ymd", $day);
133  if(isset($options['dayshift'])) $dayshift=$options['dayshift']*60*60*24;else $dayshift=0;
134
135  $weekday = $lang['gCal_weekday_'.date("w", $day)];
136  $wd_class = "gCal_wd_".date("w", $day)." ";
137
138  # marker for today. dayshift is only used for test-purposes
139  if(isset($options['dayshift'])) $dayshift=$options['dayshift']*60*60*24;else $dayshift=0;
140  if(date("Y.m.d",$day)==date("Y.m.d",time()+$dayshift)) {
141    $todaystyle="gCal_today";
142    $todayframe="gCal_todayFrame";
143  }else{
144    $todaystyle="";
145    $todayframe="";
146  }
147
148  $date_cell  = "<span class='gCal_mv_day'>".date($date_format, $day)."</span>";
149  $date_cell .= "<br/><span class='gCal_mv_weekday'>".$weekday."</span>";
150
151  # when in compact-mode dont show empty dates
152  if((date("Y.m.d",$day)!=date("Y.m.d",time()+$dayshift)) &&
153     (isset($options['compact']) || isset($options['dropempty'])) ) {
154    $no_entry=true;
155    foreach($pages as $page_key=>$page) {
156      if(isset($gCal_data[$page_key][$date])) {
157        $no_entry=false;
158        break;
159      }
160    }
161    if($no_entry) {
162      # if option "dropempty" is given drop the complete empty line.
163      if(isset($options['dropempty'])) return;
164      # otherwise omit shrink the line
165      $date_cell  = "<span class='gCal_mv_day'>".date($date_format, $day)."</span>";
166    }
167  }
168
169  echo "<tr><td class='gCal_wd gCal_wd_datecell $wd_class$todaystyle'>$date_cell</td>";
170
171
172  foreach($pages as $page_key=>$page) {
173     list($page,$pagelist) = explode("(",$page,2);
174     $pagelist = substr($pagelist,-1);
175
176     $cell = "";
177     $cat ="";
178     $cat_classes = "";
179     $style = "";
180     $events = $gCal_data[$page_key][$date];
181
182     if(is_array($events)) {
183         mergesort($events,'cmp_events');
184
185         foreach($events as $event) {
186             if(isset($event["content"])) {
187               if($cell!="") $cell .= "\n";
188               $cell .= $event["content"];
189             }
190
191             if(isset($event["categories"])) {
192               $cat[] = strtoupper($event["categories"]);
193             }
194         }
195
196         if(is_array($cat)) {
197             $cat_classes .= 'gCal_cell_cat_'.implode(' gCal_cell_cat_',$cat)." ";
198         }
199     }
200
201
202     $class = trim(trim($cat_classes)." ".trim($wd_class)." ".$todayframe);
203
204     echo "<td class='gCal_wd $class'>$cell</td>";
205  }
206
207  echo "</tr>\n";
208}
209
210/**
211 * echos the colgroup-tag of calendar table to define the widths of the page-columns
212 *
213 * @author Frank Hinkel <frank@hi-sys.de>
214 *
215 * @param  array pages        the columns to show the data for
216 * @param  array options      the options from the gcal-command
217 */
218function show_column_groups(&$pages,&$options) {
219  global $conf;
220
221  # setup array with column-widths. either user defined or automatic
222  $width_list = array();
223  if(isset($options["width"]) && $options["width"]{0}=="(" && substr($options["width"],-1)==")")
224    $width_list = explode(",",substr($options["width"],1,-1));
225
226  # first width-value is for the date-column. Use 10% as default value.
227  if(!isset($width_list[0])) $width_list[0]="10%";
228
229  # calculate all columns with same width as default
230  $page_count = count($pages);
231  if($page_count>0 && $options["width"]!='auto')
232    $column_width=floor((100-$width_list[0])/$page_count)."%";
233  else
234    $column_width="*";
235
236  echo "<colgroup>";
237    echo "<col width='".$width_list[0]."'>";
238
239    foreach($pages as $key=>$page_id) {
240      $width = (isset($width_list[$key+1]))?$width_list[$key+1]:$column_width;
241      echo "<col width='$width'>";
242    }
243  echo "</colgroup>";
244}
245
246
247/**
248 * displays the clickable (or not) column-headers
249 *
250 * @author Frank Hinkel <frank@hi-sys.de>
251 *
252 * @param  array pages        the columns to show the data for
253 * @param  array options      the options from the gcal-command
254 */
255function show_column_headers(&$pages,&$options) {
256  global $lang;
257  global $conf;
258
259  # show the date-column
260  echo "<tr>";
261  echo "<th class='gCal_columnHead'>".$lang['gCal_day']."</th>";
262
263  # show the column headers of the pages-array
264  foreach($pages as $key=>$page_ID) {
265    # convert page-ID to page-title
266    list($page_name,$page_list) = explode("(",$page_ID,2);
267    $page_list = substr($page_list,0,-1);
268
269    if($page_list=="") {
270      $page_ID = substitute_asterisk($page_ID);
271
272      $name = noNS($page_ID);
273      if ($conf['useheading']) {
274        // get page title
275        $title = p_get_first_heading($page_ID);
276        if($title) $name = $title;
277      }
278      $head = "<a title='$pagelist' href='".wl($page_ID)."'>".$name."</a>";
279    }else if($page_name=="") {
280      $page_list=explode("|",$page_list);
281      $head=$page_name;
282
283      $titles = array();
284
285      foreach($page_list as $pl) {
286        $pl = substitute_asterisk($pl);
287
288        $name = noNS($pl);
289        if ($conf['useheading']) {
290          // get page title
291          $title = p_get_first_heading($pl);
292          if ($title) $name = $title;
293        }
294
295        $titles[] = "<span><a title='$pagelist' href='".wl($pl)."'>".$name."</a></span>";
296      }
297
298      $head = implode(' ',$titles);
299    }else{
300      $head=$page_name;
301    }
302
303    # get column-width from list or take default value
304    echo "<th class='gCal_columnHead'>$head</th>";
305  }
306
307  echo "</tr>\n";
308}
309
310
311/**
312 * substitute asterisk by $conf['start'] (no Namespace). I.e. ":calendar:*" gets ":calendar:start"
313 *
314 * @author Frank Hinkel <frank@hi-sys.de>
315 *
316 * @param  array page_ID
317 */
318function substitute_asterisk($page_ID) {
319  global $conf;
320
321  if( (substr($page_ID,-2)==':*') || ($page_ID=="*")) {
322    $page_ID = substr($page_ID,0,-1);
323    $page_ID.= noNS($conf['start']);
324  }
325
326  return $page_ID;
327}
328
329/**
330 * order the events of a given day by time. used mergesort instead of usort, because it is stable.
331 * which means that events stay in their original order when they compare to be equal.
332 */
333function mergesort(&$array, $cmp_function = 'strcmp') {
334   // Arrays of size < 2 require no action.
335   if (count($array) < 2) return;
336   // Split the array in half
337   $halfway = count($array) / 2;
338   $array1 = array_slice($array, 0, $halfway);
339   $array2 = array_slice($array, $halfway);
340   // Recurse to sort the two halves
341   mergesort($array1, $cmp_function);
342   mergesort($array2, $cmp_function);
343
344   // If all of $array1 is <= all of $array2, just append them.
345   if (call_user_func($cmp_function, end($array1), $array2[0]) < 1) {
346       $array = array_merge($array1, $array2);
347       return;
348   }
349   // Merge the two sorted arrays into a single sorted array
350   $array = array();
351   $ptr1 = $ptr2 = 0;
352   while ($ptr1 < count($array1) && $ptr2 < count($array2)) {
353       if (call_user_func($cmp_function, $array1[$ptr1], $array2[$ptr2]) < 1) {
354           $array[] = $array1[$ptr1++];
355       }
356       else {
357           $array[] = $array2[$ptr2++];
358       }
359   }
360   // Merge the remainder
361   while ($ptr1 < count($array1)) $array[] = $array1[$ptr1++];
362   while ($ptr2 < count($array2)) $array[] = $array2[$ptr2++];
363   return;
364}
365
366
367function cmp_events($e1,$e2) {
368  $t1 = $e1['start_time'];if($t1=="")$t1 = $e1['end_time'];
369  $t2 = $e2['start_time'];if($t2=="")$t2 = $e2['end_time'];
370
371  if($t1==$t2) {
372    $t1 = $e1['end_time'];
373    $t2 = $e2['end_time'];
374    if($t1==$t2) return 0;
375  }
376
377  return ($t1 < $t2) ? -1 : 1;
378}
379
380
381