From a6920922ca1e5a6d8ecfee43b282890ab52ea4da Mon Sep 17 00:00:00 2001 From: Tower Date: Tue, 2 Jun 2026 15:39:31 +0200 Subject: [PATCH] middleware added --- init.php | 1953 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 1308 insertions(+), 645 deletions(-) diff --git a/init.php b/init.php index b8b33c3..b66826b 100644 --- a/init.php +++ b/init.php @@ -40,6 +40,7 @@ $dirs = [ 'WEBROOT/src/MVC/View', 'WEBROOT/src/MVC/View/admin', 'WEBROOT/src/MVC/View/templates', + 'WEBROOT/src/MVC/Middleware', 'WEBROOT/src/MVC/Layout', 'WEBROOT/src/MVC/Layout/Templates', 'WEBROOT/storage', @@ -101,7 +102,7 @@ $files[$projectName . '.code-workspace'] = <<globalMiddlewares[] = $middleware; + } public function add($service, $controller, $method, $middlewares = [], $isApi = null) { // Auto-detect API route if $isApi is not explicitly set @@ -1196,9 +1201,14 @@ class Router { throw new \Exception("Service '$service' not found."); } + // 1. Run Global Middlewares + foreach ($this->globalMiddlewares as $middleware) { + $this->runMiddleware($middleware); + } + $route = $this->routes[$service]; - // Run Middlewares + // 2. Run Route-Specific Middlewares foreach ($route['middlewares'] as $middleware) { $this->runMiddleware($middleware); } @@ -1228,18 +1238,135 @@ class Router { } protected function runMiddleware($middleware) { - if ($middleware === 'admin') { - if (!isset($_SESSION['is_admin']) || $_SESSION['is_admin'] !== true) { - die("Access Denied: Admin rights required."); - } + Middleware::run($middleware); + } +} +PHP; + +$files['WEBROOT/src/MVC/Core/Middleware.php'] = <<<'PHP' + \MVC\Middleware\AuthMiddleware::class, + 'admin' => \MVC\Middleware\AdminMiddleware::class, + 'block' => \MVC\Middleware\BlockMiddleware::class, + 'global' => \MVC\Middleware\EveryRequestMiddleware::class, + ]; + + /** + * Führt eine Middleware aus. + */ + public static function run($name) { + if (!isset(self::$map[$name])) { + return; // Oder Exception werfen } + + $class = self::$map[$name]; + $middleware = new $class(); - if ($middleware === 'auth') { - if (empty($_SESSION['user_logged_in'])) { - header('Location: ?service=login'); - exit; - } + if (!$middleware instanceof MiddlewareInterface) { + throw new \Exception("Middleware '$class' muss MiddlewareInterface implementieren."); } + + $middleware->handle(); + } +} +PHP; + +$files['WEBROOT/src/MVC/Core/MiddlewareInterface.php'] = <<<'PHP' + + <?= $this->getBlock('title') ?> - + +
@@ -1344,15 +1564,17 @@ $files['WEBROOT/src/MVC/Layout/Templates/main.php'] = <<<'HTML' + HTML; // --- CONTROLLERS --- -$files['WEBROOT/src/MVC/Controller/AdminController.php'] = <<<'PHP' -📧 E-Mail Service - -
- +
+
- + -
-
-
- - -
-
- - -
-
- - -
- -
-
-HTML; +
+
+
+ + +
+
+ + +
+
+ + +
+ +
+
+ HTML; -$files['WEBROOT/src/MVC/View/admin/users.php'] = <<<'HTML' -

👤 Benutzerverwaltung

- -
- -
- - - - - -
-HTML; + $files['WEBROOT/src/MVC/View/admin/users.php'] = <<<'HTML'

👤 Benutzerverwaltung

+ +
+
+ +
+ + + + + +
+ HTML; -$files['WEBROOT/src/MVC/Controller/ApiController.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): ?>
  • :
"; -$files['WEBROOT/src/MVC/View/docs.php'] = <<<'HTML' -
-

🏛️ MVC Framework - Die Entwickler-Bibel

- -
-

📖 Inhaltsverzeichnis

-
-
    -
  • 1. Kern-Architektur + $files['WEBROOT/src/MVC/View/docs.php'] = <<<'HTML'
    +

    🏛️ MVC Framework - Die Entwickler-Bibel

    + +
    +

    📖 Inhaltsverzeichnis

    + +
    + + +
    +

    1.1 Request Lifecycle

    +

    Der Weg einer Anfrage durch das Framework ist linear und vorhersehbar:

    +
      +
    1. Entry: Alle Requests treffen auf WEBROOT/index.php.
    2. +
    3. Bootstrap: Session wird gestartet, der autoloader lädt Klassen + nach Bedarf.
    4. +
    5. Routing: Der Router lädt die routes.php und prüft + den GET['service'] Parameter.
    6. +
    7. Security: Middlewares (z.B. auth) werden ausgeführt.
    8. +
    9. Logic: Der Controller führt die Zielmethode aus.
    10. +
    11. Rendering: Der Controller ruft $this->render() auf.
    12. +
    13. Output: Das fertige Layout wird an den Browser gesendet.
    14. +
    +
    + +
    +

    1.2 Detaillierte Verzeichnisstruktur

    +
    +            ├── Framework.code-workpace
    +            ├── README.md
    +            ├── init.php
    +            └── /WEBROOT
    +                ├── /api
    +                |   └── /v1
    +                ├── /src
    +                |   ├── /config
    +                |   ├── /database
    +                |   ├── /MVC
    +                |       ├── /Core
    +                |       ├── /Classes
    +                |       ├── /Controller
    +                |       ├── /Model
    +                |       ├── /View
    +                |       └── /Layout
    +                |           └── /Templates
    +                ├── /commands
    +                ├── /static
    +                ├── /storage
    +                └── /logs
    +                    
    + +
    + +
    +

    1.3 Autoloader & Namespaces

    +

    Das Framework nutzt einen PSR-4 kompatiblen Autoloader in src/MVC/autoloader.php. +

    +
    // Automatische Auflösung:
    +            // MVC\Classes\Auth -> src/MVC/Classes/Auth.php
    +            // MVC\Core\Router  -> src/MVC/Core/Router.php
    +
    + + +
    +

    2.1 Routing Grundlagen

    +

    Routen werden zentral in src/config/routes.php definiert.

    +
    $router->add('home', \MVC\Controller\HomeController::class, 'index');
    +
    + +
    +

    2.2 Middleware System

    +

    Middlewares sind Klassen, die vor dem eigentlichen Controller ausgeführt werden. Sie dienen der + Validierung von Requests, Authentifizierung oder Logging.

    + +

    Globale Middlewares

    +

    Diese werden bei jedem Request ausgeführt (z.B. IP-Blocker oder globales + Logging):

    +
    $router->addGlobal('block');
    +            $router->addGlobal('global');
    + +

    Routen-spezifische Middlewares

    +

    Diese werden nur für bestimmte Services definiert:

    +
    // Erfordert Login ('auth') und Admin-Status ('admin')
    +            $router->add('admin', Controller::class, 'index', ['auth', 'admin']);
    + +

    Verfügbare Middlewares

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NameKlasseFunktion
    authAuthMiddlewarePrüft, ob der User eingeloggt ist ($_SESSION['user_logged_in']).
    adminAdminMiddlewarePrüft auf Administrator-Rechte ($_SESSION['is_admin']).
    blockBlockMiddlewareEinfacher IP-Blocker für gesperrte Adressen.
    globalEveryRequestMiddlewarePlatzhalter für Logik, die immer laufen soll.
    + +

    Eigene Middleware erstellen

    +
      +
    1. Erstelle eine Klasse in src/MVC/Middleware/.
    2. +
    3. Implementiere das MiddlewareInterface.
    4. +
    5. Registriere den Namen im Mapping der src/MVC/Core/Middleware.php.
    6. +
    +
    + + + + +
    +

    3.1 Database Methods (Low-Level)

    +

    Sichere DB-Operationen via src/utils/databaseMethods.php unter Verwendung von + Prepared Statements:

    -
  • -
  • 2. Routing & Middleware + + +
    +

    3.2 Core\Model (Abstraktion)

    +

    Ermöglicht objektorientierte DB-Zugriffe durch Vererbung.

    +
    class User extends \MVC\Core\Model {
    +                protected static $table = "Users";
    +            }
    +            $allUsers = User::all();
    +
    + +
    +

    3.3 Installations-Script

    +

    Das Script install_db.php automatisiert das gesamte DB-Setup:

      -
    • Routing Grundlagen
    • -
    • Middleware (Auth/Admin)
    • -
    • Navigations-System
    • +
    • Root-Access: Verbindet sich mit Root-Rechten (siehe env.ini). +
    • +
    • DB-Erstellung: Erstellt die Datenbank und einen dedizierten Worker-User. +
    • +
    • Tabellen: Legt Users (mit Admin-Account) und + Mailing an. +
    • +
    • Models: Generiert automatisch die zugehörigen Model-Dateien im Quellcode. +
    -
  • -
  • 3. Datenbank & Models + + + +
    +

    4.1 Layout Engine (Blöcke)

    +

    Das Framework nutzt ein flexibles Block-System in MVC\Layout\Layout:

    +
    $layout = new Layout('main');
    +            $layout->setBlock('title', 'Mein Titel');
    +            $layout->setBlock('content', 'HTML-Inhalt');
    +            echo $layout->render();
    +
    + +
    +

    4.2 View System

    +

    Die MVC\Core\View Klasse extrahiert Daten-Arrays direkt in PHP-Templates:

    +
    // Im Controller:
    +            return $this->render('home', ['name' => 'Max']);
    +
    +            // In src/MVC/View/home.php:
    +            <h1>Hallo <?= $name ?></h1>
    +
    + +
    +

    4.3 DarkMode & Themes

    +

    Unterstützt nahtlose Umschaltung zwischen Light- und DarkMode:

    -
  • -
-
    -
  • 4. UI & Layout + + + +
    +

    5.1 Auth Klasse

    +

    Zentrales Identitätsmanagement:

    +
    Auth::login($user, $pass); // Login-Versuch
    +            Auth::check();             // Eingeloggt?
    +            Auth::isAdmin();           // Admin-Rechte?
    +            Auth::user();              // Gibt User-Array zurück
    +
    + +
    +

    5.2 Form Generator

    +

    Erstellt konsistente HTML-Formulare mit Bootstrap-ähnlichem Styling:

    +
    echo Form::open('service_name');
    +            echo Form::input('email', 'E-Mail', 'email');
    +            echo Form::textarea('msg', 'Nachricht');
    +            echo Form::submit('Senden');
    +            echo Form::close();
    +
    + +
    +

    5.3 Storage & File Handling

    +

    Abstraktionslayer für das Dateisystem:

      -
    • Layout Engine (Blöcke)
    • -
    • View System
    • -
    • DarkMode & Themes
    • +
    • Upload: Storage::upload('file_input') speichert sicher in + /storage/uploads/. +
    • +
    • Download: Storage::download('path/to/file') erzwingt + Datei-Download mit korrekten Headern.
    • +
    • Listing: Storage::listFiles() gibt Array aller verfügbaren + Dateien zurück.
    -
  • -
  • 5. Framework Klassen + + +
    +

    5.4 Mailer Klasse

    +

    Versand von System-Mails:

    -
  • -
  • 6. Tools & API + + +
    +

    5.5 Logger & Debugging

    +

    Zentrales Fehler-Management:

      -
    • CLI Werkzeuge (make.php)
    • -
    • API Entwicklung
    • -
    • Best Practices
    • +
    • Auto-Catch: Registriert sich als globaler Exception- und Error-Handler. +
    • +
    • Tracing: Schreibt vollständige Stacktraces in + WEBROOT/logs/error.log. +
    • +
    • Manuell: Logger::log('Nachricht', 'LEVEL') für eigenes + Logging.
    -
  • -
-
-
+ - -
-

1.1 Request Lifecycle

-

Der Weg einer Anfrage durch das Framework ist linear und vorhersehbar:

-
    -
  1. Entry: Alle Requests treffen auf WEBROOT/index.php.
  2. -
  3. Bootstrap: Session wird gestartet, der autoloader lädt Klassen nach Bedarf.
  4. -
  5. Routing: Der Router lädt die routes.php und prüft den GET['service'] Parameter.
  6. -
  7. Security: Middlewares (z.B. auth) werden ausgeführt.
  8. -
  9. Logic: Der Controller führt die Zielmethode aus.
  10. -
  11. Rendering: Der Controller ruft $this->render() auf.
  12. -
  13. Output: Das fertige Layout wird an den Browser gesendet.
  14. -
-
+ +
+

6.1 CLI Werkzeuge (make.php)

+

Das Schweizer Taschenmesser für die Entwicklung:

+
    +
  • -c, --controller: Nur den Controller erstellen.
  • +
  • -v, --view: Nur die View erstellen.
  • +
  • -r, --route: Nur die Route registrieren.
  • +
  • -n, --nav: Nur den Navigationspunkt hinzufügen.
  • +
  • -a, --auth: Erfordert Login für diesen Service.
  • +
  • -l, --label "Text": Anzeigename in der Sidebar.
  • +
+

How to Use:

+
    +
  • php make.php module [Name]: Erstellt Controller, View, Route und Nav-Eintrag in + einem Rutsch.
  • +
  • php make.php model [Tabelle] [Spalten]: Generiert fertige Model-Klassen inkl. + Spaltendokumentation.
  • +
+
-
-

1.2 Detaillierte Verzeichnisstruktur

-
-├── Framework.code-workpace
-├── README.md
-├── init.php
-└── /WEBROOT
-    ├── /api
-    |   └── /v1
-    ├── /src
-    |   ├── /config
-    |   ├── /database
-    |   ├── /MVC
-    |       ├── /Core
-    |       ├── /Classes
-    |       ├── /Controller
-    |       ├── /Model
-    |       ├── /View
-    |       └── /Layout
-    |           └── /Templates
-    ├── /commands
-    ├── /static
-    ├── /storage
-    └── /logs
-        
+
+

6.2 API Entwicklung

+

Standardisierte JSON-Antworten über die Api Klasse:

+
// In src/MVC/Classes/Api.php
+            Api::jsonResponse(['data' => '...'], 200);
+

API-Files befinden sich übersichtlich in WEBROOT/api/v1/.

+
-
+
+

6.3 Best Practices

+
    +
  • Security: Keine Variablen direkt in SQL-Strings (Prepared Statements + nutzen!).
  • +
  • Output: Variablen in Views immer mit htmlspecialchars() + maskieren.
  • +
  • Architecture: Controller rufen Models auf, Views zeigen nur Daten an. Keine + DB-Logik in der View!
  • +
+
+
-
-

1.3 Autoloader & Namespaces

-

Das Framework nutzt einen PSR-4 kompatiblen Autoloader in src/MVC/autoloader.php.

-
// Automatische Auflösung:
-// MVC\Classes\Auth -> src/MVC/Classes/Auth.php
-// MVC\Core\Router  -> src/MVC/Core/Router.php
-
+ + @media (max-width: 768px) { + .toc-grid { + grid-template-columns: 1fr; + } + } + + HTML; -HTML; -$files['WEBROOT/src/MVC/View/login.php'] = <<<'HTML' - - -HTML; + $files['WEBROOT/src/MVC/View/login.php'] = <<<'HTML' + + HTML; -$files['WEBROOT/src/MVC/View/templates/data_form.php'] = <<<'HTML' -

📝 Daten-Formular

+ $files['WEBROOT/src/MVC/View/templates/data_form.php'] = <<<'HTML'

📝 Daten-Formular

- + - -
- + +
+
+ - -
-
    - -
  • - -
-
- + +
+
    + +
  • + +
+
+ -
- -
-
- 'Max', 'required' => true]) ?> -
-
- 'Mustermann', 'required' => true]) ?> -
-
+
+ +
+
+ 'Max', 'required' => true]) ?> +
+
+ 'Mustermann', 'required' => true]) ?> +
+
- 'max@example.com', 'required' => true]) ?> + 'max@example.com', 'required' => true]) ?> -
- - -
+
+ + +
-
- -
- - - -
-
+
+ +
+ + + +
+
-
- -
- - -
-
+
+ +
+ + +
+
- - - -
+ + + +
- -HTML; + -HTML; + .form-group label { + display: block; + margin-bottom: 8px; + font-weight: 600; + } -$files['WEBROOT/src/MVC/View/templates/download.php'] = <<<'HTML' -

