docs: consolidate documentation into organized structure

- Move 12 markdown files from root to docs/ subdirectories
- Organize documentation by category:
  • docs/troubleshooting/ (1 file)  - Technical troubleshooting guides
  • docs/deployment/      (4 files) - Deployment and security documentation
  • docs/guides/          (3 files) - Feature-specific guides
  • docs/planning/        (4 files) - Planning and improvement proposals

Root directory cleanup:
- Reduced from 16 to 4 markdown files in root
- Only essential project files remain:
  • CLAUDE.md (AI instructions)
  • README.md (Main project readme)
  • CLEANUP_PLAN.md (Current cleanup plan)
  • SRC_STRUCTURE_IMPROVEMENTS.md (Structure improvements)

This improves:
 Documentation discoverability
 Logical organization by purpose
 Clean root directory
 Better maintainability
This commit is contained in:
2025-10-05 11:05:04 +02:00
parent 887847dde6
commit 5050c7d73a
36686 changed files with 196456 additions and 12398919 deletions

View File

@@ -0,0 +1,128 @@
# Bild-Upload-System
Dieses Dokument beschreibt das Bild-Upload-System des Frameworks.
## Funktionen
- Strukturierte Ordnerhierarchie basierend auf Datum und ID
- Automatische Erstellung mehrerer Bildvarianten (Größen)
- Unterstützung für mehrere Dateiformate (JPG, WebP, AVIF)
- Duplikat-Erkennung über SHA256-Hash
- Sicherheitsvalidierung von Dateitypen und -größen
- Performance-Optimierung durch moderne Bildformate
## Ordnerstruktur
Die Bilder werden in folgendem Muster gespeichert:
```
/uploads
└─ /YYYY (Jahr)
└─ /MM (Monat)
└─ /DD (Tag)
└─ /XXX (ID Teil 1)
└─ /XXX (ID Teil 2)
└─ /XXX (ID Teil 3)
└─ original.jpg
└─ thumbnail.jpg
└─ thumbnail.webp
└─ thumbnail.avif
└─ small.jpg
└─ small.webp
└─ small.avif
└─ medium.jpg
└─ medium.webp
└─ medium.avif
└─ large.jpg
└─ large.webp
└─ large.avif
```
## Bildvarianten
Folgende Bildvarianten werden automatisch erstellt:
- **thumbnail**: 150x150px, quadratisch zugeschnitten
- **small**: 400x400px, proportional skaliert
- **medium**: 800x800px, proportional skaliert
- **large**: 1200x1200px, proportional skaliert
## Dateiformate
Jede Variante wird in folgenden Formaten gespeichert:
- **JPG**: Für universelle Kompatibilität
- **WebP**: Für moderne Browser mit besserer Kompression
- **AVIF**: Für neueste Browser mit bester Kompression (falls PHP-Unterstützung vorhanden)
## Datenbank-Schema
Das System verwendet zwei Tabellen:
### `images`
- `id`: Primärschlüssel
- `filename`: Generierter Dateiname
- `original_filename`: Originaler Upload-Dateiname
- `mime_type`: MIME-Typ des Bildes
- `file_size`: Dateigröße in Bytes
- `width`: Bildbreite in Pixeln
- `height`: Bildhöhe in Pixeln
- `hash`: SHA256-Hash für Duplikat-Erkennung
- `upload_path`: Relativer Pfad zum Bild
- `created_at`: Erstellungszeitpunkt
- `updated_at`: Letzter Aktualisierungszeitpunkt
### `image_variants`
- `id`: Primärschlüssel
- `image_id`: Fremdschlüssel zur `images`-Tabelle
- `variant`: Name der Variante (thumbnail, small, medium, large)
- `format`: Dateiformat (jpg, webp, avif)
- `width`: Bildbreite in Pixeln
- `height`: Bildhöhe in Pixeln
- `file_size`: Dateigröße in Bytes
- `filename`: Name der Variantendatei
- `created_at`: Erstellungszeitpunkt
## Verwendung
### Bild hochladen
```php
// In einem Controller
public function upload(Request $request)
{
$file = $request->files->get('image');
$image = $this->imageService->uploadImage($file);
// URL zu einer Bildvariante erhalten
$thumbnailUrl = $this->imageService->getImageUrl($image, 'thumbnail', 'webp');
$mediumUrl = $this->imageService->getImageUrl($image, 'medium', 'jpg');
}
```
### Bild anzeigen
```html
<!-- Optimale Bildauswahl mit picture-Element -->
<picture>
<source srcset="/media/uploads/2025/06/26/001/234/567/1234567/medium.avif" type="image/avif">
<source srcset="/media/uploads/2025/06/26/001/234/567/1234567/medium.webp" type="image/webp">
<img src="/media/uploads/2025/06/26/001/234/567/1234567/medium.jpg" alt="Beschreibung">
</picture>
```
## Technische Details
### Bildverarbeitung
Die Bildverarbeitung erfolgt mit der GD-Bibliothek. Für die Verwendung von AVIF ist PHP 8.1+ mit AVIF-Unterstützung erforderlich.
### Performance
Bilder werden mit Cache-Headers ausgeliefert, die eine lange Browser-Cache-Dauer ermöglichen, um Bandbreite zu sparen und die Ladezeit zu verbessern.
### Sicherheit
Alle Uploads werden validiert, um sicherzustellen, dass nur erlaubte Bildtypen verarbeitet werden. Es werden sichere, eindeutige Dateinamen generiert, um Konflikte zu vermeiden.

