ILIAS  release_8 Revision v8.19
All Data Structures Namespaces Files Functions Variables Modules Pages
class.ilTrSummaryTableGUI.php
Go to the documentation of this file.
1 <?php
2 
19 declare(strict_types=0);
20 
27 {
28  protected ?ilObjectLP $olp = null;
29  protected bool $is_root;
30  protected bool $is_in_course = false;
31  protected bool $is_in_group = false;
32  protected int $ref_id;
33  protected ?string $type = null;
34  protected int $obj_id;
35 
38 
42  public function __construct(
43  ?object $a_parent_obj,
44  string $a_parent_cmd,
45  int $a_ref_id,
46  bool $a_print_mode = false
47  ) {
48  global $DIC;
49  $this->objDefinition = $DIC['objDefinition'];
50  $this->rbacsystem = $DIC->rbac()->system();
51  $this->access = $DIC->access();
52  $this->ref_id = $a_ref_id;
53  $this->obj_id = ilObject::_lookupObjId($a_ref_id);
54  $this->is_root = ($a_ref_id == ROOT_FOLDER_ID);
55 
56  $this->setId("trsmy");
57 
58  if (!$this->is_root) {
59  // #17084 - are we multi-object or not?
60  // we cannot parse type filter (too complicated)
61  $type = ilObject::_lookupType($this->obj_id);
62  if (!$this->objDefinition->isContainer($type)) {
63  $this->type = $type;
64  $this->olp = ilObjectLP::getInstance($this->obj_id);
65  }
66  }
67 
68  if (
69  !$this->is_root &&
70  $DIC->repositoryTree()->checkForParentType($this->ref_id, 'grp')
71  ) {
72  $this->is_in_group = true;
73  } elseif (
74  !$this->is_root &&
75  $DIC->repositoryTree()->checkForParentType($this->ref_id, 'crs')
76  ) {
77  $this->is_in_course = true;
78  }
79 
80  parent::__construct($a_parent_obj, $a_parent_cmd);
81 
82  if ($a_print_mode) {
83  $this->setPrintMode(true);
84  }
85 
86  $this->parseTitle($this->obj_id, "trac_summary");
87  $this->setLimit(9999);
88  $this->setShowTemplates(true);
89  $this->setExportFormats(array(self::EXPORT_CSV, self::EXPORT_EXCEL));
90 
91  $this->addColumn($this->lng->txt("title"), "title");
92  $this->setDefaultOrderField("title");
93 
94  $labels = $this->getSelectableColumns();
95  foreach ($this->getSelectedColumns() as $c) {
96  // see bug #35119; these column list percentage lists and are not sortable
97  if (in_array($c, ["status", "mark", "language", "country", "gender", "city", "sel_country"])) {
98  $this->addColumn($labels[$c]["txt"]);
99  } else {
100  $this->addColumn($labels[$c]["txt"], $c);
101  }
102  }
103 
104  if ($this->is_root) {
105  $this->addColumn($this->lng->txt("path"));
106  $this->addColumn($this->lng->txt("action"));
107  }
108 
109  // $this->setExternalSorting(true);
110  $this->setEnableHeader(true);
111  $this->setFormAction(
112  $this->ctrl->getFormActionByClass(get_class($this))
113  );
114  $this->setRowTemplate("tpl.trac_summary_row.html", "Services/Tracking");
115  $this->initFilter();
116 
117  $this->getItems($a_parent_obj->getObjId(), $a_ref_id);
118  }
119 
120  public function getSelectableColumns(): array
121  {
122  $lng_map = array("user_total" => "users",
123  "first_access_min" => "trac_first_access",
124  "last_access_max" => "trac_last_access",
125  "mark" => "trac_mark",
126  "status" => "trac_status",
127  'status_changed_max' => 'trac_status_changed',
128  "spent_seconds_avg" => "trac_spent_seconds",
129  "percentage_avg" => "trac_percentage",
130  "read_count_sum" => "trac_read_count",
131  "read_count_avg" => "trac_read_count",
132  "read_count_spent_seconds_avg" => "trac_read_count_spent_seconds"
133  );
134 
135  $all = array("user_total");
136  $default = array();
137 
138  // show only if extended data was activated in lp settings
139  $tracking = new ilObjUserTracking();
140  if ($tracking->hasExtendedData(
142  )) {
143  $all[] = "read_count_sum";
144  $all[] = "read_count_avg";
145  $default[] = "read_count_sum";
146  }
147  if ($tracking->hasExtendedData(
149  )) {
150  if ($this->is_root || !$this->type || ilObjectLP::supportsSpentSeconds(
151  $this->type
152  )) {
153  $all[] = "spent_seconds_avg";
154  $default[] = "spent_seconds_avg";
155  }
156  }
157  if ($tracking->hasExtendedData(
159  ) &&
160  $tracking->hasExtendedData(
162  )) {
163  if ($this->is_root || !$this->type || ilObjectLP::supportsSpentSeconds(
164  $this->type
165  )) {
166  $all[] = "read_count_spent_seconds_avg";
167  // $default[] = "read_count_spent_seconds_avg";
168  }
169  }
170 
171  if ($this->is_root || !$this->type || $this->isPercentageAvailable(
172  $this->obj_id
173  )) {
174  $all[] = "percentage_avg";
175  }
176 
177  if ($this->is_root || !$this->olp || $this->olp->isActive()) {
178  $all[] = "status";
179  $all[] = 'status_changed_max';
180  }
181 
182  if ($this->is_root || !$this->type || ilObjectLP::supportsMark(
183  $this->type
184  )) {
185  $all[] = "mark";
186  }
187 
188  $privacy = array("gender", "city", "country", "sel_country");
189  foreach ($privacy as $field) {
190  if (
191  ($this->is_in_course && $this->setting->get("usr_settings_course_export_" . $field)) ||
192  ($this->is_in_group && $this->setting->get("usr_settings_group_export_" . $field))
193  ) {
194  $all[] = $field;
195  }
196  }
197 
198  $all[] = "language";
199 
200  $default[] = "percentage_avg";
201  $default[] = "status";
202  $default[] = "mark";
203 
204  if ($tracking->hasExtendedData(
206  )) {
207  $all[] = "first_access_min";
208  $all[] = "last_access_max";
209  }
210 
211  $all[] = "create_date_min";
212  $all[] = "create_date_max";
213 
214  $columns = array();
215  foreach ($all as $column) {
216  $l = $column;
217 
218  $prefix = false;
219  if (substr($l, -3) == "avg") {
220  $prefix = "&#216; ";
221  } elseif (substr($l, -3) == "sum" || $l == "user_total") {
222  $prefix = "&#8721; ";
223  }
224 
225  if (isset($lng_map[$l])) {
226  $l = $lng_map[$l];
227  }
228 
229  $txt = $prefix . $this->lng->txt($l);
230 
231  if (in_array(
232  $column,
233  array("read_count_avg",
234  "spent_seconds_avg",
235  "percentage_avg"
236  )
237  )) {
238  $txt .= " / " . $this->lng->txt("user");
239  }
240 
241  $columns[$column] = array(
242  "txt" => $txt,
243  "default" => (in_array($column, $default) ? true : false)
244  );
245  }
246  return $columns;
247  }
248 
249  public function initFilter(): void
250  {
251  if ($this->is_root) {
252  parent::initBaseFilter(true, false);
253  return;
254  }
255 
256  // show only if extended data was activated in lp settings
257  $tracking = new ilObjUserTracking();
258 
259  $item = $this->addFilterItemByMetaType(
260  "user_total",
262  true,
263  "&#8721; " . $this->lng->txt("users")
264  );
265  $this->filter["user_total"] = $item->getValue();
266 
267  if ($tracking->hasExtendedData(
269  )) {
270  $item = $this->addFilterItemByMetaType(
271  "read_count_sum",
273  true,
274  "&#8721; " . $this->lng->txt("trac_read_count")
275  );
276  $this->filter["read_count"] = $item->getValue();
277  }
278 
279  if ($tracking->hasExtendedData(
281  )) {
282  if ($this->is_root || !$this->type || ilObjectLP::supportsSpentSeconds(
283  $this->type
284  )) {
285  $item = $this->addFilterItemByMetaType(
286  "spent_seconds",
288  true,
289  "&#216; " . $this->lng->txt(
290  "trac_spent_seconds"
291  ) . " / " . $this->lng->txt("user")
292  );
293  $this->filter["spent_seconds"]["from"] = $item->getCombinationItem(
294  "from"
295  )->getValueInSeconds();
296  $this->filter["spent_seconds"]["to"] = $item->getCombinationItem(
297  "to"
298  )->getValueInSeconds();
299  }
300  }
301 
302  if ($this->is_root || !$this->type || $this->isPercentageAvailable(
303  $this->obj_id
304  )) {
305  $item = $this->addFilterItemByMetaType(
306  "percentage",
308  true,
309  "&#216; " . $this->lng->txt(
310  "trac_percentage"
311  ) . " / " . $this->lng->txt("user")
312  );
313  $this->filter["percentage"] = $item->getValue();
314  }
315 
316  if ($this->is_root || !$this->olp || $this->olp->isActive()) {
317  $item = $this->addFilterItemByMetaType(
318  "status",
320  true
321  );
322  $item->setOptions(
323  array("" => $this->lng->txt("trac_all"),
324  ilLPStatus::LP_STATUS_NOT_ATTEMPTED_NUM + 1 => $this->lng->txt(
326  ),
327  ilLPStatus::LP_STATUS_IN_PROGRESS_NUM + 1 => $this->lng->txt(
329  ),
330  ilLPStatus::LP_STATUS_COMPLETED_NUM + 1 => $this->lng->txt(
332  ),
333  ilLPStatus::LP_STATUS_FAILED_NUM + 1 => $this->lng->txt(
335  )
336  )
337  );
338  $this->filter["status"] = $item->getValue();
339  if ($this->filter["status"]) {
340  $this->filter["status"]--;
341  }
342 
343  $item = $this->addFilterItemByMetaType(
344  "status_changed_max",
346  true,
347  $this->lng->txt("trac_status_changed")
348  );
349  $this->filter["status_changed"] = $item->getDate();
350  }
351 
352  if ($this->is_root || !$this->type || ilObjectLP::supportsMark(
353  $this->type
354  )) {
355  $item = $this->addFilterItemByMetaType(
356  "mark",
358  true,
359  $this->lng->txt("trac_mark")
360  );
361  $this->filter["mark"] = $item->getValue();
362  }
363 
364  if ($this->setting->get("usr_settings_course_export_gender")) {
365  $item = $this->addFilterItemByMetaType(
366  "gender",
368  true
369  );
370  $item->setOptions(
371  array(
372  "" => $this->lng->txt("trac_all"),
373  "n" => $this->lng->txt("gender_n"),
374  "m" => $this->lng->txt("gender_m"),
375  "f" => $this->lng->txt("gender_f"),
376  )
377  );
378  $this->filter["gender"] = $item->getValue();
379  }
380 
381  if ($this->setting->get("usr_settings_course_export_city")) {
382  $item = $this->addFilterItemByMetaType(
383  "city",
385  true
386  );
387  $this->filter["city"] = $item->getValue();
388  }
389 
390  if ($this->setting->get("usr_settings_course_export_country")) {
391  $item = $this->addFilterItemByMetaType(
392  "country",
394  true
395  );
396  $this->filter["country"] = $item->getValue();
397  }
398 
399  if ($this->setting->get("usr_settings_course_export_sel_country")) {
400  $item = $this->addFilterItemByMetaType(
401  "sel_country",
403  true
404  );
405  $item->setOptions(
406  array("" => $this->lng->txt(
407  "trac_all"
408  )
409  ) + $this->getSelCountryCodes()
410  );
411  $this->filter["sel_country"] = $item->getValue();
412  }
413 
414  $item = $this->addFilterItemByMetaType(
415  "language",
417  true
418  );
419  $this->filter["language"] = $item->getValue();
420 
421  if ($tracking->hasExtendedData(
423  )) {
424  $item = $this->addFilterItemByMetaType(
425  "first_access_min",
427  true,
428  $this->lng->txt("trac_first_access")
429  );
430  $this->filter["first_access"] = $item->getDate();
431 
432  $item = $this->addFilterItemByMetaType(
433  "last_access_max",
435  true,
436  $this->lng->txt("trac_last_access")
437  );
438  $this->filter["last_access"] = $item->getDate();
439  }
440 
441  $item = $this->addFilterItemByMetaType(
442  "registration_filter",
444  true
445  );
446  $this->filter["registration"] = $item->getDate();
447  }
448 
449  public function getSelCountryCodes(): array
450  {
451  $options = array();
452  foreach (ilCountry::getCountryCodes() as $c) {
453  $options[$c] = $this->lng->txt("meta_c_" . $c);
454  }
455  asort($options);
456  return $options;
457  }
458 
462  public function getItems(int $a_object_id, int $a_ref_id): void
463  {
464  // show only selected subobjects for lp mode
465  $preselected_obj_ids = $filter = null;
466 
468  if (
469  $olp->getCurrentMode(
473  ) {
474  $collection = $olp->getCollectionInstance();
475  $preselected_obj_ids[$a_object_id][] = $a_ref_id;
476  foreach ($collection->getItems() as $item => $item_info) {
477  $tmp_lp = ilObjectLP::getInstance(
478  ilObject::_lookupObjId($item_info)
479  );
480  if ($tmp_lp->isActive()) {
481  $preselected_obj_ids[ilObject::_lookupObjId(
482  $item_info
483  )][] = $item_info;
484  }
485  }
486  $filter = $this->getCurrentFilter();
487  } elseif ($this->is_root) {
488  // using search to get all relevant objects
489  // #8498/#8499: restrict to objects with at least "read_learning_progress" access
490  $preselected_obj_ids = $this->searchObjects(
491  $this->getCurrentFilter(true),
492  "read_learning_progress"
493  );
494  } else {
495  // using summary filters
496  $filter = $this->getCurrentFilter();
497  }
498 
500  $a_object_id,
501  $a_ref_id,
505  ilUtil::stripSlashes($this->getLimit()),
506  $filter,
507  $this->getSelectedColumns(),
508  $preselected_obj_ids
509  );
510 
511  // build status to image map
512  $valid_status = array(ilLPStatus::LP_STATUS_NOT_ATTEMPTED_NUM,
516  );
517  $status_map = array();
519  foreach ($valid_status as $status) {
520  $status_map[$status] = $status_icons->renderIconForStatus($status);
521  }
522 
523  // language map
524  $this->lng->loadLanguageModule("meta");
525  $languages = array();
526  foreach ($this->lng->getInstalledLanguages() as $lang_key) {
527  $languages[$lang_key] = $this->lng->txt("meta_l_" . $lang_key);
528  }
529 
530  $rows = array();
531  foreach ($data["set"] as $idx => $result) {
532  // sessions have no title
533  if ($result["title"] == "" && $result["type"] == "sess") {
534  $sess = new ilObjSession($result["obj_id"], false);
535  $data["set"][$idx]["title"] = $sess->getFirstAppointment(
536  )->appointmentToString();
537  }
538 
539  $data["set"][$idx]["offline"] = ilLearningProgressBaseGUI::isObjectOffline(
540  $result["obj_id"],
541  $result["type"]
542  );
543 
544  // #13807
545  if ($result["ref_ids"]) {
546  $valid = false;
547  foreach ($result["ref_ids"] as $check_ref_id) {
549  'read_learning_progress',
550  $check_ref_id
551  )) {
552  $valid = true;
553  break;
554  }
555  }
556  if (!$valid) {
557  foreach (array_keys($data["set"][$idx]) as $col_id) {
558  if (!in_array(
559  $col_id,
560  array("type",
561  "title",
562  "obj_id",
563  "ref_id",
564  "offline"
565  )
566  )) {
567  $data["set"][$idx][$col_id] = null;
568  }
569  }
570  $data["set"][$idx]["privacy_conflict"] = true;
571  continue;
572  }
573  }
574 
575  // percentages
576  $users_no = $result["user_total"];
577  $data["set"][$idx]["country"] = $this->getItemsPercentages(
578  $result["country"],
579  $users_no
580  );
581  $data["set"][$idx]["gender"] = $this->getItemsPercentages(
582  $result["gender"],
583  $users_no,
584  array(
585  "n" => $this->lng->txt("gender_n"),
586  "m" => $this->lng->txt("gender_m"),
587  "f" => $this->lng->txt("gender_f"),
588  )
589  );
590  $data["set"][$idx]["city"] = $this->getItemsPercentages(
591  $result["city"],
592  $users_no
593  );
594  $data["set"][$idx]["sel_country"] = $this->getItemsPercentages(
595  $result["sel_country"],
596  $users_no,
597  $this->getSelCountryCodes()
598  );
599  $data["set"][$idx]["mark"] = $this->getItemsPercentages(
600  $result["mark"],
601  $users_no
602  );
603  $data["set"][$idx]["language"] = $this->getItemsPercentages(
604  $result["language"],
605  $users_no,
606  $languages
607  );
608 
609  // if we encounter any invalid status codes, e.g. null, map them to not attempted instead
610  foreach ($result["status"] as $status_code => $status_counter) {
611  // null is cast to ""
612  if ($status_code === "" || !in_array(
613  $status_code,
614  $valid_status
615  )) {
616  $result['status'][ilLPStatus::LP_STATUS_NOT_ATTEMPTED_NUM] =
617  $result['status'][ilLPStatus::LP_STATUS_NOT_ATTEMPTED_NUM] ?? 0 + $status_counter;
618  unset($result["status"][$status_code]);
619  }
620  }
621  $data["set"][$idx]["status"] = $this->getItemsPercentagesStatus(
622  $result["status"],
623  $users_no,
624  $status_map
625  );
626 
627  if (!$this->isPercentageAvailable($result["obj_id"])) {
628  $data["set"][$idx]["percentage_avg"] = null;
629  }
630  }
631 
632  $this->setMaxCount($data["cnt"]);
633  $this->setData($data["set"]);
634  }
635 
639  protected function getItemsPercentages(
640  $data = null,
641  int $overall = 0,
642  array $value_map = null,
643  $limit = 3
644  ): array {
645  if (!$overall) {
646  return [];
647  }
648 
649  $result = [];
650 
651  if ($data) {
652  if (is_array($data) && count($data) < $limit) {
653  $limit = count($data);
654  }
655  if (is_array($data) && (count($data) == $limit + 1)) {
656  ++$limit;
657  }
658  $counter = $others_counter = 0;
659  $others_sum = $overall;
660  $all_sum = 0;
661  foreach ($data as $id => $count) {
662  $counter++;
663  $all_sum += $count;
664  if ($counter <= $limit) {
665  $caption = $id;
666 
667  if ($value_map && isset($value_map[$id])) {
668  $caption = $value_map[$id];
669  }
670  if ($caption == "") {
671  $caption = $this->lng->txt("none");
672  }
673  if (
674  $counter == $limit &&
675  $all_sum < $overall
676  ) {
677  ++$others_counter;
678  continue;
679  }
680  $perc = round($count / $overall * 100);
681  $result[] = array(
682  "caption" => $caption,
683  "absolute" => $count,
684  // ." ".($count > 1 ? $lng->txt("users") : $lng->txt("user")),
685  "percentage" => $perc
686  );
687  $others_sum -= $count;
688  } else {
689  $others_counter++;
690  }
691  }
692 
693  if ($others_counter) {
694  $perc = round($others_sum / $overall * 100);
695  $result[] = array(
696  "caption" => $others_counter . " " . $this->lng->txt(
697  "trac_others"
698  ),
699  "absolute" => $others_sum,
700  // ." ".($others_sum > 1 ? $lng->txt("users") : $lng->txt("user")),
701  "percentage" => $perc
702  );
703  }
704  }
705 
706  return $result;
707  }
708 
712  protected function getItemsPercentagesStatus(
713  $data = null,
714  int $overall = 0,
715  array $value_map = null
716  ): array {
717  $result = array();
718  foreach ($value_map as $id => $caption) {
719  $count = 0;
720  if (isset($data[$id])) {
721  $count = $data[$id];
722  }
723  $perc = round($count / $overall * 100);
724 
725  $result[] = array(
726  "caption" => $caption,
727  "absolute" => $count,
728  "percentage" => $perc
729  );
730  }
731 
732  return $result;
733  }
734 
735  protected function parseValue(
736  string $id,
737  ?string $value,
738  string $type
739  ): string {
740  // get rid of aggregation
741  $pos = strrpos($id, "_");
742  if ($pos !== false) {
743  $function = strtoupper(substr($id, $pos + 1));
744  if (in_array(
745  $function,
746  array("MIN", "MAX", "SUM", "AVG", "COUNT")
747  )) {
748  $id = substr($id, 0, $pos);
749  }
750  }
751 
752  if (trim($value) == "") {
753  if ($id == "title") {
754  return "--" . $this->lng->txt("none") . "--";
755  }
756  return "";
757  }
758  switch ($id) {
759  case 'status_changed':
760  case "first_access":
761  case "create_date":
763  new ilDateTime($value, IL_CAL_DATETIME)
764  );
765  break;
766 
767  case "last_access":
769  new ilDateTime($value, IL_CAL_UNIX)
770  );
771  break;
772 
773  case "spent_seconds":
774  case "read_count_spent_seconds":
775  if (!ilObjectLP::supportsSpentSeconds($type)) {
776  $value = "-";
777  } else {
779  (int) $value,
780  $value < 3600
781  ); // #14858
782  }
783  break;
784 
785  case "percentage":
786  if (false /* $this->isPercentageAvailable() */) {
787  $value = "-";
788  } else {
789  $value = $value . "%";
790  }
791  break;
792 
793  case "mark":
794  if (!ilObjectLP::supportsMark($type)) {
795  $value = "-";
796  }
797  break;
798  }
799 
800  return $value;
801  }
802 
806  protected function fillRow(array $a_set): void
807  {
808  $this->tpl->setVariable(
809  "ICON",
811  (int) $a_set["obj_id"],
812  "tiny",
813  $a_set["type"]
814  )
815  );
816  $this->tpl->setVariable("ICON_ALT", $this->lng->txt($a_set["type"]));
817  $this->tpl->setVariable("TITLE", $a_set["title"]);
818 
819  if ($a_set["offline"] || ($a_set["privacy_conflict"] ?? null)) {
820  $mess = array();
821  if ($a_set["offline"]) {
822  $mess[] = $this->lng->txt("offline");
823  }
824  if ($a_set["privacy_conflict"] ?? null) {
825  $mess[] = $this->lng->txt("status_no_permission");
826  }
827  $this->tpl->setCurrentBlock("status_bl");
828  $this->tpl->setVariable("TEXT_STATUS", implode(", ", $mess));
829  $this->tpl->parseCurrentBlock();
830  }
831 
832  foreach ($this->getSelectedColumns() as $c) {
833  switch ($c) {
834  case "country":
835  case "gender":
836  case "city":
837  case "language":
838  case "status":
839  case "mark":
840  case "sel_country":
841  $this->renderPercentages($c, $a_set[$c]);
842  break;
843 
844  case "percentage_avg":
845  if ((int) $a_set[$c] === 0 || !$this->isPercentageAvailable(
846  $a_set["obj_id"]
847  )) {
848  $this->tpl->setVariable(strtoupper($c), "");
849  break;
850  }
851 
852  // no break
853  default:
854  $value = $this->parseValue($c, $a_set[$c], $a_set["type"]);
855  $this->tpl->setVariable(strtoupper($c), $value);
856  break;
857  }
858  }
859 
860  if ($this->is_root) {
861  $path = $this->buildPath($a_set["ref_ids"]);
862  if ($path) {
863  $this->tpl->setCurrentBlock("item_path");
864  foreach ($path as $ref_id => $path_item) {
865  $this->tpl->setVariable("PATH_ITEM", $path_item);
866 
867  if (!$this->anonymized) {
868  $this->ctrl->setParameterByClass(
869  $this->ctrl->getCmdClass(),
870  'details_id',
871  $ref_id
872  );
873  $this->tpl->setVariable(
874  "URL_DETAILS",
875  $this->ctrl->getLinkTargetByClass(
876  $this->ctrl->getCmdClass(),
877  'details'
878  )
879  );
880  $this->ctrl->setParameterByClass(
881  $this->ctrl->getCmdClass(),
882  'details_id',
883  ''
884  );
885  $this->tpl->setVariable(
886  "TXT_DETAILS",
887  $this->lng->txt(
888  'trac_participants'
889  )
890  );
891  } else {
892  $this->tpl->setVariable(
893  "URL_DETAILS",
895  $ref_id,
896  $a_set["type"]
897  )
898  );
899  $this->tpl->setVariable(
900  "TXT_DETAILS",
901  $this->lng->txt('view')
902  );
903  }
904 
905  $this->tpl->parseCurrentBlock();
906  }
907  }
908 
909  $this->tpl->setCurrentBlock("item_command");
910  $this->ctrl->setParameterByClass(
911  get_class($this),
912  'hide',
913  $a_set["obj_id"]
914  );
915  $this->tpl->setVariable(
916  "HREF_COMMAND",
917  $this->ctrl->getLinkTargetByClass(
918  get_class($this),
919  'hide'
920  )
921  );
922  $this->tpl->setVariable(
923  "TXT_COMMAND",
924  $this->lng->txt('trac_hide')
925  );
926  $this->tpl->parseCurrentBlock();
927 
928  $this->tpl->touchBlock("path_action");
929  } elseif ($a_set["ref_ids"]) { // #18446
930  // #16453
931  $path = new ilPathGUI();
932  $path = $path->getPath(
933  $this->ref_id,
934  (int) array_pop($a_set["ref_ids"])
935  );
936  if ($path) {
937  $this->tpl->setVariable(
938  'COLL_PATH',
939  $this->lng->txt('path') . ': ' . $path
940  );
941  }
942  }
943  }
944 
945  protected function renderPercentages(string $id, array $data): void
946  {
947  if ($data) {
948  foreach ($data as $item) {
949  $this->tpl->setCurrentBlock($id . "_row");
950  $this->tpl->setVariable("CAPTION", $item["caption"]);
951  $this->tpl->setVariable("ABSOLUTE", $item["absolute"]);
952  $this->tpl->setVariable("PERCENTAGE", $item["percentage"]);
953  $this->tpl->parseCurrentBlock();
954  }
955  } else {
956  $this->tpl->touchBlock($id);
957  }
958  }
959 
960  protected function isArrayColumn(string $a_name): bool
961  {
962  if (in_array(
963  $a_name,
964  array("country",
965  "gender",
966  "city",
967  "language",
968  "status",
969  "mark",
970  'sel_country'
971  )
972  )) {
973  return true;
974  }
975  return false;
976  }
977 
978  public function numericOrdering(string $a_field): bool
979  {
980  $pos = strrpos($a_field, "_");
981  if ($pos !== false) {
982  $function = strtoupper(substr($a_field, $pos + 1));
983  if (in_array(
984  $function,
985  array("MIN", "MAX", "SUM", "AVG", "COUNT", "TOTAL")
986  )) {
987  return true;
988  }
989  }
990  return false;
991  }
992 
993  public function isStatusShown(): bool
994  {
995  return in_array('status', $this->getSelectedColumns());
996  }
997 
998  protected function fillHeaderExcel(ilExcel $a_excel, int &$a_row): void
999  {
1000  $a_excel->setCell($a_row, 0, $this->lng->txt("title"));
1001 
1002  $labels = $this->getSelectableColumns();
1003  $cnt = 1;
1004  foreach ($this->getSelectedColumns() as $c) {
1005  $label = $labels[$c]["txt"];
1006  $label = str_replace(
1007  "&#216;",
1008  $this->lng->txt("trac_average"),
1009  $label
1010  );
1011  $label = str_replace(
1012  "&#8721;",
1013  $this->lng->txt("trac_sum"),
1014  $label
1015  );
1016 
1017  if (!$this->isArrayColumn($c)) {
1018  $a_excel->setCell($a_row, $cnt, $label);
1019  $cnt++;
1020  } else {
1021  if ($c != "status") {
1022  $a_excel->setCell($a_row, $cnt, $label . " #1");
1023  $a_excel->setCell($a_row, ++$cnt, $label . " #1");
1024  $a_excel->setCell($a_row, ++$cnt, $label . " #1 %");
1025  $a_excel->setCell($a_row, ++$cnt, $label . " #2");
1026  $a_excel->setCell($a_row, ++$cnt, $label . " #2");
1027  $a_excel->setCell($a_row, ++$cnt, $label . " #2 %");
1028  $a_excel->setCell($a_row, ++$cnt, $label . " #3");
1029  $a_excel->setCell($a_row, ++$cnt, $label . " #3");
1030  $a_excel->setCell($a_row, ++$cnt, $label . " #3 %");
1031  $a_excel->setCell(
1032  $a_row,
1033  ++$cnt,
1034  $label . " " . $this->lng->txt(
1035  "trac_others"
1036  )
1037  );
1038  $a_excel->setCell(
1039  $a_row,
1040  ++$cnt,
1041  $label . " " . $this->lng->txt(
1042  "trac_others"
1043  )
1044  );
1045  $a_excel->setCell(
1046  $a_row,
1047  ++$cnt,
1048  $label . " " . $this->lng->txt(
1049  "trac_others"
1050  ) . " %"
1051  );
1052  } else {
1053  // build status to image map
1054  $valid_status = array(ilLPStatus::LP_STATUS_NOT_ATTEMPTED_NUM,
1058  );
1059  $cnt--;
1060  foreach ($valid_status as $status) {
1062  $status
1063  );
1064  $a_excel->setCell($a_row, ++$cnt, $text);
1065  $a_excel->setCell($a_row, ++$cnt, $text . " %");
1066  }
1067  }
1068  $cnt++;
1069  }
1070  }
1071 
1072  $a_excel->setBold(
1073  "A" . $a_row . ":" . $a_excel->getColumnCoord($cnt) . $a_row
1074  );
1075  }
1076 
1077  protected function fillRowExcel(
1078  ilExcel $a_excel,
1079  int &$a_row,
1080  array $a_set
1081  ): void {
1082  $a_excel->setCell($a_row, 0, $a_set["title"]);
1083 
1084  $cnt = 1;
1085  foreach ($this->getSelectedColumns() as $c) {
1086  if (!$this->isArrayColumn($c)) {
1087  $val = $this->parseValue($c, $a_set[$c], $a_set["type"]);
1088  $a_excel->setCell($a_row, $cnt, $val);
1089  $cnt++;
1090  } else {
1091  foreach ((array) $a_set[$c] as $idx => $value) {
1092  if ($c == "status") {
1093  $a_excel->setCell(
1094  $a_row,
1095  $cnt,
1096  (int) $value["absolute"]
1097  );
1098  $a_excel->setCell(
1099  $a_row,
1100  ++$cnt,
1101  $value["percentage"] . "%"
1102  );
1103  } else {
1104  $a_excel->setCell($a_row, $cnt, $value["caption"]);
1105  $a_excel->setCell(
1106  $a_row,
1107  ++$cnt,
1108  (int) $value["absolute"]
1109  );
1110  $a_excel->setCell(
1111  $a_row,
1112  ++$cnt,
1113  $value["percentage"] . "%"
1114  );
1115  }
1116  $cnt++;
1117  }
1118  if (sizeof($a_set[$c]) < 4 && $c != "status") {
1119  for ($loop = 4; $loop > sizeof($a_set[$c]); $loop--) {
1120  $a_excel->setCell($a_row, $cnt, "");
1121  $a_excel->setCell($a_row, ++$cnt, "");
1122  $a_excel->setCell($a_row, ++$cnt, "");
1123  $cnt++;
1124  }
1125  }
1126  }
1127  }
1128  }
1129 
1130  protected function fillHeaderCSV(ilCSVWriter $a_csv): void
1131  {
1132  $a_csv->addColumn($this->lng->txt("title"));
1133 
1134  $labels = $this->getSelectableColumns();
1135  foreach ($this->getSelectedColumns() as $c) {
1136  $label = $labels[$c]["txt"];
1137  $label = str_replace(
1138  "&#216;",
1139  $this->lng->txt("trac_average"),
1140  $label
1141  );
1142  $label = str_replace(
1143  "&#8721;",
1144  $this->lng->txt("trac_sum"),
1145  $label
1146  );
1147 
1148  if (!$this->isArrayColumn($c)) {
1149  $a_csv->addColumn($label);
1150  } else {
1151  if ($c != "status") {
1152  $a_csv->addColumn($label . " #1");
1153  $a_csv->addColumn($label . " #1");
1154  $a_csv->addColumn($label . " #1 %");
1155  $a_csv->addColumn($label . " #2");
1156  $a_csv->addColumn($label . " #2");
1157  $a_csv->addColumn($label . " #2 %");
1158  $a_csv->addColumn($label . " #3");
1159  $a_csv->addColumn($label . " #3");
1160  $a_csv->addColumn($label . " #3 %");
1161  $a_csv->addColumn(
1162  $label . " " . $this->lng->txt("trac_others")
1163  );
1164  $a_csv->addColumn(
1165  $label . " " . $this->lng->txt("trac_others")
1166  );
1167  $a_csv->addColumn(
1168  $label . " " . $this->lng->txt("trac_others") . " %"
1169  );
1170  } else {
1171  // build status to image map
1172  $valid_status = array(ilLPStatus::LP_STATUS_NOT_ATTEMPTED_NUM,
1176  );
1177  foreach ($valid_status as $status) {
1179  $status
1180  );
1181  $a_csv->addColumn($text);
1182  $a_csv->addColumn($text . " %");
1183  }
1184  }
1185  }
1186  }
1187 
1188  $a_csv->addRow();
1189  }
1190 
1191  protected function fillRowCSV(ilCSVWriter $a_csv, array $a_set): void
1192  {
1193  $a_csv->addColumn($a_set["title"]);
1194 
1195  foreach ($this->getSelectedColumns() as $c) {
1196  if (!$this->isArrayColumn($c)) {
1197  $val = $this->parseValue($c, $a_set[$c], $a_set["type"]);
1198  $a_csv->addColumn($val);
1199  } else {
1200  foreach ((array) $a_set[$c] as $idx => $value) {
1201  if ($c != "status") {
1202  $a_csv->addColumn($value["caption"]);
1203  }
1204  $a_csv->addColumn((string) $value["absolute"]);
1205  $a_csv->addColumn($value["percentage"]);
1206  }
1207  if (sizeof($a_set[$c]) < 4 && $c != "status") {
1208  for ($loop = 4; $loop > sizeof($a_set[$c]); $loop--) {
1209  $a_csv->addColumn("");
1210  $a_csv->addColumn("");
1211  $a_csv->addColumn("");
1212  }
1213  }
1214  }
1215  }
1216 
1217  $a_csv->addRow();
1218  }
1219 }
const LP_STATUS_COMPLETED_NUM
__construct(?object $a_parent_obj, string $a_parent_cmd, int $a_ref_id, bool $a_print_mode=false)
Constructor.
parseValue(string $id, ?string $value, string $type)
setData(array $a_data)
Creates a path for a start and endnode.
addColumn(string $a_col)
fillRow(array $a_set)
Fill table row.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
fillRowCSV(ilCSVWriter $a_csv, array $a_set)
getCurrentFilter(bool $as_query=false)
setExportFormats(array $formats)
Set available export formats.
const IL_CAL_DATETIME
$c
Definition: cli.php:38
static _getIcon(int $obj_id=0, string $size="big", string $type="", bool $offline=false)
Get icon for repository item.
setFormAction(string $a_form_action, bool $a_multipart=false)
fillHeaderCSV(ilCSVWriter $a_csv)
const ROOT_FOLDER_ID
Definition: constants.php:32
const LP_STATUS_NOT_ATTEMPTED
fillHeaderExcel(ilExcel $a_excel, int &$a_row)
static stripSlashes(string $a_str, bool $a_strip_html=true, string $a_allow="")
getItems(int $a_object_id, int $a_ref_id)
Build summary item rows for given object and filter(s.
searchObjects(array $filter, string $permission, ?array $preset_obj_ids=null, bool $a_check_lp_activation=true)
Search objects that match current filters.
$valid
getColumnCoord(int $a_col)
Get column "name" from number.
setShowTemplates(bool $a_value)
const LP_STATUS_IN_PROGRESS_NUM
static formatDate(ilDateTime $date, bool $a_skip_day=false, bool $a_include_wd=false, bool $include_seconds=false)
static getInstance(int $variant=ilLPStatusIcons::ICON_VARIANT_DEFAULT, ?\ILIAS\UI\Renderer $renderer=null, ?\ILIAS\UI\Factory $factory=null)
setPrintMode(bool $a_value=false)
setCell(int $a_row, int $a_col, $a_value, ?string $a_datatype=null)
Set cell value.
getItemsPercentages( $data=null, int $overall=0, array $value_map=null, $limit=3)
Render data as needed for summary list (based on grouped values)
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) ...
const FILTER_NUMBER_RANGE
setId(string $a_val)
$path
Definition: ltiservices.php:32
const LP_STATUS_IN_PROGRESS
static _lookupObjId(int $ref_id)
global $DIC
Definition: feed.php:28
static getObjectsSummaryForObject(int $a_parent_obj_id, int $a_parent_ref_id, string $a_order_field="", string $a_order_dir="", int $a_offset=0, int $a_limit=9999, ?array $a_filters=null, ?array $a_additional_fields=null, ?array $a_preselected_obj_ids=null)
Get all aggregated tracking data for parent object :TODO: sorting, offset, limit, objectives...
addFilterItemByMetaType(string $id, int $type=self::FILTER_TEXT, bool $a_optional=false, string $caption="")
Add filter by standard type.
setBold(string $a_coords)
Set cell(s) to bold.
const LP_STATUS_FAILED
const FILTER_DATETIME_RANGE
TableGUI class for learning progress.
setDefaultOrderField(string $a_defaultorderfield)
isPercentageAvailable(int $a_obj_id)
const FILTER_DURATION_RANGE
setRowTemplate(string $a_template, string $a_template_dir="")
Set row template.
static _getStatusText(int $a_status, ?ilLanguage $a_lng=null)
Get status alt text.
$txt
Definition: error.php:13
renderPercentages(string $id, array $data)
$rows
Definition: xhr_table.php:10
const LP_STATUS_NOT_ATTEMPTED_NUM
static supportsSpentSeconds(string $obj_type)
fillRowExcel(ilExcel $a_excel, int &$a_row, array $a_set)
__construct(Container $dic, ilPlugin $plugin)
setLimit(int $a_limit=0, int $a_default_limit=0)
static checkPermission(string $a_permission, int $a_ref_id, ?int $a_user_id=null)
wrapper for rbac access checks
addColumn(string $a_text, string $a_sort_field="", string $a_width="", bool $a_is_checkbox_action_column=false, string $a_class="", string $a_tooltip="", bool $a_tooltip_with_html=false)
getItemsPercentagesStatus( $data=null, int $overall=0, array $value_map=null)
Render status data as needed for summary list (based on grouped values)
static getCountryCodes()
Get country codes (DIN EN 3166-1)
static supportsMark(string $obj_type)
static _lookupType(int $id, bool $reference=false)
parseTitle(int $a_obj_id, string $action, int $a_user_id=0)
static isObjectOffline(int $a_obj_id, string $a_type='')
const LP_STATUS_COMPLETED
static getInstance(int $obj_id)
setEnableHeader(bool $a_enableheader)
setMaxCount(int $a_max_count)
set max.
const LP_STATUS_FAILED_NUM