ILIAS  release_4-3 Revision
 All Data Structures Namespaces Files Functions Variables Groups Pages
class.ilCalendarWeekGUI.php
Go to the documentation of this file.
1 <?php
2 /*
3  +-----------------------------------------------------------------------------+
4  | ILIAS open source |
5  +-----------------------------------------------------------------------------+
6  | Copyright (c) 1998-2006 ILIAS open source, University of Cologne |
7  | |
8  | This program is free software; you can redistribute it and/or |
9  | modify it under the terms of the GNU General Public License |
10  | as published by the Free Software Foundation; either version 2 |
11  | of the License, or (at your option) any later version. |
12  | |
13  | This program is distributed in the hope that it will be useful, |
14  | but WITHOUT ANY WARRANTY; without even the implied warranty of |
15  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16  | GNU General Public License for more details. |
17  | |
18  | You should have received a copy of the GNU General Public License |
19  | along with this program; if not, write to the Free Software |
20  | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
21  +-----------------------------------------------------------------------------+
22 */
23 
34 include_once('Services/Calendar/classes/class.ilDate.php');
35 include_once('Services/Calendar/classes/class.ilCalendarHeaderNavigationGUI.php');
36 include_once('Services/Calendar/classes/class.ilCalendarUserSettings.php');
37 include_once('Services/Calendar/classes/class.ilCalendarAppointmentColors.php');
38 
39 
40 
42 {
43  protected $num_appointments = 1;
44  protected $seed = null;
45  protected $user_settings = null;
46  protected $weekdays = array();
47 
48  protected $lng;
49  protected $ctrl;
50  protected $tabs_gui;
51  protected $tpl;
52 
53  protected $timezone = 'UTC';
54 
62  public function __construct(ilDate $seed_date)
63  {
64  global $ilCtrl, $lng, $ilUser,$ilTabs,$tpl;
65 
66  $this->seed = $seed_date;
67  $this->seed_info = $this->seed->get(IL_CAL_FKT_GETDATE,'','UTC');
68 
69  $this->tpl = $tpl;
70  $this->lng = $lng;
71  $this->ctrl = $ilCtrl;
72  $this->tabs_gui = $ilTabs;
73 
74  $this->user_settings = ilCalendarUserSettings::_getInstanceByUserId($ilUser->getId());
75  $this->app_colors = new ilCalendarAppointmentColors($ilUser->getId());
76 
77  $this->timezone = $ilUser->getTimeZone();
78  }
79 
86  public function executeCommand()
87  {
88  global $ilCtrl,$tpl;
89 
90  $this->ctrl->saveParameter($this,'seed');
91 
92 
93  $next_class = $ilCtrl->getNextClass();
94  switch($next_class)
95  {
96  case 'ilcalendarappointmentgui':
97  $this->ctrl->setReturn($this,'');
98  $this->tabs_gui->setSubTabActive($_SESSION['cal_last_tab']);
99 
100  // initial date for new calendar appointments
101  $idate = new ilDate($_REQUEST['idate'], IL_CAL_DATE);
102 
103  include_once('./Services/Calendar/classes/class.ilCalendarAppointmentGUI.php');
104  $app = new ilCalendarAppointmentGUI($this->seed,$idate,(int) $_GET['app_id']);
105  $this->ctrl->forwardCommand($app);
106  break;
107 
108  default:
109  $time = microtime(true);
110  $cmd = $this->ctrl->getCmd("show");
111  $this->$cmd();
112  $tpl->setContent($this->tpl->get());
113  #echo "Zeit: ".(microtime(true) - $time);
114  break;
115  }
116 
117  return true;
118  }
119 
126  public function show()
127  {
128  global $ilUser, $lng;
129 
130 
131  // config
132  $raster = 15;
133  if($this->user_settings->getDayStart())
134  {
135  // push starting point to last "slot" of hour BEFORE morning aggregation
136  $morning_aggr = ($this->user_settings->getDayStart()-1)*60+(60-$raster);
137  }
138  else
139  {
140  $morning_aggr = 0;
141  }
142  $evening_aggr = $this->user_settings->getDayEnd()*60;
143 
144 
145  $this->tpl = new ilTemplate('tpl.week_view.html',true,true,'Services/Calendar');
146 
147  include_once('./Services/YUI/classes/class.ilYuiUtil.php');
150 
151 
152  $navigation = new ilCalendarHeaderNavigationGUI($this,$this->seed,ilDateTime::WEEK);
153  $this->tpl->setVariable('NAVIGATION',$navigation->getHTML());
154 
155  if(isset($_GET["bkid"]))
156  {
157  $user_id = $_GET["bkid"];
158  $disable_empty = true;
159  $no_add = true;
160  }
161  elseif($ilUser->getId() == ANONYMOUS_USER_ID)
162  {
163  $user_id = $ilUser->getId();
164  $disable_empty = false;
165  $no_add = true;
166  }
167  else
168  {
169  $user_id = $ilUser->getId();
170  $disable_empty = false;
171  $no_add = false;
172  }
173  include_once('Services/Calendar/classes/class.ilCalendarSchedule.php');
174  $this->scheduler = new ilCalendarSchedule($this->seed,ilCalendarSchedule::TYPE_WEEK,$user_id,$disable_empty);
175  $this->scheduler->addSubitemCalendars(true);
176  $this->scheduler->calculate();
177 
178  $counter = 0;
179  $hours = null;
180  $all_fullday = array();
181  foreach(ilCalendarUtil::_buildWeekDayList($this->seed,$this->user_settings->getWeekStart())->get() as $date)
182  {
183  $daily_apps = $this->scheduler->getByDay($date,$this->timezone);
184  $hours = $this->parseHourInfo($daily_apps,$date,$counter,$hours,
185  $morning_aggr,
186  $evening_aggr,
187  $raster
188  );
189  $this->weekdays[] = $date;
190 
191  $num_apps[$date->get(IL_CAL_DATE)] = count($daily_apps);
192 
193  $all_fullday[] = $daily_apps;
194  $counter++;
195  }
196 
197  $colspans = $this->calculateColspans($hours);
198 
199  include_once('Services/Calendar/classes/class.ilCalendarSettings.php');
200  $settings = ilCalendarSettings::_getInstance();
201 
202  // Table header
203  $counter = 0;
204  foreach(ilCalendarUtil::_buildWeekDayList($this->seed,$this->user_settings->getWeekStart())->get() as $date)
205  {
206  $date_info = $date->get(IL_CAL_FKT_GETDATE,'','UTC');
207  $this->ctrl->setParameterByClass('ilcalendarappointmentgui','seed',$date->get(IL_CAL_DATE));
208  $this->ctrl->setParameterByClass('ilcalendarappointmentgui','idate',$date->get(IL_CAL_DATE));
209  $this->ctrl->setParameterByClass('ilcalendardaygui','seed',$date->get(IL_CAL_DATE));
210 
211  if(!$no_add)
212  {
213  if ($settings->getEnableGroupMilestones())
214  {
215  $this->tpl->setCurrentBlock("new_ms");
216  $this->tpl->setVariable('H_NEW_MS_SRC', ilUtil::getImagePath('ms_add.png'));
217  $this->tpl->setVariable('H_NEW_MS_ALT', $this->lng->txt('cal_new_ms'));
218  $this->tpl->setVariable('NEW_MS_LINK', $this->ctrl->getLinkTargetByClass('ilcalendarappointmentgui','addMilestone'));
219  $this->tpl->parseCurrentBlock();
220  }
221 
222 
223  $this->tpl->setCurrentBlock("new_app");
224  $this->tpl->setVariable('NEW_APP_LINK',$this->ctrl->getLinkTargetByClass('ilcalendarappointmentgui','add'));
225  $this->ctrl->clearParametersByClass('ilcalendarappointmentgui');
226  $this->tpl->setVariable('NEW_APP_SRC',ilUtil::getImagePath('date_add.png'));
227  $this->tpl->setVariable('NEW_APP_ALT',$this->lng->txt('cal_new_app'));
228  $this->tpl->parseCurrentBlock();
229  }
230 
231  $dayname = ilCalendarUtil::_numericDayToString($date->get(IL_CAL_FKT_DATE,'w'),true);
232  $daydate = $date_info['mday'].' '.ilCalendarUtil::_numericMonthToString($date_info['mon'],false);
233 
234  if(!$disable_empty || $num_apps[$date->get(IL_CAL_DATE)] > 0)
235  {
236  $link = $this->ctrl->getLinkTargetByClass('ilcalendardaygui','');
237  $this->ctrl->clearParametersByClass('ilcalendardaygui');
238 
239  $this->tpl->setCurrentBlock("day_view1_link");
240  $this->tpl->setVariable('HEADER_DATE',$daydate);
241  $this->tpl->setVariable('DAY_VIEW_LINK',$link);
242  $this->tpl->parseCurrentBlock();
243 
244  $this->tpl->setCurrentBlock("day_view2_link");
245  $this->tpl->setVariable('DAYNAME',$dayname);
246  $this->tpl->setVariable('DAY_VIEW_LINK',$link);
247  $this->tpl->parseCurrentBlock();
248  }
249  else
250  {
251  $this->tpl->setCurrentBlock("day_view1_no_link");
252  $this->tpl->setVariable('HEADER_DATE',$daydate);
253  $this->tpl->parseCurrentBlock();
254 
255  $this->tpl->setCurrentBlock("day_view2_no_link");
256  $this->tpl->setVariable('DAYNAME',$dayname);
257  $this->tpl->parseCurrentBlock();
258  }
259 
260  $this->tpl->setCurrentBlock('day_header_row');
261  $this->tpl->setVariable('DAY_COLSPAN',max($colspans[$counter],1));
262  $this->tpl->parseCurrentBlock();
263 
264  $counter++;
265  }
266 
267  // show fullday events
268  $counter = 0;
269  foreach($all_fullday as $daily_apps)
270  {
271  foreach($daily_apps as $event)
272  {
273  if($event['fullday'])
274  {
275  $this->showFulldayAppointment($event);
276  }
277  }
278  $this->tpl->setCurrentBlock('f_day_row');
279  $this->tpl->setVariable('COLSPAN',max($colspans[$counter],1));
280  $this->tpl->parseCurrentBlock();
281  $counter++;
282  }
283  $this->tpl->setCurrentBlock('fullday_apps');
284  $this->tpl->setVariable('TXT_F_DAY', $lng->txt("cal_all_day"));
285  $this->tpl->parseCurrentBlock();
286 
287  $new_link_counter = 0;
288  foreach($hours as $num_hour => $hours_per_day)
289  {
290  $first = true;
291  foreach($hours_per_day as $num_day => $hour)
292  {
293  if($first)
294  {
295  if(!($num_hour%60) || ($num_hour == $morning_aggr && $morning_aggr) ||
296  ($num_hour == $evening_aggr && $evening_aggr))
297  {
298  $first = false;
299 
300  // aggregation rows
301  if(($num_hour == $morning_aggr && $morning_aggr) ||
302  ($num_hour == $evening_aggr && $evening_aggr))
303  {
304  $this->tpl->setVariable('TIME_ROWSPAN', 1);
305  }
306  // rastered hour
307  else
308  {
309  $this->tpl->setVariable('TIME_ROWSPAN', 60/$raster);
310  }
311 
312  $this->tpl->setCurrentBlock('time_txt');
313 
314  $this->tpl->setVariable('TIME',$hour['txt']);
315  $this->tpl->parseCurrentBlock();
316  }
317  }
318 
319  foreach($hour['apps_start'] as $app)
320  {
321  $this->showAppointment($app);
322  }
323 
324  // screen reader: appointments are divs, now output cell
325  if ($ilUser->prefs["screen_reader_optimization"])
326  {
327  $this->tpl->setCurrentBlock('scrd_day_cell');
328  $this->tpl->setVariable('TD_CLASS','calstd');
329  $this->tpl->parseCurrentBlock();
330  }
331 
332 
333  #echo "NUMDAY: ".$num_day;
334  #echo "COLAPANS: ".max($colspans[$num_day],1).'<br />';
335  $num_apps = $hour['apps_num'];
336  $colspan = max($colspans[$num_day],1);
337 
338 
339  // Show new apointment link
340  if(!$hour['apps_num'] && !$ilUser->prefs["screen_reader_optimization"] && !$no_add)
341  {
342  $this->tpl->setCurrentBlock('new_app_link');
343  $this->ctrl->setParameterByClass('ilcalendarappointmentgui','idate',$this->weekdays[$num_day]->get(IL_CAL_DATE));
344  $this->ctrl->setParameterByClass('ilcalendarappointmentgui','seed',$this->seed->get(IL_CAL_DATE));
345  $this->ctrl->setParameterByClass('ilcalendarappointmentgui','hour',floor($num_hour/60));
346  $this->tpl->setVariable('DAY_NEW_APP_LINK',$this->ctrl->getLinkTargetByClass('ilcalendarappointmentgui','add'));
347  $this->ctrl->clearParametersByClass('ilcalendarappointmentgui');
348 
349  $this->tpl->setVariable('DAY_NEW_APP_SRC',ilUtil::getImagePath('date_add.png'));
350  $this->tpl->setVariable('DAY_NEW_APP_ALT',$this->lng->txt('cal_new_app'));
351  $this->tpl->setVariable('DAY_NEW_ID',++$new_link_counter);
352  $this->tpl->parseCurrentBlock();
353  }
354 
355  for($i = $colspan;$i > $hour['apps_num'];$i--)
356  {
357  if ($ilUser->prefs["screen_reader_optimization"])
358  {
359  continue;
360  }
361  $this->tpl->setCurrentBlock('day_cell');
362 
363  // last "slot" of hour needs border
364  $empty_border = '';
365  if($num_hour%60 == 60-$raster ||
366  ($num_hour == $morning_aggr && $morning_aggr) ||
367  ($num_hour == $evening_aggr && $evening_aggr))
368  {
369  $empty_border = ' calempty_border';
370  }
371 
372  if($i == ($hour['apps_num'] + 1))
373  {
374  $this->tpl->setVariable('TD_CLASS','calempty calrightborder'.$empty_border);
375  #$this->tpl->setVariable('TD_STYLE',$add_style);
376  }
377  else
378  {
379  $this->tpl->setVariable('TD_CLASS','calempty'.$empty_border);
380  #$this->tpl->setVariable('TD_STYLE',$add_style);
381  }
382 
383  if(!$hour['apps_num'])
384  {
385  $this->tpl->setVariable('DAY_ID',$new_link_counter);
386  }
387  $this->tpl->setVariable('TD_ROWSPAN',1);
388  $this->tpl->parseCurrentBlock();
389  }
390  }
391 
392  $this->tpl->touchBlock('time_row');
393  }
394 
395  $this->tpl->setVariable("TXT_TIME", $lng->txt("time"));
396  }
397 
405  protected function showFulldayAppointment($a_app)
406  {
407  $this->tpl->setCurrentBlock('panel_code');
408  $this->tpl->setVariable('NUM',$this->num_appointments);
409  $this->tpl->parseCurrentBlock();
410 
411  // milestone icon
412  if ($a_app['event']->isMilestone())
413  {
414  $this->tpl->setCurrentBlock('fullday_ms_icon');
415  $this->tpl->setVariable('ALT_FD_MS', $this->lng->txt("cal_milestone"));
416  $this->tpl->setVariable('SRC_FD_MS', ilUtil::getImagePath("icon_ms_s.png"));
417  $this->tpl->parseCurrentBlock();
418  }
419 
420  $this->tpl->setCurrentBlock('fullday_app');
421 
422  include_once('./Services/Calendar/classes/class.ilCalendarAppointmentPanelGUI.php');
423  $this->tpl->setVariable('PANEL_F_DAY_DATA',ilCalendarAppointmentPanelGUI::_getInstance($this->seed)->getHTML($a_app));
424  $this->tpl->setVariable('F_DAY_ID',$this->num_appointments);
425 
426  $compl = ($a_app['event']->isMilestone() && $a_app['event']->getCompletion() > 0)
427  ? " (".$a_app['event']->getCompletion()."%)"
428  : "";
429 
430  $this->tpl->setVariable('F_APP_TITLE',$a_app['event']->getPresentationTitle().$compl);
431 
432  $color = $this->app_colors->getColorByAppointment($a_app['event']->getEntryId());
433  $this->tpl->setVariable('F_APP_BGCOLOR',$color);
434  $this->tpl->setVariable('F_APP_FONTCOLOR',ilCalendarUtil::calculateFontColor($color));
435 
436  $this->ctrl->clearParametersByClass('ilcalendarappointmentgui');
437  $this->ctrl->setParameterByClass('ilcalendarappointmentgui','app_id',$a_app['event']->getEntryId());
438  $this->tpl->setVariable('F_APP_EDIT_LINK',$this->ctrl->getLinkTargetByClass('ilcalendarappointmentgui','edit'));
439 
440  $this->tpl->parseCurrentBlock();
441 
442  $this->num_appointments++;
443  }
444 
451  protected function showAppointment($a_app)
452  {
453  global $ilUser;
454 
455  $this->tpl->setCurrentBlock('panel_code');
456  $this->tpl->setVariable('NUM',$this->num_appointments);
457  $this->tpl->parseCurrentBlock();
458 
459  if (!$ilUser->prefs["screen_reader_optimization"])
460  {
461  $this->tpl->setCurrentBLock('not_empty');
462  }
463  else
464  {
465  $this->tpl->setCurrentBLock('scrd_not_empty');
466  }
467 
468  include_once('./Services/Calendar/classes/class.ilCalendarAppointmentPanelGUI.php');
469  $this->tpl->setVariable('PANEL_DATA',ilCalendarAppointmentPanelGUI::_getInstance($this->seed)->getHTML($a_app));
470 
471  $this->ctrl->clearParametersByClass('ilcalendarappointmentgui');
472  $this->ctrl->setParameterByClass('ilcalendarappointmentgui','app_id',$a_app['event']->getEntryId());
473  $this->tpl->setVariable('APP_EDIT_LINK',$this->ctrl->getLinkTargetByClass('ilcalendarappointmentgui','edit'));
474 
475  if($a_app['event']->isFullDay())
476  {
477  $title = $a_app['event']->getPresentationTitle();
478  }
479  else
480  {
481  switch($this->user_settings->getTimeFormat())
482  {
484  $title = $a_app['event']->getStart()->get(IL_CAL_FKT_DATE,'H:i',$this->timezone);
485  break;
486 
488  $title = $a_app['event']->getStart()->get(IL_CAL_FKT_DATE,'h:ia',$this->timezone);
489  break;
490  }
491  // add end time for screen readers
492  if ($ilUser->prefs["screen_reader_optimization"])
493  {
494  switch($this->user_settings->getTimeFormat())
495  {
497  $title.= "-".$a_app['event']->getEnd()->get(IL_CAL_FKT_DATE,'H:i',$this->timezone);
498  break;
499 
501  $title.= "-".$a_app['event']->getEnd()->get(IL_CAL_FKT_DATE,'h:ia',$this->timezone);
502  break;
503  }
504  }
505 
506  // booking
507  if($a_app['category_type'] == ilCalendarCategory::TYPE_CH)
508  {
509  include_once 'Services/Booking/classes/class.ilBookingEntry.php';
510  $entry = new ilBookingEntry($a_app['event']->getContextId());
511  if($entry)
512  {
513  $title .= ' '.$a_app['event']->getTitle();
514  if($entry->isOwner())
515  {
516  $max = (int)$entry->getNumberOfBookings();
517  $current = (int)$entry->getCurrentNumberOfBookings($a_app['event']->getEntryId());
518  if($max > 1)
519  {
520  $title .= ' ('.$current.'/'.$max.')';
521  }
522  else if($current == $max)
523  {
524  $title .= ' ('.$this->lng->txt('cal_booked_out').')';
525  }
526  else
527  {
528  $title .= ' ('.$this->lng->txt('cal_book_free').')';
529  }
530  }
531  else if($entry->hasBooked($a_app['event']->getEntryId()))
532  {
533  $title .= ' ('.$this->lng->txt('cal_date_booked').')';
534  }
535  }
536  }
537  else
538  {
539  $title .= (' '.$a_app['event']->getPresentationTitle());
540  }
541  }
542 
543  $this->tpl->setVariable('APP_TITLE',$title);
544 
545  $this->tpl->setVariable('LINK_NUM',$this->num_appointments);
546 
547  $color = $this->app_colors->getColorByAppointment($a_app['event']->getEntryId());
548  $style = 'background-color: '.$color.';';
549  $style .= ('color:'.ilCalendarUtil::calculateFontColor($color));
550  $this->tpl->setVariable('LINK_STYLE',$style);
551 
552  if (!$ilUser->prefs["screen_reader_optimization"])
553  {
554  // provide table cell attributes
555  $this->tpl->parseCurrentBlock();
556 
557  $this->tpl->setCurrentBlock('day_cell');
558 
559  $this->tpl->setVariable('DAY_CELL_NUM',$this->num_appointments);
560  $this->tpl->setVariable('TD_ROWSPAN',$a_app['rowspan']);
561  $this->tpl->setVariable('TD_STYLE',$style);
562  $this->tpl->setVariable('TD_CLASS','calevent');
563 
564  $this->tpl->parseCurrentBlock();
565  }
566  else
567  {
568  // screen reader: work on div attributes
569  $this->tpl->setVariable('DIV_STYLE',$style);
570  $this->tpl->parseCurrentBlock();
571  }
572 
573  $this->num_appointments++;
574 
575  }
576 
577 
578 
585  protected function parseHourInfo($daily_apps,$date,$num_day,$hours = null,
586  $morning_aggr, $evening_aggr, $raster)
587  {
588  global $ilUser;
589 
590  for($i = $morning_aggr;$i <= $evening_aggr;$i+=$raster)
591  {
592  $hours[$i][$num_day]['apps_start'] = array();
593  $hours[$i][$num_day]['apps_num'] = 0;
594  switch($this->user_settings->getTimeFormat())
595  {
597  if ($morning_aggr > 0 && $i == $morning_aggr)
598  {
599  $hours[$i][$num_day]['txt'] = sprintf('%02d:00',0)."-".
600  sprintf('%02d:00',ceil(($i+1)/60));
601  }
602  else
603  {
604  $hours[$i][$num_day]['txt'].= sprintf('%02d:%02d',floor($i/60),$i%60);
605  }
606  if ($evening_aggr < 23*60 && $i == $evening_aggr)
607  {
608  $hours[$i][$num_day]['txt'].= "-".sprintf('%02d:00',23);
609  }
610  break;
611 
613  if ($morning_aggr > 0 && $i == $morning_aggr)
614  {
615  $hours[$i][$num_day]['txt'] = date('h a',mktime(0,0,0,1,1,2000))."-";
616  }
617  $hours[$i][$num_day]['txt'].= date('h a',mktime(floor($i/60),$i%60,0,1,1,2000));
618  if ($evening_aggr < 23 && $i == $evening_aggr)
619  {
620  $hours[$i][$num_day]['txt'].= "-".date('h a',mktime(23,0,0,1,1,2000));
621  }
622  break;
623  }
624  }
625 
626  $date_info = $date->get(IL_CAL_FKT_GETDATE,'','UTC');
627 
628 
629  foreach($daily_apps as $app)
630  {
631  // fullday appointment are not relavant
632  if($app['fullday'])
633  {
634  continue;
635  }
636  // start hour for this day
637  if($app['start_info']['mday'] != $date_info['mday'])
638  {
639  $start = 0;
640  }
641  else
642  {
643  $start = $app['start_info']['hours']*60+$app['start_info']['minutes'];
644  }
645  // end hour for this day
646  if($app['end_info']['mday'] != $date_info['mday'])
647  {
648  $end = 23*60;
649  }
650  elseif($app['start_info']['hours'] == $app['end_info']['hours'])
651  {
652  $end = $start+$raster;
653  }
654 
655  else
656  {
657  $end = $app['end_info']['hours']*60+$app['end_info']['minutes'];
658  }
659 
660  // set end to next hour for screen readers
661  if ($ilUser->prefs["screen_reader_optimization"])
662  {
663  $end = $start+$raster;
664  }
665 
666  if ($start < $morning_aggr)
667  {
668  $start = $morning_aggr;
669  }
670  if ($end <= $morning_aggr)
671  {
672  $end = $morning_aggr+$raster;
673  }
674  if ($start > $evening_aggr)
675  {
676  $start = $evening_aggr;
677  }
678  if ($end > $evening_aggr+$raster)
679  {
680  $end = $evening_aggr+$raster;
681  }
682  if ($end <= $start)
683  {
684  $end = $start+$raster;
685  }
686 
687  // map start and end to raster
688  $start = floor($start/$raster)*$raster;
689  $end = ceil($end/$raster)*$raster;
690 
691  $first = true;
692  for($i = $start;$i < $end;$i+=$raster)
693  {
694  if($first)
695  {
696  if (!$ilUser->prefs["screen_reader_optimization"])
697  {
698  $app['rowspan'] = ceil(($end - $start)/$raster);
699  }
700  else // screen readers get always a rowspan of 1
701  {
702  $app['rowspan'] = 1;
703  }
704  $hours[$i][$num_day]['apps_start'][] = $app;
705  $first = false;
706  }
707  $hours[$i][$num_day]['apps_num']++;
708  }
709  }
710  return $hours;
711  }
712 
720  protected function calculateColspans($hours)
721  {
722  global $ilUser;
723 
724  foreach($hours as $hour_num => $hours_per_day)
725  {
726  foreach($hours_per_day as $num_day => $hour)
727  {
728  $colspans[$num_day] = max($colspans[$num_day],$hour['apps_num']);
729 
730  // screen reader: always one col
731  if ($ilUser->prefs["screen_reader_optimization"])
732  {
733  $colspans[$num_day] = 1;
734  }
735  }
736  }
737  return $colspans;
738  }
739 
740 
741 }
742 
743 ?>