View File

@@ -0,0 +1,118 @@
# Static Site Generator
Diese Komponente ermöglicht die Generierung statischer HTML-Seiten aus den dynamischen Routen der Anwendung, die mit dem `#[StaticPage]` Attribut markiert sind.
## Funktionsweise
Der Static Site Generator identifiziert alle Controller-Methoden, die mit dem `#[StaticPage]` Attribut markiert sind, und erzeugt für jede entsprechende Route eine statische HTML-Datei im `public/static` Verzeichnis. Die Verzeichnisstruktur wird entsprechend der URL-Struktur erstellt.
## Markieren von Routen als statische Seiten
Um eine Route als statische Seite zu kennzeichnen, füge das `#[StaticPage]` Attribut zur Controller-Methode hinzu:
```php
use App\Framework\Attributes\StaticPage;
use App\Framework\Attributes\Route;
class HomeController
{
#[Route('/')]
#[StaticPage]
public function index()
{
// Diese Seite wird als statische Seite generiert
return new ViewResult(new HomeViewModel());
}
#[Route('/about')]
#[StaticPage(outputPath: 'ueber-uns')]
public function about()
{
// Diese Seite wird mit benutzerdefiniertem Pfad generiert
return new ViewResult(new AboutViewModel());
}
#[Route('/dynamic-content')]
public function dynamic()
{
// Diese Seite wird NICHT als statische Seite generiert
return new ViewResult(new DynamicViewModel());
}
}
```
## Verwendung
### Über die Kommandozeile
```bash
# Nur mit #[StaticPage] markierte Routen generieren (Standard)
php bin/generate-static.php
# Oder mit Composer
composer generate-static
# Alle GET-Routen generieren (ignoriert #[StaticPage] Attribut)
php bin/generate-static.php --all
# Mit benutzerdefinierten Optionen
php bin/generate-static.php --manual-routes=config/static-routes.json --output=public/static --exclude="\/api\/.*,\/admin\/.*"
```
### Verfügbare Optionen
- `--manual-routes=<datei>`: Pfad zu einer JSON-Datei mit zu generierenden Routen (überschreibt Attributerkennung)
- `--output=<ordner>`: Ausgabeverzeichnis (Standard: public/static)
- `--exclude=<muster>`: Kommagetrennte Liste von Regex-Mustern für auszuschließende Routen
- `--all`: Alle GET-Routen generieren (ignoriert #[StaticPage] Attribut)
- `--help`: Hilfe anzeigen
### Programmatisch verwenden
```php
use App\Framework\StaticSite\StaticSiteGenerator;
use App\Framework\StaticSite\StaticPageCollector;
// Anwendung initialisieren
$app = /* ... */;
// Routen mit StaticPage-Attribut sammeln
$router = $app->getContainer()->get(HttpRouter::class);
$staticPageCollector = new StaticPageCollector($router);
$routes = $staticPageCollector->collectStaticPages();
// Oder alle GET-Routen sammeln
// $routes = $staticPageCollector->collectAllGetRoutes();
// Generator initialisieren
$generator = new StaticSiteGenerator($app, $routes);
// Optional: Ausgabeverzeichnis anpassen
$generator->setOutputDirectory(__DIR__ . '/path/to/output');
// Statische Seiten generieren
$generator->generate();
```
## Ausgabestruktur
Für jede markierte Route wird eine entsprechende Datei oder Verzeichnisstruktur erstellt:
- `/``/public/static/index.html`
- `/about``/public/static/about/index.html` (oder benutzerdefinierter Pfad, wenn im Attribut angegeben)
- `/blog/post-1``/public/static/blog/post-1/index.html`
## Erweitertes StaticPage-Attribut
Das `#[StaticPage]` Attribut unterstützt folgende Parameter:
- `outputPath`: Optionaler benutzerdefinierter Ausgabepfad für die statische Seite
- `prerender`: Ob die Seite beim Deployment vorgerendert werden soll (Standard: true)
## Vorteile statischer Seiten
- Verbesserte Performance durch Wegfall der dynamischen Verarbeitung
- Geringere Serverlast
- Einfacheres Hosting (statische Dateien können überall gehostet werden)
- Verbesserte Sicherheit durch Reduzierung der Angriffsfläche
- Bessere SEO durch schnellere Ladezeiten

View File

@@ -0,0 +1,118 @@
# WebSocket Server
Dieses Dokument beschreibt die Implementierung und Verwendung des WebSocket-Servers.
## Übersicht
Der WebSocket-Server ist als eigenständiger Prozess implementiert, der unabhängig vom HTTP-Server läuft. Dies ermöglicht langlebige Verbindungen, die mit dem PHP-FPM/Apache-Modell nicht möglich wären.
## Starten des WebSocket-Servers
Der WebSocket-Server kann mit folgendem Befehl gestartet werden:
```bash
php websocket.php
```
Oder, wenn die Ausführungsrechte gesetzt sind:
```bash
./websocket.php
```
Der Server läuft standardmäßig auf `0.0.0.0:8080` und kann über WebSocket-Clients erreicht werden.
## Konfiguration
Die Konfiguration des WebSocket-Servers erfolgt direkt in der `websocket.php`-Datei. Hier können Host und Port angepasst werden:
```php
$server->start('0.0.0.0', 8080);
```
## Implementierung von WebSocket-Controllern
WebSocket-Controller werden wie normale HTTP-Controller implementiert, geben jedoch ein `WebSocketResult`-Objekt zurück. Hier ist ein Beispiel:
```php
#[Route(path: '/chat/websocket', method: Method::GET)]
public function chatWebSocket(): WebSocketResult
{
return new WebSocketResult()
->onConnect(function (WebSocketConnection $connection) {
// Handler für neue Verbindungen
})
->onMessage(function (WebSocketConnection $connection, string $message) {
// Handler für eingehende Nachrichten
})
->onClose(function (WebSocketConnection $connection, int $code, string $reason) {
// Handler für geschlossene Verbindungen
})
->onError(function (WebSocketConnection $connection, \Throwable $error) {
// Handler für Fehler
});
}
```
## Testen mit dem ChatController
Der bestehende `ChatController` kann als Beispiel für die Verwendung von WebSockets dienen. Um ihn zu testen:
1. Starten Sie den WebSocket-Server:
```bash
php websocket.php
```
2. Öffnen Sie eine WebSocket-Verbindung zum Server (z.B. mit JavaScript):
```javascript
const socket = new WebSocket('ws://localhost:8080/chat/websocket');
socket.onopen = function(e) {
console.log("Verbindung hergestellt");
};
socket.onmessage = function(event) {
console.log(`Daten empfangen: ${event.data}`);
};
socket.onclose = function(event) {
if (event.wasClean) {
console.log(`Verbindung geschlossen, Code=${event.code} Grund=${event.reason}`);
} else {
console.log('Verbindung unterbrochen');
}
};
socket.onerror = function(error) {
console.log(`Fehler: ${error.message}`);
};
// Nachricht senden
socket.send(JSON.stringify({
type: 'chat_message',
message: 'Hallo Welt!'
}));
```
## Architektur
Der WebSocket-Server verwendet folgende Komponenten:
1. **websocket.php**: Einstiegspunkt und Hauptskript
2. **WebSocketServer**: Verarbeitet WebSocket-Verbindungen und -Nachrichten
3. **WebSocketConnection**: Repräsentiert eine aktive WebSocket-Verbindung
4. **WebSocketResult**: Definiert Handler für WebSocket-Ereignisse
Der Server nutzt das bestehende Routing-System, um WebSocket-Anfragen an die entsprechenden Controller weiterzuleiten.
## Vorteile gegenüber der HTTP-basierten Implementierung
1. **Langlebige Verbindungen**: Der Server kann Verbindungen über längere Zeit offen halten
2. **Echtzeit-Kommunikation**: Bidirektionale Kommunikation in Echtzeit
3. **Ressourceneffizienz**: Geringerer Overhead im Vergleich zu HTTP-Polling
4. **Skalierbarkeit**: Der WebSocket-Server kann unabhängig vom HTTP-Server skaliert werden
## Bekannte Einschränkungen
1. Der WebSocket-Server unterstützt derzeit keine SSL/TLS-Verschlüsselung direkt. Für sichere Verbindungen sollte ein Reverse-Proxy wie Nginx verwendet werden.
2. Die Implementierung ist auf einfache Anwendungsfälle ausgelegt und könnte für komplexere Szenarien erweitert werden.