Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7a2d53d7b1 | ||
|
|
307819681e | ||
|
|
27c11ba5ff | ||
|
|
c44b508689 | ||
|
|
9d0863d65f | ||
|
|
bfd16c310d | ||
|
|
85219fdb59 | ||
|
|
dc9ef406fc | ||
|
|
83f43b0149 | ||
|
|
d7cb5084ef | ||
|
|
59eba3ef2b | ||
|
|
dbcf1228d8 | ||
|
|
e341f4cfe1 | ||
|
|
6ef6c15942 |
No files matched your search
@@ -1 +0,0 @@
|
||||
<?php header('Content-Type: application/json'); echo json_encode(['status' => 'online']);
|
||||
@@ -1,33 +0,0 @@
|
||||
<?php
|
||||
session_start();
|
||||
require_once __DIR__ . '/src/MVC/autoloader.php';
|
||||
$service = $_GET['service'] ?? 'home';
|
||||
try {
|
||||
$router = new \MVC\Core\Router();
|
||||
$router->add('home', \MVC\Controller\HomeController::class, 'index');
|
||||
$router->add('toggle_theme', \MVC\Controller\HomeController::class, 'toggle_theme');
|
||||
$router->add('test1', \MVC\Controller\TestController::class, 'service1');
|
||||
$router->add('test2', \MVC\Controller\TestController::class, 'service2');
|
||||
$router->add('aussentemp', \MVC\Controller\AussentempController::class, 'aussentemp', ['auth']);
|
||||
|
||||
$layout = new \MVC\Layout\Layout('main');
|
||||
$layout->setBlock('title', 'MVC Starter');
|
||||
$layout->setBlock('header_title', '🚀 MVC Dashboard');
|
||||
$layout->setBlock('header_actions', '<button class="btn-toggle" onclick="toggleTheme()">🌓 Theme umschalten</button>');
|
||||
|
||||
// Sidebar Block
|
||||
ob_start();
|
||||
?>
|
||||
<nav>
|
||||
<a href="?service=home">🏠 Home</a>
|
||||
<a href="?service=test1">🛠️ Test 1</a>
|
||||
<a href="?service=test2">📊 Test 2</a>
|
||||
</nav>
|
||||
<?php
|
||||
$layout->setBlock('sidebar', ob_get_clean());
|
||||
|
||||
$layout->setBlock('content', $router->dispatch($service));
|
||||
echo $layout->render();
|
||||
} catch (\Exception $e) {
|
||||
http_response_code(404); echo "<h1>404</h1><p>" . $e->getMessage() . "</p>";
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace MVC\Controller;
|
||||
|
||||
use MVC\Core\Controller;
|
||||
// use MVC\Model\YourModel; // Importiere dein Model
|
||||
|
||||
class AussentempController extends Controller {
|
||||
public function aussentemp() {
|
||||
// Nutze Models für den Datenbankzugriff
|
||||
// $data = YourModel::all();
|
||||
|
||||
return $this->render('aussentemp', [
|
||||
'title' => 'Aussentemp Modul',
|
||||
'message' => 'Willkommen in deinem neuen Modul Aussentemp!'
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
<?php
|
||||
namespace MVC\Controller;
|
||||
use MVC\Core\Controller;
|
||||
class TestController extends Controller {
|
||||
|
||||
public function service1() {
|
||||
return $this->render(
|
||||
'test1',
|
||||
[
|
||||
'msg' => 'Service 1 ist bereit!'
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
public function service2() {
|
||||
return $this->render(
|
||||
'test2',
|
||||
[
|
||||
'data' =>
|
||||
[
|
||||
'Layout' => 'Header + Sidebar',
|
||||
'Theme' => 'Auto-Toggle'
|
||||
]
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de" class="<?= ($_SESSION['theme'] ?? 'light') === 'dark' ? 'dark-mode' : '' ?>">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title><?= $this->getBlock('title') ?></title>
|
||||
<style>
|
||||
:root { --bg: #ffffff; --text: #333; --sidebar: #f4f4f4; --header: #007bff; --accent: #007bff; --border: #ddd; }
|
||||
.dark-mode { --bg: #1a1a1a; --text: #f4f4f4; --sidebar: #252525; --header: #111; --accent: #3498db; --border: #333; }
|
||||
body { font-family: 'Segoe UI', sans-serif; margin: 0; background: var(--bg); color: var(--text); transition: 0.3s; height: 100vh; overflow: hidden; display: flex; flex-direction: column; }
|
||||
.main-header { height: 60px; background: var(--header); color: white; display: flex; align-items: center; justify-content: space-between; padding: 0 20px; box-shadow: 0 2px 5px rgba(0,0,0,0.1); z-index: 10; }
|
||||
.main-container { flex: 1; display: flex; overflow: hidden; }
|
||||
.sidebar { width: 260px; background: var(--sidebar); padding: 20px; border-right: 1px solid var(--border); overflow-y: auto; }
|
||||
.content { flex: 1; padding: 40px; overflow-y: auto; }
|
||||
.btn-toggle { padding: 8px 15px; border: 1px solid rgba(255,255,255,0.3); border-radius: 5px; cursor: pointer; background: transparent; color: white; font-size: 0.9rem; }
|
||||
.btn-toggle:hover { background: rgba(255,255,255,0.1); }
|
||||
nav a { display: block; padding: 12px; text-decoration: none; color: inherit; border-radius: 5px; margin-bottom: 5px; }
|
||||
nav a:hover { background: rgba(0,0,0,0.05); }
|
||||
.logo { font-size: 1.4rem; font-weight: bold; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header class="main-header">
|
||||
<div class="logo"><?= $this->getBlock('header_title') ?></div>
|
||||
<div class="header-actions">
|
||||
<?= $this->getBlock('header_actions') ?>
|
||||
</div>
|
||||
</header>
|
||||
<div class="main-container">
|
||||
<div class="sidebar">
|
||||
<?= $this->getBlock('sidebar') ?>
|
||||
</div>
|
||||
<div class="content">
|
||||
<?= $this->getBlock('content') ?>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
function toggleTheme() { fetch('?service=toggle_theme').then(() => location.reload()); }
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,22 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace MVC\Model;
|
||||
|
||||
use MVC\Core\Model;
|
||||
|
||||
/**
|
||||
* Model für die Tabelle 'messungen'
|
||||
* Verfügbare Spalten: 'id', 'ts', 'aussentemp'
|
||||
*/
|
||||
class Messungen extends Model {
|
||||
protected static $table = "messungen";
|
||||
|
||||
// Hier kannst du spezifische Methoden für dieses Model hinzufügen
|
||||
|
||||
/**
|
||||
* Beispiel: Suche nach einer spezifischen Spalte
|
||||
*/
|
||||
public static function getByFirstColumn($value) {
|
||||
return self::where("id = ?", $value);
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
<h2><?= htmlspecialchars($title) ?></h2>
|
||||
<div class="card">
|
||||
<p><?= htmlspecialchars($message) ?></p>
|
||||
<p>Hier kannst du nun dein Projekt aufbauen.</p>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.card {
|
||||
background: var(--card-bg);
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
border: 1px solid var(--card-border);
|
||||
}
|
||||
</style>
|
||||
@@ -1 +0,0 @@
|
||||
<h1>Dashboard</h1><p>Willkommen in deinem neuen MVC-System mit integriertem Header.</p>
|
||||
@@ -1 +0,0 @@
|
||||
<h1>Service 1</h1><p><?= $msg ?></p>
|
||||
@@ -1 +0,0 @@
|
||||
<h1>System Check</h1><ul><?php foreach($data as $k => $v): ?><li><b><?= $k ?>:</b> <?= $v ?></li><?php endforeach; ?></ul>
|
||||
@@ -1,6 +0,0 @@
|
||||
[database]
|
||||
APP_ENV = "dev"
|
||||
DB_DEV_HOST = "localhost"
|
||||
DB_DEV_USERNAME = "root"
|
||||
DB_DEV_PASSWORD = ""
|
||||
DB_DEV_DATABASE = "mein_projekt"
|
||||
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
use MVC\Classes\Api;
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
require_once __DIR__ . '/../../src/MVC/autoloader.php';
|
||||
|
||||
use MVC\Controller\ApiController;
|
||||
|
||||
try {
|
||||
Api::jsonResponse((new ApiController())->get());
|
||||
} catch (\Exception $e) {
|
||||
Api::jsonResponse($e->getMessage(), 404);
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
error_reporting(E_ALL);
|
||||
ini_set('display_errors', 1);
|
||||
session_start();
|
||||
require_once __DIR__ . '/src/MVC/autoloader.php';
|
||||
$service = $_GET['service'] ?? 'home';
|
||||
try {
|
||||
$router = new \MVC\Core\Router();
|
||||
$router->add('home', \MVC\Controller\HomeController::class, 'index');
|
||||
$router->add('toggle_theme', \MVC\Controller\HomeController::class, 'toggle_theme');
|
||||
$router->add('abgas', \MVC\Controller\AbgasController::class, 'abgas');
|
||||
$router->add('vorlauf', \MVC\Controller\VorlaufController::class, 'vorlauf', ['auth']);
|
||||
$router->add('puffer', \MVC\Controller\PufferController::class, 'puffer', ['auth']);
|
||||
$router->add('aussentemp', \MVC\Controller\AussentempController::class, 'aussentemp', ['auth']);
|
||||
$router->add('docs', \MVC\Controller\DocsController::class, 'index');
|
||||
$router->add('login', \MVC\Controller\AuthController::class, 'login');
|
||||
$router->add('logout', \MVC\Controller\AuthController::class, 'logout');
|
||||
|
||||
$layout = new \MVC\Layout\Layout('main');
|
||||
$layout->setBlock('title', 'MVC Starter');
|
||||
$layout->setBlock('header_title', '🚀 MVC Dashboard');
|
||||
|
||||
$headerActions = '<button class="btn-toggle" onclick="toggleTheme()">🌓 Theme umschalten</button>';
|
||||
if (isset($_SESSION['user_logged_in'])) {
|
||||
$headerActions = '<span style="margin-right: 15px;">👤 ' . htmlspecialchars($_SESSION['username']) . '</span>' .
|
||||
'<a href="?service=logout" class="btn-toggle" style="text-decoration: none; background: rgba(255,255,255,0.2);">🚪 Logout</a> ' .
|
||||
$headerActions;
|
||||
} else {
|
||||
$headerActions = '<a href="?service=login" class="btn-toggle" style="text-decoration: none; background: var(--accent); color: white; margin-right: 10px;">🔑 Login</a> ' .
|
||||
$headerActions;
|
||||
}
|
||||
$layout->setBlock('header_actions', $headerActions);
|
||||
|
||||
// Sidebar Block
|
||||
ob_start();
|
||||
$navItems = [
|
||||
'home' => ['label' => '🏠 Home', 'auth' => false],
|
||||
'abgas' => ['label' => '🔥 Abgas', 'auth' => false],
|
||||
'vorlauf' => ['label' => '🏃♂️➡️ Vorlauf', 'auth' => true],
|
||||
'puffer' => ['label' => '♨️ Puffer', 'auth' => true],
|
||||
'aussentemp' => ['label' => '🌡️ Außentemperatur', 'auth' => true],
|
||||
'docs' => ['label' => '📚 Dokumentation', 'auth' => false],
|
||||
];
|
||||
?>
|
||||
<nav>
|
||||
<?php foreach ($navItems as $navKey => $item):
|
||||
if ($item['auth'] && !isset($_SESSION['user_logged_in'])) continue;
|
||||
?>
|
||||
<a href="?service=<?= $navKey ?>" class="<?= $service === $navKey ? 'active' : '' ?>"><?= $item['label'] ?></a>
|
||||
<?php endforeach; ?>
|
||||
|
||||
<?php if (!isset($_SESSION['user_logged_in'])): ?>
|
||||
<div style="margin-top: 20px; padding: 10px; font-size: 0.8rem; opacity: 0.5; border-top: 1px solid var(--border);">
|
||||
🔒 Melden Sie sich an, um alle Funktionen zu sehen.
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</nav>
|
||||
<?php
|
||||
$layout->setBlock('sidebar', ob_get_clean());
|
||||
|
||||
$layout->setBlock('content', $router->dispatch($service));
|
||||
echo $layout->render();
|
||||
} catch (\Throwable $e) {
|
||||
http_response_code(500); echo "<h1>Error</h1><p>" . $e->getMessage() . "</p><pre>" . $e->getTraceAsString() . "</pre>";
|
||||
};
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace MVC\Classes;
|
||||
|
||||
class Api {
|
||||
public static function jsonResponse($data, int $statusCode = 200) {
|
||||
header('Content-Type: application/json');
|
||||
http_response_code($statusCode);
|
||||
echo json_encode(
|
||||
[
|
||||
'status' => $statusCode === 200 ? 'success' : 'error',
|
||||
'data' => $data,
|
||||
], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE
|
||||
);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace MVC\Classes;
|
||||
|
||||
class Client {
|
||||
|
||||
public static function ip() {
|
||||
if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
|
||||
$ipList = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
|
||||
return trim($ipList[0]);
|
||||
} else if (!empty($_SERVER['REMOTE_ADDR'])) {
|
||||
return $_SERVER['REMOTE_ADDR'];
|
||||
} else {
|
||||
return 'UNKNOWN';
|
||||
}
|
||||
}
|
||||
|
||||
public static function port() {
|
||||
return $_SERVER['REMOTE_PORT'] ?? 'UNKNOWN';
|
||||
}
|
||||
|
||||
public static function country() {
|
||||
$response = file_get_contents('http://ip-api.com/json/{' . self::ip() . '}?fields=country,countryCode');
|
||||
$data = json_decode($response);
|
||||
return $data->country ?? 'UNKNOWN';
|
||||
}
|
||||
|
||||
public static function userAgent() {
|
||||
return $_SERVER['HTTP_USER_AGENT'] ?? 'UNKNOWN';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace MVC\Classes;
|
||||
|
||||
class Cookie {
|
||||
public function set(string $CookieName, int $CookieValue, int $CookieTime) {
|
||||
setcookie($CookieName, $CookieValue, time()+($CookieTime*60));
|
||||
}
|
||||
|
||||
public function read(string $CookieName) {
|
||||
if (isset($_COOKIE[$CookieName])) {
|
||||
return $_COOKIE[$CookieName];
|
||||
}
|
||||
return 'Cookie not set';
|
||||
}
|
||||
|
||||
public function Delete(string $CookieName) {
|
||||
setcookie($CookieName, "", time()-(3600*24));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace MVC\Classes;
|
||||
|
||||
class Request {
|
||||
public static function method() {
|
||||
return $_SERVER['REQUEST_METHOD'] ?? 'UNKNOWN';
|
||||
}
|
||||
|
||||
public static function uri() {
|
||||
return $_SERVER['REQUEST_URI'] ?? 'UNKNOWN';
|
||||
}
|
||||
|
||||
public static function headers() {
|
||||
return getallheaders();
|
||||
}
|
||||
|
||||
public static function body() {
|
||||
return file_get_contents('php://input');
|
||||
}
|
||||
|
||||
public static function queryParams() {
|
||||
return $_GET;
|
||||
}
|
||||
|
||||
public static function time() {
|
||||
return $_SERVER['REQUEST_TIME'] ?? 'UNKNOWN';
|
||||
}
|
||||
|
||||
public static function referrer() {
|
||||
return $_SERVER['HTTP_REFERER'] ?? 'UNKNOWN';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace MVC\Classes;
|
||||
|
||||
class Server {
|
||||
public static function documentRoot() {
|
||||
return $_SERVER['DOCUMENT_ROOT'] ?? 'UNKNOWN';
|
||||
}
|
||||
|
||||
public static function currentDir() {
|
||||
return __DIR__;
|
||||
}
|
||||
|
||||
public static function currentScript() {
|
||||
return $_SERVER['SCRIPT_NAME'] ?? 'UNKNOWN';
|
||||
}
|
||||
|
||||
public static function name() {
|
||||
return $_SERVER['SERVER_NAME'] ?? 'UNKNOWN';
|
||||
}
|
||||
|
||||
public static function port() {
|
||||
return $_SERVER['SERVER_PORT'] ?? 'UNKNOWN';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace MVC\Controller;
|
||||
|
||||
use MVC\Core\Controller;
|
||||
use MVC\Model\Messungen;
|
||||
|
||||
class AbgasController extends Controller {
|
||||
|
||||
public function abgas() {
|
||||
|
||||
$day = $_GET['day'] ?? date('Y-m-d');
|
||||
$datum = \DateTime::createFromFormat('Y-m-d', $day);
|
||||
|
||||
if (!$datum) {
|
||||
$day = date('Y-m-d');
|
||||
}
|
||||
|
||||
$array = Messungen::getAbgasByDay($day);
|
||||
$labels = [];
|
||||
$abgas = [];
|
||||
|
||||
foreach ($array as $row) {
|
||||
$labels[] = date('H:i:s', strtotime($row['ts']));
|
||||
$abgas[] = (float)$row['abgas'];
|
||||
}
|
||||
|
||||
$prevDay = date('Y-m-d', strtotime($day . ' -1 day'));
|
||||
$nextDay = date('Y-m-d', strtotime($day . ' +1 day'));
|
||||
|
||||
return $this->render('abgas', [
|
||||
'title' => 'Abgas Modul',
|
||||
'xtitle' => 'Zeit',
|
||||
'ytitle' => 'Temperatur',
|
||||
|
||||
'array' => $array,
|
||||
|
||||
'labels' => $labels,
|
||||
'abgas' => $abgas,
|
||||
|
||||
'day' => $day,
|
||||
'prevDay' => $prevDay,
|
||||
'nextDay' => $nextDay,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace MVC\Controller;
|
||||
|
||||
use MVC\Core\Controller;
|
||||
use MVC\Model\Messungen;
|
||||
use MVC\Classes\Api;
|
||||
|
||||
class ApiController extends Controller {
|
||||
public function get() {
|
||||
$day = "2026-05-22";
|
||||
$abgas = Messungen::getAbgasByDay($day);
|
||||
|
||||
return Api::jsonResponse([
|
||||
'abgas' => $abgas,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace MVC\Controller;
|
||||
|
||||
use MVC\Core\Controller;
|
||||
use MVC\Model\Messungen;
|
||||
|
||||
class AussentempController extends Controller {
|
||||
|
||||
public function aussentemp() {
|
||||
|
||||
$day = $_GET['day'] ?? date('Y-m-d');
|
||||
$datum = \DateTime::createFromFormat('Y-m-d', $day);
|
||||
|
||||
if (!$datum) {
|
||||
$day = date('Y-m-d');
|
||||
}
|
||||
|
||||
$array = Messungen::getAussentempByDay($day);
|
||||
$labels = [];
|
||||
$aussentemp = [];
|
||||
|
||||
foreach ($array as $row) {
|
||||
$labels[] = date('H:i:s', strtotime($row['ts']));
|
||||
$aussentemp[] = (float)$row['aussentemp'];
|
||||
}
|
||||
|
||||
$prevDay = date('Y-m-d', strtotime($day . ' -1 day'));
|
||||
$nextDay = date('Y-m-d', strtotime($day . ' +1 day'));
|
||||
|
||||
return $this->render('aussentemp', [
|
||||
'title' => 'Aussentemperatur Modul',
|
||||
'xtitle' => 'Zeit',
|
||||
'ytitle' => 'Temperatur',
|
||||
|
||||
'array' => $array,
|
||||
|
||||
'labels' => $labels,
|
||||
'aussentemp' => $aussentemp,
|
||||
|
||||
'day' => $day,
|
||||
'prevDay' => $prevDay,
|
||||
'nextDay' => $nextDay,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace MVC\Controller;
|
||||
|
||||
use MVC\Core\Controller;
|
||||
|
||||
class AuthController extends Controller {
|
||||
public function login() {
|
||||
if (isset($_SESSION['user_logged_in'])) {
|
||||
header('Location: ?service=home');
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$username = $_POST['username'] ?? '';
|
||||
$password = $_POST['password'] ?? '';
|
||||
|
||||
// Hardcoded logins
|
||||
$users = [
|
||||
'admin' => 'password123',
|
||||
'user' => 'user123'
|
||||
];
|
||||
|
||||
if (isset($users[$username]) && $users[$username] === $password) {
|
||||
$_SESSION['user_logged_in'] = true;
|
||||
$_SESSION['username'] = $username;
|
||||
header('Location: ?service=home');
|
||||
exit;
|
||||
} else {
|
||||
return $this->render('login', ['error' => 'Ungültige Anmeldedaten']);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->render('login');
|
||||
}
|
||||
|
||||
public function logout() {
|
||||
session_destroy();
|
||||
header('Location: ?service=login');
|
||||
exit;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace MVC\Controller;
|
||||
|
||||
use MVC\Core\Controller;
|
||||
|
||||
class DocsController extends Controller {
|
||||
public function index() {
|
||||
return $this->render('docs', [
|
||||
'title' => '📚 System-Dokumentation'
|
||||
]);
|
||||
}
|
||||
}
|
||||
File renamed without changes.
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace MVC\Controller;
|
||||
|
||||
use MVC\Core\Controller;
|
||||
use MVC\Model\Messungen;
|
||||
|
||||
class PufferController extends Controller {
|
||||
|
||||
public function puffer() {
|
||||
|
||||
// Tag holen
|
||||
$day = $_GET['day'] ?? date('Y-m-d');
|
||||
|
||||
// Validierung
|
||||
$datum = \DateTime::createFromFormat('Y-m-d', $day);
|
||||
if (!$datum) {
|
||||
$day = date('Y-m-d');
|
||||
}
|
||||
|
||||
// Daten laden
|
||||
$array = Messungen::getPufferByDay($day);
|
||||
|
||||
// Chart Daten vorbereiten
|
||||
$labels = [];
|
||||
$pufferOben = [];
|
||||
$pufferUnten = [];
|
||||
|
||||
foreach ($array as $row) {
|
||||
|
||||
// Zeit kürzen für Chart
|
||||
$labels[] = date('H:i:s', strtotime($row['ts']));
|
||||
|
||||
$pufferOben[] = (float)$row['kessel_oben'];
|
||||
$pufferUnten[] = (float)$row['kessel_unten'];
|
||||
}
|
||||
|
||||
// Navigation
|
||||
$prevDay = date('Y-m-d', strtotime($day . ' -1 day'));
|
||||
$nextDay = date('Y-m-d', strtotime($day . ' +1 day'));
|
||||
|
||||
return $this->render('puffer', [
|
||||
'title' => 'Puffer Übersicht',
|
||||
'xtitle' => 'Zeit',
|
||||
'ytitle' => 'Temperatur',
|
||||
|
||||
'array' => $array,
|
||||
|
||||
'labels' => $labels,
|
||||
'pufferOben' => $pufferOben,
|
||||
'pufferUnten' => $pufferUnten,
|
||||
|
||||
'day' => $day,
|
||||
'prevDay' => $prevDay,
|
||||
'nextDay' => $nextDay,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace MVC\Controller;
|
||||
|
||||
use MVC\Core\Controller;
|
||||
use MVC\Model\Messungen;
|
||||
|
||||
class VorlaufController extends Controller {
|
||||
|
||||
public function vorlauf() {
|
||||
|
||||
// Tag holen
|
||||
$day = $_GET['day'] ?? date('Y-m-d');
|
||||
|
||||
// Validierung
|
||||
$datum = \DateTime::createFromFormat('Y-m-d', $day);
|
||||
if (!$datum) {
|
||||
$day = date('Y-m-d');
|
||||
}
|
||||
|
||||
// Daten laden
|
||||
$array = Messungen::getVorlaufByDay($day);
|
||||
|
||||
// Chart Daten vorbereiten
|
||||
$labels = [];
|
||||
$vorlaufIst = [];
|
||||
$vorlaufSoll = [];
|
||||
|
||||
foreach ($array as $row) {
|
||||
|
||||
// Zeit kürzen für Chart
|
||||
$labels[] = date('H:i:s', strtotime($row['ts']));
|
||||
|
||||
$vorlaufIst[] = (float)$row['vorlauf_ist'];
|
||||
$vorlaufSoll[] = (float)$row['vorlauf_soll'];
|
||||
}
|
||||
|
||||
// Navigation
|
||||
$prevDay = date('Y-m-d', strtotime($day . ' -1 day'));
|
||||
$nextDay = date('Y-m-d', strtotime($day . ' +1 day'));
|
||||
|
||||
return $this->render('vorlauf', [
|
||||
'title' => 'Vorlauf Übersicht',
|
||||
'xtitle' => 'Zeit',
|
||||
'ytitle' => 'Temperatur',
|
||||
|
||||
'array' => $array,
|
||||
|
||||
'labels' => $labels,
|
||||
'vorlaufIst' => $vorlaufIst,
|
||||
'vorlaufSoll' => $vorlaufSoll,
|
||||
|
||||
'day' => $day,
|
||||
'prevDay' => $prevDay,
|
||||
'nextDay' => $nextDay,
|
||||
]);
|
||||
}
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
+1
-1
@@ -51,7 +51,7 @@ class Router {
|
||||
|
||||
if ($middleware === 'auth') {
|
||||
if (empty($_SESSION['user_logged_in'])) {
|
||||
header('Location: login.php');
|
||||
header('Location: ?service=login');
|
||||
exit;
|
||||
}
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,112 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de" class="<?= ($_SESSION['theme'] ?? 'light') === 'dark' ? 'dark-mode' : '' ?>">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title><?= $this->getBlock('title') ?></title>
|
||||
<style>
|
||||
:root {
|
||||
--bg: #ffffff;
|
||||
--text: #333;
|
||||
--sidebar: #f4f4f4;
|
||||
--header: #007bff;
|
||||
--accent: #007bff;
|
||||
--border: #ddd;
|
||||
}
|
||||
.dark-mode {
|
||||
--bg: #1a1a1a;
|
||||
--text: #f4f4f4;
|
||||
--sidebar: #252525;
|
||||
--header: #111;
|
||||
--accent: #3498db;
|
||||
--border: #333;
|
||||
}
|
||||
body {
|
||||
font-family: 'Segoe UI', sans-serif;
|
||||
margin: 0;
|
||||
background: var(--bg);
|
||||
color: var(--text);
|
||||
transition: 0.3s;
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.main-header {
|
||||
height: 60px;
|
||||
background: var(--header);
|
||||
color: white;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 20px;
|
||||
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
|
||||
z-index: 10;
|
||||
}
|
||||
.main-container {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
}
|
||||
.sidebar {
|
||||
width: 260px;
|
||||
background: var(--sidebar);
|
||||
padding: 20px;
|
||||
border-right: 1px solid var(--border);
|
||||
overflow-y: auto;
|
||||
}
|
||||
.content {
|
||||
flex: 1;
|
||||
padding: 40px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.btn-toggle {
|
||||
padding: 8px 15px;
|
||||
border: 1px solid rgba(255,255,255,0.3);
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
background: transparent;
|
||||
color: white;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
.btn-toggle:hover {
|
||||
background: rgba(255,255,255,0.1);
|
||||
}
|
||||
nav a {
|
||||
display: block;
|
||||
padding: 12px;
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
border-radius: 5px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
nav a:hover {
|
||||
background: rgba(0,0,0,0.05);
|
||||
}
|
||||
nav a.active {
|
||||
background: rgba(0,0,0,0.25);
|
||||
}
|
||||
.logo {
|
||||
font-size: 1.4rem; font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header class="main-header">
|
||||
<div class="logo"><?= $this->getBlock('header_title') ?></div>
|
||||
<div class="header-actions">
|
||||
<?= $this->getBlock('header_actions') ?>
|
||||
</div>
|
||||
</header>
|
||||
<div class="main-container">
|
||||
<div class="sidebar">
|
||||
<?= $this->getBlock('sidebar') ?>
|
||||
</div>
|
||||
<div class="content">
|
||||
<?= $this->getBlock('content') ?>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
function toggleTheme() { fetch('?service=toggle_theme').then(() => location.reload()); }
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace MVC\Model;
|
||||
|
||||
use MVC\Core\Model;
|
||||
|
||||
/**
|
||||
* Model für die Tabelle 'messungen'
|
||||
* Verfügbare Spalten: 'id', 'ts', 'aussentemp', 'vorlauf_ist', 'vorlauf_soll', 'kessel_oben', 'kessel_unten', 'wohnung', 'abgas', 'stellung', 'stellung_proz', 'mischeron', 'abweichung', 'neigung', 'rtsoll', 'misch_begin', 'nachtabs'
|
||||
*/
|
||||
class Messungen extends Model {
|
||||
protected static $table = "messungen";
|
||||
|
||||
// Hier kannst du spezifische Methoden für dieses Model hinzufügen
|
||||
|
||||
/**
|
||||
* Beispiel: Suche nach einer spezifischen Spalte
|
||||
*/
|
||||
public static function getByFirstColumn($value) {
|
||||
return self::where("id = ?", $value);
|
||||
}
|
||||
|
||||
public static function getAbgasByDay($day) {
|
||||
$sql = "SELECT ts, abgas FROM " . self::$table . " WHERE ts LIKE '$day%' ORDER BY ts ASC";
|
||||
return self::query($sql)->fetch_all(MYSQLI_ASSOC);
|
||||
}
|
||||
|
||||
public static function getVorlaufByDay($day) {
|
||||
$sql = "SELECT ts, vorlauf_ist, vorlauf_soll FROM " . self::$table . " WHERE ts LIKE '$day%' ORDER BY ts ASC";
|
||||
return self::query($sql)->fetch_all(MYSQLI_ASSOC);
|
||||
}
|
||||
|
||||
public static function getPufferByDay($day) {
|
||||
$sql = "SELECT ts, kessel_oben, kessel_unten FROM " . self::$table . " WHERE ts LIKE '$day%' ORDER BY ts ASC";
|
||||
return self::query($sql)->fetch_all(MYSQLI_ASSOC);
|
||||
}
|
||||
|
||||
public static function getAussentempByDay($day) {
|
||||
$sql = "SELECT ts, aussentemp FROM " . self::$table . " WHERE ts LIKE '$day%' ORDER BY ts ASC";
|
||||
return self::query($sql)->fetch_all(MYSQLI_ASSOC);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @var array $array
|
||||
* @var string $prevDay
|
||||
* @var string $nextDay
|
||||
* @var string $day
|
||||
* @var string $title
|
||||
* @var string $xtitle
|
||||
* @var string $ytitle
|
||||
* @var string $labels
|
||||
* @var string $abgas
|
||||
*/
|
||||
|
||||
?>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-zoom"></script>
|
||||
|
||||
<div style="height:800px;">
|
||||
<canvas id="logChart"></canvas>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const ctx = document.getElementById('logChart').getContext('2d');
|
||||
|
||||
const logChart = new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: <?php echo json_encode($labels); ?>,
|
||||
|
||||
datasets: [{
|
||||
label: 'Abgas',
|
||||
|
||||
data: <?php echo json_encode($abgas); ?>,
|
||||
|
||||
borderColor: 'rgba(75, 192, 192, 1)',
|
||||
backgroundColor: 'rgba(75, 192, 192, 0.2)',
|
||||
|
||||
fill: true,
|
||||
tension: 0.1
|
||||
}]
|
||||
},
|
||||
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
|
||||
plugins: {
|
||||
title: {
|
||||
display: true,
|
||||
text: '<?= $title ?>'
|
||||
},
|
||||
|
||||
legend: {
|
||||
display: true,
|
||||
position: 'top'
|
||||
},
|
||||
|
||||
zoom: {
|
||||
pan: {
|
||||
enabled: true,
|
||||
mode: 'x'
|
||||
},
|
||||
|
||||
zoom: {
|
||||
wheel: {
|
||||
enabled: true
|
||||
},
|
||||
|
||||
pinch: {
|
||||
enabled: true
|
||||
},
|
||||
|
||||
mode: 'x'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
interaction: {
|
||||
mode: 'index',
|
||||
intersect: false
|
||||
},
|
||||
|
||||
scales: {
|
||||
x: {
|
||||
title: {
|
||||
display: true,
|
||||
text: '<?= $xtitle ?>'
|
||||
}
|
||||
},
|
||||
|
||||
y: {
|
||||
min: 0,
|
||||
max: 600,
|
||||
|
||||
title: {
|
||||
display: true,
|
||||
text: '<?= $ytitle ?>'
|
||||
},
|
||||
|
||||
ticks: {
|
||||
stepSize: 20
|
||||
},
|
||||
|
||||
beginAtZero: true
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<div style="margin-bottom:20px;">
|
||||
|
||||
<a href="?service=abgas&day=<?php echo $prevDay; ?>">
|
||||
← Vorheriger Tag
|
||||
</a>
|
||||
|
||||
<strong style="margin:0 20px;">
|
||||
<?php echo $day; ?>
|
||||
</strong>
|
||||
|
||||
<a href="?service=abgas&day=<?php echo $nextDay; ?>">
|
||||
Nächster Tag →
|
||||
</a>
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,126 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @var array $array
|
||||
* @var string $prevDay
|
||||
* @var string $nextDay
|
||||
* @var string $day
|
||||
* @var string $title
|
||||
* @var string $xtitle
|
||||
* @var string $ytitle
|
||||
* @var string $labels
|
||||
* @var string $aussentemp
|
||||
*/
|
||||
|
||||
?>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-zoom"></script>
|
||||
|
||||
<div style="height:800px;">
|
||||
<canvas id="logChart"></canvas>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const ctx = document.getElementById('logChart').getContext('2d');
|
||||
|
||||
const logChart = new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: <?php echo json_encode($labels); ?>,
|
||||
|
||||
datasets: [{
|
||||
label: 'Aussentemperatur',
|
||||
|
||||
data: <?php echo json_encode($aussentemp); ?>,
|
||||
|
||||
borderColor: 'rgba(75, 192, 192, 1)',
|
||||
backgroundColor: 'rgba(75, 192, 192, 0.2)',
|
||||
|
||||
fill: true,
|
||||
tension: 0.1
|
||||
}]
|
||||
},
|
||||
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
|
||||
plugins: {
|
||||
title: {
|
||||
display: true,
|
||||
text: '<?= $title ?>'
|
||||
},
|
||||
|
||||
legend: {
|
||||
display: true,
|
||||
position: 'top'
|
||||
},
|
||||
|
||||
zoom: {
|
||||
pan: {
|
||||
enabled: true,
|
||||
mode: 'x'
|
||||
},
|
||||
|
||||
zoom: {
|
||||
wheel: {
|
||||
enabled: true
|
||||
},
|
||||
|
||||
pinch: {
|
||||
enabled: true
|
||||
},
|
||||
|
||||
mode: 'x'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
interaction: {
|
||||
mode: 'index',
|
||||
intersect: false
|
||||
},
|
||||
|
||||
scales: {
|
||||
x: {
|
||||
title: {
|
||||
display: true,
|
||||
text: '<?= $xtitle ?>'
|
||||
}
|
||||
},
|
||||
|
||||
y: {
|
||||
min: 0,
|
||||
max: 50,
|
||||
|
||||
title: {
|
||||
display: true,
|
||||
text: '<?= $ytitle ?>'
|
||||
},
|
||||
|
||||
ticks: {
|
||||
stepSize: 20
|
||||
},
|
||||
|
||||
beginAtZero: true
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<div style="margin-bottom:20px;">
|
||||
|
||||
<a href="?service=aussentemp&day=<?php echo $prevDay; ?>">
|
||||
← Vorheriger Tag
|
||||
</a>
|
||||
|
||||
<strong style="margin:0 20px;">
|
||||
<?php echo $day; ?>
|
||||
</strong>
|
||||
|
||||
<a href="?service=aussentemp&day=<?php echo $nextDay; ?>">
|
||||
Nächster Tag →
|
||||
</a>
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,127 @@
|
||||
<div class="docs-container">
|
||||
<h1>🏛️ Framework Architektur & Dokumentation</h1>
|
||||
|
||||
<div class="toc">
|
||||
<h3>Inhalt</h3>
|
||||
<ul>
|
||||
<li><a href="#intro">1. Einführung</a></li>
|
||||
<li><a href="#files">2. Datei-Referenz (Deep Dive)</a></li>
|
||||
<li><a href="#api">3. API-System</a></li>
|
||||
<li><a href="#database">4. Datenbank & Models</a></li>
|
||||
<li><a href="#classes">5. Helper Klassen</a></li>
|
||||
<li><a href="#generators">6. CLI-Generatoren</a></li>
|
||||
<li><a href="#best-practices">7. Best Practices</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<section id="intro">
|
||||
<h2>1. Einführung</h2>
|
||||
<p>Dieses Framework basiert auf dem <strong>Model-View-Controller (MVC)</strong> Entwurfsmuster und nutzt einen <strong>Front Controller</strong> (index.php). Alle Anfragen werden zentral verarbeitet, was globale Middleware (wie Authentifizierung) und ein einheitliches Layout ermöglicht.</p>
|
||||
</section>
|
||||
|
||||
<section id="files">
|
||||
<h2>2. Datei-Referenz (Deep Dive)</h2>
|
||||
<h3>Framework Core</h3>
|
||||
<ul>
|
||||
<li><strong>Router.php:</strong> Verwaltet die Routen. Unterstützt Middlewares. Das Dispatching erfolgt über den <code>service</code> Parameter in der URL.</li>
|
||||
<li><strong>Controller.php:</strong> Basisklasse für alle Controller. Bietet <code>render()</code> für Views und <code>json()</code> für API-Responses.</li>
|
||||
<li><strong>Model.php:</strong> Abstrakte Basis für Datenbank-Entitäten. Kapselt die <code>databaseMethods.php</code> in ein objektorientiertes Interface.</li>
|
||||
<li><strong>View.php:</strong> Behandelt das Extrahieren von Daten in HTML-Templates.</li>
|
||||
</ul>
|
||||
<h3>Konfiguration</h3>
|
||||
<ul>
|
||||
<li><strong>env.ini:</strong> Speichert Datenbank-Zugangsdaten für <code>dev</code> und <code>live</code> Umgebungen. <strong>Wichtig:</strong> Niemals in Git committen!</li>
|
||||
<li><strong>autoloader.php:</strong> Registriert einen PSR-4 ähnlichen Autoloader für den <code>MVC\</code> Namespace.</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section id="api">
|
||||
<h2>3. API-System</h2>
|
||||
<p>APIs liegen im Verzeichnis <code>WEBROOT/api/v1/</code>. Sie nutzen die <code>ApiController</code>-Klasse.</p>
|
||||
<pre>
|
||||
// Beispiel: WEBROOT/api/v1/get.php
|
||||
use MVC\Classes\Api;
|
||||
use MVC\Controller\ApiController;
|
||||
|
||||
Api::jsonResponse((new ApiController())->get());
|
||||
</pre>
|
||||
<p>Die Klasse <code>MVC\Classes\Api</code> stellt die Methode <code>jsonResponse($data, $status)</code> bereit, die automatisch die korrekten Header setzt und die Antwort einheitlich formatiert.</p>
|
||||
</section>
|
||||
|
||||
<section id="database">
|
||||
<h2>4. Datenbank & Models</h2>
|
||||
<p>Das Framework nutzt <code>mysqli</code> mit Prepared Statements für maximale Sicherheit.</p>
|
||||
<h3>databaseMethods.php (Die Power-Tools)</h3>
|
||||
<p>Diese Datei enthält prozedurale Funktionen für alle CRUD-Operationen:</p>
|
||||
<ul>
|
||||
<li><code>DatabaseShow($table, $columns, $where, ...$values)</code></li>
|
||||
<li><code>DatabaseInsert($table, $columns, ...$values)</code></li>
|
||||
<li><code>DatabaseUpdate($table, $set, $where, ...$values)</code></li>
|
||||
<li><code>DatabaseDelete($table, $where, ...$values)</code></li>
|
||||
<li><code>DatabaseShowWithFK($table, $fkMap, ...)</code>: Ermöglicht das automatische Auflösen von Fremdschlüsseln (Joins ohne SQL-Schreiben).</li>
|
||||
</ul>
|
||||
<h3>Models</h3>
|
||||
<p>Models vereinfachen den Zugriff. Beispiel:</p>
|
||||
<pre>
|
||||
$user = User::find(1); // Holt User mit ID 1
|
||||
$admins = User::where("role = ?", "admin");
|
||||
</pre>
|
||||
</section>
|
||||
|
||||
<section id="classes">
|
||||
<h2>5. Helper Klassen (MVC\Classes)</h2>
|
||||
<p>Nützliche Helfer, die in jedem Controller verfügbar sind:</p>
|
||||
<ul>
|
||||
<li><strong>Request:</strong> Zugriff auf <code>method()</code>, <code>queryParams()</code>, <code>headers()</code> und den <code>body()</code>.</li>
|
||||
<li><strong>Client:</strong> Ermittelt <code>ip()</code>, <code>userAgent()</code> und sogar das <code>country()</code> via IP-API.</li>
|
||||
<li><strong>Server:</strong> Informationen über den Host, Ports und Pfade.</li>
|
||||
<li><strong>Cookie:</strong> Einfaches Interface zum <code>set()</code>, <code>read()</code> und <code>Delete()</code> von Cookies.</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section id="generators">
|
||||
<h2>6. CLI-Generatoren</h2>
|
||||
<p>Diese Scripte beschleunigen die Entwicklung massiv:</p>
|
||||
<h3>create_module.php</h3>
|
||||
<p>Erstellt ein komplettes Feature-Bundle bestehend aus einem Controller und einer View. Registriert danach den Service in der <code>index.php</code>.</p>
|
||||
<h3>create_model.php</h3>
|
||||
<p>Generiert eine Model-Klasse basierend auf einer vorhandenen Datenbank-Tabelle. Analysiert die Spalten und erstellt entsprechende PHP-Kommentare für die IDE.</p>
|
||||
</section>
|
||||
|
||||
<section id="best-practices">
|
||||
<h2>7. Best Practices</h2>
|
||||
<div class="bp-grid">
|
||||
<div class="bp-card">
|
||||
<h4>Naming</h4>
|
||||
<p>Controller immer mit <code>Controller</code>-Suffix (z.B. <code>UserController</code>). Models im Singular (z.B. <code>User</code>).</p>
|
||||
</div>
|
||||
<div class="bp-card">
|
||||
<h4>Logic Placement</h4>
|
||||
<p>Halte Controller "schlank". Komplexe SQL-Logik oder Berechnungen gehören in das jeweilige Model.</p>
|
||||
</div>
|
||||
<div class="bp-card">
|
||||
<h4>Security</h4>
|
||||
<p>Nutze <code>['auth']</code> Middleware konsequent für alle internen Seiten. Verwende niemals <code>$_GET</code> oder <code>$_POST</code> direkt, sondern die <code>Request</code>-Klasse.</p>
|
||||
</div>
|
||||
<div class="bp-card">
|
||||
<h4>API First</h4>
|
||||
<p>Wenn du Daten für das Frontend bereitstellst, nutze den <code>ApiController</code>. So bleibt die Geschäftslogik vom HTML getrennt.</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.docs-container { max-width: 1000px; color: var(--text); }
|
||||
.toc { background: var(--sidebar); padding: 20px; border-radius: 8px; margin-bottom: 30px; border: 1px solid var(--border); }
|
||||
.toc h3 { margin-top: 0; }
|
||||
section { margin-bottom: 50px; padding-bottom: 20px; border-bottom: 1px solid var(--border); }
|
||||
h2 { color: var(--accent); font-size: 1.8rem; margin-bottom: 20px; }
|
||||
h3 { color: var(--text); opacity: 0.9; }
|
||||
pre { background: #1e1e1e; color: #d4d4d4; padding: 15px; border-radius: 5px; overflow-x: auto; border: 1px solid #333; font-size: 0.9rem; }
|
||||
.bp-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-top: 20px; }
|
||||
.bp-card { background: var(--sidebar); padding: 20px; border-radius: 8px; border: 1px solid var(--border); }
|
||||
.bp-card h4 { margin-top: 0; color: var(--accent); }
|
||||
.bp-card p { font-size: 0.9rem; margin-bottom: 0; }
|
||||
code { background: var(--sidebar); padding: 2px 5px; border-radius: 3px; font-family: monospace; }
|
||||
</style>
|
||||
@@ -0,0 +1,2 @@
|
||||
<h1>Dashboard</h1>
|
||||
<p>Willkommen in deinem neuen MVC-System mit integriertem Header.</p>
|
||||
@@ -0,0 +1,60 @@
|
||||
<style>
|
||||
.login-container {
|
||||
max-width: 400px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
background: var(--sidebar);
|
||||
}
|
||||
.login-container h2 {
|
||||
text-align: center;
|
||||
margin-top: 0;
|
||||
}
|
||||
.login-container input {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
margin: 10px 0;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 4px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.login-container button {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
background: var(--header);
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.login-container button:hover {
|
||||
opacity: 0.9;
|
||||
}
|
||||
.error-msg {
|
||||
color: #e74c3c;
|
||||
background: rgba(231, 76, 60, 0.1);
|
||||
padding: 10px;
|
||||
border-radius: 4px;
|
||||
margin-bottom: 15px;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="login-container">
|
||||
<h2>🔑 Login</h2>
|
||||
<?php if (isset($error)): ?>
|
||||
<div class="error-msg"><?= $error ?></div>
|
||||
<?php endif; ?>
|
||||
<form method="POST">
|
||||
<div>
|
||||
<label>Benutzername</label>
|
||||
<input type="text" name="username" required autofocus placeholder="Admin / User">
|
||||
</div>
|
||||
<div>
|
||||
<label>Passwort</label>
|
||||
<input type="password" name="password" required placeholder="********">
|
||||
</div>
|
||||
<button type="submit">Anmelden</button>
|
||||
</form>
|
||||
</div>
|
||||
@@ -0,0 +1,116 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @var array $array
|
||||
* @var string $prevDay
|
||||
* @var string $nextDay
|
||||
* @var string $day
|
||||
* @var string $title
|
||||
* @var string $xtitle
|
||||
* @var string $ytitle
|
||||
* @var string $labels
|
||||
* @var string $pufferOben
|
||||
* @var string $pufferUnten
|
||||
*/
|
||||
?>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-zoom"></script>
|
||||
|
||||
<div style="height:800px;">
|
||||
<canvas id="logChart"></canvas>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const ctx = document.getElementById('logChart').getContext('2d');
|
||||
|
||||
new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: <?php echo json_encode($labels); ?>,
|
||||
|
||||
datasets: [
|
||||
{
|
||||
label: 'Puffer Oben',
|
||||
data: <?php echo json_encode($pufferOben); ?>,
|
||||
borderColor: 'rgba(54, 162, 235, 1)',
|
||||
backgroundColor: 'rgba(54, 162, 235, 0.2)',
|
||||
tension: 0.2,
|
||||
fill: false
|
||||
},
|
||||
{
|
||||
label: 'Puffer Unten',
|
||||
data: <?php echo json_encode($pufferUnten); ?>,
|
||||
borderColor: 'rgba(255, 99, 132, 1)',
|
||||
backgroundColor: 'rgba(255, 99, 132, 0.2)',
|
||||
tension: 0.2,
|
||||
fill: false
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
|
||||
plugins: {
|
||||
title: {
|
||||
display: true,
|
||||
text: '<?= $title ?>'
|
||||
},
|
||||
|
||||
legend: {
|
||||
display: true,
|
||||
position: 'top'
|
||||
},
|
||||
|
||||
zoom: {
|
||||
pan: {
|
||||
enabled: true,
|
||||
mode: 'x'
|
||||
},
|
||||
zoom: {
|
||||
wheel: {
|
||||
enabled: true
|
||||
},
|
||||
pinch: {
|
||||
enabled: true
|
||||
},
|
||||
mode: 'x'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
interaction: {
|
||||
mode: 'index',
|
||||
intersect: false
|
||||
},
|
||||
|
||||
scales: {
|
||||
x: {
|
||||
title: {
|
||||
display: true,
|
||||
text: '<?= $xtitle ?>'
|
||||
}
|
||||
},
|
||||
y: {
|
||||
title: {
|
||||
display: true,
|
||||
text: '<?= $ytitle ?>'
|
||||
},
|
||||
beginAtZero: false
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<div style="margin-bottom:20px;">
|
||||
<a href="?service=puffer&day=<?php echo $prevDay; ?>">← Vorheriger Tag</a>
|
||||
|
||||
<strong style="margin:0 20px;">
|
||||
<?php echo $day; ?>
|
||||
</strong>
|
||||
|
||||
<a href="?service=puffer&day=<?php echo $nextDay; ?>">Nächster Tag →</a>
|
||||
</div>
|
||||
@@ -0,0 +1,116 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @var array $array
|
||||
* @var string $prevDay
|
||||
* @var string $nextDay
|
||||
* @var string $day
|
||||
* @var string $title
|
||||
* @var string $xtitle
|
||||
* @var string $ytitle
|
||||
* @var string $labels
|
||||
* @var string $vorlaufIst
|
||||
* @var string $vorlaufSoll
|
||||
*/
|
||||
?>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-zoom"></script>
|
||||
|
||||
<div style="height:800px;">
|
||||
<canvas id="logChart"></canvas>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const ctx = document.getElementById('logChart').getContext('2d');
|
||||
|
||||
new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: <?php echo json_encode($labels); ?>,
|
||||
|
||||
datasets: [
|
||||
{
|
||||
label: 'Vorlauf IST',
|
||||
data: <?php echo json_encode($vorlaufIst); ?>,
|
||||
borderColor: 'rgba(54, 162, 235, 1)',
|
||||
backgroundColor: 'rgba(54, 162, 235, 0.2)',
|
||||
tension: 0.2,
|
||||
fill: false
|
||||
},
|
||||
{
|
||||
label: 'Vorlauf SOLL',
|
||||
data: <?php echo json_encode($vorlaufSoll); ?>,
|
||||
borderColor: 'rgba(255, 99, 132, 1)',
|
||||
backgroundColor: 'rgba(255, 99, 132, 0.2)',
|
||||
tension: 0.2,
|
||||
fill: false
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
|
||||
plugins: {
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Vorlauf IST vs SOLL'
|
||||
},
|
||||
|
||||
legend: {
|
||||
display: true,
|
||||
position: 'top'
|
||||
},
|
||||
|
||||
zoom: {
|
||||
pan: {
|
||||
enabled: true,
|
||||
mode: 'x'
|
||||
},
|
||||
zoom: {
|
||||
wheel: {
|
||||
enabled: true
|
||||
},
|
||||
pinch: {
|
||||
enabled: true
|
||||
},
|
||||
mode: 'x'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
interaction: {
|
||||
mode: 'index',
|
||||
intersect: false
|
||||
},
|
||||
|
||||
scales: {
|
||||
x: {
|
||||
title: {
|
||||
display: true,
|
||||
text: '<?= $xtitle ?>'
|
||||
}
|
||||
},
|
||||
y: {
|
||||
title: {
|
||||
display: true,
|
||||
text: '<?= $ytitle ?>'
|
||||
},
|
||||
beginAtZero: false
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<div style="margin-bottom:20px;">
|
||||
<a href="?service=vorlauf&day=<?php echo $prevDay; ?>">← Vorheriger Tag</a>
|
||||
|
||||
<strong style="margin:0 20px;">
|
||||
<?php echo $day; ?>
|
||||
</strong>
|
||||
|
||||
<a href="?service=vorlauf&day=<?php echo $nextDay; ?>">Nächster Tag →</a>
|
||||
</div>
|
||||
File renamed without changes.
@@ -0,0 +1,6 @@
|
||||
[database]
|
||||
APP_ENV = "dev"
|
||||
DB_DEV_HOST = "blackpi.ipv64.net"
|
||||
DB_DEV_USERNAME = "worker"
|
||||
DB_DEV_PASSWORD = "bBHofurUJWKzPE8Z"
|
||||
DB_DEV_DATABASE = "HEIZUNG"
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
/**
|
||||
* Ultimate MVC Project Bootstrapper (Fixed Version with Header)
|
||||
* Erstellt ein voll funktionsfähiges Projekt inkl. Dev-Server, Header, DarkMode & freiem Zugriff.
|
||||
* Ultimate MVC Project Bootstrapper (Fixed Version with Header & Auth)
|
||||
* Erstellt ein voll funktionsfähiges Projekt inkl. Dev-Server, Header, DarkMode & Auth-System.
|
||||
*/
|
||||
|
||||
if (php_sapi_name() !== 'cli') {
|
||||
@@ -34,6 +34,7 @@ $dirs = [
|
||||
'WEBROOT/src/utils',
|
||||
'WEBROOT/src/MVC',
|
||||
'WEBROOT/src/MVC/Core',
|
||||
'WEBROOT/src/MVC/Classes',
|
||||
'WEBROOT/src/MVC/Controller',
|
||||
'WEBROOT/src/MVC/Model',
|
||||
'WEBROOT/src/MVC/View',
|
||||
@@ -369,10 +370,16 @@ PHP;
|
||||
$files['WEBROOT/src/config/env.ini'] = <<<INI
|
||||
[database]
|
||||
APP_ENV = "dev"
|
||||
DB_DEV_HOST = "localhost"
|
||||
DB_DEV_USERNAME = "root"
|
||||
|
||||
DB_DEV_HOST = ""
|
||||
DB_DEV_USERNAME = ""
|
||||
DB_DEV_PASSWORD = ""
|
||||
DB_DEV_DATABASE = "mein_projekt"
|
||||
DB_DEV_DATABASE = ""
|
||||
|
||||
DB_LIVE_HOST = ""
|
||||
DB_LIVE_USERNAME = ""
|
||||
DB_LIVE_PASSWORD = ""
|
||||
DB_LIVE_DATABASE = ""
|
||||
INI;
|
||||
|
||||
// --- DB: databaseConnect.php ---
|
||||
@@ -398,6 +405,148 @@ function db_connect() {
|
||||
}
|
||||
}
|
||||
PHP;
|
||||
// -- CLASSES --
|
||||
|
||||
$files['WEBROOT/src/MVC/Classes/Api.php'] = <<<'PHP'
|
||||
<?php
|
||||
|
||||
namespace MVC\Classes;
|
||||
|
||||
class Api {
|
||||
public static function jsonResponse($data, int $statusCode = 200) {
|
||||
header('Content-Type: application/json');
|
||||
http_response_code($statusCode);
|
||||
echo json_encode(
|
||||
[
|
||||
'status' => $statusCode === 200 ? 'success' : 'error',
|
||||
'data' => $data,
|
||||
], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE
|
||||
);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
PHP;
|
||||
|
||||
$files['WEBROOT/src/MVC/Classes/Client.php'] = <<<'PHP'
|
||||
<?php
|
||||
|
||||
namespace MVC\Classes;
|
||||
|
||||
class Client {
|
||||
|
||||
public static function ip() {
|
||||
if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
|
||||
$ipList = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
|
||||
return trim($ipList[0]);
|
||||
} else if (!empty($_SERVER['REMOTE_ADDR'])) {
|
||||
return $_SERVER['REMOTE_ADDR'];
|
||||
} else {
|
||||
return 'UNKNOWN';
|
||||
}
|
||||
}
|
||||
|
||||
public static function port() {
|
||||
return $_SERVER['REMOTE_PORT'] ?? 'UNKNOWN';
|
||||
}
|
||||
|
||||
public static function country() {
|
||||
$response = file_get_contents('http://ip-api.com/json/{' . self::ip() . '}?fields=country,countryCode');
|
||||
$data = json_decode($response);
|
||||
return $data->country ?? 'UNKNOWN';
|
||||
}
|
||||
|
||||
public static function userAgent() {
|
||||
return $_SERVER['HTTP_USER_AGENT'] ?? 'UNKNOWN';
|
||||
}
|
||||
}
|
||||
PHP;
|
||||
|
||||
$files['WEBROOT/src/MVC/Classes/Cookie.php'] = <<<'PHP'
|
||||
<?php
|
||||
|
||||
namespace MVC\Classes;
|
||||
|
||||
class Cookie {
|
||||
public function set(string $CookieName, int $CookieValue, int $CookieTime) {
|
||||
setcookie($CookieName, $CookieValue, time()+($CookieTime*60));
|
||||
}
|
||||
|
||||
public function read(string $CookieName) {
|
||||
if (isset($_COOKIE[$CookieName])) {
|
||||
return $_COOKIE[$CookieName];
|
||||
}
|
||||
return 'Cookie not set';
|
||||
}
|
||||
|
||||
public function Delete(string $CookieName) {
|
||||
setcookie($CookieName, "", time()-(3600*24));
|
||||
}
|
||||
}
|
||||
PHP;
|
||||
|
||||
$files['WEBROOT/src/MVC/Classes/Request.php'] = <<<'PHP'
|
||||
<?php
|
||||
|
||||
namespace MVC\Classes;
|
||||
|
||||
class Request {
|
||||
public static function method() {
|
||||
return $_SERVER['REQUEST_METHOD'] ?? 'UNKNOWN';
|
||||
}
|
||||
|
||||
public static function uri() {
|
||||
return $_SERVER['REQUEST_URI'] ?? 'UNKNOWN';
|
||||
}
|
||||
|
||||
public static function headers() {
|
||||
return getallheaders();
|
||||
}
|
||||
|
||||
public static function body() {
|
||||
return file_get_contents('php://input');
|
||||
}
|
||||
|
||||
public static function queryParams() {
|
||||
return $_GET;
|
||||
}
|
||||
|
||||
public static function time() {
|
||||
return $_SERVER['REQUEST_TIME'] ?? 'UNKNOWN';
|
||||
}
|
||||
|
||||
public static function referrer() {
|
||||
return $_SERVER['HTTP_REFERER'] ?? 'UNKNOWN';
|
||||
}
|
||||
}
|
||||
PHP;
|
||||
|
||||
$files['WEBROOT/src/MVC/Classes/Server.php'] = <<<'PHP'
|
||||
<?php
|
||||
|
||||
namespace MVC\Classes;
|
||||
|
||||
class Server {
|
||||
public static function documentRoot() {
|
||||
return $_SERVER['DOCUMENT_ROOT'] ?? 'UNKNOWN';
|
||||
}
|
||||
|
||||
public static function currentDir() {
|
||||
return __DIR__;
|
||||
}
|
||||
|
||||
public static function currentScript() {
|
||||
return $_SERVER['SCRIPT_NAME'] ?? 'UNKNOWN';
|
||||
}
|
||||
|
||||
public static function name() {
|
||||
return $_SERVER['SERVER_NAME'] ?? 'UNKNOWN';
|
||||
}
|
||||
|
||||
public static function port() {
|
||||
return $_SERVER['SERVER_PORT'] ?? 'UNKNOWN';
|
||||
}
|
||||
}
|
||||
PHP;
|
||||
|
||||
// --- CORE ---
|
||||
$files['WEBROOT/src/MVC/Core/Controller.php'] = <<<'PHP'
|
||||
@@ -581,7 +730,7 @@ class Router {
|
||||
|
||||
if ($middleware === 'auth') {
|
||||
if (empty($_SESSION['user_logged_in'])) {
|
||||
header('Location: login.php');
|
||||
header('Location: ?service=login');
|
||||
exit;
|
||||
}
|
||||
}
|
||||
@@ -666,6 +815,7 @@ $files['WEBROOT/src/MVC/Layout/Templates/main.php'] = <<<'HTML'
|
||||
.btn-toggle:hover { background: rgba(255,255,255,0.1); }
|
||||
nav a { display: block; padding: 12px; text-decoration: none; color: inherit; border-radius: 5px; margin-bottom: 5px; }
|
||||
nav a:hover { background: rgba(0,0,0,0.05); }
|
||||
nav a.active { background: rgba(0,0,0,0.1); }
|
||||
.logo { font-size: 1.4rem; font-weight: bold; }
|
||||
</style>
|
||||
</head>
|
||||
@@ -692,10 +842,31 @@ $files['WEBROOT/src/MVC/Layout/Templates/main.php'] = <<<'HTML'
|
||||
HTML;
|
||||
|
||||
// --- CONTROLLERS ---
|
||||
$files['WEBROOT/src/MVC/Controller/ApiController.php'] = <<<'PHP'
|
||||
<?php
|
||||
|
||||
namespace MVC\Controller;
|
||||
|
||||
use MVC\Core\Controller;
|
||||
use MVC\Classes\Api;
|
||||
|
||||
class ApiController extends Controller {
|
||||
public static function get(){
|
||||
return Api::jsonResponse([
|
||||
'data' => 'DummyData',
|
||||
]);
|
||||
}
|
||||
}
|
||||
PHP;
|
||||
|
||||
$files['WEBROOT/src/MVC/Controller/HomeController.php'] = <<<'PHP'
|
||||
<?php
|
||||
namespace MVC\Controller;
|
||||
use MVC\Core\Controller;
|
||||
use MVC\Classes\Client;
|
||||
use MVC\Classes\Cookie;
|
||||
use MVC\Classes\Request;
|
||||
use MVC\Classes\Server;
|
||||
class HomeController extends Controller {
|
||||
|
||||
public function index() {
|
||||
@@ -714,10 +885,75 @@ class HomeController extends Controller {
|
||||
}
|
||||
PHP;
|
||||
|
||||
$files['WEBROOT/src/MVC/Controller/AuthController.php'] = <<<'PHP'
|
||||
<?php
|
||||
|
||||
namespace MVC\Controller;
|
||||
|
||||
use MVC\Core\Controller;
|
||||
|
||||
class AuthController extends Controller {
|
||||
public function login() {
|
||||
if (isset($_SESSION['user_logged_in'])) {
|
||||
header('Location: ?service=home');
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$username = $_POST['username'] ?? '';
|
||||
$password = $_POST['password'] ?? '';
|
||||
|
||||
// Hardcoded logins
|
||||
$users = [
|
||||
'admin' => 'password123',
|
||||
'user' => 'user123'
|
||||
];
|
||||
|
||||
if (isset($users[$username]) && $users[$username] === $password) {
|
||||
$_SESSION['user_logged_in'] = true;
|
||||
$_SESSION['username'] = $username;
|
||||
header('Location: ?service=home');
|
||||
exit;
|
||||
} else {
|
||||
return $this->render('login', ['error' => 'Ungültige Anmeldedaten']);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->render('login');
|
||||
}
|
||||
|
||||
public function logout() {
|
||||
session_destroy();
|
||||
header('Location: ?service=login');
|
||||
exit;
|
||||
}
|
||||
}
|
||||
PHP;
|
||||
|
||||
$files['WEBROOT/src/MVC/Controller/DocsController.php'] = <<<'PHP'
|
||||
<?php
|
||||
|
||||
namespace MVC\Controller;
|
||||
|
||||
use MVC\Core\Controller;
|
||||
|
||||
class DocsController extends Controller {
|
||||
public function index() {
|
||||
return $this->render('docs', [
|
||||
'title' => '📚 System-Dokumentation'
|
||||
]);
|
||||
}
|
||||
}
|
||||
PHP;
|
||||
|
||||
$files['WEBROOT/src/MVC/Controller/TestController.php'] = <<<'PHP'
|
||||
<?php
|
||||
namespace MVC\Controller;
|
||||
use MVC\Core\Controller;
|
||||
use MVC\Classes\Client;
|
||||
use MVC\Classes\Cookie;
|
||||
use MVC\Classes\Request;
|
||||
use MVC\Classes\Server;
|
||||
class TestController extends Controller {
|
||||
|
||||
public function service1() {
|
||||
@@ -744,13 +980,151 @@ class TestController extends Controller {
|
||||
}
|
||||
PHP;
|
||||
|
||||
// --- API ---
|
||||
$files['WEBROOT/api/v1/get.php'] = <<<'PHP'
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
|
||||
require_once __DIR__ . '/../../src/MVC/autoloader.php';
|
||||
|
||||
use MVC\Controller\ApiController;
|
||||
|
||||
$api = (new ApiController());
|
||||
|
||||
try {
|
||||
echo ($api->get());
|
||||
} catch (\Exception $e) {
|
||||
echo ($e->getMessage());
|
||||
}
|
||||
PHP;
|
||||
|
||||
|
||||
// --- VIEWS ---
|
||||
$files['WEBROOT/src/MVC/View/home.php'] = "<h1>Dashboard</h1><p>Willkommen in deinem neuen MVC-System mit integriertem Header.</p>";
|
||||
$files['WEBROOT/src/MVC/View/test1.php'] = "<h1>Service 1</h1><p><?= \$msg ?></p>";
|
||||
$files['WEBROOT/src/MVC/View/test2.php'] = "<h1>System Check</h1><ul><?php foreach(\$data as \$k => \$v): ?><li><b><?= \$k ?>:</b> <?= \$v ?></li><?php endforeach; ?></ul>";
|
||||
|
||||
// --- API ---
|
||||
$files['WEBROOT/api/v1/get.php'] = "<?php header('Content-Type: application/json'); echo json_encode(['status' => 'online']);";
|
||||
$files['WEBROOT/src/MVC/View/docs.php'] = <<<'HTML'
|
||||
<div class="docs-container">
|
||||
<h1>🏛️ Framework Architektur & Dokumentation</h1>
|
||||
|
||||
<div class="toc">
|
||||
<h3>Inhalt</h3>
|
||||
<ul>
|
||||
<li><a href="#intro">1. Einführung</a></li>
|
||||
<li><a href="#files">2. Datei-Referenz (Deep Dive)</a></li>
|
||||
<li><a href="#api">3. API-System</a></li>
|
||||
<li><a href="#database">4. Datenbank & Models</a></li>
|
||||
<li><a href="#classes">5. Helper Klassen</a></li>
|
||||
<li><a href="#generators">6. CLI-Generatoren</a></li>
|
||||
<li><a href="#best-practices">7. Best Practices</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<section id="intro">
|
||||
<h2>1. Einführung</h2>
|
||||
<p>Dieses Framework basiert auf dem <strong>Model-View-Controller (MVC)</strong> Entwurfsmuster und nutzt einen <strong>Front Controller</strong> (index.php). Alle Anfragen werden zentral verarbeitet, was globale Middleware (wie Authentifizierung) und ein einheitliches Layout ermöglicht.</p>
|
||||
</section>
|
||||
|
||||
<section id="files">
|
||||
<h2>2. Datei-Referenz (Deep Dive)</h2>
|
||||
<h3>Framework Core</h3>
|
||||
<ul>
|
||||
<li><strong>Router.php:</strong> Verwaltet die Routen. Unterstützt Middlewares. Das Dispatching erfolgt über den <code>service</code> Parameter in der URL.</li>
|
||||
<li><strong>Controller.php:</strong> Basisklasse für alle Controller. Bietet <code>render()</code> für Views und <code>json()</code> für API-Responses.</li>
|
||||
<li><strong>Model.php:</strong> Abstrakte Basis für Datenbank-Entitäten. Kapselt die <code>databaseMethods.php</code> in ein objektorientiertes Interface.</li>
|
||||
<li><strong>View.php:</strong> Behandelt das Extrahieren von Daten in HTML-Templates.</li>
|
||||
</ul>
|
||||
<h3>Konfiguration</h3>
|
||||
<ul>
|
||||
<li><strong>env.ini:</strong> Speichert Datenbank-Zugangsdaten für <code>dev</code> und <code>live</code> Umgebungen.</li>
|
||||
<li><strong>autoloader.php:</strong> Registriert einen PSR-4 ähnlichen Autoloader für den <code>MVC\</code> Namespace.</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section id="api">
|
||||
<h2>3. API-System</h2>
|
||||
<p>APIs liegen im Verzeichnis <code>WEBROOT/api/v1/</code>. Sie nutzen die <code>ApiController</code>-Klasse.</p>
|
||||
<pre>
|
||||
// Beispiel: WEBROOT/api/v1/get.php
|
||||
use MVC\Classes\Api;
|
||||
use MVC\Controller\ApiController;
|
||||
|
||||
Api::jsonResponse((new ApiController())->get());
|
||||
</pre>
|
||||
</section>
|
||||
|
||||
<section id="database">
|
||||
<h2>4. Datenbank & Models</h2>
|
||||
<p>Das Framework nutzt <code>mysqli</code> mit Prepared Statements für maximale Sicherheit.</p>
|
||||
<h3>databaseMethods.php (Die Power-Tools)</h3>
|
||||
<ul>
|
||||
<li><code>DatabaseShow($table, $columns, $where, ...$values)</code></li>
|
||||
<li><code>DatabaseInsert($table, $columns, ...$values)</code></li>
|
||||
<li><code>DatabaseUpdate($table, $set, $where, ...$values)</code></li>
|
||||
<li><code>DatabaseDelete($table, $where, ...$values)</code></li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section id="classes">
|
||||
<h2>5. Helper Klassen (MVC\Classes)</h2>
|
||||
<ul>
|
||||
<li><strong>Request:</strong> Zugriff auf <code>method()</code>, <code>queryParams()</code>, <code>headers()</code>.</li>
|
||||
<li><strong>Client:</strong> Ermittelt <code>ip()</code>, <code>userAgent()</code>, <code>country()</code>.</li>
|
||||
<li><strong>Cookie:</strong> Interface zum <code>set()</code>, <code>read()</code>, <code>Delete()</code> von Cookies.</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section id="generators">
|
||||
<h2>6. CLI-Generatoren</h2>
|
||||
<p><code>php create_module.php [Name]</code> - Erstellt Controller & View.</p>
|
||||
<p><code>php create_model.php [Tabelle] [Spalten]</code> - Erstellt ein Model.</p>
|
||||
</section>
|
||||
|
||||
<section id="best-practices">
|
||||
<h2>7. Best Practices</h2>
|
||||
<p><strong>Naming:</strong> Controller immer mit <code>Controller</code>-Suffix. Models im Singular.</p>
|
||||
<p><strong>Security:</strong> Nutze <code>['auth']</code> Middleware konsequent für alle internen Seiten.</p>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.docs-container { max-width: 1000px; color: var(--text); }
|
||||
.toc { background: var(--sidebar); padding: 20px; border-radius: 8px; margin-bottom: 30px; border: 1px solid var(--border); }
|
||||
.toc h3 { margin-top: 0; }
|
||||
section { margin-bottom: 50px; padding-bottom: 20px; border-bottom: 1px solid var(--border); }
|
||||
h2 { color: var(--accent); font-size: 1.8rem; margin-bottom: 20px; }
|
||||
pre { background: #1e1e1e; color: #d4d4d4; padding: 15px; border-radius: 5px; overflow-x: auto; border: 1px solid #333; font-size: 0.9rem; }
|
||||
</style>
|
||||
HTML;
|
||||
|
||||
$files['WEBROOT/src/MVC/View/login.php'] = <<<'HTML'
|
||||
<style>
|
||||
.login-container { max-width: 400px; margin: 50px auto; padding: 30px; border: 1px solid var(--border); border-radius: 8px; background: var(--sidebar); box-shadow: 0 4px 15px rgba(0,0,0,0.1); }
|
||||
.login-container h2 { text-align: center; margin-top: 0; color: var(--text); }
|
||||
.login-container input { width: 100%; padding: 12px; margin: 10px 0; border: 1px solid var(--border); border-radius: 4px; box-sizing: border-box; background: var(--bg); color: var(--text); }
|
||||
.login-container button { width: 100%; padding: 12px; background: var(--header); color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 1rem; font-weight: bold; }
|
||||
.login-container button:hover { opacity: 0.9; }
|
||||
.error-msg { color: #e74c3c; background: rgba(231, 76, 60, 0.1); padding: 10px; border-radius: 4px; margin-bottom: 15px; text-align: center; font-size: 0.9rem; }
|
||||
</style>
|
||||
<div class="login-container">
|
||||
<h2>🔑 Login</h2>
|
||||
<?php if (isset($error)): ?>
|
||||
<div class="error-msg"><?= htmlspecialchars($error) ?></div>
|
||||
<?php endif; ?>
|
||||
<form method="POST">
|
||||
<div>
|
||||
<label>Benutzername</label>
|
||||
<input type="text" name="username" required autofocus placeholder="Admin / User">
|
||||
</div>
|
||||
<div>
|
||||
<label>Passwort</label>
|
||||
<input type="password" name="password" required placeholder="********">
|
||||
</div>
|
||||
<button type="submit">Anmelden</button>
|
||||
</form>
|
||||
</div>
|
||||
HTML;
|
||||
|
||||
// --- ENTRY POINT ---
|
||||
$files['WEBROOT/index.php'] = <<<'PHP'
|
||||
@@ -760,31 +1134,62 @@ require_once __DIR__ . '/src/MVC/autoloader.php';
|
||||
$service = $_GET['service'] ?? 'home';
|
||||
try {
|
||||
$router = new \MVC\Core\Router();
|
||||
|
||||
// LOGIN EIN/AUSSCHALTEN: Einfach ['auth'] als 4. Parameter hinzufügen oder entfernen
|
||||
$router->add('home', \MVC\Controller\HomeController::class, 'index');
|
||||
$router->add('toggle_theme', \MVC\Controller\HomeController::class, 'toggle_theme');
|
||||
$router->add('test1', \MVC\Controller\TestController::class, 'service1');
|
||||
$router->add('test2', \MVC\Controller\TestController::class, 'service2');
|
||||
$router->add('docs', \MVC\Controller\DocsController::class, 'index');
|
||||
$router->add('test1', \MVC\Controller\TestController::class, 'service1', ['auth']);
|
||||
$router->add('test2', \MVC\Controller\TestController::class, 'service2', ['auth']);
|
||||
$router->add('login', \MVC\Controller\AuthController::class, 'login');
|
||||
$router->add('logout', \MVC\Controller\AuthController::class, 'logout');
|
||||
|
||||
$layout = new \MVC\Layout\Layout('main');
|
||||
$layout->setBlock('title', 'MVC Starter');
|
||||
$layout->setBlock('header_title', '🚀 MVC Dashboard');
|
||||
$layout->setBlock('header_actions', '<button class="btn-toggle" onclick="toggleTheme()">🌓 Theme umschalten</button>');
|
||||
|
||||
$headerActions = '<button class="btn-toggle" onclick="toggleTheme()">🌓 Theme umschalten</button>';
|
||||
if (isset($_SESSION['user_logged_in'])) {
|
||||
$headerActions = '<span style="margin-right: 15px; font-size: 0.9rem;">👤 ' . htmlspecialchars($_SESSION['username']) . '</span>' .
|
||||
'<a href="?service=logout" class="btn-toggle" style="text-decoration: none; background: rgba(255,255,255,0.2); margin-right: 10px;">🚪 Logout</a> ' .
|
||||
$headerActions;
|
||||
} else {
|
||||
$headerActions = '<a href="?service=login" class="btn-toggle" style="text-decoration: none; background: var(--accent); color: white; margin-right: 10px;">🔑 Login</a> ' .
|
||||
$headerActions;
|
||||
}
|
||||
$layout->setBlock('header_actions', $headerActions);
|
||||
|
||||
// Sidebar Block
|
||||
ob_start();
|
||||
$navItems = [
|
||||
'home' => ['label' => '🏠 Home', 'auth' => false],
|
||||
'test1' => ['label' => '🛠️ Test 1', 'auth' => true],
|
||||
'test2' => ['label' => '📊 Test 2', 'auth' => true],
|
||||
'docs' => ['label' => '📚 Dokumentation', 'auth' => false],
|
||||
];
|
||||
?>
|
||||
<nav>
|
||||
<a href="?service=home">🏠 Home</a>
|
||||
<a href="?service=test1">🛠️ Test 1</a>
|
||||
<a href="?service=test2">📊 Test 2</a>
|
||||
<?php foreach ($navItems as $navKey => $item):
|
||||
if ($item['auth'] && !isset($_SESSION['user_logged_in'])) continue;
|
||||
?>
|
||||
<a href="?service=<?= $navKey ?>" class="<?= $service === $navKey ? 'active' : '' ?>"><?= $item['label'] ?></a>
|
||||
<?php endforeach; ?>
|
||||
|
||||
<?php if (!isset($_SESSION['user_logged_in'])): ?>
|
||||
<div style="margin-top: 20px; padding: 10px; font-size: 0.8rem; opacity: 0.5; border-top: 1px solid var(--border);">
|
||||
🔒 Melden Sie sich an, um alle Funktionen zu sehen.
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</nav>
|
||||
<?php
|
||||
$layout->setBlock('sidebar', ob_get_clean());
|
||||
|
||||
$layout->setBlock('content', $router->dispatch($service));
|
||||
echo $layout->render();
|
||||
} catch (\Exception $e) {
|
||||
http_response_code(404); echo "<h1>404</h1><p>" . $e->getMessage() . "</p>";
|
||||
} catch (\Throwable $e) {
|
||||
http_response_code(500);
|
||||
echo "<h1>Error</h1><p>" . htmlspecialchars($e->getMessage()) . "</p>";
|
||||
if (ini_get('display_errors')) echo "<pre>" . htmlspecialchars($e->getTraceAsString()) . "</pre>";
|
||||
}
|
||||
PHP;
|
||||
|
||||
@@ -909,6 +1314,10 @@ $controllerContent = <<<PHPCTRL
|
||||
namespace MVC\Controller;
|
||||
|
||||
use MVC\Core\Controller;
|
||||
use MVC\Classes\Client;
|
||||
use MVC\Classes\Cookie;
|
||||
use MVC\Classes\Request;
|
||||
use MVC\Classes\Server;
|
||||
// use MVC\Model\YourModel; // Importiere dein Model
|
||||
|
||||
class {$className}Controller extends Controller {
|
||||
@@ -958,11 +1367,9 @@ if (!file_exists($viewFile)) {
|
||||
|
||||
// 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 "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 " Registriere das Modul in WEBROOT/index.php beim Router:\n";
|
||||
echo " \$router->add('{$key}', \\MVC\\Controller\\{$className}Controller::class, '{$key}', ['auth']);\n";
|
||||
echo " (Lösche ['auth'] wenn kein Login erforderlich ist)\n\n";
|
||||
echo "------------------------\n";
|
||||
PHP;
|
||||
|
||||
@@ -973,6 +1380,7 @@ foreach ($files as $file => $content) {
|
||||
echo "📄 Datei erstellt: $file\n";
|
||||
}
|
||||
|
||||
echo "\n✨ Projekt '$projectName' wurde mit HEADER initialisiert!\n";
|
||||
echo "1. Starten: php server.php\n";
|
||||
echo "2. Öffnen: http://localhost:8000\n";
|
||||
echo "\n✨ Projekt '$projectName' wurde initialisiert!\n";
|
||||
echo "1. Richte deine Datenbankverbindung in WEBROOT/src/config/env.ini ein.\n";
|
||||
echo "2. Starten: php server.php\n";
|
||||
echo "3. Öffnen: http://localhost:8000\n";
|
||||
Reference in new issue
Block a user