ver. 0.289: ShopCategory + ShopClient frontend migration to Domain + Views + Controllers
ShopCategory: 9 frontend methods in CategoryRepository, front\Views\ShopCategory (3 methods), deleted factory + view, updated 6 callers, +17 tests. ShopClient: 13 frontend methods in ClientRepository, front\Views\ShopClient (8 methods), front\Controllers\ShopClientController (15 methods + buildEmailBody helper), deleted factory + view + controls, updated 7 callers, +36 tests. Security fix: removed hardcoded password bypass 'Legia1916'. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -15,7 +15,7 @@ Panel administratora (33 moduły) został w pełni zmigrowany na architekturę D
|
||||
|-------|--------|-----------------|
|
||||
| Site | Router główny | route(), check_url_params(), title() |
|
||||
| ShopBasket | ZMIGROWANY do `front\Controllers\ShopBasketController` | Operacje koszyka, add/remove/quantity, checkout |
|
||||
| ShopClient | Fasada | Deleguje do factory |
|
||||
| ShopClient | ZMIGROWANY do `front\Controllers\ShopClientController` | Logowanie, rejestracja, odzyskiwanie hasla, adresy, zamowienia |
|
||||
| ShopOrder | KRYTYCZNY | Webhooki płatności (tPay, Przelewy24, Hotpay) — bezpośrednie operacje DB |
|
||||
| ShopProduct | Fasada | lazy_loading, warehouse_message, draw_product_attributes |
|
||||
| ShopProducer | Fasada | list(), products() |
|
||||
@@ -27,8 +27,8 @@ Panel administratora (33 moduły) został w pełni zmigrowany na architekturę D
|
||||
|-------|--------|--------------------|
|
||||
| ShopProduct | ORYGINALNA LOGIKA (~370 linii) | KRYTYCZNY — product_details(), promoted/top/new products |
|
||||
| ShopOrder | ORYGINALNA LOGIKA (~180 linii) | KRYTYCZNY — basket_save() tworzy zamówienie |
|
||||
| ShopClient | ORYGINALNA LOGIKA | KRYTYCZNY — login (BUG: hardcoded bypass 'Legia1916'), signup, recover |
|
||||
| ShopCategory | ORYGINALNA LOGIKA | WYSOKI — złożone SQL z language fallback |
|
||||
| ShopClient | ZMIGROWANA do `ClientRepository` + `ShopClientController` — usunięta | — |
|
||||
| ShopCategory | ZMIGROWANA do `CategoryRepository` — usunięta | — |
|
||||
| Articles | ORYGINALNA LOGIKA | WYSOKI — złożone SQL z language fallback |
|
||||
| ShopPromotion | ORYGINALNA LOGIKA | WYSOKI — silnik promocji (5 typów) |
|
||||
| ShopBasket | ZMIGROWANA do `Domain\Basket\BasketCalculator` — usunięta | — |
|
||||
@@ -50,13 +50,14 @@ Panel administratora (33 moduły) został w pełni zmigrowany na architekturę D
|
||||
| Klasa | Status |
|
||||
|-------|--------|
|
||||
| Site | KRYTYCZNY — show() ~600 linii, pattern substitution engine |
|
||||
| ShopCategory | VIEW z logiką routingu (infinite scroll vs pagination) |
|
||||
| ShopCategory | PRZENIESIONA do `front\Views\ShopCategory` |
|
||||
| Articles | Czyste VIEW |
|
||||
| Scontainers | PRZENIESIONA do `front\Views\Scontainers` |
|
||||
| Menu | PRZENIESIONA do `front\Views\Menu` |
|
||||
| Banners | PRZENIESIONA do `front\Views\Banners` |
|
||||
| Languages, Newsletter | PRZENIESIONE do `front\Views\` (nowy namespace) |
|
||||
| ShopClient, ShopOrder, ShopPaymentMethod | Czyste VIEW |
|
||||
| ShopClient | PRZENIESIONA do `front\Views\ShopClient` |
|
||||
| ShopOrder, ShopPaymentMethod | Czyste VIEW |
|
||||
| ShopTransport | PUSTA klasa (placeholder) |
|
||||
|
||||
### shop/ (14 klas — encje biznesowe)
|
||||
@@ -111,7 +112,7 @@ articles(8), banner(2), controls(1), menu(4), newsletter(2), scontainers(1), sho
|
||||
|
||||
## Znane bugi do naprawy podczas refaktoringu
|
||||
|
||||
1. **KRYTYCZNY** `front\factory\ShopClient::login()` — hardcoded password bypass `'Legia1916'`
|
||||
1. ~~**KRYTYCZNY** `front\factory\ShopClient::login()` — hardcoded password bypass `'Legia1916'`~~ **NAPRAWIONE** — `ClientRepository::authenticate()` bez bypass
|
||||
2. `front\factory\Settings::get_single_settings_value()` — ignoruje `$param`, zawsze zwraca `firm_name`
|
||||
3. ~~`front\factory\Newsletter::newsletter_unsubscribe()` — błędna składnia SQL w delete~~ **NAPRAWIONE** — `NewsletterRepository::unsubscribe()` z poprawną składnią medoo `delete()`
|
||||
4. ~~`cms\Layout::__get()` — referuje nieistniejące `$this->data`~~ **NAPRAWIONE** — klasa usunięta, zastąpiona przez `$layoutsRepo->find()`
|
||||
@@ -204,17 +205,40 @@ Legacy Cleanup
|
||||
|
||||
---
|
||||
|
||||
### Etap: Category Frontend Service
|
||||
### Etap: Category Frontend Service — ZREALIZOWANY
|
||||
|
||||
**Cel:** Migracja `front\factory\ShopCategory` do Domain.
|
||||
**Cel:** Migracja `front\factory\ShopCategory` i `front\view\ShopCategory` do Domain + Views.
|
||||
|
||||
**UWAGA:** Zamiast tworzenia osobnego `CategoryFrontendService`, metody dodano do istniejącego `CategoryRepository` (zgodnie z wzorcem projektu).
|
||||
|
||||
**DODANE METODY (do istniejącej klasy `CategoryRepository`):**
|
||||
- `getCategorySort(int $categoryId, string $langId): int` — z Redis cache
|
||||
- `categoryName(int $categoryId, string $langId): string` — z Redis cache
|
||||
- `categoryUrl(int $categoryId, string $langId): string` — z Redis cache
|
||||
- `frontCategoryDetails(int $categoryId, string $langId): ?array` — z Redis cache
|
||||
- `categoriesTree(int $parentId, string $langId): array` — rekurencyjne, z Redis cache
|
||||
- `blogCategoryProducts(int $categoryId, string $langId, int $sortType, int $from, int $limit): ?array` — złożone SQL z language fallback
|
||||
- `categoryProductsCount(int $categoryId, string $langId): int`
|
||||
- `productsId(int $categoryId, string $langId, int $sortType): ?array` — złożone SQL z language fallback
|
||||
- `paginatedCategoryProducts(int $categoryId, string $langId, int $sortType, int $from, int $limit): ?array`
|
||||
- Stałe: `SORT_ORDER_SQL`, `PRODUCTS_PER_PAGE`, `LANGUAGE_FALLBACK_NAME_SQL`
|
||||
- Testy: +17 w `CategoryRepositoryTest`
|
||||
|
||||
**NOWE:**
|
||||
- `Domain/Category/CategoryFrontendService.php` — `getCategorySort()`, `categoryName()`, `categoryUrl()`, `blogCategoryProducts()`, `categoryProducts()`, `productsId()` (złożone SQL z sortowaniem/language fallback/paginacją), `categoryDetails()`, `categoriesDetails()` (rekurencyjne), `categoryProductsCount()`
|
||||
- Testy: `CategoryFrontendServiceTest`
|
||||
- `front\Views\ShopCategory` — czysty VIEW (`categoryDescription()`, `categoryView()`, `categories()`)
|
||||
- BUG FIX: `categoryView()` — `category_products_count()` wywoływane z tablicą zamiast ID
|
||||
|
||||
**ZMIANA:**
|
||||
- `front/factory/ShopCategory` → fasada
|
||||
- `front/factory/ShopProduct::product_categories()` → deleguje do `CategoryFrontendService`
|
||||
- `front/factory/ShopCategory` → USUNIETA (logika przeniesiona do `CategoryRepository`)
|
||||
- `front/view/ShopCategory` → USUNIETA (zastąpiona przez `front\Views\ShopCategory`)
|
||||
- `index.php` — przepięcie `category_name` na `categoryName`
|
||||
- `front\view\Site::show()` — przepięcie `categoriesTree`, `frontCategoryDetails`, `blogCategoryProducts`
|
||||
- `front\controls\Site::route()` — przepięcie `categoryView`
|
||||
- `templates/shop-category/categories.php` — przepięcie na `\front\Views\ShopCategory::categories()`
|
||||
- `templates/menu/pages.php` — przepięcie `category_url` na `categoryUrl`
|
||||
- `front\controls\ShopProduct` — przepięcie `products_id` + `get_category_sort`
|
||||
|
||||
**Testy:** 501 OK, 1562 asercji
|
||||
|
||||
---
|
||||
|
||||
@@ -345,21 +369,44 @@ front\factory\ShopPromotion::promotion_type_XX() → shop\Product::is_product_on
|
||||
|
||||
---
|
||||
|
||||
### Etap: Client Authentication (Security Fix)
|
||||
### Etap: Client Authentication (Security Fix) — ZREALIZOWANY
|
||||
|
||||
**Cel:** Migracja `front\factory\ShopClient` + NAPRAWIENIE hardcoded password bypass.
|
||||
**Cel:** Migracja `front\factory\ShopClient`, `front\view\ShopClient`, `front\controls\ShopClient` + NAPRAWIENIE hardcoded password bypass.
|
||||
|
||||
**UWAGA:** Zamiast tworzenia osobnego `ClientFrontendService`, metody dodano do istniejącego `ClientRepository` (zgodnie z wzorcem projektu). Kontroler utworzony jako `front\Controllers\ShopClientController` z DI.
|
||||
|
||||
**DODANE METODY (do istniejącej klasy `ClientRepository`):**
|
||||
- Simple CRUD: `clientDetails()`, `clientEmail()`, `clientAddresses()`, `addressDetails()`, `addressDelete()`, `addressSave(int $clientId, ?int $addressId, array $data)`, `markAddressAsCurrent()`
|
||||
- `clientOrders()` — zachowuje zależność od `\front\factory\ShopOrder::order_details()`
|
||||
- `authenticate(string $email, string $password)` — **BEZ** bypassa 'Legia1916', zwraca `['status' => 'ok'|'error'|'inactive', ...]`
|
||||
- `createClient()` — zwraca `['id' => ..., 'hash' => ...]` lub null
|
||||
- `confirmRegistration()` — zwraca email lub null
|
||||
- `generateNewPassword()` — zwraca `['email' => ..., 'password' => ...]` lub null
|
||||
- `initiatePasswordRecovery()` — zwraca hash lub null
|
||||
- Testy: +36 w `ClientRepositoryTest` (guard clauses, authenticate 5 scenariuszy, createClient, confirmRegistration, generateNewPassword, initiatePasswordRecovery, address CRUD, markAddressAsCurrent)
|
||||
|
||||
**NOWE:**
|
||||
- `Domain/Client/ClientFrontendService.php`:
|
||||
- `login()` — **BEZ** bypassa 'Legia1916', z opcjonalną migracją md5 → password_hash
|
||||
- `signup()`, `registerConfirm()`, `sendPasswordRecovery()`, `resetPassword()`
|
||||
- `clientDetails()`, `clientOrders()`
|
||||
- CRUD adresów: `saveAddress()`, `deleteAddress()`, `getAddresses()`, `markAddressAsCurrent()`
|
||||
- Testy: `ClientFrontendServiceTest` — **KRYTYCZNY test: login z 'Legia1916' NIE przechodzi**
|
||||
- `front\Views\ShopClient` — czysty VIEW (8 metod camelCase: addressEdit, clientAddresses, clientMenu, clientOrders, recoverPassword, miniLogin, loginForm, registerForm)
|
||||
- `front\Controllers\ShopClientController` — instancyjny kontroler z DI (`ClientRepository` przez konstruktor)
|
||||
- 15 metod publicznych (camelCase)
|
||||
- Prywatny helper `buildEmailBody(string $templateName, array $replacements = [])` — deduplikuje 4× powtórzony wzorzec budowania emaili z newslettera
|
||||
- `authenticate()` zwraca dane → kontroler obsługuje sesję/flash/redirect (separation of concerns)
|
||||
- `addressSave()` przyjmuje `array $data` zamiast 6 parametrów
|
||||
|
||||
**ZMIANA:**
|
||||
- `front/factory/ShopClient` → fasada
|
||||
- `front/controls/ShopClient` → deleguje do serwisu
|
||||
- `front/factory/ShopClient` → USUNIETA (logika przeniesiona do `ClientRepository`)
|
||||
- `front/view/ShopClient` → USUNIETA (zastąpiona przez `front\Views\ShopClient`)
|
||||
- `front/controls/ShopClient` → USUNIETA (zastąpiona przez `front\Controllers\ShopClientController`)
|
||||
- `front\controls\Site::getControllerFactories()` — zarejestrowany `'ShopClient'`
|
||||
- `front\factory\ShopOrder` — przepięcie `client_email` na `ClientRepository::clientEmail()`
|
||||
- `front\Controllers\ShopBasketController` — przepięcie `client_addresses` na `ClientRepository::clientAddresses()`
|
||||
- `front\view\Site` — przepięcie `mini_login` na `\front\Views\ShopClient::miniLogin()`
|
||||
- 3 szablony `shop-client/*` — przepięcie `client_menu` na `\front\Views\ShopClient::clientMenu()`
|
||||
- `templates/shop-basket/summary-view.php` — przepięcie `login_form` na `\front\Views\ShopClient::loginForm()`
|
||||
|
||||
**SECURITY FIX:** Hardcoded password bypass `'Legia1916'` usunięty — `authenticate()` sprawdza wyłącznie md5(register_date + password)
|
||||
|
||||
**Testy:** 537 OK, 1648 asercji
|
||||
|
||||
---
|
||||
|
||||
@@ -539,11 +586,11 @@ front\factory\ShopPromotion::promotion_type_XX() → shop\Product::is_product_on
|
||||
| Etap | Zakres | Priorytet | Nowe klasy Domain | Testy |
|
||||
|------|--------|-----------|-------------------|-------|
|
||||
| Settings + Languages | Fundamenty | FUNDAMENT | 2 serwisy | 2 |
|
||||
| Category Frontend | Kategorie | WYSOKI | 1 serwis | 1 |
|
||||
| ~~Category Frontend~~ | ~~Kategorie~~ | ZREALIZOWANY | — | — |
|
||||
| ~~Banners/Menu/Pages/Articles/Layouts~~ | ~~Treści~~ | ZREALIZOWANY | — | — |
|
||||
| Promotion Engine | Promocje | KRYTYCZNY | 1 serwis | 1 |
|
||||
| Product Frontend | Produkty | KRYTYCZNY | 1 serwis | 1 |
|
||||
| Client/Auth (security fix) | Klienci | KRYTYCZNY | 1 serwis | 1 |
|
||||
| ~~Client/Auth (security fix)~~ | ~~Klienci~~ | ZREALIZOWANY | — | — |
|
||||
| Transport/Payment/Coupon | Dostawa/Płatności | WYSOKI | 3 serwisy | 3 |
|
||||
| Basket Service | Koszyk | WYSOKI | 1 serwis | 1 |
|
||||
| Product Instance + Cache | Produkt cache | ŚREDNI | 1 loader | 1 |
|
||||
|
||||
Reference in New Issue
Block a user