49 KiB
Plan Refaktoryzacji shopPRO - Domain-Driven Architecture
Cel
Stopniowe przeniesienie logiki biznesowej do architektury warstwowej:
- Domain/ - logika biznesowa (core)
- Admin/ - warstwa administratora
- Frontend/ - warstwa użytkownika
- Shared/ - współdzielone narzędzia
Docelowa struktura
autoload/
├── Domain/ # Logika biznesowa (CORE) - namespace \Domain\
│ ├── Product/
│ │ ├── ProductRepository.php # ✅ Zmigrowane (getQuantity, getPrice, getName, find, updateQuantity, archive, unarchive)
│ │ ├── ProductService.php # Logika biznesowa (przyszłość)
│ │ └── ProductCacheService.php # Cache produktu (przyszłość)
│ ├── Banner/
│ │ └── BannerRepository.php # ✅ Zmigrowane (find, delete, save)
│ ├── Settings/
│ │ └── SettingsRepository.php # ✅ Zmigrowane (saveSettings, getSettings) - bezposrednio DB
│ ├── Dictionaries/
│ │ └── DictionariesRepository.php # ✅ Zmigrowane (listForAdmin, find, save, delete, allUnits)
│ ├── Cache/
│ │ └── CacheRepository.php # ✅ Zmigrowane (clearCache)
│ ├── Order/
│ ├── Category/
│ └── ...
│
├── admin/ # Warstwa administratora (istniejący katalog!)
│ ├── Controllers/ # Nowe kontrolery - namespace \admin\Controllers\
│ │ ├── ArticlesController.php
│ │ ├── BannerController.php
│ │ ├── DictionariesController.php
│ │ ├── FilemanagerController.php
│ │ ├── ProductArchiveController.php
│ │ └── SettingsController.php
│ ├── controls/ # Stare kontrolery (legacy fallback)
│ ├── factory/ # Stare helpery (legacy)
│ └── view/ # Widoki (statyczne - OK bez zmian)
│
├── Frontend/ # Warstwa użytkownika (przyszłość)
│ ├── Controllers/
│ └── Services/
│
├── Shared/ # Współdzielone narzędzia
│ ├── Cache/
│ │ ├── CacheHandler.php
│ │ └── RedisConnection.php
│ └── Helpers/
│ └── S.php
│
└── [LEGACY] # Stare klasy (stopniowo deprecated)
├── shop/
├── admin/factory/
└── front/factory/
WAŻNE: Konwencja namespace → katalog (Linux case-sensitive!)
\Domain\→autoload/Domain/(duże D - nowy katalog)\admin\Controllers\→autoload/admin/Controllers/(małe a - istniejący katalog)- NIE używać
\Admin\(duże A) bo na serwerze Linux katalog toadmin/(małe a)
Zasady migracji
1. Stopniowość
- Przenosimy jedną funkcję na raz
- Zachowujemy kompatybilność wsteczną
- Stare klasy działają jako fasady do nowych
2. Dependency Injection zamiast statycznych metod
// ❌ STARE - statyczne
class Product {
public static function getQuantity($id) {
global $mdb;
return $mdb->get('pp_shop_products', 'quantity', ['id' => $id]);
}
}
// ✅ NOWE - instancje z DI
class ProductRepository {
private $db;
public function __construct($db) {
$this->db = $db;
}
public function getQuantity($id) {
return $this->db->get('pp_shop_products', 'quantity', ['id' => $id]);
}
}
3. Fasady dla kompatybilności
// Stara klasa wywołuje nową
namespace shop;
class Product {
public static function getQuantity($id) {
global $mdb;
$repo = new \Domain\Product\ProductRepository($mdb);
return $repo->getQuantity($id);
}
}
Proces migracji funkcji
Krok 1: Wybór funkcji
- Wybierz prostą funkcję statyczną
- Sprawdź jej zależności
- Przeanalizuj gdzie jest używana
Krok 2: Stworzenie nowej struktury
- Utwórz folder
Domain/{Module}/ - Stwórz odpowiednią klasę (Repository/Service/Entity)
- Przenieś logikę
Krok 3: Znalezienie użyć
grep -r "Product::getQuantity" .
Krok 4: Aktualizacja wywołań
- Opcja A: Bezpośrednie wywołanie nowej klasy
- Opcja B: Fasada w starej klasie (zalecane na początek)
Krok 5: Testy
- Napisz test jednostkowy dla nowej funkcji
- Sprawdź czy stare wywołania działają
Status migracji
✅ Zmigrowane moduły
- Cache (częściowo)
- ✅ CacheHandler - ma delete/deletePattern
- ✅ RedisConnection - singleton
- ✅ S::clear_product_cache() - nowa metoda
🔄 Status modułów
-
Product
- ✅ get_product_quantity() - ZMIGROWANE (2025-02-05) 🎉
- Nowa klasa:
Domain\Product\ProductRepository::getQuantity() - Fasada w:
shop\Product::get_product_quantity() - Test:
tests/Unit/Domain/Product/ProductRepositoryTest.php - Testy: ✅ 5/5 przechodzą
- Aktualizacja: ver. 0.238
- Użycie DI: ✅ Konstruktor przyjmuje
$db
- Nowa klasa:
- ✅ get_product_price() - ZMIGROWANE (2026-02-05) 🎉
- Nowa metoda:
Domain\Product\ProductRepository::getPrice() - Fasada w:
shop\Product::get_product_price() - Testy: ✅ 4 nowe testy (cena regularna, promocyjna, promo wyższa, nie znaleziono)
- Użycie:
front\factory\ShopPromotion(linia 132) - Aktualizacja: ver. 0.239
- Nowa metoda:
- ✅ get_product_name() - ZMIGROWANE (2026-02-05) 🎉
- Nowa metoda:
Domain\Product\ProductRepository::getName() - Fasada w:
shop\Product::get_product_name() - Testy: ✅ 2 nowe testy (nazwa znaleziona, nie znaleziona)
- Użycie: brak aktywnych wywołań (przygotowane na przyszłość)
- Aktualizacja: ver. 0.239
- Nowa metoda:
- ✅ archive() / unarchive() - ZMIGROWANE (2026-02-06) 🎉
- Nowe metody:
Domain\Product\ProductRepository::archive(),unarchive() - Nowy kontroler:
admin\Controllers\ProductArchiveController(DI, instancyjny) - Szablony:
admin/templates/product-archive/(rename zarchive/, dawniejproduct_archive/) - Testy: ✅ 4 nowe testy repozytorium + 6 testów kontrolera
- FIX: SQL bug w
ajax_products_list_archive()(puste wyszukiwanie + brakarchive = 1) - Dalsze porządki: ver. 0.252 (nowy table-list, wydzielony custom script, usunięte legacy pliki)
- Aktualizacja: ver. 0.241 / 0.252
- Nowe metody:
- is_product_on_promotion() - NASTĘPNA 👉
- ✅ get_product_quantity() - ZMIGROWANE (2025-02-05) 🎉
-
Banner (DEMO pełnej migracji kontrolera)
- ✅ BannerRepository - ZMIGROWANE (2026-02-05) 🎉
- Nowa klasa:
Domain\Banner\BannerRepository(find, delete, save, saveTranslations) - Nowy kontroler:
admin\Controllers\BannerController(DI, instancyjny) - Router:
admin\Site::route()→ sprawdza nowy kontroler → fallback na stary - Testy: ✅ 4 testy (find z tłumaczeniami, not found, delete, save)
- Stary kontroler
admin\controls\Bannersdziała jako niezależny fallback - Stara factory
admin\factory\Bannerszachowana bez zmian (fallback) - Aktualizacja: ver. 0.239
- Nowa klasa:
- ✅ BannerRepository - ZMIGROWANE (2026-02-05) 🎉
-
Articles (migracja kontrolera - etap edit/details)
- ✅ ArticleRepository::find() - ZMIGROWANE (2026-02-06) 🎉
- Nowa klasa:
Domain\Article\ArticleRepository(find: artykul + relacje) - Nowy kontroler:
admin\Controllers\ArticlesController(DI, instancyjny) - Zmigrowana akcja:
article_edit->edit(mapowanie wadmin\Site::$actionMap) - Kompatybilność:
admin\factory\Articles::article_details()deleguje do nowego repozytorium - Legacy cleanup: metody przejęte przez nowe kontrolery oznaczone
@deprecatedwadmin\controls\Articles|Banners|Settings - Testy repozytorium rozszerzone o czyszczenie nieprzypisanych plik<69>w/zdj<64><6A>
- Aktualizacja: ver. 0.243
- Nowa klasa:
- ✅ ArticleRepository::save() - ZMIGROWANE (2026-02-06) 🎉
- Metoda
save()z prywatnych helperow (buildArticleRow, buildLangRow, saveTranslations, savePages, assignTempFiles, assignTempImages, deleteMarkedFiles, deleteMarkedImages) - Zmigrowana akcja:
article_save->save(mapowanie wadmin\Site::$actionMap) - Kompatybilnosc:
admin\factory\Articles::article_save()deleguje do repozytorium - Testy: 7 nowych testow save (create, update, translations, pages, marked delete)
- Aktualizacja: ver. 0.244
- Metoda
- ✅ ArticleRepository::archive() - ZMIGROWANE (2026-02-06) 🎉
- Metoda
archive()(ustawia status = -1) - Zmigrowana akcja:
article_delete->delete(mapowanie wadmin\Site::$actionMap) - Kompatybilnosc:
admin\factory\Articles::articles_set_archive()deleguje do repozytorium - Testy: 2 nowe testy archive (success, failure)
- Aktualizacja: ver. 0.245
- Metoda
- ✅ ArticlesController::browseList() - ZMIGROWANE (2026-02-07) 🎉
- Nowa metoda kontrolera:
browseList()(DI, instancyjna) - Zmigrowana akcja:
browse_list->browseList(mapowanie wadmin\Site::$actionMap) - Legacy cleanup: usuniety
autoload/admin/controls/class.Articles.php(brak fallback dla modułu Articles) - Testy: 2 nowe testy kontraktu kontrolera (method exists + return type)
- Nowa metoda kontrolera:
- ✅ ArticlesController::galleryOrderSave() - ZMIGROWANE (2026-02-07) 🎉
- Nowa metoda kontrolera:
galleryOrderSave()(AJAX) - Zmigrowana akcja:
gallery_order_save->galleryOrderSave(mapowanie wadmin\Site::$actionMap) - Implementacja: używa
Domain\Article\ArticleRepository::saveGalleryOrder() - Testy: 2 nowe testy kontraktu kontrolera (method exists + return type)
- Nowa metoda kontrolera:
- ✅ Usuniecie legacy kontrolera Articles - ZMIGROWANE (2026-02-07) 🎉
- Usuniety plik:
autoload/admin/controls/class.Articles.php - Wymaganie dla aktualizacji: dodac wpis do
ver_X.XXX_files.txt - Wpis do usuniecia:
F: ../autoload/admin/controls/class.Articles.php
- Usuniety plik:
- ✅ Stabilizacja generatora
.htaccess- ZMIGROWANE (2026-02-07) 🎉- FIX: regula admin ma
QSA(query string dla sortowania/filtrow) - FIX:
\S::htacces()komentujeAddHandler|SetHandler|ForceTypedla zgodnosci z hostingiem - UPDATE:
libraries/htaccess.confzaktualizowany, aby poprawki nie znikaly po regeneracji
- FIX: regula admin ma
- ✅ ArticleRepository::find() - ZMIGROWANE (2026-02-06) 🎉
-
Settings (migracja kontrolera)
- ✅ SettingsRepository - ZMIGROWANE (2026-02-05) 🎉
- Nowa klasa:
Domain\Settings\SettingsRepository(saveSettings, getSettings) - Aktualny stan: bezpośredni dostęp do DB (usunięta delegacja do
admin\factory\Settings) - ver. 0.250 - Nowy kontroler:
admin\Controllers\SettingsController(DI, instancyjny) - Testy: ✅ 3 testy (instancja, metody)
- Stary kontroler
admin\controls\Settingszachowany jako fallback - Aktualizacja: ver. 0.240 / 0.250
- Nowa klasa:
- ✅ CacheRepository - ZMIGROWANE (2026-02-05) 🎉
- Nowa klasa:
Domain\Cache\CacheRepository(clearCache) - Używa
\S::delete_dir()+\RedisConnection - Testy: ✅ 4 testy (z Redis, bez Redis, niedostępny, struktura)
- Aktualizacja: ver. 0.240
- Nowa klasa:
- ✅ SettingsRepository - ZMIGROWANE (2026-02-05) 🎉
-
Dictionaries (migracja kontrolera i repozytorium)
- ✅ DictionariesRepository - ZMIGROWANE (2026-02-09) 🎉
- Nowa klasa:
Domain\Dictionaries\DictionariesRepository(listForAdmin, find, save, delete, allUnits) - Nowy kontroler:
admin\Controllers\DictionariesController(DI, instancyjny) - Migracja na nowe komponenty:
components/table-list+components/form-edit - Legacy cleanup: usunięto klasy z
admin\controls,admin\factory,front\factory - Aktualizacja: ver. 0.251
- Nowa klasa:
- ✅ DictionariesRepository - ZMIGROWANE (2026-02-09) 🎉
-
Filemanager (migracja routingu)
- ✅ FilemanagerController - ZMIGROWANE (2026-02-10) 🎉
- Nowy kontroler:
admin\Controllers\FilemanagerController - Naprawa błędu:
Invalid Key - Legacy cleanup: usunięto
autoload/admin/controls/class.Filemanager.phpiautoload/admin/view/class.FileManager.php - Aktualizacja: ver. 0.252
- Nowy kontroler:
- ✅ FilemanagerController - ZMIGROWANE (2026-02-10) 🎉
-
Users (migracja kontrolera i repozytorium)
- ✅ UserRepository - ZMIGROWANE (2026-02-12) 🎉
- Nowa klasa:
Domain\User\UserRepository(find, getById, save, delete, checkLogin, logon, details, updateById, sendTwofaCode, verifyTwofaCode) - Nowy kontroler:
admin\Controllers\UsersController(DI, instancyjny: view_list, user_edit, user_save, user_delete, login_form, twofa) - Router:
admin\Site- factory wpis dla moduluUsers - Fasada:
admin\factory\Usersdeleguje do repozytorium (backward compatibility dla login/2FA flow) - AJAX:
admin/ajax/users.php-check_loginoparty oUserRepository - Legacy cleanup: usuniety
autoload/admin/controls/class.Users.php - Testy: 25 testow repozytorium (CRUD, logon, 2FA, checkLogin) + 12 testow kontrolera (kontrakty + normalizeUser)
- Nowa klasa:
- ✅ UserRepository - ZMIGROWANE (2026-02-12) 🎉
-
Integrations (migracja kontrolera i repozytorium + cleanup Sellasist/Baselinker)
- ✅ IntegrationsRepository - ZMIGROWANE (2026-02-13) 🎉
- Nowa klasa:
Domain\Integrations\IntegrationsRepository(settings Apilo/ShopPRO, OAuth, product linking, API fetch) - Nowy kontroler:
admin\Controllers\IntegrationsController(DI, instancyjny) - Router:
admin\Site- factory wpis dla moduluIntegrations - Fasada:
admin\factory\Integrationsdeleguje do repozytorium (tylko Apilo + ShopPRO) - CLEANUP: usunieto integracje Sellasist i Baselinker z calego projektu
- Usuniete pliki:
controls/Integrations,controls/Baselinker,factory/Baselinker,front/factory/Shop,shop/ShopStatus, szablony sellasist/baselinker - Wyczyszczone referencje w: cron.php, Order, ShopStatuses, ShopTransport, ShopPaymentMethod, ShopProduct, config.php, front/factory/*
- Testy: 16 nowych testow (repozytorium) + 10 testow kontrolera
- Aktualizacja: ver. 0.263
- Nowa klasa:
- ✅ IntegrationsRepository - ZMIGROWANE (2026-02-13) 🎉
📋 Do zrobienia
- Order
- Category
- ShopAttribute
- ShopProduct (factory)
Testowanie
Framework: PHPUnit
Instalacja:
composer require --dev phpunit/phpunit
Struktura testów
tests/
├── Unit/
│ ├── Domain/
│ │ ├── Article/ArticleRepositoryTest.php
│ │ ├── Banner/BannerRepositoryTest.php
│ │ ├── Cache/CacheRepositoryTest.php
│ │ ├── Dictionaries/DictionariesRepositoryTest.php
│ │ ├── Product/ProductRepositoryTest.php
│ │ ├── Settings/SettingsRepositoryTest.php
│ │ ├── User/UserRepositoryTest.php
│ │ └── Integrations/IntegrationsRepositoryTest.php
│ └── admin/
│ └── Controllers/
│ ├── ArticlesControllerTest.php
│ ├── DictionariesControllerTest.php
│ ├── IntegrationsControllerTest.php
│ ├── ProductArchiveControllerTest.php
│ ├── SettingsControllerTest.php
│ └── UsersControllerTest.php
└── Integration/
Łącznie: 212 testów, 577 asercji
Przykład testu
// tests/Unit/Domain/Product/ProductRepositoryTest.php
use PHPUnit\Framework\TestCase;
use Domain\Product\ProductRepository;
class ProductRepositoryTest extends TestCase {
public function testGetQuantityReturnsCorrectValue() {
// Arrange
$mockDb = $this->createMock(\medoo::class);
$mockDb->method('get')->willReturn(10);
$repo = new ProductRepository($mockDb);
// Act
$quantity = $repo->getQuantity(123);
// Assert
$this->assertEquals(10, $quantity);
}
}
Zasady kodu
1. SOLID Principles
- Single Responsibility - jedna klasa = jedna odpowiedzialność
- Open/Closed - otwarty na rozszerzenia, zamknięty na modyfikacje
- Liskov Substitution - podklasy mogą zastąpić nadklasy
- Interface Segregation - wiele małych interfejsów
- Dependency Inversion - zależności od abstrakcji
2. Nazewnictwo
- Entity -
Product.php(reprezentuje obiekt domenowy) - Repository -
ProductRepository.php(dostęp do danych) - Service -
ProductService.php(logika biznesowa) - Controller -
ProductController.php(obsługa requestów)
3. Type Hinting
// ✅ DOBRE
public function getQuantity(int $id): ?int {
return $this->db->get('pp_shop_products', 'quantity', ['id' => $id]);
}
// ❌ ZŁE
public function getQuantity($id) {
return $this->db->get('pp_shop_products', 'quantity', ['id' => $id]);
}
Narzędzia pomocnicze
Autoloader (produkcja)
Autoloader w 9 entry pointach obsługuje dwie konwencje:
autoload/{namespace}/class.{ClassName}.php(legacy)autoload/{namespace}/{ClassName}.php(PSR-4, fallback)
Entry pointy: index.php, ajax.php, api.php, cron.php, cron-turstmate.php, download.php, admin/index.php, admin/ajax.php, cron/cron-xml.php
Static Analysis
composer require --dev phpstan/phpstan
vendor/bin/phpstan analyse autoload/Domain
Kolejność refaktoryzacji (priorytet)
- Cache ✅
- Product (w trakcie)
- ✅ getQuantity (ver. 0.238)
- ✅ getPrice (ver. 0.239)
- ✅ getName (ver. 0.239)
- ✅ archive / unarchive (ver. 0.241)
- is_product_on_promotion - NASTĘPNA 👉
- getFromCache
- getProductImg
- Banner ✅ (pełna migracja kontrolera, ver. 0.239)
- Settings ✅ (pełna migracja repo/kontrolera + cleanup legacy, ver. 0.250)
- Dictionaries ✅ (repo + kontroler + form/table, ver. 0.251)
- ProductArchive ✅ (migracja kontrolera + cleanup szablonów, ver. 0.252)
- Filemanager ✅ (migracja routingu + fix
Invalid Key, ver. 0.252) - Users ✅ (repo + kontroler + 2FA + legacy cleanup, ver. 0.253)
- Pages ✅ (repo + kontroler + drzewo stron + AJAX endpoints, ver. 0.262)
- Integrations ✅ (repo + kontroler + cleanup Sellasist/Baselinker, ver. 0.263)
- Order
- Category
- ShopAttribute
- Form Edit System - Nowy uniwersalny system formularzy edycji
- ✅ Klasy ViewModel:
FormFieldType,FormField,FormTab,FormAction,FormEditViewModel - ✅ Walidacja:
FormValidatorz obsługą reguł per pole i sekcje językowe - ✅ Persist:
FormRequestHandler- zapamiętywanie danych przy błędzie walidacji - ✅ Renderer:
FormFieldRenderer- renderowanie wszystkich typów pól - ✅ Szablon:
admin/templates/components/form-edit.php- uniwersalny layout - ✅ BannerController - przerobiony na nowy system formularzy
- Wspierane typy pól: text, number, email, password, date, datetime, switch, select, textarea, editor, image, file, hidden, lang_section
- Obsługa zakładek (vertical) i sekcji językowych (horizontal)
- Do zrobienia: Przerobić pozostałe kontrolery/formularze (Product, Category, Pages, itd.)
- ✅ Klasy ViewModel:
Rozpoczęto: 2025-02-05 Ostatnia aktualizacja: 2026-02-12
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) │ │
│ └─────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
Przykład użycia w kontrolerze
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) |
- |
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 wymaganetype=email- walidacja formatu e-mailtype=number- walidacja liczbytype=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:
- Przy błędzie walidacji dane są zapisywane w
$_SESSION['form_persist'][$formId] - Formularz automatycznie przywraca dane z sesji przy ponownym wyświetleniu
- Po udanym zapisie sesja jest czyszczona automatycznie przez
FormRequestHandler
Przerabianie istniejących formularzy
- Kontroler - zamień
view\Xxx::edit()naFormEditViewModel - Repository - dostosuj
save()do formatu zFormRequestHandler(lub dodaj wsparcie dla obu formatów) - Szablon - usuń stary szablon lub zostaw jako fallback
- Testy - zaktualizuj testy jeśli zmienił się format danych
Aktualizacja 2026-02-12 - Users
Users (migracja kontrolera i repozytorium)
- NOWE:
Domain\User\UserRepository(delete, find, save, checkLogin, logon, details, sendTwofaCode, verifyTwofaCode) - NOWE:
admin\Controllers\UsersController(view_list, user_edit, user_save, user_delete) - UPDATE: Router
admin\Site- nowy kontroler DI dla modu<64>uUsers - UPDATE:
admin\factory\Usersjako fasada delegujaca do repozytorium - UPDATE:
admin/ajax/users.php- endpointcheck_loginoparty oUserRepository - Testy po zmianie: 95 tests, 204 assertions
- UPDATE: UsersController:
view_list+user_editmigrowane na nowy system list/form (table-list + form-edit)
Aktualizacja 2026-02-12 (finalizacja Users)
- Users: pelna migracja na nowa architekture (Domain + DI Controller), bez fallbacku do legacy kontrolera/factory/view.
UsersControllerobsluguje:list/view_list,user_edit,user_save,user_delete,login_form,twofa.- Dodano walidacje warunkowa:
twofa_emailwymagany gdytwofa_enabled = 1. - Widoki users migrowane z
grid/gridEditnatable-listiform-edit.
Aktualizacja 2026-02-12 - Languages
- NOWE:
Domain\\Languages\\LanguagesRepository(languages + translations CRUD/list) - NOWE:
admin\\Controllers\\LanguagesController(DI) - UPDATE:
admin\\Site- nowy kontroler DI dla moduluLanguages - UPDATE:
admin\\factory\\Languagesjako fasada delegujaca do repozytorium - UPDATE: widoki
languages/*migrowane nacomponents/table-listicomponents/form-edit - CLEANUP: usunieto legacy
admin\\controls\\Languagesiadmin\\view\\Languages - Testy po zmianie: 130 tests, 301 assertions
Aktualizacja 2026-02-12 (Languages final)
- NOWE:
Domain\\Languages\\LanguagesRepository(list/save/delete dla jezykow i tlumaczen) - NOWE:
admin\\Controllers\\LanguagesController(DI) dla akcjiview_list/list,language_*,translation_* - UPDATE:
admin\\factory\\Languagesjako fasada delegujaca do repozytorium - CLEANUP: usunieto legacy
admin\\controls\\Languagesorazadmin\\view\\Languages - UPDATE: poprawki globalne
components/table-listdla krotkich kolumn/filtr<74>w
Aktualizacja 2026-02-12 (ver. 0.255)
- UPDATE: SettingsController, BannerController, DictionariesController, ArticlesController pobieraja liste jezykow przez Domain/Languages/LanguagesRepository (DI) zamiast legacy admin/factory/Languages.
- UPDATE: router DI (admin/Site) przekazuje LanguagesRepository do kontrolerow Articles, Banners, Settings, Dictionaries.
- UPDATE: pozostale aktywne odwolania legacy (admin/controls, admin/factory/Shop*) zostaly przepiete na LanguagesRepository.
- FIX: autoload/admin/factory/class.Languages.php poprawione na <?php (zgodnosc z short_open_tag=Off).
- Testy po zmianie: 130 tests, 303 assertions.
Aktualizacja 2026-02-12 (ver. 0.256)
-
Layouts - ZMIGROWANE (2026-02-12) ??
- NOWE:
Domain\\Layouts\\LayoutsRepository(find, save, delete, listForAdmin, menusWithPages, categoriesTree) - NOWE:
admin\\Controllers\\LayoutsController(DI) - UPDATE: lista
/admin/layouts/view_list/migrowana nacomponents/table-list - UPDATE: widok
layouts/layout-editkorzysta z danych dostarczonych przez repozytorium (bez wywolan legacy factory) - NOWE: partial
admin/templates/layouts/subcategories-list.php - CLEANUP: usuniete
autoload/admin/controls/class.Layouts.phpiautoload/admin/view/class.Layouts.php - KOMPATYBILNOSC:
autoload/admin/factory/class.Layouts.phpdeleguje do repozytorium
- NOWE:
-
Languages
- UPDATE:
Domain\\Languages\\LanguagesRepository::defaultLanguageId()jako wspolna metoda do pobierania jezyka domyslnego
- UPDATE:
-
Articles
- UPDATE:
admin\\Controllers\\ArticlesControllerkorzysta zDomain\\Layouts\\LayoutsRepository(DI) dla listy layoutow
- UPDATE:
-
Testy po zmianie: 141 tests, 336 assertions
Aktualizacja 2026-02-12 (ver. 0.257)
-
Newsletter - ZMIGROWANE (2026-02-12)
- NOWE:
Domain\\Newsletter\\NewsletterRepository(listy admin, szablony, ustawienia, kolejka wysylki) - NOWE:
Domain\\Newsletter\\NewsletterPreviewRenderer(wspolny render podgladu) - NOWE:
admin\\Controllers\\NewsletterController(DI) - UPDATE: routing DI (
admin\\Site) rozszerzony o modulNewsletter - UPDATE: widoki
/admin/newsletter/*migrowane nacomponents/table-listicomponents/form-edit - UPDATE:
admin\\factory\\Newsletterjako fasada do repozytorium - UPDATE:
front\\factory\\Newsletterbez zaleznosci odadmin\\view\\Newsletter - CLEANUP: usuniete
autoload/admin/controls/class.Newsletter.php,autoload/admin/view/class.Newsletter.php
- NOWE:
-
Testy po zmianie: 150 tests, 372 assertions
Aktualizacja 2026-02-12 (ver. 0.258)
- Newsletter
- UPDATE: tymczasowo wylaczono flow
prepare/send/preview(wymaga przebudowy). - UPDATE: tymczasowo wylaczono modul
Szablony uzytkownika. - UPDATE: aktywna obsluga tylko szablonow administracyjnych (
is_admin = 1). - CLEANUP: usuniete nieuzywane widoki
prepare.php,preview.php,email-templates-user.php.
- UPDATE: tymczasowo wylaczono flow
Aktualizacja 2026-02-12 (ver. 0.259)
- Scontainers - ZMIGROWANE (2026-02-12)
- NOWE:
Domain\Scontainers\ScontainersRepository(listForAdmin, find, save, delete, detailsForLanguage) - NOWE:
admin\Controllers\ScontainersController(DI) - UPDATE:
/admin/scontainers/view_list/migrowane nacomponents/table-list - UPDATE:
/admin/scontainers/container_edit/migrowane nacomponents/form-edit - UPDATE:
admin\factory\Scontainersjako fasada do repozytorium - UPDATE:
front\factory\Scontainerskorzysta z repozytorium domenowego - CLEANUP: usuniete
autoload/admin/controls/class.Scontainers.phpiautoload/admin/view/class.Scontainers.php
- NOWE:
- Testy po zmianie: 158 tests, 397 assertions
Aktualizacja 2026-02-12 (ver. 0.260)
- ArticlesArchive - ZMIGROWANE (2026-02-12)
- NOWE:
admin\Controllers\ArticlesArchiveController(DI) - UPDATE:
Domain\Article\ArticleRepositoryrozszerzone olistArchivedForAdmin(),restore(),deletePermanently() - UPDATE:
/admin/articles_archive/view_list/migrowane nacomponents/table-list - UPDATE: routing DI (
admin\Site) rozszerzony o modulArticlesArchive+ mapowaniearticle_restore -> restore - CLEANUP: usuniete
autoload/admin/controls/class.ArticlesArchive.php,autoload/admin/factory/class.ArticlesArchive.php,autoload/admin/view/class.ArticlesArchive.php
- NOWE:
- Testy po zmianie: 165 tests, 424 assertions
Plan 2026-02-13 - Refaktoryzacja /admin/articles/
- Przeniesc zaleznosci listy artykulow z
admin\factory\ArticlesdoDomain\Article\ArticleRepository(etykiety stron, operacje pomocnicze). - Dodac akcje routowane przez
admin\Controllers\ArticlesControllerdla operacji AJAX (article_image_alt_change,article_file_name_change,article_image_delete,article_file_delete). - Przepiac widok
admin/templates/articles/article-edit.phpz/admin/ajax.phpna endpointy/admin/articles/*. - Usunac legacy
admin\view\Articlesi zastapic rekurencje podstron przezTpl::view('articles/subpages-list', ...). - Usunac
admin/ajax/articles.phporaz odpiac include zadmin/ajax.php. - Przeszukac projekt pod pozostale zaleznosci i uruchomic testy modulu Articles.
Aktualizacja 2026-02-13 (ver. 0.261)
- Articles - dalsza refaktoryzacja
/admin/articles/- UPDATE:
Domain\Article\ArticleRepositoryrozszerzone o metody UI/admin:pagesSummaryForArticles(),updateImageAlt(),updateFileName(),markImageToDelete(),markFileToDelete(). - UPDATE:
admin\Controllers\ArticlesControllerobsluguje nowe akcje routingu:article_image_alt_change,article_file_name_change,article_image_delete,article_file_delete. - UPDATE: lista artykulow (
list) nie korzysta juz zadmin\factory\Articles::article_pages(). - UPDATE:
admin/templates/articles/article-edit.phpprzepiete z/admin/ajax.php?a=article_*na endpointy/admin/articles/article_*/. - UPDATE: rekurencja podstron w widoku oparta o
Tpl::view('articles/subpages-list', ...)(bezadmin\view\Articles). - CLEANUP: usuniete legacy pliki
autoload/admin/view/class.Articles.phporazadmin/ajax/articles.php;admin/ajax.phpnie includuje juzajax/articles.php.
- UPDATE:
- Testy po zmianie: 176 tests, 439 assertions.
Aktualizacja 2026-02-13 (ver. 0.261)
- Articles (/admin/articles)
- UPDATE:
Domain\Article\ArticleRepositoryrozszerzone osaveFilesOrder()oraz zapisfiles_orderprzysave()(eliminuje koniecznosc drugiego zapisu po sortowaniu). - UPDATE: routing DI (
admin\Site) rozszerzony o mapowaniefiles_order_save -> filesOrderSave. - UPDATE:
admin\Controllers\ArticlesController- nowa akcja AJAXfilesOrderSave. - UPDATE: widok
admin/templates/articles/article-edit-custom-script.php- drag&drop dla listy zalacznikow + hidden inputfiles_order. - UPDATE: potwierdzenia usuwania zdjec i zalacznikow przepiete na
jquery-confirmze stylemtable-list-confirm-dialog(jak na liscie artykulow). - FIX: dolaczona biblioteka
jquery-impromptuw widoku edycji artykulu dla kompatybilnosci.
- UPDATE:
- Testy po zmianie: 178 tests, 443 assertions.
Plan 2026-02-13 - Refaktoryzacja /admin/pages/
- Dodac
Domain\Pages\PagesRepository(CRUD menu/stron, drzewo stron, sortowanie, SEO, operacje AJAX). - Dodac
admin\Controllers\PagesController(DI) i przepiac routing/admin/pages/*na nowy kontroler. - Przebudowac widoki
admin/templates/pages/*tak, aby nie korzystaly zadmin\factory\Pagesiadmin\view\Pages. - Przepiac endpointy AJAX z
/admin/ajax.php?a=*na/admin/pages/*(save_pages_order,save_articles_order,generate_seo_link,cookie_*). - Przeszukac i zaktualizowac zaleznosci w innych modulach (
articles,layouts, helpery) powiazane z Pages. - Usunac legacy klasy/pliki Pages (
autoload/admin/controls/class.Pages.php,autoload/admin/view/class.Pages.php,autoload/admin/factory/class.Pages.php,admin/ajax/pages.php) po odpieciu zaleznosci. - Dodac/uzupelnic testy (
PagesRepository,PagesController) i uruchomic testy.
Aktualizacja 2026-02-13 - Pages (/admin/pages)
- NOWE:
Domain\Pages\PagesRepository(CRUD menu/stron, drzewo stron, porzadkowanie, SEO link, URL preview, cookies tree-state). - NOWE:
admin\Controllers\PagesController(DI) dla akcji:view_list/list,browse_list,pages_url_browser,menu_*,page_*,save_*_order,generate_seo_link,cookie_*. - UPDATE:
/admin/pages/*dziala bez legacyadmin\controls\Pagesiadmin\view\Pages. - UPDATE: widoki
admin/templates/pages/*przepiete na dane z kontrolera/repozytorium (bezadmin\factory\Pages). - UPDATE: endpointy zalezne od Pages w innych modulach (
articles,layouts,shop-category,shop-product) przepiete zadmin/ajax.php?a=*na/admin/pages/*. - CLEANUP: usuniete
autoload/admin/controls/class.Pages.php,autoload/admin/view/class.Pages.php,autoload/admin/factory/class.Pages.php,admin/ajax/pages.php;admin/ajax.phpnie includuje juzajax/pages.php. - Testy: OK (186 tests, 478 assertions).
Aktualizacja 2026-02-13 - Integrations (/admin/integrations)
- NOWE:
Domain\Integrations\IntegrationsRepository(settings Apilo/ShopPRO, OAuth, product linking, API fetch lists, product search/create, ShopPRO import). - NOWE:
admin\Controllers\IntegrationsController(DI) dla akcji:apilo_settings,apilo_settings_save,apilo_authorization,get_platform_list,get_status_types_list,get_carrier_account_list,get_payment_types_list,apilo_create_product,apilo_product_search,apilo_product_select_save,apilo_product_select_delete,shoppro_settings,shoppro_settings_save,shoppro_product_import. - UPDATE:
admin\factory\Integrationsjako fasada delegujaca doDomain\Integrations\IntegrationsRepository(tylko Apilo + ShopPRO). - CLEANUP: usunieto integracje Sellasist i Baselinker z calego projektu:
- Usuniete klasy:
admin\controls\Integrations,admin\controls\Baselinker,admin\factory\Baselinker,front\factory\Shop,shop\ShopStatus - Usuniete szablony:
integrations/sellasist-settings.php,integrations/baselinker-settings.php,admin/templates/baselinker/ - Wyczyszczone referencje w:
cron.php,cron/cron-xml.php,shop\Order,admin\controls\ShopStatuses,admin\controls\ShopTransport,admin\controls\ShopPaymentMethod,admin\controls\ShopProduct,admin\factory\ShopStatuses,admin\factory\ShopTransport,admin\factory\ShopProduct,front\factory\ShopStatuses,front\factory\ShopTransport,front\factory\ShopPaymentMethod,front\factory\ShopProduct,front\factory\ShopOrder,shop\Product,config.php - Wyczyszczone szablony:
shop-statuses/*,shop-transport/*,shop-payment-method/*,shop-product/*,site/main-layout.php
- Usuniete klasy:
- Testy: OK (212 tests, 577 assertions).
Plan 2026-02-13 - Refaktoryzacja /admin/shop_promotion/ (HITL)
- Etap 1 (analiza i kontrakt): potwierdzic docelowy kontrakt URL i kompatybilnosc wsteczna:
- kontrakt docelowy: tylko
/admin/shop_promotion/list/,/admin/shop_promotion/edit/,/admin/shop_promotion/save/,/admin/shop_promotion/delete/ - brak kompatybilnosci ze starymi URL i aliasami akcji (
view_list,promotion_delete)
- kontrakt docelowy: tylko
- Etap 2 (Domain): dodac
Domain\Promotion\PromotionRepository:listForAdmin(filters, sort, dir, page, perPage)z whitelist sortowania i bind paramsfind(int $id)+ domyslne dane dla nowego formularzasave(array $data): ?int(insert/update, normalizacja switchy, JSON dla kategorii)delete(int $id): boolcategoriesTree(?int $parentId): array(drzewo kategorii z tlumaczeniami, bez zaleznosci odadmin\factory\ShopCategory)
- Etap 3 (Admin Controller + routing DI): dodac
admin\Controllers\ShopPromotionControlleri przepiac routing:- rejestracja factory w
admin\Site::$newControllerspod modulemShopPromotion - akcje:
list,edit,save,delete - zachowac obsluge legacy payload (
valuesJSON) oraz obslugeform-edit($_POST)
- rejestracja factory w
- Etap 4 (widoki): przepiac modul z
grid/gridEditna nowe komponenty:- nowy widok listy oparty o
components/table-list(filtry: nazwa, aktywny) - nowy widok edycji oparty o
components/form-edit(+ pola custom dla drzew kategorii) - nowe partiale dla drzewa kategorii w module
shop-promotion(usuniecie zaleznosci odshop-product/subcategories-list) - nowy
shop-promotion/promotion-edit-custom-script.php(warunkowe pola pocondition_type, obsluga drzewa kategorii)
- nowy widok listy oparty o
- Etap 5 (zaleznosci i cleanup): przeszukac i odpiac legacy zaleznosci:
- menu admin: link kanoniczny na
/admin/shop_promotion/list/ - usunac legacy pliki po pelnym przepieciu:
autoload/admin/controls/class.ShopPromotion.phpautoload/admin/factory/class.ShopPromotion.phpadmin/templates/shop-promotion/view-list.php(grid)admin/templates/shop-promotion/promotion-edit.php(gridEdit)
- sprawdzic pozostale odwolania
ShopPromotionishop_promotion/view_listw calym repo
- menu admin: link kanoniczny na
- Etap 6 (testy): dodac/uzupelnic testy:
tests/Unit/Domain/Promotion/PromotionRepositoryTest.phptests/Unit/admin/Controllers/ShopPromotionControllerTest.php- uruchomic minimum: nowe testy modulu + pelny
composer test
- Etap 7 (dokumentacja po wdrozeniu): zaktualizowac:
DATABASE_STRUCTURE.md(dodacpp_shop_promotion, jesli nadal brak)PROJECT_STRUCTURE.mdREFACTORING_PLAN.md(sekcja "Aktualizacja ...")TESTING.md(nowy wynik suite)
Aktualizacja 2026-02-13 (ver. 0.264)
- ShopPromotion - migracja
/admin/shop_promotionna Domain + DI + nowe widoki- NOWE:
Domain\Promotion\PromotionRepository(listForAdmin,find,save,delete,categoriesTree, invalidacja cache aktywnych promocji) - NOWE:
admin\Controllers\ShopPromotionController(DI) z akcjamilist,edit,save,delete - UPDATE: routing DI (
admin\Site) rozszerzony o modulShopPromotion - UPDATE: modul
/admin/shop_promotion/*dziala nacomponents/table-listicomponents/form-edit - NOWE: widoki/partiale
shop-promotion/promotions-list,shop-promotion/promotion-edit,shop-promotion/promotion-categories-selector,shop-promotion/promotion-categories-tree,shop-promotion/promotion-edit-custom-script - CLEANUP: usuniete legacy
autoload/admin/controls/class.ShopPromotion.php,autoload/admin/factory/class.ShopPromotion.php,admin/templates/shop-promotion/view-list.php - UPDATE: menu admin przepiete na kanoniczny URL
/admin/shop_promotion/list/
- NOWE:
- Testy po zmianie: OK (222 tests, 609 assertions).
Aktualizacja 2026-02-13 (ver. 0.265)
- ShopPromotion - stabilizacja po migracji
- UPDATE: dodane
date_fromwDomain\Promotion\PromotionRepository(save/find/list/sort) - UPDATE:
admin\Controllers\ShopPromotionControllerrozszerzony o poleData odna formularzu i kolumneData odna liscie - UPDATE:
shop\Promotion::get_active_promotions()filtruje aktywnosc podate_fromidate_to - FIX: zapis edycji promocji nie tworzy nowego rekordu (hidden
id+ fallbackidz URL) - TEST: rozszerzono
PromotionRepositoryTesto asercjedate_from
- UPDATE: dodane
- Testy po zmianie: OK (222 tests, 614 assertions).
Plan 2026-02-13 - Refaktoryzacja /admin/shop_coupon/ (HITL)
- Etap 1 (analiza i kontrakt URL/routingu):
- potwierdzic docelowy kontrakt URL:
/admin/shop_coupon/list/,/admin/shop_coupon/edit/,/admin/shop_coupon/save/,/admin/shop_coupon/delete/ - decyzja: utrzymujemy aliasy legacy (
view_list,coupon_edit,coupon_save,coupon_delete) w nowym kontrolerze jako kompatybilnosc wsteczna, przy jednoczesnym przejsciu menu i nowych widokow na URL kanoniczne - sprawdzic mapowanie modulu
ShopCouponwadmin\Site(DI factory + fallback)
- potwierdzic docelowy kontrakt URL:
- Etap 2 (Domain):
- dodac
Domain\Coupon\CouponRepository:listForAdmin(filters, sort, dir, page, perPage)(whitelist sortowania + paginacja)find(int $id)(domyslne dane dla nowego formularza)save(array $data): ?int(insert/update, normalizacja switchy, JSON dlacategories)delete(int $id): boolcategoriesTree(?int $parentId): array(drzewo kategorii bez zaleznosci odadmin\factory\ShopCategory)
- dodac
- Etap 3 (Admin Controller + routing DI):
- dodac
admin\Controllers\ShopCouponControllerz akcjamilist,edit,save,delete - przepiac routing DI w
admin\Site::$newControllersdla moduluShopCoupon - zachowac obsluge legacy payload
valuesJSON i nowego payload$_POSTzcomponents/form-edit
- dodac
- Etap 4 (widoki):
- przepiac liste z
gridnacomponents/table-list(filtry: nazwa, aktywny, uzyty, wyslany) - przepiac edycje z
gridEditnacomponents/form-edit - dodac partiale drzewa kategorii w module
shop-coupon(usuniecie zaleznosci odshop-product/subcategories-list) - dodac
shop-coupon/coupon-edit-custom-script.php(obsluga drzewa kategorii i zachowania formularza)
- przepiac liste z
- Etap 5 (cleanup i zaleznosci):
- usunac legacy po pelnym przepieciu:
autoload/admin/controls/class.ShopCoupon.phpautoload/admin/factory/class.ShopCoupon.phpadmin/templates/shop-coupon/view-list.php(wersja grid)admin/templates/shop-coupon/coupon-edit.php(wersja gridEdit)
- przepiac menu admin na kanoniczny URL
/admin/shop_coupon/list/ - przeszukac repo i usunac pozostale odwolania do
shop_coupon/view_listi legacy klasadmin\controls\ShopCoupon,admin\factory\ShopCoupon
- usunac legacy po pelnym przepieciu:
- Etap 6 (testy):
- dodac
tests/Unit/Domain/Coupon/CouponRepositoryTest.php - dodac
tests/Unit/admin/Controllers/ShopCouponControllerTest.php - uruchomic testy modulu + pelny
composer test
- dodac
- Etap 7 (dokumentacja i release note):
- zaktualizowac
DATABASE_STRUCTURE.md(dodacpp_shop_coupon) - zaktualizowac
PROJECT_STRUCTURE.md - zaktualizowac
REFACTORING_PLAN.md(sekcja "Aktualizacja ...") - zaktualizowac
TESTING.md(nowy wynik suite + nowe testy) - dopisac wpis w
updates/changelog.php
- zaktualizowac
Tryb HITL dla realizacji
- Po kazdym etapie (1-7) zatrzymanie i krotkie podsumowanie diffu do akceptacji przed kolejnym krokiem.
Postep 2026-02-13 (ShopCoupon)
- Etap 2 zakonczony:
- NOWE:
autoload/Domain/Coupon/CouponRepository.php - Zakres:
listForAdmin,find,save,delete,categoriesTree - Walidacja:
php -lOK
- NOWE:
- Etap 3 zakonczony:
- NOWE:
autoload/admin/Controllers/ShopCouponController.php - UPDATE:
autoload/admin/class.Site.php- rejestracja DI factory dla moduluShopCoupon - Kompatybilnosc: dodane aliasy akcji
view_list,coupon_edit,coupon_save,coupon_delete - Walidacja:
php -lOK
- NOWE:
- Etap 4 zakonczony:
- NOWE widoki:
admin/templates/shop-coupon/coupons-list.php,admin/templates/shop-coupon/coupon-edit-new.php - NOWE partiale:
admin/templates/shop-coupon/coupon-categories-selector.php,admin/templates/shop-coupon/coupon-categories-tree.php - NOWY skrypt:
admin/templates/shop-coupon/coupon-edit-custom-script.php - UPDATE:
ShopCouponController::edit()budujeFormEditViewModel(zakladki ustawienia/kategorie) - Walidacja:
php -lOK
- NOWE widoki:
- Etap 5 zakonczony:
- CLEANUP: usuniete pliki legacy:
autoload/admin/controls/class.ShopCoupon.phpautoload/admin/factory/class.ShopCoupon.phpadmin/templates/shop-coupon/view-list.phpadmin/templates/shop-coupon/coupon-edit.php
- UPDATE: menu admin (
admin/templates/site/main-layout.php) wskazuje kanoniczny URL/admin/shop_coupon/list/ - WERYFIKACJA: brak odwolan do
shop_coupon/view_list,admin\controls\ShopCoupon,admin\factory\ShopCouponw kodzie
- CLEANUP: usuniete pliki legacy:
- Etap 6 zakonczony:
- NOWE testy:
tests/Unit/Domain/Coupon/CouponRepositoryTest.php(8 testow)tests/Unit/admin/Controllers/ShopCouponControllerTest.php(5 testow)
- Test modulu:
OK (8 tests, 49 assertions) - Pelny suite:
OK (235 tests, 682 assertions)
- NOWE testy:
- Etap 7 zakonczony:
- UPDATE: dokumentacja techniczna zaktualizowana (
DATABASE_STRUCTURE.md,PROJECT_STRUCTURE.md,TESTING.md) - UPDATE: dopisany release note w
updates/changelog.php(ver. 0.266)
- UPDATE: dokumentacja techniczna zaktualizowana (
Aktualizacja 2026-02-13 (ver. 0.266)
- ShopCoupon - migracja
/admin/shop_couponna Domain + DI + nowe widoki- NOWE:
Domain\Coupon\CouponRepository(listForAdmin,find,save,delete,categoriesTree) - NOWE:
admin\Controllers\ShopCouponController(DI) z akcjamilist,edit,save,delete - UPDATE: kompatybilnosc aliasow legacy (
view_list,coupon_edit,coupon_save,coupon_delete) obslugiwana przez nowy kontroler - UPDATE: modul
/admin/shop_coupon/*dziala nacomponents/table-listicomponents/form-edit - NOWE: widoki/partiale
shop-coupon/coupons-list,shop-coupon/coupon-edit-new,shop-coupon/coupon-categories-selector,shop-coupon/coupon-categories-tree,shop-coupon/coupon-edit-custom-script - CLEANUP: usuniete legacy
autoload/admin/controls/class.ShopCoupon.php,autoload/admin/factory/class.ShopCoupon.php,admin/templates/shop-coupon/view-list.php,admin/templates/shop-coupon/coupon-edit.php - UPDATE: menu admin przepiete na kanoniczny URL
/admin/shop_coupon/list/ - FIX: po akceptacji HITL ujednolicone UI drzewek i checkboxow miedzy kuponami i layoutami (spojne strzalki, brak nieestetycznego focusu, iCheck dla checkboxow)
- NOWE:
- Testy po zmianie: OK (235 tests, 682 assertions).