ILIAS  release_10 Revision v10.1-43-ga1241a92c2f
class.ilLPTableBaseGUI.php
Go to the documentation of this file.
1 <?php
2 
19 declare(strict_types=0);
20 
23 
31 {
32  public const HIT_LIMIT = 5000;
34  protected HttpService $http;
35 
36  protected array $filter = [];
37  protected bool $anonymized = true;
39  private ilObjUser $user;
40  protected ilSetting $setting;
43  protected ilTree $tree;
44  protected \ilGlobalTemplateInterface $main_tpl;
45 
46  public function __construct(
47  ?object $a_parent_obj,
48  string $a_parent_cmd = "",
49  string $a_template_context = ""
50  ) {
51  global $DIC;
52  $this->main_tpl = $DIC->ui()->mainTemplate();
53 
54  $this->objDefinition = $DIC['objDefinition'];
55  $this->ilObjDataCache = $DIC['ilObjDataCache'];
56  $this->tree = $DIC->repositoryTree();
57  $this->user = $DIC->user();
58  $this->setting = $DIC->settings();
59  $this->http = $DIC->http();
60  $this->refinery = $DIC->refinery();
61 
62  $this->anonymized = !ilObjUserTracking::_enabledUserRelatedData();
63  if (!$this->anonymized && isset($this->obj_id) && $this->obj_id > 0) {
64  $olp = ilObjectLP::getInstance($this->obj_id);
65  $this->anonymized = $olp->isAnonymized();
66  }
67 
68  /*
69  * BT 35453: parent constructor needs to be called after $this->anonymized
70  * is set, in order for getSelectableUserColumns to also properly return
71  * user defined fields (e.g. firstname, lastname, and other user data).
72  */
73  parent::__construct($a_parent_obj, $a_parent_cmd, $a_template_context);
74 
75  // country names
76  $this->lng->loadLanguageModule("meta");
77  }
78 
79  protected function initItemIdFromPost(): array
80  {
81  if ($this->http->wrapper()->post()->has('item_id')) {
82  return $this->http->wrapper()->post()->retrieve(
83  'item_id',
84  $this->refinery->kindlyTo()->listOf(
85  $this->refinery->kindlyTo()->int()
86  )
87  );
88  }
89  return [];
90  }
91 
92  protected function initUidFromPost(): array
93  {
94  if ($this->http->wrapper()->post()->has('uid')) {
95  return $this->http->wrapper()->post()->retrieve(
96  'uid',
97  $this->refinery->kindlyTo()->listOf(
98  $this->refinery->kindlyTo()->int()
99  )
100  );
101  }
102  return [];
103  }
104 
105  public function executeCommand(): bool
106  {
107  $this->determineSelectedFilters();
108  if (!$this->ctrl->getNextClass($this)) {
109  $to_hide = false;
110 
111  switch ($this->ctrl->getCmd()) {
112  case "applyFilter":
113  $this->resetOffset();
114  $this->writeFilterToSession();
115  $this->storeProperty("offset", "0");
116  break;
117 
118  case "resetFilter":
119  $this->resetOffset();
120  $this->resetFilter();
121  $this->storeProperty("offset", "0");
122  break;
123 
124  case "hideSelected":
125  $to_hide = $this->initItemIdFromPost();
126  break;
127 
128  case "hide":
129  $hide = 0;
130  if ($this->http->wrapper()->query()->has('hide')) {
131  $hide = $this->http->wrapper()->query()->retrieve(
132  'hide',
133  $this->refinery->kindlyTo()->int()
134  );
135  }
136  $to_hide = [$hide];
137  break;
138 
139  case "mailselectedusers":
140  if (!$this->initUidFromPost()) {
141  $this->main_tpl->setOnScreenMessage(
142  'failure',
143  $this->lng->txt(
144  "no_checkbox"
145  ),
146  true
147  );
148  } else {
149  $this->sendMail(
150  $this->initUidFromPost(),
151  $this->parent_obj,
152  $this->parent_cmd
153  );
154  }
155  break;
156 
157  case 'addToClipboard':
158  if (!$this->initUidFromPost()) {
159  $this->main_tpl->setOnScreenMessage(
160  'failure',
161  $this->lng->txt(
162  'no_checkbox'
163  ),
164  true
165  );
166  } else {
167  $this->addToClipboard();
168  }
169  break;
170 
171  // page selector
172  default:
173  $this->determineOffsetAndOrder();
174  $this->storeNavParameter();
175  $this->storeProperty("offset", (string) $this->getOffset());
176  break;
177  }
178 
179  if ($to_hide) {
180  $obj = $this->getFilterItemByPostVar("hide");
181  $value = array_unique(
182  array_merge((array) $obj->getValue(), $to_hide)
183  );
184  $obj->setValue($value);
185  $obj->writeToSession();
186  }
187 
188  if ($this->requested_tmpl_create !== "") {
189  $this->ctrl->setParameter(
190  $this->parent_obj,
191  "tbltplcrt",
192  $this->requested_tmpl_create
193  );
194  }
195  if ($this->requested_tmpl_delete !== "") {
196  $this->ctrl->setParameter(
197  $this->parent_obj,
198  "tbltpldel",
199  $this->requested_tmpl_delete
200  );
201  }
202  $this->ctrl->redirect($this->parent_obj, $this->parent_cmd);
203  } else {
204  // e.g. repository selector
205  return parent::executeCommand();
206  }
207  return true;
208  }
209 
213  protected function findReferencesForObjId(int $a_obj_id): array
214  {
215  $ref_ids = array_keys(ilObject::_getAllReferences($a_obj_id));
216  sort($ref_ids, SORT_NUMERIC);
217  return $ref_ids;
218  }
219 
220 
221 
222  protected function sendMail(
223  array $a_user_ids,
224  $a_parent_obj,
225  string $a_parent_cmd
226  ): void {
227  // see ilObjCourseGUI::sendMailToSelectedUsersObject()
228 
229  $rcps = array();
230  foreach ($a_user_ids as $usr_id) {
231  $rcps[] = ilObjUser::_lookupLogin($usr_id);
232  }
233 
234  $template = array();
235  $sig = null;
236 
237  $ref_id = 0;
238  if ($this->http->wrapper()->query()->has('ref_id')) {
239  $ref_id = $this->http->wrapper()->query()->retrieve(
240  'ref_id',
241  $this->refinery->kindlyTo()->int()
242  );
243  }
244  // repository-object-specific
245  if ($ref_id) {
246  $obj_lp = ilObjectLP::getInstance(
248  );
249  $tmpl_id = $obj_lp->getMailTemplateId();
250 
251  if ($tmpl_id) {
252  $template = array(
253  ilMailFormCall::CONTEXT_KEY => $tmpl_id,
254  'ref_id' => $ref_id,
255  'ts' => time()
256  );
257  } else {
258  $sig = ilLink::_getLink($ref_id);
259  $sig = rawurlencode(base64_encode($sig));
260  }
261  }
262 
265  $a_parent_obj,
266  $a_parent_cmd,
267  array(),
268  array(
269  'type' => 'new',
270  'rcp_to' => implode(',', $rcps),
271  'sig' => $sig
272  ),
273  $template
274  )
275  );
276  }
277 
281  protected function searchObjects(
282  array $filter,
283  string $permission,
284  ?array $preset_obj_ids = null,
285  bool $a_check_lp_activation = true
286  ): array {
287  $query_parser = new ilQueryParser($filter["query"] ?? '');
288  $query_parser->setMinWordLength(0);
289  $query_parser->setCombination(ilQueryParser::QP_COMBINATION_AND);
290  $query_parser->parse();
291  if (!$query_parser->validate()) {
292  ilLoggerFactory::getLogger('trac')->notice(
293  $query_parser->getMessage()
294  );
295  // echo $query_parser->getMessage();
296  return [];
297  }
298 
299  if ($filter["type"] == "lres") {
300  $filter["type"] = array('lm', 'sahs', 'htlm');
301  } else {
302  $filter["type"] = array($filter["type"]);
303  }
304 
305  $object_search = new ilLikeObjectSearch($query_parser);
306  $object_search->setFilter($filter["type"]);
307  if ($preset_obj_ids) {
308  $object_search->setIdFilter($preset_obj_ids);
309  }
310  $res = $object_search->performSearch();
311 
312  if ($permission) {
313  $res->setRequiredPermission($permission);
314  }
315 
316  $res->setMaxHits(self::HIT_LIMIT);
317 
318  if ($a_check_lp_activation) {
319  $res->addObserver($this, "searchFilterListener");
320  }
321 
322  if (!$this->filter["area"]) {
323  $res->filter(ROOT_FOLDER_ID, true);
324  } else {
325  $res->filter($this->filter["area"], true);
326  }
327 
328  $objects = array();
329  foreach ($res->getResults() as $obj_data) {
330  $objects[$obj_data['obj_id']][] = $obj_data['ref_id'];
331  }
332  return $objects ?: array();
333  }
334 
340  public function searchFilterListener(int $a_ref_id, array $a_data): bool
341  {
342  if (is_array($this->filter["hide"]) && in_array(
343  $a_data["obj_id"],
344  $this->filter["hide"]
345  )) {
346  return false;
347  }
348  $olp = ilObjectLP::getInstance($a_data["obj_id"]);
349  if (get_class(
350  $olp
351  ) != "ilObjectLP" && // #13654 - LP could be unsupported
352  !$olp->isActive()) {
353  return false;
354  }
355  return true;
356  }
357 
358  protected function isForwardingToFormDispatcher(): bool
359  {
360  return false;
361  }
362 
363  protected function initRepositoryFilter(array $filter): array
364  {
365  $repo = new ilRepositorySelector2InputGUI(
366  $this->lng->txt('trac_filter_area'),
367  'effective_from',
368  false,
369  ($this->isForwardingToFormDispatcher()) ? $this : null
370  );
371  $white_list = [];
372  foreach ($this->objDefinition->getAllRepositoryTypes() as $type) {
373  if ($this->objDefinition->isContainer($type)) {
374  $white_list[] = $type;
375  }
376  }
377  $repo->getExplorerGUI()->setTypeWhiteList($white_list);
378  $this->addFilterItem($repo);
379  $repo->readFromSession();
380  $filter['area'] = (int) $repo->getValue();
381  return $filter;
382  }
383 
387  public function initBaseFilter(
388  bool $a_split_learning_resources = false,
389  bool $a_include_no_status_filter = true,
390  bool $show_type_filter = true
391  ) {
392  $this->setDisableFilterHiding(true);
393 
394  // only courses in Achievements > Learning Progress (ILIAS 10 only) #43289
395  if ($show_type_filter) {
396  // object type selection
397  $si = new ilSelectInputGUI($this->lng->txt("obj_type"), "type");
398  $si->setOptions($this->getPossibleTypes($a_split_learning_resources));
399  $this->addFilterItem($si);
400  $si->readFromSession();
401  if (!$si->getValue()) {
402  $si->setValue("crs");
403  }
404  $this->filter["type"] = $si->getValue();
405  }
406 
407 
408  // hidden items
409  $msi = new ilMultiSelectInputGUI(
410  $this->lng->txt("trac_filter_hidden"),
411  "hide"
412  );
413  $this->addFilterItem($msi);
414  $msi->readFromSession();
415  $this->filter["hide"] = $msi->getValue();
416  if ($this->filter["hide"]) {
417  // create options from current value
418  $types = $this->getCurrentFilter(true);
419  $options = [];
420  foreach ($this->filter["hide"] as $obj_id) {
421  $options[$obj_id] = $this->ilObjDataCache->lookupTitle(
422  (int) $obj_id
423  );
424  }
425  $msi->setOptions($options);
426  }
427 
428  // title/description
429  $ti = new ilTextInputGUI(
430  $this->lng->txt("trac_title_description"),
431  "query"
432  );
433  $ti->setMaxLength(64);
434  $ti->setSize(20);
435  $this->addFilterItem($ti);
436  $ti->readFromSession();
437  $this->filter["query"] = $ti->getValue();
438 
439  // repository area selection
441  $this->lng->txt("trac_filter_area"),
442  "area"
443  );
444  $rs->setSelectText($this->lng->txt("trac_select_area"));
445  $this->addFilterItem($rs);
446  $rs->readFromSession();
447  $this->filter["area"] = $rs->getValue();
448 
449  // hide "not started yet"
450  if ($a_include_no_status_filter) {
451  $cb = new ilCheckboxInputGUI(
452  $this->lng->txt("trac_filter_has_status"),
453  "status"
454  );
455  $this->addFilterItem($cb);
456  $cb->readFromSession();
457  $this->filter["status"] = $cb->getChecked();
458  }
459  }
460 
463  protected function buildPath(array $ref_ids): array
464  {
465  if (!count($ref_ids)) {
466  return [];
467  }
468  $result = [];
469  foreach ($ref_ids as $ref_id) {
470  $path = "...";
471  $counter = 0;
472  $path_full = $this->tree->getPathFull($ref_id);
473  foreach ($path_full as $data) {
474  if (++$counter < (count($path_full) - 1)) {
475  continue;
476  }
477  $path .= " &raquo; ";
478  if ($ref_id != $data['ref_id']) {
479  $path .= $data['title'];
480  } else {
481  $path .= ('<a target="_top" href="' .
482  ilLink::_getLink(
483  $data['ref_id'],
484  $data['type']
485  ) . '">' .
486  $data['title'] . '</a>');
487  }
488  }
489 
490  $result[$ref_id] = $path;
491  }
492  return $result;
493  }
494 
495  protected function getPossibleTypes(
496  bool $a_split_learning_resources = false,
497  bool $a_include_digilib = false,
498  bool $a_allow_undefined_lp = false
499  ): array {
500  global $DIC;
501 
502  $component_repository = $DIC['component.repository'];
503 
504  $options = array();
505 
506  if ($a_split_learning_resources) {
507  $options['lm'] = $this->lng->txt('objs_lm');
508  $options['sahs'] = $this->lng->txt('objs_sahs');
509  $options['htlm'] = $this->lng->txt('objs_htlm');
510  } else {
511  $options['lres'] = $this->lng->txt('obj_lrss');
512  }
513 
514  $options['crs'] = $this->lng->txt('objs_crs');
515  $options['grp'] = $this->lng->txt('objs_grp');
516  $options['exc'] = $this->lng->txt('objs_exc');
517  $options['file'] = $this->lng->txt('objs_file');
518  $options['mcst'] = $this->lng->txt('objs_mcst');
519  $options['svy'] = $this->lng->txt('objs_svy');
520  $options['tst'] = $this->lng->txt('objs_tst');
521  $options['prg'] = $this->lng->txt('objs_prg');
522  $options['iass'] = $this->lng->txt('objs_iass');
523  $options['copa'] = $this->lng->txt('objs_copa');
524  $options['frm'] = $this->lng->txt('objs_frm');
525  $options['cmix'] = $this->lng->txt('objs_cmix');
526  $options['lti'] = $this->lng->txt('objs_lti');
527  $options['lso'] = $this->lng->txt('objs_lso');
528  $options['dcl'] = $this->lng->txt('objs_dcl');
529 
530  if ($a_allow_undefined_lp) {
531  $options['root'] = $this->lng->txt('obj_reps');
532  $options['cat'] = $this->lng->txt('objs_cat');
533  $options["webr"] = $this->lng->txt("objs_webr");
534  $options["wiki"] = $this->lng->txt("objs_wiki");
535  $options["blog"] = $this->lng->txt("objs_blog");
536  $options["prtf"] = $this->lng->txt("objs_prtf");
537  $options["prtt"] = $this->lng->txt("objs_prtt");
538  }
539 
540  // repository plugins (currently only active)
541  $plugins = $component_repository->getPluginSlotById(
542  "robj"
543  )->getActivePlugins();
544  foreach ($plugins as $pl) {
545  $pl_id = $pl->getId();
547  $options[$pl_id] = ilObjectPlugin::lookupTxtById(
548  $pl_id,
549  "objs_" . $pl_id
550  );
551  }
552  }
553 
554  asort($options);
555  return $options;
556  }
557 
558  protected function parseValue(
559  string $id,
560  ?string $value,
561  string $type
562  ): string {
563  // get rid of aggregation
564  $pos = strrpos($id, "_");
565  if ($pos !== false) {
566  $function = strtoupper(substr($id, $pos + 1));
567  if (in_array(
568  $function,
569  array("MIN", "MAX", "SUM", "AVG", "COUNT")
570  )) {
571  $id = substr($id, 0, $pos);
572  }
573  }
574 
575  if ((trim((string) $value) == "") && $id != "status") {
576  if ($id == "title" &&
577  get_class($this) != "ilTrObjectUsersPropsTableGUI" &&
578  get_class($this) != "ilTrMatrixTableGUI") {
579  return "--" . $this->lng->txt("none") . "--";
580  }
581  return " ";
582  }
583 
584  switch ($id) {
585  case "first_access":
586  case "create_date":
587  case 'status_changed':
589  new ilDateTime($value, IL_CAL_DATETIME)
590  );
591  break;
592 
593  case "last_access":
595  new ilDateTime($value, IL_CAL_UNIX)
596  );
597  break;
598 
599  case "birthday":
601  new ilDate($value, IL_CAL_DATE)
602  );
603  break;
604 
605  case "spent_seconds":
606  if (!ilObjectLP::supportsSpentSeconds($type)) {
607  $value = "-";
608  } else {
610  (int) $value,
611  ((int) $value < 3600 ? true : false)
612  ); // #14858
613  }
614  break;
615 
616  case "percentage":
617  if (false /* $this->isPercentageAvailable() */) {
618  $value = "-";
619  } else {
620  $value = $value . "%";
621  }
622  break;
623 
624  case "mark":
625  if (!ilObjectLP::supportsMark($type)) {
626  $value = "-";
627  }
628  break;
629 
630  case "gender":
631  $value = $this->lng->txt("gender_" . $value);
632  break;
633 
634  case "status":
635  $icons = ilLPStatusIcons::getInstance($this->getIconVariant());
636  $value = $icons->renderIconForStatus((int) $value);
637  break;
638 
639  case "language":
640  $this->lng->loadLanguageModule("meta");
641  $value = $this->lng->txt("meta_l_" . $value);
642  break;
643 
644  case "sel_country":
645  $value = $this->lng->txt("meta_c_" . $value);
646  break;
647  }
648 
649  return $value ?? '';
650  }
651 
652  public function getCurrentFilter(bool $as_query = false): array
653  {
654  $result = array();
655  foreach ($this->filter as $id => $value) {
656  $item = $this->getFilterItemByPostVar($id);
657  switch ($id) {
658  case "title":
659  case "country":
660  case "gender":
661  case "city":
662  case "language":
663  case "login":
664  case "firstname":
665  case "lastname":
666  case "mark":
667  case "u_comment":
668  case "institution":
669  case "department":
670  case "street":
671  case "zipcode":
672  case "email":
673  case "matriculation":
674  case "sel_country":
675  case "query":
676  case "type":
677  case "area":
678  if ($value) {
679  $result[$id] = $value;
680  }
681  break;
682 
683  case "status":
684  if (!is_null($value) && $value !== "") {
685  $result[$id] = $value;
686  }
687  break;
688 
689  case "user_total":
690  case "read_count":
691  case "percentage":
692  case "hide":
693  case "spent_seconds":
694  if (is_array($value) && implode("", $value)) {
695  $result[$id] = $value;
696  }
697  break;
698 
699  case "registration":
700  case "create_date":
701  case "first_access":
702  case "last_access":
703  case 'status_changed':
704  if ($value) {
705  if ($value["from"]) {
706  $result[$id]["from"] = $value["from"]->get(
708  );
709  }
710  if ($value["to"]) {
711  $result[$id]["to"] = $value["to"]->get(
713  );
714  }
715  }
716  break;
717 
718  case "birthday":
719  if ($value) {
720  if ($value["from"]) {
721  $result[$id]["from"] = $value["from"]->get(
723  );
724  $result[$id]["from"] = substr(
725  $result[$id]["from"],
726  0,
727  -8
728  ) . "00:00:00";
729  }
730  if ($value["to"]) {
731  $result[$id]["to"] = $value["to"]->get(
733  );
734  $result[$id]["to"] = substr(
735  $result[$id]["to"],
736  0,
737  -8
738  ) . "23:59:59";
739  }
740  }
741  break;
742  }
743  }
744  return $result;
745  }
746 
747  protected function isPercentageAvailable(int $a_obj_id): bool
748  {
749  if ($a_obj_id === 0) {
750  return false;
751  }
752  $olp = ilObjectLP::getInstance($a_obj_id);
753  $mode = $olp->getCurrentMode();
754  if (in_array(
755  $mode,
768  )
769  )) {
770  return true;
771  }
772  return false;
773  }
774 
775  protected function parseTitle(
776  int $a_obj_id,
777  string $action,
778  int $a_user_id = 0
779  ) {
780  global $DIC;
781 
782  $user = "";
783  if ($a_user_id) {
784  if ($a_user_id != $this->user->getId()) {
785  $a_user = ilObjectFactory::getInstanceByObjId($a_user_id);
786  } else {
787  $a_user = $this->user;
788  }
789  $user .= ", " . $a_user->getFullName(
790  ); // " [".$a_user->getLogin()."]";
791  }
792 
793  if ($a_obj_id != ROOT_FOLDER_ID) {
794  $this->setTitle(
795  $this->lng->txt(
796  $action
797  ) . ": " . $this->ilObjDataCache->lookupTitle($a_obj_id) . $user
798  );
799 
800  $olp = ilObjectLP::getInstance($a_obj_id);
801  $this->setDescription(
802  $this->lng->txt('trac_mode') . ": " . $olp->getModeText(
803  $olp->getCurrentMode()
804  )
805  );
806  } else {
807  $this->setTitle($this->lng->txt($action));
808  }
809  }
810 
814  protected function getExportMeta(): array
815  {
816  global $DIC;
817 
818  $ilClientIniFile = $DIC['ilClientIniFile'];
819 
820  /* see spec
821  Name of installation
822  Name of the course
823  Permalink to course
824  Owner of course object
825  Date of report generation
826  Reporting period
827  Name of person who generated the report.
828  */
829 
831 
832  $data = array();
833  $data[$this->lng->txt(
834  "trac_name_of_installation"
835  )] = $ilClientIniFile->readVariable('client', 'name');
836 
837  if ($this->obj_id) {
838  $data[$this->lng->txt(
839  "trac_object_name"
840  )] = $this->ilObjDataCache->lookupTitle((int) $this->obj_id);
841  if ($this->ref_id) {
842  $data[$this->lng->txt("trac_object_link")] = ilLink::_getLink(
843  $this->ref_id,
844  ilObject::_lookupType($this->obj_id)
845  );
846  }
847  $data[$this->lng->txt(
848  "trac_object_owner"
850  ilObject::_lookupOwner($this->obj_id)
851  );
852  }
853 
854  $data[$this->lng->txt(
855  "trac_report_date"
857  new ilDateTime(
858  time(),
860  )
861  );
862  $data[$this->lng->txt("trac_report_owner")] = $this->user->getFullName(
863  );
864 
865  return $data;
866  }
867 
868  protected function fillMetaExcel(ilExcel $a_excel, int &$a_row): void
869  {
870  foreach ($this->getExportMeta() as $caption => $value) {
871  $a_excel->setCell($a_row, 0, $caption);
872  $a_excel->setCell($a_row, 1, $value);
873  $a_row++;
874  }
875  $a_row++;
876  }
877 
878  protected function fillMetaCSV(ilCSVWriter $a_csv): void
879  {
880  foreach ($this->getExportMeta() as $caption => $value) {
881  $a_csv->addColumn(strip_tags($caption));
882  $a_csv->addColumn(strip_tags($value));
883  $a_csv->addRow();
884  }
885  $a_csv->addRow();
886  }
887 
893  protected function showTimingsWarning(int $a_ref_id, int $a_user_id)
894  {
895  $timing_cache = ilTimingCache::getInstanceByRefId($a_ref_id);
896  if ($timing_cache->isWarningRequired($a_user_id)) {
897  $timings = ilTimingCache::_getTimings($a_ref_id);
898  if (
899  $timings['item']['changeable'] &&
900  ($timings['user'][$a_user_id] ?? false) &&
901  $timings['user'][$a_user_id]['end']
902  ) {
903  $end = $timings['user'][$a_user_id]['end'];
904  } elseif ($timings['item']['suggestion_end']) {
905  $end = $timings['item']['suggestion_end'];
906  } else {
907  $end = true;
908  }
909  return $end;
910  }
911  return false;
912  }
913 
914  protected function formatSeconds(
915  int $seconds,
916  bool $a_shorten_zero = false
917  ): string {
918  $seconds = ($seconds > 0) ? $seconds : 0;
919  if ($a_shorten_zero && !$seconds) {
920  return "-";
921  }
922 
923  $hours = floor($seconds / 3600);
924  $rest = $seconds % 3600;
925 
926  $minutes = floor($rest / 60);
927  $rest = $rest % 60;
928 
929  if ($rest) {
930  $minutes++;
931  }
932 
933  return sprintf("%dh%02dm", $hours, $minutes);
934  }
935 
941  protected function anonymizeValue($a_value, bool $a_force_number = false)
942  {
943  // currently inactive
944  return $a_value;
945  }
946 
947  protected function buildValueScale(
948  int $a_max_value,
949  bool $a_anonymize = false,
950  bool $a_format_seconds = false
951  ): array {
952  $step = 0;
953  if ($a_max_value) {
954  $step = $a_max_value / 10;
955  $base = ceil(log($step, 10));
956  $fac = ceil($step / pow(10, ($base - 1)));
957  $step = pow(10, $base - 1) * $fac;
958  }
959  if ($step <= 1) {
960  $step = 1;
961  }
962  $ticks = range(0, $a_max_value + $step, $step);
963 
964  $value_ticks = array(0 => 0);
965  foreach ($ticks as $tick) {
966  $value = $tvalue = $tick;
967  if ($a_anonymize) {
968  $value = $this->anonymizeValue($value, true);
969  $tvalue = $this->anonymizeValue($tvalue);
970  }
971  if ($a_format_seconds) {
972  $tvalue = $this->formatSeconds($value);
973  }
974  $value_ticks[$value] = $tvalue;
975  }
976 
977  return $value_ticks;
978  }
979 
980  protected function getMonthsFilter($a_short = false): array
981  {
982  $options = array();
983  for ($loop = 0; $loop < 10; $loop++) {
984  $year = date("Y") - $loop;
985  $options[$year] = $year;
986  for ($loop2 = 12; $loop2 > 0; $loop2--) {
987  $month = str_pad($loop2, 2, "0", STR_PAD_LEFT);
988  if ($year . $month <= date("Ym")) {
989  if (!$a_short) {
990  $caption = $year . " / " . $this->lng->txt(
991  "month_" . $month . "_long"
992  );
993  } else {
994  $caption = $year . "/" . $month;
995  }
996  $options[$year . "-" . $month] = $caption;
997  }
998  }
999  }
1000  return $options;
1001  }
1002 
1003  protected function getMonthsYear($a_year = null, $a_short = false): array
1004  {
1005  if (!$a_year) {
1006  $a_year = date("Y");
1007  }
1008 
1009  $all = array();
1010  for ($loop = 1; $loop < 13; $loop++) {
1011  $month = str_pad($loop, 2, "0", STR_PAD_LEFT);
1012  if ($a_year . "-" . $month <= date("Y-m")) {
1013  if (!$a_short) {
1014  $caption = $this->lng->txt("month_" . $month . "_long");
1015  } else {
1016  $caption = $this->lng->txt("month_" . $month . "_short");
1017  }
1018  $all[$a_year . "-" . $month] = $caption;
1019  }
1020  }
1021  return $all;
1022  }
1023 
1024  protected function getSelectableUserColumns(
1025  int $a_in_course = 0,
1026  int $a_in_group = 0
1027  ): array {
1028  $cols = $privacy_fields = array();
1029 
1030  $up = new ilUserProfile();
1031  $up->skipGroup("preferences");
1032  $up->skipGroup("settings");
1033  $up->skipGroup("interests");
1034  $ufs = $up->getStandardFields();
1035 
1036  // default fields
1037  $cols["login"] = array(
1038  "txt" => $this->lng->txt("login"),
1039  "default" => true
1040  );
1041 
1042  if (!$this->anonymized) {
1043  $cols["firstname"] = array(
1044  "txt" => $this->lng->txt("firstname"),
1045  "default" => true
1046  );
1047  $cols["lastname"] = array(
1048  "txt" => $this->lng->txt("lastname"),
1049  "default" => true
1050  );
1051  }
1052 
1053  // show only if extended data was activated in lp settings
1054  $tracking = new ilObjUserTracking();
1055  if ($tracking->hasExtendedData(
1057  )) {
1058  $cols["first_access"] = array(
1059  "txt" => $this->lng->txt("trac_first_access"),
1060  "default" => true
1061  );
1062  $cols["last_access"] = array(
1063  "txt" => $this->lng->txt("trac_last_access"),
1064  "default" => true
1065  );
1066  }
1067  if ($tracking->hasExtendedData(
1069  )) {
1070  $cols["read_count"] = array(
1071  "txt" => $this->lng->txt("trac_read_count"),
1072  "default" => true
1073  );
1074  }
1075  if ($tracking->hasExtendedData(
1077  ) &&
1078  ilObjectLP::supportsSpentSeconds($this->type)) {
1079  $cols["spent_seconds"] = array(
1080  "txt" => $this->lng->txt("trac_spent_seconds"),
1081  "default" => true
1082  );
1083  }
1084 
1085  if ($this->isPercentageAvailable($this->obj_id)) {
1086  $cols["percentage"] = array(
1087  "txt" => $this->lng->txt("trac_percentage"),
1088  "default" => true
1089  );
1090  }
1091 
1092  // do not show status if learning progress is deactivated
1093  $olp = ilObjectLP::getInstance($this->obj_id);
1094  if ($olp->isActive()) {
1095  $cols["status"] = array(
1096  "txt" => $this->lng->txt("trac_status"),
1097  "default" => true
1098  );
1099 
1100  $cols['status_changed'] = array(
1101  'txt' => $this->lng->txt('trac_status_changed'),
1102  'default' => false
1103  );
1104  }
1105 
1106  if (ilObjectLP::supportsMark($this->type)) {
1107  $cols["mark"] = array(
1108  "txt" => $this->lng->txt("trac_mark"),
1109  "default" => true
1110  );
1111  }
1112 
1113  $cols["u_comment"] = array(
1114  "txt" => $this->lng->txt("trac_comment"),
1115  "default" => false
1116  );
1117 
1118  $cols["create_date"] = array(
1119  "txt" => $this->lng->txt("create_date"),
1120  "default" => false
1121  );
1122  $cols["language"] = array(
1123  "txt" => $this->lng->txt("language"),
1124  "default" => false
1125  );
1126 
1127  // add user data only if object is [part of] course
1128  if (!$this->anonymized &&
1129  ($a_in_course || $a_in_group)) {
1130  // only show if export permission is granted
1131  if (ilPrivacySettings::getInstance()->checkExportAccess(
1132  $a_in_group === 0 ? $a_in_course : $a_in_group
1133  )) {
1134  // other user profile fields
1135  foreach ($ufs as $f => $fd) {
1136  if (!isset($cols[$f]) && $f != "username" && !($fd["lists_hide"] ?? false)) {
1137  if ($a_in_course &&
1138  !(($fd["course_export_fix_value"] ?? false) || $this->setting->get(
1139  "usr_settings_course_export_" . $f
1140  ))) {
1141  continue;
1142  }
1143  if ($a_in_group &&
1144  !(($fd["group_export_fix_value"] ?? false) || $this->setting->get(
1145  "usr_settings_group_export_" . $f
1146  ))) {
1147  continue;
1148  }
1149 
1150  $cols[$f] = array(
1151  "txt" => $this->lng->txt($f),
1152  "default" => false
1153  );
1154  $privacy_fields[] = $f;
1155  }
1156  }
1157 
1158  // additional defined user data fields
1159  $user_defined_fields = ilUserDefinedFields::_getInstance();
1160  if ($a_in_course) {
1161  $user_defined_fields = $user_defined_fields->getCourseExportableFields(
1162  );
1163  } else {
1164  $user_defined_fields = $user_defined_fields->getGroupExportableFields(
1165  );
1166  }
1167  foreach ($user_defined_fields as $definition) {
1168  if ($definition["field_type"] != UDF_TYPE_WYSIWYG) {
1169  $f = "udf_" . $definition["field_id"];
1170  $cols[$f] = array(
1171  "txt" => $definition["field_name"],
1172  "default" => false
1173  );
1174 
1175  $privacy_fields[] = $f;
1176  }
1177  }
1178  }
1179  }
1180  return array($cols, $privacy_fields);
1181  }
1182 
1186  protected function addToClipboard(): void
1187  {
1188  $users = $this->initUidFromPost();
1189  $clip = ilUserClipboard::getInstance($this->user->getId());
1190  $clip->add($users);
1191  $clip->save();
1192  $this->lng->loadLanguageModule('user');
1193  $this->main_tpl->setOnScreenMessage(
1194  'success',
1195  $this->lng->txt(
1196  'clipboard_user_added'
1197  ),
1198  true
1199  );
1200  }
1201 
1205  public function getIconVariant(): int
1206  {
1207  return $this->icon_variant;
1208  }
1209 
1213  public function setIconVariant(int $variant): void
1214  {
1215  $this->icon_variant = $variant;
1216  }
1217 }
buildValueScale(int $a_max_value, bool $a_anonymize=false, bool $a_format_seconds=false)
static array static setUseRelativeDates(bool $a_status)
set use relative dates
addColumn(string $a_col)
$res
Definition: ltiservices.php:69
getPossibleTypes(bool $a_split_learning_resources=false, bool $a_include_digilib=false, bool $a_allow_undefined_lp=false)
static formatDate(ilDateTime $date, bool $a_skip_day=false, bool $a_include_wd=false, bool $include_seconds=false, ilObjUser $user=null,)
getCurrentFilter(bool $as_query=false)
const IL_CAL_DATETIME
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static getLogger(string $a_component_id)
Get component logger.
This class represents a selection list property in a property form.
addFilterItem(ilTableFilterItem $a_input_item, bool $a_optional=false)
const ROOT_FOLDER_ID
Definition: constants.php:32
static _lookupFullname(int $a_user_id)
getSelectableUserColumns(int $a_in_course=0, int $a_in_group=0)
findReferencesForObjId(int $a_obj_id)
getMonthsYear($a_year=null, $a_short=false)
searchObjects(array $filter, string $permission, ?array $preset_obj_ids=null, bool $a_check_lp_activation=true)
Search objects that match current filters.
static _getAllReferences(int $id)
get all reference ids for object ID
fillMetaExcel(ilExcel $a_excel, int &$a_row)
sendMail(array $a_user_ids, $a_parent_obj, string $a_parent_cmd)
setDescription(string $a_val)
static getInstance(int $variant=ilLPStatusIcons::ICON_VARIANT_DEFAULT, ?\ILIAS\UI\Renderer $renderer=null, ?\ILIAS\UI\Factory $factory=null)
setDisableFilterHiding(bool $a_val=true)
Class ilUserProfile.
__construct(?object $a_parent_obj, string $a_parent_cmd="", string $a_template_context="")
fillMetaCSV(ilCSVWriter $a_csv)
static _lookupOwner(int $obj_id)
Lookup owner user ID for object ID.
setOptions(array $a_options)
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) ...
addToClipboard()
Add selected users to clipboard.
sort()
description: > Example for rendering a Sort Glyph.
Definition: sort.php:25
$path
Definition: ltiservices.php:30
searchFilterListener(int $a_ref_id, array $a_data)
Listener for SearchResultFilter Checks wheather the object is hidden and mode is not LP_MODE_DEACTIVA...
getFilterItemByPostVar(string $a_post_var)
resetOffset(bool $a_in_determination=false)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
anonymizeValue($a_value, bool $a_force_number=false)
setCell(int $a_row, int $col, $value, ?string $datatype=null, bool $disable_strip_tags_for_strings=false)
Set cell value.
$ref_id
Definition: ltiauth.php:66
static http()
Fetches the global http state from ILIAS.
TableGUI class for learning progress.
getExportMeta()
Build export meta data.
isPercentageAvailable(int $a_obj_id)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
setIconVariant(int $variant)
Sets the variant of LP icons that is shown in the table.
getIconVariant()
Gets the variant of LP icons that is shown in the table.
parseValue(string $id, ?string $value, string $type)
global $DIC
Definition: shib_login.php:25
ilObjectDataCache $ilObjDataCache
ilObjectDefinition $objDefinition
static _lookupObjectId(int $ref_id)
formatSeconds(int $seconds, bool $a_shorten_zero=false)
const UDF_TYPE_WYSIWYG
setTitle(string $a_title, string $a_icon="", string $a_icon_alt="")
static lookupTxtById(string $plugin_id, string $lang_var)
static redirect(string $a_script)
static isTypePluginWithLP(string $a_type, bool $a_active_status=true)
initBaseFilter(bool $a_split_learning_resources=false, bool $a_include_no_status_filter=true, bool $show_type_filter=true)
Init filter.
initRepositoryFilter(array $filter)
static getInstanceByObjId(?int $obj_id, bool $stop_on_error=true)
get an instance of an Ilias object by object id
static supportsSpentSeconds(string $obj_type)
const IL_CAL_DATE
ilGlobalTemplateInterface $main_tpl
getMonthsFilter($a_short=false)
__construct(Container $dic, ilPlugin $plugin)
const LP_MODE_CMIX_COMPL_OR_PASSED_WITH_FAILED
static getRedirectTarget( $gui, string $cmd, array $gui_params=[], array $mail_params=[], array $context_params=[])
filter(string $filter_id, $class_path, string $cmd, bool $activated=true, bool $expanded=true)
static _getTimings(int $a_ref_id)
static supportsMark(string $obj_type)
static _lookupType(int $id, bool $reference=false)
parseTitle(int $a_obj_id, string $action, int $a_user_id=0)
showTimingsWarning(int $a_ref_id, int $a_user_id)
static getInstance(int $obj_id)
determineOffsetAndOrder(bool $a_omit_offset=false)
storeProperty(string $type, string $value)
static getInstance(int $a_usr_id)
static getInstanceByRefId(int $ref_id)
RefineryFactory $refinery
static _lookupLogin(int $a_user_id)