📥 Datei Downloads

+ .form-control { + width: 100%; + padding: 12px; + border: 1px solid var(--border); + border-radius: 4px; + background: var(--bg); + color: var(--text); + box-sizing: border-box; + } -
- - - - - - - - - - - - - - - - - - - - - - - - - -
DateinameGrößeDatumAktion
Keine Dateien verfügbar.
KB - 💾 Download -
-
+ .checkbox-group, + .radio-group { + display: flex; + flex-direction: column; + gap: 10px; + margin-top: 5px; + } - -HTML; + .checkbox-label, + .radio-label { + display: flex; + align-items: center; + gap: 10px; + cursor: pointer; + font-weight: normal; + } -$files['WEBROOT/src/MVC/View/templates/upload.php'] = <<<'HTML' -

📤 Datei Upload

+ .btn { + padding: 12px 24px; + border: none; + border-radius: 4px; + cursor: pointer; + font-weight: bold; + margin-right: 10px; + } - + .btn-primary { + background: var(--accent); + color: white; + } - -
- -
- + .btn-secondary { + background: #95a5a6; + color: white; + } -
- 'multipart/form-data']) ?> - - true]) ?> - - 'Kurze Beschreibung der Datei...']) ?> + .btn:hover { + opacity: 0.9; + } + + HTML; - - - -
+ $files['WEBROOT/src/MVC/View/templates/data_table.php'] = <<<'HTML'

