ILIAS  release_8 Revision v8.24
class.ilSessionStatisticsGUI.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
25{
26 private const MODE_TODAY = 1;
27 private const MODE_LAST_DAY = 2;
28 private const MODE_LAST_WEEK = 3;
29 private const MODE_LAST_MONTH = 4;
30 private const MODE_DAY = 5;
31 private const MODE_WEEK = 6;
32 private const MODE_MONTH = 7;
33 private const MODE_YEAR = 8;
34
35 private const SCALE_DAY = 1;
36 private const SCALE_WEEK = 2;
37 private const SCALE_MONTH = 3;
38 private const SCALE_YEAR = 4;
39 private const SCALE_PERIODIC_WEEK = 5;
40
41 private const REQUEST_SMD = "smd";
42 private const REQUEST_SMM = "smm";
43 private const REQUEST_SST = "sst";
44 private const REQUEST_STO = "sto";
45 private const REQUEST_REF = "ref_id";
46
47 private ilCtrl $ilCtrl;
57
58 private int $ref_id = -1;
59 private ?int $smd = null;
60 private ?string $smm = null;
61 private ?string $sst = null;
62 private ?string $sto = null;
63
64 public function __construct()
65 {
66 global $DIC;
67
68 $this->ilCtrl = $DIC->ctrl();
69 $this->ilTabs = $DIC->tabs();
70 $this->lng = $DIC->language();
71 $this->tpl = $DIC->ui()->mainTemplate();
72 $this->toolbar = $DIC->toolbar();
73 $this->settings = $DIC->settings();
74 $this->access = $DIC->access();
75 $this->clientIniFile = $DIC->clientIni();
76 $this->user = $DIC->user();
77 $this->logger = $DIC->logger()->auth();
78
79 $http = $DIC->http();
80 $kindlyTo = $DIC->refinery()->kindlyTo();
81 if ($http->request()->getMethod() === "POST") {
82 if ($http->wrapper()->post()->has(self::REQUEST_SMD)) {
83 $this->smd = $http->wrapper()->post()->retrieve(self::REQUEST_SMD, $kindlyTo->int());
84 }
85 if ($http->wrapper()->post()->has(self::REQUEST_SMM)) {
86 $this->smm = $http->wrapper()->post()->retrieve(self::REQUEST_SMM, $kindlyTo->string());
87 }
88 if ($http->wrapper()->post()->has(self::REQUEST_STO)) {
89 $this->sto = $http->wrapper()->post()->retrieve(self::REQUEST_STO, $kindlyTo->string());
90 }
91 if ($http->wrapper()->post()->has(self::REQUEST_SST)) {
92 $this->sst = $http->wrapper()->post()->retrieve(self::REQUEST_SST, $kindlyTo->string());
93 }
94 } else {
95 if ($http->wrapper()->query()->has(self::REQUEST_SMD)) {
96 $this->smd = $http->wrapper()->query()->retrieve(self::REQUEST_SMD, $kindlyTo->int());
97 }
98 if ($http->wrapper()->query()->has(self::REQUEST_SMM)) {
99 $this->smm = $http->wrapper()->query()->retrieve(self::REQUEST_SMM, $kindlyTo->string());
100 }
101 if ($http->wrapper()->query()->has(self::REQUEST_STO)) {
102 $this->sto = $http->wrapper()->query()->retrieve(self::REQUEST_STO, $kindlyTo->string());
103 }
104 if ($http->wrapper()->query()->has(self::REQUEST_SST)) {
105 $this->sst = $http->wrapper()->query()->retrieve(self::REQUEST_SST, $kindlyTo->string());
106 }
107 }
108 if ($http->wrapper()->query()->has(self::REQUEST_REF)) {
109 $this->ref_id = $http->wrapper()->query()->retrieve(self::REQUEST_REF, $kindlyTo->int());
110 }
111 }
112
113 public function executeCommand(): bool
114 {
115 $this->setSubTabs();
116
117 switch ($this->ilCtrl->getNextClass()) {
118 default:
119 $cmd = $this->ilCtrl->getCmd("current");
120 $this->$cmd();
121 }
122
123 return true;
124 }
125
126 protected function setSubTabs(): void
127 {
128 $this->ilTabs->addSubTab(
129 "current",
130 $this->lng->txt("trac_current_system_load"),
131 $this->ilCtrl->getLinkTarget($this, "current")
132 );
133 $this->ilTabs->addSubTab(
134 "short",
135 $this->lng->txt("trac_short_system_load"),
136 $this->ilCtrl->getLinkTarget($this, "short")
137 );
138 $this->ilTabs->addSubTab(
139 "long",
140 $this->lng->txt("trac_long_system_load"),
141 $this->ilCtrl->getLinkTarget($this, "long")
142 );
143 $this->ilTabs->addSubTab(
144 "periodic",
145 $this->lng->txt("trac_periodic_system_load"),
146 $this->ilCtrl->getLinkTarget($this, "periodic")
147 );
148 }
149
150 protected function current(bool $a_export = false): void
151 {
152 $this->ilTabs->activateSubTab("current");
153
154 // current mode
155 if (!$this->smd) {
156 $mode = self::MODE_TODAY;
157 } else {
158 $mode = $this->smd;
159 }
160
161 // current measure
162 if (!$this->smm) {
163 $measure = "avg";
164 } else {
165 $measure = $this->smm;
166 }
167
168 switch ($mode) {
169 default:
170 case self::MODE_TODAY:
171 $time_from = strtotime("today");
172 $time_to = strtotime("tomorrow") - 1;
173 $scale = self::SCALE_DAY;
174 break;
175
177 $time_to = time();
178 $time_from = $time_to - 60 * 60 * 24;
179 $scale = self::SCALE_DAY;
180 break;
181
183 $time_to = time();
184 $time_from = $time_to - 60 * 60 * 24 * 7;
185 $scale = self::SCALE_WEEK;
186 break;
187
189 $time_to = time();
190 $time_from = $time_to - 60 * 60 * 24 * 30;
191 $scale = self::SCALE_MONTH;
192 break;
193 }
194
195 $mode_options = array(
196 self::MODE_TODAY => $this->lng->txt("trac_session_statistics_mode_today"),
197 self::MODE_LAST_DAY => $this->lng->txt("trac_session_statistics_mode_last_day"),
198 self::MODE_LAST_WEEK => $this->lng->txt("trac_session_statistics_mode_last_week"),
199 self::MODE_LAST_MONTH => $this->lng->txt("trac_session_statistics_mode_last_month"));
200
201 $title = $this->lng->txt("trac_current_system_load") . " - " . $mode_options[$mode];
202 $data = $this->buildData($time_from, $time_to, $title);
203
204 if (!$a_export) {
205 // toolbar
206 $this->toolbar->setFormAction($this->ilCtrl->getFormAction($this, "current"));
207
208 $mode_selector = new ilSelectInputGUI("&nbsp;" . $this->lng->txt("trac_scale"), "smd");
209 $mode_selector->setOptions($mode_options);
210 $mode_selector->setValue($mode);
211 $this->toolbar->addInputItem($mode_selector, true);
212
213 $measure_options = array(
214 "avg" => $this->lng->txt("trac_session_active_avg"),
215 "min" => $this->lng->txt("trac_session_active_min"),
216 "max" => $this->lng->txt("trac_session_active_max"));
217
218 $measure_selector = new ilSelectInputGUI("&nbsp;" . $this->lng->txt("trac_measure"), "smm");
219 $measure_selector->setOptions($measure_options);
220 $measure_selector->setValue($measure);
221 $this->toolbar->addInputItem($measure_selector, true);
222
223 $this->toolbar->addFormButton($this->lng->txt("ok"), "current");
224
225 if (count($data["active"])) {
226 $this->toolbar->addSeparator();
227 $this->toolbar->addFormButton($this->lng->txt("export"), "currentExport");
228 }
229
230 $this->tpl->setContent($this->render($data, $scale, $measure));
231
232 $this->tpl->setLeftContent($this->renderCurrentBasics());
233 } else {
234 $this->exportCSV($data, $scale);
235 }
236 }
237
238 protected function currentExport(): void
239 {
240 $this->current(true);
241 }
242
246 protected function importDate(string $a_incoming, int $a_default = null)
247 {
248 if (!$a_default) {
249 $a_default = time();
250 }
251
252 $parsed = ilCalendarUtil::parseIncomingDate($a_incoming);
253 return $parsed
254 ? $parsed->get(IL_CAL_UNIX)
255 : $a_default;
256 }
257
258 protected function short(bool $a_export = false): void
259 {
260 $this->ilTabs->activateSubTab("short");
261
262 //TODO validate input
263 // current start
264 $time_to = $this->importDate((string) $this->sst);
265
266 // current mode
267 if (!$this->smd) {
268 $mode = self::MODE_DAY;
269 } else {
270 $mode = $this->smd;
271 }
272
273 // current measure
274 if (!$this->smm) {
275 $measure = "avg";
276 } else {
277 $measure = $this->smm;
278 }
279
280 switch ($mode) {
281 default:
282 case self::MODE_DAY:
283 $time_from = $time_to - 60 * 60 * 24;
284 $scale = self::SCALE_DAY;
285 break;
286
287 case self::MODE_WEEK:
288 $time_from = $time_to - 60 * 60 * 24 * 7;
289 $scale = self::SCALE_WEEK;
290 break;
291 }
292
293 $mode_options = array(
294 self::MODE_DAY => $this->lng->txt("trac_session_statistics_mode_day"),
295 self::MODE_WEEK => $this->lng->txt("trac_session_statistics_mode_week")
296 );
297
298 $title = $this->lng->txt("trac_short_system_load") . " - " . $mode_options[$mode];
299 $data = $this->buildData($time_from, $time_to, $title);
300
301 if (!$a_export) {
302 // toolbar
303 $this->toolbar->setFormAction($this->ilCtrl->getFormAction($this, "short"));
304
305 $start_selector = new ilDateTimeInputGUI($this->lng->txt("trac_end_at"), "sst");
306 $start_selector->setDate(new ilDate($time_to, IL_CAL_UNIX));
307 $this->toolbar->addInputItem($start_selector, true);
308
309 $mode_selector = new ilSelectInputGUI("&nbsp;" . $this->lng->txt("trac_scale"), "smd");
310 $mode_selector->setOptions($mode_options);
311 $mode_selector->setValue($mode);
312 $this->toolbar->addInputItem($mode_selector, true);
313
314 $measure_options = array(
315 "avg" => $this->lng->txt("trac_session_active_avg"),
316 "min" => $this->lng->txt("trac_session_active_min"),
317 "max" => $this->lng->txt("trac_session_active_max"));
318
319 $measure_selector = new ilSelectInputGUI("&nbsp;" . $this->lng->txt("trac_measure"), "smm");
320 $measure_selector->setOptions($measure_options);
321 $measure_selector->setValue($measure);
322 $this->toolbar->addInputItem($measure_selector, true);
323
324 $this->toolbar->addFormButton($this->lng->txt("ok"), "short");
325
326 if (count($data["active"])) {
327 $this->toolbar->addSeparator();
328 $this->toolbar->addFormButton($this->lng->txt("export"), "shortExport");
329 }
330
331 $this->tpl->setContent($this->render($data, $scale, $measure));
332 } else {
333 $this->exportCSV($data, $scale);
334 }
335 }
336
337 protected function shortExport(): void
338 {
339 $this->short(true);
340 }
341
342 protected function long($a_export = false): void
343 {
344 $this->ilTabs->activateSubTab("long");
345
346 // current start
347 //TODO validate input
348 $time_to = $this->importDate((string) $this->sst);
349
350 // current mode
351 if (!$this->smd) {
352 $mode = self::MODE_WEEK;
353 } else {
354 $mode = $this->smd;
355 }
356
357 switch ($mode) {
358 default:
359 case self::MODE_WEEK:
360 $time_from = $time_to - 60 * 60 * 24 * 7;
361 $scale = self::SCALE_WEEK;
362 break;
363
364 case self::MODE_MONTH:
365 $time_from = $time_to - 60 * 60 * 24 * 30;
366 $scale = self::SCALE_MONTH;
367 break;
368
369 case self::MODE_YEAR:
370 $time_from = $time_to - 60 * 60 * 24 * 365;
371 $scale = self::SCALE_YEAR;
372 break;
373 }
374
375 $mode_options = array(
376 self::MODE_WEEK => $this->lng->txt("trac_session_statistics_mode_week"),
377 self::MODE_MONTH => $this->lng->txt("trac_session_statistics_mode_month"),
378 self::MODE_YEAR => $this->lng->txt("trac_session_statistics_mode_year")
379 );
380
381 $title = $this->lng->txt("trac_long_system_load") . " - " . $mode_options[$mode];
382 $data = $this->buildData($time_from, $time_to, $title);
383
384 if (!$a_export) {
385 // toolbar
386 $this->toolbar->setFormAction($this->ilCtrl->getFormAction($this, "long"));
387
388 $start_selector = new ilDateTimeInputGUI($this->lng->txt("trac_end_at"), "sst");
389 $start_selector->setDate(new ilDate($time_to, IL_CAL_UNIX));
390 $this->toolbar->addInputItem($start_selector, true);
391
392 $mode_selector = new ilSelectInputGUI("&nbsp;" . $this->lng->txt("trac_scale"), "smd");
393 $mode_selector->setOptions($mode_options);
394 $mode_selector->setValue($mode);
395 $this->toolbar->addInputItem($mode_selector, true);
396
397 $this->toolbar->addFormButton($this->lng->txt("ok"), "long");
398
399 if (count($data["active"])) {
400 $this->toolbar->addSeparator();
401 $this->toolbar->addFormButton($this->lng->txt("export"), "longExport");
402 }
403
404 $this->tpl->setContent($this->render($data, $scale));
405 } else {
406 $this->exportCSV($data, $scale);
407 }
408 }
409
410 protected function longExport(): void
411 {
412 $this->long(true);
413 }
414
415 protected function periodic($a_export = false): void
416 {
417 $this->ilTabs->activateSubTab("periodic");
418
419 //TODO validate input
420 // current start
421 $time_to = $this->importDate((string) $this->sst);
422
423 // current end
424 $time_from = $this->importDate((string) $this->sto, strtotime("-7 days"));
425
426 // mixed up dates?
427 if ($time_to < $time_from) {
428 $tmp = $time_to;
429 $time_to = $time_from;
430 $time_from = $tmp;
431 }
432
433 $title = $this->lng->txt("trac_periodic_system_load");
434 $data = $this->buildData($time_from, $time_to, $title);
435
436 if (!$a_export) {
437 // toolbar
438 $this->toolbar->setFormAction($this->ilCtrl->getFormAction($this, "periodic"));
439
440 $end_selector = new ilDateTimeInputGUI($this->lng->txt("trac_begin_at"), "sto");
441 $end_selector->setDate(new ilDate($time_from, IL_CAL_UNIX));
442 $this->toolbar->addInputItem($end_selector, true);
443
444 $start_selector = new ilDateTimeInputGUI($this->lng->txt("trac_end_at"), "sst");
445 $start_selector->setDate(new ilDate($time_to, IL_CAL_UNIX));
446 $this->toolbar->addInputItem($start_selector, true);
447
448 $this->toolbar->addFormButton($this->lng->txt("ok"), "periodic");
449
450 if (count($data["active"])) {
451 $this->toolbar->addSeparator();
452 $this->toolbar->addFormButton($this->lng->txt("export"), "periodicExport");
453 }
454
455 $this->tpl->setContent($this->render($data, self::SCALE_PERIODIC_WEEK));
456 } else {
457 $this->exportCSV($data, self::SCALE_PERIODIC_WEEK);
458 }
459 }
460
461 protected function periodicExport(): void
462 {
463 $this->periodic(true);
464 }
465
466 protected function renderCurrentBasics(): string
467 {
468 // basic data - not time related
469
471
472 $control_active = ((int) $this->settings->get('session_handling_type', "0") === 1);
473 if ($control_active) {
474 $control_max_sessions = (int) $this->settings->get('session_max_count', (string) ilSessionControl::DEFAULT_MAX_COUNT);
475 $control_min_idle = (int) $this->settings->get('session_min_idle', (string) ilSessionControl::DEFAULT_MIN_IDLE);
476 $control_max_idle = (int) $this->settings->get('session_max_idle', (string) ilSessionControl::DEFAULT_MAX_IDLE);
477 $control_max_idle_first = (int) $this->settings->get('session_max_idle_after_first_request', (string) ilSessionControl::DEFAULT_MAX_IDLE_AFTER_FIRST_REQUEST);
478 }
479
482
483
484 // build left column
485
486 $left = new ilTemplate("tpl.session_statistics_left.html", true, true, "Services/Authentication");
487
488 $left->setVariable("CAPTION_CURRENT", $this->lng->txt("users_online"));
489 $left->setVariable("VALUE_CURRENT", $active);
490
491 $left->setVariable("CAPTION_LAST_AGGR", $this->lng->txt("trac_last_aggregation"));
492 $left->setVariable("VALUE_LAST_AGGR", ilDatePresentation::formatDate($last_aggr));
493
494 $left->setVariable("CAPTION_LAST_MAX", $this->lng->txt("trac_last_maxed_out_sessions"));
495 $left->setVariable("VALUE_LAST_MAX", ilDatePresentation::formatDate($last_maxed_out));
496
497 $left->setVariable("CAPTION_SESSION_CONTROL", $this->lng->txt("sess_load_dependent_session_handling"));
498 if (!$control_active) {
499 $left->setVariable("VALUE_SESSION_CONTROL", $this->lng->txt("no"));
500 } else {
501 $left->setVariable("VALUE_SESSION_CONTROL", $this->lng->txt("yes"));
502
503 $left->setCurrentBlock("control_details");
504
505 $left->setVariable("CAPTION_SESSION_CONTROL_LIMIT", $this->lng->txt("session_max_count"));
506 $left->setVariable("VALUE_SESSION_CONTROL_LIMIT", $control_max_sessions);
507
508 $left->setVariable("CAPTION_SESSION_CONTROL_IDLE_MIN", $this->lng->txt("session_min_idle"));
509 $left->setVariable("VALUE_SESSION_CONTROL_IDLE_MIN", $control_min_idle);
510
511 $left->setVariable("CAPTION_SESSION_CONTROL_IDLE_MAX", $this->lng->txt("session_max_idle"));
512 $left->setVariable("VALUE_SESSION_CONTROL_IDLE_MAX", $control_max_idle);
513
514 $left->setVariable("CAPTION_SESSION_CONTROL_IDLE_FIRST", $this->lng->txt("session_max_idle_after_first_request"));
515 $left->setVariable("VALUE_SESSION_CONTROL_IDLE_FIRST", $control_max_idle_first);
516
517 $left->parseCurrentBlock();
518 }
519
520 // sync button
521 if ($this->access->checkAccess("write", "", $this->ref_id)) {
522 $left->setVariable("URL_SYNC", $this->ilCtrl->getFormAction($this, "adminSync"));
523 $left->setVariable("CMD_SYNC", "adminSync");
524 $left->setVariable("TXT_SYNC", $this->lng->txt("trac_sync_session_stats"));
525 }
526
527 return $left->get();
528 }
529
530 protected function buildData(int $a_time_from, int $a_time_to, string $a_title): array
531 {
532 // basic data - time related
533
534 $maxed_out_duration = round(ilSessionStatistics::getMaxedOutDuration($a_time_from, $a_time_to) / 60);
535 $counters = ilSessionStatistics::getNumberOfSessionsByType($a_time_from, $a_time_to);
536 $opened = (int) $counters["opened"];
537 $closed_limit = (int) $counters["closed_limit"];
538 unset($counters["opened"], $counters["closed_limit"]);
539
540
541 // build center column
542
543 $data = array();
544
546 $data["title"] = $a_title . " (" .
548 new ilDateTime($a_time_from, IL_CAL_UNIX),
549 new ilDateTime($a_time_to, IL_CAL_UNIX)
550 ) . ")";
551
552 $data["maxed_out_time"] = array($this->lng->txt("trac_maxed_out_time"), $maxed_out_duration);
553 $data["maxed_out_counter"] = array($this->lng->txt("trac_maxed_out_counter"), $closed_limit);
554 $data["opened"] = array($this->lng->txt("trac_sessions_opened"), $opened);
555 $data["closed"] = array($this->lng->txt("trac_sessions_closed"), array_sum($counters));
556 foreach ($counters as $type => $counter) {
557 $data["closed_details"][] = array($this->lng->txt("trac_" . $type), (int) $counter);
558 }
559
560 $data["active"] = ilSessionStatistics::getActiveSessions($a_time_from, $a_time_to);
561 $this->logger->debug("Data to plot: " . var_export($data, true));
562 return $data;
563 }
564
565 protected function render(array $a_data, int $a_scale, string $a_measure = null): string
566 {
567 $center = new ilTemplate("tpl.session_statistics_center.html", true, true, "Services/Authentication");
568
569 foreach ($a_data as $idx => $item) {
570 switch ($idx) {
571 case "active":
572 case "title":
573 // nothing to do
574 break;
575
576 case "closed_details":
577 $center->setCurrentBlock("closed_details");
578 foreach ($item as $detail) {
579 $center->setVariable("CAPTION_CLOSED_DETAILS", $detail[0]);
580 $center->setVariable("VALUE_CLOSED_DETAILS", $detail[1]);
581 $center->parseCurrentBlock();
582 }
583 break;
584
585 default:
586 $tpl_var = strtoupper($idx);
587 $center->setVariable("CAPTION_" . $tpl_var, $item[0]);
588 $center->setVariable("VALUE_" . $tpl_var, $item[1]);
589 break;
590 }
591 }
592
593 if ($a_data["active"]) {
594 $center->setVariable("CHART", $this->getChart($a_data["active"], $a_data["title"], $a_scale, $a_measure));
595 } else {
596 $this->tpl->setOnScreenMessage('info', $this->lng->txt("trac_session_statistics_no_data"));
597 }
598
599 return $center->get();
600 }
601
605 protected function getChart(array $a_data, string $a_title, int $a_scale = self::SCALE_DAY, string $a_measure = null): string
606 {
608 $chart->setSize("700", "500");
609 $chart->setYAxisToInteger(true);
610
611 $legend = new ilChartLegend();
612 $chart->setLegend($legend);
613
614 if (!$a_measure) {
615 $measures = ["min", "avg", "max"];
616 } else {
617 $measures = [$a_measure];
618 }
619
620 $colors_map = array("min" => "#00cc00",
621 "avg" => "#0000cc",
622 "max" => "#cc00cc");
623
624 $colors = $act_line = array();
625 foreach ($measures as $measure) {
626 $act_line[$measure] = $chart->getDataInstance(ilChartGrid::DATA_LINES);
627 $act_line[$measure]->setLineSteps(true);
628 $act_line[$measure]->setLabel($this->lng->txt("trac_session_active_" . $measure));
629 $colors[] = $colors_map[$measure];
630 }
631
632 if ($a_scale === self::SCALE_DAY || $a_scale === self::SCALE_WEEK) {
633 $max_line = $chart->getDataInstance(ilChartGrid::DATA_LINES);
634 $max_line->setLabel($this->lng->txt("session_max_count"));
635 $colors[] = "#cc0000";
636 }
637
638 $chart->setColors($colors);
639
640 $chart_data = $this->adaptDataToScale($a_scale, $a_data);
641
642 $scale = ceil(count($chart_data) / 5);
643 $labels = array();
644 foreach ($chart_data as $idx => $item) {
645 $date = $item["slot_begin"];
646
647 if ($a_scale === self::SCALE_PERIODIC_WEEK || !($idx % ceil($scale))) {
648 switch ($a_scale) {
649 case self::SCALE_DAY:
650 $labels[$date] = date("H:i", $date);
651 break;
652
653 case self::SCALE_WEEK:
654 $labels[$date] = date("d.m. H", $date) . "h";
655 break;
656
658 $labels[$date] = date("d.m.", $date);
659 break;
660
661 case self::SCALE_YEAR:
662 $labels[$date] = date("Y-m", $date);
663 break;
664
666 $day = substr((string) $date, 0, 1);
667 $hour = substr((string) $date, 1, 2);
668 $min = substr((string) $date, 3, 2);
669
670 // build ascending scale from day values
671 $day_value = ($day - 1) * 60 * 60 * 24;
672 $date = $day_value + $hour * 60 * 60 + $min * 60;
673
674 // 6-hour interval labels
675 if ((!isset($old_hour) || $hour != $old_hour) && $hour && $hour % 6 == 0) {
676 $labels[$date] = $hour;
677 $old_hour = $hour;
678 }
679 // day label
680 if (!isset($old_day) || $day != $old_day) {
681 $labels[$date] = ilCalendarUtil::_numericDayToString((int) $day, false);
682 $old_day = $day;
683 }
684 break;
685 }
686 }
687
688 foreach ($measures as $measure) {
689 $value = (int) $item["active_" . $measure];
690 $act_line[$measure]->addPoint($date, $value);
691 }
692
693 if (isset($max_line)) {
694 $max_line->addPoint($date, (int) $item["max_sessions"]);
695 }
696 }
697
698 foreach ($act_line as $line) {
699 $chart->addData($line);
700 }
701 if (isset($max_line)) {
702 $chart->addData($max_line);
703 }
704
705 $chart->setTicks($labels, null, true);
706
707 return $chart->getHTML();
708 }
709
710 protected function adaptDataToScale(int $a_scale, array $a_data): array
711 {
712 // can we use original data?
713 switch ($a_scale) {
714 case self::SCALE_DAY:
715 // 96 values => ok
716 // fallthrough
717
718 case self::SCALE_WEEK:
719 // 672 values => ok
720 return $a_data;
721 }
722
723 $tmp = [];
724 foreach ($a_data as $item) {
725 $date_parts = getdate($item["slot_begin"]);
726
727 // aggregate slots for scale
728 switch ($a_scale) {
729 default:
731 // aggregate to hours => 720 values
732 $slot = mktime($date_parts["hours"], 0, 0, $date_parts["mon"], $date_parts["mday"], $date_parts["year"]);
733 break;
734
735 case self::SCALE_YEAR:
736 // aggregate to days => 365 values
737 $slot = mktime(0, 0, 1, $date_parts["mon"], $date_parts["mday"], $date_parts["year"]);
738 break;
739
741 // aggregate to weekdays => 672 values
742 $day = $date_parts["wday"];
743 if (!$day) {
744 $day = 7;
745 }
746 $slot = $day . date("His", $item["slot_begin"]);
747 break;
748 }
749
750 // process minx/max, prepare avg
751 foreach ($item as $id => $value) {
752 switch (substr((string) $id, -3)) {
753 case "min":
754 if (!isset($tmp[$slot][$id]) || $value < $tmp[$slot][$id]) {
755 $tmp[$slot][$id] = $value;
756 }
757 break;
758
759 case "max":
760 if (!isset($tmp[$slot][$id]) || $value > $tmp[$slot][$id]) {
761 $tmp[$slot][$id] = $value;
762 }
763 break;
764
765 case "avg":
766 $tmp[$slot][$id][] = $value;
767 break;
768 }
769 }
770 }
771
772 foreach ($tmp as $slot => $attr) {
773 $tmp[$slot]["active_avg"] = (int) round(array_sum($attr["active_avg"]) / count($attr["active_avg"]));
774 $tmp[$slot]["slot_begin"] = $slot;
775 }
776 ksort($tmp);
777 return array_values($tmp);
778 }
779
780 protected function adminSync(): void
781 {
782 // see ilSession::_writeData()
783 $now = time();
786
787 $this->tpl->setOnScreenMessage('success', $this->lng->txt("trac_sync_session_stats_success"), true);
788 $this->ilCtrl->redirect($this);
789 }
790
791 protected function exportCSV(array $a_data, $a_scale): void
792 {
794
795 $csv = new ilCSVWriter();
796 $csv->setSeparator(";");
797
798 $now = time();
799
800 // meta
801 $meta = array(
802 $this->lng->txt("trac_name_of_installation") => $this->clientIniFile->readVariable('client', 'name'),
803 $this->lng->txt("trac_report_date") => ilDatePresentation::formatDate(new ilDateTime($now, IL_CAL_UNIX)),
804 $this->lng->txt("trac_report_owner") => $this->user->getFullName(),
805 );
806 foreach ($a_data as $idx => $item) {
807 switch ($idx) {
808 case "title":
809 $meta[$this->lng->txt("title")] = $item;
810 break;
811
812 case "active":
813 // nothing to do
814 break;
815
816 case "closed_details":
817 foreach ($item as $detail) {
818 $meta[$a_data["closed"][0] . " - " . $detail[0]] = $detail[1];
819 }
820 break;
821
822 default:
823 $meta[$item[0]] = $item[1];
824 break;
825 }
826 }
827 foreach ($meta as $caption => $value) {
828 $csv->addColumn(strip_tags((string) $caption));
829 $csv->addColumn(strip_tags((string) $value));
830 $csv->addRow();
831 }
832 $csv->addRow();
833
834 // aggregate data
835 $aggr_data = $this->adaptDataToScale($a_scale, $a_data["active"]);
836
837 // header
838 $first = $aggr_data;
839 $first = array_keys(array_shift($first));
840 foreach ($first as $column) {
841 // split weekday and time slot again
842 if ($a_scale === self::SCALE_PERIODIC_WEEK && $column === "slot_begin") {
843 $csv->addColumn("weekday");
844 $csv->addColumn("time");
845 } else {
846 $csv->addColumn(strip_tags((string) $column));
847 }
848 }
849 $csv->addRow();
850
851 // data
852 foreach ($aggr_data as $row) {
853 foreach ($row as $column => $value) {
854 if (is_array($value)) {
855 $value = implode(', ', $value);
856 }
857 switch ($column) {
858 case "slot_begin":
859 // split weekday and time slot again
860 if ($a_scale === self::SCALE_PERIODIC_WEEK) {
861 $csv->addColumn(ilCalendarUtil::_numericDayToString((int) substr((string) $value, 0, 1)));
862 $value = substr((string) $value, 1, 2) . ":" . substr((string) $value, 3, 2);
863 break;
864 }
865 // fallthrough
866
867 // no break
868 case "slot_end":
869 $value = date("d.m.Y H:i", $value);
870 break;
871 }
872 $csv->addColumn(strip_tags((string) $value));
873 }
874 $csv->addRow();
875 }
876
877 // send
878 $filename = "session_statistics_" . date("Ymd", $now) . ".csv";
879 header("Content-type: text/comma-separated-values");
880 header("Content-Disposition: attachment; filename=\"" . $filename . "\"");
881 header("Expires: 0");
882 header("Cache-Control: must-revalidate, post-check=0,pre-check=0");
883 header("Pragma: public");
884 echo $csv->getCSVString();
885 exit();
886 }
887}
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
$filename
Definition: buildRTE.php:78
const IL_CAL_UNIX
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static parseIncomingDate($a_value, bool $a_add_time=false)
Try to parse incoming value to date object.
static _numericDayToString(int $a_day, bool $a_long=true)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static getInstanceByType(int $a_type, string $a_id)
const TYPE_GRID
Class ilCtrl provides processing control methods.
getNextClass($a_gui_class=null)
@inheritDoc
redirect(object $a_gui_obj, string $a_cmd=null, string $a_anchor=null, bool $is_async=false)
@inheritDoc
getCmd(string $fallback_command=null)
@inheritDoc
getFormAction(object $a_gui_obj, string $a_fallback_cmd=null, string $a_anchor=null, bool $is_async=false, bool $has_xml_style=false)
@inheritDoc
static formatPeriod(ilDateTime $start, ilDateTime $end, bool $a_skip_starting_day=false)
Format a period of two dates Shows: 14.
static setUseRelativeDates(bool $a_status)
set use relative dates
static formatDate(ilDateTime $date, bool $a_skip_day=false, bool $a_include_wd=false, bool $include_seconds=false)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
@classDescription Date and time handling
Class for single dates.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
language handling
Component logger with individual log levels by component id.
User class.
This class represents a selection list property in a property form.
static getExistingSessionCount(array $a_types)
returns number of valid sessions relating to given session types
const DEFAULT_MAX_COUNT
default value for settings that have not been defined in setup or administration yet
static array $session_types_controlled
getChart(array $a_data, string $a_title, int $a_scale=self::SCALE_DAY, string $a_measure=null)
Build chart for active sessions.
adaptDataToScale(int $a_scale, array $a_data)
importDate(string $a_incoming, int $a_default=null)
ilGlobalTemplateInterface $tpl
render(array $a_data, int $a_scale, string $a_measure=null)
buildData(int $a_time_from, int $a_time_to, string $a_title)
exportCSV(array $a_data, $a_scale)
static getLastAggregation()
Get timestamp of last aggregation.
static getNumberOfSessionsByType(int $a_from, int $a_to)
Get session counters by type (opened, closed)
static getLastMaxedOut()
Get latest slot during which sessions were maxed out.
static aggretateRaw(int $a_now)
Aggregate raw session data (older than given time)
static getMaxedOutDuration(int $a_from, int $a_to)
Get maxed out duration in given timeframe.
static _destroyExpiredSessions()
Destroy expired sessions.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
special template class to simplify handling of ITX/PEAR
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
global $DIC
Definition: feed.php:28
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
exit
Definition: login.php:28
$type
$http
Definition: raiseError.php:7