1<?php
2/* Copyright (c) 1998-2014 ILIAS open source, Extended GPL, see docs/LICENSE */
3
4use Psr\Http\Message\RequestInterface;
5use Psr\Http\Message\ServerRequestInterface;
6
7/**
8 * Administrate calendar appointments
9 * @author  Stefan Meyer <smeyer.ilias@gmx.de>
10 * @ingroup ServicesCalendar
11 */
12class ilCalendarAppointmentGUI
13{
14    protected $seed = null;
15    protected $initialDate = null;
16    protected $default_fulltime = true;
17
18    protected $app = null;
19    protected $rec = null;
20    protected $timezone = null;
21
22    protected $tpl;
23    protected $lng;
24    protected $ctrl;
25
26    /**
27     * @var RequestInterface|ServerRequestInterface
28     */
29    protected $request;
30
31    /**
32     * @var \ilLogger
33     */
34    private $logger = null;
35
36    /**
37     * @todo make appointment_id required and remove all GET request
38     *
39     * @access public
40     * @param ilDate seed
41     * @return
42     */
43    public function __construct(ilDate $seed, ilDate $initialDate, $a_appointment_id = 0)
44    {
45        global $DIC;
46
47        $this->lng = $DIC->language();
48        $this->lng->loadLanguageModule('dateplaner');
49        $this->ctrl = $DIC->ctrl();
50        $this->tpl = $DIC->ui()->mainTemplate();
51        $this->logger = $GLOBALS['DIC']->logger()->cal();
52        $this->request = $DIC->http()->request();
53
54        $this->initTimeZone();
55        $this->initSeed($seed);
56        $this->initInitialDate($initialDate);
57        $this->initAppointment($a_appointment_id);
58    }
59
60    public function executeCommand()
61    {
62        global $DIC;
63
64        $ilUser = $DIC['ilUser'];
65        $ilSetting = $DIC['ilSetting'];
66        $tpl = $DIC['tpl'];
67        $ilTabs = $DIC['ilTabs'];
68
69
70        // Clear tabs and set back target
71        $ilTabs->clearTargets();
72        $ilTabs->setBackTarget(
73            $this->lng->txt('cal_back_to_cal'),
74            $this->ctrl->getLinkTarget($this, 'cancel')
75        );
76
77        $next_class = $this->ctrl->getNextClass($this);
78        switch ($next_class) {
79
80            default:
81                $cmd = $this->ctrl->getCmd("add");
82                $this->$cmd();
83                break;
84        }
85
86    }
87
88    /**
89     * Get current appointment
90     * @return ilCalendarEntry
91     */
92    public function getAppointment()
93    {
94        return $this->app;
95    }
96
97    /**
98     * cancel editing
99     *
100     * @access protected
101     * @param
102     * @return
103     */
104    protected function cancel()
105    {
106        $this->ctrl->returnToParent($this);
107    }
108
109    /**
110     * init form
111     *
112     * @access protected
113     * @param string mode ('edit' | 'create')
114     * @return
115     */
116    protected function initForm($a_mode, $a_as_milestone = false, $a_edit_single_app = false)
117    {
118        global $DIC;
119
120        $ilUser = $DIC['ilUser'];
121        $tpl = $DIC['tpl'];
122
123        $this->form = new ilPropertyFormGUI();
124
125        include_once('./Services/YUI/classes/class.ilYuiUtil.php');
126        ilYuiUtil::initDomEvent();
127        $resp_info = false;
128        switch ($a_mode) {
129            case 'create':
130                $this->ctrl->saveParameter($this, array('seed','idate'));
131                $this->form->setFormAction($this->ctrl->getFormAction($this));
132                if ($a_as_milestone) {
133                    $this->form->setTitle($this->lng->txt('cal_new_ms'));
134                    $this->form->addCommandButton('saveMilestone', $this->lng->txt('cal_add_milestone'));
135                    $this->form->addCommandButton('cancel', $this->lng->txt('cancel'));
136                } else {
137                    $this->form->setTitle($this->lng->txt('cal_new_app'));
138                    $this->form->addCommandButton('save', $this->lng->txt('cal_add_appointment'));
139                    $this->form->addCommandButton('cancel', $this->lng->txt('cancel'));
140                }
141                break;
142
143            case 'edit':
144                if ($a_as_milestone) {
145                    $this->form->setTitle($this->lng->txt('cal_edit_milestone'));
146                } else {
147                    $this->form->setTitle($this->lng->txt('cal_edit_appointment'));
148                }
149                $this->ctrl->saveParameter($this, array('seed','app_id','idate'));
150                $this->form->setFormAction($this->ctrl->getFormAction($this));
151
152                $ass = new ilCalendarCategoryAssignments($this->app->getEntryId());
153                $cat = $ass->getFirstAssignment();
154                include_once('./Services/Calendar/classes/class.ilCalendarCategory.php');
155                $cat_info = ilCalendarCategories::_getInstance()->getCategoryInfo($cat);
156                $type = ilObject::_lookupType($cat_info['obj_id']);
157                if ($a_as_milestone && $cat_info['type'] == ilCalendarCategory::TYPE_OBJ
158                    && ($type == "grp" || $type == "crs")) {
159                    $resp_info = true;
160                    $this->form->addCommandButton('editResponsibleUsers', $this->lng->txt('cal_change_responsible_users'));
161                }
162                $this->form->addCommandButton('update', $this->lng->txt('save'));
163                // $this->form->addCommandButton('askDelete',$this->lng->txt('delete'));
164                $this->form->addCommandButton('cancel', $this->lng->txt('cancel'));
165                break;
166        }
167        // title
168        $title = new ilTextInputGUI($this->lng->txt('title'), 'title');
169        $title->setValue($this->app->getTitle());
170        $title->setRequired(true);
171        $title->setMaxLength(128);
172        $title->setSize(32);
173        $this->form->addItem($title);
174
175        // calendar selection
176        $calendar = new ilSelectInputGUI($this->lng->txt('cal_category_selection'), 'calendar');
177        if ($_POST['category']) {
178            $calendar->setValue((int) $_POST['calendar']);
179            $selected_calendar = (int) $_POST['calendar'];
180        } elseif ($_GET['category_id']) {
181            $calendar->setValue((int) $_GET['category_id']);
182            $selected_calendar = (int) $_GET['category_id'];
183        } elseif ($a_mode == 'edit') {
184            $ass = new ilCalendarCategoryAssignments($this->app->getEntryId());
185            $cat = $ass->getFirstAssignment();
186            $calendar->setValue($cat);
187            $selected_calendar = $cat;
188        } elseif (isset($_GET['ref_id'])) {
189            include_once('./Services/Calendar/classes/class.ilCalendarCategories.php');
190            $obj_cal = ilObject::_lookupObjId($_GET['ref_id']);
191            $calendar->setValue(ilCalendarCategories::_lookupCategoryIdByObjId($obj_cal));
192            $selected_calendar = ilCalendarCategories::_lookupCategoryIdByObjId($obj_cal);
193            $cats = ilCalendarCategories::_getInstance($ilUser->getId());
194            $cats->readSingleCalendar($selected_calendar);
195        } else {
196            $cats = ilCalendarCategories::_getInstance($ilUser->getId());
197            $categories = $cats->prepareCategoriesOfUserForSelection();
198            $selected_calendar = key((array) $categories);
199            $calendar->setValue($selected_calendar);
200        }
201        $calendar->setRequired(true);
202        $cats = ilCalendarCategories::_getInstance($ilUser->getId());
203        $calendar->setOptions($cats->prepareCategoriesOfUserForSelection());
204
205        include_once './Services/Calendar/classes/class.ilCalendarSettings.php';
206        if (ilCalendarSettings::_getInstance()->isNotificationEnabled()) {
207            $notification_cals = $cats->getNotificationCalendars();
208            $notification_cals = count($notification_cals) ? implode(',', $notification_cals) : '';
209            $calendar->addCustomAttribute("onchange=\"ilToggleNotification([" . $notification_cals . "]);\"");
210        }
211        $this->form->addItem($calendar);
212
213        if (!$a_as_milestone) {
214            include_once './Services/Form/classes/class.ilDateDurationInputGUI.php';
215            $tpl->addJavaScript('./Services/Form/js/date_duration.js');
216            $dur = new ilDateDurationInputGUI($this->lng->txt('cal_fullday'), 'event');
217            $dur->setRequired(true);
218            $dur->enableToggleFullTime(
219                $this->lng->txt('cal_fullday_title'),
220                $this->app->isFullday() ? true : false
221            );
222            $dur->setShowTime(true);
223            $dur->setStart($this->app->getStart());
224            $dur->setEnd($this->app->getEnd());
225            $this->form->addItem($dur);
226
227            // recurrence
228            include_once('./Services/Calendar/classes/Form/class.ilRecurrenceInputGUI.php');
229            $rec = new ilRecurrenceInputGUI($this->lng->txt('cal_recurrences'), 'frequence');
230            $rec->setRecurrence($this->rec);
231            $this->form->addItem($rec);
232
233            // location
234            $where = new ilTextInputGUI($this->lng->txt('cal_where'), 'location');
235            $where->setValue($this->app->getLocation());
236            $where->setMaxLength(128);
237            $where->setSize(32);
238            $this->form->addItem($where);
239        } else {
240            $deadline = new ilDateTimeInputGUI($this->lng->txt('cal_deadline'), 'event_start');
241            $deadline->setDate($this->app->getStart());
242            $deadline->setShowTime(false);
243            $deadline->setMinuteStepSize(5);
244            $this->form->addItem($deadline);
245
246            // completion
247            $completion_vals = array();
248            for ($i = 0; $i <= 100; $i += 5) {
249                $completion_vals[$i] = $i . " %";
250            }
251            $compl = new ilSelectInputGUI(
252                $this->lng->txt('cal_task_completion'),
253                'completion'
254            );
255            $compl->setOptions($completion_vals);
256            $compl->setValue($this->app->getCompletion());
257            $this->form->addItem($compl);
258        }
259
260        $desc = new ilTextAreaInputGUI($this->lng->txt('description'), 'description');
261        $desc->setValue($this->app->getDescription());
262        $desc->setRows(5);
263        $this->form->addItem($desc);
264
265        if ($a_as_milestone && $a_mode == "edit" && $resp_info) {
266            // users responsible
267            $users = $this->app->readResponsibleUsers();
268            $resp = new ilNonEditableValueGUI($this->lng->txt('cal_responsible'), "", true);
269            $delim = "";
270            foreach ($users as $r) {
271                $value .= $delim . $r["lastname"] . ", " . $r["firstname"] . " [" . $r["login"] . "]";
272                $delim = "<br />";
273            }
274            if (count($users) > 0) {
275                $resp->setValue($value);
276            } else {
277                $resp->setValue("-");
278            }
279
280            $this->form->addItem($resp);
281        }
282
283
284        if (ilCalendarSettings::_getInstance()->isUserNotificationEnabled()) {
285            $notu = new ilTextWizardInputGUI($this->lng->txt('cal_user_notification'), 'notu');
286            $notu->setInfo($this->lng->txt('cal_user_notification_info'));
287            $notu->setSize(20);
288            $notu->setMaxLength(64);
289
290            $values = array();
291            foreach ($this->notification->getRecipients() as $rcp) {
292                switch ($rcp['type']) {
293                    case ilCalendarUserNotification::TYPE_USER:
294                        $values[] = ilObjUser::_lookupLogin($rcp['usr_id']);
295                        break;
296
297                    case ilCalendarUserNotification::TYPE_EMAIL:
298                        $values[] = $rcp['email'];
299                        break;
300                }
301            }
302            if (count($values)) {
303                $notu->setValues($values);
304            } else {
305                $notu->setValues(array(''));
306            }
307            $this->form->addItem($notu);
308        }
309
310        // Notifications
311        include_once './Services/Calendar/classes/class.ilCalendarSettings.php';
312        if (ilCalendarSettings::_getInstance()->isNotificationEnabled() and count($cats->getNotificationCalendars())) {
313            $selected_cal = new ilCalendarCategory($selected_calendar);
314            $disabled = true;
315            if ($selected_cal->getType() == ilCalendarCategory::TYPE_OBJ) {
316                if (ilObject::_lookupType($selected_cal->getObjId()) == 'crs' or ilObject::_lookupType($selected_cal->getObjId()) == 'grp') {
317                    $disabled = false;
318                }
319            }
320
321            $tpl->addJavaScript('./Services/Calendar/js/toggle_notification.js');
322            $not = new ilCheckboxInputGUI($this->lng->txt('cal_cg_notification'), 'not');
323            $not->setInfo($this->lng->txt('cal_notification_info'));
324            $not->setValue(1);
325            $not->setChecked($this->app->isNotificationEnabled());
326            $not->setDisabled($disabled);
327            $this->form->addItem($not);
328        }
329    }
330
331
332    /**
333     * add new appointment
334     *
335     * @param \ilPropertyFormGUI $form
336     * @access protected
337     * @return
338     */
339    protected function add(ilPropertyFormGUI $form = null)
340    {
341        global $DIC;
342
343        $ilHelp = $DIC->help();
344
345        $ilHelp->setScreenIdComponent("cal");
346        $ilHelp->setScreenId("app");
347        $ilHelp->setSubScreenId("create");
348
349        if (!$form instanceof ilPropertyFormGUI) {
350            $this->initForm('create');
351        }
352        $this->tpl->setContent($this->form->getHTML());
353    }
354
355    /**
356     * add milestone
357     *
358     * @access protected
359     * @return
360     */
361    protected function addMilestone()
362    {
363        global $DIC;
364
365        $tpl = $DIC['tpl'];
366        $ilHelp = $DIC['ilHelp'];
367
368        $ilHelp->setScreenIdComponent("cal");
369        $ilHelp->setScreenId("app");
370        $ilHelp->setSubScreenId("create_milestone");
371
372        $this->initForm('create', true);
373        $tpl->setContent($this->form->getHTML());
374    }
375
376    /**
377     * save milestone
378     *
379     * @access protected
380     */
381    protected function saveMilestone()
382    {
383        $this->save(true);
384    }
385
386    /**
387     * save appointment
388     *
389     * @access protected
390     */
391    protected function save($a_as_milestone = false)
392    {
393        global $DIC;
394
395        $ilErr = $DIC['ilErr'];
396
397        $this->load('create', $a_as_milestone);
398
399        if ($this->app->validate() and $this->notification->validate()) {
400            if (!(int) $_POST['calendar']) {
401                $cat_id = $this->createDefaultCalendar();
402            } else {
403                $cat_id = (int) $_POST['calendar'];
404            }
405
406            $this->app->save();
407            $this->notification->setEntryId($this->app->getEntryId());
408            $this->notification->save();
409            $this->rec->setEntryId($this->app->getEntryId());
410            $this->saveRecurrenceSettings();
411
412            include_once('./Services/Calendar/classes/class.ilCalendarCategoryAssignments.php');
413            $ass = new ilCalendarCategoryAssignments($this->app->getEntryId());
414            $ass->addAssignment($cat_id);
415
416            // Send notifications
417            include_once './Services/Calendar/classes/class.ilCalendarSettings.php';
418            if (ilCalendarSettings::_getInstance()->isNotificationEnabled() and (bool) $_POST['not']) {
419                $this->distributeNotifications($cat_id, $this->app->getEntryId(), true);
420            }
421            if (ilCalendarSettings::_getInstance()->isUserNotificationEnabled()) {
422                $this->distributeUserNotifications();
423            }
424
425            include_once('./Services/Calendar/classes/class.ilCalendarCategory.php');
426            $cat_info = ilCalendarCategories::_getInstance()->getCategoryInfo($cat_id);
427            $type = ilObject::_lookupType($cat_info['obj_id']);
428
429            if ($a_as_milestone && $cat_info['type'] == ilCalendarCategory::TYPE_OBJ
430                && ($type == "grp" || $type == "crs")) {
431                ilUtil::sendSuccess($this->lng->txt('cal_created_milestone_resp_q'), true);
432                return $this->showResponsibleUsersList($cat_info['obj_id']);
433            } elseif ($a_as_milestone) {
434                ilUtil::sendSuccess($this->lng->txt('cal_created_milestone'), true);
435                $this->ctrl->returnToParent($this);
436            } else {
437                ilUtil::sendSuccess($this->lng->txt('cal_created_appointment'), true);
438                $this->ctrl->returnToParent($this);
439            }
440        } else {
441            $this->form->setValuesByPost();
442            ilUtil::sendFailure($ilErr->getMessage());
443            return $this->add($this->form);
444        }
445        if ($a_as_milestone) {
446            $this->addMilestone();
447        } else {
448            $this->add();
449        }
450    }
451
452    /**
453     * Send mail to selected users
454     * @global ilObjUser $ilUser
455     */
456    protected function distributeUserNotifications()
457    {
458        global $DIC;
459
460        $ilUser = $DIC['ilUser'];
461
462        include_once './Services/Calendar/classes/class.ilCalendarMailNotification.php';
463        $notification = new ilCalendarMailNotification();
464        $notification->setAppointmentId($this->app->getEntryId());
465
466        foreach ($this->notification->getRecipients() as $rcp) {
467            switch ($rcp['type']) {
468                case ilCalendarUserNotification::TYPE_USER:
469                    $notification->setSender(ANONYMOUS_USER_ID);
470                    $notification->setRecipients(array($rcp['usr_id']));
471                    $notification->setType(ilCalendarMailNotification::TYPE_USER);
472                    break;
473
474                case ilCalendarUserNotification::TYPE_EMAIL:
475                    $notification->setSender(ANONYMOUS_USER_ID);
476                    $notification->setRecipients(array($rcp['email']));
477                    $notification->setType(ilCalendarMailNotification::TYPE_USER_ANONYMOUS);
478                    break;
479            }
480            $notification->send();
481        }
482    }
483
484
485    /**
486     * Distribute mail notifications
487     * @return
488     */
489    protected function distributeNotifications($a_cat_id, $app_id, $a_new_appointment = true)
490    {
491        include_once('./Services/Calendar/classes/class.ilCalendarCategory.php');
492        $cat_info = ilCalendarCategories::_getInstance()->getCategoryInfo($a_cat_id);
493
494        include_once './Services/Calendar/classes/class.ilCalendarMailNotification.php';
495        $notification = new ilCalendarMailNotification();
496        $notification->setAppointmentId($app_id);
497
498        switch ($cat_info['type']) {
499            case ilCalendarCategory::TYPE_OBJ:
500
501                    switch ($cat_info['obj_type']) {
502                        case 'crs':
503                            $ref_ids = ilObject::_getAllReferences($cat_info['obj_id']);
504                            $ref_id = current($ref_ids);
505                            $notification->setRefId($ref_id);
506                            $notification->setType(
507                                $a_new_appointment ?
508                                ilCalendarMailNotification::TYPE_CRS_NEW_NOTIFICATION :
509                                ilCalendarMailNotification::TYPE_CRS_NOTIFICATION
510                            );
511                            break;
512
513                        case 'grp':
514                            $ref_ids = ilObject::_getAllReferences($cat_info['obj_id']);
515                            $ref_id = current($ref_ids);
516                            $notification->setRefId($ref_id);
517                            $notification->setType(
518                                $a_new_appointment ?
519                                ilCalendarMailNotification::TYPE_GRP_NEW_NOTIFICATION :
520                                ilCalendarMailNotification::TYPE_GRP_NOTIFICATION
521                            );
522                            break;
523                    }
524                    break;
525        }
526
527        $notification->send();
528    }
529
530    /**
531    * Edit responsible users
532    */
533    public function editResponsibleUsers()
534    {
535        include_once('./Services/Calendar/classes/class.ilCalendarCategoryAssignments.php');
536        $cat_id = ilCalendarCategoryAssignments::_lookupCategory($this->app->getEntryId());
537        include_once('./Services/Calendar/classes/class.ilCalendarCategory.php');
538        $cat_info = ilCalendarCategories::_getInstance()->getCategoryInfo($cat_id);
539
540        $this->showResponsibleUsersList($cat_info['obj_id']);
541    }
542
543    /**
544    * Show responsible uses of a milestone (default set is participants
545    * of group)
546    */
547    public function showResponsibleUsersList($a_grp_id)
548    {
549        global $DIC;
550
551        $tpl = $DIC['tpl'];
552
553        include_once("./Services/Calendar/classes/class.ilMilestoneResponsiblesTableGUI.php");
554        $table_gui = new ilMilestoneResponsiblesTableGUI(
555            $this,
556            "",
557            $a_grp_id,
558            $this->app->getEntryId()
559        );
560        $tpl->setContent($table_gui->getHTML());
561    }
562
563    /**
564    * Save milestone responsibilites
565    */
566    public function saveMilestoneResponsibleUsers()
567    {
568        global $DIC;
569
570        $ilCtrl = $DIC['ilCtrl'];
571
572        $this->app->writeResponsibleUsers($_POST["user_id"]);
573        $ilCtrl->returnToParent($this);
574    }
575
576    /**
577     * Check edit single apppointment / edit all appointments for recurring appointments.
578     * @todo works with milestones???
579     */
580    protected function askEdit()
581    {
582        // check for recurring entries
583        include_once './Services/Calendar/classes/class.ilCalendarRecurrences.php';
584        $rec = ilCalendarRecurrences::_getRecurrences($this->getAppointment()->getEntryId());
585        if (!$rec) {
586            return $this->edit(true);
587        }
588        // Show edit single/all appointments
589        $this->ctrl->saveParameter($this, array('seed','app_id','dt','idate'));
590
591        include_once('./Services/Utilities/classes/class.ilConfirmationGUI.php');
592        $confirm = new ilConfirmationGUI();
593        $confirm->setFormAction($this->ctrl->getFormAction($this));
594        #$confirm->setHeaderText($this->lng->txt('cal_edit_app_sure'));
595        $confirm->setCancel($this->lng->txt('cancel'), 'cancel');
596        $confirm->addItem('appointments[]', $this->app->getEntryId(), $this->app->getTitle());
597        $confirm->addButton($this->lng->txt('cal_edit_single'), 'editSingle');
598        $confirm->setConfirm($this->lng->txt('cal_edit_recurrences'), 'edit');
599
600        $GLOBALS['DIC']['tpl']->setContent($confirm->getHTML());
601    }
602
603    /**
604     * Edit one single appointment
605    ^ */
606    protected function editSingle()
607    {
608        $_REQUEST['rexl'] = 1;
609        $GLOBALS['DIC']['ilCtrl']->setParameter($this, 'rexcl', 1);
610        $this->edit(true);
611    }
612
613    /**
614     * edit appointment
615     *
616     * @access protected
617     * @param bool singel appointment
618     * @param \ilPropertyFormGUI
619     * @return
620     */
621    protected function edit($a_edit_single_app = false, ilPropertyFormGUI $form = null)
622    {
623        global $DIC;
624
625        $tpl = $DIC->ui()->mainTemplate();
626        $ilUser = $DIC['ilUser'];
627        $ilErr = $DIC['ilErr'];
628        $ilHelp = $DIC['ilHelp'];
629
630        $ilHelp->setScreenIdComponent("cal");
631        $ilHelp->setScreenId("app");
632        if ($this->app->isMilestone()) {
633            $ilHelp->setSubScreenId("edit_milestone");
634        } else {
635            $ilHelp->setSubScreenId("edit");
636        }
637
638        include_once('./Services/Calendar/classes/class.ilCalendarCategory.php');
639        include_once('./Services/Calendar/classes/class.ilCalendarCategories.php');
640        include_once('./Services/Calendar/classes/class.ilCalendarCategoryAssignments.php');
641
642        $GLOBALS['DIC']['ilCtrl']->saveParameter($this, array('seed','app_id','dt','idate'));
643
644        if ($_REQUEST['rexl']) {
645            $GLOBALS['DIC']['ilCtrl']->setParameter($this, 'rexl', 1);
646
647            // Calculate new appointment time
648            $duration = $this->getAppointment()->getEnd()->get(IL_CAL_UNIX) - $this->getAppointment()->getStart()->get(IL_CAL_UNIX);
649            include_once './Services/Calendar/classes/class.ilCalendarRecurrenceCalculator.php';
650            $calc = new ilCalendarRecurrenceCalculator($this->getAppointment(), $this->rec);
651
652            $current_date = new ilDateTime($_REQUEST['dt'], IL_CAL_UNIX);
653
654            $yesterday = clone $current_date;
655            $yesterday->increment(IL_CAL_DAY, -1);
656            $tomorrow = clone $current_date;
657            $tomorrow->increment(IL_CAL_DAY, 1);
658
659
660            foreach ($calc->calculateDateList($current_date, $tomorrow, 1) as $date_entry) {
661                if (ilDateTime::_equals($current_date, $date_entry, IL_CAL_DAY)) {
662                    $this->getAppointment()->setStart(new ilDateTime($date_entry->get(IL_CAL_UNIX), IL_CAL_UNIX));
663                    $this->getAppointment()->setEnd(new ilDateTime($date_entry->get(IL_CAL_UNIX) + $duration, IL_CAL_UNIX));
664                    break;
665                }
666            }
667
668            // Finally reset recurrence
669            $this->rec = new ilCalendarRecurrence();
670        }
671
672        $cat_id = ilCalendarCategoryAssignments::_lookupCategory($this->app->getEntryId());
673        $cats = ilCalendarCategories::_getInstance($ilUser->getId());
674
675        if (!$cats->isVisible($cat_id)) {
676            $ilErr->raiseError($this->lng->txt('permission_denied'), $ilErr->WARNING);
677            return false;
678        }
679        if (!$cats->isEditable($cat_id) or $this->app->isAutoGenerated()) {
680            $this->showInfoScreen();
681            return true;
682        }
683        if (!$form instanceof ilPropertyFormGUI) {
684            $this->initForm('edit', $this->app->isMilestone(), $a_edit_single_app);
685        }
686        $tpl->setContent($this->form->getHTML());
687    }
688
689    /**
690     * show info screen
691     *
692     * @access protected
693     * @return
694     */
695    protected function showInfoScreen()
696    {
697        global $DIC;
698
699        $tpl = $DIC['tpl'];
700        $ilUser = $DIC['ilUser'];
701
702        include_once("./Services/InfoScreen/classes/class.ilInfoScreenGUI.php");
703        $info = new ilInfoScreenGUI($this);
704        $info->setFormAction($this->ctrl->getFormAction($this));
705
706        if ($this->app->isMilestone()) {
707            $info->addSection($this->lng->txt('cal_ms_details'));
708        } else {
709            $info->addSection($this->lng->txt('cal_details'));
710        }
711
712        // Appointment
713        $info->addProperty(
714            $this->lng->txt('appointment'),
715            ilDatePresentation::formatPeriod(
716                $this->app->getStart(),
717                $this->app->getEnd()
718            )
719        );
720        $info->addProperty($this->lng->txt('title'), $this->app->getPresentationTitle());
721
722        // Description
723        if (strlen($desc = $this->app->getDescription())) {
724            $info->addProperty($this->lng->txt('description'), $desc);
725        }
726
727        // Location
728        if (strlen($loc = $this->app->getLocation())) {
729            $info->addProperty($this->lng->txt('cal_where'), $loc);
730        }
731
732        // completion
733        if ($this->app->isMilestone() && $this->app->getCompletion() > 0) {
734            $info->addProperty(
735                $this->lng->txt('cal_task_completion'),
736                $this->app->getCompletion() . " %"
737            );
738        }
739
740        include_once('./Services/Calendar/classes/class.ilCalendarCategoryAssignments.php');
741        $cat_id = ilCalendarCategoryAssignments::_lookupCategory($this->app->getEntryId());
742        $cat_info = ilCalendarCategories::_getInstance()->getCategoryInfo($cat_id);
743        $type = ilObject::_lookupType($cat_info['obj_id']);
744        if ($this->app->isMilestone() && $cat_info['type'] == ilCalendarCategory::TYPE_OBJ
745            && ($type == "grp" || $type == "crs")) {
746            // users responsible
747            $users = $this->app->readResponsibleUsers();
748            $delim = "";
749            foreach ($users as $r) {
750                $value .= $delim . $r["lastname"] . ", " . $r["firstname"] . " [" . $r["login"] . "]";
751                $delim = "<br />";
752            }
753            if (count($users) > 0) {
754                $info->addProperty(
755                    $this->lng->txt('cal_responsible'),
756                    $value
757                );
758            }
759        }
760
761        $category = new ilCalendarCategory($cat_id);
762
763        if ($category->getType() == ilCalendarCategory::TYPE_OBJ) {
764            $info->addSection($this->lng->txt('additional_info'));
765
766            $cat_info = ilCalendarCategories::_getInstance()->getCategoryInfo($cat_id);
767            $refs = ilObject::_getAllReferences($cat_info['obj_id']);
768
769            include_once('./Services/Link/classes/class.ilLink.php');
770            $href = ilLink::_getStaticLink(current($refs), ilObject::_lookupType($cat_info['obj_id']), true);
771            $info->addProperty($this->lng->txt('perma_link'), '<a class="small" href="' . $href . '" target="_top">' . $href . '</a>');
772        }
773
774        $tpl->setContent($info->getHTML());
775    }
776
777    /**
778     * update
779     *
780     * @access protected
781     * @return
782     */
783    protected function update()
784    {
785        global $DIC;
786
787        $ilErr = $DIC['ilErr'];
788
789        $single_editing = ($_REQUEST['rexl'] ? true : false);
790
791        $this->load('edit', $this->app->isMilestone());
792
793        if ($this->app->validate() and $this->notification->validate()) {
794            if (!(int) $_POST['calendar']) {
795                $cat_id = $this->createDefaultCalendar();
796            } else {
797                $cat_id = (int) $_POST['calendar'];
798            }
799
800            if ($single_editing) {
801                $original_id = $this->getAppointment()->getEntryId();
802                $this->getAppointment()->save();
803                $selected_ut = (int) ($this->request->getQueryParams()['dt'] ?? 0);
804                if ($selected_ut > 0) {
805                    $exclusion = new ilCalendarRecurrenceExclusion();
806                    $exclusion->setEntryId($original_id);
807                    $exclusion->setDate(new ilDate($selected_ut, IL_CAL_UNIX));
808                    $this->logger->dump($this->getAppointment()->getEntryId());
809                    $this->logger->dump(ilDatePresentation::formatDate(new ilDate($selected_ut, IL_CAL_UNIX)));
810                    $exclusion->save();
811                }
812                $this->rec = new ilCalendarRecurrence();
813                $this->rec->setEntryId($this->getAppointment()->getEntryId());
814            } else {
815                $this->getAppointment()->update();
816            }
817            $this->notification->save();
818            $this->saveRecurrenceSettings();
819            include_once('./Services/Calendar/classes/class.ilCalendarCategoryAssignments.php');
820            $ass = new ilCalendarCategoryAssignments($this->app->getEntryId());
821            $this->logger->debug($this->app->getEntryId());
822            $ass->deleteAssignments();
823            $ass->addAssignment($cat_id);
824
825            // Send notifications
826            include_once './Services/Calendar/classes/class.ilCalendarSettings.php';
827            if (ilCalendarSettings::_getInstance()->isNotificationEnabled() and (bool) $_POST['not']) {
828                $this->distributeNotifications($cat_id, $this->app->getEntryId(), false);
829            }
830            if (ilCalendarSettings::_getInstance()->isUserNotificationEnabled()) {
831                $this->distributeUserNotifications();
832            }
833
834            ilUtil::sendSuccess($this->lng->txt('msg_obj_modified'), true);
835            $this->ctrl->returnToParent($this);
836        } else {
837            $this->form->setValuesByPost();
838            ilUtil::sendFailure($ilErr->getMessage());
839        }
840        $this->edit(false, $this->form);
841    }
842
843    /**
844     * ask delete
845     *
846     * @access protected
847     * @return
848     */
849    protected function askDelete()
850    {
851        global $DIC;
852
853        $tpl = $DIC['tpl'];
854
855        $this->ctrl->saveParameter(
856            $this,
857            [
858                'seed',
859                'app_id',
860                'dt',
861                'idate'
862            ]
863        );
864
865        $app_id = (int) ($this->request->getQueryParams()['app_id'] ?? 0);
866        if (!$app_id) {
867            ilUtil::sendFailure($this->lng->txt('err_check_input'));
868            $this->ctrl->returnToParent($this);
869        }
870
871        $entry = new ilCalendarEntry($app_id);
872        $recs = ilCalendarRecurrences::_getRecurrences($app_id);
873        if (
874            !count($recs) &&
875            !$this->app->isMilestone()
876        ) {
877            $confirm = new ilConfirmationGUI();
878            $confirm->setFormAction($this->ctrl->getFormAction($this));
879            $confirm->setHeaderText($this->lng->txt('cal_delete_app_sure'));
880            $confirm->setCancel($this->lng->txt('cancel'), 'cancel');
881            $confirm->addItem('appointments[]', $this->app->getEntryId(), $this->app->getTitle());
882            $confirm->setConfirm($this->lng->txt('delete'), 'delete');
883            $this->tpl->setContent($confirm->getHTML());
884        } else {
885
886            $table = new ilCalendarRecurrenceTableGUI(
887                $this->app,
888                $this,
889                'askDelete'
890            );
891            $table->init();
892            $table->parse();
893            $this->tpl->setContent($table->getHTML());
894            ilUtil::sendQuestion($this->lng->txt('cal_delete_app_sure'));
895            ilUtil::sendInfo($this->lng->txt('cal_recurrence_confirm_deletion'));
896        }
897    }
898
899    /**
900     * delete
901     *
902     * @access protected
903     * @param
904     * @return
905     */
906    protected function delete()
907    {
908        $app_ids = (array) ($this->request->getParsedBody()['appointment_ids'] ?? []);
909        if (!$app_ids) {
910            $this->logger->dump($app_ids);
911            $app_ids = (array) ($this->request->getQueryParams()['app_id'] ?? []);
912        }
913        if (!$app_ids) {
914            $this->ctrl->returnToParent($this);
915        }
916        foreach ($app_ids as $app_id) {
917            $app = new ilCalendarEntry($app_id);
918            $app->delete();
919
920            include_once('./Services/Calendar/classes/class.ilCalendarCategoryAssignments.php');
921            ilCalendarCategoryAssignments::_deleteByAppointmentId($app_id);
922
923            include_once './Services/Calendar/classes/class.ilCalendarUserNotification.php';
924            ilCalendarUserNotification::deleteCalendarEntry($app_id);
925        }
926        ilUtil::sendSuccess($this->lng->txt('cal_deleted_app'), true);
927        $this->ctrl->returnToParent($this);
928    }
929
930    /**
931     * delete single item of recurrence list
932     *
933     * @access protected
934     * @param
935     * @return
936     */
937    protected function deleteExclude($a_return = true)
938    {
939        $recurrence_ids = (array) ($this->request->getParsedBody()['recurrence_ids'] ?? []);
940        $app_id = (int) ($this->request->getQueryParams()['app_id'] ?? 0);
941        if (!count($recurrence_ids)) {
942            ilUtil::sendFailure($this->lng->txt('select_one'), true);
943            $this->ctrl->redirect($this, 'askDelete');
944        }
945        if (!$app_id) {
946            $this->ctrl->returnToParent($this);
947        }
948        foreach ($recurrence_ids as $rdate) {
949            $exclusion = new ilCalendarRecurrenceExclusion();
950            $exclusion->setEntryId($app_id);
951            $exclusion->setDate(new ilDate($rdate, IL_CAL_UNIX));
952            $exclusion->save();
953        }
954        if ($a_return) {
955            ilUtil::sendSuccess($this->lng->txt('cal_deleted_app'), true);
956            $this->ctrl->returnToParent($this);
957        }
958    }
959
960    /**
961     * init timezone
962     *
963     * @access protected
964     * @param
965     * @return
966     */
967    protected function initTimeZone()
968    {
969        global $DIC;
970
971        $ilUser = $DIC['ilUser'];
972
973        $this->timezone = $ilUser->getTimeZone();
974    }
975
976    /**
977     * init initial date
978     * @param ilDate $initialDate
979     */
980    protected function initInitialDate(ilDate $initialDate)
981    {
982        if (!isset($_GET['hour'])) {
983            $this->initialDate = clone $initialDate;
984            $this->default_fulltime = true;
985        } else {
986            if ((int) $_GET['hour'] < 10) {
987                $time = '0' . (int) $_GET['hour'] . ':00:00';
988            } else {
989                $time = (int) $_GET['hour'] . ':00:00';
990            }
991            $this->initialDate = new ilDateTime($initialDate->get(IL_CAL_DATE) . ' ' . $time, IL_CAL_DATETIME, $this->timezone);
992            $this->default_fulltime = false;
993        }
994    }
995
996    /**
997     * init seed
998     *
999     * @access protected
1000     * @param
1001     * @return
1002     */
1003    protected function initSeed(ilDate $seed)
1004    {
1005        $this->seed = clone $seed;
1006        $this->default_fulltime = true;
1007    }
1008
1009    /**
1010     * init appointment
1011     *
1012     * @access protected
1013     * @param int appointment id
1014     * @return
1015     */
1016    protected function initAppointment($a_app_id = 0)
1017    {
1018        include_once('./Services/Calendar/classes/class.ilCalendarEntry.php');
1019        include_once('./Services/Calendar/classes/class.ilCalendarRecurrences.php');
1020        $this->app = new ilCalendarEntry($a_app_id);
1021
1022        include_once './Services/Calendar/classes/class.ilCalendarUserNotification.php';
1023        $this->notification = new ilCalendarUserNotification($this->app->getEntryId());
1024
1025        if (!$a_app_id) {
1026            $start = clone $this->initialDate;
1027            $this->app->setStart($start);
1028
1029            $seed_end = clone $this->initialDate;
1030            if ($this->default_fulltime) {
1031                #$seed_end->increment(IL_CAL_DAY,1);
1032            } else {
1033                $seed_end->increment(IL_CAL_HOUR, 1);
1034            }
1035            $this->app->setEnd($seed_end);
1036            $this->app->setFullday($this->default_fulltime);
1037
1038            $this->rec = new ilCalendarRecurrence();
1039        } else {
1040            $this->rec = ilCalendarRecurrences::_getFirstRecurrence($this->app->getEntryId());
1041        }
1042    }
1043
1044    /**
1045     * load post
1046     *
1047     * @access protected
1048     * @param
1049     * @return
1050     */
1051    protected function load($a_mode, $a_as_milestone = false)
1052    {
1053        // needed for date handling
1054        $this->initForm($a_mode, $a_as_milestone);
1055        $this->form->checkInput();
1056
1057        if ($a_as_milestone) {
1058            $this->app->setMilestone(true);
1059            $this->app->setCompletion(ilUtil::stripSlashes($_POST['completion']));
1060        }
1061
1062        $this->app->setTitle(ilUtil::stripSlashes($_POST['title']));
1063        $this->app->setLocation(ilUtil::stripSlashes($_POST['location']));
1064        $this->app->setDescription(ilUtil::stripSlashes($_POST['description']));
1065        $this->app->setTitle(ilUtil::stripSlashes($_POST['title']));
1066        $this->app->enableNotification((int) $_POST['not']);
1067
1068        if ($a_as_milestone) {	// milestones are always fullday events
1069            $start = $this->form->getItemByPostVar('event_start');
1070            $start = $start->getDate();
1071
1072            $this->app->setFullday(true);
1073
1074            // for milestones is end date = start date
1075            $this->app->setStart($start);
1076            $this->app->setEnd($start);
1077        } else {
1078            $period = $this->form->getItemByPostVar('event');
1079            $start = $period->getStart();
1080            $end = $period->getEnd();
1081
1082            $this->app->setFullday($start instanceof ilDate);
1083            $this->app->setStart($start);
1084            $this->app->setEnd($end);
1085        }
1086
1087        $this->loadNotificationRecipients();
1088        $this->loadRecurrenceSettings($a_as_milestone = false);
1089    }
1090
1091    protected function loadNotificationRecipients()
1092    {
1093        $this->notification->setRecipients(array());
1094
1095        foreach ((array) $_POST['notu'] as $rcp) {
1096            $rcp = trim(ilUtil::stripSlashes($rcp));
1097            $usr_id = ilObjUser::_loginExists($rcp);
1098
1099            if (strlen($rcp) == 0) {
1100                continue;
1101            }
1102
1103            if ($usr_id) {
1104                $this->notification->addRecipient(
1105                    ilCalendarUserNotification::TYPE_USER,
1106                    $usr_id
1107                );
1108            } else {
1109                $this->notification->addRecipient(
1110                    ilCalendarUserNotification::TYPE_EMAIL,
1111                    0,
1112                    $rcp
1113                );
1114            }
1115        }
1116    }
1117
1118    /**
1119     * load recurrence settings
1120     *
1121     * @access protected
1122     * @return
1123     */
1124    protected function loadRecurrenceSettings($a_as_milestone = false)
1125    {
1126        $this->rec->reset();
1127
1128        switch ($_POST['frequence']) {
1129            case IL_CAL_FREQ_DAILY:
1130                $this->rec->setFrequenceType($_POST['frequence']);
1131                $this->rec->setInterval((int) $_POST['count_DAILY']);
1132                break;
1133
1134            case IL_CAL_FREQ_WEEKLY:
1135                $this->rec->setFrequenceType($_POST['frequence']);
1136                $this->rec->setInterval((int) $_POST['count_WEEKLY']);
1137                if (is_array($_POST['byday_WEEKLY'])) {
1138                    $this->rec->setBYDAY(ilUtil::stripSlashes(implode(',', $_POST['byday_WEEKLY'])));
1139                }
1140                break;
1141
1142            case IL_CAL_FREQ_MONTHLY:
1143                $this->rec->setFrequenceType($_POST['frequence']);
1144                $this->rec->setInterval((int) $_POST['count_MONTHLY']);
1145                switch ((int) $_POST['subtype_MONTHLY']) {
1146                    case 0:
1147                        // nothing to do;
1148                        break;
1149
1150                    case 1:
1151                        switch ((int) $_POST['monthly_byday_day']) {
1152                            case 8:
1153                                // Weekday
1154                                $this->rec->setBYSETPOS((int) $_POST['monthly_byday_num']);
1155                                $this->rec->setBYDAY('MO,TU,WE,TH,FR');
1156                                break;
1157
1158                            case 9:
1159                                // Day of month
1160                                $this->rec->setBYMONTHDAY((int) $_POST['monthly_byday_num']);
1161                                break;
1162
1163                            default:
1164                                $this->rec->setBYDAY((int) $_POST['monthly_byday_num'] . $_POST['monthly_byday_day']);
1165                                break;
1166                        }
1167                        break;
1168
1169                    case 2:
1170                        $this->rec->setBYMONTHDAY((int) $_POST['monthly_bymonthday']);
1171                        break;
1172                }
1173                break;
1174
1175            case IL_CAL_FREQ_YEARLY:
1176                $this->rec->setFrequenceType($_POST['frequence']);
1177                $this->rec->setInterval((int) $_POST['count_YEARLY']);
1178                switch ((int) $_POST['subtype_YEARLY']) {
1179                    case 0:
1180                        // nothing to do;
1181                        break;
1182
1183                    case 1:
1184                        $this->rec->setBYMONTH((int) $_POST['yearly_bymonth_byday']);
1185                        $this->rec->setBYDAY((int) $_POST['yearly_byday_num'] . $_POST['yearly_byday']);
1186                        break;
1187
1188                    case 2:
1189                        $this->rec->setBYMONTH((int) $_POST['yearly_bymonth_by_monthday']);
1190                        $this->rec->setBYMONTHDAY((int) $_POST['yearly_bymonthday']);
1191                        break;
1192                }
1193                break;
1194        }
1195
1196        // UNTIL
1197        switch ((int) $_POST['until_type']) {
1198            case 1:
1199                $this->rec->setFrequenceUntilDate(null);
1200                // nothing to do
1201                break;
1202
1203            case 2:
1204                $this->rec->setFrequenceUntilDate(null);
1205                $this->rec->setFrequenceUntilCount((int) $_POST['count']);
1206                break;
1207
1208            case 3:
1209                $dt = new ilDateTimeInputGUI('', 'until_end');
1210                $dt->setRequired(true);
1211                if ($dt->checkInput()) {
1212                    $this->rec->setFrequenceUntilCount(0);
1213                    $this->rec->setFrequenceUntilDate($dt->getDate());
1214                }
1215                break;
1216        }
1217    }
1218
1219    /**
1220     * save recurrence settings
1221     *
1222     * @access protected
1223     * @param
1224     * @return
1225     */
1226    protected function saveRecurrenceSettings()
1227    {
1228        switch ($_POST['frequence']) {
1229            case 'NONE':
1230            case '':
1231                // No recurrence => delete if there is an recurrence rule
1232                if ($this->rec->getRecurrenceId()) {
1233                    $this->rec->delete();
1234                }
1235                break;
1236
1237            default:
1238                if ($this->rec->getRecurrenceId()) {
1239                    $this->rec->update();
1240                } else {
1241                    $this->rec->save();
1242                }
1243                break;
1244        }
1245    }
1246
1247    /**
1248     * Create a default calendar
1249     *
1250     * @access protected
1251     * @return
1252     */
1253    protected function createDefaultCalendar()
1254    {
1255        global $DIC;
1256
1257        $ilUser = $DIC['ilUser'];
1258        $lng = $DIC['lng'];
1259
1260        $cat = new ilCalendarCategory();
1261        $cat->setColor(ilCalendarCategory::DEFAULT_COLOR);
1262        $cat->setType(ilCalendarCategory::TYPE_USR);
1263        $cat->setTitle($this->lng->txt('cal_default_calendar'));
1264        $cat->setObjId($ilUser->getId());
1265
1266        // delete calendar cache
1267        include_once './Services/Calendar/classes/class.ilCalendarCache.php';
1268        ilCalendarCache::getInstance()->deleteUserEntries($ilUser->getId());
1269
1270        return $cat->add();
1271    }
1272
1273    /**
1274     * Register to an appointment
1275     * @return
1276     */
1277    protected function confirmRegister()
1278    {
1279        global $DIC;
1280
1281        $tpl = $DIC['tpl'];
1282
1283        $entry = new ilCalendarEntry((int) $_GET['app_id']);
1284        $start = ilDatePresentation::formatDate(
1285            new ilDateTime($_GET['dstart'], IL_CAL_UNIX),
1286            new ilDateTime($_GET['dend'], IL_CAL_UNIX)
1287        );
1288
1289
1290        include_once 'Services/Utilities/classes/class.ilConfirmationGUI.php';
1291        $conf = new ilConfirmationGUI;
1292
1293        $this->ctrl->setParameter($this, 'dstart', (int) $_REQUEST['dstart']);
1294        $this->ctrl->setParameter($this, 'dend', (int) $_REQUEST['dend']);
1295
1296        $conf->setFormAction($this->ctrl->getFormAction($this));
1297        $conf->setHeaderText($this->lng->txt('cal_confirm_reg_info'));
1298        $conf->setConfirm($this->lng->txt('cal_reg_register'), 'register');
1299        $conf->setCancel($this->lng->txt('cancel'), 'cancel');
1300        $conf->addItem('app_id', $entry->getEntryId(), $entry->getTitle() . ' (' . $start . ')');
1301
1302        $tpl->setContent($conf->getHTML());
1303    }
1304
1305    /**
1306     * Register
1307     * @return
1308     */
1309    protected function register()
1310    {
1311        global $DIC;
1312
1313        $ilUser = $DIC['ilUser'];
1314
1315        include_once './Services/Calendar/classes/class.ilCalendarRegistration.php';
1316        $reg = new ilCalendarRegistration((int) $_POST['app_id']);
1317        $reg->register(
1318            $ilUser->getId(),
1319            new ilDateTime((int) $_REQUEST['dstart'], IL_CAL_UNIX),
1320            new ilDateTime((int) $_REQUEST['dend'], IL_CAL_UNIX)
1321        );
1322
1323        ilUtil::sendSuccess($this->lng->txt('cal_reg_registered'), true);
1324        $this->ctrl->returnToParent($this);
1325    }
1326
1327    /**
1328     * Confirmation screen to unregister calendar
1329     */
1330    public function confirmUnregister()
1331    {
1332        global $DIC;
1333
1334        $tpl = $DIC['tpl'];
1335
1336
1337        $entry = new ilCalendarEntry((int) $_GET['app_id']);
1338        $start = ilDatePresentation::formatDate(
1339            $dstart = new ilDateTime($_GET['dstart'], IL_CAL_UNIX),
1340            $dend = new ilDateTime($_GET['dend'], IL_CAL_UNIX)
1341        );
1342
1343
1344        include_once 'Services/Utilities/classes/class.ilConfirmationGUI.php';
1345        $conf = new ilConfirmationGUI;
1346
1347        $this->ctrl->setParameter($this, 'dstart', (int) $_REQUEST['dstart']);
1348        $this->ctrl->setParameter($this, 'dend', (int) $_REQUEST['dend']);
1349
1350        $conf->setFormAction($this->ctrl->getFormAction($this));
1351        $conf->setHeaderText($this->lng->txt('cal_confirm_unreg_info'));
1352        $conf->setConfirm($this->lng->txt('cal_reg_unregister'), 'unregister');
1353        $conf->setCancel($this->lng->txt('cancel'), 'cancel');
1354        $conf->addItem('app_id', $entry->getEntryId(), $entry->getTitle() . ' (' . $start . ')');
1355
1356        $tpl->setContent($conf->getHTML());
1357    }
1358
1359    /**
1360     * Unregister calendar, was confirmed
1361     * @return
1362     */
1363    protected function unregister()
1364    {
1365        global $DIC;
1366
1367        $ilUser = $DIC['ilUser'];
1368
1369        include_once './Services/Calendar/classes/class.ilCalendarRegistration.php';
1370        $reg = new ilCalendarRegistration((int) $_POST['app_id']);
1371        $reg->unregister(
1372            $ilUser->getId(),
1373            new ilDateTime((int) $_REQUEST['dstart'], IL_CAL_UNIX),
1374            new ilDateTime((int) $_REQUEST['dend'], IL_CAL_UNIX)
1375        );
1376
1377        ilUtil::sendSuccess($this->lng->txt('cal_reg_unregistered'), true);
1378        $this->ctrl->returnToParent($this);
1379    }
1380
1381    /**
1382     * Confirmation screen for booking of consultation appointment
1383     */
1384    public function book()
1385    {
1386        global $DIC;
1387
1388        $ilUser = $DIC['ilUser'];
1389        $tpl = $DIC['tpl'];
1390
1391        $entry_id = (int) $_GET['app_id'];
1392        $this->ctrl->saveParameter($this, 'app_id');
1393
1394        include_once 'Services/Calendar/classes/class.ilCalendarEntry.php';
1395        include_once 'Services/Booking/classes/class.ilBookingEntry.php';
1396        $entry = new ilCalendarEntry($entry_id);
1397        $booking = new \ilBookingEntry($entry->getContextId());
1398        $user = $booking->getObjId();
1399
1400
1401        $form = $this->initFormConfirmBooking();
1402        $form->getItemByPostVar('date')->setValue(ilDatePresentation::formatPeriod($entry->getStart(), $entry->getEnd()));
1403        $form->getItemByPostVar('title')->setValue($entry->getTitle() . " (" . ilObjUser::_lookupFullname($user) . ')');
1404
1405        $tpl->setContent($form->getHTML());
1406        return true;
1407    }
1408
1409    /**
1410     *
1411     * @return ilPropertyFormGUI
1412     */
1413    protected function initFormConfirmBooking()
1414    {
1415        include_once './Services/Form/classes/class.ilPropertyFormGUI.php';
1416        $form = new ilPropertyFormGUI();
1417        $form->setFormAction($this->ctrl->getFormAction($this));
1418        $form->addCommandButton('bookconfirmed', $this->lng->txt('cal_confirm_booking'));
1419        $form->addCommandButton('cancel', $this->lng->txt('cancel'));
1420
1421        $date = new ilNonEditableValueGUI($this->lng->txt('appointment'), 'date');
1422        $form->addItem($date);
1423
1424        $title = new ilNonEditableValueGUI($this->lng->txt('title'), 'title');
1425        $form->addItem($title);
1426
1427        $message = new ilTextAreaInputGUI($this->lng->txt('cal_ch_booking_message_tbl'), 'comment');
1428        $message->setRows(5);
1429        $form->addItem($message);
1430
1431        return $form;
1432    }
1433
1434    /**
1435     * Book consultation appointment, was confirmed
1436     */
1437    public function bookconfirmed()
1438    {
1439        global $DIC;
1440
1441        $ilUser = $DIC->user();
1442
1443        $entry = (int) $_REQUEST['app_id'];
1444        $form = $this->initFormConfirmBooking();
1445        if ($form->checkInput()) {
1446            // check if appointment is bookable
1447            include_once './Services/Calendar/classes/class.ilCalendarEntry.php';
1448            $cal_entry = new ilCalendarEntry($entry);
1449
1450            include_once './Services/Booking/classes/class.ilBookingEntry.php';
1451            $booking = new ilBookingEntry($cal_entry->getContextId());
1452
1453            if (!$booking->isAppointmentBookableForUser($entry, $GLOBALS['DIC']['ilUser']->getId())) {
1454                ilUtil::sendFailure($this->lng->txt('cal_booking_failed_info'), true);
1455                $this->ctrl->returnToParent($this);
1456            }
1457
1458            include_once './Services/Calendar/classes/ConsultationHours/class.ilConsultationHourUtils.php';
1459            ilConsultationHourUtils::bookAppointment($ilUser->getId(), $entry);
1460
1461            include_once './Services/Booking/classes/class.ilBookingEntry.php';
1462            ilBookingEntry::writeBookingMessage($entry, $ilUser->getId(), $form->getInput('comment'));
1463        }
1464        ilUtil::sendSuccess($this->lng->txt('cal_booking_confirmed'), true);
1465        $this->ctrl->returnToParent($this);
1466    }
1467
1468    /**
1469     * Confirmation screen to cancel consultation appointment or ressource booking
1470     * depends on calendar category
1471     */
1472    public function cancelBooking()
1473    {
1474        global $DIC;
1475
1476        $ilUser = $DIC['ilUser'];
1477        $tpl = $DIC['tpl'];
1478
1479        $entry = (int) $_GET['app_id'];
1480
1481        include_once 'Services/Calendar/classes/class.ilCalendarEntry.php';
1482        $entry = new ilCalendarEntry($entry);
1483
1484        $category = $this->calendarEntryToCategory($entry);
1485        if ($category->getType() == ilCalendarCategory::TYPE_CH) {
1486            include_once 'Services/Booking/classes/class.ilBookingEntry.php';
1487            $booking = new ilBookingEntry($entry->getContextId());
1488            if (!$booking->hasBooked($entry->getEntryId())) {
1489                $this->ctrl->returnToParent($this);
1490                return false;
1491            }
1492
1493            $entry_title = ' ' . $entry->getTitle() . " (" . ilObjUser::_lookupFullname($booking->getObjId()) . ')';
1494        } elseif ($category->getType() == ilCalendarCategory::TYPE_BOOK) {
1495            $entry_title = ' ' . $entry->getTitle();
1496        } else {
1497            $this->ctrl->returnToParent($this);
1498            return false;
1499        }
1500
1501        $title = ilDatePresentation::formatPeriod($entry->getStart(), $entry->getEnd());
1502
1503        include_once 'Services/Utilities/classes/class.ilConfirmationGUI.php';
1504        $conf = new ilConfirmationGUI;
1505        $conf->setFormAction($this->ctrl->getFormAction($this));
1506        $conf->setHeaderText($this->lng->txt('cal_cancel_booking_info'));
1507        $conf->setConfirm($this->lng->txt('cal_cancel_booking'), 'cancelconfirmed');
1508        $conf->setCancel($this->lng->txt('cancel'), 'cancel');
1509        $conf->addItem('app_id', $entry->getEntryId(), $title . ' - ' . $entry_title);
1510
1511        $tpl->setContent($conf->getHTML());
1512    }
1513
1514    /**
1515     * Cancel consultation appointment or ressource booking, was confirmed
1516     * This will delete the calendar entry
1517     */
1518    public function cancelConfirmed()
1519    {
1520        global $DIC;
1521
1522        $ilUser = $DIC['ilUser'];
1523
1524        $entry = (int) $_POST['app_id'];
1525
1526        include_once 'Services/Calendar/classes/class.ilCalendarEntry.php';
1527        $entry = new ilCalendarEntry($entry);
1528
1529        $category = $this->calendarEntryToCategory($entry);
1530        if ($category->getType() == ilCalendarCategory::TYPE_CH) {
1531            // find cloned calendar entry in user calendar
1532            include_once 'Services/Calendar/classes/ConsultationHours/class.ilConsultationHourAppointments.php';
1533            $apps = ilConsultationHourAppointments::getAppointmentIds(
1534                $ilUser->getId(),
1535                $entry->getContextId(),
1536                $entry->getStart(),
1537                ilCalendarCategory::TYPE_CH,
1538                false
1539            );
1540
1541            // Fix for wrong, old entries
1542            foreach ((array) $apps as $own_app) {
1543                $ref_entry = new ilCalendarEntry($own_app);
1544                $ref_entry->delete();
1545            }
1546
1547            include_once 'Services/Booking/classes/class.ilBookingEntry.php';
1548            $booking = new ilBookingEntry($entry->getContextId());
1549            $booking->cancelBooking($entry->getEntryId());
1550
1551        // do NOT delete original entry
1552        } elseif ($category->getType() == ilCalendarCategory::TYPE_BOOK) {
1553            $booking = new ilBookingReservation($entry->getContextId());
1554            $booking->setStatus(ilBookingReservation::STATUS_CANCELLED);
1555            $booking->update();
1556
1557            $entry->delete();
1558        }
1559
1560        ilUtil::sendSuccess($this->lng->txt('cal_cancel_booking_confirmed'), true);
1561        $this->ctrl->returnToParent($this);
1562    }
1563
1564    /**
1565     * Get category object of given calendar entry
1566     * @param ilCalendarEntry $entry
1567     * @return ilCalendarCategory
1568     */
1569    protected function calendarEntryToCategory(ilCalendarEntry $entry)
1570    {
1571        include_once 'Services/Calendar/classes/class.ilCalendarCategoryAssignments.php';
1572        include_once 'Services/Calendar/classes/class.ilCalendarCategory.php';
1573        $assignment = new ilCalendarCategoryAssignments($entry->getEntryId());
1574        $assignment = $assignment->getFirstAssignment();
1575        return new ilCalendarCategory($assignment);
1576    }
1577
1578    /**
1579     * Do auto completion
1580     * @return void
1581     */
1582    protected function doUserAutoComplete()
1583    {
1584        if (!isset($_GET['autoCompleteField'])) {
1585            $a_fields = array('login','firstname','lastname','email');
1586        } else {
1587            $a_fields = array((string) $_GET['autoCompleteField']);
1588        }
1589
1590        include_once './Services/User/classes/class.ilUserAutoComplete.php';
1591        $auto = new ilUserAutoComplete();
1592        $auto->setSearchFields($a_fields);
1593        $auto->enableFieldSearchableCheck(true);
1594        $auto->setMoreLinkAvailable(true);
1595
1596        if (($_REQUEST['fetchall'])) {
1597            $auto->setLimit(ilUserAutoComplete::MAX_ENTRIES);
1598        }
1599
1600        echo $auto->getList($_REQUEST['query']);
1601        exit();
1602    }
1603}
1604