fix: Gitea Traefik routing and connection pool optimization
Some checks failed
🚀 Build & Deploy Image / Determine Build Necessity (push) Failing after 10m14s
🚀 Build & Deploy Image / Build Runtime Base Image (push) Has been skipped
🚀 Build & Deploy Image / Build Docker Image (push) Has been skipped
🚀 Build & Deploy Image / Run Tests & Quality Checks (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Staging (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Production (push) Has been skipped
Security Vulnerability Scan / Check for Dependency Changes (push) Failing after 11m25s
Security Vulnerability Scan / Composer Security Audit (push) Has been cancelled

- Remove middleware reference from Gitea Traefik labels (caused routing issues)
- Optimize Gitea connection pool settings (MAX_IDLE_CONNS=30, authentication_timeout=180s)
- Add explicit service reference in Traefik labels
- Fix intermittent 504 timeouts by improving PostgreSQL connection handling

Fixes Gitea unreachability via git.michaelschiemer.de
This commit is contained in:
2025-11-09 14:46:15 +01:00
parent 85c369e846
commit 36ef2a1e2c
1366 changed files with 104925 additions and 28719 deletions

193
src/Domain/Cms/README.md Normal file
View File

@@ -0,0 +1,193 @@
# Headless CMS Modul
Ein Block-basiertes Headless CMS System für das Custom PHP Framework.
## Übersicht
Das CMS Modul ermöglicht die Verwaltung von Content durch ein flexibles Block-System, ähnlich WordPress Blocks, Storyblok oder Contentful. Content besteht aus einer geordneten Liste von Content-Blöcken, die als JSON in der Datenbank gespeichert werden.
## Architektur
### Block-basiertes System
Content besteht aus einer **geordneten Liste von Content-Blöcken**. Jeder Block hat:
- **Block Type**: HERO, TEXT, IMAGE, GALLERY, CTA, VIDEO, etc.
- **Block Data**: Typed Value Object mit block-spezifischen Daten
- **Block ID**: Eindeutige ID innerhalb des Contents
- **Block Settings**: Optionale Konfiguration (Styling, Visibility)
### Beispiel: Landing Page
```php
use App\Domain\Cms\Entities\Content;
use App\Domain\Cms\Enums\BlockType;
use App\Domain\Cms\ValueObjects\*;
$content = Content::create(
clock: $clock,
contentTypeId: ContentTypeId::fromString('landing_page'),
slug: ContentSlug::fromString('homepage'),
title: 'Welcome to Our Product',
blocks: ContentBlocks::fromArray([
ContentBlock::create(
blockType: BlockType::HERO,
blockId: 'hero-1',
data: BlockData::fromArray([
'title' => 'Revolutionary Product',
'subtitle' => 'Transform your workflow',
'backgroundImage' => 'img-123', // MediaId als String
'ctaText' => 'Get Started',
'ctaLink' => '/signup'
])
),
ContentBlock::create(
blockType: BlockType::TEXT,
blockId: 'text-1',
data: BlockData::fromArray([
'content' => '<p>Our product is...</p>',
'alignment' => 'center'
])
)
])
);
```
## Datenbank-Schema
### content_types
Speichert Content Type Definitionen:
- `id` (VARCHAR) - Content Type Identifier
- `name` (VARCHAR) - Display Name
- `slug` (VARCHAR) - URL-freundlicher Slug
- `description` (TEXT) - Beschreibung
- `is_system` (BOOLEAN) - System Content Type
### contents
Speichert Content Instanzen:
- `id` (VARCHAR) - ULID Identifier
- `content_type_id` (VARCHAR) - Foreign Key zu content_types
- `slug` (VARCHAR) - URL-freundlicher Slug (unique)
- `title` (VARCHAR) - Content Titel
- `blocks` (JSON) - Array von Block-Objekten
- `meta_data` (JSON) - SEO, Open Graph Metadaten
- `status` (ENUM) - draft, published, archived
- `author_id` (VARCHAR) - Author User ID
- `published_at` (TIMESTAMP) - Veröffentlichungsdatum
- `created_at`, `updated_at` (TIMESTAMP)
## Verwendung
### ContentService
```php
use App\Domain\Cms\Services\ContentService;
use App\Domain\Cms\ValueObjects\*;
// Content erstellen
$content = $contentService->create(
contentTypeId: ContentTypeId::fromString('landing_page'),
title: 'Welcome Page',
blocks: ContentBlocks::fromArray([...]),
slug: ContentSlug::fromString('homepage')
);
// Content finden
$content = $contentService->findBySlug(ContentSlug::fromString('homepage'));
// Content veröffentlichen
$published = $contentService->publish($content->id);
// Content aktualisieren
$updated = $contentService->updateBlocks(
$content->id,
ContentBlocks::fromArray([...])
);
```
## REST API
### Endpoints
- `GET /api/v1/cms/contents` - Liste aller Contents
- `GET /api/v1/cms/contents/{id}` - Content Details
- `POST /api/v1/cms/contents` - Content erstellen
- `PUT /api/v1/cms/contents/{id}` - Content aktualisieren
- `DELETE /api/v1/cms/contents/{id}` - Content löschen
- `POST /api/v1/cms/contents/{id}/publish` - Content veröffentlichen
- `POST /api/v1/cms/contents/{id}/unpublish` - Content zurückziehen
### Beispiel Request
```json
POST /api/v1/cms/contents
{
"content_type_id": "landing_page",
"slug": "homepage",
"title": "Welcome Page",
"blocks": [
{
"id": "hero-1",
"type": "hero",
"data": {
"title": "Revolutionary Product",
"subtitle": "Transform your workflow",
"backgroundImage": "img-123",
"ctaText": "Get Started",
"ctaLink": "/signup"
},
"settings": {
"fullWidth": true
}
}
],
"status": "draft"
}
```
## Block Types
- `HERO` - Hero Section mit Titel, Bild, CTA
- `TEXT` - Rich Text Block
- `IMAGE` - Einzelnes Bild mit Caption
- `GALLERY` - Bildergalerie
- `CTA` - Call-to-Action Block
- `VIDEO` - Video Embed
- `FORM` - Formular Integration
- `COLUMNS` - Multi-Column Layout
- `QUOTE` - Zitat Block
- `SEPARATOR` - Trenner/Divider
## Integration mit anderen Domains
### Media Domain
Block Data kann MediaId als String enthalten:
```php
BlockData::fromArray([
'imageId' => 'img-123', // MediaId als String
'caption' => 'Product Screenshot'
])
```
### Meta Domain
SEO-Metadaten können in `meta_data` gespeichert werden:
```php
$content = $content->withMetaData(BlockData::fromArray([
'title' => 'SEO Title',
'description' => 'SEO Description',
'og_title' => 'OG Title',
'og_image' => 'og-image.jpg'
]));
```
## Migration
```bash
php console.php db:migrate
```
Die Migrations erstellen die Tabellen `content_types` und `contents` mit JSON-Spalten für Blocks.