📊 Datenübersicht

- -HTML; +
+ +
+ + +
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
IDNameStatusDatumAktionen
#Beispiel Datensatz Aktiv + + +
+
+ + + HTML; + + $files['WEBROOT/src/MVC/View/templates/download.php'] = <<<'HTML'

📥 Datei Downloads +

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
DateinameGrößeDatumAktion
Keine Dateien + verfügbar.
KB + 💾 Download +
+
+ + + HTML; + + $files['WEBROOT/src/MVC/View/templates/upload.php'] = <<<'HTML'

📤 Datei Upload

+ + + + +
+ +
+ + +
+ 'multipart/form-data']) ?> + + true]) ?> + + 'Kurze Beschreibung der Datei...']) ?> + + + + +
+ + + HTML; + + // --- CONFIG: routes.php --- + $files['WEBROOT/src/config/routes.php'] = <<<'PHP' add(service_name, controller_class, method_name, options); */ + +// Global Middlewares (executed on every request) +$router->addGlobal('global'); // Beispiel: Logging +$router->addGlobal('block'); // Beispiel: IP-Blocker + $router->add('home', \MVC\Controller\HomeController::class, 'index'); $router->add('toggle_theme', \MVC\Controller\HomeController::class, 'toggle_theme'); $router->add('docs', \MVC\Controller\DocsController::class, 'index'); @@ -2255,6 +2914,7 @@ $router->add('download_file', \MVC\Controller\TemplateController::class, 'downlo // API Routes (Path-based) $router->add('api/v1/test', \MVC\Controller\ApiController::class, 'get'); +$router->add('api/v1/become', \MVC\Controller\ApiController::class, 'become'); PHP; // --- CONFIG: navigation.php --- @@ -2332,9 +2992,8 @@ try { ob_start(); // Load navigation from config $navItems = require __DIR__ . '/src/config/navigation.php'; - ?> - + setBlock('sidebar', ob_get_clean()); $layout->setBlock('content', $output); @@ -2578,73 +3239,75 @@ PHPCTRL; if ($doView) { $viewContent = << -
-

