12-05-2026 Frontend dev
Some checks are pending
linter / quality (push) Waiting to run
tests / ci (push) Waiting to run

This commit is contained in:
Kevin Adametz 2026-05-12 18:32:33 +02:00
parent 405df0a122
commit 5b8bdf4182
779 changed files with 480564 additions and 6241 deletions

View file

@ -0,0 +1,282 @@
# 01 Legacy-Analyse
Detailliertes Inventar des Symfony-1.4-Backends in `/_businessportal24.com/`. Das `presseecho`-Projekt ist code-identisch.
---
## 1. Projektstruktur (Top-Level)
```
_businessportal24.com/
├── apps/
│ ├── backend/ ← Admin-App (Routing, Config, Templates). Modules liegen in Plugins.
│ └── frontend/ ← Public/Frontend-App (wird NICHT migriert neue Frontends existieren)
├── config/ ← Globale Config (Datenbanken, Projekt, i18n)
├── lib/ ← Global genutzte Klassen (Models liegen aber in Plugin)
├── plugins/ ← Fachliche Logik der Hauptteil!
│ ├── PressePortalPlugin ★ Kern-Plugin (Entities, Modules, Forms)
│ ├── sfDoctrineGuardPlugin ← Auth
│ ├── sfDoctrineGuardPaymentPlugin ★ Payment, Invoice, Coupon
│ ├── sfDoctrineApplyPlugin ← Registrierung
│ ├── sfFormExtraPlugin ← Form-Widgets
│ ├── sfImageTransformPlugin ← Image-Thumbnailing
│ ├── sfImageTransformExtraPlugin
│ ├── sfCaptchaGDPlugin ← Captcha
│ ├── sfCsvPlugin ← CSV-Export
│ ├── isicsWidgetFormTinyMCEPlugin← WYSIWYG
│ ├── tnHttpErrorPlugin ← HTTP-Error-Handling
│ └── tnStrategicTesterResponsePlugin
├── symfony-1.4/ ← Framework (Vendor)
├── data/ ← Fixtures
├── web/ ← DocRoot, Public Assets
└── cron_script_{local,server}.sh
```
---
## 2. Admin-Module (`PressePortalPlugin/modules/`)
### 2.1 Verwaltung / CRUD
| Modul | Entität | Admin-URL | Migrations-Target |
|---|---|---|---|
| `adminCenter` | Dashboard / Navigationshub | `/` | Livewire `admin.dashboard` (existiert) |
| `adminSfGuardAuth` | Login/Logout | `/login`, `/logout` | Fortify (existiert) |
| `adminSfGuardUser` (über Routing) | User | `/sf_guard_user` | `admin.users.*` (existiert) |
| `adminSfGuardGroup` | Rollen | `/sf_guard_group` | Spatie Roles → `admin.roles.*` (existiert) |
| `adminSfGuardPermission` | Permissions | `/sf_guard_permission` | Spatie Permissions |
| `adminSalutation` | Anreden | `/salutation` | → Config (`config/salutations.php`) |
| `adminCountry` | Länder | `/country` | → Config (`config/countries.php`) |
| `adminCategory` | Kategorien (i18n) | `/category` | `admin.categories.*` (existiert) |
| `adminCompany` | Firmen/Agenturen | `/company` | `admin.companies.*` (existiert) |
| `adminContact` | Ansprechpartner | `/contact` | `admin.contacts.*` (existiert) |
| `adminPressrelease` | Pressemitteilungen | `/pressrelease` | `admin.press-releases.*` (existiert) |
| `adminPressreleaseimage` | Bilder zu PMs | `/pressreleaseimage` | Teil von PressRelease |
| `adminPromotionlink` | Werbeplätze/Links | `/promotionlink` | **Scope-Entscheidung nötig** |
| `adminFootercode` | Custom Footer-HTML | `/footercode` | **Scope-Entscheidung nötig** |
| `adminBlacklist` | Wort-Blacklist | `/blacklist` | `admin.blacklist.*` (neu) |
| `adminNewslettersubscription` | Newsletter-Subscriber | `/newslettersubscription` | `admin.newsletter.subscribers` (existiert) |
| `sfpCouponAdmin` | Gutscheine | `/coupon` | `admin.coupons.*` (existiert) |
| `sfpInvoiceAdmin` | Rechnungen | `/invoice` | `admin.invoices.*` (existiert) |
| `sfpInvoiceBillingAddressAdmin` | Rechn.-Adressen | `/invoice_billing_address` | Teil von Invoice |
| `sfpUserBillingAddressAdmin` | User-Rechn.-Adressen | `/user_billing_address` | Teil von User |
| `sfpUserPaymentOptionAdmin` | User-Abos/Payment | `/user_payment_option` | `admin.payments.*` (existiert) |
### 2.2 Service-/System-Module
| Modul | Zweck | Migrations-Target |
|---|---|---|
| `sfpCron` | HTTP-Trigger für Cron-Scripts | Laravel Scheduler (`routes/console.php`) |
| `sfpStore` | Abo-/Bestell-Flow | Stripe Checkout + Domain-Service |
| `sfpInvoicePdf` | PDF-Generation | `barryvdh/laravel-dompdf` + Blade-Template |
| `sfpUserBilling` | User-seitige Rechn.-Übersicht | Frontend-/Kundencenter-Views |
| `import` | CSV-/Daten-Import | **Neu als `php artisan` Command(s)** |
| `ajax` | Autocompletion für Admin-Forms | Livewire `wire:model`-Suche |
| `tnHttpError` | Error-Views | Laravel's Standard-Error-Pages |
### 2.3 Frontend-Module (werden NICHT migriert)
| Modul | Zweck |
|---|---|
| `company`, `customercenter`, `page`, `pressrelease`, `pressreleaseimage`, `category`, `profile`, `newsletter`, `presscontact`, `sfApply`, `sfGuardAuth`, `sfGuardUser` | Altes Symfony-Frontend. Wird ersetzt durch bestehendes `resources/views/web/*` und das neue Backend-API |
---
## 3. Datenmodell (aus `PressePortalPlugin/config/doctrine/schema.yml`)
### 3.1 Entitäten (Kern)
| Doctrine-Entität | Zeilen in Schema | Fachlicher Zweck |
|---|---|---|
| `Salutation` | 418 | Anrede (Herr/Frau, i18n) |
| `Country` | 2332 | Länder |
| `sfGuardUser` | 3884 | User |
| `sfGuardUserProfile` | 92191 | User-Profil (Name, Adresse, Tel, E-Mail, API-Key, Tax-ID …) |
| `Company` | 197278 | Firma (inkl. Logo, Login, Footer-Code-Disable) |
| `Agency` | 280297 | Column-Aggregation-Inheritance von Company (ctype='agency') |
| `CompanyUser` | 300318 | User ↔ Company Pivot |
| `ApiUser` | 321339 | API-Only User-Markierung |
| `ResponsibleCompanyUser` | 342360 | Verantwortliche User pro Company |
| `Contact` | 365411 | Ansprechpartner einer Firma |
| `NewsletterSubscription` | 418469 | Newsletter-Anmeldungen |
| `Category` | 476494 | Kategorien (i18n, sluggable) |
| `PressRelease` | 500575 | Pressemitteilungen (mit Teaser-Range, Status, SEO) |
| `PressReleaseContact` | 583601 | PM ↔ Contact Pivot |
| `PressReleaseImage` | 608644 | Bilder zu PMs |
| `PromotionLink` | 650684 | Werbelinks |
| `PromotionLinkCategory` | 687705 | PromotionLink ↔ Category Pivot |
| `FooterCode` | 707733 | Custom Footer-HTML pro Kategorie/Sprache |
| `CategoryFooterCode` | 735753 | Pivot |
| `Blacklist` | 755768 | Worte für Spam-Check |
| `UserBillingAddress` | 771807 | Rechn.-Adresse am User |
| `InvoiceBillingAddress` | 809841 | Rechn.-Adresse auf Rechnung (Snapshot) |
| `UserPaymentOptionCompany` | 854874 | Abo ↔ Firma |
### 3.2 Entitäten aus `sfDoctrineGuardPaymentPlugin`
| Entität | Zweck |
|---|---|
| `PaymentOption` | Produkt-Definition (Preis, Typ: recurring/onetime/single) |
| `PaymentOptionReference` | Self-referencing, Parent→Child (z. B. Aufpreispakete) |
| `PaymentOptionExcludeGroup` | Gruppen, die Option NICHT buchen dürfen |
| `PaymentOptionAccessGroup` | Gruppen, die durch Option Zugriff erhalten |
| `UserPaymentOption` | Gebuchtes Abo (User ↔ Produkt), Status, Laufzeit |
| `UserPaymentOptionReference` | Self-referencing |
| `UserPayment` | Zahlungsdatensatz |
| `Invoice` | Rechnung (mit Mahnungen, Fälligkeit) |
| `UserBillingAddress` | (hier nochmal definiert) |
| `InvoiceBillingAddress` | (hier nochmal definiert) |
| `Coupon` | Gutschein |
### 3.3 sfGuard-Tabellen
`sfGuardUser`, `sfGuardGroup`, `sfGuardPermission`, `sfGuardUserGroup`, `sfGuardGroupPermission`, `sfGuardUserPermission`, `sfGuardRememberKey` → Mapping auf Laravel `users` + Spatie `roles`/`permissions`/`model_has_*`.
### 3.4 Besondere Doctrine-Features
| Feature | Verwendung | Laravel-Äquivalent |
|---|---|---|
| `actAs: Timestampable` | auf fast allen Entitäten | `created_at`/`updated_at` (Standard) |
| `actAs: I18n` | `Salutation`, `Category`, `PaymentOption` | Translation-Tabellen oder `spatie/laravel-translatable` |
| `actAs: Sluggable` | `Company`, `Category`, `PressRelease`, `PressReleaseImage` | `spatie/laravel-sluggable` |
| `inheritance: column_aggregation` | `Agency extends Company` | Entweder gemeinsames Model mit `type`-Scope, oder Parent+Child-Model mit globalem Scope |
| `relations refClass` | viele M:N | Pivot-Tabellen, `belongsToMany` |
---
## 4. Routing (`apps/backend/config/routing.yml`)
Auszug **15 `sfDoctrineRouteCollection`** (auto-generated REST für alle CRUD-Entitäten) + folgende Custom-Routes:
| Route | URL | Ziel |
|---|---|---|
| `homepage` | `/` | `adminCenter::index` |
| `change` | `/mychange` | `adminCenter::change` |
| `sf_guard_signin` | `/login` | Login |
| `sf_guard_signout` | `/logout` | Logout |
| `sf_guard_password` | `/request_password` | Password-Reset |
| `usercp` | `/usercp` | User-CP |
| `masterdata` | `/masterdata` | Stammdaten |
| `portalcp` | `/portalcp` | Portal-CP |
| `promotioncp` | `/promotioncp` | Promotion |
| `pressrelease_company_autocomplete` | `/pressrelease/companyautocomplete` | AJAX |
| `company_user_autocomplete` | `/company/userautocomplete` | AJAX |
| `press_release_autocomplete_url` | `/ajax/press_release_autocomplete` | AJAX |
| `sf_image` | `/thumbnails/sf_image/:format/:filepath.:sf_format` | Thumbnails |
| `slug_image` | `/thumbnails/:type/:format/:path/:slug-:id.:sf_format` | Thumbnails (Slug) |
→ Abbildung auf `routes/admin.php` (bereits zu 80 % vorhanden) + ein paar Livewire-Aktionen.
---
## 5. Admin-Menü (`config/adminMenu/hnav.yml`)
```
Home
├─ Master data
│ ├─ Countries
│ ├─ Salutations
│ └─ Blacklists
├─ User CP
│ ├─ Users
│ ├─ Groups
│ ├─ Permissions
│ └─ Newsletter subscription
├─ Billing
│ ├─ Payment options
│ ├─ Coupons
│ └─ Invoices
├─ Portal CP
│ ├─ Press releases
│ ├─ Press release images
│ ├─ Categories
│ ├─ Companies
│ └─ Contacts
└─ Promotions
├─ Promotion links
└─ Footer code
```
→ Diese Struktur ist im neuen Laravel-Projekt bereits in der `sidebar.blade.php`-Navigation abgebildet.
---
## 6. Cron-Scripts (`cron_script_server.sh`)
```bash
php symfony sfp:user-payment-create --application=frontend
php symfony sfp:invoice-create --application=frontend --culture=de
php symfony sfp:invoice-reminder --application=frontend --culture=de
# php symfony sfp:user-paymentoption-expire --application=frontend (deaktiviert)
```
Dazu `sfpCron::index` (HTTP-getriggert, sehr unsicher: Shared-Secret als URL-Parameter).
**Ziel-Mapping:**
| Legacy-Task | Neu |
|---|---|
| `sfp:user-payment-create` | Job `CreateRecurringPayments` (daily) |
| `sfp:invoice-create` | Job `GenerateInvoices` (daily) |
| `sfp:invoice-reminder` | Job `SendInvoiceReminders` (daily) |
| `sfp:user-paymentoption-expire` | Job `ExpirePaymentOptions` (daily) |
Alles über Laravel Scheduler → `routes/console.php`.
---
## 7. API (aus `lib/ApiActions.class.php` + Frontend-Modulen)
- **Auth**: Statischer `api_key` im User-Profil (String, SHA1-base64).
- **CSRF**: Für API-Requests in `prepareForm()` deaktiviert.
- **Endpoints** (exakte Liste siehe [`07-API-MIGRATION.md`](./07-API-MIGRATION.md)):
- `POST /pressrelease/create` neue PM anlegen
- `POST /pressreleaseimage/upload` Bild hochladen
- `GET /pressrelease/list` PMs des Users
- `GET /company/list`
- `POST /newsletter/subscribe`
- …
---
## 8. Mailer (`lib/bpMailer.class.php`)
- Templating via `get_partial()` in Symfony.
- Versand via SwiftMailer.
→ Ersetzt durch:
- Laravel `Mailable` + Blade-Templates
- Queues (`mail` queue)
---
## 9. Frontend-Assets / Thumbnails
- URL-Format: `/thumbnails/pressreleaseimage/thumb_200/pr/<slug>-<id>.jpg`
- Generator: `sfImageTransformPlugin`
- Pfade referenzieren Slugs → bei Slug-Änderung Broken-Links
→ Ersatz: `intervention/image` + `/storage/images/...` + `public/thumbnails/...`. Für alte URLs **302-Redirect-Middleware**.
---
## 10. Vorarbeiten im Repository (nicht verlieren!)
1. **`_businessportal24.com/dev/`** Bereits extrahiertes Core-Package mit DTOs, Enums, Value Objects, Domain-Events. Inhalte prüfen + dort wo sinnvoll in Laravel-App übernehmen.
2. **`_businessportal24.com/dev/migration/`** Vorhandene Migrations-Doku (CHECKLIST, IMPLEMENTATION etc.) als Referenz nutzen, aber **nicht mehr pflegen**.
3. **`dev/_old/Models/`** & **`dev/_old/migrations/`** Früher automatisch erzeugte Eloquent-Modelle/-Migrations aus dem alten Schema (2024). Wert: Nützliches Mapping der Spalten-/Typ-Namen. **NICHT** 1:1 übernehmen Schema wird modernisiert.
---
## 11. „Kritische" Stellen (Achtung bei Migration)
| Datei / Ort | Problem |
|---|---|
| `PressePortalPlugin/lib/helper/PaypalCredentialsHelper.php` (oder vergleichbar) | Hart-kodierte PayPal-Credentials → entfällt (nur Stripe) |
| `sfpCron/actions/actions.class.php` | Shared Secret `G8ZvEbnP8fEPfnWX4L` in URL; `exec()`-Call → entfällt |
| `sfGuardUser.password`-Feld | `sha1($salt.$password)` → Laravel bcrypt, Legacy-Hasher nötig |
| `Company.ctype` enum | Inheritance-Feld; bei Migration entscheiden, ob `type enum('agency','company')` oder Single-Table |
| `sfGuardUserProfile.api_key` | Wird von API-Clients genutzt → Umwandlung nach Sanctum + Keep-Alive |
| `PressRelease.text` | `string(40000)` in MySQL 8 auf `TEXT` oder `MEDIUMTEXT` mappen |
| Thumbnails mit `/slug-id.ext` | Bei Slug-Änderung 404; neues Schema sollte `id` primär nutzen, Slug redirectbar |
| Mehrsprachigkeit `I18n` behavior | Aktuell `de` + `en` Daten in `*_translation`-Tabellen siehe [`04-DATA-MODEL.md`](./04-DATA-MODEL.md) |