ILIAS  Release_5_0_x_branch Revision 61816
 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  include_once "Services/UIComponent/Glyph/classes/class.ilGlyphGUI.php";
203 
204  // Table header
205  $counter = 0;
206  foreach(ilCalendarUtil::_buildWeekDayList($this->seed,$this->user_settings->getWeekStart())->get() as $date)
207  {
208  $date_info = $date->get(IL_CAL_FKT_GETDATE,'','UTC');
209  $this->ctrl->setParameterByClass('ilcalendarappointmentgui','seed',$date->get(IL_CAL_DATE));
210  $this->ctrl->setParameterByClass('ilcalendarappointmentgui','idate',$date->get(IL_CAL_DATE));
211  $this->ctrl->setParameterByClass('ilcalendardaygui','seed',$date->get(IL_CAL_DATE));
212 
213  if(!$no_add)
214  {
215  $new_app_url = $this->ctrl->getLinkTargetByClass('ilcalendarappointmentgui','add');
216 
217  if ($settings->getEnableGroupMilestones())
218  {
219  $new_ms_url = $this->ctrl->getLinkTargetByClass('ilcalendarappointmentgui','addMilestone');
220 
221  $this->tpl->setCurrentBlock("new_ms");
222  $this->tpl->setVariable('DD_ID', $date->get(IL_CAL_UNIX));
223  $this->tpl->setVariable('DD_TRIGGER', ilGlyphGUI::get(ilGlyphGUI::ADD));
224  $this->tpl->setVariable('URL_DD_NEW_APP', $new_app_url);
225  $this->tpl->setVariable('TXT_DD_NEW_APP', $this->lng->txt('cal_new_app'));
226  $this->tpl->setVariable('URL_DD_NEW_MS', $new_ms_url);
227  $this->tpl->setVariable('TXT_DD_NEW_MS', $this->lng->txt('cal_new_ms'));
228  $this->tpl->parseCurrentBlock();
229  }
230  else
231  {
232  $this->tpl->setCurrentBlock("new_app");
233  $this->tpl->setVariable('NEW_APP_LINK',$new_app_url);
234  $this->tpl->setVariable('NEW_APP_SRC',ilGlyphGUI::get(ilGlyphGUI::ADD, $this->lng->txt('cal_new_app')));
235  // $this->tpl->setVariable('NEW_APP_ALT',$this->lng->txt('cal_new_app'));
236  $this->tpl->parseCurrentBlock();
237  }
238 
239  $this->ctrl->clearParametersByClass('ilcalendarappointmentgui');
240  }
241 
242  $dayname = ilCalendarUtil::_numericDayToString($date->get(IL_CAL_FKT_DATE,'w'),true);
243  $daydate = $date_info['mday'].' '.ilCalendarUtil::_numericMonthToString($date_info['mon'],false);
244 
245  if(!$disable_empty || $num_apps[$date->get(IL_CAL_DATE)] > 0)
246  {
247  $link = $this->ctrl->getLinkTargetByClass('ilcalendardaygui','');
248  $this->ctrl->clearParametersByClass('ilcalendardaygui');
249 
250  $this->tpl->setCurrentBlock("day_view1_link");
251  $this->tpl->setVariable('HEADER_DATE',$daydate);
252  $this->tpl->setVariable('DAY_VIEW_LINK',$link);
253  $this->tpl->parseCurrentBlock();
254 
255  $this->tpl->setCurrentBlock("day_view2_link");
256  $this->tpl->setVariable('DAYNAME',$dayname);
257  $this->tpl->setVariable('DAY_VIEW_LINK',$link);
258  $this->tpl->parseCurrentBlock();
259  }
260  else
261  {
262  $this->tpl->setCurrentBlock("day_view1_no_link");
263  $this->tpl->setVariable('HEADER_DATE',$daydate);
264  $this->tpl->parseCurrentBlock();
265 
266  $this->tpl->setCurrentBlock("day_view2_no_link");
267  $this->tpl->setVariable('DAYNAME',$dayname);
268  $this->tpl->parseCurrentBlock();
269  }
270 
271  $this->tpl->setCurrentBlock('day_header_row');
272  $this->tpl->setVariable('DAY_COLSPAN',max($colspans[$counter],1));
273  $this->tpl->parseCurrentBlock();
274 
275  $counter++;
276  }
277 
278  // show fullday events
279  $counter = 0;
280  foreach($all_fullday as $daily_apps)
281  {
282  foreach($daily_apps as $event)
283  {
284  if($event['fullday'])
285  {
286  $this->showFulldayAppointment($event);
287  }
288  }
289  $this->tpl->setCurrentBlock('f_day_row');
290  $this->tpl->setVariable('COLSPAN',max($colspans[$counter],1));
291  $this->tpl->parseCurrentBlock();
292  $counter++;
293  }
294  $this->tpl->setCurrentBlock('fullday_apps');
295  $this->tpl->setVariable('TXT_F_DAY', $lng->txt("cal_all_day"));
296  $this->tpl->parseCurrentBlock();
297 
298  $new_link_counter = 0;
299  foreach($hours as $num_hour => $hours_per_day)
300  {
301  $first = true;
302  foreach($hours_per_day as $num_day => $hour)
303  {
304  if($first)
305  {
306  if(!($num_hour%60) || ($num_hour == $morning_aggr && $morning_aggr) ||
307  ($num_hour == $evening_aggr && $evening_aggr))
308  {
309  $first = false;
310 
311  // aggregation rows
312  if(($num_hour == $morning_aggr && $morning_aggr) ||
313  ($num_hour == $evening_aggr && $evening_aggr))
314  {
315  $this->tpl->setVariable('TIME_ROWSPAN', 1);
316  }
317  // rastered hour
318  else
319  {
320  $this->tpl->setVariable('TIME_ROWSPAN', 60/$raster);
321  }
322 
323  $this->tpl->setCurrentBlock('time_txt');
324 
325  $this->tpl->setVariable('TIME',$hour['txt']);
326  $this->tpl->parseCurrentBlock();
327  }
328  }
329 
330  foreach($hour['apps_start'] as $app)
331  {
332  $this->showAppointment($app);
333  }
334 
335  // screen reader: appointments are divs, now output cell
336  if ($ilUser->prefs["screen_reader_optimization"])
337  {
338  $this->tpl->setCurrentBlock('scrd_day_cell');
339  $this->tpl->setVariable('TD_CLASS','calstd');
340  $this->tpl->parseCurrentBlock();
341  }
342 
343 
344  #echo "NUMDAY: ".$num_day;
345  #echo "COLAPANS: ".max($colspans[$num_day],1).'<br />';
346  $num_apps = $hour['apps_num'];
347  $colspan = max($colspans[$num_day],1);
348 
349 
350  // Show new apointment link
351  if(!$hour['apps_num'] && !$ilUser->prefs["screen_reader_optimization"] && !$no_add)
352  {
353  $this->tpl->setCurrentBlock('new_app_link');
354  $this->ctrl->setParameterByClass('ilcalendarappointmentgui','idate',$this->weekdays[$num_day]->get(IL_CAL_DATE));
355  $this->ctrl->setParameterByClass('ilcalendarappointmentgui','seed',$this->seed->get(IL_CAL_DATE));
356  $this->ctrl->setParameterByClass('ilcalendarappointmentgui','hour',floor($num_hour/60));
357  $this->tpl->setVariable('DAY_NEW_APP_LINK',$this->ctrl->getLinkTargetByClass('ilcalendarappointmentgui','add'));
358  $this->ctrl->clearParametersByClass('ilcalendarappointmentgui');
359 
360  $this->tpl->setVariable('DAY_NEW_APP_SRC', ilGlyphGUI::get(ilGlyphGUI::ADD, $this->lng->txt('cal_new_app')));
361  $this->tpl->setVariable('DAY_NEW_APP_ALT',$this->lng->txt('cal_new_app'));
362  $this->tpl->setVariable('DAY_NEW_ID',++$new_link_counter);
363  $this->tpl->parseCurrentBlock();
364  }
365 
366  for($i = $colspan;$i > $hour['apps_num'];$i--)
367  {
368  if ($ilUser->prefs["screen_reader_optimization"])
369  {
370  continue;
371  }
372  $this->tpl->setCurrentBlock('day_cell');
373 
374  // last "slot" of hour needs border
375  $empty_border = '';
376  if($num_hour%60 == 60-$raster ||
377  ($num_hour == $morning_aggr && $morning_aggr) ||
378  ($num_hour == $evening_aggr && $evening_aggr))
379  {
380  $empty_border = ' calempty_border';
381  }
382 
383  if($i == ($hour['apps_num'] + 1))
384  {
385  $this->tpl->setVariable('TD_CLASS','calempty calrightborder'.$empty_border);
386  #$this->tpl->setVariable('TD_STYLE',$add_style);
387  }
388  else
389  {
390  $this->tpl->setVariable('TD_CLASS','calempty'.$empty_border);
391  #$this->tpl->setVariable('TD_STYLE',$add_style);
392  }
393 
394  if(!$hour['apps_num'])
395  {
396  $this->tpl->setVariable('DAY_ID',$new_link_counter);
397  }
398  $this->tpl->setVariable('TD_ROWSPAN',1);
399  $this->tpl->parseCurrentBlock();
400  }
401  }
402 
403  $this->tpl->touchBlock('time_row');
404  }
405 
406  $this->tpl->setVariable("TXT_TIME", $lng->txt("time"));
407  }
408 
416  protected function showFulldayAppointment($a_app)
417  {
418  $this->tpl->setCurrentBlock('panel_code');
419  $this->tpl->setVariable('NUM',$this->num_appointments);
420  $this->tpl->parseCurrentBlock();
421 
422  // milestone icon
423  if ($a_app['event']->isMilestone())
424  {
425  $this->tpl->setCurrentBlock('fullday_ms_icon');
426  $this->tpl->setVariable('ALT_FD_MS', $this->lng->txt("cal_milestone"));
427  $this->tpl->setVariable('SRC_FD_MS', ilUtil::getImagePath("icon_ms.svg"));
428  $this->tpl->parseCurrentBlock();
429  }
430 
431  $this->tpl->setCurrentBlock('fullday_app');
432 
433  include_once('./Services/Calendar/classes/class.ilCalendarAppointmentPanelGUI.php');
434  $this->tpl->setVariable('PANEL_F_DAY_DATA',ilCalendarAppointmentPanelGUI::_getInstance($this->seed)->getHTML($a_app));
435  $this->tpl->setVariable('F_DAY_ID',$this->num_appointments);
436 
437  $compl = ($a_app['event']->isMilestone() && $a_app['event']->getCompletion() > 0)
438  ? " (".$a_app['event']->getCompletion()."%)"
439  : "";
440 
441  $this->tpl->setVariable('F_APP_TITLE',$a_app['event']->getPresentationTitle().$compl);
442 
443  $color = $this->app_colors->getColorByAppointment($a_app['event']->getEntryId());
444  $this->tpl->setVariable('F_APP_BGCOLOR',$color);
445  $this->tpl->setVariable('F_APP_FONTCOLOR',ilCalendarUtil::calculateFontColor($color));
446 
447  $this->ctrl->clearParametersByClass('ilcalendarappointmentgui');
448  $this->ctrl->setParameterByClass('ilcalendarappointmentgui','app_id',$a_app['event']->getEntryId());
449  $this->tpl->setVariable('F_APP_EDIT_LINK',$this->ctrl->getLinkTargetByClass('ilcalendarappointmentgui','edit'));
450 
451  $this->tpl->parseCurrentBlock();
452 
453  $this->num_appointments++;
454  }
455 
462  protected function showAppointment($a_app)
463  {
464  global $ilUser;
465 
466  $this->tpl->setCurrentBlock('panel_code');
467  $this->tpl->setVariable('NUM',$this->num_appointments);
468  $this->tpl->parseCurrentBlock();
469 
470  if (!$ilUser->prefs["screen_reader_optimization"])
471  {
472  $this->tpl->setCurrentBLock('not_empty');
473  }
474  else
475  {
476  $this->tpl->setCurrentBLock('scrd_not_empty');
477  }
478 
479  include_once('./Services/Calendar/classes/class.ilCalendarAppointmentPanelGUI.php');
480  $this->tpl->setVariable('PANEL_DATA',ilCalendarAppointmentPanelGUI::_getInstance($this->seed)->getHTML($a_app));
481 
482  $this->ctrl->clearParametersByClass('ilcalendarappointmentgui');
483  $this->ctrl->setParameterByClass('ilcalendarappointmentgui','app_id',$a_app['event']->getEntryId());
484  $this->tpl->setVariable('APP_EDIT_LINK',$this->ctrl->getLinkTargetByClass('ilcalendarappointmentgui','edit'));
485 
486  $color = $this->app_colors->getColorByAppointment($a_app['event']->getEntryId());
487  $style = 'background-color: '.$color.';';
488  $style .= ('color:'.ilCalendarUtil::calculateFontColor($color));
489  $td_style = $style;
490 
491 
492  if($a_app['event']->isFullDay())
493  {
494  $title = $a_app['event']->getPresentationTitle();
495  }
496  else
497  {
498  switch($this->user_settings->getTimeFormat())
499  {
501  $title = $a_app['event']->getStart()->get(IL_CAL_FKT_DATE,'H:i',$this->timezone);
502  break;
503 
505  $title = $a_app['event']->getStart()->get(IL_CAL_FKT_DATE,'h:ia',$this->timezone);
506  break;
507  }
508  // add end time for screen readers
509  if ($ilUser->prefs["screen_reader_optimization"])
510  {
511  switch($this->user_settings->getTimeFormat())
512  {
514  $title.= "-".$a_app['event']->getEnd()->get(IL_CAL_FKT_DATE,'H:i',$this->timezone);
515  break;
516 
518  $title.= "-".$a_app['event']->getEnd()->get(IL_CAL_FKT_DATE,'h:ia',$this->timezone);
519  break;
520  }
521  }
522 
523  $title .= (' '.$a_app['event']->getPresentationTitle());
524  $td_style .= $a_app['event']->getPresentationStyle();
525  }
526 
527  $this->tpl->setVariable('APP_TITLE',$title);
528  $this->tpl->setVariable('LINK_NUM',$this->num_appointments);
529 
530  $this->tpl->setVariable('LINK_STYLE',$style);
531 
532 
533  if (!$ilUser->prefs["screen_reader_optimization"])
534  {
535  // provide table cell attributes
536  $this->tpl->parseCurrentBlock();
537 
538  $this->tpl->setCurrentBlock('day_cell');
539 
540  $this->tpl->setVariable('DAY_CELL_NUM',$this->num_appointments);
541  $this->tpl->setVariable('TD_ROWSPAN',$a_app['rowspan']);
542  $this->tpl->setVariable('TD_STYLE',$td_style);
543  $this->tpl->setVariable('TD_CLASS','calevent');
544 
545  $this->tpl->parseCurrentBlock();
546  }
547  else
548  {
549  // screen reader: work on div attributes
550  $this->tpl->setVariable('DIV_STYLE',$style);
551  $this->tpl->parseCurrentBlock();
552  }
553 
554  $this->num_appointments++;
555 
556  }
557 
558 
559 
566  protected function parseHourInfo($daily_apps,$date,$num_day,$hours = null,
567  $morning_aggr, $evening_aggr, $raster)
568  {
569  global $ilUser;
570 
571  for($i = $morning_aggr;$i <= $evening_aggr;$i+=$raster)
572  {
573  $hours[$i][$num_day]['apps_start'] = array();
574  $hours[$i][$num_day]['apps_num'] = 0;
575  switch($this->user_settings->getTimeFormat())
576  {
578  if ($morning_aggr > 0 && $i == $morning_aggr)
579  {
580  $hours[$i][$num_day]['txt'] = sprintf('%02d:00',0)."-".
581  sprintf('%02d:00',ceil(($i+1)/60));
582  }
583  else
584  {
585  $hours[$i][$num_day]['txt'].= sprintf('%02d:%02d',floor($i/60),$i%60);
586  }
587  if ($evening_aggr < 23*60 && $i == $evening_aggr)
588  {
589  $hours[$i][$num_day]['txt'].= "-".sprintf('%02d:00',23);
590  }
591  break;
592 
594  if ($morning_aggr > 0 && $i == $morning_aggr)
595  {
596  $hours[$i][$num_day]['txt'] = date('h a',mktime(0,0,0,1,1,2000))."-";
597  }
598  $hours[$i][$num_day]['txt'].= date('h a',mktime(floor($i/60),$i%60,0,1,1,2000));
599  if ($evening_aggr < 23 && $i == $evening_aggr)
600  {
601  $hours[$i][$num_day]['txt'].= "-".date('h a',mktime(23,0,0,1,1,2000));
602  }
603  break;
604  }
605  }
606 
607  $date_info = $date->get(IL_CAL_FKT_GETDATE,'','UTC');
608 
609 
610  foreach($daily_apps as $app)
611  {
612  // fullday appointment are not relavant
613  if($app['fullday'])
614  {
615  continue;
616  }
617  // start hour for this day
618  if($app['start_info']['mday'] != $date_info['mday'])
619  {
620  $start = 0;
621  }
622  else
623  {
624  $start = $app['start_info']['hours']*60+$app['start_info']['minutes'];
625  }
626  // end hour for this day
627  if($app['end_info']['mday'] != $date_info['mday'])
628  {
629  $end = 23*60;
630  }
631  elseif($app['start_info']['hours'] == $app['end_info']['hours'])
632  {
633  $end = $start+$raster;
634  }
635 
636  else
637  {
638  $end = $app['end_info']['hours']*60+$app['end_info']['minutes'];
639  }
640 
641  // set end to next hour for screen readers
642  if ($ilUser->prefs["screen_reader_optimization"])
643  {
644  $end = $start+$raster;
645  }
646 
647  if ($start < $morning_aggr)
648  {
649  $start = $morning_aggr;
650  }
651  if ($end <= $morning_aggr)
652  {
653  $end = $morning_aggr+$raster;
654  }
655  if ($start > $evening_aggr)
656  {
657  $start = $evening_aggr;
658  }
659  if ($end > $evening_aggr+$raster)
660  {
661  $end = $evening_aggr+$raster;
662  }
663  if ($end <= $start)
664  {
665  $end = $start+$raster;
666  }
667 
668  // map start and end to raster
669  $start = floor($start/$raster)*$raster;
670  $end = ceil($end/$raster)*$raster;
671 
672  $first = true;
673  for($i = $start;$i < $end;$i+=$raster)
674  {
675  if($first)
676  {
677  if (!$ilUser->prefs["screen_reader_optimization"])
678  {
679  $app['rowspan'] = ceil(($end - $start)/$raster);
680  }
681  else // screen readers get always a rowspan of 1
682  {
683  $app['rowspan'] = 1;
684  }
685  $hours[$i][$num_day]['apps_start'][] = $app;
686  $first = false;
687  }
688  $hours[$i][$num_day]['apps_num']++;
689  }
690  }
691  return $hours;
692  }
693 
701  protected function calculateColspans($hours)
702  {
703  global $ilUser;
704 
705  foreach($hours as $hour_num => $hours_per_day)
706  {
707  foreach($hours_per_day as $num_day => $hour)
708  {
709  $colspans[$num_day] = max($colspans[$num_day],$hour['apps_num']);
710 
711  // screen reader: always one col
712  if ($ilUser->prefs["screen_reader_optimization"])
713  {
714  $colspans[$num_day] = 1;
715  }
716  }
717  }
718  return $colspans;
719  }
720 
721 
722 }
723 
724 ?>