-

Hier kannst du nun dein Projekt aufbauen.

-
+
+

+

Hier kannst du nun dein Projekt aufbauen.

+
- -HTML; + + HTML; - if (!file_exists($viewFile)) { - file_put_contents($viewFile, $viewContent); - echo "✅ View erstellt: WEBROOT/src/MVC/View/{$key}.php\n"; - } else { - echo "⚠️ View existiert bereits.\n"; - } - } + if (!file_exists($viewFile)) { + file_put_contents($viewFile, $viewContent); + echo "✅ View erstellt: WEBROOT/src/MVC/View/{$key}.php\n"; + } else { + echo "⚠️ View existiert bereits.\n"; + } + } - // 3. Route hinzufügen - if ($doRoute) { - if (file_exists($routesFile)) { - $routesContent = file_get_contents($routesFile); - $routeLine = "\$router->add('{$key}', \\MVC\\Controller\\{$className}Controller::class, '{$key}'" . ($isAuth ? ", ['auth']" : "") . ");\n"; - - if (strpos($routesContent, "'{$key}'") === false) { - file_put_contents($routesFile, $routesContent . $routeLine); - echo "✅ Route hinzugefügt: {$routesFile}\n"; - } else { - echo "⚠️ Route für '{$key}' existiert bereits in routes.php\n"; - } - } else { - echo "❌ Fehler: routes.php nicht gefunden!\n"; - } - } + // 3. Route hinzufügen + if ($doRoute) { + if (file_exists($routesFile)) { + $routesContent = file_get_contents($routesFile); + $routeLine = "\$router->add('{$key}', + \\MVC\\Controller\\{$className}Controller::class, '{$key}'" . ($isAuth ? ", + ['auth']" : "") . ");\n"; - // 4. Navigation hinzufügen - if ($doNav) { - if (file_exists($navFile)) { - $navContent = file_get_contents($navFile); - $navItem = " '{$key}' => ['label' => '{$label}'],\n"; - - if (strpos($navContent, "'{$key}'") === false) { - // Wir suchen nach dem Ende des Arrays ]; - $newNavContent = preg_replace('/(\];\s*)$/', $navItem . '$1', trim($navContent)); - file_put_contents($navFile, $newNavContent . "\n"); - echo "✅ Navigation hinzugefügt: {$navFile}\n"; - } else { - echo "⚠️ Navigation für '{$key}' existiert bereits in navigation.php\n"; - } - } else { - echo "❌ Fehler: navigation.php nicht gefunden!\n"; - } - } + if (strpos($routesContent, "'{$key}'") === false) { + file_put_contents($routesFile, $routesContent . $routeLine); + echo "✅ Route hinzugefügt: {$routesFile}\n"; + } else { + echo "⚠️ Route für '{$key}' existiert bereits in routes.php\n"; + } + } else { + echo "❌ Fehler: routes.php nicht gefunden!\n"; + } + } - echo "\nFertig!\n"; -} -PHP; + // 4. Navigation hinzufügen + if ($doNav) { + if (file_exists($navFile)) { + $navContent = file_get_contents($navFile); + $navItem = " '{$key}' => ['label' => '{$label}'],\n"; + + if (strpos($navContent, "'{$key}'") === false) { + // Wir suchen nach dem Ende des Arrays ]; + $newNavContent = preg_replace('/(\];\s*)$/', $navItem . '$1', + trim($navContent)); + file_put_contents($navFile, $newNavContent . "\n"); + echo "✅ Navigation hinzugefügt: {$navFile}\n"; + } else { + echo "⚠️ Navigation für '{$key}' existiert bereits in navigation.php\n"; + } + } else { + echo "❌ Fehler: navigation.php nicht gefunden!\n"; + } + } + + echo "\nFertig!\n"; + } + PHP; -$files['install_db.php'] = <<<'PHP' -