Merge pull request 'DatabaseUserManager' (#25) from DatabaseUserManager into dev

Reviewed-on: #25
Reviewed-by: niklas.ortmann <ortmann.niklas@yahoo.de>
This commit was merged in pull request #25.
This commit is contained in:
2026-06-10 16:15:38 +02:00
14 changed files with 372 additions and 1896 deletions
+240 -5
View File
@@ -1,26 +1,261 @@
<?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)
{
// TODO: Implement findUser() method.
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)
{
// TODO: Implement addUser() method.
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)
{
// TODO: Implement updateUser() method.
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)
{
// TODO: Implement deleteUser() method.
}
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.");
}
}
}
+27 -5
View File
@@ -1,10 +1,32 @@
<?php
require_once "UserManagerDAO.php";
class UserManager extends LocalUserManager{
require_once "LocalUserManager.php";
require_once "DatabaseUserManager.php";
public static function getInstance(){
// TODO: implement this.
// TODO: dummy-user anlegen: - `max.mustermann, test123, mustermann@web.de` (analog zu ArticleManager)
/**
* Zentrale Klasse für den Zugriff auf Benutzerdaten.
*
* Hier kann zwischen lokaler Speicherung und Datenbankspeicherung
* gewechselt werden.
*/
class UserManager {
public static function getInstance() {
$userManager = DatabaseUserManager::getInstance();
/*
* Dummy-User anlegen, falls er noch nicht existiert.
* Passwort: test123
*/
if ($userManager->findUser("mustermann@web.de") == null) {
$userManager->addUser(
"mustermann@web.de",
"Max",
"Mustermann",
password_hash("test12345", PASSWORD_DEFAULT)
);
}
return $userManager;
}
}