ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
class.ilSessionStatisticsGUI.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
22{
23 private const int MODE_TODAY = 1;
24 private const int MODE_LAST_DAY = 2;
25 private const int MODE_LAST_WEEK = 3;
26 private const int MODE_LAST_MONTH = 4;
27 private const int MODE_DAY = 5;
28 private const int MODE_WEEK = 6;
29 private const int MODE_MONTH = 7;
30 private const int MODE_YEAR = 8;
31
32 private const int SCALE_DAY = 1;
33 private const int SCALE_WEEK = 2;
34 private const int SCALE_MONTH = 3;
35 private const int SCALE_YEAR = 4;
36 private const int SCALE_PERIODIC_WEEK = 5;
37
38 private const string REQUEST_SMD = 'smd';
39 private const string REQUEST_SMM = 'smm';
40 private const string REQUEST_SST = 'sst';
41 private const string REQUEST_STO = 'sto';
42 private const string REQUEST_REF = 'ref_id';
43
44 private ilCtrl $ilCtrl;
54
55 private int $ref_id = -1;
56 private ?int $smd = null;
57 private ?string $smm = null;
58 private ?string $sst = null;
59 private ?string $sto = null;
60
61 public function __construct()
62 {
63 global $DIC;
64
65 $this->ilCtrl = $DIC->ctrl();
66 $this->ilTabs = $DIC->tabs();
67 $this->lng = $DIC->language();
68 $this->tpl = $DIC->ui()->mainTemplate();
69 $this->toolbar = $DIC->toolbar();
70 $this->settings = $DIC->settings();
71 $this->access = $DIC->access();
72 $this->clientIniFile = $DIC->clientIni();
73 $this->user = $DIC->user();
74 $this->logger = $DIC->logger()->auth();
75
76 $http = $DIC->http();
77 $kindlyTo = $DIC->refinery()->kindlyTo();
78 if ($http->request()->getMethod() === 'POST') {
79 if ($http->wrapper()->post()->has(self::REQUEST_SMD)) {
80 $this->smd = $http->wrapper()->post()->retrieve(self::REQUEST_SMD, $kindlyTo->int());
81 }
82 if ($http->wrapper()->post()->has(self::REQUEST_SMM)) {
83 $this->smm = $http->wrapper()->post()->retrieve(self::REQUEST_SMM, $kindlyTo->string());
84 }
85 if ($http->wrapper()->post()->has(self::REQUEST_STO)) {
86 $this->sto = $http->wrapper()->post()->retrieve(self::REQUEST_STO, $kindlyTo->string());
87 }
88 if ($http->wrapper()->post()->has(self::REQUEST_SST)) {
89 $this->sst = $http->wrapper()->post()->retrieve(self::REQUEST_SST, $kindlyTo->string());
90 }
91 } else {
92 if ($http->wrapper()->query()->has(self::REQUEST_SMD)) {
93 $this->smd = $http->wrapper()->query()->retrieve(self::REQUEST_SMD, $kindlyTo->int());
94 }
95 if ($http->wrapper()->query()->has(self::REQUEST_SMM)) {
96 $this->smm = $http->wrapper()->query()->retrieve(self::REQUEST_SMM, $kindlyTo->string());
97 }
98 if ($http->wrapper()->query()->has(self::REQUEST_STO)) {
99 $this->sto = $http->wrapper()->query()->retrieve(self::REQUEST_STO, $kindlyTo->string());
100 }
101 if ($http->wrapper()->query()->has(self::REQUEST_SST)) {
102 $this->sst = $http->wrapper()->query()->retrieve(self::REQUEST_SST, $kindlyTo->string());
103 }
104 }
105 if ($http->wrapper()->query()->has(self::REQUEST_REF)) {
106 $this->ref_id = $http->wrapper()->query()->retrieve(self::REQUEST_REF, $kindlyTo->int());
107 }
108 }
109
110 public function executeCommand(): bool
111 {
112 $this->setSubTabs();
113
114 switch ($this->ilCtrl->getNextClass()) {
115 default:
116 $cmd = $this->ilCtrl->getCmd('current');
117 $this->$cmd();
118 }
119
120 return true;
121 }
122
123 protected function setSubTabs(): void
124 {
125 $this->ilTabs->addSubTab(
126 'current',
127 $this->lng->txt('trac_current_system_load'),
128 $this->ilCtrl->getLinkTarget($this, 'current')
129 );
130 $this->ilTabs->addSubTab(
131 'short',
132 $this->lng->txt('trac_short_system_load'),
133 $this->ilCtrl->getLinkTarget($this, 'short')
134 );
135 $this->ilTabs->addSubTab(
136 'long',
137 $this->lng->txt('trac_long_system_load'),
138 $this->ilCtrl->getLinkTarget($this, 'long')
139 );
140 $this->ilTabs->addSubTab(
141 'periodic',
142 $this->lng->txt('trac_periodic_system_load'),
143 $this->ilCtrl->getLinkTarget($this, 'periodic')
144 );
145 }
146
147 protected function current(bool $a_export = false): void
148 {
149 $this->ilTabs->activateSubTab('current');
150
151 // current mode
152 if (!$this->smd) {
153 $mode = self::MODE_TODAY;
154 } else {
155 $mode = $this->smd;
156 }
157
158 // current measure
159 if (!$this->smm) {
160 $measure = 'avg';
161 } else {
162 $measure = $this->smm;
163 }
164
165 switch ($mode) {
166 default:
167 case self::MODE_TODAY:
168 $time_from = strtotime('today');
169 $time_to = strtotime('tomorrow') - 1;
170 $scale = self::SCALE_DAY;
171 break;
172
174 $time_to = time();
175 $time_from = $time_to - 60 * 60 * 24;
176 $scale = self::SCALE_DAY;
177 break;
178
180 $time_to = time();
181 $time_from = $time_to - 60 * 60 * 24 * 7;
182 $scale = self::SCALE_WEEK;
183 break;
184
186 $time_to = time();
187 $time_from = $time_to - 60 * 60 * 24 * 30;
188 $scale = self::SCALE_MONTH;
189 break;
190 }
191
192 $mode_options = [
193 self::MODE_TODAY => $this->lng->txt('trac_session_statistics_mode_today'),
194 self::MODE_LAST_DAY => $this->lng->txt('trac_session_statistics_mode_last_day'),
195 self::MODE_LAST_WEEK => $this->lng->txt('trac_session_statistics_mode_last_week'),
196 self::MODE_LAST_MONTH => $this->lng->txt('trac_session_statistics_mode_last_month')
197 ];
198
199 $title = $this->lng->txt('trac_current_system_load') . ' - ' . $mode_options[$mode];
200 $data = $this->buildData($time_from, $time_to, $title);
201
202 if (!$a_export) {
203 // toolbar
204 $this->toolbar->setFormAction($this->ilCtrl->getFormAction($this, 'current'));
205
206 $mode_selector = new ilSelectInputGUI('&nbsp;' . $this->lng->txt('trac_scale'), 'smd');
207 $mode_selector->setOptions($mode_options);
208 $mode_selector->setValue($mode);
209 $this->toolbar->addInputItem($mode_selector, true);
210
211 $measure_options = [
212 'avg' => $this->lng->txt('trac_session_active_avg'),
213 'min' => $this->lng->txt('trac_session_active_min'),
214 'max' => $this->lng->txt('trac_session_active_max')
215 ];
216
217 $measure_selector = new ilSelectInputGUI('&nbsp;' . $this->lng->txt('trac_measure'), 'smm');
218 $measure_selector->setOptions($measure_options);
219 $measure_selector->setValue($measure);
220 $this->toolbar->addInputItem($measure_selector, true);
221
222 $this->toolbar->addFormButton($this->lng->txt('ok'), 'current');
223
224 if (count($data['active'])) {
225 $this->toolbar->addSeparator();
226 $this->toolbar->addFormButton($this->lng->txt('export'), 'currentExport');
227 }
228
229 $this->tpl->setContent($this->render($data, $scale, $measure));
230
231 $this->tpl->setLeftContent($this->renderCurrentBasics());
232 } else {
233 $this->exportCSV($data, $scale);
234 }
235 }
236
237 protected function currentExport(): void
238 {
239 $this->current(true);
240 }
241
245 protected function importDate(string $a_incoming, ?int $a_default = null)
246 {
247 if (!$a_default) {
248 $a_default = time();
249 }
250
251 $parsed = ilCalendarUtil::parseIncomingDate($a_incoming);
252 return $parsed
253 ? $parsed->get(IL_CAL_UNIX)
254 : $a_default;
255 }
256
257 protected function short(bool $a_export = false): void
258 {
259 $this->ilTabs->activateSubTab('short');
260
261 //TODO validate input
262 // current start
263 $time_to = $this->importDate((string) $this->sst);
264
265 // current mode
266 if (!$this->smd) {
267 $mode = self::MODE_DAY;
268 } else {
269 $mode = $this->smd;
270 }
271
272 // current measure
273 if (!$this->smm) {
274 $measure = 'avg';
275 } else {
276 $measure = $this->smm;
277 }
278
279 switch ($mode) {
280 default:
281 case self::MODE_DAY:
282 $time_from = $time_to - 60 * 60 * 24;
283 $scale = self::SCALE_DAY;
284 break;
285
286 case self::MODE_WEEK:
287 $time_from = $time_to - 60 * 60 * 24 * 7;
288 $scale = self::SCALE_WEEK;
289 break;
290 }
291
292 $mode_options = [
293 self::MODE_DAY => $this->lng->txt('trac_session_statistics_mode_day'),
294 self::MODE_WEEK => $this->lng->txt('trac_session_statistics_mode_week')
295 ];
296
297 $title = $this->lng->txt('trac_short_system_load') . ' - ' . $mode_options[$mode];
298 $data = $this->buildData($time_from, $time_to, $title);
299
300 if (!$a_export) {
301 // toolbar
302 $this->toolbar->setFormAction($this->ilCtrl->getFormAction($this, 'short'));
303
304 $start_selector = new ilDateTimeInputGUI($this->lng->txt('trac_end_at'), 'sst');
305 $start_selector->setDate(new ilDate($time_to, IL_CAL_UNIX));
306 $this->toolbar->addInputItem($start_selector, true);
307
308 $mode_selector = new ilSelectInputGUI('&nbsp;' . $this->lng->txt('trac_scale'), 'smd');
309 $mode_selector->setOptions($mode_options);
310 $mode_selector->setValue($mode);
311 $this->toolbar->addInputItem($mode_selector, true);
312
313 $measure_options = [
314 'avg' => $this->lng->txt('trac_session_active_avg'),
315 'min' => $this->lng->txt('trac_session_active_min'),
316 'max' => $this->lng->txt('trac_session_active_max')
317 ];
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 = [
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
473
474
475 // build left column
476
477 $left = new ilTemplate('tpl.session_statistics_left.html', true, true, 'components/ILIAS/Authentication');
478
479 $left->setVariable('CAPTION_CURRENT', $this->lng->txt('users_online'));
480 $left->setVariable('VALUE_CURRENT', $active);
481
482 $left->setVariable('CAPTION_LAST_AGGR', $this->lng->txt('trac_last_aggregation'));
483 $left->setVariable('VALUE_LAST_AGGR', ilDatePresentation::formatDate($last_aggr));
484
485 // sync button
486 if ($this->access->checkAccess('write', '', $this->ref_id)) {
487 $left->setVariable('URL_SYNC', $this->ilCtrl->getFormAction($this, 'adminSync'));
488 $left->setVariable('CMD_SYNC', 'adminSync');
489 $left->setVariable('TXT_SYNC', $this->lng->txt('trac_sync_session_stats'));
490 }
491
492 return $left->get();
493 }
494
495 protected function buildData(int $a_time_from, int $a_time_to, string $a_title): array
496 {
497 // basic data - time related
498
499 $counters = ilSessionStatistics::getNumberOfSessionsByType($a_time_from, $a_time_to);
500 $opened = (int) $counters['opened'];
501 unset($counters['opened']);
502
503
504 // build center column
505
506 $data = [];
507
509 $data['title'] = $a_title . ' (' .
511 new ilDateTime($a_time_from, IL_CAL_UNIX),
512 new ilDateTime($a_time_to, IL_CAL_UNIX)
513 ) . ')';
514
515 $data['opened'] = [$this->lng->txt('trac_sessions_opened'), $opened];
516 $data['closed'] = [$this->lng->txt('trac_sessions_closed'), array_sum($counters)];
517 foreach ($counters as $type => $counter) {
518 $data['closed_details'][] = [$this->lng->txt('trac_' . $type), (int) $counter];
519 }
520
521 $data['active'] = ilSessionStatistics::getActiveSessions($a_time_from, $a_time_to);
522 $this->logger->debug('Data to plot: ' . var_export($data, true));
523 return $data;
524 }
525
526 protected function render(array $a_data, int $a_scale, ?string $a_measure = null): string
527 {
528 $center = new ilTemplate('tpl.session_statistics_center.html', true, true, 'components/ILIAS/Authentication');
529
530 foreach ($a_data as $idx => $item) {
531 switch ($idx) {
532 case 'active':
533 case 'title':
534 // nothing to do
535 break;
536
537 case 'closed_details':
538 $center->setCurrentBlock('closed_details');
539 foreach ($item as $detail) {
540 $center->setVariable('CAPTION_CLOSED_DETAILS', $detail[0]);
541 $center->setVariable('VALUE_CLOSED_DETAILS', $detail[1]);
542 $center->parseCurrentBlock();
543 }
544 break;
545
546 default:
547 $tpl_var = strtoupper($idx);
548 $center->setVariable('CAPTION_' . $tpl_var, $item[0]);
549 $center->setVariable('VALUE_' . $tpl_var, $item[1]);
550 break;
551 }
552 }
553
554 if ($a_data['active']) {
555 $center->setVariable('CHART', $this->getChart($a_data['active'], $a_data['title'], $a_scale, $a_measure));
556 } else {
557 $this->tpl->setOnScreenMessage('info', $this->lng->txt('trac_session_statistics_no_data'));
558 }
559
560 return $center->get();
561 }
562
566 protected function getChart(
567 array $a_data,
568 string $a_title,
569 int $a_scale = self::SCALE_DAY,
570 ?string $a_measure = null
571 ): string {
572 $chart = ilChart::getInstanceByType(ilChart::TYPE_GRID, 'objstacc');
573 $chart->setSize('700', '500');
574 $chart->setYAxisToInteger(true);
575
576 $legend = new ilChartLegend();
577 $chart->setLegend($legend);
578
579 if (!$a_measure) {
580 $measures = ['min', 'avg', 'max'];
581 } else {
582 $measures = [$a_measure];
583 }
584
585 $colors_map = [
586 'min' => '#00cc00',
587 'avg' => '#0000cc',
588 'max' => '#cc00cc'
589 ];
590
591 $colors = $act_line = [];
592 foreach ($measures as $measure) {
593 $act_line[$measure] = $chart->getDataInstance(ilChartGrid::DATA_LINES);
594 $act_line[$measure]->setLineSteps(true);
595 $act_line[$measure]->setLabel($this->lng->txt('trac_session_active_' . $measure));
596 $colors[] = $colors_map[$measure];
597 }
598
599 $chart->setColors($colors);
600
601 $chart_data = $this->adaptDataToScale($a_scale, $a_data);
602
603 $scale = ceil(count($chart_data) / 5);
604 $labels = [];
605 foreach ($chart_data as $idx => $item) {
606 $date = $item['slot_begin'];
607
608 if ($a_scale === self::SCALE_PERIODIC_WEEK || !($idx % ceil($scale))) {
609 switch ($a_scale) {
610 case self::SCALE_DAY:
611 $labels[$date] = date('H:i', $date);
612 break;
613
614 case self::SCALE_WEEK:
615 $labels[$date] = date('d.m. H', $date) . 'h';
616 break;
617
619 $labels[$date] = date('d.m.', $date);
620 break;
621
622 case self::SCALE_YEAR:
623 $labels[$date] = date('Y-m', $date);
624 break;
625
627 $day = substr((string) $date, 0, 1);
628 $hour = substr((string) $date, 1, 2);
629 $min = substr((string) $date, 3, 2);
630
631 // build ascending scale from day values
632 $day_value = ($day - 1) * 60 * 60 * 24;
633 $date = $day_value + $hour * 60 * 60 + $min * 60;
634
635 // 6-hour interval labels
636 if ((!isset($old_hour) || $hour != $old_hour) && $hour && $hour % 6 == 0) {
637 $labels[$date] = $hour;
638 $old_hour = $hour;
639 }
640 // day label
641 if (!isset($old_day) || $day != $old_day) {
642 $labels[$date] = ilCalendarUtil::_numericDayToString((int) $day, false);
643 $old_day = $day;
644 }
645 break;
646 }
647 }
648
649 foreach ($measures as $measure) {
650 $value = (int) $item['active_' . $measure];
651 $act_line[$measure]->addPoint($date, $value);
652 }
653 }
654
655 foreach ($act_line as $line) {
656 $chart->addData($line);
657 }
658
659 $chart->setTicks($labels, null, true);
660
661 return $chart->getHTML();
662 }
663
664 protected function adaptDataToScale(int $a_scale, array $a_data): array
665 {
666 // can we use original data?
667 switch ($a_scale) {
668 case self::SCALE_DAY:
669 // 96 values => ok
670 // fallthrough
671
672 case self::SCALE_WEEK:
673 // 672 values => ok
674 return $a_data;
675 }
676
677 $tmp = [];
678 foreach ($a_data as $item) {
679 $date_parts = getdate($item['slot_begin']);
680
681 // aggregate slots for scale
682 switch ($a_scale) {
683 default:
684 case self::SCALE_MONTH:
685 // aggregate to hours => 720 values
686 $slot = mktime($date_parts['hours'], 0, 0, $date_parts['mon'], $date_parts['mday'], $date_parts['year']);
687 break;
688
689 case self::SCALE_YEAR:
690 // aggregate to days => 365 values
691 $slot = mktime(0, 0, 1, $date_parts['mon'], $date_parts['mday'], $date_parts['year']);
692 break;
693
694 case self::SCALE_PERIODIC_WEEK:
695 // aggregate to weekdays => 672 values
696 $day = $date_parts['wday'];
697 if (!$day) {
698 $day = 7;
699 }
700 $slot = $day . date('His', $item['slot_begin']);
701 break;
702 }
703
704 // process minx/max, prepare avg
705 foreach ($item as $id => $value) {
706 switch (substr((string) $id, -3)) {
707 case 'min':
708 if (!isset($tmp[$slot][$id]) || $value < $tmp[$slot][$id]) {
709 $tmp[$slot][$id] = $value;
710 }
711 break;
712
713 case 'max':
714 if (!isset($tmp[$slot][$id]) || $value > $tmp[$slot][$id]) {
715 $tmp[$slot][$id] = $value;
716 }
717 break;
718
719 case 'avg':
720 $tmp[$slot][$id][] = $value;
721 break;
722 }
723 }
724 }
725
726 foreach ($tmp as $slot => $attr) {
727 $tmp[$slot]['active_avg'] = (int) round(array_sum($attr['active_avg']) / count($attr['active_avg']));
728 $tmp[$slot]['slot_begin'] = $slot;
729 }
730 ksort($tmp);
731 return array_values($tmp);
732 }
733
734 protected function adminSync(): void
735 {
736 // see ilSession::_writeData()
737 $now = time();
740
741 $this->tpl->setOnScreenMessage('success', $this->lng->txt('trac_sync_session_stats_success'), true);
742 $this->ilCtrl->redirect($this);
743 }
744
745 protected function exportCSV(array $a_data, $a_scale): never
746 {
748
749 $csv = new ilCSVWriter();
750 $csv->setSeparator(';');
751
752 $now = time();
753
754 // meta
755 $meta = [
756 $this->lng->txt('trac_name_of_installation') => $this->clientIniFile->readVariable('client', 'name'),
757 $this->lng->txt('trac_report_date') => ilDatePresentation::formatDate(new ilDateTime($now, IL_CAL_UNIX)),
758 $this->lng->txt('trac_report_owner') => $this->user->getFullName(),
759 ];
760 foreach ($a_data as $idx => $item) {
761 switch ($idx) {
762 case 'title':
763 $meta[$this->lng->txt('title')] = $item;
764 break;
765
766 case 'active':
767 // nothing to do
768 break;
769
770 case 'closed_details':
771 foreach ($item as $detail) {
772 $meta[$a_data['closed'][0] . ' - ' . $detail[0]] = $detail[1];
773 }
774 break;
775
776 default:
777 $meta[$item[0]] = $item[1];
778 break;
779 }
780 }
781 foreach ($meta as $caption => $value) {
782 $csv->addColumn(strip_tags((string) $caption));
783 $csv->addColumn(strip_tags((string) $value));
784 $csv->addRow();
785 }
786 $csv->addRow();
787
788 // aggregate data
789 $aggr_data = $this->adaptDataToScale($a_scale, $a_data['active']);
790
791 // header
792 $first = $aggr_data;
793 $first = array_keys(array_shift($first));
794 foreach ($first as $column) {
795 // split weekday and time slot again
796 if ($a_scale === self::SCALE_PERIODIC_WEEK && $column === 'slot_begin') {
797 $csv->addColumn('weekday');
798 $csv->addColumn('time');
799 } else {
800 $csv->addColumn(strip_tags((string) $column));
801 }
802 }
803 $csv->addRow();
804
805 // data
806 foreach ($aggr_data as $row) {
807 foreach ($row as $column => $value) {
808 if (is_array($value)) {
809 $value = implode(', ', $value);
810 }
811 switch ($column) {
812 case 'slot_begin':
813 // split weekday and time slot again
814 if ($a_scale === self::SCALE_PERIODIC_WEEK) {
815 $csv->addColumn(ilCalendarUtil::_numericDayToString((int) substr((string) $value, 0, 1)));
816 $value = substr((string) $value, 1, 2) . ':' . substr((string) $value, 3, 2);
817 break;
818 }
819 // fallthrough
820
821 // no break
822 case 'slot_end':
823 $value = date('d.m.Y H:i', $value);
824 break;
825 }
826 $csv->addColumn(strip_tags((string) $value));
827 }
828 $csv->addRow();
829 }
830
831 // send
832 $filename = 'session_statistics_' . date('Ymd', $now) . '.csv';
833 header('Content-type: text/comma-separated-values');
834 header('Content-Disposition: attachment; filename="' . $filename . '"');
835 header('Expires: 0');
836 header('Cache-Control: must-revalidate, post-check=0,pre-check=0');
837 header('Pragma: public');
838 echo $csv->getCSVString();
839 exit();
840 }
841}
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
$filename
Definition: buildRTE.php:78
const IL_CAL_UNIX
Class ilAccessHandler Checks access for ILIAS objects.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static _numericDayToString(int $a_day, bool $a_long=true, ?ilLanguage $lng=null)
static parseIncomingDate($value, bool $add_time=false)
Try to parse incoming value to date object.
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...
setSize(string $a_x, string $a_y)
Set chart size.
Class ilCtrl provides processing control methods.
getFormAction(object $a_gui_obj, ?string $a_fallback_cmd=null, ?string $a_anchor=null, bool $is_async=false, bool $has_xml_style=false)
@inheritDoc
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
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, ?ilObjUser $user=null,)
static formatPeriod(ilDateTime $start, ilDateTime $end, bool $a_skip_starting_day=false, ?ilObjUser $user=null)
Format a period of two dates Shows: 14.
This class represents a date/time property in a property form.
@classDescription Date and time handling
Class for single dates.
INIFile Parser Early access in init proceess! Avoid further dependencies like logging or other servic...
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)
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)
render(array $a_data, int $a_scale, ?string $a_measure=null)
ilGlobalTemplateInterface $tpl
buildData(int $a_time_from, int $a_time_to, string $a_title)
exportCSV(array $a_data, $a_scale)
importDate(string $a_incoming, ?int $a_default=null)
static getLastAggregation()
Get timestamp of last aggregation.
static getNumberOfSessionsByType(int $a_from, int $a_to)
Get session counters by type (opened, closed)
static aggretateRaw(int $a_now)
Aggregate raw session data (older than given time)
static _destroyExpiredSessions()
Destroy expired sessions.
ILIAS Setting Class.
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...
$http
Definition: deliver.php:30
exit
global $DIC
Definition: shib_login.php:26
$counter