- Dodano PSR-4 autoloader do wszystkich 6 punktów wejścia - Shared\: CacheHandler, Helpers, Html, ImageManipulator, Tpl - Domain\: LanguagesRepository, SettingsRepository, UserRepository - Stare class.*.php → cienkie wrappery (kompatybilność wsteczna) - Dodano dokumentację: docs/PROJECT_STRUCTURE.md + pozostałe docs/ - Dodano CLAUDE.md z workflow Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
179 lines
8.6 KiB
Markdown
179 lines
8.6 KiB
Markdown
# Form Edit System - Dokumentacja użycia
|
|
|
|
## Architektura
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ Controller │
|
|
│ ┌─────────────────┐ ┌─────────────────┐ │
|
|
│ │ edit() │ │ save() │ │
|
|
│ │ - buduje VM │ │ - walidacja │ │
|
|
│ │ - renderuje │ │ - zapis │ │
|
|
│ └────────┬────────┘ └─────────────────┘ │
|
|
└───────────┼─────────────────────────────────────────────────┘
|
|
│
|
|
▼
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ FormEditViewModel │
|
|
│ - title, formId, data, fields, tabs, actions │
|
|
│ - validationErrors, persist, languages │
|
|
└───────────┬─────────────────────────────────────────────────┘
|
|
│
|
|
▼
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ components/form-edit.php (szablon) │
|
|
│ ┌─────────────────────────────────────────────────────┐ │
|
|
│ │ FormFieldRenderer - renderuje każde pole │ │
|
|
│ │ ├─ input, select, textarea, switch │ │
|
|
│ │ ├─ date, datetime, editor, image │ │
|
|
│ │ └─ lang_section (zagnieżdżone pola) │ │
|
|
│ └─────────────────────────────────────────────────────┘ │
|
|
└─────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
## Pliki systemu
|
|
|
|
| Plik | Opis |
|
|
|------|------|
|
|
| `autoload/admin/ViewModels/Forms/FormFieldType.php` | Stale typow pol |
|
|
| `autoload/admin/ViewModels/Forms/FormField.php` | Factory methods per typ |
|
|
| `autoload/admin/ViewModels/Forms/FormTab.php` | Zakladki |
|
|
| `autoload/admin/ViewModels/Forms/FormAction.php` | Akcje (zapisz, anuluj) |
|
|
| `autoload/admin/ViewModels/Forms/FormEditViewModel.php` | ViewModel formularza |
|
|
| `autoload/admin/Support/Forms/FormValidator.php` | Walidacja pol |
|
|
| `autoload/admin/Support/Forms/FormRequestHandler.php` | Obsluga POST + persist |
|
|
| `autoload/admin/Support/Forms/FormFieldRenderer.php` | Renderowanie HTML |
|
|
| `admin/templates/components/form-edit.php` | Uniwersalny szablon |
|
|
|
|
## Przykład użycia w kontrolerze
|
|
|
|
```php
|
|
use admin\ViewModels\Forms\FormEditViewModel;
|
|
use admin\ViewModels\Forms\FormField;
|
|
use admin\ViewModels\Forms\FormTab;
|
|
use admin\ViewModels\Forms\FormAction;
|
|
use admin\Support\Forms\FormRequestHandler;
|
|
|
|
class BannerController
|
|
{
|
|
public function edit(): string
|
|
{
|
|
$banner = $this->repository->find($id);
|
|
$languages = \admin\factory\Languages::languages_list();
|
|
|
|
$viewModel = new FormEditViewModel(
|
|
formId: 'banner-edit',
|
|
title: 'Edycja banera',
|
|
data: $banner,
|
|
tabs: [
|
|
new FormTab('settings', 'Ustawienia', 'fa-wrench'),
|
|
new FormTab('content', 'Zawartość', 'fa-file'),
|
|
],
|
|
fields: [
|
|
// Zakładka Ustawienia
|
|
FormField::text('name', [
|
|
'label' => 'Nazwa',
|
|
'tab' => 'settings',
|
|
'required' => true,
|
|
]),
|
|
FormField::switch('status', [
|
|
'label' => 'Aktywny',
|
|
'tab' => 'settings',
|
|
]),
|
|
FormField::date('date_start', [
|
|
'label' => 'Data rozpoczęcia',
|
|
'tab' => 'settings',
|
|
]),
|
|
|
|
// Sekcja językowa w zakładce Zawartość
|
|
FormField::langSection('translations', 'content', [
|
|
FormField::image('src', ['label' => 'Obraz']),
|
|
FormField::text('url', ['label' => 'Url']),
|
|
FormField::editor('text', ['label' => 'Treść']),
|
|
]),
|
|
],
|
|
actions: [
|
|
FormAction::save('/admin/banners/save', '/admin/banners'),
|
|
FormAction::cancel('/admin/banners'),
|
|
],
|
|
languages: $languages,
|
|
persist: true,
|
|
);
|
|
|
|
return \Tpl::view('components/form-edit', ['form' => $viewModel]);
|
|
}
|
|
|
|
public function save(): void
|
|
{
|
|
$formHandler = new FormRequestHandler();
|
|
$viewModel = $this->buildFormViewModel(); // jak w edit()
|
|
|
|
$result = $formHandler->handleSubmit($viewModel, $_POST);
|
|
|
|
if (!$result['success']) {
|
|
// Błędy walidacji - zapisane automatycznie do sesji
|
|
echo json_encode(['success' => false, 'errors' => $result['errors']]);
|
|
exit;
|
|
}
|
|
|
|
// Sukces - persist wyczyszczony automatycznie
|
|
$this->repository->save($result['data']);
|
|
echo json_encode(['success' => true]);
|
|
exit;
|
|
}
|
|
}
|
|
```
|
|
|
|
## Dostępne typy pól
|
|
|
|
| Typ | Metoda | Opcje |
|
|
|-----|--------|-------|
|
|
| `text` | `FormField::text(name, ['label' => '...', 'required' => true])` | placeholder, help |
|
|
| `number` | `FormField::number(name, [...])` | - |
|
|
| `email` | `FormField::email(name, [...])` | walidacja formatu |
|
|
| `password` | `FormField::password(name, [...])` | - |
|
|
| `date` | `FormField::date(name, [...])` | datetimepicker |
|
|
| `datetime` | `FormField::datetime(name, [...])` | datetimepicker z czasem |
|
|
| `switch` | `FormField::switch(name, [...])` | checked (bool) |
|
|
| `select` | `FormField::select(name, ['options' => [...]])` | options: [key => label] |
|
|
| `textarea` | `FormField::textarea(name, ['rows' => 4])` | rows |
|
|
| `editor` | `FormField::editor(name, ['toolbar' => 'MyTool'])` | CKEditor |
|
|
| `image` | `FormField::image(name, ['filemanager' => true])` | filemanager URL |
|
|
| `file` | `FormField::file(name, [...])` | filemanager |
|
|
| `hidden` | `FormField::hidden(name, value)` | - |
|
|
| `color` | `FormField::color(name, ['label' => '...'])` | HTML5 color picker + text input |
|
|
| `lang_section` | `FormField::langSection(name, 'tab', [fields])` | pola per język |
|
|
|
|
## Walidacja
|
|
|
|
Walidacja jest automatyczna na podstawie właściwości pól:
|
|
- `required` - pole wymagane
|
|
- `type` = `email` - walidacja formatu e-mail
|
|
- `type` = `number` - walidacja liczby
|
|
- `type` = `date` - walidacja formatu YYYY-MM-DD
|
|
|
|
Dla sekcji językowych walidacja jest powtarzana dla każdego aktywnego języka.
|
|
|
|
## Persist (zapamiętywanie danych)
|
|
|
|
Gdy `persist = true`:
|
|
1. Przy błędzie walidacji dane są zapisywane w `$_SESSION['form_persist'][$formId]`
|
|
2. Formularz automatycznie przywraca dane z sesji przy ponownym wyświetleniu
|
|
3. Po udanym zapisie sesja jest czyszczona automatycznie przez `FormRequestHandler`
|
|
|
|
## Przerabianie istniejących formularzy
|
|
|
|
1. **Kontroler** - zamień `view\Xxx::edit()` na `FormEditViewModel`
|
|
2. **Repository** - dostosuj `save()` do formatu z `FormRequestHandler` (lub dodaj wsparcie dla obu formatów)
|
|
3. **Szablon** - usuń stary szablon lub zostaw jako fallback
|
|
4. **Testy** - zaktualizuj testy jeśli zmienił się format danych
|
|
|
|
## Aktualizacja 2026-02-15 (ver. 0.275)
|
|
|
|
- Modul `ShopCategory` zostal zmigrowany do warstwy Domain + DI, ale formularz kategorii nadal korzysta z legacy `gridEdit`.
|
|
- W ramach migracji wydzielono skrypty UI do osobnych partiali `*-custom-script.php` (lista, browse, edycja, produkty), co upraszcza dalsze przepiecie formularza na `components/form-edit`.
|
|
- Po migracji `ShopCategory` kolejnym kandydatem do pelnej migracji formularza na Form Edit System pozostaje modul `Order` (zgodnie z `REFACTORING_PLAN.md`).
|
|
|
|
---
|
|
*Dokument aktualizowany: 2026-02-15*
|