ILIAS  release_8 Revision v8.19
All Data Structures Namespaces Files Functions Variables Modules Pages
class.ilSessionStatisticsGUI.php
Go to the documentation of this file.
1 <?php
2 
19 declare(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;
48  private ilTabsGUI $ilTabs;
49  private ilLanguage $lng;
53  private ilAccess $access;
55  private ilObjUser $user;
56  private ilLogger $logger;
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 
176  case self::MODE_LAST_DAY:
177  $time_to = time();
178  $time_from = $time_to - 60 * 60 * 24;
179  $scale = self::SCALE_DAY;
180  break;
181 
182  case self::MODE_LAST_WEEK:
183  $time_to = time();
184  $time_from = $time_to - 60 * 60 * 24 * 7;
185  $scale = self::SCALE_WEEK;
186  break;
187 
188  case self::MODE_LAST_MONTH:
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  {
607  $chart = ilChart::getInstanceByType(ilChart::TYPE_GRID, "objstacc");
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 
657  case self::SCALE_MONTH:
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 
665  case self::SCALE_PERIODIC_WEEK:
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:
730  case self::SCALE_MONTH:
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 
740  case self::SCALE_PERIODIC_WEEK:
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 }
const DEFAULT_MAX_COUNT
default value for settings that have not been defined in setup or administration yet ...
exportCSV(array $a_data, $a_scale)
static getNumberOfSessionsByType(int $a_from, int $a_to)
Get session counters by type (opened, closed)
exit
Definition: login.php:28
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
$type
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static formatDate(ilDateTime $date, bool $a_skip_day=false, bool $a_include_wd=false, bool $include_seconds=false)
render(array $a_data, int $a_scale, string $a_measure=null)
const IL_CAL_UNIX
static _destroyExpiredSessions()
Destroy expired sessions.
static aggretateRaw(int $a_now)
Aggregate raw session data (older than given time)
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)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
ilGlobalTemplateInterface $tpl
global $DIC
Definition: feed.php:28
static getLastAggregation()
Get timestamp of last aggregation.
importDate(string $a_incoming, int $a_default=null)
setDate(ilDateTime $a_date=null)
set date E.g $dt_form->setDate(new ilDateTime(time(),IL_CAL_UTC)); or $dt_form->setDate(new ilDateTim...
$http
Definition: raiseError.php:7
static _numericDayToString(int $a_day, bool $a_long=true)
const TYPE_GRID
$filename
Definition: buildRTE.php:78
static getExistingSessionCount(array $a_types)
returns number of valid sessions relating to given session types
static getMaxedOutDuration(int $a_from, int $a_to)
Get maxed out duration in given timeframe.
static array $session_types_controlled
static formatPeriod(ilDateTime $start, ilDateTime $end, bool $a_skip_starting_day=false)
Format a period of two dates Shows: 14.
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
static parseIncomingDate($a_value, bool $a_add_time=false)
Try to parse incoming value to date object.
static setUseRelativeDates(bool $a_status)
set use relative dates
static getLastMaxedOut()
Get latest slot during which sessions were maxed out.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
buildData(int $a_time_from, int $a_time_to, string $a_title)
static getInstanceByType(int $a_type, string $a_id)