philippurbschat.de/home/app/models/User.php

197 lines
No EOL
7.9 KiB
PHP

<?php
class User {
private $db;
public function __construct() {
$this->db = new Database();
}
public static function parseProjects($projects): array {
if (empty($projects)) {
return [];
}
if (is_string($projects)) {
$trimmed = trim($projects);
while (is_string($trimmed) && (str_starts_with($trimmed, '[') || str_starts_with($trimmed, '{') || str_starts_with($trimmed, '"'))) {
$decoded = json_decode($trimmed, true);
if (json_last_error() === JSON_ERROR_NONE && $decoded !== null) {
$trimmed = $decoded;
} else {
break;
}
}
if (is_array($trimmed)) {
$projects = $trimmed;
} else {
$projects = explode(',', (string)$trimmed);
}
}
if (!is_array($projects)) {
return [];
}
$allModules = ModuleService::getAll();
$slugMap = [];
foreach ($allModules as $s => $m) {
$slugMap[strtolower($s)] = $s;
$slugMap[strtolower($m['name'])] = $s;
$slugMap[strtolower(str_replace([' ', '-', '_'], '', $m['name']))] = $s;
$slugMap[strtolower(ltrim($m['path'], '/'))] = $s;
}
$slugMap['web audio synth'] = 'test';
$slugMap['webaudiosynth'] = 'test';
$slugMap['synth'] = 'test';
$slugMap['geschichtenmaschine'] = 'storymachine';
$slugMap['geschichten-maschine'] = 'storymachine';
$slugMap['pflanzen'] = 'plants';
$slugMap['pflanzentracker'] = 'plants';
$ignore = ['on', 'off', 'true', 'false', '1', '0', 'null', 'undefined'];
$clean = [];
foreach ($projects as $key => $val) {
$candidates = [];
if (is_string($key) && !is_numeric($key)) {
$candidates[] = $key;
if (is_string($val) && !in_array(strtolower(trim($val)), $ignore, true)) {
$candidates[] = $val;
}
} else {
if (is_string($val) && !in_array(strtolower(trim($val)), $ignore, true)) {
$candidates[] = $val;
} elseif (is_array($val)) {
if (!empty($val['slug'])) $candidates[] = $val['slug'];
elseif (!empty($val['name'])) $candidates[] = $val['name'];
elseif (!empty($val['id'])) $candidates[] = $val['id'];
elseif (!empty($val['project'])) $candidates[] = $val['project'];
else {
foreach ($val as $sub) {
if (is_string($sub) && !in_array(strtolower(trim($sub)), $ignore, true)) {
$candidates[] = $sub;
}
}
}
}
}
foreach ($candidates as $cand) {
$candSan = trim($cand, " \t\n\r\0\x0B[]\"'/");
if (empty($candSan)) continue;
// Check if candidate contains colon or equals, e.g. "plants:plants" or "storymachine:geschichtenmaschine"
$subParts = preg_split('/[:=]/', $candSan);
$matched = false;
foreach ($subParts as $part) {
$pSan = trim($part, " \t\n\r\0\x0B[]\"'/");
if (empty($pSan)) continue;
$pLower = strtolower($pSan);
$pNorm = str_replace([' ', '-', '_'], '', $pLower);
if (isset($slugMap[$pLower])) {
$clean[] = $slugMap[$pLower];
$matched = true;
break;
} elseif (isset($slugMap[$pNorm])) {
$clean[] = $slugMap[$pNorm];
$matched = true;
break;
}
}
if (!$matched) {
$lower = strtolower($candSan);
$normalized = str_replace([' ', '-', '_'], '', $lower);
if (isset($slugMap[$lower])) {
$clean[] = $slugMap[$lower];
} elseif (isset($slugMap[$normalized])) {
$clean[] = $slugMap[$normalized];
} elseif (isset($allModules[$lower])) {
$clean[] = $lower;
}
}
}
}
return array_values(array_unique($clean));
}
// Auth-Logic
public function authenticate($email, $password) {
$this->db->query("SELECT * FROM home_users WHERE email = :email AND status = 'Active'");
$this->db->bind(':email', $email);
$user = $this->db->single();
if ($user && password_verify($password, $user['password'])) {
$user['projects'] = self::parseProjects($user['projects'] ?? []);
if (in_array(strtolower($user['email']), ['philipp.urbschat@gmail.com', 'hi@philippurbschat.de'])) {
$user['is_admin'] = true;
} else {
$user['is_admin'] = (bool)$user['is_admin'];
}
return $user;
}
return false;
}
// Data-Retrieval
public function getAll() {
$this->db->query("SELECT id, name, email, is_admin, status, projects FROM home_users ORDER BY id DESC");
$users = $this->db->resultSet();
foreach ($users as &$user) {
$user['projects'] = self::parseProjects($user['projects'] ?? []);
}
return $users;
}
public function getById($id) {
$this->db->query("SELECT * FROM home_users WHERE id = :id");
$this->db->bind(':id', $id);
$user = $this->db->single();
if ($user) {
$user['projects'] = self::parseProjects($user['projects'] ?? []);
}
return $user;
}
// Persistence
public function save($data, $id = null) {
$projectsList = self::parseProjects($data['projects'] ?? []);
$projectsJson = json_encode($projectsList);
if ($id) {
$sql = "UPDATE home_users SET name = :name, email = :email, projects = :projects, is_admin = :is_admin, status = :status ";
if (!empty($data['password'])) {
$sql .= ", password = :password ";
}
$sql .= "WHERE id = :id";
$this->db->query($sql);
$this->db->bind(':id', $id);
} else {
$sql = "INSERT INTO home_users (name, email, password, projects, is_admin, status) VALUES (:name, :email, :password, :projects, :is_admin, :status)";
$this->db->query($sql);
}
$this->db->bind(':name', $data['name']);
$this->db->bind(':email', $data['email']);
$this->db->bind(':projects', $projectsJson);
$this->db->bind(':is_admin', !empty($data['is_admin']) ? 1 : 0);
$this->db->bind(':status', $data['status']);
if (!$id || !empty($data['password'])) {
$this->db->bind(':password', password_hash($data['password'], PASSWORD_DEFAULT));
}
return $this->db->execute();
}
public function delete($id) {
$this->db->query("DELETE FROM home_users WHERE id = :id");
$this->db->bind(':id', $id);
return $this->db->execute();
}
public function findByEmail(string $email): ?array {
$this->db->query("SELECT * FROM home_users WHERE LOWER(email) = LOWER(:email)");
$this->db->bind(':email', trim($email));
$user = $this->db->single();
if ($user) {
$user['projects'] = self::parseProjects($user['projects'] ?? []);
}
return $user ?: null;
}
public function updatePassword(int $id, string $newPasswordHash): bool {
$this->db->query("UPDATE home_users SET password = :password WHERE id = :id");
$this->db->bind(':password', $newPasswordHash);
$this->db->bind(':id', $id);
return $this->db->execute();
}
}