- Migrate front\factory\ShopBasket → Domain\Basket\BasketCalculator (4 static methods, 18 callers updated) - Migrate front\controls\ShopBasket → front\Controllers\ShopBasketController (camelCase, instance methods) - Add snake_case→camelCase action dispatch for new controllers in Site::route() - Update title()/page_title() to check front\Controllers\ before fallback - Remove cms\Layout class (replaced by $layoutsRepo->find()) - Add 8 tests for BasketCalculator (484 tests, 1528 assertions) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
27 KiB
Plan refaktoryzacji frontendu shopPRO
Kontekst
Panel administratora (33 moduły) został w pełni zmigrowany na architekturę Domain + DI + Controllers (ver. 0.237–0.277). Teraz kolej na frontend: klasy front/, shop/, cms/, klasy utility z autoload/ oraz szablony templates/.
Cel: przenieść logikę biznesową z warstwy frontendowej do warstwy domenowej (Domain/), zachowując kompatybilność wsteczną przez fasady. Zastosować te same wzorce co w adminie (DI, repozytoria/serwisy, testy PHPUnit).
Inwentaryzacja — co istnieje
front/controls/ (8 klas — handlery requestów)
| Klasa | Status | Logika biznesowa |
|---|---|---|
| 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 |
| 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() |
| ShopCoupon | Fasada | use_coupon(), delete_coupon() |
| Newsletter | Fasada | signin(), confirm(), unsubscribe() |
front/factory/ (20 klas — pobieranie danych + logika)
| Klasa | Status | Priorytet migracji |
|---|---|---|
| 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 |
| 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 |
— |
| ShopTransport | CZĘŚCIOWO zmigrowana | ŚREDNI — transport_methods z filtrowaniem |
| ShopPaymentMethod | ZMIGROWANA (Domain) | — |
| ShopStatuses | ZMIGROWANA (Domain) | — |
| Scontainers | ZMIGROWANA (Domain) — usunięta | — |
| Newsletter | ZMIGROWANA (Domain) — usunięta | — |
| Settings | Fasada (BUG: get_single_settings_value ignoruje $param) | NISKI |
| Languages | USUNIĘTA — przepięta na Domain | — |
| Layouts | USUNIETA — przepieta na Domain | — |
| Banners | USUNIETA — przepieta na Domain | — |
| Menu | USUNIETA — przepieta na Domain | — |
| Pages | USUNIETA — przepieta na Domain | — |
| ShopAttribute | ZMIGROWANA (Domain) — usunięta | — |
| ShopCoupon | Model danych | NISKI |
front/view/ (12 klas — renderowanie)
| Klasa | Status |
|---|---|
| Site | KRYTYCZNY — show() ~600 linii, pattern substitution engine |
| ShopCategory | VIEW z logiką routingu (infinite scroll vs pagination) |
| 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 |
| ShopTransport | PUSTA klasa (placeholder) |
shop/ (14 klas — encje biznesowe)
| Klasa | Linii | Status | Priorytet |
|---|---|---|---|
| Product | ~950 | KRYTYCZNY — pricing, atrybuty, search, cache, permutacje | KRYTYCZNY |
| Order | ~500+ | KRYTYCZNY — statusy, Apilo sync, emaile, webhooki | KRYTYCZNY |
| Promotion | ~200 | WYSOKI — matching aktywnych promocji + delegacja do factory | WYSOKI |
| Basket | ~80 | ŚREDNI — walidacja stanów magazynowych | ŚREDNI |
| Category | ~60 | NISKI — proste zapytania, pusty konstruktor | NISKI |
| Search | ~80 | NISKI — wrapper na szablony | NISKI |
| Coupon | ~60 | NISKI — niekompletne metody | NISKI |
| Transport | ~30 | NISKI — transport_list() | NISKI |
| PaymentMethod | — | ZMIGROWANA (fasada do Domain) | — |
| Producer | — | ZMIGROWANA (fasada do Domain) | — |
| ProductSet | — | ZMIGROWANA (fasada do Domain) | — |
| ProductAttribute | ~100 | OK — dobry caching | — |
| ProductCustomField | ~50 | OK — Redis caching | — |
| Shop | ~30 | OK — utility do cen | — |
autoload/ root (klasy utility)
| Klasa | Linii | Status |
|---|---|---|
| S | ~960 | PRZENIESIONA do Shared\Helpers\Helpers — 12 metod usunieto, bug fix |
| Tpl | ~90 | PRZENIESIONA do Shared\Tpl\Tpl — DRY render(), bug fix branch 3, ~135 plikow przepietych |
| CacheHandler | ~50 | ZMIGROWANY do Shared\Cache\CacheHandler — wrappery usuniete |
| RedisConnection | ~40 | ZMIGROWANY do Shared\Cache\RedisConnection — wrappery usuniete |
| ~100 | OK — PHPMailer wrapper (drobne poprawki) | |
| Log | ~20 | OK — audit logging |
| DbModel | — | USUNIETA — logika wbudowana w shop\Promotion |
| Cache | ~50 | USUNIETA — zastapiona CacheHandler (Redis) w ver. 0.282 |
| Html | ~80 | OK — form helpers |
| Image | ~100 | OK — GD wrapper |
| Mobile_Detect | — | USUNIETA — przestarzala detekcja UA, zastapiona responsive design |
cms/ (1 klasa)
| Klasa | Status |
|---|---|
| Layout | USUNIETA — zastapiona przez $layoutsRepo->find() |
templates/ (75 plików w 15 modułach)
articles(8), banner(2), controls(1), menu(4), newsletter(2), scontainers(1), shop-basket(9), shop-category(6), shop-client(8), shop-coupon(1), shop-order(3), shop-producer(3), shop-product(12), shop-search(3), site(11)
Entry points
index.php— główny frontend (autoload, sesja, DB, routing, DOM post-processing)ajax.php— AJAX handler (koszyk, transport, kontakt)api.php— REST API (Ekomi CSV export)download.php— pobieranie plikówcron-turstmate.php— TrustMate integracja
Znane bugi do naprawy podczas refaktoringu
- KRYTYCZNY
front\factory\ShopClient::login()— hardcoded password bypass'Legia1916' front\factory\Settings::get_single_settings_value()— ignoruje$param, zawsze zwracafirm_nameNAPRAWIONE —front\factory\Newsletter::newsletter_unsubscribe()— błędna składnia SQL w deleteNewsletterRepository::unsubscribe()z poprawną składnią medoodelete()NAPRAWIONE — klasa usunięta, zastąpiona przezcms\Layout::__get()— referuje nieistniejące$this->data$layoutsRepo->find()shop\Search— typo w use:shop\Produt(brak 'c')
Kolejność migracji (graf zależności)
Settings, Languages (liście — brak zależności)
↓
Banners, Menu, Pages, Articles, Layouts (zależą od Languages)
↓
Category (zależy od Languages)
↓
Promotion (zależy od Category — rozbicie circular dep)
↓
Product Frontend (zależy od Category, Promotion, Languages)
↓
Client/Auth (standalone + security fix)
↓
Transport, Payment, Coupon (frontend serwisy)
↓
Basket (zależy od Product, Promotion, Transport, Coupon)
↓
Order Creation (zależy od Basket, Product, Transport, Payment)
↓
Payment Webhooks (zależy od Order)
↓
shop\Order instance + Apilo (zależy od Order Operations)
↓
shop\Product instance + cache (zależy od ProductFrontendService)
↓
Frontend App + Controllers (nowa warstwa DI)
↓
Site Layout Engine (zależy od wszystkiego)
↓
Entry Point Unification (index.php, ajax.php)
↓
Legacy Cleanup
Etapy migracji
Etap: Settings + Languages — ZREALIZOWANY
Cel: Dodac metody frontendowe (z cache Redis) do istniejacych repozytoriow Domain.
DODANE METODY (do istniejacych klas):
Domain/Settings/SettingsRepository—allSettings($skipCache),getSingleValue($param)(FIX: uzywa poprawnie $param)Domain/Languages/LanguagesRepository—defaultLanguage(),activeLanguages(),translations($lang)- Testy: dopisane do
SettingsRepositoryTest(6 testow),LanguagesRepositoryTest(7 testow)
ZMIANA:
front/factory/Settings→ fasada delegujaca doSettingsRepositoryfront/factory/Languages→ fasada delegujaca doLanguagesRepositorytests/bootstrap.php— uzupelniony stub CacheHandler oget()/set()/exists()
BUG FIX: get_single_settings_value() — zmiana ['param' => 'firm_name'] na ['param' => $param]
Etap: Newsletter Frontend — ZREALIZOWANY
Cel: Przeniesienie logiki frontendowej z front\factory\Newsletter do Domain\Newsletter\NewsletterRepository. Migracja view do nowego namespace front\Views.
DODANE METODY (do istniejącej klasy NewsletterRepository):
unsubscribe(string $hash): bool— FIX: poprawna składnia medoodelete()(2 args zamiast 3)confirmSubscription(string $hash): boolgetHashByEmail(string $email): ?stringremoveByEmail(string $email): boolsignup(string $email, string $serverName, bool $ssl, array $settings): boolsendQueued(int $limit, string $serverName, bool $ssl, string $unsubscribeLabel): bool- Konstruktor rozszerzony o opcjonalne:
ArticleRepository,NewsletterPreviewRenderer(lazy-init) - Testy: 10 nowych testów w
NewsletterRepositoryTest
ZMIANA:
front/factory/Newsletter→ USUNIĘTA (logika przeniesiona doNewsletterRepository)front/view/Newsletter→ USUNIĘTA, zastąpiona przezfront/Views/Newsletter(nowy namespace, bezclass.prefix)front/controls/Newsletter→ thin wrapper naNewsletterRepositoryfront/view/Site::show()→\front\Views\Newsletter::render()index.php→$newsletterRepo->sendQueued()front/factory/ShopClient(4 miejsca) →NewsletterRepository::templateByName()tests/bootstrap.php— dodane stuby:S::email_check(),S::get_session(),S::set_session()
BUG FIX: newsletter_unsubscribe() — medoo delete() wywoływane z 3 argumentami zamiast 2
Etap: Category Frontend Service
Cel: Migracja front\factory\ShopCategory do Domain.
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
ZMIANA:
front/factory/ShopCategory→ fasadafront/factory/ShopProduct::product_categories()→ deleguje doCategoryFrontendService
Etap: Articles Frontend — ZREALIZOWANY
Cel: Migracja front\factory\Articles, front\view\Articles i statycznych metod class.Article do Domain + Views.
DODANE METODY (do istniejącej klasy ArticleRepository):
articleDetailsFrontend(int $articleId, string $langId): ?array— z copy_from fallback + Redis cachearticlesIds(int $pageId, string $langId, int $limit, int $sortType, int $from): ?array— złożone SQL z language fallback + sortowanie + LIMIT + Redis cachepageArticlesCount(int $pageId, string $langId): int— COUNT z Redis cachepageArticles(array $page, string $langId, int $bs): array— paginacjanews(int $pageId, int $limit, string $langId): ?array— inline sort_type query (eliminacja zależności odfront\factory\Pages)articleNoindex(int $articleId, string $langId): bool— jawny $langId zamiastglobal $langtopArticles(int $pageId, int $limit, string $langId): ?array— ORDER BY views DESC + Redis cachenewsListArticles(int $pageId, int $limit, string $langId): ?array— ORDER BY date_add DESC + CacheHandler (Redis) zamiast legacy\Cache
NOWE:
front\Views\Articles— czysty VIEW + utility:- Renderowanie:
fullArticle(),miniatureArticlesList(),entryArticlesList(),fullArticlesList(),news(),newsList() - Utility:
generateTableOfContents(),processHeaders(),generateHeadersIds(),getImage()
- Renderowanie:
ZMIANA:
front\factory\Articles→ fasada (10 metod delegujących do repo + Views)front\view\Articles→ fasada (5 metod delegujących do repo + Views)class.Article→ USUNIĘTA (encja + metody statyczne przeniesione doArticleRepository+front\Views\Articles)front\view\Site::show()→ 5 sekcji przepiętych na repo + Viewsfront\controls\Site::route()→ single article + page_type switch przepięte na repo + Views- 5 szablonów
templates/articles/*→\front\Views\Articles:: tests/bootstrap.php— dodany stubS::is_array_fix()- Testy: 13 nowych w
ArticleRepositoryTest(450 OK, 1431 asercji)
Etap: Banners Frontend — ZREALIZOWANY
Cel: Migracja front\factory\Banners i front\view\Banners do Domain + Views.
DODANE METODY (do istniejącej klasy BannerRepository):
banners(string $langId): ?array— aktywne banery (home_page=0), filtrowanie dat, Redis cache, plaski format languagesmainBanner(string $langId): ?array— baner glowny (home_page=1), filtrowanie dat, Redis cache, plaski format languages
NOWE:
front\Views\Banners— czysty VIEW (banners(),mainBanner())
ZMIANA:
front\factory\Banners→ USUNIETA (logika przeniesiona doBannerRepository)front\view\Banners→ USUNIETA (zastapiona przezfront\Views\Banners)front\view\Site::show()— przepiecie na$bannerRepo->banners()/$bannerRepo->mainBanner()+\front\Views\Banners::- Testy: 4 nowe w
BannerRepositoryTest(454 OK, 1449 asercji)
Etap: Menu, Pages, Layouts Frontend Services — ZREALIZOWANY
Cel: Migracja pozostałych fabryk "liściowych".
UWAGA: Zamiast tworzenia osobnych FrontendService, metody dodano do istniejących repozytoriów Domain (zgodnie z wzorcem projektu).
DODANE METODY (do istniejących klas):
Domain/Layouts/LayoutsRepository—categoryDefaultLayoutId(),getDefaultLayout(),getProductLayout(),getArticleLayout(),getCategoryLayout(),getActiveLayout()(Redis cache, 3-level fallback)Domain/Pages/PagesRepository—frontPageDetails(),frontPageSort(),frontMainPageId(),frontLangUrl(),frontMenuDetails(),frontMenuPages()(Redis cache, rekurencja)- Testy: +8 w
LayoutsRepositoryTest, +8 wPagesRepositoryTest
NOWE:
front\Views\Menu— czysty VIEW (pages(),menu())
ZMIANA:
front/factory/Layouts→ USUNIETA (logika wLayoutsRepository)front/factory/Menu→ USUNIETA (logika wPagesRepository)front/factory/Pages→ USUNIETA (logika wPagesRepository)front/view/Menu→ USUNIETA (zastapiona przezfront\Views\Menu)templates/menu/submenu.php→ USUNIETA (martwy kod)front\view\Site::show()— przepiecie na$layoutsRepo+$pagesRepofront\controls\Site::check_url_params()— przepiecie na$pagesRepo->frontPageDetails()index.php— przepiecie na$pagesRepo->frontPageDetails()Shared\Helpers\Helpers::htacces()— optymalizacja 3→1 wywolan- Szablony
templates/menu/*— przepiecie na\front\Views\Menu:: templates/site/languages.php— przepiecie na$pagesRepo->frontLangUrl()
BUG FIX: frontPageDetails() — null $lang_id przy wczesnym check_url_params() (usuniety string type hint + cast + ?? '' na call site)
Testy: 470 OK, 1484 asercji
Etap: Promotion Engine (rozbicie circular dependency)
Cel: Przeniesienie silnika promocji do Domain. Rozbicie cyklicznej zależności shop\Promotion ↔ front\factory\ShopPromotion.
Obecna zależność cykliczna:
shop\Promotion::find_promotion() → front\factory\ShopPromotion::promotion_type_XX()
front\factory\ShopPromotion::promotion_type_XX() → shop\Product::is_product_on_promotion()
Rozwiązanie: Wszystko w jednym serwisie PromotionFrontendService.
NOWE:
Domain/Promotion/PromotionFrontendService.php:getActivePromotions()(zshop\Promotion)applyPromotions(array $basket)(zshop\Promotion::find_promotion())private applyType01..05()(zfront\factory\ShopPromotion)private isProductOnPromotion()(zshop\Product— proste zapytanie)
- Testy:
PromotionFrontendServiceTest(7 typów promocji + brak aktywnych)
ZMIANA:
shop/Promotion→ fasada doPromotionFrontendService::applyPromotions()front/factory/ShopPromotion→ fasada
Etap: Product Frontend Service
Cel: Migracja front\factory\ShopProduct i statycznych metod shop\Product do Domain.
NOWE:
Domain/Product/ProductFrontendService.php:- Z
front\factory\ShopProduct:productDetails()(~330 linii z Redis),promotedProducts(),topProducts(),newProducts(),productUrl(),getMinimalPrice(),isProductActive(),getProductSku(),getProductEan(),productImage(),productWp(),randomProducts(),warehouseMessageZero(),warehouseMessageNonzero() - Z
shop\Product(statyczne):isProductOnPromotion(),getProductImg(),getProductUrl(),addVisit(),productSetsForBasket(),searchProductsByName(),searchProductByNameAjax()
- Z
- Testy:
ProductFrontendServiceTest
ZMIANA:
front/factory/ShopProduct→ fasadashop/Productstatyczne metody → fasady doProductFrontendService
UWAGA: Konstruktor shop\Product, getFromCache(), calculate_basket_product_price() — zostają na razie (instancyjne, używane w szablonach). Migracja w etapie "Product Instance + Cache".
Etap: Client Authentication (Security Fix)
Cel: Migracja front\factory\ShopClient + NAPRAWIENIE hardcoded password bypass.
NOWE:
Domain/Client/ClientFrontendService.php:login()— BEZ bypassa 'Legia1916', z opcjonalną migracją md5 → password_hashsignup(),registerConfirm(),sendPasswordRecovery(),resetPassword()clientDetails(),clientOrders()- CRUD adresów:
saveAddress(),deleteAddress(),getAddresses(),markAddressAsCurrent()
- Testy:
ClientFrontendServiceTest— KRYTYCZNY test: login z 'Legia1916' NIE przechodzi
ZMIANA:
front/factory/ShopClient→ fasadafront/controls/ShopClient→ deleguje do serwisu
Etap: Transport, Payment, Coupon Frontend Services
Cel: Frontend serwisy dla transportu, płatności i kuponów.
NOWE:
Domain/Transport/TransportFrontendService.php—transportMethods()(filtrowanie WP, free delivery),transportCost(),transportDetails()Domain/PaymentMethod/PaymentMethodFrontendService.php—activePaymentMethods(),paymentMethodsByTransport(),paymentMethodDetails()Domain/Coupon/CouponFrontendService.php—validateCoupon(),applyCoupon(),markCouponUsed()- Testy: 3 pliki testowe
ZMIANA:
front/factory/ShopTransport→ fasadafront/factory/ShopCoupon→ fasadashop/Coupon→ fasadashop/Transport→ fasada
Etap: Basket Service
Cel: Migracja logiki koszyka do Domain\Basket\BasketService.
NOWE:
Domain/Basket/BasketService.php:addProduct(),removeProduct(),changeQuantity(),increaseQuantity(),decreaseQuantity()summaryPrice(),countProducts(),countProductsText()validateStock()(zshop\Basket::check_product_quantity_in_stock())calculateProductPrice()(zshop\Product::calculate_basket_product_price()~112 linii)
- Testy:
BasketServiceTest(pricing z promocjami/kuponami, walidacja stanów)
ZMIANA:
front/factory/ShopBasket→ fasadafront/controls/ShopBasket— wewnętrznie używaBasketServiceshop/Basket→ fasadashop/Product::calculate_basket_product_price()→ fasada
Etap: shop\Product Instance + Cache
Cel: Refaktoring konstruktora shop\Product i getFromCache().
NOWE:
Domain/Product/ProductDataLoader.php:loadFull(int $productId, ?string $langId, ?string $permutationHash)— ładowanie pełnych danych produktuloadCached()— Redis cache wrapper
- Testy:
ProductDataLoaderTest
ZMIANA:
shop/Product— konstruktor igetFromCache()delegują doProductDataLoader- ArrayAccess interface zachowany (szablony dalej używają
$product->property)
Etap: Order Creation Frontend Service
Cel: Migracja front\factory\ShopOrder::basket_save() (~180 linii).
NOWE:
Domain/Order/OrderFrontendService.php:createOrder()— tworzenie zamówienia z koszyka (walidacja, kalkulacja cen, insert, redukcja stanów, obsługa kuponu, wysyłka emaili, auto-status dla pobrania)generateOrderNumber()— format YYYY/MM/NNNorderDetails(),orderIdByHash(),orderHashById()
- Testy:
OrderFrontendServiceTest
ZMIANA:
front/factory/ShopOrder→ fasada
Etap: Payment Webhook Service
Cel: Wyodrębnienie webhooków płatności z front\controls\ShopOrder.
NOWE:
Domain/Payment/PaymentWebhookService.php:processTpay(array $params)— weryfikacja tPayprocessPrzelewy24(array $params)— weryfikacja przez API + walidacja kwotyprocessHotpay(array $params)— walidacja SHA256 hashprivate markOrderPaid()— wspólna logika (update status + email + Apilo sync)
- Testy:
PaymentWebhookServiceTest
ZMIANA:
front/controls/ShopOrder— webhooki stają się thin wrappers
POPRAWA: Zamiana file_put_contents('tpay.txt') na \Log::save_log()
Etap: shop\Order Instance + Apilo Service
Cel: Refaktoring shop\Order instancyjnych metod + wyodrębnienie integracji Apilo.
NOWE:
Domain/Integrations/ApiloService.php:syncPayment(),syncStatus(),processQueue()private queueSync(),private loadQueue(),private saveQueue()
Domain/Order/OrderOperationsService.php:setAsPaid(),setAsUnpaid(),updateStatus(),sendStatusChangeEmail(),resendConfirmationEmail()
- Testy:
ApiloServiceTest,OrderOperationsServiceTest
ZMIANA:
shop/Orderinstancyjne metody → fasady doOrderOperationsService- Konstruktor i ArrayAccess bez zmian
Etap: Frontend App + Controllers (DI layer)
Cel: Stworzenie front\App (wzorowanego na admin\App) z mapą kontrolerów i DI.
NOWE:
autoload/front/App.php—render(),handleAjax(),getControllerFactories()(DI wiring)autoload/front/Controllers/ShopBasketController.php— DI zBasketService,ProductFrontendServiceautoload/front/Controllers/ShopOrderController.php— DI zOrderFrontendService,PaymentWebhookServiceautoload/front/Controllers/ShopClientController.php— DI zClientFrontendService- Testy: 3 pliki testowe kontrolerów
ZMIANA:
front/controls/ShopBasket,ShopOrder,ShopClient→ delegują do nowych kontrolerów
Etap: Site Layout Engine
Cel: Refaktoring front\view\Site::show() (~600 linii) na testowalny LayoutEngine.
NOWE:
autoload/front/View/LayoutEngine.php:resolveLayout(array $page, array $params)— wybór layoutu (product > category > article > page > default)processPatterns(string $html, array $context)— zamiana tagów szablonowych- Osobne prywatne metody:
replaceCategories(),replaceProducts(),replaceMenus(),replaceLanguageTags(),replaceBanners(),replaceArticles(),replaceContainers(),replaceMetaTags(), etc.
- Testy:
LayoutEngineTest
ZMIANA:
front/view/Site::show()→ thin wrapper naLayoutEngine
Etap: Entry Point Unification
Cel: Ujednolicenie bootstrapu index.php i ajax.php.
NOWE:
autoload/front/Bootstrap.php—init()(autoloader, config, sesja, DB, lang/settings)autoload/front/PostProcessor.php— ekstrakcja DOM manipulacji zindex.php(GTM, Facebook Pixel, WebP, lazy loading)
ZMIANA:
index.php→ uproszczony:Bootstrap::init()→App::render()→PostProcessor::process()ajax.php→ uproszczony:Bootstrap::init()→App::handleAjax()
Etap: Legacy Cleanup
Cel: Finalne porządki.
USUNIĘCIE:
- Martwy kod
eval()dla[PHP]bloków (jeśli nieużywany) ZREALIZOWANE w ver. 0.282class.Cache.php(legacy file-based)- Pusta klasa
front\view\ShopTransport
ZMIANA:
- Dodanie
@deprecateddo wszystkich metod-fasad wfront/factory/,front/controls/,shop/ - PHPDoc do wszystkich nowych klas Domain z
@since - Aktualizacja
tests/bootstrap.php - BUG FIX:
shop\Search— typoshop\Produt→shop\Product BUG FIX:ZREALIZOWANE w etapie Newsletter Frontendfront\factory\Newsletter::newsletter_unsubscribe()— poprawka SQL
Podsumowanie
| Etap | Zakres | Priorytet | Nowe klasy Domain | Testy |
|---|---|---|---|---|
| Settings + Languages | Fundamenty | FUNDAMENT | 2 serwisy | 2 |
| Category Frontend | Kategorie | WYSOKI | 1 serwis | 1 |
| ZREALIZOWANY | — | — | ||
| Promotion Engine | Promocje | KRYTYCZNY | 1 serwis | 1 |
| Product Frontend | Produkty | KRYTYCZNY | 1 serwis | 1 |
| Client/Auth (security fix) | Klienci | KRYTYCZNY | 1 serwis | 1 |
| 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 |
| Order Creation | Zamówienia | WYSOKI | 1 serwis | 1 |
| Payment Webhooks | Webhooki | WYSOKI | 1 serwis | 1 |
| Order Instance + Apilo | Zamówienie + Apilo | ŚREDNI | 2 serwisy | 2 |
| Frontend App + Controllers | DI layer | WYSOKI | App + 3 kontrolery | 3 |
| Layout Engine | Silnik layoutu | ŚREDNI | 1 engine | 1 |
| Entry Point Unification | Entry points | ŚREDNI | Bootstrap + PostProcessor | 1 |
| Legacy Cleanup | Porządki | NISKI | — | — |
Łącznie: 16 etapów, ~24 nowe klasy Domain, ~25 plików testowych
Wzorce do przestrzegania (z migracji admin)
- Konstruktor DI z
$db(medoo) - CacheHandler (Redis) dla cachingu — unifikacja (usunięcie starego
Cache) - Fasady w
shop\*ifront\factory\*dla kompatybilności wstecznej - Testy PHPUnit z mockami medoo
- Namespace
\Domain\*→autoload/Domain/*/ - Namespace
\front\Controllers\→autoload/front/Controllers/ - Klasy Domain sa wspolne dla admin i frontendu — NIE tworzymy osobnych FrontendService/AdminService. Metody frontendowe (z cache Redis) dodajemy do istniejacych repozytoriow/serwisow Domain. Klasy sa ladowane lazy (instancja tworzona dopiero przy wywolaniu), wiec nie wplywaja na wydajnosc.
Nazewnictwo plikow
- Nowe klasy:
NazwaKlasy.php(bez przedrostkaclass.) - Legacy:
class.NazwaKlasy.php— zostawiamy do momentu migracji danej klasy - Autoloader obsluguje oba formaty (probuje
class.X.php, potemX.php) - Nowe katalogi z duzej litery:
Views/,Controllers/(legacy:view/,controls/,factory/)
Statyczne vs instancyjne metody
- Statyczne — gdy klasa jest bezstanowa (brak konstruktora, brak properties, brak DI). Czyste funkcje: dane wchodzą, wynik wychodzi. Przykład: klasy VIEW (
front\Views\Languages::render($data),front\view\Banners::banners($data)) - Instancyjne — gdy klasa ma zależności do wstrzyknięcia (repozytoria, serwisy) lub trzyma stan. Przykład: kontrolery z DI (
ShopProductControllerzProductRepository,LanguagesRepository)
Weryfikacja po każdym etapie
composer test(pełny suite PHPUnit)- Manualne sprawdzenie frontendu: strona główna, kategoria, produkt, koszyk, zamówienie
- Sprawdzenie AJAX: dodawanie do koszyka, zmiana transportu, kupon
- Sprawdzenie webhooków płatności (tPay, Przelewy24, Hotpay)