Files
shopPRO/docs/FRONTEND_REFACTORING_PLAN.md
Jacek Pyziak 437d4c78dc ver. 0.288: BasketCalculator + ShopBasketController migration, cms\Layout removal
- 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>
2026-02-17 09:38:45 +01:00

27 KiB
Raw Blame History

Plan refaktoryzacji frontendu shopPRO

Kontekst

Panel administratora (33 moduły) został w pełni zmigrowany na architekturę Domain + DI + Controllers (ver. 0.2370.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
Email ~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ów
  • cron-turstmate.php — TrustMate integracja

Znane bugi do naprawy podczas refaktoringu

  1. KRYTYCZNY front\factory\ShopClient::login() — hardcoded password bypass 'Legia1916'
  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 NAPRAWIONENewsletterRepository::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()
  5. 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/SettingsRepositoryallSettings($skipCache), getSingleValue($param) (FIX: uzywa poprawnie $param)
  • Domain/Languages/LanguagesRepositorydefaultLanguage(), activeLanguages(), translations($lang)
  • Testy: dopisane do SettingsRepositoryTest (6 testow), LanguagesRepositoryTest (7 testow)

ZMIANA:

  • front/factory/Settings → fasada delegujaca do SettingsRepository
  • front/factory/Languages → fasada delegujaca do LanguagesRepository
  • tests/bootstrap.php — uzupelniony stub CacheHandler o get()/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 medoo delete() (2 args zamiast 3)
  • confirmSubscription(string $hash): bool
  • getHashByEmail(string $email): ?string
  • removeByEmail(string $email): bool
  • signup(string $email, string $serverName, bool $ssl, array $settings): bool
  • sendQueued(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 do NewsletterRepository)
  • front/view/Newsletter → USUNIĘTA, zastąpiona przez front/Views/Newsletter (nowy namespace, bez class. prefix)
  • front/controls/Newsletter → thin wrapper na NewsletterRepository
  • front/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.phpgetCategorySort(), categoryName(), categoryUrl(), blogCategoryProducts(), categoryProducts(), productsId() (złożone SQL z sortowaniem/language fallback/paginacją), categoryDetails(), categoriesDetails() (rekurencyjne), categoryProductsCount()
  • Testy: CategoryFrontendServiceTest

ZMIANA:

  • front/factory/ShopCategory → fasada
  • front/factory/ShopProduct::product_categories() → deleguje do CategoryFrontendService

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 cache
  • articlesIds(int $pageId, string $langId, int $limit, int $sortType, int $from): ?array — złożone SQL z language fallback + sortowanie + LIMIT + Redis cache
  • pageArticlesCount(int $pageId, string $langId): int — COUNT z Redis cache
  • pageArticles(array $page, string $langId, int $bs): array — paginacja
  • news(int $pageId, int $limit, string $langId): ?array — inline sort_type query (eliminacja zależności od front\factory\Pages)
  • articleNoindex(int $articleId, string $langId): bool — jawny $langId zamiast global $lang
  • topArticles(int $pageId, int $limit, string $langId): ?array — ORDER BY views DESC + Redis cache
  • newsListArticles(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()

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 do ArticleRepository + front\Views\Articles)
  • front\view\Site::show() → 5 sekcji przepiętych na repo + Views
  • front\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 stub S::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 languages
  • mainBanner(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 do BannerRepository)
  • front\view\Banners → USUNIETA (zastapiona przez front\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/LayoutsRepositorycategoryDefaultLayoutId(), getDefaultLayout(), getProductLayout(), getArticleLayout(), getCategoryLayout(), getActiveLayout() (Redis cache, 3-level fallback)
  • Domain/Pages/PagesRepositoryfrontPageDetails(), frontPageSort(), frontMainPageId(), frontLangUrl(), frontMenuDetails(), frontMenuPages() (Redis cache, rekurencja)
  • Testy: +8 w LayoutsRepositoryTest, +8 w PagesRepositoryTest

NOWE:

  • front\Views\Menu — czysty VIEW (pages(), menu())

ZMIANA:

  • front/factory/Layouts → USUNIETA (logika w LayoutsRepository)
  • front/factory/Menu → USUNIETA (logika w PagesRepository)
  • front/factory/Pages → USUNIETA (logika w PagesRepository)
  • front/view/Menu → USUNIETA (zastapiona przez front\Views\Menu)
  • templates/menu/submenu.php → USUNIETA (martwy kod)
  • front\view\Site::show() — przepiecie na $layoutsRepo + $pagesRepo
  • front\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() (z shop\Promotion)
    • applyPromotions(array $basket) (z shop\Promotion::find_promotion())
    • private applyType01..05() (z front\factory\ShopPromotion)
    • private isProductOnPromotion() (z shop\Product — proste zapytanie)
  • Testy: PromotionFrontendServiceTest (7 typów promocji + brak aktywnych)

ZMIANA:

  • shop/Promotion → fasada do PromotionFrontendService::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()
  • Testy: ProductFrontendServiceTest

ZMIANA:

  • front/factory/ShopProduct → fasada
  • shop/Product statyczne metody → fasady do ProductFrontendService

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_hash
    • signup(), registerConfirm(), sendPasswordRecovery(), resetPassword()
    • clientDetails(), clientOrders()
    • CRUD adresów: saveAddress(), deleteAddress(), getAddresses(), markAddressAsCurrent()
  • Testy: ClientFrontendServiceTestKRYTYCZNY test: login z 'Legia1916' NIE przechodzi

ZMIANA:

  • front/factory/ShopClient → fasada
  • front/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.phptransportMethods() (filtrowanie WP, free delivery), transportCost(), transportDetails()
  • Domain/PaymentMethod/PaymentMethodFrontendService.phpactivePaymentMethods(), paymentMethodsByTransport(), paymentMethodDetails()
  • Domain/Coupon/CouponFrontendService.phpvalidateCoupon(), applyCoupon(), markCouponUsed()
  • Testy: 3 pliki testowe

ZMIANA:

  • front/factory/ShopTransport → fasada
  • front/factory/ShopCoupon → fasada
  • shop/Coupon → fasada
  • shop/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() (z shop\Basket::check_product_quantity_in_stock())
    • calculateProductPrice() (z shop\Product::calculate_basket_product_price() ~112 linii)
  • Testy: BasketServiceTest (pricing z promocjami/kuponami, walidacja stanów)

ZMIANA:

  • front/factory/ShopBasket → fasada
  • front/controls/ShopBasket — wewnętrznie używa BasketService
  • shop/Basket → fasada
  • shop/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 produktu
    • loadCached() — Redis cache wrapper
  • Testy: ProductDataLoaderTest

ZMIANA:

  • shop/Product — konstruktor i getFromCache() delegują do ProductDataLoader
  • 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/NNN
    • orderDetails(), 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 tPay
    • processPrzelewy24(array $params) — weryfikacja przez API + walidacja kwoty
    • processHotpay(array $params) — walidacja SHA256 hash
    • private 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/Order instancyjne metody → fasady do OrderOperationsService
  • 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.phprender(), handleAjax(), getControllerFactories() (DI wiring)
  • autoload/front/Controllers/ShopBasketController.php — DI z BasketService, ProductFrontendService
  • autoload/front/Controllers/ShopOrderController.php — DI z OrderFrontendService, PaymentWebhookService
  • autoload/front/Controllers/ShopClientController.php — DI z ClientFrontendService
  • 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 na LayoutEngine

Etap: Entry Point Unification

Cel: Ujednolicenie bootstrapu index.php i ajax.php.

NOWE:

  • autoload/front/Bootstrap.phpinit() (autoloader, config, sesja, DB, lang/settings)
  • autoload/front/PostProcessor.php — ekstrakcja DOM manipulacji z index.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)
  • class.Cache.php (legacy file-based) ZREALIZOWANE w ver. 0.282
  • Pusta klasa front\view\ShopTransport

ZMIANA:

  • Dodanie @deprecated do wszystkich metod-fasad w front/factory/, front/controls/, shop/
  • PHPDoc do wszystkich nowych klas Domain z @since
  • Aktualizacja tests/bootstrap.php
  • BUG FIX: shop\Search — typo shop\Produtshop\Product
  • BUG FIX: front\factory\Newsletter::newsletter_unsubscribe() — poprawka SQL ZREALIZOWANE w etapie Newsletter Frontend

Podsumowanie

Etap Zakres Priorytet Nowe klasy Domain Testy
Settings + Languages Fundamenty FUNDAMENT 2 serwisy 2
Category Frontend Kategorie WYSOKI 1 serwis 1
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
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\* i front\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 przedrostka class.)
  • Legacy: class.NazwaKlasy.php — zostawiamy do momentu migracji danej klasy
  • Autoloader obsluguje oba formaty (probuje class.X.php, potem X.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 (ShopProductController z ProductRepository, LanguagesRepository)

Weryfikacja po każdym etapie

  1. composer test (pełny suite PHPUnit)
  2. Manualne sprawdzenie frontendu: strona główna, kategoria, produkt, koszyk, zamówienie
  3. Sprawdzenie AJAX: dodawanie do koszyka, zmiana transportu, kupon
  4. Sprawdzenie webhooków płatności (tPay, Przelewy24, Hotpay)