diff --git a/WEBROOT/src/MVC/Core/Model.php b/WEBROOT/src/MVC/Core/Model.php index cccb241..e72afd9 100644 --- a/WEBROOT/src/MVC/Core/Model.php +++ b/WEBROOT/src/MVC/Core/Model.php @@ -4,6 +4,14 @@ namespace MVC\Core; abstract class Model { protected static $table; + protected static $conn; + + protected static function getConnection() { + if (!self::$conn) { + self::$conn = \db_connect(); + } + return self::$conn; + } public static function all() { return \DatabaseShow(static::$table, "*"); @@ -40,12 +48,11 @@ abstract class Model { } public static function query($sql, ...$params) { - $conn = \db_connect(); + $conn = self::getConnection(); if (empty($params)) { return $conn->query($sql); } $stmt = $conn->prepare($sql); - // This is a simplified version, real projects use more robust parameter binding $types = str_repeat('s', count($params)); $stmt->bind_param($types, ...$params); $stmt->execute(); diff --git a/create_model.php b/create_model.php index 0fcfcb4..01764a8 100644 --- a/create_model.php +++ b/create_model.php @@ -76,4 +76,4 @@ if (!file_exists($modelFile)) { echo "Spalten: " . implode(', ', $columns) . "\n"; } else { echo "⚠️ Model {$className}.php existiert bereits.\n"; -} +} \ No newline at end of file diff --git a/create_module.php b/create_module.php index fc5b357..98a20d7 100644 --- a/create_module.php +++ b/create_module.php @@ -65,27 +65,27 @@ $viewContent = << HTML; if (!file_exists($viewFile)) { - file_put_contents($viewFile, $viewContent); - echo "✅ View erstellt: WEBROOT/src/MVC/View/{$key}.php\n"; +file_put_contents($viewFile, $viewContent); +echo "✅ View erstellt: WEBROOT/src/MVC/View/{$key}.php\n"; } else { - echo "⚠️ View existiert bereits.\n"; +echo "⚠️ View existiert bereits.\n"; } // 3. Anleitung ausgeben echo "\n--- NÄCHSTE SCHRITTE ---\n"; echo "1. Registriere das Modul in WEBROOT/index.php beim Router:\n"; -echo " \$router->add('{$key}', \\MVC\\Controller\\{$className}Controller::class, '{$key}', ['auth']);\n\n"; +echo " \$router->add('{$key}', \\MVC\\Controller\\{$className}Controller::class, '{$key}', ['auth']);\n\n"; echo "2. Füge den Service in der Seitenverwaltung (Admin) oder in config.php hinzu:\n"; -echo " ID: {$key}\n"; -echo " Name: " . ucfirst($name) . "\n"; -echo "------------------------\n"; +echo " ID: {$key}\n"; +echo " Name: " . ucfirst($name) . "\n"; +echo "------------------------\n"; \ No newline at end of file diff --git a/init_mvc.php b/init_mvc.php index 3db8220..562a607 100644 --- a/init_mvc.php +++ b/init_mvc.php @@ -26,10 +26,12 @@ $dirs = [ 'WEBROOT', 'WEBROOT/api', 'WEBROOT/api/v1', + 'WEBROOT/commands', 'WEBROOT/static', 'WEBROOT/src', 'WEBROOT/src/config', 'WEBROOT/src/database', + 'WEBROOT/src/utils', 'WEBROOT/src/MVC', 'WEBROOT/src/MVC/Core', 'WEBROOT/src/MVC/Controller', @@ -60,6 +62,309 @@ echo "Drücke STRG+C zum Beenden.\n\n"; passthru("php -S $host:$port -t \"$root\""); PHP; +$files['.htaccess'] = <<<'HTACCESS' +RewriteEngine On + +RewriteRule ^(Commands|config_backups|controller|modules)($|/.*) - [F,L,NC] +RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] +SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1 + +# ----------------------------------- +# .php entfernen +# ----------------------------------- + +# browser requestet datei.php -> redirect zu /datei +RewriteCond %{THE_REQUEST} \s/+(.+?)\.php[\s?] [NC] +RewriteRule ^ /%1 [R=301,L] + +# /datei -> datei.php +RewriteCond %{REQUEST_FILENAME} !-f +RewriteCond %{REQUEST_FILENAME} !-d +RewriteCond %{DOCUMENT_ROOT}/$1.php -f +RewriteRule ^(.+)$ $1.php [L] +HTACCESS; + +$files[$projectName . '.code-workspace'] = <<prepare($sql); + + if (!$stmt) { + die("Fehler beim Prepare: " . $conn->error); + } + + if (!$stmt->execute()) { + die("Fehler beim Execute: " . $stmt->error); + } + + return true; +} + +function DatabaseShowTables() { + include_once(__DIR__ . '/../database/databaseConnect.php'); + $conn = db_connect(); + + $tablesResult = $conn->query("SHOW TABLES"); + if (!$tablesResult) { + die("Fehler beim Laden der Tabellen: " . $conn->error); + } + + $tables = []; + + while ($tableRow = $tablesResult->fetch_array()) { + $tables[] = $tableRow[0]; + } + + return $tables; +} + +function DatabaseShowTableStructure($table) { + include_once(__DIR__ . '/../database/databaseConnect.php'); + $conn = db_connect(); + + $stmt = $conn->prepare("SHOW COLUMNS FROM `$table`"); + if (!$stmt) { + die("Fehler beim Prepare: " . $conn->error); + } + + if (!$stmt->execute()) { + die("Fehler beim Execute: " . $stmt->error); + } + + $result = $stmt->get_result(); + + $columns = []; + + while ($column = $result->fetch_assoc()) { + $columns[] = [ + "Field" => $column["Field"], + "Type" => $column["Type"], + "Null" => $column["Null"], + "Key" => $column["Key"], + "Default" => $column["Default"], + "Extra" => $column["Extra"] + ]; + } + + return $columns; +} + +function DatabaseShow($table, $columns = "*", $where = "", ...$values) { + include_once(__DIR__ . '/../database/databaseConnect.php'); + $conn = db_connect(); + + $sql = "SELECT $columns FROM `$table`"; + + if (!empty($where)) { + $sql .= " WHERE $where"; + } + + $stmt = $conn->prepare($sql); + + if (!$stmt) { + die("Fehler beim Prepare: " . $conn->error); + } + + if (!$stmt->execute($values)) { + die("Fehler beim Execute: " . $stmt->error); + } + + $result = $stmt->get_result(); + return $result->fetch_all(MYSQLI_ASSOC); +} + + +function DatabaseInsert($table, $columns, ...$values) { + include_once(__DIR__ . '/../database/databaseConnect.php'); + $conn = db_connect(); + + $placeholders = rtrim(str_repeat("?,", count($values)), ","); + $sql = "INSERT INTO `$table` ($columns) VALUES ($placeholders)"; + $stmt = $conn->prepare($sql); + + if (!$stmt) { + die("Fehler beim Prepare: " . $conn->error); + } + + if (!$stmt->execute($values)) { + die("Fehler beim Execute: " . $stmt->error); + } + + return true; +} + +function DatabaseDelete($table, $where, ...$values) { + include_once(__DIR__ . '/../database/databaseConnect.php'); + $conn = db_connect(); + + $sql = "DELETE FROM `$table` WHERE $where"; + $stmt = $conn->prepare($sql); + + if (!$stmt) { + die("Fehler beim Prepare: " . $conn->error); + } + + if (!$stmt->execute($values)) { + die("Fehler beim Execute: " . $stmt->error); + } + + return true; +} + +function DatabaseUpdate($table, $set, $where, ...$values) { + include_once(__DIR__ . '/../database/databaseConnect.php'); + $conn = db_connect(); + + $sql = "UPDATE `$table` SET $set WHERE $where"; + $stmt = $conn->prepare($sql); + + if (!$stmt) { + die("Fehler beim Prepare: " . $conn->error); + } + + if (!$stmt->execute($values)) { + die("Fehler beim Execute: " . $stmt->error); + } + + return true; +} + +function getFKValue($conn, $table, $key, $value, $id, &$cache) { + if ($id === null) return null; + + $cacheKey = $table . "_" . $id; + + if (isset($cache[$cacheKey])) { + return $cache[$cacheKey]; + } + + $stmt = $conn->prepare("SELECT `$value` FROM `$table` WHERE `$key` = ? LIMIT 1"); + if (!$stmt) { + die("FK Prepare Fehler: " . $conn->error); + } + + $stmt->bind_param("i", $id); + $stmt->execute(); + + $result = $stmt->get_result()->fetch_assoc(); + $valueResult = $result[$value] ?? null; + + $cache[$cacheKey] = $valueResult; + + return $valueResult; +} + +function DatabaseShowWithFK($table, $fkMap = [], $columns = "*", $where = "", ...$values) { + include_once(__DIR__ . '/../database/databaseConnect.php'); + $conn = db_connect(); + + $cache = []; + + $select = is_array($columns) ? implode(", ", $columns) : $columns; + + $sql = "SELECT $select FROM `$table`"; + if (!empty($where)) { + $sql .= " WHERE $where"; + } + + $stmt = $conn->prepare($sql); + if (!$stmt) die("Fehler beim Prepare: " . $conn->error); + + if (!empty($values)) { + $stmt->execute($values); + } else { + $stmt->execute(); + } + + $result = $stmt->get_result(); + if (!$result) die("Fehler beim get_result: " . $conn->error); + + $rows = $result->fetch_all(MYSQLI_ASSOC); + + foreach ($rows as &$row) { + foreach ($fkMap as $fkColumn => $fkInfo) { + + if (!isset($row[$fkColumn]) || $row[$fkColumn] === null) { + continue; + } + + $row[$fkColumn] = getFKValue( + $conn, + $fkInfo['table'], + $fkInfo['key'], + $fkInfo['value'], + $row[$fkColumn], + $cache + ); + } + } + + return [ + "rows" => $rows + ]; +} +PHP; + // --- CONFIG: env.ini --- $files['WEBROOT/src/config/env.ini'] = <<view = new View(__DIR__ . '/../View'); } + + public function __construct() { + $this->view = new View(__DIR__ . '/../View'); + } + protected function render($template, $data = []) { - foreach ($data as $key => $value) { $this->view->assign($key, $value); } + foreach ($data as $key => $value) { + $this->view->assign($key, $value); + } return $this->view->render($template); } + protected function json($data, $status = 200) { header('Content-Type: application/json'); http_response_code($status); @@ -102,20 +416,68 @@ class Controller { exit; } } + PHP; $files['WEBROOT/src/MVC/Core/Model.php'] = <<<'PHP' $value) { + $sets[] = "$column = ?"; + $values[] = $value; + } + $setString = implode(", ", $sets); + return \DatabaseUpdate(static::$table, $setString, $where, ...array_merge($values, $whereParams)); + } + + public static function delete($where, ...$params) { + return \DatabaseDelete(static::$table, $where, ...$params); + } + public static function query($sql, ...$params) { - require_once __DIR__ . '/../../database/databaseConnect.php'; - $conn = db_connect(); - if (!$conn) return null; - if (empty($params)) return $conn->query($sql); + $conn = self::getConnection(); + if (empty($params)) { + return $conn->query($sql); + } $stmt = $conn->prepare($sql); - $types = str_repeat('s', count($params)); + $types = str_repeat('s', count($params)); $stmt->bind_param($types, ...$params); $stmt->execute(); return $stmt->get_result(); @@ -125,37 +487,96 @@ PHP; $files['WEBROOT/src/MVC/Core/View.php'] = <<<'PHP' viewPath = $viewPath; } - public function assign($key, $value) { $this->data[$key] = $value; } + + public function __construct($viewPath) { + $this->viewPath = $viewPath; + } + + public function assign($key, $value) { + $this->data[$key] = $value; + } + public function render($template) { extract($this->data); $file = $this->viewPath . '/' . $template . '.php'; - if (file_exists($file)) { ob_start(); include $file; return ob_get_clean(); } - return "View $template nicht gefunden."; + if (file_exists($file)) { + ob_start(); + include $file; + return ob_get_clean(); + } + return "View $template not found at $file"; } } + PHP; $files['WEBROOT/src/MVC/Core/Router.php'] = <<<'PHP' routes[$service] = ['controller' => $controller, 'method' => $method, 'middlewares' => $middlewares]; + $this->routes[$service] = [ + 'controller' => $controller, + 'method' => $method, + 'middlewares' => $middlewares + ]; } + public function dispatch($service) { - if (!isset($this->routes[$service])) throw new \Exception("Service '$service' nicht gefunden."); + if (!isset($this->routes[$service])) { + throw new \Exception("Service '$service' not found."); + } + $route = $this->routes[$service]; - $controller = new $route['controller'](); + + // Run Middlewares + foreach ($route['middlewares'] as $middleware) { + $this->runMiddleware($middleware); + } + + $controllerClass = $route['controller']; $method = $route['method']; + + if (!class_exists($controllerClass)) { + throw new \Exception("Controller class '$controllerClass' not found."); + } + + $controller = new $controllerClass(); + + if (!method_exists($controller, $method)) { + throw new \Exception("Method '$method' not found in controller '$controllerClass'."); + } + return $controller->$method(); } + + protected function runMiddleware($middleware) { + if ($middleware === 'admin') { + if (!isset($_SESSION['is_admin']) || $_SESSION['is_admin'] !== true) { + die("Access Denied: Admin rights required."); + } + } + + if ($middleware === 'auth') { + if (empty($_SESSION['user_logged_in'])) { + header('Location: login.php'); + exit; + } + } + } } + PHP; $files['WEBROOT/src/MVC/Layout/Layout.php'] = <<<'PHP' @@ -177,37 +598,131 @@ PHP; $files['WEBROOT/src/MVC/autoloader.php'] = <<<'PHP' + <?= $this->getBlock('title') ?> +
@@ -224,15 +739,17 @@ $files['WEBROOT/src/MVC/Layout/Templates/main.php'] = <<<'HTML' + HTML; // --- CONTROLLERS --- -$files['WEBROOT/src/MVC/Controller/HomeController.php'] = <<<'PHP' -Dashboard

Willkommen in deinem neuen MVC-System mit integriertem Header.

"; $files['WEBROOT/src/MVC/View/test1.php'] = "

Service 1

"; -$files['WEBROOT/src/MVC/View/test2.php'] = "

System Check

    \$v): ?>
  • :
"; + $files['WEBROOT/src/MVC/View/test2.php'] = "

System Check

+
    \$v): ?>
  • :
"; -// --- API --- -$files['WEBROOT/api/v1/get.php'] = " 'online']);"; + // --- API --- + $files['WEBROOT/api/v1/get.php'] = " 'online']);"; // --- ENTRY POINT --- $files['WEBROOT/index.php'] = <<<'PHP' @@ -307,4 +825,4 @@ foreach ($files as $file => $content) { echo "\n✨ Projekt '$projectName' wurde mit HEADER initialisiert!\n"; echo "1. Starten: php server.php\n"; -echo "2. Öffnen: http://localhost:8000\n"; +echo "2. Öffnen: http://localhost:8000\n"; \ No newline at end of file