ILIAS  trunk Revision v11.0_alpha-2638-g80c1d007f79
class.ilCourseContentGUI.php
Go to the documentation of this file.
1 <?php
2 
19 declare(strict_types=0);
20 
26 
34 {
39 
42  protected ilLanguage $lng;
43  protected ilTabsGUI $tabs;
47  protected ilObjUser $user;
49  protected ilTree $tree;
51  protected Factory $refinery;
55 
56  public function __construct(ilContainerGUI $container_gui_obj)
57  {
58  global $DIC;
59 
60  $this->main_tpl = $DIC->ui()->mainTemplate();
61  $this->tpl = $DIC->ui()->mainTemplate();
62  $this->ctrl = $DIC->ctrl();
63  $this->lng = $DIC->language();
64  $this->tabs = $DIC->tabs();
65  $this->fav_manager = new ilFavouritesManager();
66  $this->access = $DIC->access();
67  $this->error = $DIC['ilErr'];
68  $this->user = $DIC->user();
69  $this->objectDataCache = $DIC['ilObjDataCache'];
70  $this->tree = $DIC->repositoryTree();
71  $this->http = $DIC->http();
72  $this->refinery = $DIC->refinery();
73  $this->ui_factory = $DIC->ui()->factory();
74  $this->ui_renderer = $DIC->ui()->renderer();
75  $this->lom_services = $DIC->learningObjectMetadata();
76 
77  $this->container_gui = $container_gui_obj;
78  $this->container_obj = $this->container_gui->getObject();
79  $this->initCourseObject();
80  }
81 
82  public function executeCommand(): void
83  {
84  if (!$this->access->checkAccess('read', '', $this->container_obj->getRefId())) {
85  $this->error->raiseError($this->lng->txt('msg_no_perm_read'), $this->error->WARNING);
86  }
87 
88  $this->__setSubTabs();
89  $this->tabs->setTabActive('view_content');
90  $cmd = $this->ctrl->getCmd();
91 
92  switch ($this->ctrl->getNextClass($this)) {
93  default:
94  $start = $this->initStartObjects();
95  if ($start instanceof ilCourseStart) {
96  $this->showStartObjects($start);
97  break;
98  }
99  if (!$cmd) {
100  throw new RuntimeException('Missing ctrl command.');
101  }
102  $this->$cmd();
103  break;
104  }
105  }
106 
107  protected function initMemberIdFromQuery(): int
108  {
109  if ($this->http->wrapper()->query()->has('member_id')) {
110  return $this->http->wrapper()->query()->retrieve(
111  'member_id',
112  $this->refinery->kindlyTo()->int()
113  );
114  }
115  return 0;
116  }
117 
118  public function getContainerObject(): ilContainer
119  {
120  return $this->container_obj;
121  }
122 
123  public function initStartObjects(): ?ilCourseStart
124  {
125  if ($this->access->checkAccess('write', '', $this->course_obj->getRefId())) {
126  return null;
127  }
128  $start_obj = new ilCourseStart($this->course_obj->getRefId(), $this->course_obj->getId());
129  if (count($start_obj->getStartObjects()) && !$start_obj->allFullfilled($this->user->getId())) {
130  return $start_obj;
131  }
132  return null;
133  }
134 
135  public function showStartObjects(ilCourseStart $start_obj): void
136  {
137  $this->tabs->setSubTabActive('crs_content');
138 
139  $this->tpl->addBlockFile("ADM_CONTENT", "adm_content", "tpl.crs_start_view.html", 'components/ILIAS/Course');
140  $this->tpl->setVariable("INFO_STRING", $this->lng->txt('crs_info_start'));
141  $this->tpl->setVariable("TBL_TITLE_START", $this->lng->txt('crs_table_start_objects'));
142  $this->tpl->setVariable("HEADER_NR", $this->lng->txt('crs_nr'));
143  $this->tpl->setVariable("HEADER_DESC", $this->lng->txt('description'));
144  $this->tpl->setVariable("HEADER_EDITED", $this->lng->txt('crs_objective_accomplished'));
145 
146  $lm_continue = new ilCourseLMHistory($this->course_obj->getRefId(), $this->user->getId());
147  $continue_data = $lm_continue->getLMHistory();
148 
149  $counter = 0;
150  foreach ($start_obj->getStartObjects() as $start) {
151  $obj_id = $this->objectDataCache->lookupObjId((int) $start['item_ref_id']);
152  $ref_id = $start['item_ref_id'];
153  $type = $this->objectDataCache->lookupType($obj_id);
154 
156 
157  $obj_link = ilLink::_getLink($ref_id, $type);
158  $obj_frame = '';
159 
160  // Tmp fix for tests
161  $obj_frame = $type == 'tst' ? '' : $obj_frame;
162 
163  if ($this->access->checkAccess('read', '', $ref_id)) {
164  $this->tpl->setCurrentBlock("start_read");
165  $this->tpl->setVariable("READ_TITLE_START", $this->objectDataCache->lookupTitle($obj_id));
166  $this->tpl->setVariable("READ_TARGET_START", $obj_frame);
167  $this->tpl->setVariable(
168  "READ_LINK_START",
169  $obj_link . '&crs_show_result=' . $this->course_obj->getRefId()
170  );
171  $this->tpl->parseCurrentBlock();
172  } else {
173  $this->tpl->setCurrentBlock("start_visible");
174  $this->tpl->setVariable("VISIBLE_LINK_START", $this->objectDataCache->lookupTitle($obj_id));
175  $this->tpl->parseCurrentBlock();
176  }
177 
178  // CONTINUE LINK
179  if (isset($continue_data[$ref_id])) {
180  $this->tpl->setCurrentBlock("link");
181  $this->tpl->setVariable("LINK_HREF", ilLink::_getLink($ref_id, '', array('obj_id',
182  $continue_data[$ref_id]['lm_page_id']
183  )));
184  #$this->tpl->setVariable("CONTINUE_LINK_TARGET",$target);
185  $this->tpl->setVariable("LINK_NAME", $this->lng->txt('continue_work'));
186  $this->tpl->parseCurrentBlock();
187  }
188 
189  // add to desktop link
190  if ($this->course_obj->getAboStatus()) {
191  if (!$this->fav_manager->ifIsFavourite($this->user->getId(), $ref_id)) {
192  if ($this->access->checkAccess('read', '', $ref_id)) {
193  $this->tpl->setCurrentBlock("link");
194  $this->ctrl->setParameterByClass(get_class($this->container_gui), 'item_ref_id', $ref_id);
195  $this->ctrl->setParameterByClass(get_class($this->container_gui), 'item_id', $ref_id);
196  $this->ctrl->setParameterByClass(get_class($this->container_gui), 'type', $type);
197 
198  $this->tpl->setVariable(
199  "LINK_HREF",
200  $this->ctrl->getLinkTarget($this->container_gui, 'addToDesk')
201  );
202  $this->tpl->setVariable("LINK_NAME", $this->lng->txt("rep_add_to_favourites"));
203  $this->tpl->parseCurrentBlock();
204  }
205  } else {
206  $this->tpl->setCurrentBlock("link");
207  $this->ctrl->setParameterByClass(get_class($this->container_gui), 'item_ref_id', $ref_id);
208  $this->ctrl->setParameterByClass(get_class($this->container_gui), 'item_id', $ref_id);
209  $this->ctrl->setParameterByClass(get_class($this->container_gui), 'type', $type);
210 
211  $this->tpl->setVariable(
212  "LINK_HREF",
213  $this->ctrl->getLinkTarget($this->container_gui, 'removeFromDesk')
214  );
215  $this->tpl->setVariable("LINK_NAME", $this->lng->txt("rep_remove_from_favourites"));
216  $this->tpl->parseCurrentBlock();
217  }
218  }
219 
220  // Description
221  if (strlen($this->objectDataCache->lookupDescription($obj_id))) {
222  $this->tpl->setCurrentBlock("start_description");
223  $this->tpl->setVariable("DESCRIPTION_START", $this->objectDataCache->lookupDescription($obj_id));
224  $this->tpl->parseCurrentBlock();
225  }
226 
227  if ($start_obj->isFullfilled($this->user->getId(), $ref_id)) {
228  $accomplished = 'accomplished';
229  $icon = ilUtil::getImagePath("standard/icon_ok.svg");
230  } else {
231  $accomplished = 'not_accomplished';
232  $icon = ilUtil::getImagePath("standard/icon_not_ok.svg");
233  }
234  $this->tpl->setCurrentBlock("start_row");
235  $this->tpl->setVariable("EDITED_IMG", $icon);
236  $this->tpl->setVariable("EDITED_ALT", $this->lng->txt('crs_objective_' . $accomplished));
237  $this->tpl->setVariable("ROW_CLASS", 'option_value');
238  $this->tpl->setVariable("ROW_CLASS_CENTER", 'option_value_center');
239  $this->tpl->setVariable("OBJ_NR_START", ++$counter . '.');
240  $this->tpl->parseCurrentBlock();
241  }
242  }
243 
247  protected function manageTimings(array $failed_items = []): void
248  {
249  if (!$this->access->checkAccess('write', '', $this->container_obj->getRefId())) {
250  $this->error->raiseError($this->lng->txt('msg_no_perm_write'), $this->error->WARNING);
251  }
252  $this->tabs->setTabActive('timings_timings');
253  $this->tabs->clearSubTabs();
254 
255  $table = new ilTimingsManageTableGUI(
256  $this,
257  'manageTimings',
258  $this->getContainerObject(),
259  $this->course_obj
260  );
261  if ($failed_items !== []) {
262  $table->setFailureStatus(true);
263  }
264  $table->init();
265  $table->parse(
267  $failed_items
268  );
269  $this->tpl->setContent($table->getHTML());
270  }
271 
275  protected function managePersonalTimings(array $failed = []): void
276  {
277  global $ilErr, $ilAccess;
278 
279  if (!$this->access->checkAccess('read', '', $this->container_obj->getRefId())) {
280  $this->error->raiseError($this->lng->txt('msg_no_perm_read'), $ilErr->WARNING);
281  }
282  $this->tabs->setTabActive('timings_timings');
283  $this->tabs->clearSubTabs();
284 
285  $table = new ilTimingsPersonalTableGUI(
286  $this,
287  'managePersonalTimings',
288  $this->getContainerObject(),
289  $this->course_obj
290  );
291  $table->setFailureStatus((bool) count($failed));
292  $table->setUserId($this->user->getId());
293  $table->init();
294  $table->parse(
296  $this->getContainerObject()->getRefId(),
297  false
298  ),
299  $failed
300  );
301  $this->tpl->setContent($table->getHTML());
302  }
303 
307  protected function updatePersonalTimings(): bool
308  {
309  if (!$this->access->checkAccess('read', '', $this->container_obj->getRefId())) {
310  $this->error->raiseError($this->lng->txt('msg_no_perm_write'), $this->error->WARNING);
311  }
312  $this->tabs->clearSubTabs();
313  $failed = array();
314 
315  $post_item = (array) ($this->http->request()->getParsedBody()['item'] ?? []);
316  foreach ($post_item as $ref_id => $data) {
317  $sug_start_dt = ilCalendarUtil::parseIncomingDate($data['sug_start']);
318  $sug_end_dt = ilCalendarUtil::parseIncomingDate($data['sug_end']);
319 
320  if ($sug_start_dt instanceof ilDate && $sug_end_dt instanceof ilDate) {
321  if (ilDateTime::_after($sug_start_dt, $sug_end_dt)) {
322  $failed[$ref_id] = 'crs_timing_err_start_end';
323  continue;
324  }
325  // update user date
326  $tu = new ilTimingUser($ref_id, $GLOBALS['ilUser']->getId());
327  $tu->getStart()->setDate($sug_start_dt->get(IL_CAL_UNIX), IL_CAL_UNIX);
328  $tu->getEnd()->setDate($sug_end_dt->get(IL_CAL_UNIX), IL_CAL_UNIX);
329  $tu->update();
330  } else {
331  $failed['ref_id'] = 'crs_timing_err_valid_dates';
332  }
333  }
334  if ($failed === []) {
335  $this->main_tpl->setOnScreenMessage('success', $GLOBALS['lng']->txt('settings_saved'));
336  $this->managePersonalTimings();
337  return true;
338  } else {
339  $this->main_tpl->setOnScreenMessage('failure', $this->lng->txt('err_check_input'));
340  $this->managePersonalTimings($failed);
341  return true;
342  }
343  }
344 
345  public function returnToMembers(): void
346  {
347  $this->ctrl->returnToParent($this);
348  }
349 
354  public function showUserTimings(): void
355  {
356  $this->tpl->addBlockfile('ADM_CONTENT', 'adm_content', 'tpl.crs_user_timings.html', 'components/ILIAS/Course');
357  $this->tabs->clearSubTabs();
358  $this->tabs->setTabActive('members');
359 
360  if (!$this->initMemberIdFromQuery()) {
361  $this->main_tpl->setOnScreenMessage('failure', $this->lng->txt('no_checkbox'), true);
362  $this->ctrl->returnToParent($this);
363  }
364 
365  // Back button
366  $this->tpl->addBlockfile("BUTTONS", "buttons", "tpl.buttons.html");
367  $this->tpl->setCurrentBlock("btn_cell");
368  $this->tpl->setVariable("BTN_LINK", $this->ctrl->getLinkTarget($this, 'returnToMembers'));
369  $this->tpl->setVariable("BTN_TXT", $this->lng->txt("back"));
370  $this->tpl->parseCurrentBlock();
371 
372  $usr_icon = $this->ui_factory->symbol()->icon()->standard(
373  'usr',
374  $this->lng->txt('obj_usr'),
375  'large'
376  );
377  $this->tpl->setVariable("HEADER_IMG", $this->ui_renderer->render($usr_icon));
378  $this->tpl->setVariable("TABLE_HEADER", $this->lng->txt('timings_of'));
380  $this->tpl->setVariable("USER_NAME", $name['lastname'] . ', ' . $name['firstname']);
381 
382  $this->tpl->setVariable("TXT_TITLE", $this->lng->txt('title'));
383  $this->tpl->setVariable("TXT_START_END", $this->lng->txt('crs_timings_short_start_end'));
384  $this->tpl->setVariable("TXT_INFO_START_END", $this->lng->txt('crs_timings_start_end_info'));
385  $this->tpl->setVariable("TXT_CHANGED", $this->lng->txt('crs_timings_changed'));
386  $this->tpl->setVariable("TXT_OWN_PRESETTING", $this->lng->txt('crs_timings_planed_start'));
387  $this->tpl->setVariable("TXT_INFO_OWN_PRESETTING", $this->lng->txt('crs_timings_from_until'));
388 
389  $items = ilObjectActivation::getTimingsAdministrationItems($this->course_obj->getRefId());
390  foreach ($items as $item) {
391  if (($item['timing_type'] == ilObjectActivation::TIMINGS_PRESETTING) or
392  ilObjectActivation::hasChangeableTimings($item['ref_id'])) {
393  $this->__renderUserItem($item, 0);
394  }
395  }
396  }
397 
402  public function __renderUserItem(array $item, int $level): void
403  {
404  $this->lng->loadLanguageModule('meta');
405 
406  $usr_planed = new ilTimingUser($item['ref_id'], $this->initMemberIdFromQuery());
407 
408  for ($i = 0; $i < $level; $i++) {
409  $this->tpl->touchBlock('start_indent');
410  $this->tpl->touchBlock('end_indent');
411  }
412  if (strlen($item['description'])) {
413  $this->tpl->setCurrentBlock("item_description");
414  $this->tpl->setVariable("DESC", $item['description']);
415  $this->tpl->parseCurrentBlock();
416  }
417 
418  $tlt_data = $this->lom_services->read(
419  ilObject::_lookupObjId($item['ref_id']),
420  0,
421  $item['type'],
422  $this->lom_services->paths()->firstTypicalLearningTime()
423  )->firstData($this->lom_services->paths()->firstTypicalLearningTime());
424 
425  if ($tlt = $this->lom_services->dataHelper()->durationToSeconds($tlt_data->value())) {
426  $this->tpl->setCurrentBlock("tlt");
427  $this->tpl->setVariable("TXT_TLT", $this->lng->txt('meta_typical_learning_time'));
428  $this->tpl->setVariable("TLT_VAL", ilDatePresentation::secondsToString($tlt));
429  $this->tpl->parseCurrentBlock();
430  }
431 
432  if (!$item['title'] &&
433  $item['type'] == 'sess') {
436  $app_info['start'],
437  $app_info['end'],
438  (bool) $app_info['fullday']
439  );
440  }
441 
442  $this->tpl->setCurrentBlock("title_plain");
443  $this->tpl->setVariable("TITLE", $item['title']);
444  $this->tpl->parseCurrentBlock();
445 
446  $this->tpl->setCurrentBlock("container_standard_row");
447 
448  $this->tpl->setVariable('TYPE_IMG', ilObject::_getIcon($item['obj_id'], 'tiny', $item['type']));
449  $this->tpl->setVariable("TYPE_ALT_IMG", $this->lng->txt('obj_' . $item['type']));
450 
451  if ($item['timing_type'] == ilObjectActivation::TIMINGS_PRESETTING) {
452  if ($usr_planed->getStart()->get(IL_CAL_UNIX)) {
453  $this->tpl->setVariable('SUG_START', $usr_planed->getStart()->get(IL_CAL_DATE));
454  }
455  if ($usr_planed->getEnd()->get(IL_CAL_UNIX)) {
456  $this->tpl->setVariable('SUG_END', $usr_planed->getEnd()->get(IL_CAL_DATE));
457  }
458  }
459  $this->tpl->parseCurrentBlock();
460  foreach (ilObjectActivation::getTimingsAdministrationItems($item['ref_id']) as $item_data) {
461  if (($item_data['timing_type'] == ilObjectActivation::TIMINGS_PRESETTING) or
462  ilObjectActivation::hasChangeableTimings($item_data['ref_id'])) {
463  $this->__renderUserItem($item_data, $level + 1);
464  }
465  }
466  }
467 
468  protected function updateManagedTimings(): bool
469  {
470  if (!$this->access->checkAccess('write', '', $this->container_obj->getRefId())) {
471  $this->error->raiseError($this->lng->txt('msg_no_perm_write'), $this->error->WARNING);
472  }
473 
474  $this->tabs->clearSubTabs();
475 
476  $failed = array();
477  $post_item = (array) ($this->http->request()->getParsedBody()['item']) ?? [];
478  foreach ($post_item as $ref_id => $data) {
479  $item_obj = new ilObjectActivation();
480  $item_obj->read($ref_id);
481 
482  $data['active'] = $data['active'] ?? 0;
484  $item_obj->toggleChangeable((bool) ($data['change'] ?? false));
485 
486  if ($this->course_obj->getTimingMode() == ilCourseConstants::IL_CRS_VIEW_TIMING_ABSOLUTE) {
487  $sug_start_dt = ilCalendarUtil::parseIncomingDate($data['sug_start'] ?? '');
488  $sug_end_dt = ilCalendarUtil::parseIncomingDate($data['sug_end'] ?? '');
489 
490  if ($sug_start_dt instanceof ilDate && $sug_end_dt instanceof ilDate) {
491  if (ilDateTime::_after($sug_start_dt, $sug_end_dt)) {
492  $failed[$ref_id] = 'crs_timing_err_start_end';
493  continue;
494  }
495  $item_obj->setSuggestionStart($sug_start_dt->get(IL_CAL_UNIX));
496  $item_obj->setSuggestionEnd($sug_end_dt->get(IL_CAL_UNIX));
497  } else {
498  $failed['ref_id'] = 'crs_timing_err_valid_dates';
499  continue;
500  }
501  } else {
502  if (
503  (int) $data['sug_start_rel'] < 0 || (int) $data['duration_a'] < 0
504  ) {
505  $failed[$ref_id] = 'crs_timing_err_start_dur_rel';
506  continue;
507  }
508  $item_obj->setSuggestionStartRelative($data['sug_start_rel']);
509  $item_obj->setSuggestionEndRelative($data['sug_start_rel'] + $data['duration_a']);
510 
511  // add default values for start/end (relative to now)
512  $start = new ilDate(time(), IL_CAL_UNIX);
513  $start->increment(IL_CAL_DAY, $data['sug_start_rel']);
514  $item_obj->setSuggestionStart($start->get(IL_CAL_UNIX));
515 
516  $start->increment(IL_CAL_DAY, $data['duration_a']);
517  $item_obj->setSuggestionEnd($start->get(IL_CAL_UNIX));
518  }
519 
520  $item_obj->update($ref_id);
521  }
522  if ($failed === []) {
523  // update course => create calendar entries
524  $this->course_obj->update();
525  $this->tpl->setOnScreenMessage('success', $this->lng->txt('settings_saved'));
526  $this->manageTimings();
527  return true;
528  } else {
529  $this->main_tpl->setOnScreenMessage('failure', $this->lng->txt('err_check_input'));
530  $this->manageTimings($failed);
531  return true;
532  }
533  }
534 
535  public function __setSubTabs(): void
536  {
537  if ($this->container_obj->getType() == 'crs') {
538  $this->container_gui->setContentSubTabs();
539  }
540  }
541 
542  public function initCourseObject(): bool
543  {
544  if ($this->container_obj instanceof ilObjCourse) {
545  $this->course_obj = $this->container_obj;
546  } else {
547  $course_ref_id = $this->tree->checkForParentType($this->container_obj->getRefId(), 'crs');
548  $course = ilObjectFactory::getInstanceByRefId($course_ref_id, false);
549  if ($course instanceof ilObjCourse) {
550  $this->course_obj = $course;
551  }
552  }
553  return true;
554  }
555 } // END class.ilCourseContentGUI
manageTimings(array $failed_items=[])
Manage timings.
updatePersonalTimings()
Update personal timings.
static parseIncomingDate($value, bool $add_time=false)
Try to parse incoming value to date object.
static hasChangeableTimings(int $ref_id)
Check if there is any active changeable timing (in subtree)
static _getIcon(int $obj_id=0, string $size="big", string $type="", bool $offline=false)
Get icon for repository item.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
TableGUI class for timings administration.
static _lookupName(int $a_user_id)
lookup user name
__construct(ilContainerGUI $container_gui_obj)
const IL_CAL_UNIX
static secondsToString(int $seconds, bool $force_with_seconds=false, ?ilLanguage $a_lng=null)
converts seconds to string: Long: 7 days 4 hour(s) ...
ilFavouritesManager $fav_manager
__renderUserItem(array $item, int $level)
$ilErr
Definition: raiseError.php:33
static _lookupObjId(int $ref_id)
static getItems(int $parent_id, bool $with_list_data=true)
Get sub item data.
showStartObjects(ilCourseStart $start_obj)
while($session_entry=$r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) return null
const IL_CAL_DAY
static getTimingsAdministrationItems(int $parent_id)
Get (sub) item data for timings administration view (active/inactive)
isFullfilled(int $user_id, int $item_id)
static _lookupAppointment(int $a_obj_id)
static http()
Fetches the global http state from ILIAS.
$GLOBALS["DIC"]
Definition: wac.php:53
static _after(ilDateTime $start, ilDateTime $end, string $a_compare_field='', string $a_tz='')
compare two dates and check start is after end This method does not consider tz offsets.
static getInstanceByRefId(int $ref_id, bool $stop_on_error=true)
get an instance of an Ilias object by reference id
global $DIC
Definition: shib_login.php:26
ilGlobalTemplateInterface $tpl
static getImagePath(string $image_name, string $module_path="", string $mode="output", bool $offline=false)
get image path (for images located in a template directory)
Class ilContainer.
TableGUI class for timings administration.
managePersonalTimings(array $failed=[])
Manage personal timings.
const IL_CAL_DATE
static _appointmentToString(int $start, int $end, bool $fulltime)
static _checkAllConditionsOfTarget(int $a_target_ref_id, int $a_target_id, string $a_target_type="", int $a_usr_id=0)
checks wether all conditions of a target object are fulfilled
Class ilCourseContentGUI.
TableGUI class for editing personal timings.
ilObjectDataCache $objectDataCache
Class ilObjectActivation.
ilGlobalTemplateInterface $main_tpl