ILIAS  release_5-1 Revision 5.0.0-5477-g43f3e3fab5f
class.ilConsultationHoursGUI.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 
24 include_once './Services/Calendar/classes/class.ilCalendarRecurrence.php';
25 include_once './Services/Booking/classes/class.ilBookingEntry.php';
26 include_once './Services/Calendar/classes/ConsultationHours/class.ilConsultationHourAppointments.php';
27 
35 {
36  const MODE_CREATE = 1;
37  const MODE_UPDATE = 2;
38  const MODE_MULTI = 3;
39 
41 
42  protected $user_id;
43  protected $ctrl;
44 
45  protected $booking = null;
46 
50  public function __construct()
51  {
52  global $lng, $ilCtrl, $tpl, $ilUser;
53 
54  $user_id = (int)$_GET['user_id'];
55  if($user_id)
56  {
58  {
59  $this->user_id = $user_id;
60  }
61  else
62  {
63  $user_id = false;
64  }
65  }
66  if(!$user_id)
67  {
68  $this->user_id = $ilUser->getId();
69  }
70 
71  $this->ctrl = $ilCtrl;
72  $this->lng = $lng;
73  $this->tpl = $tpl;
74  }
75 
80  public function executeCommand()
81  {
82  global $ilUser, $ilCtrl, $tpl, $ilHelp, $ilTabs;
83 
84  $ilHelp->setScreenIdComponent("cal");
85 
86  switch($this->ctrl->getNextClass())
87  {
88  case "ilpublicuserprofilegui":
89  include_once('./Services/User/classes/class.ilPublicUserProfileGUI.php');
90  $profile = new ilPublicUserProfileGUI($this->user_id);
91  $profile->setBackUrl($this->getProfileBackUrl());
92  $ret = $ilCtrl->forwardCommand($profile);
93  $tpl->setContent($ret);
94  break;
95 
96  case 'ilrepositorysearchgui':
97 
98  include_once('./Services/Search/classes/class.ilRepositorySearchGUI.php');
99  $rep_search = new ilRepositorySearchGUI();
100 
101  if(isset($_REQUEST['assignM']))
102  {
103  $rep_search->setCallback(
104  $this,
105  'assignUsersToAppointments',
106  array()
107  );
108  $ilCtrl->setParameter($this,'assignM',1);
109  $ilCtrl->setReturn($this,'appointmentList');
110  $ilTabs->activateSubTab('cal_ch_app_list');
111  }
112  elseif(isset($_REQUEST['grp_id']))
113  {
114  $rep_search->setCallback(
115  $this,
116  'assignUsersToGroup',
117  array()
118  );
119  $ilCtrl->saveParameter($this,'grp_id');
120  $ilCtrl->setReturn($this,'groupList');
121  $ilTabs->activateSubTab('cal_ch_app_grp');
122  }
123  elseif(isset($_REQUEST['apps']))
124  {
125  $rep_search->setCallback(
126  $this,
127  'assignUsersToAppointment',
128  array()
129  );
130  $ilCtrl->saveParameter($this,'apps');
131  $ilCtrl->setReturn($this,'appointmentList');
132  $ilTabs->activateSubTab('cal_ch_app_list');
133  }
134  $ilCtrl->forwardCommand($rep_search);
135  break;
136 
137  default:
138  $tpl->setTitle($this->lng->txt("cal_ch_form_header")); // #12220
139 
140  $this->setTabs();
141  if($ilUser->getId() != $this->user_id)
142  {
143  $ilCtrl->setParameter($this, 'user_id', $this->user_id);
144  }
145 
146  $cmd = $this->ctrl->getCmd('appointmentList');
147  $this->$cmd();
148  }
149  }
150 
155  public function getUserId()
156  {
157  return $this->user_id;
158  }
159 
163  protected function searchUsersForAppointments()
164  {
165  global $ilCtrl, $ilTabs;
166 
167  $_SESSION['ch_apps'] = $_REQUEST['apps'];
168 
169  if(!count($_SESSION['ch_apps']))
170  {
171  ilUtil::sendFailure($this->lng->txt('select_one'),true);
172  $GLOBALS['ilCtrl']->redirect($this,'appointmentList');
173  }
174  $_REQUEST['assignM'] = 1;
175  $ilCtrl->setCmdClass('ilrepositorysearchgui');
176  $ilCtrl->setcmd('');
177  $this->executeCommand();
178  }
179 
184  protected function sendInfoAboutUnassignedUsers($unassigned)
185  {
186  if(!$unassigned)
187  {
188  return true;
189  }
190  $users = array();
191  foreach($unassigned as $user_id)
192  {
193  include_once './Services/User/classes/class.ilObjUser.php';
194  $users[] = ilObjUser::_lookupFullname($user_id);
195  }
196  ilUtil::sendInfo($this->lng->txt('cal_ch_user_assignment_failed_info').'<br />'.implode('<br />', $users),true);
197  return true;
198  }
199 
204  public function assignUsersToAppointments(array $users)
205  {
206  global $ilCtrl;
207 
208  $unassigned_users = array();
209  foreach($_SESSION['ch_apps'] as $app)
210  {
211  $unassigned_users = array_unique(array_merge($unassigned_users,$this->assignUsersToAppointment($users,$app,false)));
212  }
213 
214  $this->sendInfoAboutUnassignedUsers($unassigned_users);
215  $ilCtrl->redirect($this,'appointmentList');
216  }
217 
218 
224  public function assignUsersToAppointment(array $users, $a_app = 0, $a_redirect = true)
225  {
226  global $ilCtrl;
227 
228  if($a_app)
229  {
230  $app = $a_app;
231  }
232  else
233  {
234  $app = $_REQUEST['apps'];
235  }
236 
237  include_once './Services/Booking/classes/class.ilBookingEntry.php';
239 
240  $assigned_users = array();
241  foreach($users as $user)
242  {
243  if($booking->getCurrentNumberOfBookings($app) >= $booking->getNumberOfBookings())
244  {
245  break;
246  }
247  if(!ilBookingEntry::lookupBookingsOfUser((array) $app, $user))
248  {
249  include_once './Services/Calendar/classes/ConsultationHours/class.ilConsultationHourUtils.php';
251  $assigned_users[] = $user;
252  }
253  }
254 
255  $unassigned_users = array_diff($users, $assigned_users);
256 
257  if($a_redirect)
258  {
259  $this->sendInfoAboutUnassignedUsers($unassigned_users);
260  $ilCtrl->redirect($this,'appointmentList');
261  }
262  else
263  {
264  return $unassigned_users;
265  }
266 
267  }
268 
274  public function assignUsersToGroup(array $usr_ids)
275  {
276  global $ilCtrl;
277 
278  $group_id = (int) $_REQUEST['grp_id'];
279 
280  $tomorrow = new ilDateTime(time(),IL_CAL_UNIX);
281  $tomorrow->increment(IL_CAL_DAY,1);
282 
283  // Get all future consultation hours
284  include_once './Services/Calendar/classes/ConsultationHours/class.ilConsultationHourAppointments.php';
285  include_once './Services/Booking/classes/class.ilBookingEntry.php';
287  $this->user_id,
288  $group_id,
289  $tomorrow
290  );
291  $users = $usr_ids;
292  $assigned_users = array();
293  foreach($apps as $app)
294  {
296  foreach($users as $user)
297  {
298  if($booking->getCurrentNumberOfBookings($app) >= $booking->getNumberOfBookings())
299  {
300  break;
301  }
302  if(!ilBookingEntry::lookupBookingsOfUser($apps, $user))
303  {
304  include_once './Services/Calendar/classes/ConsultationHours/class.ilConsultationHourUtils.php';
306  $assigned_users[] = $user;
307  }
308  }
309  }
310 
311  $this->sendInfoAboutUnassignedUsers(array_diff($users, $assigned_users));
312  $ilCtrl->redirect($this,'bookingList');
313  }
314 
315 
320  protected function groupList()
321  {
322  global $ilToolbar, $ilTabs, $tpl;
323 
324  $ilToolbar->setFormAction($this->ctrl->getFormAction($this));
325  $ilToolbar->addButton($this->lng->txt('cal_ch_add_grp'),$this->ctrl->getLinkTarget($this,'addGroup'));
326 
327  $this->setSubTabs();
328  $ilTabs->activateSubTab('cal_ch_app_grp');
329 
330  include_once './Services/Calendar/classes/ConsultationHours/class.ilConsultationHourGroupTableGUI.php';
331  include_once './Services/Calendar/classes/ConsultationHours/class.ilConsultationHourGroups.php';
332  $gtbl = new ilConsultationHourGroupTableGUI($this,'groupList',$this->getUserId());
334 
335  $tpl->setContent($gtbl->getHTML());
336  }
337 
343  protected function addGroup(ilPropertyFormGUI $form = null)
344  {
345  global $ilTabs, $tpl;
346 
347  $this->setSubTabs();
348  $ilTabs->activateSubTab('cal_ch_app_grp');
349 
350  if($form == null)
351  {
352  $form = $this->initGroupForm();
353  }
354  $tpl->setContent($form->getHTML());
355  }
356 
360  protected function saveGroup()
361  {
362  $form = $this->initGroupForm();
363  if($form->checkInput())
364  {
365  include_once './Services/Calendar/classes/ConsultationHours/class.ilConsultationHourGroup.php';
366  $group = new ilConsultationHourGroup();
367  $group->setTitle($form->getInput('title'));
368  $group->setMaxAssignments($form->getInput('multiple'));
369  $group->setUserId($this->getUserId());
370  $group->save();
371 
372  ilUtil::sendSuccess($GLOBALS['lng']->txt('settings_saved'),true);
373  $GLOBALS['ilCtrl']->redirect($this,'groupList');
374  }
375 
376  ilUtil::sendFailure($GLOBALS['lng']->txt('err_check_input'),true);
377  $this->addGroup($form);
378  }
379 
385  protected function editGroup(ilPropertyFormGUI $form = null)
386  {
387  global $ilCtrl, $tpl, $ilTabs;
388 
389  $ilCtrl->setParameter($this,'grp_id',(int) $_REQUEST['grp_id']);
390  $this->setSubTabs();
391  $ilTabs->activateSubTab('cal_ch_app_grp');
392 
393  if($form == null)
394  {
395  $form = $this->initGroupForm((int) $_REQUEST['grp_id']);
396  }
397  $tpl->setContent($form->getHTML());
398  }
399 
406  protected function updateGroup()
407  {
408  global $ilCtrl, $tpl, $ilTabs;
409 
410  $ilCtrl->setParameter($this,'grp_id',(int) $_REQUEST['grp_id']);
411 
412  $form = $this->initGroupForm((int) $_REQUEST['grp_id']);
413  if($form->checkInput())
414  {
415  include_once './Services/Calendar/classes/ConsultationHours/class.ilConsultationHourGroup.php';
416  $group = new ilConsultationHourGroup((int) $_REQUEST['grp_id']);
417  $group->setTitle($form->getInput('title'));
418  $group->setMaxAssignments($form->getInput('multiple'));
419  $group->setUserId($this->getUserId());
420  $group->update();
421 
422  ilUtil::sendSuccess($GLOBALS['lng']->txt('settings_saved'),true);
423  $GLOBALS['ilCtrl']->redirect($this,'groupList');
424  }
425 
426  ilUtil::sendFailure($GLOBALS['lng']->txt('err_check_input'),true);
427  $this->editGroup($form);
428  }
429 
435  protected function confirmDeleteGroup()
436  {
437  global $ilCtrl, $ilTabs, $tpl;
438 
439  $ilCtrl->setParameter($this,'grp_id',(int) $_REQUEST['grp_id']);
440  $groups = array((int) $_REQUEST['grp_id']);
441 
442  $this->setSubTabs();
443  $ilTabs->activateSubTab('cal_ch_app_grp');
444 
445 
446  include_once './Services/Utilities/classes/class.ilConfirmationGUI.php';
447  $confirm = new ilConfirmationGUI();
448  $confirm->setFormAction($ilCtrl->getFormAction($this));
449  $confirm->setHeaderText($GLOBALS['lng']->txt('cal_ch_grp_delete_sure'));
450  $confirm->setConfirm($GLOBALS['lng']->txt('delete'), 'deleteGroup');
451  $confirm->setCancel($GLOBALS['lng']->txt('cancel'), 'groupList');
452 
453  foreach($groups as $grp_id)
454  {
455  include_once './Services/Calendar/classes/ConsultationHours/class.ilConsultationHourGroup.php';
456  $group = new ilConsultationHourGroup($grp_id);
457 
458  $confirm->addItem('groups[]', $grp_id, $group->getTitle());
459  }
460  $tpl->setContent($confirm->getHTML());
461  }
462 
466  protected function deleteGroup()
467  {
468  global $ilCtrl;
469 
470  foreach((array) $_REQUEST['groups'] as $grp_id)
471  {
472  include_once './Services/Calendar/classes/ConsultationHours/class.ilConsultationHourGroup.php';
473  $group = new ilConsultationHourGroup($grp_id);
474  $group->delete();
475  }
476  ilUtil::sendSuccess($GLOBALS['lng']->txt('cal_ch_grp_deleted'));
477  $ilCtrl->redirect($this,'groupList');
478  }
479 
483  protected function initGroupForm($a_group_id = 0)
484  {
485  include_once './Services/Calendar/classes/ConsultationHours/class.ilConsultationHourGroup.php';
486  $group = new ilConsultationHourGroup($a_group_id);
487 
488  include_once 'Services/Form/classes/class.ilPropertyFormGUI.php';
489  $form = new ilPropertyFormGUI();
490  $form->setFormAction($GLOBALS['ilCtrl']->getFormAction($this));
491 
492  if($a_group_id)
493  {
494  $form->setTitle($GLOBALS['lng']->txt('cal_ch_grp_update_tbl'));
495  $form->addCommandButton('updateGroup', $GLOBALS['lng']->txt('save'));
496  $form->addCommandButton('groupList', $GLOBALS['lng']->txt('cancel'));
497  }
498  else
499  {
500  $form->setTitle($GLOBALS['lng']->txt('cal_ch_grp_add_tbl'));
501  $form->addCommandButton('saveGroup', $GLOBALS['lng']->txt('save'));
502  $form->addCommandButton('appointmentList', $GLOBALS['lng']->txt('cancel'));
503  }
504 
505  $title = new ilTextInputGUI($GLOBALS['lng']->txt('title'),'title');
506  $title->setMaxLength(128);
507  $title->setSize(40);
508  $title->setRequired(true);
509  $title->setValue($group->getTitle());
510  $form->addItem($title);
511 
512  $multiple = new ilNumberInputGUI($GLOBALS['lng']->txt('cal_ch_grp_multiple'),'multiple');
513  $multiple->setRequired(true);
514  $multiple->setMinValue(1);
515  $multiple->setSize(1);
516  $multiple->setMaxLength(2);
517  $multiple->setInfo($GLOBALS['lng']->txt('cal_ch_grp_multiple_info'));
518  $multiple->setValue($group->getMaxAssignments());
519  $form->addItem($multiple);
520 
521  return $form;
522  }
523 
527  protected function bookingList()
528  {
529  global $ilToolbar, $ilTabs, $tpl;
530 
531  $this->setSubTabs();
532  $ilTabs->activateSubTab('cal_ch_app_bookings');
533 
534  include_once './Services/Calendar/classes/ConsultationHours/class.ilConsultationHourBookingTableGUI.php';
535  $btable = new ilConsultationHourBookingTableGUI($this,'bookingList',$this->getUserId());
537  $tpl->setContent($btable->getHTML());
538  }
539 
543  protected function confirmDeleteBooking()
544  {
545  $this->confirmRejectBooking(false);
546  }
547 
551  protected function confirmRejectBooking($a_send_notification = true)
552  {
553  global $ilTabs, $tpl;
554 
555  $this->setSubTabs();
556  $ilTabs->activateSubTab('cal_ch_app_bookings');
557 
558  include_once('./Services/Utilities/classes/class.ilConfirmationGUI.php');
559 
560  $confirm = new ilConfirmationGUI();
561  $confirm->setFormAction($this->ctrl->getFormAction($this));
562 
563  if($a_send_notification)
564  {
565  ilUtil::sendInfo($this->lng->txt('cal_ch_cancel_booking_info'));
566  $confirm->setHeaderText($this->lng->txt('cal_ch_cancel_booking_sure'));
567  $confirm->setConfirm($this->lng->txt('cal_ch_reject_booking'), 'rejectBooking');
568  }
569  else
570  {
571  ilUtil::sendInfo($this->lng->txt('cal_ch_delete_booking_info'));
572  $confirm->setHeaderText($this->lng->txt('cal_ch_delete_booking_sure'));
573  $confirm->setConfirm($this->lng->txt('cal_ch_delete_booking'), 'deleteBooking');
574  }
575 
576  $confirm->setCancel($this->lng->txt('cancel'),'bookingList');
577 
578  include_once 'Services/Calendar/classes/class.ilCalendarEntry.php';
579  foreach((array) $_REQUEST['bookuser'] as $bookuser)
580  {
581  $ids = explode('_',$bookuser);
582 
583  include_once './Services/Calendar/classes/class.ilCalendarEntry.php';
584  include_once './Services/User/classes/class.ilUserUtil.php';
585  $entry = new ilCalendarEntry($ids[0]);
586  $confirm->addItem(
587  'bookuser[]',
588  $bookuser,
590  $ids[1],
591  true,
592  false,
593  '',
594  true,
595  true
596  ).', '.ilDatePresentation::formatDate($entry->getStart())
597  );
598  }
599  $tpl->setContent($confirm->getHTML());
600  }
601 
605  protected function deleteBooking()
606  {
607  $this->rejectBooking(false);
608  }
609 
614  protected function rejectBooking($a_send_notification = true)
615  {
616  global $ilCtrl;
617 
618  foreach((array) $_REQUEST['bookuser'] as $bookuser)
619  {
620  $ids = explode('_',$bookuser);
621 
622  include_once './Services/Calendar/classes/ConsultationHours/class.ilConsultationHourUtils.php';
623  ilConsultationHourUtils::cancelBooking($ids[1],$ids[0],$a_send_notification);
624  }
625  if($a_send_notification)
626  {
627  ilUtil::sendSuccess($this->lng->txt('cal_ch_canceled_bookings'),true);
628  }
629  else
630  {
631  ilUtil::sendSuccess($this->lng->txt('cal_ch_deleted_bookings'),true);
632  }
633  $ilCtrl->redirect($this,'bookingList');
634  }
635 
641  protected function appointmentList()
642  {
643  global $ilToolbar, $ilHelp, $ilTabs;
644 
645  $ilHelp->setScreenId("consultation_hours");
646 
647  $ilToolbar->setFormAction($this->ctrl->getFormAction($this));
648  $ilToolbar->addButton($this->lng->txt('cal_ch_add_sequence'),$this->ctrl->getLinkTarget($this,'createSequence'));
649 
650  $this->setSubTabs();
651  $ilTabs->activateSubTab('cal_ch_app_list');
652 
653  include_once './Services/Calendar/classes/ConsultationHours/class.ilConsultationHoursTableGUI.php';
654  $tbl = new ilConsultationHoursTableGUI($this,'appointmentList',$this->getUserId());
655  $tbl->parse();
656  $this->tpl->setContent($tbl->getHTML());
657  }
658 
663  protected function createSequence()
664  {
665  $this->initFormSequence(self::MODE_CREATE);
666 
667  $this->booking = new ilBookingEntry();
668  $this->form->getItemByPostVar('bo')->setValue($this->booking->getNumberOfBookings());
669  $this->form->getItemByPostVar('ap')->setValue(1);
670  $this->form->getItemByPostVar('du')->setMinutes(15);
671  $this->form->getItemByPostVar('st')->setDate(
672  new ilDateTime(mktime(8,0,0,date('n',time()),date('d',time()),date('Y',time())),IL_CAL_UNIX));
673 
674  $this->tpl->setContent($this->form->getHTML());
675  }
676 
682  protected function initFormSequence($a_mode)
683  {
684  include_once './Services/Form/classes/class.ilPropertyFormGUI.php';
685 
686  include_once('./Services/YUI/classes/class.ilYuiUtil.php');
688 
689  $this->form = new ilPropertyFormGUI();
690  $this->form->setFormAction($this->ctrl->getFormAction($this));
691 
692  switch($a_mode)
693  {
694  case self::MODE_CREATE:
695  $this->form->setTitle($this->lng->txt('cal_ch_add_sequence'));
696  $this->form->addCommandButton('saveSequence', $this->lng->txt('save'));
697  $this->form->addCommandButton('appointmentList', $this->lng->txt('cancel'));
698  break;
699 
700  /*
701  case self::MODE_UPDATE:
702  $this->form->setTitle($this->lng->txt('cal_ch_edit_sequence'));
703  $this->form->addCommandButton('updateSequence', $this->lng->txt('save'));
704  $this->form->addCommandButton('appointmentList', $this->lng->txt('cancel'));
705  break;
706  */
707 
708  case self::MODE_MULTI:
709  $this->form->setTitle($this->lng->txt('cal_ch_multi_edit_sequence'));
710  $this->form->addCommandButton('updateMulti', $this->lng->txt('save'));
711  $this->form->addCommandButton('appointmentList', $this->lng->txt('cancel'));
712  break;
713  }
714 
715  // in case of existing groups show a selection
716  include_once './Services/Calendar/classes/ConsultationHours/class.ilConsultationHourGroups.php';
718  {
719  $group = new ilSelectInputGUI($this->lng->txt('cal_ch_grp_selection'),'grp');
720  $group->setOptions($options);
721  $group->setRequired(false);
722  $this->form->addItem($group);
723  }
724 
725  // Title
726  $ti = new ilTextInputGUI($this->lng->txt('title'),'ti');
727  $ti->setSize(32);
728  $ti->setMaxLength(128);
729  $ti->setRequired(true);
730  $this->form->addItem($ti);
731 
732  if($a_mode != self::MODE_MULTI)
733  {
734  // Start
735  include_once './Services/Form/classes/class.ilDateTimeInputGUI.php';
736  $dur = new ilDateTimeInputGUI($this->lng->txt('cal_start'),'st');
737  $dur->setShowTime(true);
738  $dur->setMinuteStepSize(5);
739  $this->form->addItem($dur);
740 
741  // Duration
742  $du = new ilDurationInputGUI($this->lng->txt('cal_ch_duration'),'du');
743  $du->setShowMinutes(true);
744  $du->setShowHours(true);
745  $this->form->addItem($du);
746 
747  // Number of appointments
748  $nu = new ilNumberInputGUI($this->lng->txt('cal_ch_num_appointments'),'ap');
749  $nu->setInfo($this->lng->txt('cal_ch_num_appointments_info'));
750  $nu->setSize(2);
751  $nu->setMaxLength(2);
752  $nu->setRequired(true);
753  $nu->setMinValue(1);
754  $this->form->addItem($nu);
755 
756  // Recurrence
757  include_once('./Services/Calendar/classes/Form/class.ilRecurrenceInputGUI.php');
758  $rec = new ilRecurrenceInputGUI($this->lng->txt('cal_recurrences'),'frequence');
759  $rec->setEnabledSubForms(
760  array(
764  )
765  );
766  $this->form->addItem($rec);
767  }
768 
769  // Number of bookings
770  $nu = new ilNumberInputGUI($this->lng->txt('cal_ch_num_bookings'),'bo');
771  $nu->setSize(2);
772  $nu->setMaxLength(2);
773  $nu->setMinValue(1);
774  $nu->setRequired(true);
775  $this->form->addItem($nu);
776 
777  // Deadline
778  $dead = new ilDurationInputGUI($this->lng->txt('cal_ch_deadline'),'dead');
779  $dead->setInfo($this->lng->txt('cal_ch_deadline_info'));
780  $dead->setShowMinutes(false);
781  $dead->setShowHours(true);
782  $dead->setShowDays(true);
783  $this->form->addItem($dead);
784 
785  // Location
786  $lo = new ilTextInputGUI($this->lng->txt('cal_where'),'lo');
787  $lo->setSize(32);
788  $lo->setMaxLength(128);
789  $this->form->addItem($lo);
790 
791  // Description
792  $de = new ilTextAreaInputGUI($this->lng->txt('description'),'de');
793  $de->setRows(10);
794  $de->setCols(60);
795  $this->form->addItem($de);
796 
797  // Target Object
798  $tgt = new ilTextInputGUI($this->lng->txt('cal_ch_target_object'),'tgt');
799  $tgt->setInfo($this->lng->txt('cal_ch_target_object_info'));
800  $tgt->setSize(16);
801  $tgt->setMaxLength(128);
802  $this->form->addItem($tgt);
803  }
804 
809  protected function saveSequence()
810  {
811  global $ilObjDataCache;
812 
813  $this->initFormSequence(self::MODE_CREATE);
814 
815  if($this->form->checkInput())
816  {
817  $this->form->setValuesByPost();
818 
819  $booking = new ilBookingEntry();
820  $booking->setObjId($this->getUserId());
821  $booking->setNumberOfBookings($this->form->getInput('bo'));
822 
823  $deadline = $this->form->getInput('dead');
824  $deadline = $deadline['dd'] * 24 + $deadline['hh'];
825  $booking->setDeadlineHours($deadline);
826 
827  // consultation hour group
828  include_once './Services/Calendar/classes/ConsultationHours/class.ilConsultationHourGroups.php';
830  {
831  $booking->setBookingGroup((int) $this->form->getInput('grp'));
832  }
833 
834  $tgt = explode(',',$this->form->getInput('tgt'));
835  $obj_ids = array();
836  foreach((array) $tgt as $ref_id)
837  {
838  if(!trim($ref_id))
839  {
840  continue;
841  }
842  $obj_id = $ilObjDataCache->lookupObjId($ref_id);
843  $type = ilObject::_lookupType($obj_id);
844  $valid_types = array('crs','grp');
845  if(!$obj_id or !in_array($type, $valid_types))
846  {
847  ilUtil::sendFailure($this->lng->txt('cal_ch_unknown_repository_object'));
848  $this->tpl->setContent($this->form->getHTML());
849  return;
850  }
851 
852  $obj_ids[] = $obj_id;
853  }
854  $booking->setTargetObjIds($obj_ids);
855 
856  $booking->save();
858 
859  ilUtil::sendSuccess($this->lng->txt('settings_saved'), true);
860  $this->ctrl->redirect($this,'appointmentList');
861  }
862  else
863  {
864  $this->form->setValuesByPost();
865  $this->tpl->setContent($this->form->getHTML());
866  }
867  }
868 
875  {
876  include_once './Services/Calendar/classes/class.ilDateList.php';
877  $concurrent_dates = new ilDateList(ilDateList::TYPE_DATETIME);
878  $start = clone $this->form->getItemByPostVar('st')->getDate();
879  for($i = 0; $i < $this->form->getItemByPostVar('ap')->getValue(); $i++)
880  {
881  $concurrent_dates->add(clone $start);
882 
883  $start->increment(ilDateTime::MINUTE,$this->form->getItemByPostVar('du')->getMinutes());
884  $start->increment(ilDateTime::HOUR,$this->form->getItemByPostVar('du')->getHours());
885  #$start = new ilDateTime(,IL_CAL_UNIX);
886  }
887 
888  include_once './Services/Calendar/classes/class.ilCalendarUtil.php';
889  $def_cat = ilCalendarUtil::initDefaultCalendarByType(ilCalendarCategory::TYPE_CH,$this->getUserId(),$this->lng->txt('cal_ch_personal_ch'),true);
890 
891  // Add calendar appointment for each
892  include_once './Services/Calendar/classes/class.ilCalendarCategoryAssignments.php';
893  include_once './Services/Calendar/classes/class.ilCalendarEntry.php';
894  include_once './Services/Calendar/classes/class.ilCalendarRecurrenceCalculator.php';
895  include_once './Services/Booking/classes/class.ilBookingPeriod.php';
896 
897  $num_appointments = 0;
898  foreach($concurrent_dates as $dt)
899  {
900  if($num_appointments >= self::MAX_APPOINTMENTS_PER_SEQUENCE)
901  {
902  break;
903  }
904 
905  $end = clone $dt;
906  $end->increment(ilDateTime::MINUTE,$this->form->getItemByPostVar('du')->getMinutes());
907  $end->increment(ilDateTime::HOUR,$this->form->getItemByPostVar('du')->getHours());
908 
909  $calc = new ilCalendarRecurrenceCalculator(
910  new ilBookingPeriod($dt,$end),
911  $this->form->getItemByPostVar('frequence')->getRecurrence()
912  );
913 
914  // Calculate with one year limit
915  $limit = clone $dt;
916  $limit->increment(ilDateTime::YEAR,1);
917 
918  $date_list = $calc->calculateDateList($dt,$limit);
919 
920  $num = 0;
921  foreach($date_list as $app_start)
922  {
923  $app_end = clone $app_start;
924  $app_end->increment(ilDateTime::MINUTE,$this->form->getItemByPostVar('du')->getMinutes());
925  $app_end->increment(ilDateTime::HOUR,$this->form->getItemByPostVar('du')->getHours());
926 
927 
928  $entry = new ilCalendarEntry();
929  $entry->setContextId($booking->getId());
930  $entry->setTitle($this->form->getInput('ti'));
931  $entry->setSubtitle("#consultationhour#"); // dynamic, see ilCalendarEntry
932  $entry->setDescription($this->form->getInput('de'));
933  $entry->setLocation($this->form->getInput('lo'));
934  $entry->setStart($app_start);
935  $entry->setEnd($app_end);
936 
937  $entry->setTranslationType(IL_CAL_TRANSLATION_SYSTEM);
938  $entry->save();
939 
940  $cat_assign = new ilCalendarCategoryAssignments($entry->getEntryId());
941  $cat_assign->addAssignment($def_cat->getCategoryID());
942 
943  $num_appointments++;
944  }
945  }
946  }
947 
952  protected function setTabs()
953  {
954  global $ilTabs, $ilUser, $ilCtrl;
955 
956  $ilCtrl->setParameter($this, 'user_id', '');
957  $ilTabs->addTab('consultation_hours_'.$ilUser->getId(), $this->lng->txt('cal_ch_ch'), $this->ctrl->getLinkTarget($this,'appointmentList'));
958 
960  {
961  $ilCtrl->setParameter($this, 'user_id', $user_id);
962  $ilTabs->addTab('consultation_hours_'.$user_id, $this->lng->txt('cal_ch_ch').': '.$login, $this->ctrl->getLinkTarget($this,'appointmentList'));
963  }
964  $ilCtrl->setParameter($this, 'user_id', '');
965 
966  $ilTabs->addTab('ch_settings', $this->lng->txt('settings'), $this->ctrl->getLinkTarget($this,'settings'));
967 
968  $ilTabs->activateTab('consultation_hours_'.$this->getUserId());
969  }
970 
976  protected function setSubTabs()
977  {
978  global $ilTabs, $ilCtrl;
979 
980  $ilCtrl->setParameter($this,'user_id',$this->getUserId());
981  $ilTabs->addSubTab('cal_ch_app_list',$this->lng->txt('cal_ch_app_list'),$ilCtrl->getLinkTarget($this,'appointmentList'));
982  $ilTabs->addSubTab('cal_ch_app_grp',$this->lng->txt('cal_ch_app_grp'),$ilCtrl->getLinkTarget($this,'groupList'));
983  $ilTabs->addSubTab('cal_ch_app_bookings',$this->lng->txt('cal_ch_app_bookings'),$ilCtrl->getLinkTarget($this,'bookingList'));
984  }
985 
989  public function edit()
990  {
991  global $ilTabs;
992 
993  if(!isset($_REQUEST['apps']))
994  {
995  ilUtil::sendFailure($this->lng->txt('select_one'));
996  return $this->appointmentList();
997  }
998 
999  $this->initFormSequence(self::MODE_MULTI);
1000 
1001  if($_REQUEST['apps'] && !is_array($_REQUEST['apps']))
1002  {
1003  $_REQUEST['apps'] = explode(';', $_REQUEST['apps']);
1004  }
1005 
1006  $hidden = new ilHiddenInputGUI('apps');
1007  $hidden->setValue(implode(';', $_REQUEST['apps']));
1008  $this->form->addItem($hidden);
1009 
1010  include_once 'Services/Calendar/classes/class.ilCalendarEntry.php';
1011  $first = $_REQUEST['apps'];
1012  $first = array_shift($_REQUEST['apps']);
1013  $entry = new ilCalendarEntry($first);
1014 
1015  $this->form->getItemByPostVar('ti')->setValue($entry->getTitle());
1016  $this->form->getItemByPostVar('lo')->setValue($entry->getLocation());
1017  $this->form->getItemByPostVar('de')->setValue($entry->getDescription());
1018 
1019  include_once 'Services/Booking/classes/class.ilBookingEntry.php';
1020  $booking = new ilBookingEntry($entry->getContextId());
1021 
1022  $this->form->getItemByPostVar('bo')->setValue($booking->getNumberOfBookings());
1023 
1024  $ref_ids = array();
1025  foreach($booking->getTargetObjIds() as $obj_id)
1026  {
1027  $refs = ilObject::_getAllReferences($obj_id);
1028  $ref_ids[] = end($refs);
1029  }
1030  $this->form->getItemByPostVar('tgt')->setValue(implode(',',$ref_ids));
1031 
1032  $deadline = $booking->getDeadlineHours();
1033  $this->form->getItemByPostVar('dead')->setDays(floor($deadline/24));
1034  $this->form->getItemByPostVar('dead')->setHours($deadline%24);
1035 
1036  if($booking->getBookingGroup())
1037  {
1038  $this->form->getItemByPostVar('grp')->setValue($booking->getBookingGroup());
1039  }
1040 
1041  $this->tpl->setContent($this->form->getHTML());
1042  }
1043 
1048  protected function updateMulti()
1049  {
1050  global $ilObjDataCache;
1051 
1052  $this->initFormSequence(self::MODE_MULTI);
1053 
1054  if($this->form->checkInput())
1055  {
1056  $this->form->setValuesByPost();
1057  $apps = explode(';', $_POST['apps']);
1058 
1059  include_once 'Services/Booking/classes/class.ilBookingEntry.php';
1060  include_once 'Services/Calendar/classes/class.ilCalendarEntry.php';
1061 
1062  // do collision-check if max bookings were reduced
1063  // no collision check
1064  $first = $apps;
1065  $first = array_shift($first);
1067  #if($this->form->getInput('bo') < $entry->getNumberOfBookings())
1068  #{
1069  # $this->edit();
1070  # return;
1071  #}
1072 
1073  // create new context
1074  $booking = new ilBookingEntry();
1075 
1076  $booking->setObjId($this->getUserId());
1077  $booking->setNumberOfBookings($this->form->getInput('bo'));
1078 
1079  $deadline = $this->form->getInput('dead');
1080  $deadline = $deadline['dd']*24+$deadline['hh'];
1081  $booking->setDeadlineHours($deadline);
1082 
1083  $tgt = explode(',',$this->form->getInput('tgt'));
1084  $obj_ids = array();
1085  foreach((array) $tgt as $ref_id)
1086  {
1087  if(!trim($ref_id))
1088  {
1089  continue;
1090  }
1091  $obj_id = $ilObjDataCache->lookupObjId($ref_id);
1092  $type = ilObject::_lookupType($obj_id);
1093  $valid_types = array('crs','grp');
1094  if(!$obj_id or !in_array($type, $valid_types))
1095  {
1096  ilUtil::sendFailure($this->lng->txt('cal_ch_unknown_repository_object'));
1097  $this->edit();
1098  return;
1099  }
1100  $obj_ids[] = $obj_id;
1101  }
1102  $booking->setTargetObjIds($obj_ids);
1103 
1104  include_once './Services/Calendar/classes/ConsultationHours/class.ilConsultationHourGroups.php';
1106  {
1107  $booking->setBookingGroup($this->form->getInput('grp'));
1108  }
1109  $booking->save();
1110 
1111 
1112  // update entries
1113  $title = $this->form->getInput('ti');
1114  $location = $this->form->getInput('lo');
1115  $description = $this->form->getInput('de');
1116 
1117  foreach($apps as $item_id)
1118  {
1119  $entry = new ilCalendarEntry($item_id);
1120  $entry->setContextId($booking->getId());
1121  $entry->setTitle($title);
1122  $entry->setLocation($location);
1123  $entry->setDescription($description);
1124  $entry->update();
1125  }
1126 
1128 
1129  ilUtil::sendSuccess($this->lng->txt('settings_saved'), true);
1130  $this->ctrl->redirect($this,'appointmentList');
1131  }
1132  $this->tpl->setContent($this->form->getHTML());
1133  }
1134 
1138  public function confirmDelete()
1139  {
1140  global $tpl;
1141 
1142  if(!isset($_REQUEST['apps']))
1143  {
1144  ilUtil::sendFailure($this->lng->txt('select_one'));
1145  return $this->appointmentList();
1146  }
1147 
1148  include_once('./Services/Utilities/classes/class.ilConfirmationGUI.php');
1149 
1150 
1151  $this->ctrl->saveParameter($this,array('seed','app_id','dt'));
1152 
1153  $confirm = new ilConfirmationGUI();
1154  $confirm->setFormAction($this->ctrl->getFormAction($this));
1155  $confirm->setHeaderText($this->lng->txt('cal_delete_app_sure'));
1156  $confirm->setCancel($this->lng->txt('cancel'),'cancel');
1157 
1158  include_once 'Services/Calendar/classes/class.ilCalendarEntry.php';
1159 
1160  $bookings_available = array();
1161  foreach((array) $_REQUEST['apps'] as $entry_id)
1162  {
1163  $entry = new ilCalendarEntry($entry_id);
1164  $confirm->addItem('apps[]', $entry_id, ilDatePresentation::formatDate($entry->getStart()).', '.$entry->getTitle());
1165 
1166  include_once './Services/Booking/classes/class.ilBookingEntry.php';
1168  {
1169  $bookings_available[] = ilDatePresentation::formatDate($entry->getStart()).', '.$entry->getTitle();
1170  }
1171  }
1172 
1173  if($bookings_available)
1174  {
1175  ilUtil::sendInfo($this->lng->txt('cal_ch_delete_app_booking_info').'<br />'.implode('<br />',$bookings_available));
1176  }
1177 
1178  $confirm->setConfirm($this->lng->txt('delete'),'delete');
1179  $confirm->setCancel($this->lng->txt('cancel'),'appointmentList');
1180 
1181  $tpl->setContent($confirm->getHTML());
1182  }
1183 
1187  public function delete()
1188  {
1189  if(!isset($_POST['apps']))
1190  {
1191  ilUtil::sendFailure($this->lng->txt('select_one'));
1192  return $this->appointmentList();
1193  }
1194 
1195  include_once 'Services/Calendar/classes/class.ilCalendarEntry.php';
1196  include_once 'Services/Calendar/classes/class.ilCalendarCategoryAssignments.php';
1197  foreach($_POST['apps'] as $entry_id)
1198  {
1199  // cancel booking for users
1201  if($booking)
1202  {
1203  foreach($booking->getCurrentBookings($entry_id) as $user_id)
1204  {
1205  include_once './Services/Calendar/classes/ConsultationHours/class.ilConsultationHourUtils.php';
1207  }
1208  }
1209  // remove calendar entries
1210  include_once './Services/Calendar/classes/class.ilCalendarEntry.php';
1211  $entry = new ilCalendarEntry($entry_id);
1212  $entry->delete();
1213 
1215  }
1216 
1218 
1219  ilUtil::sendSuccess($this->lng->txt('cal_deleted_app'), true);
1220  $this->ctrl->redirect($this, 'appointmentList');
1221  }
1222 
1226  public function showProfile()
1227  {
1228  global $tpl, $ilTabs, $ilCtrl;
1229 
1230  $ilTabs->clearTargets();
1231 
1232  $user_id = (int)$_GET['user'];
1233 
1234  include_once 'Services/User/classes/class.ilPublicUserProfileGUI.php';
1235  $profile = new ilPublicUserProfileGUI($user_id);
1236  $profile->setBackUrl($this->getProfileBackUrl());
1237  $tpl->setContent($ilCtrl->getHTML($profile));
1238  }
1239 
1245  protected function getProfileBackUrl()
1246  {
1247  // from repository
1248  if(isset($_REQUEST["ref_id"]))
1249  {
1250  $url = $this->ctrl->getLinkTargetByClass('ilCalendarMonthGUI');
1251  }
1252  // from panel
1253  else if(isset($_GET['panel']))
1254  {
1255  $url = $this->ctrl->getLinkTargetByClass('ilCalendarPresentationGUI');
1256  }
1257  // from appointments
1258  else
1259  {
1260  $url = $this->ctrl->getLinkTarget($this, 'appointmentList');
1261  }
1262  return $url;
1263  }
1264 
1268  public function settings()
1269  {
1270  global $tpl, $ilTabs, $ilHelp;
1271 
1272  $ilHelp->setScreenId("consultation_hours_settings");
1273  $ilTabs->activateTab('ch_settings');
1274 
1275  $form = $this->initSettingsForm();
1276  $tpl->setContent($form->getHTML());
1277  }
1278 
1283  protected function initSettingsForm()
1284  {
1285  global $ilDB, $ilUser;
1286 
1287  include_once './Services/Form/classes/class.ilPropertyFormGUI.php';
1288 
1289  $form = new ilPropertyFormGUI();
1290  $form->setFormAction($this->ctrl->getFormAction($this));
1291 
1292  $mng = new ilTextInputGUI($this->lng->txt('cal_ch_manager'), 'mng');
1293  $mng->setInfo($this->lng->txt('cal_ch_manager_info'));
1294  $form->addItem($mng);
1295 
1296  $mng->setValue(ilConsultationHourAppointments::getManager(true));
1297 
1298  $form->setTitle($this->lng->txt('settings'));
1299  $form->addCommandButton('updateSettings', $this->lng->txt('save'));
1300  // $form->addCommandButton('appointmentList', $this->lng->txt('cancel'));
1301  return $form;
1302  }
1303 
1307  public function updateSettings()
1308  {
1309  global $ilDB, $ilCtrl, $ilUser, $tpl, $ilTabs;
1310 
1311  $form = $this->initSettingsForm();
1312  if($form->checkInput())
1313  {
1314  $mng = $form->getInput('mng');
1316  {
1317  ilUtil::sendSuccess($this->lng->txt('settings_saved'), true);
1318  $ilCtrl->redirect($this, 'settings');
1319  }
1320  else
1321  {
1322  $ilTabs->activateTab('ch_settings');
1323 
1324  ilUtil::sendFailure($this->lng->txt('cal_ch_unknown_user'));
1325  $field = $form->getItemByPostVar('mng');
1326  $field->setValue($mng);
1327  $tpl->setContent($form->getHTML());
1328  return;
1329  }
1330  }
1331  }
1332 }
1333 ?>
static sendSuccess($a_info="", $a_keep=false)
Send Success Message to Screen.
confirmRejectBooking($a_send_notification=true)
Show delete booking confirmation.
Consultation hours editor.
showProfile()
show public profile of given user
This class represents a duration (typical hh:mm:ss) property in a property form.
bookingList()
Show list of bookings.
const IL_CAL_FREQ_MONTHLY
Model for a calendar entry.
$_POST['username']
Definition: cron.php:12
static getManager($a_as_name=false)
Get consultation hour manager for current user.
$_SESSION["AccountId"]
This class represents a selection list property in a property form.
This class represents a property form user interface.
const IL_CAL_TRANSLATION_SYSTEM
$_GET["client_id"]
$tbl
Definition: example_048.php:81
$location
Definition: buildRTE.php:44
assignUsersToAppointments(array $users)
Assign users to multiple appointments.
initGroupForm($a_group_id=0)
Init new/update group form.
This class represents an input GUI for recurring events/appointments (course events or calendar appoi...
confirmDeleteGroup()
Confirm delete type $ilCtrl type $ilTabs.
static getAppointmentIds($a_user_id, $a_context_id=NULL, $a_start=NULL, $a_type=NULL, $a_check_owner=true)
Get all appointment ids.
edit()
Edit multiple sequence items.
$cmd
Definition: sahs_server.php:35
static removeObsoleteEntries()
Remove unused booking entries.
Booking definition.
confirmDeleteBooking()
Show delete booking confirmation.
static getInstanceByCalendarEntryId($a_id)
Get instance by calendar entry.
$url
Definition: shib_logout.php:72
const IL_CAL_UNIX
static _getAllReferences($a_id)
get all reference ids of object
setShowMinutes($a_showminutes)
Set Show Minutes.
static setManager($a_user_name)
Set consultation hour manager for current user.
confirmDelete()
confirm delete for multiple entries
_lookupFullname($a_user_id)
Lookup Full Name.
This class represents a date/time property in a property form.
global $tpl
Definition: ilias.php:8
global $ilCtrl
Definition: ilias.php:18
setInfo($a_info)
Set Information Text.
static getGroupSelectOptions($a_user_id)
Get group selection options.
static sendInfo($a_info="", $a_keep=false)
Send Info Message to Screen.
calculateDateList(ilDateTime $a_start, ilDateTime $a_end, $a_limit=-1)
calculate date list
groupList()
Show consultation hour group type $ilToolbar.
createAppointments(ilBookingEntry $booking)
Create calendar appointments.
searchUsersForAppointments()
start searching for users
const IL_CAL_DAY
This class represents a hidden form property in a property form.
static getGroupsOfUser($a_user_id)
Get a all groups of an user.
GUI class for public user profile presentation.
static getNamePresentation($a_user_id, $a_user_image=false, $a_profile_link=false, $a_profile_back_link="", $a_force_first_lastname=false, $a_omit_login=false, $a_sortable=true, $a_return_data_array=false)
Default behaviour is:
static lookupBookingsForAppointment($a_app_id)
Lookup booked users for appointment type $ilDB.
if(!is_array($argv)) $options
static getManagedUsers()
Get all managed consultation hours users for current users.
Calculates an ilDateList for a given calendar entry and recurrence rule.
List of dates.
This class represents a number property in a property form.
const IL_CAL_FREQ_DAILY
Model of calendar entry recurrcences.
setSubTabs()
Set sub tabs type $ilTabs type $ilCtrl.
setSize($a_size)
Set Size.
This class represents a text property in a property form.
static formatDate(ilDateTime $date)
Format a date public.
static initDomEvent()
Init YUI DomEvent.
Date and time handling
addGroup(ilPropertyFormGUI $form=null)
Show add group form type $ilToolbar type $ilTabs.
Consultation hours administration.
sendInfoAboutUnassignedUsers($unassigned)
Send info message about unassigned users.
static getAppointmentIdsByGroup($a_user_id, $a_ch_group_id, ilDateTime $start=null)
Get appointment ids by consultation hour group.
static _deleteByAppointmentId($a_app_id)
Delete appointment assignment.
setOptions($a_options)
Set Options.
static lookupBookingsOfUser($a_app_ids, $a_usr_id, ilDateTime $start=null)
Lookup bookings if user.
static _lookupType($a_id, $a_reference=false)
lookup object type
static sendFailure($a_info="", $a_keep=false)
Send Failure Message to Screen.
static cancelBooking($a_usr_id, $a_app_id, $a_send_notification=true)
Cancel a booking.
setSize($a_size)
Set Size.
appointmentList()
Show settings of consultation hours.
global $ilUser
Definition: imgupload.php:15
$ref_id
Definition: sahs_server.php:39
editGroup(ilPropertyFormGUI $form=null)
Edit group type $ilCtrl.
global $lng
Definition: privfeed.php:40
This class represents a text area property in a property form.
global $ilDB
rejectBooking($a_send_notification=true)
static initDefaultCalendarByType($a_type_id, $a_usr_id, $a_title, $a_create=false)
Init the default calendar for given type and user.
if($_REQUEST['ilias_path']) define('ILIAS_HTTP_PATH' $_REQUEST['ilias_path']
Definition: index.php:7
setEnabledSubForms($a_sub_forms)
set enabled subforms
static getCountGroupsOfUser($a_user_id)
Get number of consultation hour groups type $ilDB.
createSequence()
Create new sequence.
$GLOBALS['PHPCAS_CLIENT']
This global variable is used by the interface class phpCAS.
Definition: CAS.php:276
assignUsersToAppointment(array $users, $a_app=0, $a_redirect=true)
Assign users to an appointment.
Booking period Used for calculation of recurring events.
updateMulti()
Update multiple sequence items.
const IL_CAL_FREQ_WEEKLY
updateGroup()
Update group type $ilCtrl type $tpl type $ilTabs.
setShowTime($a_showtime)
Set Show Time Information.
Confirmation screen class.
static bookAppointment($a_usr_id, $a_app_id)
Book an appointment.
getProfileBackUrl()
Build context-sensitive profile back url.