aboutsummaryrefslogtreecommitdiff
path: root/lade_daten.php
blob: eeff6c78227f582233fcb4731252c295992db4aa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
<?php
/* Copyright 2025-2026 Florian Fischer
 * punktestand is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later version.
 *
 * punktestand is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * punktestand. If not, see <https://www.gnu.org/licenses/>.
 */

// PHP Klasse, die alle Daten einer Schulklasse enthält.
class Klasse {
  public string $bezeichner;
  public int $punkte;
  public string $farbe;

  public function __construct(string $bezeichner, ?string $farbe) {
    $this->bezeichner = $bezeichner;
    $this->punkte = 0;
    if (is_null($farbe)) {
      // Die Standardfarbe ist ein leichtes Blau
      $this->farbe = 'rgb(54, 162, 235)';
    } else {
      $this->farbe = $farbe;
    }
  }
}

// Die Funktion lade_daten liefert die Klassen und ihren Punktestand, sowie alle
// aufgetretenen Ereignisse in einem array zurück.
function lade_daten($config, $schuljahr, $jahrgang): array {
  // Zusätzliche Parameter neben der Datenbankbeschreibung für den PDO Konstruktor.
  $pdo_parameter = array();

  // Behandle unterschiedliche Arten von Datenbanken
  if ($config['dbtype'] == 'sqlite') {
    $db_beschreibung = sprintf("sqlite:%s", $config['dbname']);
  } else {
    $db_beschreibung = sprintf('%s:host=%s;dbname=%s', $config['dbtype'], $config['dbhost'], $config['dbname']);
    // MySql bspw. benötigt einen Nutzernamen und ein Passwort für die Verbindung
    array_push($pdo_parameter, $config['dbuser']);
    array_push($pdo_parameter, $config['dbpassword']);
  }

  // Versuche die Verbindung zur Datenbank aufzubauen. Benötigte Parameter
  // müssen in der richtigen Reihenfolge in dem $pdo_parameter array enthalten sein.
  try {
    $verbindung = new PDO($db_beschreibung, ...$pdo_parameter);
  } catch(PDOException $e) {
    // Die Verbindung ist fehlgeschlagen
    error_log($e->getMessage());
    return "null; alert('Es konnte keine Verbindung zur Datenbank hergestellt werden, bitte gib deiner Lehrkraft Bescheid. Fehler: " . $e->getMessage() . "')";
  }

  // Die Verbindung war erfolgreich

  // Bereite unsere Klassenabfrage vor.
  // Dies verhindert SQL-Injection Angriffe, da die Parameter Schuljahr und
  // Jahrgang über die URL kontrollierbar sind.
  $klassen_abfrage = $verbindung->prepare('SELECT * FROM Klasse WHERE Schuljahr = ? AND Jahrgang = ?');
  $klassen_abfrage->bindValue(1, $schuljahr, PDO::PARAM_STR);
  $klassen_abfrage->bindValue(2, $jahrgang, PDO::PARAM_INT);
  $klassen_abfrage->execute();

  // Die Klassen im passenden Jahrgang und Schuljahr
  $klassen = array();
  foreach ($klassen_abfrage->fetchAll() as $zeile) {
    $bezeichner = sprintf('%d%s', $zeile['Jahrgang'], $zeile['Bezeichner']);
    $klasse = new Klasse($bezeichner, $zeile['Farbe']);
    // Indiziere die Klassen mit dem jeweiligen Bezeichner
    $klassen[$bezeichner] = $klasse;
  }

  // Bereite die Ereignisabfrage vor. Sicherheitshinweis siehe: Klassenabfrage.
  // Nur Ereignisse mit einem Delta != 0, also solche die wirklich den Punktestand
  // verändern, werden ausgewählt.
  $ereignis_abfrage = $verbindung->prepare('SELECT * FROM Ereignis WHERE Schuljahr = ? AND Jahrgang = ? AND Delta != 0');
  $ereignis_abfrage->bindValue(1, $schuljahr, PDO::PARAM_STR);
  $ereignis_abfrage->bindValue(2, $jahrgang, PDO::PARAM_INT);
  $ereignis_abfrage->execute();

  // Alle Ereignisse der ausgewählten Klassen
  $ereignisse = $ereignis_abfrage->fetchAll();

  // Deklaration der streak_ereignisse Variable, die nur unter bestimmten
  // Umständen mit einem Wert gefüllt wird. Die Forward-Deklaration ermöglicht es
  // die Variable danach zu benutzen unabhängig, davon ob sie mit einem sinnvollen
  // Wert gefüllt wurde.
  $streak_ereignisse = null;
  $streak_ereignis_beschreibung = $config['streak_ereignis'];
  if ($streak_ereignis_beschreibung != '') {
    // Bereite die Streak-Ereignisabfrage vor. Sicherheitshinweis siehe: Klassenabfrage.
    // Nur Ereignisse mit dem konfigurierten Namen werden ausgewählt.
    // Zusätzlich werden nur Ereignisse mit einem Datum betrachtet, da zur Streak
    // Berechnung die Ereignisse in eine zeitliche Reihenfolge gebracht werden
    // müssen.
    $streak_ereignis_abfrage = $verbindung->prepare('SELECT * FROM Ereignis WHERE Schuljahr = ? AND Jahrgang = ? AND Beschreibung = ? ORDER BY Datum ASC');
    $streak_ereignis_abfrage->bindValue(1, $schuljahr, PDO::PARAM_STR);
    $streak_ereignis_abfrage->bindValue(2, $jahrgang, PDO::PARAM_INT);
    $streak_ereignis_abfrage->bindValue(3, $streak_ereignis_beschreibung, PDO::PARAM_STR);
    $streak_ereignis_abfrage->execute();

    // Alle Streak-Ereignisse der ausgewählten Klassen
    $streak_ereignisse = $streak_ereignis_abfrage->fetchAll();
  }


  // Schließe die Datenbank Verbindung
  $verbindung = null;

  foreach ($ereignisse as $ereignis) {
    $bezeichner = sprintf('%d%s', $ereignis['Jahrgang'], $ereignis['Bezeichner']);
    // Aktualisiere den Punktestand nach dem Ereignis.
    $klassen[$bezeichner]->punkte += $ereignis['Delta'];
  }

  $daten = array();
  $daten['klassen'] = array_values($klassen);
  $daten['ereignisse'] = $ereignisse;
  if ($streak_ereignisse != null) {
    $daten['streakEreignisse'] = $streak_ereignisse;
  }
  return $daten;
}

