LayoutEngine::show() w 3 galeziach (category/article/product) nadpisywal tylko $page['language']['title'], a meta_title homepage zylo dalej i wygrywalo w substytucji [TITLE]. Wyodrebniono applyEntityMetaToPage() jako pure-function ktora zawsze nadpisuje meta_title/meta_keywords/meta_description encji (nawet pustym/null), eliminujac wyciek. 5 nowych testow w LayoutEngineMetaTagsTest. Suita 846 testow zielona. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
8.6 KiB
Roadmap: shopPRO
Overview
shopPRO to autorski silnik sklepu internetowego rozwijany iteracyjnie. Projekt jest już na produkcji (v0.333) — roadmap obejmuje planowane funkcje i usprawnienia kolejnych wersji.
Current Milestone
Feature — Product list custom labels quick edit Status: Complete Phases: 1 of 1 complete
Phases
| Phase | Name | Plans | Status | Completed |
|---|---|---|---|---|
| 1 | Sensitive data logging fix | 1 | Done | 2026-03 |
| 2 | Path traversal + XSS escaping | 1 | Done | 2026-03 (v0.335) |
| 3 | Error handling w krytycznych ścieżkach | 1 | Done | 2026-03 (v0.336) |
| 4 | CSRF protection — admin panel forms | 1 | Applied | 2026-03 (v0.337) |
| 5 | Order bugs fix — duplicate + COD status | 1 | Applied | 2026-03 (v0.338) |
Next Milestone
Tech debt — Integrations refactoring Status: Planning
| Phase | Name | Plans | Status | Completed |
|---|---|---|---|---|
| 6 | IntegrationsRepository split → ApiloRepository | 2 | Done | 2026-03 |
Hotfix
| Phase | Name | Plans | Status | Completed |
|---|---|---|---|---|
| 7 | Coupon Fatal Error — order placement crash | 1 | Done | 2026-03-15 |
| 8 | Apilo orders not sending — diagnoza i naprawa | 1 | Done | 2026-03-16 |
| 9 | Apilo email notification + infinite retry | 1 | Done | 2026-03-19 |
| 15 | Scontainers edit saves as new record | 1 | Done | 2026-04-18 |
| 17 | Cart summary transport cost fix | 1 | Done | 2026-04-20 |
| 18 | Google feed permutation URL fix | 1 | Done | 2026-04-30 |
| 19 | Frontend meta tags fix (category + product) | 1 | Done | 2026-05-13 |
Feature
| Phase | Name | Plans | Status | Completed |
|---|---|---|---|---|
| 10 | Edycja personalizacji produktu w koszyku | 1 | Done | 2026-03-19 |
| 11 | DataLayer GA4 analytics fix | 1 | Done | 2026-03-25 |
| 12 | summaryView redirect fix — double order block | 1 | Done | 2026-03-25 |
| 13 | Basket logging + TTL token fix | 1 | Done | 2026-03-25 |
| 14 | Custom fields delete bug — usunięcie wszystkich pól | 1 | Done | 2026-04-16 |
| 16 | Product list custom labels quick edit | 1 | Done | 2026-04-19 |
Phase Details
Phase 4 — CSRF protection
Problem: Brak tokenów CSRF na formularzach panelu admina. State-changing POST endpointy (create/update/delete) są potencjalnie podatne na ataki CSRF.
Scope: Dodanie CSRF tokenów do formularzy i walidacji w panelu administracyjnym.
Reference: .paul/codebase/concerns.md — MEDIUM — Missing CSRF tokens
Phase 6 — IntegrationsRepository split
Problem: IntegrationsRepository ma 875 linii — miesza logikę generyczną (settings, logi, product linking) z logiką specyficzną dla Apilo (~650 linii). Narusza zasadę jednej odpowiedzialności.
Scope:
- Plan 06-01: Utwórz
ApiloRepositoryz metodami apilo* (non-breaking) - Plan 06-02: Zmigruj konsumentów (IntegrationsController, ShopProductController, OrderAdminService, cron.php), usuń apilo* z IntegrationsRepository
Phase 5 — Order bugs fix
Problem 1: Zduplikowane zamówienia — klient widzi błąd i klika złóż zamówienie ponownie. Pierwsze zamówienie trafiło do bazy mimo błędu. Powrót do /podsumowanie regeneruje token i pozwala złożyć drugie zamówienie.
Problem 2: Zamówienia COD (płatność przy odbiorze) dostają status "Zamówienie złożone" zamiast "Przyjęte do realizacji". Kod sprawdza hardkodowane payment_id == 3, które jest inne w tej instancji sklepu.
Scope: Guard w summaryView(), try-catch w basketSave(), kolumna is_cod w pp_shop_payment_methods, użycie flagi zamiast hardkodowanego ID.
Roadmap created: 2026-03-12
Phase 11 — DataLayer GA4 analytics fix
Problem: Eventy dataLayer ecommerce (purchase, begin_checkout, view_item, add_to_cart) używają starego formatu UA (id/name zamiast item_id/item_name), brak currency w view_item, price:0 w purchase, brak eventu view_cart. Remarketing dynamiczny i konwersje GA4 nie działają poprawnie.
Scope: Poprawka 4 istniejących eventów do formatu GA4 + dodanie nowego eventu view_cart na stronie koszyka.
Reference: poprawki_datalayer_projectpro.md — audyt analityki z pomysloweprezenty.pl
Phase 12 — summaryView redirect fix
Problem: Po złożeniu pierwszego zamówienia, guard w summaryView() sprawdzał sesyjny order-submit-last-order-id i redirectował na stronę starego zamówienia. Blokował dostęp do /koszyk-podsumowanie dla kolejnych zamówień. Poprawka z instancji klienta (change.md) do wdrożenia globalnie.
Scope: Usunięcie bloku redirect z summaryView() w ShopBasketController.php. Double-submit protection w basketSave() pozostaje bez zmian.
Phase 13 — Basket logging + TTL token fix
Problem: Brak logowania w basketSave() uniemożliwia diagnozę błędów zamówień. Token zamówienia jednorazowy — nadpisywany przy każdym wejściu na podsumowanie, co powoduje że druga karta, "wstecz" lub odświeżenie unieważnia formularz.
Scope: Dodanie metody logOrder() z 4 punktami logowania, zmiana tokena z jednorazowego na TTL 30 min, redirect przy błędzie tokena na /koszyk-podsumowanie zamiast /koszyk, nowy double-submit guard.
Phase 14 — Custom fields delete bug
Problem: Usunięcie WSZYSTKICH dodatkowych pól z produktu nie działa. jQuery .serialize() nie wysyła klucza custom_field_name[] gdy nie ma żadnych pól → array_key_exists('custom_field_name', $d) w ProductRepository zwraca false → saveCustomFields() nigdy nie jest wywoływany → pola pozostają w bazie.
Scope: Dodanie hidden markera custom_field_name_present w szablonie JS + zmiana warunku w ProductRepository na sprawdzanie tego markera. Test jednostkowy.
Phase 15 - Scontainers edit saves as new record
Problem: Edycja kontenera statycznego (/admin/scontainers/edit/id={id}) zapisuje rekord jako nowy wpis zamiast aktualizacji. W praktyce podczas zapisu gubi się id i repository wykonuje insert.
Scope: Poprawić przekazywanie id w nowym flow formularza ScontainersController + dodać test regresyjny dla edycji, bez zmian globalnych w innych kontrolerach.
Phase 16 - Product list custom labels quick edit
Problem: Na liscie produktow brakuje szybkiego trybu uzupelniania custom_label_0..4. Administrator musi wchodzic do edycji produktu, co spowalnia uzupelnianie danych Google XML.
Scope: Dodac przycisk "Pokaz etykiety niestandardowe" obok "Dodaj produkt", zapisywac jego stan w sesji, pokazac 5 pol custom label pod nazwa produktu, zapisac wartosci do bazy i zapewnic podpowiedzi z juz istniejacych wartosci.
Phase 17 - Cart summary transport cost fix
Problem: Na /koszyk-podsumowanie kazdy transport z flaga delivery_free = 1 pokazywany jest za 0,00 zl, niezaleznie od tego czy koszyk osiagnal prog darmowej dostawy settings.free_delivery. Szablon summary-view.php sprawdza tylko flage, nie wartosc koszyka. Suma koncowa zamowienia jest zaniżona.
Scope: Przekazac z ShopBasketController::summaryView() do szablonu wyliczony transport_cost_effective i flage free_delivery_applies uwzgledniajaca prog. Zaktualizowac summary-view.php aby uzywal tych kluczy zamiast surowej flagi delivery_free. Test jednostkowy dla logiki wyliczenia.
Phase 18 — Google feed permutation URL fix
Problem: URL produktu z permutacją atrybutów w feedzie Google miał format /slug/20-170/21-175 (slash między parami). Wzorzec routingu pp_routes używa [0-9-]+, który nie obejmuje /, więc URL nie matchuje żadnej trasy i index.php ładuje stronę główną. Klienci z GMC trafiają na home zamiast na produkt z wybraną kombinacją.
Scope: Zmienić separator z / na _ w generatorze feedu (ProductRepository::appendCombinationToXml), rozszerzyć regex routingu o _ (Helpers), dodać konwersję _ → | w warstwie front (LayoutEngine), preselekcja wartości atrybutu w partialu na podstawie permutation_hash z URL. Plus unit testy regex + generator linku.
Phase 19 — Frontend meta tags fix
Problem: Strony kategorii (np. /sen-i-otulenie) i strony produktów (np. /kocyk-niemowlaka-szczeniak-z-balonikiem-fuksja) renderują <title> strony głównej oraz literalne wartości content="keywords"/content="description" zamiast właściwych metatagów SEO z bazy. Niepoprawne meta blokują indeksację Google i Merchant Center.
Scope: Diagnostyka (pp_routes + meta w DB + sesyjny $page), checkpoint:decision z 4 opcjami fixu (routes/engine/data/session), implementacja wybranej opcji w LayoutEngine.php lub index.php, test jednostkowy, human-verify na 3 URL-ach.
Last updated: 2026-05-13 (Phase 19 complete)