261 lines
7.8 KiB
PHP
261 lines
7.8 KiB
PHP
<?php
|
|
|
|
require_once "UserManagerDAO.php";
|
|
|
|
/**
|
|
* Klasse für den Zugriff auf Benutzerdaten über eine SQLite-Datenbank.
|
|
*
|
|
* Diese Klasse verwendet PDO, Prepared Statements und speichert
|
|
* Benutzerdaten in der Datei db/users.db.
|
|
*/
|
|
class DatabaseUserManager implements UserManagerDAO {
|
|
|
|
private static $instance = null;
|
|
|
|
/**
|
|
* Konstruktor.
|
|
*
|
|
* Erstellt die Benutzerdatenbank und die Tabelle users,
|
|
* falls diese noch nicht existieren.
|
|
*
|
|
* @throws RuntimeException wenn die Datenbank nicht erstellt werden kann
|
|
*/
|
|
public function __construct()
|
|
{
|
|
try {
|
|
$db = $this->getConnection();
|
|
|
|
$db->exec("
|
|
CREATE TABLE IF NOT EXISTS users (
|
|
email TEXT PRIMARY KEY,
|
|
vorname TEXT NOT NULL,
|
|
nachname TEXT NOT NULL,
|
|
password TEXT NOT NULL
|
|
);
|
|
");
|
|
|
|
unset($db);
|
|
|
|
} catch (PDOException $e) {
|
|
throw new RuntimeException("Benutzerdatenbank konnte nicht erstellt werden.");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Baut eine Verbindung zur SQLite-Datenbank auf.
|
|
*
|
|
* @return PDO Datenbankverbindung
|
|
*
|
|
* @throws RuntimeException wenn keine Verbindung hergestellt werden kann
|
|
*/
|
|
private function getConnection()
|
|
{
|
|
try {
|
|
$dsn = 'sqlite:' . __DIR__ . '/../../db/users.db';
|
|
|
|
$db = new PDO($dsn, null, null);
|
|
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
|
|
|
return $db;
|
|
|
|
} catch (PDOException $e) {
|
|
throw new RuntimeException("Verbindung zur Benutzerdatenbank fehlgeschlagen.");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Gibt die Singleton-Instanz des DatabaseUserManagers zurück.
|
|
*
|
|
* @return DatabaseUserManager Instanz des DatabaseUserManagers
|
|
*/
|
|
public static function getInstance()
|
|
{
|
|
if (self::$instance == null) {
|
|
self::$instance = new DatabaseUserManager();
|
|
}
|
|
|
|
return self::$instance;
|
|
}
|
|
|
|
/**
|
|
* Sucht einen Benutzer anhand seiner E-Mail-Adresse.
|
|
*
|
|
* @param string $email E-Mail-Adresse des Benutzers
|
|
*
|
|
* @return array|null Benutzerdaten als Array oder null,
|
|
* wenn kein Benutzer gefunden wurde
|
|
*
|
|
* @throws RuntimeException wenn der Benutzer nicht geladen werden kann
|
|
*/
|
|
public function findUser($email)
|
|
{
|
|
try {
|
|
$db = $this->getConnection();
|
|
|
|
$sql = "SELECT * FROM users WHERE email = :email";
|
|
$command = $db->prepare($sql);
|
|
|
|
$command->execute([
|
|
":email" => $email
|
|
]);
|
|
|
|
$user = $command->fetch(PDO::FETCH_ASSOC);
|
|
|
|
return $user ?: null;
|
|
|
|
} catch (PDOException $e) {
|
|
throw new RuntimeException("Benutzer konnte nicht geladen werden.");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Fügt einen neuen Benutzer in die Datenbank ein.
|
|
*
|
|
* Die Speicherung erfolgt innerhalb einer Transaktion.
|
|
* Doppelte E-Mail-Adressen werden durch den Primary Key verhindert.
|
|
*
|
|
* @param string $email E-Mail-Adresse des Benutzers
|
|
* @param string $vorname Vorname des Benutzers
|
|
* @param string $nachname Nachname des Benutzers
|
|
* @param string $password Passwort-Hash des Benutzers
|
|
*
|
|
* @return void
|
|
*
|
|
* @throws InvalidArgumentException wenn die E-Mail-Adresse bereits verwendet wird
|
|
* @throws RuntimeException wenn der Benutzer nicht gespeichert werden kann
|
|
*/
|
|
public function addUser($email, $vorname, $nachname, $password)
|
|
{
|
|
try {
|
|
$db = $this->getConnection();
|
|
$db->beginTransaction();
|
|
|
|
$sql = "
|
|
INSERT INTO users (email, vorname, nachname, password)
|
|
VALUES (:email, :vorname, :nachname, :password)
|
|
";
|
|
|
|
$command = $db->prepare($sql);
|
|
|
|
$command->execute([
|
|
":email" => $email,
|
|
":vorname" => $vorname,
|
|
":nachname" => $nachname,
|
|
":password" => $password
|
|
]);
|
|
|
|
$db->commit();
|
|
|
|
} catch (PDOException $e) {
|
|
if (isset($db) && $db->inTransaction()) {
|
|
$db->rollBack();
|
|
}
|
|
|
|
if ($e->getCode() === "23000") {
|
|
throw new InvalidArgumentException("Diese E-Mail-Adresse wird bereits verwendet.");
|
|
}
|
|
|
|
throw new RuntimeException("Benutzer konnte nicht gespeichert werden.");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Aktualisiert die Daten eines bestehenden Benutzers.
|
|
*
|
|
* Optional kann zusätzlich das Passwort geändert werden.
|
|
* Wenn kein neues Passwort übergeben wird, bleibt das alte Passwort erhalten.
|
|
*
|
|
* @param string $oldEmail Aktuelle E-Mail-Adresse des Benutzers
|
|
* @param string $newEmail Neue E-Mail-Adresse des Benutzers
|
|
* @param string $vorname Neuer Vorname des Benutzers
|
|
* @param string $nachname Neuer Nachname des Benutzers
|
|
* @param string|null $password Neues Passwort oder null
|
|
*
|
|
* @return bool true, wenn der Benutzer aktualisiert wurde,
|
|
* sonst false
|
|
*
|
|
* @throws InvalidArgumentException wenn die neue E-Mail-Adresse bereits verwendet wird
|
|
* @throws RuntimeException wenn der Benutzer nicht aktualisiert werden kann
|
|
*/
|
|
public function updateUser($oldEmail, $newEmail, $vorname, $nachname, $password = null)
|
|
{
|
|
try {
|
|
$db = $this->getConnection();
|
|
|
|
if (!empty($password)) {
|
|
$sql = "
|
|
UPDATE users
|
|
SET email = :newEmail,
|
|
vorname = :vorname,
|
|
nachname = :nachname,
|
|
password = :password
|
|
WHERE email = :oldEmail
|
|
";
|
|
|
|
$params = [
|
|
":newEmail" => $newEmail,
|
|
":vorname" => $vorname,
|
|
":nachname" => $nachname,
|
|
":password" => password_hash($password, PASSWORD_DEFAULT),
|
|
":oldEmail" => $oldEmail
|
|
];
|
|
} else {
|
|
$sql = "
|
|
UPDATE users
|
|
SET email = :newEmail,
|
|
vorname = :vorname,
|
|
nachname = :nachname
|
|
WHERE email = :oldEmail
|
|
";
|
|
|
|
$params = [
|
|
":newEmail" => $newEmail,
|
|
":vorname" => $vorname,
|
|
":nachname" => $nachname,
|
|
":oldEmail" => $oldEmail
|
|
];
|
|
}
|
|
|
|
$command = $db->prepare($sql);
|
|
$command->execute($params);
|
|
|
|
return $command->rowCount() > 0;
|
|
|
|
} catch (PDOException $e) {
|
|
if ($e->getCode() === "23000") {
|
|
throw new InvalidArgumentException("Diese E-Mail-Adresse wird bereits verwendet.");
|
|
}
|
|
|
|
throw new RuntimeException("Benutzer konnte nicht aktualisiert werden.");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Löscht einen Benutzer anhand seiner E-Mail-Adresse.
|
|
*
|
|
* @param string $email E-Mail-Adresse des zu löschenden Benutzers
|
|
*
|
|
* @return bool true, wenn der Benutzer gelöscht wurde,
|
|
* sonst false
|
|
*
|
|
* @throws RuntimeException wenn der Benutzer nicht gelöscht werden kann
|
|
*/
|
|
public function deleteUser($email)
|
|
{
|
|
try {
|
|
$db = $this->getConnection();
|
|
|
|
$sql = "DELETE FROM users WHERE email = :email";
|
|
$command = $db->prepare($sql);
|
|
|
|
$command->execute([
|
|
":email" => $email
|
|
]);
|
|
|
|
return $command->rowCount() > 0;
|
|
|
|
} catch (PDOException $e) {
|
|
throw new RuntimeException("Benutzer konnte nicht gelöscht werden.");
|
|
}
|
|
}
|
|
} |