--- phase: 06-admin-base plan: 01 status: complete completed: 2026-04-30 --- # SUMMARY: Plan 06-01 — Forms infrastructure ## Co zrobiono Przeniesiono z shopPRO do cmsPRO warstwę Form Edit System pod nowy namespace `Admin\` (PascalCase). Wszystkie pliki ładują się przez Composer PSR-4, smoke test runtime potwierdza poprawne działanie walidacji. ## Pliki utworzone (6) | Plik | Linii | Namespace | |------|-------|-----------| | `autoload/admin/ViewModels/Forms/FormEditViewModel.php` | 178 | `Admin\ViewModels\Forms` | | `autoload/admin/ViewModels/Forms/FormField.php` | 364 | `Admin\ViewModels\Forms` | | `autoload/admin/ViewModels/Forms/FormFieldType.php` | 25 | `Admin\ViewModels\Forms` | | `autoload/admin/ViewModels/Forms/FormTab.php` | 31 | `Admin\ViewModels\Forms` | | `autoload/admin/ViewModels/Forms/FormAction.php` | 89 | `Admin\ViewModels\Forms` | | `autoload/admin/Validation/FormValidator.php` | 196 | `Admin\Validation` | **Total**: 883 linii kodu PHP 7.4-kompatybilnego. ## Pliki zmodyfikowane (2) - `composer.json` — dodano `"require": { "php": ">=7.4" }`, mapowanie PSR-4 dla `Admin\` ustawione na realny case na disku - `vendor/composer/autoload_*` — regenerowane przez `composer dump-autoload` ## Smoke test (literalny output) ``` Admin\ViewModels\Forms\FormEditViewModel: OK Admin\ViewModels\Forms\FormField: OK Admin\ViewModels\Forms\FormFieldType: OK Admin\ViewModels\Forms\FormTab: OK Admin\ViewModels\Forms\FormAction: OK Admin\Validation\FormValidator: OK SMOKE: OK: Pole "E-mail" musi być poprawnym adresem e-mail. PHP_REQ: >=7.4 ``` `php -l` na wszystkich 6 plikach: 6× "No syntax errors detected". Zero regresji — `Domain\Articles\ArticlesRepository` i `Shared\Helpers\Helpers` ładują się dalej. ## Acceptance Criteria — status - [x] AC-1: Form ViewModels load via PSR-4 — wszystkie 5 klas + FormValidator - [x] AC-2: FormValidator namespace + dependency — `use Admin\ViewModels\Forms\...` działa - [x] AC-3: Smoke test walidacji e-maila — zwraca PL komunikat błędu - [x] AC-4: PHP `>=7.4` w composer.json + PascalCase namespace na wszystkich nowych plikach - [x] AC-5: Zero regresji — istniejące Domain/Shared repos działają ## Deviation: PSR-4 path mapping w composer.json **Plan zakładał:** `"Admin\\": "autoload/Admin/"` (PascalCase folder) **Zmienione na:** `"Admin\\": "autoload/admin/"` (lowercase folder) **Powód:** Windows file system jest case-insensitive — folder `autoload/admin/` (legacy) i `autoload/Admin/` (planowany) to ten sam katalog na dysku. Git tracked path = `admin/` (lowercase, ustanowione przez wcześniejsze fazy z legacy `controls/`, `factory/`, `view/`). Na produkcyjnym Linux (case-sensitive) PSR-4 z mapowaniem `"Admin\\": "autoload/Admin/"` nie znalazłby plików, bo realny katalog na disku to `admin/`. **Konsekwencje:** - Klasa `Admin\ViewModels\Forms\FormField` ładuje się z `autoload/admin/ViewModels/Forms/FormField.php` ✓ - Legacy `admin\controls\Articles` (lowercase namespace) NIE matches PSR-4 prefix `Admin\` (case-sensitive) — ładuje się przez legacy autoloader (`autoload/autoloader.php`) ✓ - Cross-platform safe: działa identycznie na Windows i Linux **Bonus zmiana (preventive):** `"Frontend\\": "autoload/Frontend/"` → `"Frontend\\": "autoload/front/"` z tego samego powodu — żeby Phase 14+ nie powtórzyła problemu. ## Boundaries — przestrzegane - ✓ Brak zmian w `autoload/admin/controls/`, `factory/`, `view/` (50+ plików legacy nietknięte) - ✓ Brak zmian w `autoload/Domain/`, `autoload/Shared/` - ✓ Brak zmian w `autoload/autoloader.php` - ✓ `composer.lock` nieruszony (`composer update` nie uruchamiany) - ✓ Tylko zmodyfikowano composer.json + vendor/composer/autoload_* (regen) ## Deferred issues / observations 1. **FormValidator constants nie ma** — komunikaty błędów to literały string. Mogłyby być stałe klasy (np. `MSG_REQUIRED`, `MSG_INVALID_EMAIL`) dla i18n w przyszłości. Przeniesienie 1:1 z shopPRO (zachowanie kompatybilności). 2. **FormField fluent setters mile by były** — obecnie 17-argumentowy konstruktor + 14 factory methods. Dla Phase 7+ kontrolerów to OK, ale builder pattern (`FormField::text('name')->label('X')->required()->placeholder('Y')`) byłby czystszy. Deferred. 3. **`switch` jako nazwa metody** (`FormField::switch()`) — w PHP < 8.0 to słowo kluczowe i nie może być statycznym nazwiskiem metody w niektórych kontekstach. PHP 7.4 dopuszcza je jako nazwę metody (działa), ale uwaga przy edycji w niektórych edytorach. Zachowane bo shopPRO też tak ma. 4. **FormTab/FormAction bez factory methods** — tylko konstruktor. To jest design choice z shopPRO; nie zmieniam. ## Setup dla Plan 06-02 Po 06-01 założenia stabilne dla Plan 06-02 (Controller infrastructure): - `Admin\` namespace działa via PSR-4 → mapowanie do `autoload/admin/` - composer.json deklaruje `php: >=7.4` - Form VMs dostępne — `BaseController` może budować/zwracać `FormEditViewModel` - Konwencja PascalCase utrwalona — `Admin\Base\BaseController`, `Admin\Support\TableListRequestFactory` Plan 06-02 doda: - `autoload/admin/Support/TableListRequestFactory.php` (`Admin\Support\TableListRequestFactory`) - `autoload/admin/Base/BaseController.php` (`Admin\Base\BaseController`)