ILIAS  release_8 Revision v8.19
All Data Structures Namespaces Files Functions Variables Modules Pages
class.ilCalendarDayGUI.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
29 {
30  protected array $seed_info = [];
32  protected int $num_appointments = 1;
33  protected string $timezone = 'UTC';
35 
36  public function __construct(ilDate $seed_date)
37  {
39  }
40 
41  public function initialize(int $a_calendar_presentation_type): void
42  {
43  global $DIC;
44 
45  parent::initialize($a_calendar_presentation_type);
46  $this->seed_info = (array) $this->seed->get(IL_CAL_FKT_GETDATE);
47  $this->user_settings = ilCalendarUserSettings::_getInstanceByUserId($this->user->getId());
48  $this->app_colors = new ilCalendarAppointmentColors($this->user->getId());
49  if ($this->user->getTimeZone()) {
50  $this->timezone = $this->user->getTimeZone();
51  }
52  }
53 
54  public function executeCommand(): void
55  {
56  $next_class = $this->ctrl->getNextClass();
57  switch ($next_class) {
58  case "ilcalendarappointmentpresentationgui":
59  $this->ctrl->setReturn($this, "");
60  $this->logger->debug("-ExecCommand - representation of ilDate: this->seed->get(IL_CAL_DATE) = " . $this->seed->get(IL_CAL_DATE));
61  $gui = ilCalendarAppointmentPresentationGUI::_getInstance($this->seed, (array) $this->getCurrentApp());
62  $this->ctrl->forwardCommand($gui);
63  break;
64  case 'ilcalendarappointmentgui':
65  $this->ctrl->setReturn($this, '');
66  $this->tabs_gui->setSubTabActive((string) ilSession::get('cal_last_tab'));
67 
68  // initial date for new calendar appointments
69  $idate = new ilDate($this->initInitialDateFromQuery(), IL_CAL_DATE);
70  $app = new ilCalendarAppointmentGUI($this->seed, $idate, $this->initAppointmentIdFromQuery());
71  $this->ctrl->forwardCommand($app);
72  break;
73 
74  default:
75  $cmd = $this->ctrl->getCmd("show");
76  $this->$cmd();
77  $this->main_tpl->setContent($this->tpl->get());
78  break;
79  }
80  }
81 
86  protected function show(): void
87  {
88  // config
89  $raster = 15;
90  if ($this->user_settings->getDayStart()) {
91  // push starting point to last "slot" of hour BEFORE morning aggregation
92  $morning_aggr = ($this->user_settings->getDayStart() - 1) * 60 + (60 - $raster);
93  } else {
94  $morning_aggr = 0;
95  }
96  $evening_aggr = $this->user_settings->getDayEnd() * 60;
97 
98  $this->tpl = new ilTemplate('tpl.day_view.html', true, true, 'Services/Calendar');
99 
101 
102  $bkid = $this->initBookingUserFromQuery();
103  if ($bkid) {
104  $user_id = $bkid;
105  $no_add = true;
106  } elseif ($this->user->getId() == ANONYMOUS_USER_ID) {
107  $user_id = $this->user->getId();
108  $no_add = true;
109  } else {
110  $user_id = $this->user->getId();
111  $no_add = false;
112  }
113  $scheduler = new ilCalendarSchedule($this->seed, ilCalendarSchedule::TYPE_DAY, $user_id);
114  $scheduler->addSubitemCalendars(true);
115  $scheduler->calculate();
116  $daily_apps = $scheduler->getByDay($this->seed, $this->timezone);
117 
118  //display the download files button.
119  if (count($daily_apps)) {
120  $this->view_with_appointments = true;
121  }
122 
123  $hours = $this->parseInfoIntoRaster(
124  $daily_apps,
125  $morning_aggr,
126  $evening_aggr,
127  $raster
128  );
129 
130  $colspan = $this->calculateColspan($hours);
131 
132  $navigation = new ilCalendarHeaderNavigationGUI($this, $this->seed, ilDateTime::DAY);
133  $this->ctrl->setParameterByClass('ilcalendarappointmentgui', 'seed', $this->seed->get(IL_CAL_DATE));
134 
135  // add milestone link
137 
138  if (!$no_add) {
139  $this->ctrl->setParameterByClass('ilcalendarappointmentgui', 'seed', $this->seed->get(IL_CAL_DATE));
140  $this->ctrl->setParameterByClass('ilcalendarappointmentgui', 'idate', $this->seed->get(IL_CAL_DATE));
141  $new_app_url = $this->ctrl->getLinkTargetByClass('ilcalendarappointmentgui', 'add');
142 
143  if ($settings->getEnableGroupMilestones()) {
144  $this->ctrl->setParameterByClass('ilcalendarappointmentgui', 'seed', $this->seed->get(IL_CAL_DATE));
145  $this->ctrl->setParameterByClass('ilcalendarappointmentgui', 'idate', $this->seed->get(IL_CAL_DATE));
146  $new_ms_url = $this->ctrl->getLinkTargetByClass('ilcalendarappointmentgui', 'addMilestone');
147 
148  $this->tpl->setCurrentBlock("new_ms");
149  $this->tpl->setVariable('DD_ID', $this->seed->get(IL_CAL_UNIX));
150  $this->tpl->setVariable(
151  'DD_TRIGGER',
152  $this->ui_renderer->render($this->ui_factory->symbol()->glyph()->add())
153  );
154  $this->tpl->setVariable('URL_DD_NEW_APP', $new_app_url);
155  $this->tpl->setVariable('TXT_DD_NEW_APP', $this->lng->txt('cal_new_app'));
156  $this->tpl->setVariable('URL_DD_NEW_MS', $new_ms_url);
157  $this->tpl->setVariable('TXT_DD_NEW_MS', $this->lng->txt('cal_new_ms'));
158  $this->tpl->parseCurrentBlock();
159  } else {
160  $this->tpl->setCurrentBlock("new_app1");
161  $this->tpl->setVariable(
162  'H_NEW_APP_GLYPH',
163  $this->ui_renderer->render($this->ui_factory->symbol()->glyph()->add($new_app_url))
164  );
165  $this->tpl->parseCurrentBlock();
166  }
167 
168  $this->ctrl->clearParametersByClass('ilcalendarappointmentgui');
169  }
170 
171  $this->tpl->setVariable('NAVIGATION', $navigation->getHTML());
172 
173  $this->tpl->setVariable(
174  'HEADER_DATE',
175  $this->seed_info['mday'] . ' ' . ilCalendarUtil::_numericMonthToString($this->seed_info['mon'], false)
176  );
177  $this->tpl->setVariable(
178  'HEADER_DAY',
179  ilCalendarUtil::_numericDayToString((int) $this->seed_info['wday'], true)
180  );
181  $this->tpl->setVariable('HCOLSPAN', $colspan - 1);
182 
183  $this->tpl->setVariable('TXT_TIME', $this->lng->txt("time"));
184 
185  // show fullday events
186  foreach ($daily_apps as $event) {
187  if ($event['fullday']) {
188  $this->showFulldayAppointment($event);
189  }
190  }
191  $this->tpl->setCurrentBlock('fullday_apps');
192  $this->tpl->setVariable('TXT_F_DAY', $this->lng->txt("cal_all_day"));
193  $this->tpl->setVariable('COLSPAN', $colspan - 1);
194  $this->tpl->parseCurrentBlock();
195 
196  // parse the hour rows
197  foreach ($hours as $numeric => $hour) {
198  if (!($numeric % 60) || ($numeric == $morning_aggr && $morning_aggr) ||
199  ($numeric == $evening_aggr && $evening_aggr)) {
200  if (!$no_add) {
201  $this->tpl->setCurrentBlock("new_app2");
202  $this->ctrl->clearParametersByClass('ilcalendarappointmentgui');
203  $this->ctrl->setParameterByClass('ilcalendarappointmentgui', 'seed', $this->seed->get(IL_CAL_DATE));
204  $this->ctrl->setParameterByClass(
205  'ilcalendarappointmentgui',
206  'idate',
207  $this->seed->get(IL_CAL_DATE)
208  );
209  $this->ctrl->setParameterByClass('ilcalendarappointmentgui', 'hour', floor($numeric / 60));
210  $this->tpl->setVariable(
211  'NEW_APP_GLYPH',
212  $this->ui_renderer->render($this->ui_factory->symbol()->glyph()->add(
213  $this->ctrl->getLinkTargetByClass('ilcalendarappointmentgui', 'add')
214  ))
215  );
216  $this->tpl->parseCurrentBlock();
217  }
218 
219  // aggregation rows
220  if (($numeric == $morning_aggr && $morning_aggr) ||
221  ($numeric == $evening_aggr && $evening_aggr)) {
222  $this->tpl->setVariable('TIME_ROWSPAN', 1);
223  } // rastered hour
224  else {
225  $this->tpl->setVariable('TIME_ROWSPAN', 60 / $raster);
226  }
227 
228  $this->tpl->setCurrentBlock('time_txt');
229 
230  $this->tpl->setVariable('TIME', $hour['txt']);
231  $this->tpl->parseCurrentBlock();
232  }
233 
234  foreach ($hour['apps_start'] as $app) {
235  $this->showAppointment($app);
236  }
237 
238  for ($i = ($colspan - 1); $i > $hour['apps_num']; $i--) {
239  $this->tpl->setCurrentBlock('empty_cell');
240  $this->tpl->setVariable('EMPTY_WIDTH', (100 / ($colspan - 1)) . '%');
241 
242  // last "slot" of hour needs border
243  if ($numeric % 60 == 60 - $raster ||
244  ($numeric == $morning_aggr && $morning_aggr) ||
245  ($numeric == $evening_aggr && $evening_aggr)) {
246  $this->tpl->setVariable('EMPTY_STYLE', ' calempty_border');
247  }
248 
249  $this->tpl->parseCurrentBlock();
250  }
251 
252  $this->tpl->touchBlock('time_row');
253  }
254  }
255 
256  protected function showFulldayAppointment(array $a_app): void
257  {
258  $event_tpl = new ilTemplate('tpl.day_event_view.html', true, true, 'Services/Calendar');
259 
260  // milestone icon
261  if ($a_app['event']->isMilestone()) {
262  $event_tpl->setCurrentBlock('fullday_ms_icon');
263  $event_tpl->setVariable('ALT_FD_MS', $this->lng->txt("cal_milestone"));
264  $event_tpl->setVariable('SRC_FD_MS', ilUtil::getImagePath("icon_ms.svg"));
265  $event_tpl->parseCurrentBlock();
266  }
267 
268  $event_tpl->setCurrentBlock('fullday_app');
269 
270  $compl = ($a_app['event']->isMilestone() && $a_app['event']->getCompletion() > 0)
271  ? " (" . $a_app['event']->getCompletion() . "%)"
272  : "";
273 
274  $shy = $this->getAppointmentShyButton($a_app['event'], (string) $a_app['dstart'], "");
275 
276  //$title = ($new_title = $this->getContentByPlugins($a_app['event'], $a_app['dstart'], $shy))? $new_title : $shy;
277 
278  $content = $shy . $compl;
279 
280  $event_tpl->setVariable('EVENT_CONTENT', $content);
281 
282  $color = $this->app_colors->getColorByAppointment($a_app['event']->getEntryId());
283  $event_tpl->setVariable('F_APP_BGCOLOR', $color);
284  $event_tpl->setVariable('F_APP_FONTCOLOR', ilCalendarUtil::calculateFontColor($color));
285 
286  $this->ctrl->clearParametersByClass('ilcalendarappointmentgui');
287  $this->ctrl->setParameterByClass('ilcalendarappointmentgui', 'seed', $this->seed->get(IL_CAL_DATE));
288  $this->ctrl->setParameterByClass('ilcalendarappointmentgui', 'app_id', $a_app['event']->getEntryId());
289  $event_tpl->setVariable(
290  'F_APP_EDIT_LINK',
291  $this->ctrl->getLinkTargetByClass('ilcalendarappointmentgui', 'edit')
292  );
293 
294  if ($event_html_by_plugin = $this->getContentByPlugins(
295  $a_app['event'],
296  $a_app['dstart'],
297  $content,
298  $event_tpl
299  )) {
300  $body_html = $event_html_by_plugin;
301  } else {
302  $event_tpl->parseCurrentBlock();
303  $body_html = $event_tpl->get();
304  }
305 
306  $this->tpl->setCurrentBlock("content_fd");
307  $this->tpl->setVariable("CONTENT_EVENT", $body_html);
308  $this->tpl->parseCurrentBlock();
309  $this->num_appointments++;
310  }
311 
312  protected function showAppointment(array $a_app): void
313  {
314  $event_tpl = new ilTemplate('tpl.day_event_view.html', true, true, 'Services/Calendar');
315  $event_tpl->setCurrentBlock('app');
316  $this->tpl->setVariable('APP_ROWSPAN', $a_app['rowspan']);
317  $time = '';
318  switch ($this->user_settings->getTimeFormat()) {
320  $time = $a_app['event']->getStart()->get(IL_CAL_FKT_DATE, 'H:i', $this->timezone);
321  break;
322 
324  $time = $a_app['event']->getStart()->get(IL_CAL_FKT_DATE, 'h:ia', $this->timezone);
325  break;
326  }
327 
328  $shy = $this->getAppointmentShyButton($a_app['event'], (string) $a_app['dstart'], "");
329 
330  $title = $shy;
331  $content = ($time != "") ? $time . " " . $title : $title;
332  $event_tpl->setVariable('EVENT_CONTENT', $content);
333 
334  $color = $this->app_colors->getColorByAppointment($a_app['event']->getEntryId());
335  $event_tpl->setVariable('APP_BGCOLOR', $color);
336  $event_tpl->setVariable('APP_COLOR', ilCalendarUtil::calculateFontColor($color));
337  $event_tpl->setVariable('APP_ADD_STYLES', $a_app['event']->getPresentationStyle());
338 
339  $this->ctrl->clearParametersByClass('ilcalendarappointmentgui');
340  $this->ctrl->setParameterByClass('ilcalendarappointmentgui', 'seed', $this->seed->get(IL_CAL_DATE));
341  $this->ctrl->setParameterByClass('ilcalendarappointmentgui', 'app_id', $a_app['event']->getEntryId());
342  $event_tpl->setVariable('APP_EDIT_LINK', $this->ctrl->getLinkTargetByClass('ilcalendarappointmentgui', 'edit'));
343 
344  if ($event_html_by_plugin = $this->getContentByPlugins(
345  $a_app['event'],
346  $a_app['dstart'],
347  $content,
348  $event_tpl
349  )) {
350  $event_html = $event_html_by_plugin;
351  } else {
352  $event_tpl->parseCurrentBlock();
353  $event_html = $event_tpl->get();
354  }
355 
356  $this->tpl->setCurrentBlock("event_nfd");
357  $this->tpl->setVariable("CONTENT_EVENT_NFD", $event_html);
358  $this->tpl->parseCurrentBlock();
359 
360  $this->num_appointments++;
361  }
362 
366  protected function parseInfoIntoRaster(array $daily_apps, int $morning_aggr, int $evening_aggr, int $raster): array
367  {
368  $hours = array();
369  for ($i = $morning_aggr; $i <= $evening_aggr; $i += $raster) {
370  $hours[$i]['apps_start'] = array();
371  $hours[$i]['apps_num'] = 0;
372 
373  switch ($this->user_settings->getTimeFormat()) {
375  if ($morning_aggr > 0 && $i == $morning_aggr) {
376  $hours[$i]['txt'] = sprintf('%02d:00', 0) . ' - ' .
377  sprintf('%02d:00', ceil(($i + 1) / 60));
378  } else {
379  if (!isset($hours[$i]['txt'])) {
380  $hours[$i]['txt'] = sprintf('%02d:%02d', floor($i / 60), $i % 60);
381  } else {
382  $hours[$i]['txt'] .= sprintf('%02d:%02d', floor($i / 60), $i % 60);
383  }
384  }
385  if ($evening_aggr < 23 * 60 && $i == $evening_aggr) {
386  if (!isset($hours[$i]['txt'])) {
387  $hours[$i]['txt'] = ' - ' . sprintf('%02d:00', 0);
388  } else {
389  $hours[$i]['txt'] .= ' - ' . sprintf('%02d:00', 0);
390  }
391  }
392  break;
393 
395  $this->logger->notice('Morning: ' . $morning_aggr . ' and $i:' . $i);
396  if ($morning_aggr > 0 && $i == $morning_aggr) {
397  $hours[$i]['txt'] =
398  date('h a', mktime(0, 0, 0, 1, 1, 2000)) . ' - ' .
399  date('h a', mktime($this->user_settings->getDayStart(), 0, 0, 1, 1, 2000));
400  } else {
401  $hours[$i]['txt'] = date('h a', mktime((int) floor($i / 60), $i % 60, 0, 1, 1, 2000));
402  }
403  if ($evening_aggr < 23 * 60 && $i == $evening_aggr) {
404  if (!isset($hours[$i]['txt'])) {
405  $hours[$i]['txt'] = ' - ' . date('h a', mktime(0, 0, 0, 1, 1, 2000));
406  } else {
407  $hours[$i]['txt'] .= ' - ' . date('h a', mktime(0, 0, 0, 1, 1, 2000));
408  }
409  }
410  break;
411  }
412  }
413 
414  foreach ($daily_apps as $app) {
415  // fullday appointment are not relavant
416  if ($app['fullday']) {
417  continue;
418  }
419  // start hour for this day
420  #21132 #21636
421  if ($app['start_info']['mday'] != $this->seed_info['mday']) {
422  $start = 0;
423  } else {
424  $start = $app['start_info']['hours'] * 60 + $app['start_info']['minutes'];
425  }
426  #21636
427 
428  // end hour for this day
429  #21132
430  if ($app['end_info']['mday'] != $this->seed_info['mday']) {
431  $end = 23 * 60;
432  } elseif ($app['start_info']['hours'] == $app['end_info']['hours']) {
433  $end = $start + $raster;
434  } else {
435  $end = $app['end_info']['hours'] * 60 + $app['end_info']['minutes'];
436  }
437 
438  if ($start < $morning_aggr) {
439  $start = $morning_aggr;
440  }
441  if ($end <= $morning_aggr) {
442  $end = $morning_aggr + $raster;
443  }
444  if ($start > $evening_aggr) {
445  $start = $evening_aggr;
446  }
447  if ($end > $evening_aggr + $raster) {
448  $end = $evening_aggr + $raster;
449  }
450  if ($end <= $start) {
451  $end = $start + $raster;
452  }
453 
454  // map start and end to raster
455  $start = floor($start / $raster) * $raster;
456  $end = ceil($end / $raster) * $raster;
457 
458  $first = true;
459  for ($i = $start; $i < $end; $i += $raster) {
460  if ($first) {
461  $app['rowspan'] = ceil(($end - $start) / $raster);
462  $hours[$i]['apps_start'][] = $app;
463  $first = false;
464  }
465  $hours[$i]['apps_num']++;
466  }
467  }
468  return $hours;
469  }
470 
471  protected function calculateColspan(array $hours): int
472  {
473  $colspan = 1;
474  foreach ($hours as $hour) {
475  $colspan = max($colspan, $hour['apps_num'] + 1);
476  }
477  return max($colspan, 2);
478  }
479 }
calculateColspan(array $hours)
static _getInstance(ilDate $seed, array $a_app)
get singleton instance
$app
Definition: cli.php:39
static get(string $a_var)
array $settings
Setting values (LTI parameters, custom parameters and local parameters).
Definition: System.php:200
ilCalendarUserSettings $user_settings
const ANONYMOUS_USER_ID
Definition: constants.php:27
static _numericMonthToString(int $a_month, bool $a_long=true)
numeric month to string
getContentByPlugins(ilCalendarEntry $a_cal_entry, int $a_start_date, string $a_content, ilTemplate $a_tpl)
static getImagePath(string $img, string $module_path="", string $mode="output", bool $offline=false)
get image path (for images located in a template directory)
parseInfoIntoRaster(array $daily_apps, int $morning_aggr, int $evening_aggr, int $raster)
calculate overlapping hours
const IL_CAL_UNIX
__construct(ilDate $seed_date)
static _getInstanceByUserId(int $a_user_id)
global $DIC
Definition: feed.php:28
showFulldayAppointment(array $a_app)
const IL_CAL_FKT_DATE
static initDragDrop(?ilGlobalTemplateInterface $a_main_tpl=null)
Init YUI Drag and Drop used in Modules/Survey, Services/Calendar, Services/COPage, Services/Form (Jan 2022)
static _numericDayToString(int $a_day, bool $a_long=true)
ilCalendarAppointmentColors $app_colors
const IL_CAL_FKT_GETDATE
const IL_CAL_DATE
Administrate calendar appointments.
__construct(Container $dic, ilPlugin $plugin)
static calculateFontColor(string $a_html_color_code)
Calculate best font color from html hex color code.
show()
fill data section protected
getAppointmentShyButton(ilCalendarEntry $a_calendar_entry, string $a_dstart, string $a_title_forced="")
initialize(int $a_calendar_presentation_type)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
$i
Definition: metadata.php:41
Represents a list of calendar appointments (including recurring events) for a specific user in a give...