ILIAS  trunk Revision v11.0_alpha-2638-g80c1d007f79
class.ilObjCourse.php
Go to the documentation of this file.
1 <?php
2 
24 {
25  public const int CAL_REG_START = 1;
26  public const int CAL_REG_END = 2;
27  public const int CAL_ACTIVATION_START = 3;
28  public const int CAL_ACTIVATION_END = 4;
29  public const int CAL_COURSE_START = 5;
30  public const int CAL_COURSE_END = 6;
31  public const int CAL_COURSE_TIMING_START = 7;
32  public const int CAL_COURSE_TIMING_END = 8;
33 
34  public const int STATUS_DETERMINATION_LP = 1;
35  public const int STATUS_DETERMINATION_MANUAL = 2;
36 
37  private string $contact_consultation = '';
38  private string $contact_phone = '';
39  private string $contact_email = '';
40  private string $contact_name = '';
41  private string $contact_responsibility = '';
43  private int $subscription_start = 0;
44  private int $subscription_end = 0;
45  private int $subscription_type = 0;
46  private string $subscription_password = '';
47  private int $view_mode = 0;
48  private bool $waiting_list = false;
50  private int $subscription_max_members = 0;
51  private bool $abo = true;
52  private bool $show_members = true;
53  private string $message = '';
54  private bool $course_start_time_indication = true;
56  private string $important = '';
57  private string $syllabus = '';
59  private string $latitude = '';
60  private string $longitude = '';
61  private int $locationzoom = 0;
62  private bool $enablemap = false;
63 
64  private int $session_limit = 0;
65  private int $session_prev = -1;
66  private int $session_next = -1;
67 
68  private string $reg_access_code = '';
69  private bool $reg_access_code_enabled = false;
70  private int $status_dt = 0;
71 
73 
74  private bool $crs_start_time_indication = false;
75 
77  private ?ilDateTime $crs_end = null;
78  private ?ilDate $leave_end = null;
79  private int $min_members = 0;
80  private bool $auto_fill_from_waiting = false;
81  private bool $member_export = false;
84  private bool $auto_notification = true;
85  private ?string $target_group = null;
86  private int $activation_start = 0;
87  private int $activation_end = 0;
88  private bool $activation_visibility = false;
89 
92 
93  private array $local_roles = [];
94 
95  public function __construct(int $a_id = 0, bool $a_call_by_reference = true)
96  {
97  global $DIC;
98 
99  $this->setStatusDetermination(self::STATUS_DETERMINATION_LP);
100 
101  $this->type = "crs";
102  $this->course_logger = $DIC->logger()->crs();
103  parent::__construct($a_id, $a_call_by_reference);
104  }
105 
106  public static function lookupTutorialBlockSettingEabled(int $a_obj_id): bool
107  {
108  $query = 'SELECT tutorial_support_block FROM crs_settings'
109  . ' WHERE obj_id = ' . $GLOBALS['DIC']['ilDB']->quote($a_obj_id, 'integer');
110  $res = $GLOBALS['DIC']['ilDB']->query($query);
111  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
112  return (bool) $row->tutorial_support_block;
113  }
114  return false;
115  }
116 
117  public static function lookupShowMembersEnabled(int $a_obj_id): bool
118  {
119  $query = 'SELECT show_members FROM crs_settings ' .
120  'WHERE obj_id = ' . $GLOBALS['DIC']['ilDB']->quote($a_obj_id, 'integer');
121  $res = $GLOBALS['DIC']['ilDB']->query($query);
122  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
123  return (bool) $row->show_members;
124  }
125  return false;
126  }
127 
128  public function getShowMembersExport(): bool
129  {
130  return $this->member_export;
131  }
132 
133  public function setShowMembersExport(bool $a_mem_export): void
134  {
135  $this->member_export = $a_mem_export;
136  }
137 
138  public function getRegistrationAccessCode(): string
139  {
140  return $this->reg_access_code;
141  }
142 
143  public function setRegistrationAccessCode(string $a_code): void
144  {
145  $this->reg_access_code = $a_code;
146  }
147 
148  public function isRegistrationAccessCodeEnabled(): bool
149  {
151  }
152 
153  public function enableRegistrationAccessCode(bool $a_status): void
154  {
155  $this->reg_access_code_enabled = $a_status;
156  }
157 
158  public function getImportantInformation(): string
159  {
160  return $this->important;
161  }
162 
163  public function setImportantInformation(string $a_info): void
164  {
165  $this->important = $a_info;
166  }
167 
168  public function getSyllabus(): string
169  {
170  return $this->syllabus;
171  }
172 
173  public function setSyllabus(string $a_syllabus): void
174  {
175  $this->syllabus = $a_syllabus;
176  }
177 
178  public function getTargetGroup(): ?string
179  {
180  return $this->target_group;
181  }
182 
183  public function setTargetGroup(?string $a_tg): void
184  {
185  $this->target_group = $a_tg;
186  }
187 
188  public function getContactName(): string
189  {
190  return $this->contact_name;
191  }
192 
193  public function setContactName(string $a_cn): void
194  {
195  $this->contact_name = $a_cn;
196  }
197 
198  public function getContactConsultation(): string
199  {
201  }
202 
203  public function setContactConsultation(string $a_value): void
204  {
205  $this->contact_consultation = $a_value;
206  }
207 
208  public function getContactPhone(): string
209  {
210  return $this->contact_phone;
211  }
212 
213  public function setContactPhone(string $a_value): void
214  {
215  $this->contact_phone = $a_value;
216  }
217 
218  public function getContactEmail(): string
219  {
220  return $this->contact_email;
221  }
222 
223  public function setContactEmail(string $a_value): void
224  {
225  $this->contact_email = $a_value;
226  }
227 
228  public function getContactResponsibility(): string
229  {
231  }
232 
233  public function setContactResponsibility(string $a_value): void
234  {
235  $this->contact_responsibility = $a_value;
236  }
237 
238  public function getActivationUnlimitedStatus(): bool
239  {
240  return !$this->getActivationStart() || !$this->getActivationEnd();
241  }
242 
243  public function getActivationStart(): int
244  {
246  }
247 
248  public function setActivationStart(int $a_value): void
249  {
250  $this->activation_start = $a_value;
251  }
252 
253  public function getActivationEnd(): int
254  {
255  return $this->activation_end;
256  }
257 
258  public function setActivationEnd(int $a_value): void
259  {
260  $this->activation_end = $a_value;
261  }
262 
263  public function setActivationVisibility(bool $a_value): void
264  {
265  $this->activation_visibility = $a_value;
266  }
267 
268  public function getActivationVisibility(): bool
269  {
271  }
272 
274  {
276  }
277 
278  public function setSubscriptionLimitationType(int $a_type): void
279  {
280  $this->subscription_limitation_type = $a_type;
281  }
282 
283  public function getSubscriptionUnlimitedStatus(): bool
284  {
285  return $this->subscription_limitation_type == ilCourseConstants::IL_CRS_SUBSCRIPTION_UNLIMITED;
286  }
287 
288  public function getSubscriptionStart(): int
289  {
291  }
292 
293  public function setSubscriptionStart(int $a_value): void
294  {
295  $this->subscription_start = $a_value;
296  }
297 
298  public function getSubscriptionEnd(): int
299  {
301  }
302 
303  public function setSubscriptionEnd(int $a_value): void
304  {
305  $this->subscription_end = $a_value;
306  }
307 
308  public function getSubscriptionType(): int
309  {
310  return $this->subscription_type ?: ilCourseConstants::IL_CRS_SUBSCRIPTION_DIRECT;
311  }
312 
313  public function setSubscriptionType(int $a_value): void
314  {
315  $this->subscription_type = $a_value;
316  }
317 
318  public function getSubscriptionPassword(): string
319  {
321  }
322 
323  public function setSubscriptionPassword(string $a_value): void
324  {
325  $this->subscription_password = $a_value;
326  }
327 
328  public function enabledObjectiveView(): bool
329  {
330  return $this->view_mode == ilCourseConstants::IL_CRS_VIEW_OBJECTIVE;
331  }
332 
333  public function enabledWaitingList(): bool
334  {
335  return $this->waiting_list;
336  }
337 
338  public function enableWaitingList(bool $a_status): void
339  {
340  $this->waiting_list = $a_status;
341  }
342 
343  public function inSubscriptionTime(): bool
344  {
345  if ($this->getSubscriptionUnlimitedStatus()) {
346  return true;
347  }
348  if (time() > $this->getSubscriptionStart() and time() < $this->getSubscriptionEnd()) {
349  return true;
350  }
351  return false;
352  }
353 
354  public function enableSessionLimit(int $a_status): void
355  {
356  $this->session_limit = $a_status;
357  }
358 
359  public function isSessionLimitEnabled(): bool
360  {
361  return (bool) $this->session_limit;
362  }
363 
364  public function enableSubscriptionMembershipLimitation(bool $a_status): void
365  {
366  $this->subscription_membership_limitation = $a_status;
367  }
368 
369  public function setNumberOfPreviousSessions(int $a_num): void
370  {
371  $this->session_prev = $a_num;
372  }
373 
374  public function getNumberOfPreviousSessions(): int
375  {
376  return $this->session_prev;
377  }
378 
379  public function setNumberOfNextSessions(int $a_num): void
380  {
381  $this->session_next = $a_num;
382  }
383 
384  public function getNumberOfNextSessions(): int
385  {
386  return $this->session_next;
387  }
388 
389  public function isSubscriptionMembershipLimited(): bool
390  {
392  }
393 
394  public function getSubscriptionMaxMembers(): int
395  {
397  }
398 
399  public function setSubscriptionMaxMembers(int $a_value): void
400  {
401  $this->subscription_max_members = $a_value;
402  }
403 
404  public static function _isSubscriptionNotificationEnabled(int $a_course_id): bool
405  {
406  global $DIC;
407 
408  $ilDB = $DIC->database();
409  $query = "SELECT * FROM crs_settings " .
410  "WHERE obj_id = " . $ilDB->quote($a_course_id, 'integer') . " " .
411  "AND sub_notify = 1";
412  $res = $ilDB->query($query);
413  return (bool) $res->numRows();
414  }
415 
416  public function getSubscriptionNotify(): bool
417  {
418  return true;
419  }
420 
421  public function setViewMode(int $a_mode): void
422  {
423  $this->view_mode = $a_mode;
424  }
425 
426  public function getViewMode(): int
427  {
428  return $this->view_mode;
429  }
430 
431  public static function lookupTimingMode(int $a_obj_id): int
432  {
433  global $DIC;
434 
435  $ilDB = $DIC['ilDB'];
436 
437  $query = 'SELECT timing_mode FROM crs_settings ' .
438  'WHERE obj_id = ' . $ilDB->quote($a_obj_id, 'integer');
439  $res = $ilDB->query($query);
440 
441  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
442  return (int) $row->timing_mode;
443  }
445  }
446 
447  public function setTimingMode(int $a_mode): void
448  {
449  $this->timing_mode = $a_mode;
450  }
451 
452  public function getTimingMode(): int
453  {
454  return $this->timing_mode;
455  }
456 
457  public function setTutorialSupportBlockSettingValue(int $value): void
458  {
459  $this->tutorial_support_block_setting_value = $value;
460  }
461 
463  {
465  }
466 
467  public static function _lookupViewMode(int $a_id): int
468  {
469  global $DIC;
470 
471  $ilDB = $DIC['ilDB'];
472 
473  $query = "SELECT view_mode FROM crs_settings WHERE obj_id = " . $ilDB->quote($a_id, 'integer') . " ";
474  $res = $ilDB->query($query);
475  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
476  return $row->view_mode;
477  }
478  return false;
479  }
480 
481  public static function _lookupAboStatus(int $a_id): bool
482  {
483  global $DIC;
484 
485  $ilDB = $DIC['ilDB'];
486 
487  $query = "SELECT abo FROM crs_settings WHERE obj_id = " . $ilDB->quote($a_id, 'integer') . " ";
488  $res = $ilDB->query($query);
489  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
490  return $row->abo;
491  }
492  return false;
493  }
494 
495  public function setAboStatus(bool $a_status): void
496  {
497  $this->abo = $a_status;
498  }
499 
500  public function getAboStatus(): bool
501  {
502  return $this->abo;
503  }
504 
505  public function setShowMembers(bool $a_status): void
506  {
507  $this->show_members = $a_status;
508  }
509 
510  public function getShowMembers(): bool
511  {
512  return $this->show_members;
513  }
514 
515  public function setMailToMembersType(int $a_type): void
516  {
517  $this->mail_members = $a_type;
518  }
519 
520  public function getMailToMembersType(): int
521  {
522  return $this->mail_members;
523  }
524 
525  public function getMessage(): string
526  {
527  return $this->message;
528  }
529 
530  public function setMessage(string $a_message): void
531  {
532  $this->message = $a_message;
533  }
534 
535  public function appendMessage(string $a_message): void
536  {
537  if ($this->getMessage()) {
538  $this->message .= "<br /> ";
539  }
540  $this->message .= $a_message;
541  }
542 
543  public function isActivated(): bool
544  {
545  if ($this->getOfflineStatus()) {
546  return false;
547  }
548  if ($this->getActivationUnlimitedStatus()) {
549  return true;
550  }
551  if (time() < $this->getActivationStart() or
552  time() > $this->getActivationEnd()) {
553  return false;
554  }
555  return true;
556  }
557 
561  public static function _isActivated(int $a_obj_id): bool
562  {
563  return ilObjCourseAccess::_isActivated($a_obj_id);
564  }
565 
569  public static function _registrationEnabled(int $a_obj_id): bool
570  {
571  return ilObjCourseAccess::_registrationEnabled($a_obj_id);
572  }
573 
574  public function read(): void
575  {
576  parent::read();
578  $this->__readSettings();
579  }
580 
581  public function create(): int
582  {
583  global $DIC;
584 
585  $ilAppEventHandler = $DIC['ilAppEventHandler'];
586 
587  $id = parent::create();
588 
589  $this->createMetaData();
590  $this->__createDefaultSettings();
591  $this->app_event_handler->raise(
592  'components/ILIAS/Course',
593  'create',
594  array('object' => $this,
595  'obj_id' => $this->getId(),
596  'appointments' => $this->prepareAppointments('create')
597  )
598  );
599 
600  return $id;
601  }
602 
603  public function setLatitude(string $a_latitude): void
604  {
605  $this->latitude = $a_latitude;
606  }
607 
608  public function getLatitude(): string
609  {
610  return $this->latitude;
611  }
612 
613  public function setLongitude(string $a_longitude): void
614  {
615  $this->longitude = $a_longitude;
616  }
617 
618  public function getLongitude(): string
619  {
620  return $this->longitude;
621  }
622 
623  public function setLocationZoom(int $a_locationzoom): void
624  {
625  $this->locationzoom = $a_locationzoom;
626  }
627 
628  public function getLocationZoom(): int
629  {
630  return $this->locationzoom;
631  }
632 
633  public function setEnableCourseMap(bool $a_enablemap): void
634  {
635  $this->enablemap = $a_enablemap;
636  }
637 
638  public function getEnableMap(): bool
639  {
640  return $this->getEnableCourseMap();
641  }
642 
643  public function getEnableCourseMap(): bool
644  {
645  return $this->enablemap;
646  }
647 
648  public function setCoursePeriod(?ilDateTime $start = null, ?ilDateTime $end = null): void
649  {
650  if (
651  ($start instanceof \ilDate && !$end instanceof ilDate) ||
652  ($end instanceof \ilDate && !$start instanceof ilDate)
653  ) {
654  throw new InvalidArgumentException('Different date types not supported.');
655  }
656 
657  if ($start instanceof \ilDate) {
658  $this->toggleCourseStartTimeIndication(false);
659  } else {
660  $this->toggleCourseStartTimeIndication(true);
661  }
662  $this->setCourseStart($start);
663  $this->setCourseEnd($end);
664  }
665 
666  protected function toggleCourseStartTimeIndication(bool $time_indication): void
667  {
668  $this->course_start_time_indication = $time_indication;
669  }
670 
671  public function getCourseStartTimeIndication(): bool
672  {
674  }
675 
676  protected function setCourseStart(?ilDateTime $a_value = null): void
677  {
678  $this->crs_start = $a_value;
679  }
680 
681  public function getCourseStart(): ?ilDateTime
682  {
683  return $this->crs_start;
684  }
685 
686  protected function setCourseEnd(?ilDateTime $a_value = null): void
687  {
688  $this->crs_end = $a_value;
689  }
690 
691  public function getCourseEnd(): ?ilDateTime
692  {
693  return $this->crs_end;
694  }
695 
696  public function setCancellationEnd(?ilDate $a_value = null): void
697  {
698  $this->leave_end = $a_value;
699  }
700 
701  public function getCancellationEnd(): ?ilDate
702  {
703  return $this->leave_end;
704  }
705 
706  public function setSubscriptionMinMembers(int $a_value): void
707  {
708  if ($a_value !== null) {
709  $a_value = $a_value;
710  }
711  $this->min_members = $a_value;
712  }
713 
714  public function getSubscriptionMinMembers(): int
715  {
716  return $this->min_members;
717  }
718 
719  public function setWaitingListAutoFill(bool $a_value): void
720  {
721  $this->auto_fill_from_waiting = $a_value;
722  }
723 
724  public function hasWaitingListAutoFill(): bool
725  {
727  }
728 
732  public function cloneObject(int $target_id, int $copy_id = 0, bool $omit_tree = false): ?ilObject
733  {
734  global $DIC;
735 
736  $new_obj = parent::cloneObject($target_id, $copy_id, $omit_tree);
737 
738  $this->cloneAutoGeneratedRoles($new_obj);
739  $this->cloneMetaData($new_obj);
740 
741  $new_obj->getMemberObject()->add($this->user->getId(), ilParticipants::IL_CRS_ADMIN);
742  $new_obj->getMemberObject()->updateContact($this->user->getId(), 1);
743 
744  $cwo = ilCopyWizardOptions::_getInstance($copy_id);
745  if ($cwo->isRootNode($this->getRefId())) {
746  $this->setOfflineStatus(true);
747  }
748 
749  $this->cloneSettings($new_obj);
750  ilCourseDefinedFieldDefinition::_clone($this->getId(), $new_obj->getId());
751  ilCourseFile::_cloneFiles($this->getId(), $new_obj->getId());
752  $obj_settings = new ilLPObjSettings($this->getId());
753  $obj_settings->cloneSettings($new_obj->getId());
754  unset($obj_settings);
755  $pathFactory = new ilCertificatePathFactory();
756  $templateRepository = new ilCertificateTemplateDatabaseRepository($this->db);
757 
758  $cloneAction = new ilCertificateCloneAction(
759  $this->db,
760  $pathFactory,
761  $templateRepository,
763  );
764  $cloneAction->cloneCertificate($this, $new_obj);
765 
766  $book_service = new ilBookingService();
767  $book_service->cloneSettings($this->getId(), $new_obj->getId());
768 
769  $badges = ilBadge::getInstancesByParentId($this->getId());
770  foreach ($badges as $badge) {
771  $badge->clone($new_obj->getId());
772  }
773 
774  return $new_obj;
775  }
776 
780  public function cloneDependencies(int $target_id, int $copy_id): bool
781  {
782  parent::cloneDependencies($target_id, $copy_id);
783 
784  // Clone course start objects
785  $start = new ilContainerStartObjects($this->getRefId(), $this->getId());
786  $start->cloneDependencies($target_id, $copy_id);
787 
788  // Clone course item settings
789  ilObjectActivation::cloneDependencies($this->getRefId(), $target_id, $copy_id);
790 
791  // clone objective settings
792  ilLOSettings::cloneSettings($copy_id, $this->getId(), ilObject::_lookupObjId($target_id));
793 
794  // Clone course learning objectives
795  $crs_objective = new ilCourseObjective($this);
796  $crs_objective->ilClone($target_id, $copy_id);
797 
798  // clone membership limitation
799  foreach (\ilObjCourseGrouping::_getGroupings($this->getId()) as $grouping_id) {
800  $this->course_logger->info('Handling grouping id: ' . $grouping_id);
801  $grouping = new \ilObjCourseGrouping($grouping_id);
802  $grouping->cloneGrouping($target_id, $copy_id);
803  }
804  return true;
805  }
806 
810  public function cloneAutoGeneratedRoles(ilObject $new_obj): void
811  {
812  $admin = $this->getDefaultAdminRole();
813  $new_admin = $new_obj->getDefaultAdminRole();
814 
815  if (!$admin || !$new_admin || !$this->getRefId() || !$new_obj->getRefId()) {
816  $this->course_logger->debug('Error cloning auto generated role: il_crs_admin');
817  }
818  $this->rbac_admin->copyRolePermissions($admin, $this->getRefId(), $new_obj->getRefId(), $new_admin, true);
819  $this->course_logger->debug('Finished copying of role crs_admin.');
820 
821  $tutor = $this->getDefaultTutorRole();
822  $new_tutor = $new_obj->getDefaultTutorRole();
823  if (!$tutor || !$new_tutor) {
824  $this->course_logger->info('Error cloning auto generated role: il_crs_tutor');
825  }
826  $this->rbac_admin->copyRolePermissions($tutor, $this->getRefId(), $new_obj->getRefId(), $new_tutor, true);
827  $this->course_logger->info('Finished copying of role crs_tutor.');
828 
829  $member = $this->getDefaultMemberRole();
830  $new_member = $new_obj->getDefaultMemberRole();
831  if (!$member || !$new_member) {
832  $this->course_logger->debug('Error cloning auto generated role: il_crs_member');
833  }
834  $this->rbac_admin->copyRolePermissions($member, $this->getRefId(), $new_obj->getRefId(), $new_member, true);
835  $this->course_logger->debug('Finished copying of role crs_member.');
836  }
837 
838  public function validate(): bool
839  {
840  $this->setMessage('');
841 
843  $this->getSubscriptionStart() > $this->getSubscriptionEnd()) {
844  $this->appendMessage($this->lng->txt("subscription_times_not_valid"));
845  }
847  $this->appendMessage($this->lng->txt("crs_password_required"));
848  }
849  if ($this->isSubscriptionMembershipLimited()) {
850  if ($this->getSubscriptionMinMembers() <= 0 && $this->getSubscriptionMaxMembers() <= 0) {
851  $this->appendMessage($this->lng->txt("crs_max_and_min_members_needed"));
852  }
853  if ($this->getSubscriptionMaxMembers() <= 0 && $this->enabledWaitingList()) {
854  $this->appendMessage($this->lng->txt("crs_max_members_needed"));
855  }
856  if ($this->getSubscriptionMaxMembers() > 0 && $this->getSubscriptionMinMembers() > $this->getSubscriptionMaxMembers()) {
857  $this->appendMessage($this->lng->txt("crs_max_and_min_members_invalid"));
858  }
859  }
860  if (!$this->getTitle() || !$this->getStatusDetermination()) {
861  $this->appendMessage($this->lng->txt('err_check_input'));
862  }
863  if (($this->getCourseStart() && !$this->getCourseEnd()) ||
864  (!$this->getCourseStart() && $this->getCourseEnd()) ||
865  ($this->getCourseStart() && $this->getCourseEnd() && $this->getCourseStart()->get(IL_CAL_UNIX) > $this->getCourseEnd()->get(IL_CAL_UNIX))) {
866  $this->appendMessage($this->lng->txt("crs_course_period_not_valid"));
867  }
868 
869  return strlen($this->getMessage()) > 0;
870  }
871 
872  public function validateInfoSettings(): bool
873  {
874  $error = false;
875  if ($this->getContactEmail()) {
876  $emails = explode(",", $this->getContactEmail());
877 
878  foreach ($emails as $email) {
879  $email = trim($email);
880  if (!ilUtil::is_email($email) && !ilObjUser::getUserIdByLogin($email)) {
881  $this->error->appendMessage($this->lng->txt('contact_email_not_valid') . " '" . $email . "'");
882  $error = true;
883  }
884  }
885  }
886  return !$error;
887  }
888 
889  public function hasContactData(): bool
890  {
891  return strlen($this->getContactName()) || strlen($this->getContactResponsibility()) || strlen($this->getContactEmail()) || strlen($this->getContactPhone()) || strlen($this->getContactConsultation());
892  }
893 
898  public function delete(): bool
899  {
900  // always call parent delete function first!!
901  if (!parent::delete()) {
902  return false;
903  }
904 
905  // delete meta data
906  $this->deleteMetaData();
907 
908  // put here course specific stuff
909 
910  $this->__deleteSettings();
911 
913 
915 
917 
919 
921 
922  $this->app_event_handler->raise(
923  'components/ILIAS/Course',
924  'delete',
925  array('object' => $this,
926  'obj_id' => $this->getId(),
927  'appointments' => $this->prepareAppointments('delete')
928  )
929  );
930  return true;
931  }
932 
936  public function update(): bool
937  {
938  $sorting = new ilContainerSortingSettings($this->getId());
939  $sorting->setSortMode($this->getOrderType());
940  $sorting->update();
941 
942  $this->updateMetaData();
943  $this->updateSettings();
944  parent::update();
945 
946  $this->app_event_handler->raise(
947  'components/ILIAS/Course',
948  'update',
949  array('object' => $this,
950  'obj_id' => $this->getId(),
951  'appointments' => $this->prepareAppointments('update')
952  )
953  );
954  return true;
955  }
956 
959  public function updateSettings(): void
960  {
961  $query = "SELECT * FROM crs_settings WHERE obj_id = " . $this->db->quote($this->getId(), 'integer') . " ";
962  $res = $this->db->query($query);
963 
964  if (!$res->numRows()) {
965  $this->__createDefaultSettings();
966  }
967 
968  $query = "UPDATE crs_settings SET " .
969  'tutorial_support_block = ' . $this->db->quote($this->getTutorialSupportBlockSettingValue(), 'integer') . ", " .
970  "syllabus = " . $this->db->quote($this->getSyllabus(), 'text') . ", " .
971  "contact_name = " . $this->db->quote($this->getContactName(), 'text') . ", " .
972  "contact_responsibility = " . $this->db->quote($this->getContactResponsibility(), 'text') . ", " .
973  "contact_phone = " . $this->db->quote($this->getContactPhone(), 'text') . ", " .
974  "contact_email = " . $this->db->quote($this->getContactEmail(), 'text') . ", " .
975  "contact_consultation = " . $this->db->quote($this->getContactConsultation(), 'text') . ", " .
976  "activation_type = " . $this->db->quote(!$this->getOfflineStatus(), 'integer') . ", " .
977  "sub_limitation_type = " . $this->db->quote($this->getSubscriptionLimitationType(), 'integer') . ", " .
978  "sub_start = " . $this->db->quote($this->getSubscriptionStart(), 'integer') . ", " .
979  "sub_end = " . $this->db->quote($this->getSubscriptionEnd(), 'integer') . ", " .
980  "sub_type = " . $this->db->quote($this->getSubscriptionType(), 'integer') . ", " .
981  "sub_password = " . $this->db->quote($this->getSubscriptionPassword(), 'text') . ", " .
982  "sub_mem_limit = " . $this->db->quote((int) $this->isSubscriptionMembershipLimited(), 'integer') . ", " .
983  "sub_max_members = " . $this->db->quote($this->getSubscriptionMaxMembers(), 'integer') . ", " .
984  "sub_notify = " . $this->db->quote($this->getSubscriptionNotify(), 'integer') . ", " .
985  "view_mode = " . $this->db->quote($this->getViewMode(), 'integer') . ", " .
986  'timing_mode = ' . $this->db->quote($this->getTimingMode(), 'integer') . ', ' .
987  "abo = " . $this->db->quote($this->getAboStatus(), 'integer') . ", " .
988  "waiting_list = " . $this->db->quote($this->enabledWaitingList(), 'integer') . ", " .
989  "important = " . $this->db->quote($this->getImportantInformation(), 'text') . ", " .
990  'target_group = ' . $this->db->quote($this->getTargetGroup(), \ilDBConstants::T_TEXT) . ', ' .
991  "show_members = " . $this->db->quote($this->getShowMembers(), 'integer') . ", " .
992  "show_members_export = " . $this->db->quote($this->getShowMembersExport(), 'integer') . ", " .
993  "latitude = " . $this->db->quote($this->getLatitude(), 'text') . ", " .
994  "longitude = " . $this->db->quote($this->getLongitude(), 'text') . ", " .
995  "location_zoom = " . $this->db->quote($this->getLocationZoom(), 'integer') . ", " .
996  "enable_course_map = " . $this->db->quote((int) $this->getEnableCourseMap(), 'integer') . ", " .
997  'session_limit = ' . $this->db->quote($this->isSessionLimitEnabled(), 'integer') . ', ' .
998  'session_prev = ' . $this->db->quote($this->getNumberOfPreviousSessions(), 'integer') . ', ' .
999  'session_next = ' . $this->db->quote($this->getNumberOfNextSessions(), 'integer') . ', ' .
1000  'reg_ac_enabled = ' . $this->db->quote($this->isRegistrationAccessCodeEnabled(), 'integer') . ', ' .
1001  'reg_ac = ' . $this->db->quote($this->getRegistrationAccessCode(), 'text') . ', ' .
1002  'auto_notification = ' . $this->db->quote((int) $this->getAutoNotification(), 'integer') . ', ' .
1003  'status_dt = ' . $this->db->quote($this->getStatusDetermination(), ilDBConstants::T_INTEGER) . ', ' .
1004  'mail_members_type = ' . $this->db->quote($this->getMailToMembersType(), 'integer') . ', ' .
1005  'period_start = ' . $this->db->quote(
1008  ) . ', ' .
1009  'period_end = ' . $this->db->quote(
1012  ) . ', ' .
1013  'period_time_indication = ' . $this->db->quote(
1014  $this->getCourseStartTimeIndication() ? 1 : 0,
1016  ) . ', ' .
1017  'auto_wait = ' . $this->db->quote((int) $this->hasWaitingListAutoFill(), 'integer') . ', ' .
1018  'leave_end = ' . $this->db->quote(
1019  ($this->getCancellationEnd() && !$this->getCancellationEnd()->isNull()) ? $this->getCancellationEnd()->get(IL_CAL_UNIX) : null,
1020  'integer'
1021  ) . ', ' .
1022  'min_members = ' . $this->db->quote($this->getSubscriptionMinMembers(), 'integer') . ' ' .
1023  "WHERE obj_id = " . $this->db->quote($this->getId(), 'integer');
1024 
1025  $res = $this->db->manipulate($query);
1026 
1027  // moved activation to ilObjectActivation
1028  if ($this->ref_id ?? false) {
1029  ilObjectActivation::getItem($this->ref_id);
1030 
1031  $item = new ilObjectActivation();
1032  if (!$this->getActivationStart() || !$this->getActivationEnd()) {
1033  $item->setTimingType(ilObjectActivation::TIMINGS_DEACTIVATED);
1034  } else {
1035  $item->setTimingType(ilObjectActivation::TIMINGS_ACTIVATION);
1036  $item->setTimingStart($this->getActivationStart());
1037  $item->setTimingEnd($this->getActivationEnd());
1038  $item->toggleVisible($this->getActivationVisibility());
1039  }
1040  $item->update($this->ref_id);
1041  }
1042  }
1043 
1044  public function cloneSettings(ilObject $new_obj): void
1045  {
1046  $new_obj->setTutorialSupportBlockSettingValue($this->getTutorialSupportBlockSettingValue());
1047  $new_obj->setSyllabus($this->getSyllabus());
1048  $new_obj->setContactName($this->getContactName());
1049  $new_obj->setContactResponsibility($this->getContactResponsibility());
1050  $new_obj->setContactPhone($this->getContactPhone());
1051  $new_obj->setContactEmail($this->getContactEmail());
1052  $new_obj->setContactConsultation($this->getContactConsultation());
1053  $new_obj->setOfflineStatus($this->getOfflineStatus()); // #9914
1054  $new_obj->setActivationStart($this->getActivationStart());
1055  $new_obj->setActivationEnd($this->getActivationEnd());
1056  $new_obj->setActivationVisibility($this->getActivationVisibility());
1057  $new_obj->setSubscriptionLimitationType($this->getSubscriptionLimitationType());
1058  $new_obj->setSubscriptionStart($this->getSubscriptionStart());
1059  $new_obj->setSubscriptionEnd($this->getSubscriptionEnd());
1060  $new_obj->setSubscriptionType($this->getSubscriptionType());
1061  $new_obj->setSubscriptionPassword($this->getSubscriptionPassword());
1062  $new_obj->enableSubscriptionMembershipLimitation($this->isSubscriptionMembershipLimited());
1063  $new_obj->setSubscriptionMaxMembers($this->getSubscriptionMaxMembers());
1064  $new_obj->setViewMode($this->getViewMode());
1065  $new_obj->setTimingMode($this->getTimingMode());
1066  $new_obj->setOrderType($this->getOrderType());
1067  $new_obj->setAboStatus($this->getAboStatus());
1068  $new_obj->enableWaitingList($this->enabledWaitingList());
1069  $new_obj->setImportantInformation($this->getImportantInformation());
1070  $new_obj->setTargetGroup($this->getTargetGroup());
1071  $new_obj->setShowMembers($this->getShowMembers());
1072  // patch mem_exp
1073  $new_obj->setShowMembersExport($this->getShowMembersExport());
1074  // patch mem_exp
1075  $new_obj->enableSessionLimit($this->isSessionLimitEnabled());
1076  $new_obj->setNumberOfPreviousSessions($this->getNumberOfPreviousSessions());
1077  $new_obj->setNumberOfNextSessions($this->getNumberOfNextSessions());
1078  $new_obj->setAutoNotification($this->getAutoNotification());
1079  $new_obj->enableRegistrationAccessCode($this->isRegistrationAccessCodeEnabled());
1080  $new_obj->setRegistrationAccessCode(ilMembershipRegistrationCodeUtils::generateCode());
1081  $new_obj->setStatusDetermination($this->getStatusDetermination());
1082  $new_obj->setMailToMembersType($this->getMailToMembersType());
1083  $new_obj->setCoursePeriod(
1084  $this->getCourseStart(),
1085  $this->getCourseEnd()
1086  );
1087  $new_obj->setCancellationEnd($this->getCancellationEnd());
1088  $new_obj->setWaitingListAutoFill($this->hasWaitingListAutoFill());
1089  $new_obj->setSubscriptionMinMembers($this->getSubscriptionMinMembers());
1090 
1091  // #10271
1092  $new_obj->setEnableCourseMap($this->getEnableCourseMap());
1093  $new_obj->setLatitude($this->getLatitude());
1094  $new_obj->setLongitude($this->getLongitude());
1095  $new_obj->setLocationZoom($this->getLocationZoom());
1096 
1097  $new_obj->update();
1098  }
1099 
1100  public function __createDefaultSettings(): void
1101  {
1103 
1104  $query = "INSERT INTO crs_settings (obj_id,syllabus,contact_name,contact_responsibility," .
1105  "contact_phone,contact_email,contact_consultation," .
1106  "sub_limitation_type,sub_start,sub_end,sub_type,sub_password,sub_mem_limit," .
1107  "sub_max_members,sub_notify,view_mode,timing_mode,abo," .
1108  "latitude,longitude,location_zoom,enable_course_map,waiting_list,show_members,show_members_export, " .
1109  "session_limit,session_prev,session_next, reg_ac_enabled, reg_ac, auto_notification, status_dt, " .
1110  "mail_members_type, tutorial_support_block) " .
1111  "VALUES( " .
1112  $this->db->quote($this->getId(), 'integer') . ", " .
1113  $this->db->quote($this->getSyllabus(), 'text') . ", " .
1114  $this->db->quote($this->getContactName(), 'text') . ", " .
1115  $this->db->quote($this->getContactResponsibility(), 'text') . ", " .
1116  $this->db->quote($this->getContactPhone(), 'text') . ", " .
1117  $this->db->quote($this->getContactEmail(), 'text') . ", " .
1118  $this->db->quote($this->getContactConsultation(), 'text') . ", " .
1119  $this->db->quote(ilCourseConstants::IL_CRS_SUBSCRIPTION_DEACTIVATED, 'integer') . ", " .
1120  $this->db->quote($this->getSubscriptionStart(), 'integer') . ", " .
1121  $this->db->quote($this->getSubscriptionEnd(), 'integer') . ", " .
1122  $this->db->quote(ilCourseConstants::IL_CRS_SUBSCRIPTION_DIRECT, 'integer') . ", " .
1123  $this->db->quote($this->getSubscriptionPassword(), 'text') . ", " .
1124  "0, " .
1125  $this->db->quote($this->getSubscriptionMaxMembers(), 'integer') . ", " .
1126  "1, " .
1127  "0, " .
1128  $this->db->quote(ilCourseConstants::IL_CRS_VIEW_TIMING_ABSOLUTE, 'integer') . ', ' .
1129  $this->db->quote($this->getAboStatus(), 'integer') . ", " .
1130  $this->db->quote($this->getLatitude(), 'text') . ", " .
1131  $this->db->quote($this->getLongitude(), 'text') . ", " .
1132  $this->db->quote($this->getLocationZoom(), 'integer') . ", " .
1133  $this->db->quote($this->getEnableCourseMap(), 'integer') . ", " .
1134  #"objective_view = '0', ".
1135  "1, " .
1136  "1," .
1137  '0,' .
1138  $this->db->quote($this->isSessionLimitEnabled(), 'integer') . ', ' .
1139  $this->db->quote($this->getNumberOfPreviousSessions(), 'integer') . ', ' .
1140  $this->db->quote($this->getNumberOfPreviousSessions(), 'integer') . ', ' .
1141  $this->db->quote($this->isRegistrationAccessCodeEnabled(), 'integer') . ', ' .
1142  $this->db->quote($this->getRegistrationAccessCode(), 'text') . ', ' .
1143  $this->db->quote((int) $this->getAutoNotification(), 'integer') . ', ' .
1144  $this->db->quote($this->getStatusDetermination(), 'integer') . ', ' .
1145  $this->db->quote($this->getMailToMembersType(), 'integer') . ', ' .
1146  $this->db->quote($this->getTutorialSupportBlockSettingValue(), 'integer') . ' ' .
1147  ")";
1148 
1149  $res = $this->db->manipulate($query);
1150  $this->__readSettings();
1151 
1152  $sorting = new ilContainerSortingSettings($this->getId());
1153  $sorting->setSortMode(ilContainer::SORT_MANUAL);
1154  $sorting->update();
1155  }
1156 
1157  public function __readSettings(): void
1158  {
1159  $query = "SELECT * FROM crs_settings WHERE obj_id = " . $this->db->quote($this->getId(), 'integer');
1160  $res = $this->db->query($query);
1161  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
1162  $this->setTutorialSupportBlockSettingValue((int) $row->tutorial_support_block);
1163  $this->setSyllabus((string) $row->syllabus);
1164  $this->setTargetGroup($row->target_group);
1165  $this->setContactName((string) $row->contact_name);
1166  $this->setContactResponsibility((string) $row->contact_responsibility);
1167  $this->setContactPhone((string) $row->contact_phone);
1168  $this->setContactEmail((string) $row->contact_email);
1169  $this->setContactConsultation((string) $row->contact_consultation);
1170  $this->setSubscriptionLimitationType((int) $row->sub_limitation_type);
1171  $this->setSubscriptionStart((int) $row->sub_start);
1172  $this->setSubscriptionEnd((int) $row->sub_end);
1173  $this->setSubscriptionType((int) $row->sub_type);
1174  $this->setSubscriptionPassword((string) $row->sub_password);
1175  $this->enableSubscriptionMembershipLimitation((bool) $row->sub_mem_limit);
1176  $this->setSubscriptionMaxMembers((int) $row->sub_max_members);
1177  $this->setViewMode((int) $row->view_mode);
1178  $this->setTimingMode((int) $row->timing_mode);
1179  $this->setAboStatus((bool) $row->abo);
1180  $this->enableWaitingList((bool) $row->waiting_list);
1181  $this->setImportantInformation((string) $row->important);
1182  $this->setShowMembers((bool) $row->show_members);
1183 
1184  if (\ilPrivacySettings::getInstance()->participantsListInCoursesEnabled()) {
1185  $this->setShowMembersExport((bool) $row->show_members_export);
1186  } else {
1187  $this->setShowMembersExport(false);
1188  }
1189  $this->setLatitude((string) $row->latitude);
1190  $this->setLongitude((string) $row->longitude);
1191  $this->setLocationZoom((int) $row->location_zoom);
1192  $this->setEnableCourseMap((bool) $row->enable_course_map);
1193  $this->enableSessionLimit((int) $row->session_limit);
1194  $this->setNumberOfPreviousSessions((int) $row->session_prev);
1195  $this->setNumberOfNextSessions((int) $row->session_next);
1196  $this->enableRegistrationAccessCode((bool) $row->reg_ac_enabled);
1197  $this->setRegistrationAccessCode((string) $row->reg_ac);
1198  $this->setAutoNotification((bool) $row->auto_notification);
1199  $this->setStatusDetermination((int) $row->status_dt);
1200  $this->setMailToMembersType((int) $row->mail_members_type);
1201 
1202  if ($row->period_time_indication) {
1203  $this->setCoursePeriod(
1204  new \ilDateTime($row->period_start, IL_CAL_DATETIME, \ilTimeZone::UTC),
1205  new \ilDateTime($row->period_end, IL_CAL_DATETIME, \ilTimeZone::UTC)
1206  );
1207  } elseif (!is_null($row->period_start) && !is_null($row->period_end)) {
1208  $this->setCoursePeriod(
1209  new \ilDate($row->period_start, IL_CAL_DATE),
1210  new \ilDate($row->period_end, IL_CAL_DATE)
1211  );
1212  }
1213  $this->toggleCourseStartTimeIndication((bool) $row->period_time_indication);
1214  $this->setCancellationEnd($row->leave_end ? new ilDate($row->leave_end, IL_CAL_UNIX) : null);
1215  $this->setWaitingListAutoFill((bool) $row->auto_wait);
1216  $this->setSubscriptionMinMembers((int) $row->min_members);
1217  }
1218 
1219  // moved activation to ilObjectActivation
1220  if ($this->ref_id ?? false) {
1221  $activation = ilObjectActivation::getItem($this->ref_id);
1222  switch ($activation["timing_type"]) {
1224  $this->setActivationStart((int) $activation["timing_start"]);
1225  $this->setActivationEnd((int) $activation["timing_end"]);
1226  $this->setActivationVisibility((bool) $activation["visible"]);
1227  break;
1228  }
1229  }
1230  }
1231 
1232  public function initWaitingList(): void
1233  {
1234  if (!$this->waiting_list_obj instanceof ilCourseWaitingList) {
1235  $this->waiting_list_obj = new ilCourseWaitingList($this->getId());
1236  }
1237  }
1238 
1239  protected function initCourseMemberObject(): void
1240  {
1241  $this->member_obj = ilCourseParticipant::_getInstanceByObjId($this->getId(), $this->user->getId());
1242  }
1243 
1244  protected function initCourseMembersObject(): void
1245  {
1246  $this->members_obj = ilCourseParticipants::_getInstanceByObjId($this->getId());
1247  }
1248 
1250  {
1251  if (!$this->member_obj instanceof ilCourseParticipant) {
1252  $this->initCourseMemberObject();
1253  }
1254  return $this->member_obj;
1255  }
1256 
1258  {
1259  if (!$this->members_obj instanceof ilCourseParticipants) {
1260  $this->initCourseMembersObject();
1261  }
1262  return $this->members_obj;
1263  }
1264 
1265 
1266  // RBAC METHODS
1267  public function initDefaultRoles(): void
1268  {
1270  'il_crs_admin_' . $this->getRefId(),
1271  "Admin of crs obj_no." . $this->getId(),
1272  'il_crs_admin',
1273  $this->getRefId()
1274  );
1276  'il_crs_tutor_' . $this->getRefId(),
1277  "Tutor of crs obj_no." . $this->getId(),
1278  'il_crs_tutor',
1279  $this->getRefId()
1280  );
1282  'il_crs_member_' . $this->getRefId(),
1283  "Member of crs obj_no." . $this->getId(),
1284  'il_crs_member',
1285  $this->getRefId()
1286  );
1287  }
1288 
1296  public function setParentRolePermissions(int $parent_ref_id): bool
1297  {
1298  $parent_roles = $this->rbac_review->getParentRoleIds($parent_ref_id);
1299  foreach ($parent_roles as $parent_role) {
1300  $this->rbac_admin->initIntersectionPermissions(
1301  $this->getRefId(),
1302  $parent_role['obj_id'],
1303  $parent_role['parent'],
1304  $this->__getCrsNonMemberTemplateId(),
1306  );
1307  }
1308  return true;
1309  }
1310 
1312  {
1313  $q = "SELECT obj_id FROM object_data WHERE type='rolt' AND title='il_crs_non_member'";
1314  $res = $this->ilias->db->query($q);
1315  $row = $res->fetchRow(ilDBConstants::FETCHMODE_ASSOC);
1316  return (int) $row["obj_id"];
1317  }
1318 
1319  public static function lookupCourseNonMemberTemplatesId(): int
1320  {
1321  global $DIC;
1322 
1323  $ilDB = $DIC->database();
1324 
1325  $query = 'SELECT obj_id FROM object_data WHERE type = ' . $ilDB->quote(
1326  'rolt',
1327  'text'
1328  ) . ' AND title = ' . $ilDB->quote('il_crs_non_member', 'text');
1329  $res = $ilDB->query($query);
1330  $row = $res->fetchRow(ilDBConstants::FETCHMODE_ASSOC);
1331  return (int) $row['obj_id'];
1332  }
1333 
1340  public function getLocalCourseRoles($a_translate = false): array
1341  {
1342  if (empty($this->local_roles)) {
1343  $this->local_roles = array();
1344  $role_arr = $this->rbac_review->getRolesOfRoleFolder($this->getRefId());
1345 
1346  foreach ($role_arr as $role_id) {
1347  if ($this->rbac_review->isAssignable($role_id, $this->getRefId())) {
1348  $role_Obj = ilObjectFactory::getInstanceByObjId($role_id);
1349  if ($a_translate) {
1350  $role_name = ilObjRole::_getTranslation($role_Obj->getTitle());
1351  } else {
1352  $role_name = $role_Obj->getTitle();
1353  }
1354  $this->local_roles[$role_name] = $role_Obj->getId();
1355  }
1356  }
1357  }
1358  return $this->local_roles;
1359  }
1360 
1369  public function getDefaultCourseRoles(string $a_crs_id = ""): array
1370  {
1371  if (strlen($a_crs_id) > 0) {
1372  $crs_id = $a_crs_id;
1373  } else {
1374  $crs_id = $this->getRefId();
1375  }
1376 
1377  $role_arr = $this->rbac_review->getRolesOfRoleFolder($crs_id);
1378 
1379  $arr_crsDefaultRoles = [];
1380  foreach ($role_arr as $role_id) {
1381  $role_Obj = &$this->ilias->obj_factory->getInstanceByObjId($role_id);
1382 
1383  $crs_Member = "il_crs_member_" . $crs_id;
1384  $crs_Admin = "il_crs_admin_" . $crs_id;
1385  $crs_Tutor = "il_crs_tutor_" . $crs_id;
1386 
1387  if (strcmp($role_Obj->getTitle(), $crs_Member) == 0) {
1388  $arr_crsDefaultRoles["crs_member_role"] = $role_Obj->getId();
1389  }
1390 
1391  if (strcmp($role_Obj->getTitle(), $crs_Admin) == 0) {
1392  $arr_crsDefaultRoles["crs_admin_role"] = $role_Obj->getId();
1393  }
1394 
1395  if (strcmp($role_Obj->getTitle(), $crs_Tutor) == 0) {
1396  $arr_crsDefaultRoles["crs_tutor_role"] = $role_Obj->getId();
1397  }
1398  }
1399 
1400  return $arr_crsDefaultRoles;
1401  }
1402 
1406  public function __getLocalRoles(): array
1407  {
1408  return $this->rbac_review->getRolesOfRoleFolder($this->getRefId(), false);
1409  }
1410 
1411  public function __deleteSettings(): void
1412  {
1413  $query = "DELETE FROM crs_settings " .
1414  "WHERE obj_id = " . $this->db->quote($this->getId(), 'integer') . " ";
1415  $this->db->manipulate($query);
1416  }
1417 
1418  public function getDefaultMemberRole(): int
1419  {
1420  $local_roles = $this->__getLocalRoles();
1421  foreach ($local_roles as $role_id) {
1422  $title = ilObject::_lookupTitle($role_id);
1423  if (substr($title, 0, 8) == 'il_crs_m') {
1424  return $role_id;
1425  }
1426  }
1427  return 0;
1428  }
1429 
1430  public function getDefaultTutorRole(): int
1431  {
1432  $local_roles = $this->__getLocalRoles();
1433  foreach ($local_roles as $role_id) {
1434  if ($tmp_role = ilObjectFactory::getInstanceByObjId($role_id, false)) {
1435  if (!strcmp($tmp_role->getTitle(), "il_crs_tutor_" . $this->getRefId())) {
1436  return $role_id;
1437  }
1438  }
1439  }
1440  return 0;
1441  }
1442 
1443  public function getDefaultAdminRole(): int
1444  {
1445  $local_roles = $this->__getLocalRoles();
1446  foreach ($local_roles as $role_id) {
1447  if ($tmp_role = ilObjectFactory::getInstanceByObjId($role_id, false)) {
1448  if (!strcmp($tmp_role->getTitle(), "il_crs_admin_" . $this->getRefId())) {
1449  return $role_id;
1450  }
1451  }
1452  }
1453  return 0;
1454  }
1455 
1456  public static function _deleteUser(int $a_usr_id): void
1457  {
1458  ilCourseLMHistory::_deleteUser($a_usr_id);
1461  }
1462 
1463  protected function doMDUpdateListener(string $a_element): void
1464  {
1465  switch ($a_element) {
1466  case 'General':
1467  // Update ecs content
1468  $ecs = new ilECSCourseSettings($this);
1469  $ecs->handleContentUpdate();
1470  break;
1471  }
1472  }
1473 
1474  public function addAdditionalSubItemInformation(array &$object): void
1475  {
1477  }
1478 
1482  protected function prepareAppointments(string $a_mode = 'create'): array
1483  {
1484  switch ($a_mode) {
1485  case 'create':
1486  case 'update':
1487  $apps = [];
1488  if (!$this->getActivationUnlimitedStatus() && !$this->getOfflineStatus()) {
1489  $app = new ilCalendarAppointmentTemplate(self::CAL_ACTIVATION_START);
1490  $app->setTitle($this->getTitle());
1491  $app->setSubtitle('crs_cal_activation_start');
1492  $app->setTranslationType(ilCalendarEntry::TRANSLATION_SYSTEM);
1493  $app->setDescription($this->getLongDescription());
1494  $app->setStart(new ilDateTime($this->getActivationStart(), IL_CAL_UNIX));
1495  $apps[] = $app;
1496 
1497  $app = new ilCalendarAppointmentTemplate(self::CAL_ACTIVATION_END);
1498  $app->setTitle($this->getTitle());
1499  $app->setSubtitle('crs_cal_activation_end');
1500  $app->setTranslationType(ilCalendarEntry::TRANSLATION_SYSTEM);
1501  $app->setDescription($this->getLongDescription());
1502  $app->setStart(new ilDateTime($this->getActivationEnd(), IL_CAL_UNIX));
1503  $apps[] = $app;
1504  }
1506  $app = new ilCalendarAppointmentTemplate(self::CAL_REG_START);
1507  $app->setTitle($this->getTitle());
1508  $app->setSubtitle('crs_cal_reg_start');
1509  $app->setTranslationType(ilCalendarEntry::TRANSLATION_SYSTEM);
1510  $app->setDescription($this->getLongDescription());
1511  $app->setStart(new ilDateTime($this->getSubscriptionStart(), IL_CAL_UNIX));
1512  $apps[] = $app;
1513 
1514  $app = new ilCalendarAppointmentTemplate(self::CAL_REG_END);
1515  $app->setTitle($this->getTitle());
1516  $app->setSubtitle('crs_cal_reg_end');
1517  $app->setTranslationType(ilCalendarEntry::TRANSLATION_SYSTEM);
1518  $app->setDescription($this->getLongDescription());
1519  $app->setStart(new ilDateTime($this->getSubscriptionEnd(), IL_CAL_UNIX));
1520  $apps[] = $app;
1521  }
1522  if ($this->getCourseStart() && $this->getCourseEnd()) {
1523  $app = new ilCalendarAppointmentTemplate(self::CAL_COURSE_START);
1524  $app->setTitle($this->getTitle());
1525  $app->setSubtitle('crs_cal_start');
1526  $app->setTranslationType(ilCalendarEntry::TRANSLATION_SYSTEM);
1527  $app->setDescription($this->getLongDescription());
1528  $app->setStart($this->getCourseStart());
1529  $app->setFullday(!$this->getCourseStartTimeIndication());
1530  $apps[] = $app;
1531 
1532  $app = new ilCalendarAppointmentTemplate(self::CAL_COURSE_END);
1533  $app->setTitle($this->getTitle());
1534  $app->setSubtitle('crs_cal_end');
1535  $app->setTranslationType(ilCalendarEntry::TRANSLATION_SYSTEM);
1536  $app->setDescription($this->getLongDescription());
1537  $app->setStart($this->getCourseEnd());
1538  $app->setFullday(!$this->getCourseStartTimeIndication());
1539  $apps[] = $app;
1540  }
1541  if (
1543  ) {
1544  $active = ilObjectActivation::getTimingsItems($this->getRefId());
1545  foreach ($active as $null => $item) {
1546  if ($item['timing_type'] == ilObjectActivation::TIMINGS_PRESETTING) {
1547  // create calendar entry for fixed types
1548  $app = new ilCalendarAppointmentTemplate(self::CAL_COURSE_TIMING_START);
1549  $app->setContextInfo($item['ref_id']);
1550  $app->setTitle($item['title']);
1551  $app->setSubtitle('cal_crs_timing_start');
1552  $app->setTranslationType(ilCalendarEntry::TRANSLATION_SYSTEM);
1553  $app->setStart(new ilDate($item['suggestion_start'], IL_CAL_UNIX));
1554  $app->setFullday(true);
1555  $apps[] = $app;
1556 
1557  $app = new ilCalendarAppointmentTemplate(self::CAL_COURSE_TIMING_END);
1558  $app->setContextInfo($item['ref_id']);
1559  $app->setTitle($item['title']);
1560  $app->setSubtitle('cal_crs_timing_end');
1561  $app->setTranslationType(ilCalendarEntry::TRANSLATION_SYSTEM);
1562  $app->setStart(new ilDate($item['suggestion_end'], IL_CAL_UNIX));
1563  $app->setFullday(true);
1564  $apps[] = $app;
1565  }
1566  }
1567  }
1568  return $apps;
1569 
1570  case 'delete':
1571  // Nothing to do: The category and all assigned appointments will be deleted.
1572  return array();
1573  }
1574  return [];
1575  }
1576 
1581  public static function lookupObjectsByCode(string $a_code): array
1582  {
1583  global $DIC;
1584 
1585  $ilDB = $DIC->database();
1586 
1587  $query = "SELECT obj_id FROM crs_settings " .
1588  "WHERE reg_ac_enabled = " . $ilDB->quote(1, 'integer') . " " .
1589  "AND reg_ac = " . $ilDB->quote($a_code, 'text');
1590  $res = $ilDB->query($query);
1591 
1592  $obj_ids = array();
1593  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
1594  $obj_ids[] = (int) $row->obj_id;
1595  }
1596  return $obj_ids;
1597  }
1598 
1603  public function register(
1604  int $a_user_id,
1605  int $a_role = ilCourseConstants::CRS_MEMBER,
1606  bool $a_force_registration = false
1607  ): void {
1608  if ($this->getMembersObject()->isAssigned($a_user_id)) {
1609  return;
1610  }
1611 
1612  if (!$a_force_registration) {
1613  // offline
1614  if (ilObjCourseAccess::_isOffline($this->getId())) {
1616  "Can't register to course, course is offline.",
1618  );
1619  }
1620  // activation
1621  if (!ilObjCourseAccess::_isActivated($this->getId())) {
1623  "Can't register to course, course is not activated.",
1625  );
1626  }
1627 
1631  'Cant registrate to course ' . $this->getId() .
1632  ', course subscription is deactivated.',
1634  );
1635  }
1636  }
1637 
1638  // Time Limitation
1640  if (!$this->inSubscriptionTime()) {
1642  'Cant registrate to course ' . $this->getId() .
1643  ', course is out of registration time.',
1645  );
1646  }
1647  }
1648 
1649  // Max members
1650  if ($this->isSubscriptionMembershipLimited()) {
1651  $free = max(0, $this->getSubscriptionMaxMembers() - $this->getMembersObject()->getCountMembers());
1652  $waiting_list = new ilCourseWaitingList($this->getId());
1653  if ($this->enabledWaitingList() && (!$free || $waiting_list->getCountUsers())) {
1654  $waiting_list->addToList($a_user_id);
1655  $this->lng->loadLanguageModule("crs");
1656  $info = sprintf(
1657  $this->lng->txt('crs_added_to_list'),
1658  $waiting_list->getPosition($a_user_id)
1659  );
1660  $participants = ilCourseParticipants::_getInstanceByObjId($this->getId());
1661  $participants->sendNotification(
1663  $a_user_id
1664  );
1665 
1667  $info,
1669  );
1670  }
1671 
1672  if (!$this->enabledWaitingList() && !$free) {
1673  throw new ilMembershipRegistrationException('Cant registrate to course ' . $this->getId() .
1674  ', membership is limited.', ilMembershipRegistrationException::OBJECT_IS_FULL);
1675  }
1676  }
1677  }
1678 
1679  $this->getMembersObject()->add($a_user_id, $a_role);
1680  $this->getMembersObject()->sendNotification(ilCourseMembershipMailNotification::TYPE_ADMISSION_MEMBER, $a_user_id);
1683  }
1684 
1689  public function getAutoNotification(): bool
1690  {
1691  return $this->auto_notification;
1692  }
1693 
1698  public function setAutoNotification(bool $value): void
1699  {
1700  $this->auto_notification = $value;
1701  }
1702 
1706  public function setStatusDetermination(int $a_value): void
1707  {
1708  $a_value = $a_value;
1709 
1710  // #13905
1711  if ($a_value == self::STATUS_DETERMINATION_LP) {
1713  $a_value = self::STATUS_DETERMINATION_MANUAL;
1714  }
1715  }
1716 
1717  $this->status_dt = $a_value;
1718  }
1719 
1723  public function getStatusDetermination(): int
1724  {
1725  return $this->status_dt;
1726  }
1727 
1728  public function syncMembersStatusWithLP(): void
1729  {
1730  foreach ($this->getMembersObject()->getParticipants() as $user_id) {
1731  // #15529 - force raise on sync
1732  ilLPStatusWrapper::_updateStatus($this->getId(), $user_id, null, false, true);
1733  }
1734  }
1735 
1740  public function checkLPStatusSync(int $a_member_id): void
1741  {
1742  // #11113
1745  // #13811 - we need to suppress creation if status entry
1746  $has_completed = (ilLPStatus::_lookupStatus(
1747  $this->getId(),
1748  $a_member_id,
1749  false
1751  $this->getMembersObject()->updatePassed($a_member_id, $has_completed, false, true);
1752  }
1753  }
1754 
1755  public function getOrderType(): int
1756  {
1757  if ($this->enabledObjectiveView()) {
1758  return ilContainer::SORT_MANUAL;
1759  }
1760  return parent::getOrderType();
1761  }
1762 
1766  public function handleAutoFill(): void
1767  {
1768  if (
1769  !$this->enabledWaitingList() || !$this->hasWaitingListAutoFill()
1770  ) {
1771  $this->course_logger->debug('Waiting list or auto fill disabled.');
1772  return;
1773  }
1774 
1775  $max = $this->getSubscriptionMaxMembers();
1777 
1778  $this->course_logger->debug('Max members: ' . $max);
1779  $this->course_logger->debug('Current members: ' . $now);
1780 
1781  if ($max <= $now) {
1782  return;
1783  }
1784 
1785  // see assignFromWaitingListObject()
1786  $waiting_list = new ilCourseWaitingList($this->getId());
1787 
1788  foreach ($waiting_list->getUserIds() as $user_id) {
1789  if (!$tmp_obj = ilObjectFactory::getInstanceByObjId($user_id, false)) {
1790  $this->course_logger->warning('Cannot create user instance for id: ' . $user_id);
1791  continue;
1792  }
1793  if ($this->getMembersObject()->isAssigned($user_id)) {
1794  $this->course_logger->warning('User is already assigned to course. uid: ' . $user_id . ' course_id: ' . $this->getRefId());
1795  continue;
1796  }
1799  $waiting_list->removeFromList($user_id);
1800  $this->checkLPStatusSync($user_id);
1801 
1802  $this->course_logger->info('Assigned user from waiting list to course: ' . $this->getTitle());
1803  $now++;
1804  if ($now >= $max) {
1805  break;
1806  }
1807  }
1808  }
1809 
1810  public static function mayLeave(int $a_course_id, int $a_user_id = 0, &$a_date = null): bool
1811  {
1812  global $DIC;
1813 
1814  $ilUser = $DIC['ilUser'];
1815  $ilDB = $DIC['ilDB'];
1816 
1817  if (!$a_user_id) {
1818  $a_user_id = $ilUser->getId();
1819  }
1820 
1821  $set = $ilDB->query("SELECT leave_end" .
1822  " FROM crs_settings" .
1823  " WHERE obj_id = " . $ilDB->quote($a_course_id, "integer"));
1824  $row = $ilDB->fetchAssoc($set);
1825  if ($row && $row["leave_end"]) {
1826  // timestamp to date
1827  $limit = date("Ymd", $row["leave_end"]);
1828  if ($limit < date("Ymd")) {
1829  $a_date = new ilDate(date("Y-m-d", $row["leave_end"]), IL_CAL_DATE);
1830  return false;
1831  }
1832  }
1833  return true;
1834  }
1835 
1836  public static function findCoursesWithNotEnoughMembers(): array
1837  {
1838  $ilDB = $GLOBALS['DIC']->database();
1839  $tree = $GLOBALS['DIC']->repositoryTree();
1840 
1841  $res = array();
1842 
1843  $before = new ilDateTime(time(), IL_CAL_UNIX);
1844  $now = $before->get(IL_CAL_UNIX);
1845  $now_dt = $before->get(IL_CAL_DATETIME, '', ilTimeZone::UTC);
1846 
1847  $set = $ilDB->query("SELECT obj_id, min_members" .
1848  " FROM crs_settings" .
1849  " WHERE min_members > " . $ilDB->quote(0, "integer") .
1850  " AND sub_mem_limit = " . $ilDB->quote(1, "integer") . // #17206
1851  " AND ((leave_end IS NOT NULL" .
1852  " AND leave_end < " . $ilDB->quote($now, "text") . ")" .
1853  " OR (leave_end IS NULL" .
1854  " AND sub_end IS NOT NULL" .
1855  " AND sub_end < " . $ilDB->quote($now, "text") . "))" .
1856  " AND (period_start IS NULL OR period_start > " . $ilDB->quote($now_dt, ilDBConstants::T_TEXT) . ")");
1857  while ($row = $ilDB->fetchAssoc($set)) {
1858  $refs = ilObject::_getAllReferences((int) $row['obj_id']);
1859  $ref = end($refs);
1860 
1861  if ($tree->isDeleted($ref)) {
1862  continue;
1863  }
1864 
1865  $part = new ilCourseParticipants((int) $row["obj_id"]);
1866  $reci = $part->getNotificationRecipients();
1867  if ($reci !== []) {
1868  $missing = (int) $row["min_members"] - $part->getCountMembers();
1869  if ($missing > 0) {
1870  $res[(int) $row["obj_id"]] = array($missing, $reci);
1871  }
1872  }
1873  }
1874 
1875  return $res;
1876  }
1877 } //END class.ilObjCourse
const LP_STATUS_COMPLETED_NUM
string $title
static lookupTimingMode(int $a_obj_id)
$res
Definition: ltiservices.php:66
string $contact_consultation
setSubscriptionLimitationType(int $a_type)
const int CAL_COURSE_END
setSubscriptionStart(int $a_value)
prepareAppointments(string $a_mode='create')
Prepare calendar appointments.
setLongitude(string $a_longitude)
const int CAL_REG_START
const IL_CAL_DATETIME
setActivationEnd(int $a_value)
setAboStatus(bool $a_status)
const int CAL_REG_END
setActivationVisibility(bool $a_value)
appendMessage(string $a_message)
setContactResponsibility(string $a_value)
static getInstancesByParentId(int $a_parent_id, ?array $a_filter=null)
static lookupShowMembersEnabled(int $a_obj_id)
setCoursePeriod(?ilDateTime $start=null, ?ilDateTime $end=null)
bool $reg_access_code_enabled
static lookupCourseNonMemberTemplatesId()
static _isActivated(int $a_obj_id)
Is activated.
setNumberOfNextSessions(int $a_num)
static _getInstanceByObjId(int $a_obj_id, int $a_usr_id)
static _getAllReferences(int $id)
get all reference ids for object ID
ilTree $tree
isDeleted(int $a_node_id)
This is a wrapper for isSaved() with a more useful name.
enableRegistrationAccessCode(bool $a_status)
const int CAL_COURSE_TIMING_START
setNumberOfPreviousSessions(int $a_num)
const int CAL_ACTIVATION_START
setSubscriptionMinMembers(int $a_value)
setShowMembers(bool $a_status)
setViewMode(int $a_mode)
setParentRolePermissions(int $parent_ref_id)
This method is called before "initDefaultRoles".
Apointment templates are used for automatic generated apointments.
setTimingMode(int $a_mode)
setLocationZoom(int $a_locationzoom)
setActivationStart(int $a_value)
getStatusDetermination()
Get status determination mode.
setStatusDetermination(int $a_value)
Set status determination mode.
static createDefaultRole(string $a_title, string $a_description, string $a_tpl_name, int $a_ref_id)
string $subscription_password
const IL_CAL_UNIX
static cloneDependencies(int $ref_id, int $target_id, int $copy_id)
setOrderType(int $a_value)
static mayLeave(int $a_course_id, int $a_user_id=0, &$a_date=null)
setCancellationEnd(?ilDate $a_value=null)
static _deleteUser(int $a_usr_id)
handleAutoFill()
Handle course auto fill.
setEnableCourseMap(bool $a_enablemap)
static _lookupViewMode(int $a_id)
setSubscriptionMaxMembers(int $a_value)
static _lookupObjId(int $ref_id)
ilDateTime $crs_end
static is_email(string $a_email, ?ilMailRfc822AddressParserFactory $mailAddressParserFactory=null)
This preg-based function checks whether an e-mail address is formally valid.
while($session_entry=$r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) return null
static convertDateToUtcDBTimestamp(?\ilDateTime $date=null)
static _deleteUser(int $a_usr_id)
Delete user data.
checkLPStatusSync(int $a_member_id)
sync course status from lp as lp data is not deleted on course exit new members may already have lp c...
static getUserIdByLogin(string $a_login)
static _deleteAll(int $course_id)
setSyllabus(string $a_syllabus)
static _deleteByCourse(int $a_course_id)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
getTutorialSupportBlockSettingValue()
cloneMetaData(ilObject $target_obj)
Copy meta data.
static _deleteAll(int $a_course_id)
string $contact_responsibility
static _lookupTitle(int $obj_id)
static _getInstanceByObjId(int $a_obj_id)
setContactConsultation(string $a_value)
$GLOBALS["DIC"]
Definition: wac.php:53
bool $activation_visibility
Interface for all objects that offer registration with access codes.
setCourseStart(?ilDateTime $a_value=null)
cloneSettings(ilObject $new_obj)
setSubscriptionType(int $a_value)
class ilcourseobjective
enableSessionLimit(int $a_status)
enableSubscriptionMembershipLimitation(bool $a_status)
ilDateTime $crs_start
setSubscriptionEnd(int $a_value)
setContactEmail(string $a_value)
setImportantInformation(string $a_info)
static _getTranslation(string $a_role_title)
string $reg_access_code
static getTimingsItems(int $container_ref_id)
Get (sub) item data for timings view (no session material, no side blocks)
int $subscription_max_members
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static _clone(int $a_source_id, int $a_target_id)
setMailToMembersType(int $a_type)
global $DIC
Definition: shib_login.php:26
int $subscription_limitation_type
getDefaultCourseRoles(string $a_crs_id="")
get default course roles, returns the defaultlike create roles il_crs_tutor, il_crs_admin and il_crs_...
ilCourseWaitingList $waiting_list_obj
Class ilObjForumAdministration.
Class ilContainer.
setTutorialSupportBlockSettingValue(int $value)
static _isOffline(int $obj_id)
const int STATUS_DETERMINATION_LP
setWaitingListAutoFill(bool $a_value)
setOfflineStatus(bool $status)
static _lookupStatus(int $a_obj_id, int $a_user_id, bool $a_create=true)
Lookup status.
const int CAL_ACTIVATION_END
bool $auto_fill_from_waiting
ilCourseParticipant $member_obj
const ROLE_FOLDER_ID
Definition: constants.php:34
static _cloneFiles(int $a_source_id, int $a_target_id)
static _getGroupings(int $a_course_id)
static _isActivated(int $a_obj_id, ?bool &$a_visible_flag=null, bool $a_mind_member_view=true)
static _deleteAllEntries(int $a_obj_id)
Delete all entries Normally called in case of object deletion.
getLocalCourseRoles($a_translate=false)
get ALL local roles of course, also those created and defined afterwards only fetch data once from da...
doMDUpdateListener(string $a_element)
const int STATUS_DETERMINATION_MANUAL
getAutoNotification()
Returns automatic notification status from $this->auto_notification.
bool $crs_start_time_indication
static _registrationEnabled(int $a_obj_id)
setSubscriptionPassword(string $a_value)
bool $course_start_time_indication
static getInstanceByObjId(?int $obj_id, bool $stop_on_error=true)
get an instance of an Ilias object by object id
bool $subscription_membership_limitation
static _registrationEnabled(int $a_obj_id)
Registration enabled? Method is in Access class, since it is needed by Access/ListGUI.
setTargetGroup(?string $a_tg)
setContactName(string $a_cn)
const IL_CAL_DATE
setCourseEnd(?ilDateTime $a_value=null)
static generateCode()
Generate new registration key.
static getItem(int $ref_id)
ilCourseParticipants $members_obj
static lookupNumberOfMembers(int $a_ref_id)
Lookup number of members.
ilLogger $course_logger
enableWaitingList(bool $a_status)
static findCoursesWithNotEnoughMembers()
static addAdditionalSubItemInformation(array &$item)
Parse item data for list entries.
__construct(int $a_id=0, bool $a_call_by_reference=true)
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
__construct(Container $dic, ilPlugin $plugin)
ilErrorHandling $error
int $tutorial_support_block_setting_value
static deleteResultsForUser(int $a_user_id)
$q
Definition: shib_logout.php:23
getLongDescription()
get object long description (stored in object_description)
static _deleteUser(int $a_usr_id)
toggleCourseStartTimeIndication(bool $time_indication)
setRegistrationAccessCode(string $a_code)
$info
Definition: entry_point.php:21
static _lookupAboStatus(int $a_id)
static lookupTutorialBlockSettingEabled(int $a_obj_id)
static _getInstance(int $a_copy_id)
cloneObject(int $target_id, int $copy_id=0, bool $omit_tree=false)
Clone course (no member data)
setShowMembersExport(bool $a_mem_export)
setContactPhone(string $a_value)
const int CAL_COURSE_TIMING_END
cloneAutoGeneratedRoles(ilObject $new_obj)
Clone automatic genrated roles (permissions and template permissions)
Class ilObjectActivation.
static cloneSettings(int $a_copy_id, int $a_container_id, int $a_new_container_id)
setMessage(string $a_message)
static lookupObjectsByCode(string $a_code)
cloneDependencies(int $target_id, int $copy_id)
setLatitude(string $a_latitude)
addAdditionalSubItemInformation(array &$object)
Class ilECSCourseSettings.
const int CAL_COURSE_START
static _isSubscriptionNotificationEnabled(int $a_course_id)
static _updateStatus(int $a_obj_id, int $a_usr_id, ?object $a_obj=null, bool $a_percentage=false, bool $a_force_raise=false)
static checkForumsExistsInsert(int $ref_id, int $user_id)
setAutoNotification(bool $value)
Sets automatic notification status in $this->auto_notification, using given $status.