// Die Funktion schreibe_json schreibt, die Daten die von der Funktion lade_daten
// zurückgegeben wurden in <script>-Tags als JSON in die Webseite.
function schreibe_json($CONFIG, $SCHULJAHR, $JAHRGANG): array {
  // Lade die Daten aus der Datenbank
  $daten = lade_daten($CONFIG, $SCHULJAHR, $JAHRGANG);

  // Bereite die Klassen und Ereignisse für Javascript vor
  $daten_json = json_encode($daten);

  // Ersetze die $JAHRGANG und $SCHULJAHR Platzhalter durch die Werte der Variablen
  $bilder_pfad = str_replace(
    array('$JAHRGANG', '$SCHULJAHR'),
    array($JAHRGANG, $SCHULJAHR),
    $CONFIG['bilder_pfad_format']);

  $bilder_pfad_json = json_encode($bilder_pfad);
  $streak_anzahl = json_encode($CONFIG['streak_anzahl'] ?? '');
  $streak_ziel = json_encode($CONFIG['streak_ziel'] ?? '');

  // Schreibe den Javascript Code mit unseren Daten in die Webseite
  echo "<script>";
  echo "const daten = $daten_json;\n";
  echo "const bilder_pfad = $bilder_pfad_json;\n";
  echo "const streak_anzahl = $streak_anzahl;\n";
  echo "const streak_ziel = $streak_ziel;\n";
  echo "</script>";

  return $daten;
}
?>