init
This commit is contained in:
1 parent
6d544c6f5e
commit
6ef6c15942
26 files changed
+1248
No files matched your search
@@ -0,0 +1,19 @@
|
||||
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]
|
||||
@@ -0,0 +1,52 @@
|
||||
{
|
||||
"folders": [
|
||||
{
|
||||
"path": "."
|
||||
}
|
||||
],
|
||||
"settings": {
|
||||
"workbench.colorTheme": "Default Dark Modern",
|
||||
"workbench.colorCustomizations": {
|
||||
"activityBar.background": "#ff000075",
|
||||
"activityBar.foreground": "#000000",
|
||||
"breadcrumb.foreground": "#FFFFFF",
|
||||
},
|
||||
"files.exclude": {
|
||||
"*.git*": true,
|
||||
"WEBROOT/config_backups": true,
|
||||
"WEBROOT/static": true,
|
||||
"WEBROOT/templates": true,
|
||||
},
|
||||
"editor.renderWhitespace": "all",
|
||||
"editor.smoothScrolling": true,
|
||||
"editor.fontSize": 14,
|
||||
"editor.formatOnSave": true,
|
||||
"editor.minimap.enabled": true,
|
||||
"editor.minimap.scale": 2,
|
||||
"editor.minimap.side": "right",
|
||||
"editor.minimap.maxColumn": 100,
|
||||
"editor.minimap.renderCharacters": true,
|
||||
"editor.minimap.showSlider": "always",
|
||||
"files.autoSave": "off",
|
||||
"files.autoSaveDelay": 3000,
|
||||
"window.title": "BACKEND",
|
||||
"workbench.editor.wrapTabs": true,
|
||||
},
|
||||
"extensions": {
|
||||
"recommendations": [
|
||||
"oderwat.indent-rainbow",
|
||||
"pranaygp.vscode-css-peek",
|
||||
"wayou.vscode-todo-highlight",
|
||||
"mrmlnc.vscode-mustache",
|
||||
"fabiospampinato.vscode-highlight",
|
||||
"junstyle.php-cs-fixer",
|
||||
"mtea.gettext-editor",
|
||||
"neilbrayfield.php-docblocker",
|
||||
"bmewburn.vscode-intelephense-client",
|
||||
"mohamed-ali.html-css-class-completion",
|
||||
"rifi2k.format-html-in-php",
|
||||
"mrorz.language-gettext",
|
||||
"voldemortensen.rainbow-tags",
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
|
||||
echo json_encode(
|
||||
[
|
||||
'status' => 'online'
|
||||
]
|
||||
);
|
||||
@@ -0,0 +1,34 @@
|
||||
<?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('abgas', \MVC\Controller\AbgasController::class, 'abgas');
|
||||
$router->add('vorlauf', \MVC\Controller\VorlaufController::class, 'vorlauf');
|
||||
$router->add('puffer', \MVC\Controller\PufferController::class, 'puffer');
|
||||
|
||||
$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=abgas">🔥 Abgas</a>
|
||||
<a href="?service=vorlauf">🏃♂️➡️ Vorlauf</a>
|
||||
<a href="?service=puffer">♨️ Puffer</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>";
|
||||
}
|
||||
@@ -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,19 @@
|
||||
<?php
|
||||
namespace MVC\Controller;
|
||||
use MVC\Core\Controller;
|
||||
class HomeController extends Controller {
|
||||
|
||||
public function index() {
|
||||
return $this->render('home');
|
||||
}
|
||||
|
||||
public function toggle_theme() {
|
||||
$_SESSION['theme'] = ($_SESSION['theme'] ?? 'light') === 'dark' ? 'light' : 'dark';
|
||||
|
||||
return $this->json(
|
||||
[
|
||||
'success' => true
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace MVC\Controller;
|
||||
|
||||
use MVC\Core\Controller;
|
||||
// use MVC\Model\YourModel; // Importiere dein Model
|
||||
|
||||
class PufferController extends Controller {
|
||||
public function puffer() {
|
||||
// Nutze Models für den Datenbankzugriff
|
||||
// $data = YourModel::all();
|
||||
|
||||
return $this->render('puffer', [
|
||||
'title' => 'Puffer Modul',
|
||||
'message' => 'Willkommen in deinem neuen Modul Puffer!'
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace MVC\Core;
|
||||
|
||||
class Controller {
|
||||
protected $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);
|
||||
}
|
||||
return $this->view->render($template);
|
||||
}
|
||||
|
||||
protected function json($data, $status = 200) {
|
||||
header('Content-Type: application/json');
|
||||
http_response_code($status);
|
||||
echo json_encode($data);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
namespace MVC\Core;
|
||||
|
||||
require_once __DIR__ . '/../../database/databaseConnect.php';
|
||||
require_once __DIR__ . '/../../utils/databaseMethods.php';
|
||||
|
||||
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, "*");
|
||||
}
|
||||
|
||||
public static function find($id, $column = 'ID') {
|
||||
$result = \DatabaseShow(static::$table, "*", "$column = ?", $id);
|
||||
return $result[0] ?? null;
|
||||
}
|
||||
|
||||
public static function where($where, ...$params) {
|
||||
return \DatabaseShow(static::$table, "*", $where, ...$params);
|
||||
}
|
||||
|
||||
public static function insert($data) {
|
||||
$columns = implode(", ", array_keys($data));
|
||||
$values = array_values($data);
|
||||
return \DatabaseInsert(static::$table, $columns, ...$values);
|
||||
}
|
||||
|
||||
public static function update($data, $where, ...$whereParams) {
|
||||
$sets = [];
|
||||
$values = [];
|
||||
foreach ($data as $column => $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) {
|
||||
$conn = self::getConnection();
|
||||
if (empty($params)) {
|
||||
return $conn->query($sql);
|
||||
}
|
||||
$stmt = $conn->prepare($sql);
|
||||
$types = str_repeat('s', count($params));
|
||||
$stmt->bind_param($types, ...$params);
|
||||
$stmt->execute();
|
||||
return $stmt->get_result();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
namespace MVC\Core;
|
||||
|
||||
class Router {
|
||||
protected $routes = [];
|
||||
protected $middlewares = [];
|
||||
|
||||
public function add($service, $controller, $method, $middlewares = []) {
|
||||
$this->routes[$service] = [
|
||||
'controller' => $controller,
|
||||
'method' => $method,
|
||||
'middlewares' => $middlewares
|
||||
];
|
||||
}
|
||||
|
||||
public function dispatch($service) {
|
||||
if (!isset($this->routes[$service])) {
|
||||
throw new \Exception("Service '$service' not found.");
|
||||
}
|
||||
|
||||
$route = $this->routes[$service];
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace MVC\Core;
|
||||
|
||||
class View {
|
||||
protected $data = [];
|
||||
protected $viewPath;
|
||||
|
||||
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 not found at $file";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
namespace MVC\Layout;
|
||||
class Layout {
|
||||
|
||||
protected $blocks = [];
|
||||
|
||||
protected $template;
|
||||
|
||||
public function __construct($template = 'main') {
|
||||
$this->template = $template;
|
||||
}
|
||||
|
||||
public function setBlock($name, $content) {
|
||||
$this->blocks[$name] = $content;
|
||||
}
|
||||
|
||||
public function getBlock($name) {
|
||||
return $this->blocks[$name] ?? '';
|
||||
}
|
||||
|
||||
public function render() {
|
||||
$layoutFile = __DIR__ . '/Templates/' . $this->template . '.php';
|
||||
|
||||
if (file_exists($layoutFile)) {
|
||||
ob_start();
|
||||
include $layoutFile;
|
||||
return ob_get_clean();
|
||||
}
|
||||
|
||||
return "Layout template nicht gefunden.";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<!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>
|
||||
@@ -0,0 +1,32 @@
|
||||
<?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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @var array $array
|
||||
* @var string $prevDay
|
||||
* @var string $nextDay
|
||||
* @var string $day
|
||||
* @var string $title
|
||||
* @var string $xtitle
|
||||
* @var string $ytitle
|
||||
*/
|
||||
|
||||
$labels = [];
|
||||
$abgas = [];
|
||||
|
||||
foreach ($array as $row) {
|
||||
$labels[] = $row['ts'];
|
||||
$abgas[] = (float)$row['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,2 @@
|
||||
<h1>Dashboard</h1>
|
||||
<p>Willkommen in deinem neuen MVC-System mit integriertem Header.</p>
|
||||
@@ -0,0 +1,14 @@
|
||||
<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>
|
||||
@@ -0,0 +1,123 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @var array $array
|
||||
* @var string $prevDay
|
||||
* @var string $nextDay
|
||||
* @var string $day
|
||||
* @var string $title
|
||||
* @var string $xtitle
|
||||
* @var string $ytitle
|
||||
*/
|
||||
|
||||
$labels = [];
|
||||
$vorlaufIst = [];
|
||||
$vorlaufSoll = [];
|
||||
|
||||
foreach ($array as $row) {
|
||||
$labels[] = date('H:i:s', strtotime($row['ts']));
|
||||
$vorlaufIst[] = (float)$row['vorlauf_ist'];
|
||||
$vorlaufSoll[] = (float)$row['vorlauf_soll'];
|
||||
}
|
||||
?>
|
||||
|
||||
<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>
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
spl_autoload_register(function ($class) {
|
||||
$prefix = 'MVC\\';
|
||||
$base_dir = __DIR__ . '/';
|
||||
|
||||
$len = strlen($prefix);
|
||||
if (strncmp($prefix, $class, $len) !== 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$relative_class = substr($class, $len);
|
||||
$file = $base_dir . str_replace('\\', '/', $relative_class) . '.php';
|
||||
|
||||
if (file_exists($file)) {
|
||||
require $file;
|
||||
}
|
||||
});
|
||||
@@ -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"
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
function db_connect() {
|
||||
$config = parse_ini_file(__DIR__ . '/../config/env.ini');
|
||||
$env = strtoupper($config['APP_ENV']);
|
||||
try {
|
||||
$conn = new mysqli(
|
||||
$config["DB_{$env}_HOST"],
|
||||
$config["DB_{$env}_USERNAME"],
|
||||
$config["DB_{$env}_PASSWORD"],
|
||||
$config["DB_{$env}_DATABASE"]
|
||||
);
|
||||
|
||||
$conn->set_charset("utf8mb4");
|
||||
|
||||
return $conn;
|
||||
|
||||
} catch (Exception $e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,223 @@
|
||||
<?php
|
||||
|
||||
function DatabaseCreateTable($table, $columnsDefinition) {
|
||||
include_once(__DIR__ . '/../database/databaseConnect.php');
|
||||
$conn = db_connect();
|
||||
|
||||
$sql = "CREATE TABLE IF NOT EXISTS `$table` ($columnsDefinition)";
|
||||
$stmt = $conn->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
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
/**
|
||||
* MVC Model Generator
|
||||
* Nutzung: php create_model.php <TabellenName> <Spalte1,Spalte2,...>
|
||||
*/
|
||||
|
||||
if (php_sapi_name() !== 'cli') {
|
||||
die("Dieses Script muss über die CLI ausgeführt werden.\n");
|
||||
}
|
||||
|
||||
$tableName = $argv[1] ?? null;
|
||||
$columnsInput = $argv[2] ?? null;
|
||||
|
||||
// Interaktive Abfrage, falls Argumente fehlen
|
||||
if (!$tableName) {
|
||||
echo "Tabellenname eingeben (z.B. Benutzer): ";
|
||||
$handle = fopen("php://stdin", "r");
|
||||
$tableName = trim(fgets($handle));
|
||||
fclose($handle);
|
||||
}
|
||||
|
||||
if (!$columnsInput) {
|
||||
echo "Spalten kommagetrennt eingeben (z.B. NAME,EMAIL,ROLLE): ";
|
||||
$handle = fopen("php://stdin", "r");
|
||||
$columnsInput = trim(fgets($handle));
|
||||
fclose($handle);
|
||||
}
|
||||
|
||||
if (!$tableName) die("Fehler: Kein Tabellenname angegeben.\n");
|
||||
|
||||
// Namen formatieren
|
||||
$className = str_replace(' ', '', ucwords(str_replace('_', ' ', strtolower($tableName))));
|
||||
$modelFile = __DIR__ . "/WEBROOT/src/MVC/Model/{$className}.php";
|
||||
|
||||
// Spalten aufbereiten
|
||||
$columns = array_map('trim', explode(',', $columnsInput));
|
||||
$columnList = implode("', '", $columns);
|
||||
|
||||
// Model-Inhalt generieren
|
||||
$content = <<<PHPMODEL
|
||||
<?php
|
||||
|
||||
namespace MVC\Model;
|
||||
|
||||
use MVC\Core\Model;
|
||||
|
||||
/**
|
||||
* Model für die Tabelle '{$tableName}'
|
||||
* Verfügbare Spalten: '{$columnList}'
|
||||
*/
|
||||
class {$className} extends Model {
|
||||
protected static \$table = "{$tableName}";
|
||||
|
||||
// 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("{$columns[0]} = ?", \$value);
|
||||
}
|
||||
}
|
||||
PHPMODEL;
|
||||
|
||||
// Datei schreiben
|
||||
if (!is_dir(dirname($modelFile))) {
|
||||
mkdir(dirname($modelFile), 0755, true);
|
||||
}
|
||||
|
||||
if (!file_exists($modelFile)) {
|
||||
file_put_contents($modelFile, $content);
|
||||
echo "✅ Model erstellt: WEBROOT/src/MVC/Model/{$className}.php\n";
|
||||
echo "--- INFO ---\n";
|
||||
echo "Tabelle: {$tableName}\n";
|
||||
echo "Klasse: MVC\\Model\\{$className}\n";
|
||||
echo "Spalten: " . implode(', ', $columns) . "\n";
|
||||
} else {
|
||||
echo "⚠️ Model {$className}.php existiert bereits.\n";
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
/**
|
||||
* MVC Module Generator for Gemini CLI Project
|
||||
* Nutzung: php create_module.php <name>
|
||||
*/
|
||||
|
||||
if (php_sapi_name() !== 'cli') {
|
||||
die("Dieses Script kann nur über die Kommandozeile ausgeführt werden.\n");
|
||||
}
|
||||
|
||||
$name = $argv[1] ?? null;
|
||||
|
||||
if (!$name) {
|
||||
echo "Bitte gib einen Namen für das Modul an (z.B. mein_projekt): ";
|
||||
$handle = fopen("php://stdin", "r");
|
||||
$name = trim(fgets($handle));
|
||||
fclose($handle);
|
||||
}
|
||||
|
||||
if (!$name) {
|
||||
die("Fehler: Kein Name angegeben.\n");
|
||||
}
|
||||
|
||||
// Namen formatieren
|
||||
$key = strtolower(str_replace(' ', '_', $name));
|
||||
$className = str_replace(' ', '', ucwords(str_replace('_', ' ', $key)));
|
||||
$controllerFile = __DIR__ . "/WEBROOT/src/MVC/Controller/{$className}Controller.php";
|
||||
$viewFile = __DIR__ . "/WEBROOT/src/MVC/View/{$key}.php";
|
||||
|
||||
// 1. Controller erstellen
|
||||
$controllerContent = <<<PHPCTRL
|
||||
<?php
|
||||
|
||||
namespace MVC\Controller;
|
||||
|
||||
use MVC\Core\Controller;
|
||||
// use MVC\Model\YourModel; // Importiere dein Model
|
||||
|
||||
class {$className}Controller extends Controller {
|
||||
public function {$key}() {
|
||||
// Nutze Models für den Datenbankzugriff
|
||||
// \$data = YourModel::all();
|
||||
|
||||
return \$this->render('{$key}', [
|
||||
'title' => '{$className} Modul',
|
||||
'message' => 'Willkommen in deinem neuen Modul {$className}!'
|
||||
]);
|
||||
}
|
||||
}
|
||||
PHPCTRL;
|
||||
|
||||
if (!file_exists($controllerFile)) {
|
||||
file_put_contents($controllerFile, $controllerContent);
|
||||
echo "✅ Controller erstellt: WEBROOT/src/MVC/Controller/{$className}Controller.php\n";
|
||||
} else {
|
||||
echo "⚠️ Controller existiert bereits.\n";
|
||||
}
|
||||
|
||||
// 2. View erstellen
|
||||
$viewContent = <<<HTML
|
||||
<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>
|
||||
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";
|
||||
}
|
||||
|
||||
// 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 "------------------------\n";
|
||||
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
$port = 8000;
|
||||
$host = 'localhost';
|
||||
$root = __DIR__ . '/WEBROOT';
|
||||
echo "\n🚀 Starte MVC Dev-Server auf http://$host:$port\n";
|
||||
echo "Drücke STRG+C zum Beenden.\n\n";
|
||||
passthru("php -S $host:$port -t \"$root\"");
|
||||
Reference in new issue
Block a user