ver. 0.350 - 30.04.2026
FIX - linki produktow z permutacja w feedzie Google (separator _)

ver. 0.349 - 20.04.2026
Naprawa kosztu transportu na podsumowaniu koszyka (delivery_free z uwzglednieniem progu)

ver. 0.348 - 19.04.2026
Dodano przełącznik i edycję etykiet niestandardowych na liście produktów.

ver. 0.347 - 18.04.2026
Naprawa zapisu edycji kontenerow statycznych + testy regresyjne

ver. 0.346 - 16.04.2026
Fix usuwania wszystkich dodatkowych pól produktu

ver. 0.345 - 25.03.2026
Checkout flow fix - summaryView redirect, TTL token 30min, logowanie bledow zamowien

ver. 0.344 - 19.03.2026
Edycja personalizacji produktu w koszyku

ver. 0.343 - 19.03.2026
Custom fields: type + is_required + obsługa obrazków w koszyku

ver. 0.342 - 19.03.2026
Apilo: email z danymi zamówienia + infinite retry co 30 min dla order jobów

ver. 0.341 - 16.03.2026
Bugfix: naprawiono wysyłkę zamówień do Apilo (regresja z 0.339), retry failed orders co 1h, powiadomienia mailowe o błędach

ver. 0.341 - 16.03.2026
FIX - cron.php — dodano brakujące $apiloRepository do klauzul use() w 5 handlerach cron (APILO_TOKEN_KEEPALIVE, APILO_SEND_ORDER, APILO_PRODUCT_SYNC, APILO_PRICELIST_SYNC, APILO_STATUS_POLL); regresja z ver. 0.339 (split IntegrationsRepository → ApiloRepository) powodowała Call to a member function apiloGetAccessToken() on null FIX - cron.php — zamówienia z apilo_order_id = -1 (failed) są teraz automatycznie ponawiane co 1h zamiast trwale pomijane; priorytet: najpierw nowe zamówienia (NULL), potem retry (-1) NEW - cron.php — powiadomienie mailowe na biuro@project-pro.pl przy błędzie cURL wysyłania zamówienia do Apilo NEW - cron.php — powiadomienie mailowe o trwale nieudanych zadaniach Apilo (po wyczerpaniu max_attempts)

ver. 0.340 - 15.03.2026
FIX - autoload/Domain/Order/OrderRepository.php:793 — naprawiono Fatal Error Call to undefined method stdClass::is_one_time() przy składaniu zamówienia z kodem rabatowym; zamieniono wywołania nieistniejących metod na stdClass (is_one_time(), set_as_used()) na dostęp do właściwości + istniejącą metodę CouponRepository::markAsUsed() SONARQUBE - Pierwszy skan SonarQube — wyniki zapisane w docs/TODO.md (4 bugi, 31 critical code smells, 10 major, 8 minor)

ver. 0.339 - 12.03.2026
REFACTOR - autoload/Domain/Integrations/ApiloRepository.php — nowa klasa \Domain\Integrations\ApiloRepository z 19 metodami apilo* (sync produktów, zamówień, konfiguracja) wydzielonymi z IntegrationsRepository REFACTOR - autoload/Domain/Integrations/IntegrationsRepository.php — usunięto 19 metod apilo* (~540 linii); klasa zmniejszona z ~875 do ~340 linii, zawiera wyłącznie generyczną logikę integracji (settings, logi, product linking) REFACTOR - autoload/admin/Controllers/IntegrationsController.php — konsumuje ApiloRepository przez DI zamiast IntegrationsRepository dla operacji apilo REFACTOR - autoload/Domain/Order/OrderAdminService.php — używa ApiloRepository do wysyłki zamówień do Apilo REFACTOR - cron.php — używa ApiloRepository do synchronizacji cron REFACTOR - autoload/admin/App.php — wiring DI dla ApiloRepository TEST - tests/Unit/Domain/Integrations/ApiloRepositoryTest.php — nowe testy dla ApiloRepository; suite: 818 testów, 2275 asercji

ver. 0.338 - 12.03.2026
FIX - autoload/front/Controllers/ShopBasketController::summaryView() — guard przed ponownym złożeniem zamówienia: jeśli sesja zawiera ORDER_SUBMIT_LAST_ORDER_ID, użytkownik jest przekierowywany do istniejącego zamówienia zamiast widzieć formularz ponownie FIX - autoload/front/Controllers/ShopBasketController::basketSave() — owinięcie wywołania createFromBasket() w try-catch; wyjątek jest logowany przez error_log(), użytkownik widzi komunikat błędu, koszyk sesyjny zostaje zachowany FIX - autoload/Domain/Order/OrderRepository::createFromBasket() — usunięcie hardkodowanego payment_id == 3 do wykrywania płatności przy odbiorze; zamiast tego używana jest flaga $payment_method['is_cod'] FEATURE - autoload/Domain/PaymentMethod/PaymentMethodRepository — nowa kolumna is_cod (normalizacja, zapis w save(), kolumna w forTransport() SQL) FEATURE - autoload/admin/Controllers/ShopPaymentMethodController — nowe pole "Platnosc przy odbiorze" w formularzu edycji metody płatności MIGRATION - migrations/0.338.sql — ALTER TABLE pp_shop_payment_methods ADD COLUMN is_cod TINYINT(1) NOT NULL DEFAULT 0

ver. 0.337 - 12.03.2026
SECURITY - autoload/Shared/Security/CsrfToken.php — nowa klasa z getToken(), validate(), regenerate() (token 64-znakowy hex, hash_equals() przeciw timing attacks) SECURITY - admin/templates/components/form-edit.php — dodano ukryte pole _csrf_token we wszystkich formularzach edycji SECURITY - autoload/admin/Support/Forms/FormRequestHandler::handleSubmit() — walidacja CSRF przed przetworzeniem danych formularza SECURITY - admin/templates/site/unlogged-layout.php — token CSRF w formularzu logowania + fix XSS na komunikacie alertu (htmlspecialchars) SECURITY - admin/templates/users/user-2fa.php — token CSRF w obu formularzach 2FA (weryfikacja i resend) SECURITY - autoload/admin/App::special_actions() — walidacja CSRF dla żądań POST; regeneracja tokenu po udanym logowaniu (obie ścieżki: bezpośrednia i przez 2FA) TEST - tests/Unit/Shared/Security/CsrfTokenTest.php — 7 nowych testów; suite: 817 testów, 2271 asercji

ver. 0.336 - 12.03.2026
FIX - cron.php — przywrócono E_WARNING i E_DEPRECATED (wyciszano je od zawsze, ukrywając potencjalne błędy) FIX - IntegrationsRepository::apiloAuthorize() — try-catch po zapisie tokenów Apilo; błąd DB logowany i zwraca false zamiast cicho kontynuować FIX - ProductRepository::safeUnlink() — error_log() gdy ścieżka istnieje ale jest poza upload/ FIX - ArticleRepository::safeUnlink() — to samo

ver. 0.335 - 12.03.2026
SECURITY - ProductRepository — dodano safeUnlink() z walidacją realpath() zapobiegającą path traversal; użyta w cleanupDeletedFiles(), cleanupDeletedImages(), deleteNonassignedImages() SECURITY - ArticleRepository — to samo; użyta w deleteMarkedImages(), deleteMarkedFiles(), deleteNonassignedFiles(), deleteNonassignedImages() SECURITY - templates/articles/article-full.php — htmlspecialchars() na tytule artykułu, $_SERVER['SERVER_NAME'] i $url w linkach social media SECURITY - templates/articles/article-entry.php — htmlspecialchars() na tytule i $url (3 miejsca: href, title, alt)

ver. 0.334 - 12.03.2026
SECURITY - ShopOrderController::paymentStatusTpay() — usunięto file_put_contents('tpay.txt', ...) który logował pełne dane POST/GET płatności do publicznego pliku SECURITY - ShopOrderController — hardcoded sekret HotPay "ProjectPro1916;" przeniesiony do prywatnej stałej HOTPAY_HASH_SEED SECURITY - IntegrationsRepository::getSettings() — zastąpiono raw query("SELECT * FROM $table") metodą Medoo select() (spójne z zasadą braku string concatenation w SQL) REFACTOR - index.php, admin/index.php — usunięto RedBeanPHP (rb.php): biblioteka była ładowana i inicjalizowana, ale nigdy nie używana w żadnym zapytaniu CLEANUP - libraries/rb.php — usunięto plik (536 KB zbędnych zależności) TESTS - IntegrationsRepositoryTest — zaktualizowano 6 testów do nowego API (select zamiast query dla getSettings)

ver. 0.333 - 10.03.2026
NEW - ShopBasketController — mechanizm tokenu CSRF chroniący przed podwójnym składaniem zamówienia (generowanie, walidacja, konsumpcja tokenu w sesji) NEW - ShopBasketController::basketSave() — przy duplikacie przekierowanie do istniejącego zamówienia zamiast tworzenia kolejnego FIX - templates/shop-basket/summary-view.php — JS nasłuchuje na submit formularza zamiast click przycisku (poprawna obsługa walidacji HTML5) FIX - templates/shop-basket/address-form.php — ukryte pole order_submit_token z escape XSS TESTS - ShopBasketControllerTest — testy konstruktora i zależności (5 testów)

ver. 0.332 - 01.03.2026
NEW - ProductRepository::getProductForApi() — eksportuje 4 nowe pola: new_to_date, additional_message (int 0/1), additional_message_required (int 0/1), additional_message_text NEW - ProductsApiController — obsługa nowych pól w PUT/PATCH (aktualizacja new_to_date, additional_message, additional_message_required, additional_message_text) DOCS - docs/API.md — zaktualizowane przykłady GET/PUT dla nowych pól produktu

ver. 0.331 - 01.03.2026
FIX - LayoutsRepository::getProductLayout() — fallback gdy produkt i jego kategorie nie mają przypisanego layoutu zmieniany z categories_default = 1 na status = 1; wcześniej produkty bez layoutu pobierały szablon "Podstrony - kategorie" zamiast właściwego domyślnego

ver. 0.330 - 27.02.2026
REFACTOR - Helpers::htacces() — generowanie .htaccess w całości z PHP (usunięty file_get_contents('htaccess.conf') i placeholder {HTACCESS_CACHE}) NEW - 32 statyczne trasy systemowe wstawiane do pp_routes z type='system' przy każdym htacces() (koszyk, logowanie, wylogowanie, panel klienta, newsletter, zamówienia, płatności, moduły AJAX: shopBasket/shopClient/shopProduct/shopCoupon/search) NEW - Dynamiczne trasy językowe i producentów (producenci + per-producent z paginacją) przenoszone do pp_routes zamiast .htaccess NEW - Kolumna type VARCHAR(20) NULL w pp_routes — NULL dla encji, 'system' dla tras systemowych REMOVED - libraries/htaccess.conf — plik szablonu usunięty, treść wbudowana w PHP PERF - Invalidacja cache Redis pp_routes:all po każdym htacces() — świeże trasy przy kolejnym żądaniu MIGRATION - migrations/0.329.sql (dodano type column) DOCS - docs/DATABASE_STRUCTURE.md — zaktualizowana sekcja pp_routes o kolumnę type

ver. 0.329 - 27.02.2026
REFACTOR - index.php — blok routingu przez pp_routes przeniesiony PRZED checkUrlParams() (poprawna kolejność: lang/a=page dostępne w checkUrlParams) PERF - Cache Redis dla tras (pp_routes:all, TTL 86400s) w index.php — jeden SELECT na 24h zamiast przy każdym żądaniu NEW - Kategorie, strony i artykuły zapisywane do pp_routes zamiast .htaccess w Helpers::htacces() NEW - CategoryRepository::categoryDelete() — usuwa powiązane pp_routes przed odświeżeniem NEW - PagesRepository::pageDelete() — usuwa powiązane pp_routes NEW - ArticleRepository::archive() i deletePermanently() — usuwa powiązane pp_routes MIGRATION - migrations/0.329.sql — ALTER TABLE pp_routes ADD COLUMN category_id, page_id, article_id TESTS - Zaktualizowane CategoryRepositoryTest i ArticleRepositoryTest (nowe asercje na pp_routes delete)

ver. 0.328 - 27.02.2026
NEW - order-details-custom-script.php — JS parsuje .atributes div i wstrzykuje przycisk fa-copy przy każdej wartości atrybutu UX - Kliknięcie kopiuje wartość do schowka (Clipboard API + fallback execCommand), ikona zmienia się na fa-check z zielonym tłem przez 1,5s

ver. 0.327 - 27.02.2026
NEW - ProductArchiveController::bulk_delete_permanent() — endpoint POST product_archive/bulk_delete_permanent/, przyjmuje ids[], usuwa każdy produkt przez ProductRepository::delete(), zwraca JSON {success, deleted, errors[]} UX - Kolumna checkboxów w liście archiwum produktów + pasek akcji masowych z licznikiem zaznaczonych UX - "Zaznacz wszystkie" w nagłówku tabeli (wstrzyknięty via JS), dialog potwierdzenia przed masowym usunięciem TEST - 2 nowe testy w ProductArchiveControllerTest — weryfikacja istnienia i sygnatury bulk_delete_permanent

ver. 0.326 - 27.02.2026
NEW - api\Controllers\CategoriesApiController — nowy kontroler API z akcją list NEW - Endpoint GET api.php?endpoint=categories&action=list — zwraca płaską listę aktywnych kategorii (id, parent_id, title) w domyślnym języku sklepu FIX - Usunięto zbędny parametr w CategoryRepository, eliminacja N+1 queries w categories/list przez bulk-fetch tytułów

ver. 0.325 - 27.02.2026
FIX - updates/changelog.php — naprawione krzaczki (mojibake) w polskich znakach; dane odbudowane z plików manifest NEW - updates/changelog-data.html — czyste dane changelog oddzielone od logiki PHP REFACTOR - updates/changelog.php — konwersja ze statycznego HTML na skrypt PHP: Content-Type: utf-8, parsowanie wpisów, filtrowanie po wersji NEW - Parametr ?ver=X.XXX — ogranicza changelog do 5 wersji wstecz od wersji instancji UPDATE - admin/templates/update/main-view.php — przekazuje ?ver= do URL changelog UPDATE - build-update.ps1 — nowe wpisy dopisywane do changelog-data.html zamiast changelog.php

ver. 0.324 - 27.02.2026
NEW - Domain\CronJob\CronJobType — stałe typów zadań, priorytetów, statusów, exponential backoff NEW - Domain\CronJob\CronJobRepository — CRUD na pp_cron_jobs + pp_cron_schedules (enqueue, fetchNext, markCompleted, markFailed, hasPendingJob, cleanup, recoverStuck, getDueSchedules, touchSchedule) NEW - Domain\CronJob\CronJobProcessor — orkiestracja: rejestracja handlerów, tworzenie scheduled jobs, przetwarzanie kolejki z priorytetami i retry/backoff NEW - Tabele pp_cron_jobs i pp_cron_schedules — kolejka zadań z priorytetami, exponential backoff, harmonogram cykliczny REFACTOR - cron.php — zastąpienie monolitycznego ~550 linii orkiestratorem z CronJobProcessor i zarejestrowanymi handlerami REFACTOR - OrderAdminService::queueApiloSync() — kolejkowanie przez CronJobRepository::enqueue() zamiast pliku JSON REFACTOR - OrderAdminService::syncApiloPayment(), syncApiloStatus() — zmiana z private na public (używane przez handlery cron) REMOVED - OrderAdminService::processApiloSyncQueue(), loadApiloSyncQueue(), saveApiloSyncQueue(), apiloSyncQueuePath(), stała APILO_SYNC_QUEUE_FILE NEW - Jednorazowa migracja JSON queue → DB w cron.php (automatyczna przy pierwszym uruchomieniu) SECURITY - cron.php — ochrona endpointu: wymaga $config['cron_key'] w URL (?key=...) lub trybu CLI FIX - CronJobRepository::fetchNext() — re-SELECT po UPDATE eliminuje race condition przy równoległych workerach FIX - cron.php — null check dla $mdb->query() przed ->fetch() / ->fetchAll() (3 miejsca) FIX - cron.php — walidacja odpowiedzi curl w APILO_PRODUCT_SYNC i APILO_PRICELIST_SYNC (zapobiega zapisaniu null do bazy) FIX - DI wiring — CronJobRepository przekazywany do OrderAdminService we wszystkich 4 punktach: admin\App, api\ApiRouter, front\App, cron.php TESTS - 41 nowych testów CronJob (CronJobTypeTest, CronJobRepositoryTest, CronJobProcessorTest) MIGRATION - migrations/0.324.sql

ver. 0.323 - 24.02.2026
FIX - IntegrationsRepository::shopproImportProduct() — kompletny refactor importu zdjęć: walidacja HTTP response, curl timeouty, bezpieczna budowa URL, szczegółowy log do logs/shoppro-import-debug.log i error_log, czytelny komunikat z wynikiem FIX - ProductRepository::saveProduct() — saveCustomFields() wywoływane tylko gdy klucz custom_field_name istnieje w danych (partial update przez API nie czyści custom fields) FIX - ProductRepository::delete() — usuwanie rekordów z pp_shop_products_custom_fields przy kasowaniu produktu FIX - ProductsApiController::upload_image() — poprawka ścieżki uploadu (upload/ zamiast ../upload/ — api.php działa z rootu projektu) NEW - ProductArchiveController::delete_permanent() — trwałe usunięcie produktu z archiwum (wraz ze zdjęciami i załącznikami) NEW - Przycisk "Usuń trwale" w liście produktów archiwalnych z potwierdzeniem

ver. 0.318 - 24.02.2026
NEW - IntegrationsRepository::shopproExportProduct() — eksport produktu do zdalnej instancji shopPRO: pola główne, tłumaczenia, custom fields, zdjęcia przez API (base64) NEW - IntegrationsRepository::sendImageToShopproApi() — wysyłka zdjęć do remote API shopPRO (endpoint upload_image) z base64 REFACTOR - shopproImportProduct() — wydzielono shopproDb() i missingShopproSetting() jako prywatne helpery; dodano import security_information, producer_id, custom fields i alt zdjęcia NEW - AttributeRepository::ensureAttributeForApi() i ensureAttributeValueForApi() — idempotent find-or-create dla atrybutów i ich wartości (integracje API) NEW - API endpoint POST /api.php?endpoint=dictionaries&action=ensure_attribute — utwórz lub znajdź atrybut po nazwie i typie NEW - API endpoint POST /api.php?endpoint=dictionaries&action=ensure_attribute_value — utwórz lub znajdź wartość atrybutu po nazwie NEW - API endpoint POST /api.php?endpoint=products&action=upload_image — przyjmuje zdjęcie produktu jako base64 JSON, zapisuje plik i rekord w pp_shop_products_images NEW - IntegrationsController::shoppro_product_export() — akcja admina eksportująca produkt do shopPRO NEW - Przycisk "Eksportuj do shopPRO" w liście produktów (widoczny gdy shopPRO enabled) NEW - Pole "API key" w ustawieniach integracji shopPRO (shoppro-settings.php)

ver. 0.317 - 23.02.2026
FIX - SettingsRepository::saveSettings() — pole api_key brakowało w whiteliście zapisywanych pól, przez co wartość była tracona przy każdym zapisie (TRUNCATE + insert) NEW - Pole "Klucz API" w ustawieniach — przycisk "Generuj" do losowego 32-znakowego klucza alfanumerycznego, usunięto "(ordersPRO)" z nazwy FIX - api.php — routing API przeniesiony przed ładowanie globalnych settings (wczesne wyjście), obsługa błędów przez \Throwable FIX - ApiRouter — catch \Throwable zamiast \Exception dla pełniejszego łapania błędów

ver. 0.316 - 23.02.2026
FIX - Dodanie brakującej kolumny type w tabeli pp_shop_products_custom_fields — kolumna była używana w kodzie od v0.277 ale nigdy nie miała migracji ALTER TABLE, przez co instancje ze starszą bazą dostawały PDOException: Column not found: 1054 Unknown column 'type' przy zapisie produktu

ver. 0.315 - 23.02.2026
FIX - AttributeRepository::listForAdmin() — zapytanie COUNT dostawało parametr :default_lang_id którego nie miało w SQL, powodując PDOException: SQLSTATE[HY093]: Invalid parameter number. Parametr potrzebny tylko w głównym SELECT, nie w COUNT

ver. 0.314 - 23.02.2026
FIX - Globalna wyszukiwarka w panelu admina przestała zwracać wyniki — dodano Content-Type: application/json i Cache-Control: no-store (zapobiega cache'owaniu przez proxy/CDN), zmiana AJAX z GET na POST, fetchAll(PDO::FETCH_ASSOC), top-level try/catch z gwarantowaną odpowiedzią JSON NEW - document.title w widoku szczegółów zamówienia pokazuje numer zamówienia (np. "Zamówienie ZAM/123 - shopPro")

ver. 0.313 - 23.02.2026
FIX - syncApiloPayment() i syncApiloStatus() — (int) cast na apilo_order_id (format "PPxxxxxx") dawał 0, przez co metody pomijały sync z API Apilo. Zmiana na empty() NEW - Logowanie w syncApiloPaymentIfNeeded() i syncApiloStatusIfNeeded() — każda ścieżka decyzyjna (Apilo wyłączone, brak tokenu, brak apilo_order_id, sync nieudany) zapisuje wpis do pp_log z kontekstem

ver. 0.312 - 23.02.2026
FIX - curl_getinfo() wywoływane po curl_close() — HTTP code zawsze wynosił 0, uniemożliwiając prawidłową obsługę odpowiedzi Apilo FIX - Nieskończona pętla wysyłania zamówienia — gdy Apilo zwracało błąd serwera, zamówienie nie dostawało apilo_order_id i było ponownie wybierane w każdym cyklu crona. Teraz błędne zamówienia oznaczane apilo_order_id = -1 z powiadomieniem email FIX - Ceny produktów 0.00 PLN w Apilo — string "0.00" z MySQL jest truthy w PHP, więc ternary wybierał price_brutto_promo (0.00) zamiast price_brutto. Zmiana na (float)... > 0 FIX - Walidacja cen przed wysyłką — zamówienia z zerowymi cenami produktów nie są wysyłane do Apilo (apilo_order_id = -2) z powiadomieniem email FIX - Niezainicjalizowana zmienna $order_message powodująca PHP warning

ver. 0.311 - 23.02.2026
FIX - Race condition — callback płatności przed wysłaniem zamówienia do Apilo nie synchronizował płatności (task trafiał w pustkę). Teraz syncApiloPaymentIfNeeded i syncApiloStatusIfNeeded kolejkują sync do retry gdy apilo_order_id jeszcze nie istnieje FIX - processApiloSyncQueue — zamówienia bez apilo_order_id były usuwane z kolejki bez synchronizacji. Teraz czekają (max 50 prób ~8h) aż cron wyśle zamówienie do Apilo FIX - Drugie wywołanie processApiloSyncQueue w cronie po wysyłce zamówień — sync płatności/statusów w tym samym cyklu FIX - Ceny w szczegółach zamówienia (admin + frontend) — gdy price_brutto_promo = 0 lub >= ceny regularnej, wyświetla cenę regularną zamiast 0 zł NEW - Persistence filtrów tabel w panelu admin — localStorage zapamiętuje ostatni widok (filtry, sortowanie, paginacja) i przywraca go przy powrocie do listy. Przycisk "Wyczyść" resetuje zapisany stan

ver. 0.310 - 23.02.2026
NEW - Zakładka "Logi" w sekcji Integracje — podgląd tabeli pp_log z paginacją, sortowaniem, filtrami (akcja, wiadomość, ID zamówienia) i rozwijalnym kontekstem JSON NEW - IntegrationsRepository::getLogs(), deleteLog(), clearLogs() — metody do obsługi logów NEW - IntegrationsController::logs(), logs_clear() — akcje kontrolera NEW - Przycisk "Wyczyść wszystkie logi" z potwierdzeniem

ver. 0.309 - 23.02.2026
NEW - ApiloLogger — logowanie operacji Apilo do tabeli pp_log z kontekstem JSON (send_order, resend_order, payment_sync, status_sync, status_poll) NEW - Migracja pp_log — kolumny action, order_id, context + indeksy NEW - Cache-busting dla CSS i JS w admin panelu — ?ver=filemtime() przy wszystkich lokalnych zasobach w main-layout.php FIX - Przeniesienie inicjalizacji $mdb przed SettingsRepository w admin/index.php FIX - Rzutowanie na (string) w ShopProductController::escapeHtml() — zapobiega warningom ZMIANA - Skrocone kategorie produktow na liscie — text-overflow: ellipsis z title tooltip ZMIANA - copyToClipboard() — uzywa navigator.clipboard API z fallbackiem na <textarea> ZMIANA - Uproszczenie CSS .site-content — usuniety zbedny .with-menu, menu widoczne zawsze na desktop

ver. 0.308 - 22.02.2026
NEW - Kolorowe badge statusow na liscie zamowien w admin panelu — kolory pobierane z pp_shop_statuses.color, kontrast tekstu obliczany automatycznie FIX - Walidacja formatu hex koloru z bazy (/^#[0-9a-fA-F]{3,6}$/) — odrzucanie nieprawidlowych wartosci FIX - Sanityzacja HTML w kolumnie "Dostawa" — strip_tags() + regex usuwajacy atrybuty z dozwolonych tagow (zapobieganie XSS via onclick itp.) OPTYMALIZACJA - Polaczenie dwoch zapytan SQL do pp_shop_statuses (nazwy + kolory) w jedno orderStatusData() ZMIANA - Path-based form submit w table-list.php — formularze filtrow i per-page uzywaja JS interceptora z data-path-submit zamiast natywnego GET, kompatybilne z admin URL routing NEW - 11 nowych testow jednostkowych (750 total, 2114 assertions)

ver. 0.307 - 22.02.2026
NEW - Przycisk "Sprawdz aktualizacje" w panelu admina — ikona odswiezenia obok numeru wersji, klik odpytuje serwer AJAX-em i pokazuje/ukrywa badge "aktualizacja" bez przeladowania strony NEW - UpdateController::checkUpdate() — nowa akcja AJAX czyszczaca sesje new-version i sprawdzajaca wersje z serwera NEW - updates/changelog.php — auto-generowany z manifestow JSON (_manifest.json) + changelog-legacy.json, zamiast recznej edycji HTML NEW - updates/changelog-legacy.json — migracja 295 wpisow changelogu (wersje 0.300-0.001) do formatu JSON ZMIANA - Workflow KONIEC PRACY — usuniety krok recznej edycji changelog.php (teraz automatyczny)

ver. 0.306 - 22.02.2026
FIX - Formy dostawy, dla ktorych nie ma zadnej dostepnej formy platnosci (np. wszystkie odfiltrowane przez min_order_amount/max_order_amount), sa teraz ukrywane z listy w koszyku ZMIANA - TransportRepository::transportMethodsFront() — po filtrze wagowym i korekcie darmowej dostawy, dodano filtr sprawdzajacy dostepnosc form platnosci per transport (z wykorzystaniem PaymentMethodRepository::paymentMethodsByTransport() z cache Redis) NEW - 5 nowych testow jednostkowych (739 total, 2089 assertions)

ver. 0.305 - 22.02.2026
FIX - Naprawa kolejnosci atrybutow permutacji — sortowanie po ID atrybutu (usort wg pierwszego segmentu przed -) we wszystkich miejscach: koszyk, kombinacje AJAX, getPermutation(), BasketCalculator. Zapewnia zgodnosc z permutation_hash generowanym przez ksort. NEW - Pasek postepu darmowej dostawy w koszyku — progress bar z ikona, tekstem i animacja. Pokazuje ile brakuje do progu free_delivery z ustawien sklepu. FIX - icheck CSS/JS przeniesione z szablonu product-combination do globalnego layoutu admina (main-layout.php) FIX - Tpl::isset() — obsluga isset() na zmiennych szablonu - .updateignore — lokalne style frontendowe dodane do listy ignorowania

ver. 0.304 - 22.02.2026
NEW - Kolumny min_order_amount i max_order_amount w pp_shop_payment_methods — konfigurowalne limity kwotowe per metoda platnosci NEW - Pola min/max kwoty zamowienia w formularzu edycji metody platnosci (admin) FIX - Zastapiono hardcoded warunek PayPo (id=6, 40-1000 PLN) generycznym filtrowaniem na froncie (basket checkout) NEW - Cache invalidation po zapisie metody platnosci NEW - 4 nowe testy jednostkowe (734 total, 2080 assertions) MIGRATION - migrations/0.304.sql — ALTER TABLE pp_shop_payment_methods ADD min/max_order_amount

ver. 0.303 - 22.02.2026
FIX - Naprawiono wyswietlanie atrybutow produktu na froncie — gdy dwa atrybuty mialy te sama wartosc kolejnosci (o), jeden nadpisywal drugi (kolizja kluczy tablicy). Teraz atrybuty sortowane przez usort() z unikalnymi kluczami sekwencyjnymi. NEW - Przycisk "Podglad" w formularzu edycji produktu — otwiera strone produktu w nowej karcie NEW - FormAction::preview() — nowy typ akcji formularza z target="_blank"

ver. 0.302 - 22.02.2026
NEW - API wariantow produktow — CRUD: variants, create_variant, update_variant, delete_variant NEW - API slownik atrybutow — dictionaries/attributes z wielojezycznymi nazwami i wartosciami NEW - Filtrowanie produktow po atrybutach w products/list — parametry attribute_{id}={value_id} NEW - Wzbogacone atrybuty w products/get — nazwy atrybutow i wartosci z tlumaczeniami NEW - Warianty w odpowiedzi products/get — lista wariantow z atrybutami dla produktow nadrzednych NEW - Walidacja price_brutto przy tworzeniu produktu (musi byc nieujemna liczba) NEW - Batch-loading atrybutow i wartosci (4 zapytania zamiast N+1) w AttributeRepository::listForApi() NEW - 43 nowe testy jednostkowe (730 total, 2066 assertions)

ver. 0.301 - 22.02.2026
NEW - Filtry w tabelach admina domyslnie ukryte — przycisk toggle z ikona filtra, badge z liczba aktywnych filtrow NEW - Stan filtrow zapamietywany w localStorage per widok; auto-show gdy filtry aktywne NEW - Mobilna wersja szczegolow zamowienia — responsywny layout (CSS-only, breakpoint 767px) NEW - Pasek akcji zamowienia — ikony-only na mobile, flex row bez zawijania NEW - Tabela produktow zamowienia — kompaktowa lista na mobile (obraz + nazwa + linia qty x cena = suma) NEW - Sekcje informacyjne zamowienia — full-width stacking na mobile NEW - Dropdown integracji jako bottom-sheet na mobile

ver. 0.300 - 21.02.2026
NEW - Manifest JSON per wersja — zastępuje osobne pliki _sql.txt i _files.txt NEW - Weryfikacja checksum SHA256 pobranych paczek ZIP NEW - Automatyczny backup plików przed nadpisaniem (backups/ directory) NEW - build-update.ps1 — automatyczne budowanie paczek z git diff między tagami NEW - .updateignore — wzorce plików wykluczonych z paczek aktualizacji NEW - migrations/ — folder na wersjonowane pliki SQL NEW - Panel "Log ostatniej aktualizacji" w widoku aktualizacji admina UPDATE - UpdateRepository — dual-mode dispatcher (manifest + legacy fallback)

ver. 0.299 - 21.02.2026
NEW - Toggle widoczności kolumn w komponentach table-list — przycisk z ikoną kolumn, dropdown z toggle switchami NEW - Stan widoczności kolumn zapisywany w localStorage per tabela (klucz na bazie basePath) NEW - Przycisk "Pokaż wszystkie" resetujący widoczność UPDATE - Style z table-list.php wyekstrahowane do osobnego pliku admin/layout/style-css/table-list.css UPDATE - admin/templates/site/main-layout.php — podłączenie table-list.css

ver. 0.297 - 19.02.2026
NEW - Endpoint products w REST API — lista, szczegóły, tworzenie, aktualizacja produktów NEW - \api\Controllers\ProductsApiController — 4 akcje (list, get, create, update) NEW - ProductRepository::listForApi() — lista produktów z filtrowaniem (search/status/promoted), sortowaniem i paginacją NEW - ProductRepository::findForApi() — szczegóły produktu z językami, zdjęciami, kategoriami i atrybutami NEW - Partial update — update merguje przesłane pola z istniejącymi danymi produktu NEW - Mapowanie API → format formularza (mapApiToFormData) — status/promoted jako checkboxy, languages jako mapy UPDATE - ApiRouter — rejestracja endpointu products UPDATE - docs/API.md — dokumentacja 4 akcji produktowych z przykładami - Tests: 21 nowych testów (ProductsApiControllerTest)

ver. 0.296 - 19.02.2026
NEW - REST API do zarządzania zamówieniami — lista, szczegóły, zmiana statusu, oznaczanie płatności NEW - Endpointy słownikowe — statusy zamówień, metody transportu, metody płatności NEW - Autentykacja API przez header X-Api-Key (klucz w pp_settings) NEW - \api\ApiRouter — router API z autentykacją, routingiem i helperami odpowiedzi NEW - \api\Controllers\OrdersApiController — 5 akcji (list, get, change_status, set_paid, set_unpaid) NEW - \api\Controllers\DictionariesApiController — 3 akcje (statuses, transports, payment_methods) NEW - OrderRepository::listForApi() — lista zamówień z filtrowaniem i paginacją (z updated_since do pollingu) NEW - OrderRepository::findForApi() — szczegóły zamówienia z produktami i historią statusów NEW - OrderRepository::touchUpdatedAt() — aktualizacja updated_at przy modyfikacji zamówienia NEW - Kolumna pp_shop_orders.updated_at — data ostatniej modyfikacji (polling API) NEW - Setting api_key w pp_settings — klucz autentykacji API UPDATE - api.php — skip sesji dla requestów API, routing do ApiRouter UPDATE - Metody updateOrderStatus, setAsPaid, setAsUnpaid, saveOrderByAdmin, saveNotes, createFromBasket wywołują touchUpdatedAt() NEW - docs/API.md — dokumentacja REST API - Tests: 30 nowych testów API (ApiRouter, OrdersApiController, DictionariesApiController)

ver. 0.295 - 19.02.2026
NEW - Edycja produktów w zamówieniu z panelu admina (dodawanie, usuwanie, zmiana ilości/cen) NEW - Wyszukiwarka produktów AJAX w formularzu edycji zamówienia (search_products_ajax) NEW - Automatyczna korekta stanów magazynowych przy edycji produktów zamówienia NEW - Automatyczne przeliczanie kosztu dostawy (próg darmowej dostawy) po zmianie produktów NEW - OrderRepository — CRUD: addOrderProduct(), updateOrderProduct(), deleteOrderProduct(), getOrderProduct(), updateTransportCost() NEW - OrderAdminService — searchProducts(), saveOrderProducts(), getFreeDeliveryThreshold(), adjustStock(), recalculateTransportCost() NEW - ShopOrderController — endpoint search_products_ajax, rozszerzony order_save o zapis produktów UPDATE - admin\App — rozszerzone DI wiring (ProductRepository, SettingsRepository, TransportRepository) FIX - OrderRepository::createOrder() — promo price = 0 gdy taka sama jak cena bazowa (brak realnej promocji) NEW - Template order-edit-custom-script.php — interaktywny JS do zarządzania produktami zamówienia UPDATE - Template order-edit.php — sekcja edycji produktów z dynamicznym formularzem - Tests: OrderAdminServiceTest (nowy), rozszerzony OrderRepositoryTest (+132 linii), zaktualizowany ShopOrderControllerTest

ver. 0.294 - 19.02.2026
Code review zakończony — 96 klas, ~1144 metody przejrzane. - Domain layer (16 fixes): - FIX: CategoryRepository — usunięto martwy kod updateCategoryDefaultLayoutId(), allCategoriesForCacheRefresh() - FIX: ClientRepository — null guard na query()->fetchAll() - FIX: DictionariesRepository — null guard na query()->fetchAll() (2 metody) - FIX: IntegrationsRepository — null guard na query()->fetchAll() (3 metody) - FIX: LanguagesRepository — null guard na query()->fetchAll() (2 metody) - FIX: LayoutsRepository — null guard na query()->fetchAll() (4 metody) - FIX: OrderAdminService — null safety find() + redundancja DI - FIX: OrderRepository — null guard na query()->fetchAll() - FIX: ProductRepository — null guard na query()->fetchAll() (8 metod), redundancja DI - FIX: PromotionRepository — redundancja new ProductRepository w pętlach (3 metody) - Admin layer (11 fixes): - FIX: admin\App — null guard po details() w logowaniu i 2FA - FIX: BannerController, ScontainersController, ShopProducerController — null guard find() ?: [] + save() null guard - FIX: PagesController — null guard menuDetails() ?: [], pageDetails() ?: [] - FIX: ProductArchiveController — $this->repository → $this->productRepository - FIX: ShopAttributeController — null guard findAttribute() ?: [] - FIX: ShopCouponController — null guard find() ?: [] - FIX: ShopProductSetsController, ShopPromotionController — null guard find() ?: [] - FIX: ShopProductController — null safety findForAdmin() ?: [] + 3x redundancja DI - Front layer (3 fixes): - FIX: LayoutEngine — undefined $level → null; $_GET['permutation_hash'] → ?? null - FIX: ShopBasketController — brakujące global $lang_id w basketAddProduct() - Shared layer (2 fixes): - FIX: Helpers::generate_webp_image() — $_GET['c_w']/$_GET['c_h'] → ?? null - FIX: Helpers::generate_webp_image() — bug: 'png' → 'image/png' (Imagick lossless WebP nigdy się nie aktywował) - CLASS_CATALOG.md — kompletny katalog z ✅/🔧 przy wszystkich 1144 metodach - Testy: 614 OK, 1821 asercji

ver. 0.293 - 19.02.2026
- ArticleRepository (7 fixes): - FIX: articlesByDateAdd() — SQL injection (addslashes→parameterized queries), dodano parametr $langId - FIX: articleDetailsFrontend() — uproszczono select()+foreach→get() - FIX: articlesIds(), pageArticlesCount() — parametryzacja $langId - FIX: topArticles(), newsListArticles() — DRY refactor via fetchArticlesByPage(), parametryzacja - AttributeRepository (1 fix): - FIX: clearTempAndCache() — martwy class_exists('\S') blokował czyszczenie cache/temp - CategoryRepository (2 fixes): - FIX: refreshCategoryArtifacts() — martwy class_exists('\S') blokował czyszczenie htaccess/temp - FIX: normalizeSeoLink() — krytyczny bug — linki SEO kategorii nigdy nie były generowane od usunięcia \S - BannerRepository (2 fixes): - FIX: banners(), mainBanner() — parametryzacja $today w SQL + null guard na query() - BasketCalculator (3 fixes): - FIX: checkProductQuantityInStock() — dodano is_array() guard (foreach na null→fatal) - FIX: summaryPrice() — dodano opcjonalne DI params $langId, $productRepo z fallbackiem do globals - FIX: calculateBasketProductPrice() — dodano opcjonalny $productRepo z fallbackiem do globals - PromotionRepository (1 fix): - FIX: findPromotion() — null guard na $basket (produkcyjny fatal error) - OrderRepository — zaktualizowano callery BasketCalculator (jawne DI zamiast globals), usunięto redundantne tworzenie ProductRepository w pętli - ShopBasketController, ajax.php — zaktualizowano callery summaryPrice (jawne $lang_id) - CLASS_CATALOG.md — zaktualizowano katalog dla 5 klas (rzeczywiste metody + znaczniki przeglądu) - Testy: 614 OK, 1821 asercji (+4 nowe testy BasketCalculator)

ver. 0.292 - 18.02.2026
- Faza 5.1: class.Order.php (~562 linii) USUNIETA - Logika Apilo sync przeniesiona do OrderAdminService::processApiloSyncQueue() - Email zmiany statusu zintegrowany w OrderAdminService::changeStatus() - cron.php przepiety na OrderAdminService - front\Controllers\ShopOrderController — dodano OrderAdminService jako drugie DI - \shop\Order::order_statuses() → OrderRepository::orderStatuses() (3 lokalizacje) - Faza 5.2: class.Product.php (~952 linii) USUNIETA — NAJWIEKSZA KLASA - ~20 metod przeniesionych do ProductRepository: findCached(), isProductOnPromotion(), productSetsWhenAddToBasket(), addVisit(), getProductImg(), getProductUrl(), searchProductsByName(), searchProductByNameAjax(), searchProductsByNameCount(), isStock0Buy(), getProductPermutationQuantityOptions(), getProductIdByAttributes(), getProductPermutationHash(), getProductAttributes(), generateSkuCode(), productMeta(), generateSubtitleFromAttributes(), getDefaultCombinationPrices(), getProductDataBySelectedAttributes(), productCategories(), arrayCartesian() - calculate_basket_product_price() przeniesione do BasketCalculator::calculateBasketProductPrice() - BasketCalculator przepisany: summaryPrice(), checkProductQuantityInStock() uzywaja ProductRepository - XML generation (4 metody) — konwersja object→array access - ~60+ callsite'ow zamienionych w kontrolerach, szablonach, repozytoriach i entry-pointach - Cache key strings zaktualizowane z \shop\Product:: na ProductRepository:: - Cleanup: - Usunieto dead \shop\ routing z front\App::route() - Cache key \shop\Promotion::get_active_promotions → PromotionRepository::getActivePromotions - Katalog autoload/shop/ jest teraz pusty - Production hotfixes: - FIX: findCached() — stale Redis cache z obiektami \shop\Product powodowal ceny 0,00 zl (obiekty PHP_Incomplete_Class po (array) cast maja zmanglowane klucze). Teraz invaliduje stary cache i re-fetchuje z DB - FIX: LayoutEngine.php — 4 niekwalifikowane Product::getFromCache() resolwaly do \front\Product po usunieciu use shop\Product - FIX: szablony (product-mini, product-search, product, product-warehouse-message, alert-product-sets, basket-details, main-view, promoted-products) — konwersja object access ($product->field) na array access ($product['field']) - UPDATE: AttributeRepository::getAttributeValueById() — dodano Redis cache (zgodnosc ze starym \shop\ProductAttribute::get_value_name()) - PODSUMOWANIE CALEJ MIGRACJI: 12 legacy klas, ~2363 linii kodu usunieto. Zero referencji \shop\ w aktywnym kodzie. - Testy: 610 OK, 1817 asercji

ver. 0.293 - 17.02.2026
- front\controls\Site → front\App — migracja routera na nowy namespace - Port 1:1 z camelCase: check_url_params() → checkUrlParams(), page_title() → pageTitle() - Wewnętrzna zmiana: \front\view\Site::contact() → \front\LayoutEngine::contact() - USUNIETA: autoload/front/controls/class.Site.php - front\view\Site → front\LayoutEngine — migracja layout engine na nowy namespace - Port 1:1 z camelCase: cookie_information() → cookieInformation() - Wewnętrzne zmiany: \front\controls\Site::route() → \front\App::route(), self-referencje na self:: - 13 stałych regex i ~30 tag replacements przeniesione 1:1 - USUNIETA: autoload/front/view/class.Site.php - Call sites — 4 miejsca przepięte: - index.php:62 — \front\App::checkUrlParams() - index.php:157 — \front\LayoutEngine::show() - index.php:160 — \front\LayoutEngine::cookieInformation() - ajax.php:51 — \front\App::checkUrlParams() - USUNIETE puste foldery: autoload/front/controls/, autoload/front/view/ - Pelna migracja frontendu zakonczona — autoload/front/ zawiera: App.php, LayoutEngine.php, Controllers/, Views/ - Testy: 610 OK, 1816 asercji (bez zmian — czysty rename/restructure)

ver. 0.292 - 17.02.2026
- Pelna migracja front\factory\ — USUNIETY caly folder autoload/front/factory/ (wszystkie 20 klas zmigrowane do Domain) - ShopProduct (frontend Stage 1) — migracja factory + controls na Domain - NOWE METODY w ProductRepository: ~20 metod frontendowych (getSkuWithFallback, getEanWithFallback, isProductActiveCached, productCategoriesFront, getWarehouseMessageZero/Nonzero, topProductIds, newProductIds, promotedProductIdsCached, getMinimalPrice, productImageCached, productNameCached, productUrlCached, randomProductIds, productWp) - USUNIETA: front\factory\class.ShopProduct.php (~410 linii) — logika przeniesiona do ProductRepository - USUNIETA: front\controls\class.ShopProduct.php — logika w ProductRepository + szablony - UPDATE: callerzy w szablonach, kontrolerach, index.php, cron.php przepieci na repo - ShopPaymentMethod (frontend) — migracja factory + view + shop facade na Domain - NOWE METODY w PaymentMethodRepository: metody frontendowe z Redis cache (paymentMethodsCached, paymentMethodCached, paymentMethodsByTransportCached) - USUNIETA: front\factory\class.ShopPaymentMethod.php, front\view\class.ShopPaymentMethod.php, shop\class.PaymentMethod.php - UPDATE: callerzy w szablonach i kontrolerach przepieci na PaymentMethodRepository - ShopPromotion (frontend) — migracja factory na Domain - NOWE METODY w PromotionRepository: 5 metod aplikowania promocji (applyTypeWholeBasket, applyTypeCheapestProduct, applyTypeCategoriesOr, applyTypeCategoriesAnd, applyTypeCategoryCondition) - USUNIETA: front\factory\class.ShopPromotion.php — logika przeniesiona do PromotionRepository - UPDATE: shop\Promotion::find_promotion() — 5 wywolan przepietych na repo - ShopStatuses (frontend) — rewiring callerow - USUNIETA: front\factory\class.ShopStatuses.php — 4 callerzy przepieci bezposrednio na ShopStatusRepository - ShopTransport (frontend) — migracja factory + view na Domain - NOWE METODY w TransportRepository: 4 metody frontendowe (transportMethodsFront, transportCostCached, findActiveByIdCached, forPaymentMethod) - USUNIETA: front\factory\class.ShopTransport.php, front\view\class.ShopTransport.php - UPDATE: 8 callerow przepietych na TransportRepository - FIX: broken transports_list() w ajax.php — nowa metoda forPaymentMethod() - NOWY: tests/stubs/ShopProduct.php — stub shop\Product dla testow - Testy: 610 OK, 1816 asercji (+37: 20 ProductRepository, 5 PaymentMethodRepository, 7 PromotionRepository, 5 TransportRepository)

ver. 0.291 - 17.02.2026
- ShopProducer (frontend) — migracja controls + shop facade na Domain + Controllers - NOWA METODA w ProducerRepository: allActiveProducers() — pełne dane aktywnych producentów (id, name, img) - NOWY: front\Controllers\ShopProducerController — instancyjny kontroler z DI (products(), list()) - USUNIETA: front\controls\class.ShopProducer.php — logika przeniesiona do kontrolera + repozytorium - USUNIETA: autoload\shop\class.Producer.php — fasada niepotrzebna, callery przepięte na repo - UPDATE: front\view\Site::show() — new \shop\Producer(...) zamienione na $producerRepo->findForFrontend() - UPDATE: front\controls\Site::getControllerFactories() — zarejestrowany 'ShopProducer' - FIX: bug shop\Producer::get() referował nieistniejące $this->data (usunięty z kodem klasy) - Testy: 573 OK, 1738 asercji (+8: 5 ProducerRepository frontend, 3 ShopProducerController)

ver. 0.290 - 17.02.2026
- ShopCoupon (frontend) — migracja controls + factory na Domain + Controllers - NOWE METODY w CouponRepository: 4 metody frontendowe (findByName, isAvailable, markAsUsed, incrementUsedCount) - NOWY: front\Controllers\ShopCouponController — instancyjny kontroler z DI (useCoupon, deleteCoupon) - KONWERSJA: shop\Coupon na fasade z dzialajacymi metodami (is_one_time, set_as_used) - FIX: kupony jednorazowe nigdy nie byly oznaczane jako uzyte (is_one_time zwracalo null) - USUNIETA: front\controls\class.ShopCoupon.php, front\factory\class.ShopCoupon.php - ShopOrder (frontend) — migracja controls + factory + view na Domain + Controllers - NOWE METODY w OrderRepository: 5 metod frontendowych (findIdByHash, findHashById, orderDetailsFrontend, generateOrderNumber, createFromBasket ~180 linii) - NOWY: front\Controllers\ShopOrderController — instancyjny kontroler z DI (paymentConfirmation, paymentStatusTpay, paymentStatusPrzelewy24pl, paymentStatusHotpay, orderDetails) - POPRAWA: webhooks przelewy24/hotpay — zamiana recznych $mdb->update/insert na \shop\Order::set_as_paid() + update_status() (spójnosc z tpay, poprawna obsluga Apilo sync) - UPDATE: ShopBasketController — DI OrderRepository (createFromBasket, findHashById) - UPDATE: ClientRepository::clientOrders() — OrderRepository::orderDetailsFrontend() - UPDATE: shop\Order::order_resend_confirmation_email() — OrderRepository::orderDetailsFrontend() - UPDATE: cron-turstmate.php — OrderRepository::orderDetailsFrontend() - USUNIETA: front\controls\class.ShopOrder.php, front\factory\class.ShopOrder.php, front\view\class.ShopOrder.php - Testy: 565 OK, 1716 asercji (+28: 12 CouponRepository frontend, 3 ShopCouponController, 10 OrderRepository frontend, 3 ShopOrderController)

ver. 0.289 - 17.02.2026
- ShopCategory (frontend) — migracja factory + view na Domain + Views - NOWE METODY w CategoryRepository: 9 metod frontendowych + 3 stale (SORT_ORDER_SQL, PRODUCTS_PER_PAGE, LANGUAGE_FALLBACK_NAME_SQL) - NOWY: front\Views\ShopCategory — czysty VIEW (categoryDescription, categoryView, categories) - USUNIETA: front\factory\class.ShopCategory.php — logika przeniesiona do CategoryRepository - USUNIETA: front\view\class.ShopCategory.php — zastapiona przez front\Views\ShopCategory - UPDATE: index.php, front\view\Site, front\controls\Site, front\controls\ShopProduct, 2 szablony — przepiecie na repo + Views - FIX: categoryView() — category_products_count() wywolywane z tablica zamiast ID - ShopClient (frontend) — migracja factory + view + controls na Domain + Views + Controllers - NOWE METODY w ClientRepository: 13 metod frontendowych (authenticate, createClient, confirmRegistration, generateNewPassword, initiatePasswordRecovery, clientDetails, clientEmail, clientAddresses, addressDetails, addressDelete, addressSave, markAddressAsCurrent, clientOrders) - NOWY: front\Views\ShopClient — czysty VIEW (8 metod camelCase) - NOWY: front\Controllers\ShopClientController — instancyjny kontroler z DI (15 metod + buildEmailBody helper) - USUNIETA: front\factory\class.ShopClient.php, front\view\class.ShopClient.php, front\controls\class.ShopClient.php - UPDATE: 7 callerow + rejestracja w getControllerFactories() - SECURITY FIX: usuniety hardcoded password bypass 'Legia1916' - OPTYMALIZACJA: buildEmailBody() deduplikuje 4x powtorzony wzorzec emaili - OPTYMALIZACJA: addressSave() przyjmuje array $data zamiast 6 parametrow - Testy: 537 OK, 1648 asercji (+53: 17 CategoryRepository frontend, 36 ClientRepository frontend)

ver. 0.288 - 17.02.2026
- ShopBasket (factory → Domain) — migracja na Domain - NOWY: Domain\Basket\BasketCalculator — 4 statyczne metody (summaryWp, countProductsText, summaryPrice, countProducts) - USUNIETA: front\factory\class.ShopBasket.php — logika przeniesiona do BasketCalculator - UPDATE: 18 callerow w 7 plikach przepietych na \Domain\Basket\BasketCalculator:: - ShopBasket (controls → Controllers) — migracja kontrolera - NOWY: front\Controllers\ShopBasketController — instancyjny kontroler z camelCase metodami - Wyekstrahowano jsonBasketResponse() — wspolna odpowiedz JSON dla 4 metod koszyka - Zainicjalizowano zmienne $values, $attributes, $custom_fields w basketAddProduct() - USUNIETA: front\controls\class.ShopBasket.php — zastapiona przez ShopBasketController - UPDATE: front\controls\Site::route() — konwersja snake_case → camelCase w dispatch dla nowych kontrolerow - UPDATE: front\controls\Site::title() / page_title() — sprawdzanie front\Controllers\*Controller przed fallback - Zarejestrowany 'ShopBasket' w getControllerFactories() - cms\Layout removal - USUNIETA: autoload/cms/class.Layout.php — caly folder autoload/cms/ (1 klasa, bug w get()) - UPDATE: front\view\Site::show() — new \cms\Layout(...) → $layoutsRepo->find(...) - Testy: 484 OK, 1528 asercji (+8 testow: BasketCalculatorTest)

ver. 0.287 - 17.02.2026
- Scontainers (frontend) — migracja na Domain - NOWA METODA w ScontainersRepository: frontScontainerDetails() — z Redis cache + fallback - UPDATE: clearFrontCache() — klucz cache dopasowany do nowego wzorca - NOWY: front\Views\Scontainers — czysty VIEW (scontainer()) - USUNIETA: front\factory\class.Scontainers.php — logika przeniesiona do ScontainersRepository - USUNIETA: front\view\class.Scontainers.php — zastapiona przez front\Views\Scontainers - UPDATE: front\view\Site::show() — przepiecie na $scontainersRepo->frontScontainerDetails() + \front\Views\Scontainers:: - ShopAttribute (frontend) — migracja na Domain - NOWE METODY w AttributeRepository: frontAttributeDetails(), frontValueDetails() — z Redis cache + fallback - NOWA: clearFrontCache() — czyszczenie cache frontowego per atrybut/wartość i język - UPDATE: saveAttribute(), deleteAttribute(), saveValues() — wpiete czyszczenie cache frontowego - USUNIETA: front\factory\class.ShopAttribute.php — logika przeniesiona do AttributeRepository - UPDATE: front\factory\ShopOrder — przepiecie na $attributeRepo->frontAttributeDetails() / frontValueDetails() - UPDATE: 3 szablony (product-attribute.php, summary-view.php, basket-details.php) — przepiecie na AttributeRepository - Testy: 476 OK, 1512 asercji (+6 testow: 2 ScontainersRepository frontend, 4 AttributeRepository frontend)

ver. 0.286 - 17.02.2026
- Layouts (frontend) — migracja na Domain - NOWE METODY w LayoutsRepository: categoryDefaultLayoutId(), getDefaultLayout(), getProductLayout(), getArticleLayout(), getCategoryLayout(), getActiveLayout() — z Redis cache, 3-level fallback (product→category→default) - USUNIETA: front\factory\class.Layouts.php — logika przeniesiona do LayoutsRepository - UPDATE: front\view\Site::show() — przepiecie na $layoutsRepo - UPDATE: Shared\Helpers\Helpers::htacces() — optymalizacja z 3 wywolan category_default_layout() do jednej zmiennej - Menu + Pages (frontend) — migracja na Domain + Views - NOWE METODY w PagesRepository: frontPageDetails(), frontPageSort(), frontMainPageId(), frontLangUrl(), frontMenuDetails(), frontMenuPages() — z Redis cache, rekurencja stron - NOWY: front\Views\Menu — czysty VIEW (pages(), menu()) - USUNIETA: front\factory\class.Menu.php — logika przeniesiona do PagesRepository - USUNIETA: front\factory\class.Pages.php — logika przeniesiona do PagesRepository - USUNIETA: front\view\class.Menu.php — zastapiona przez front\Views\Menu - USUNIETA: templates\menu\submenu.php — martwy kod (wola nieistniejaca metode Menu::submenu()) - UPDATE: front\controls\Site::check_url_params() — przepiecie na $pagesRepo->frontPageDetails() - UPDATE: index.php — przepiecie na $pagesRepo->frontPageDetails() - UPDATE: templates/site/languages.php — przepiecie na $pagesRepo->frontLangUrl() - UPDATE: templates/menu/menu.php, pages.php, main-menu.php — przepiecie na \front\Views\Menu:: - FIX: frontPageDetails() — usuniety type hint string z $langId + cast (string) (null $lang_id przy wczesnym wywolaniu check_url_params()) - FIX: front\controls\class.Site.php — dodano $lang_id ?? '' przy przekazywaniu do frontPageDetails() - Testy: 470 OK, 1484 asercji (+16 testow: 8 LayoutsRepository frontend, 8 PagesRepository frontend)

ver. 0.285 - 17.02.2026
- Shared\Tpl\Tpl — migracja silnika szablonow do namespace Shared - NOWY: autoload/Shared/Tpl/Tpl.php (namespace Shared\Tpl) - USUNIETA: autoload/class.Tpl.php — zastapiona przez Shared\Tpl\Tpl - ZAMIENIONE: ~135 plikow — \Tpl:: / new \Tpl → \Shared\Tpl\Tpl:: / new \Shared\Tpl\Tpl - DRY: wyciagnieto powtorzony ob_start/include/ob_get_contents/ob_end_clean do prywatnej metody renderFile() - FIX: bug w render() branch 3 — sprawdzal ../templates_user/ ale ladowal ../templates/ - CLEANUP: usunieta nieuzywana property $dir i konstruktor construct($dir) - CurlServer — usuniecie nieuzywanej klasy - USUNIETA: autoload/curl.class.php — klasa CurlServer bez referencji w projekcie (0 uzyc) - thumb.php — naprawa require po migracji Image - FIX: libraries/thumb.php — zmiana require_once '../autoload/class.Image.php' na ../autoload/Shared/Image/ImageManipulator.php + use - FIX: poprawiony short open tag <? na <?php - Testy: 454 OK, 1449 asercji

ver. 0.284 - 16.02.2026
- DbModel — usunięcie klasy base ORM - USUNIETA: autoload/class.DbModel.php — jedyny konsument (shop\Promotion) ma teraz wbudowany konstruktor + get() - UPDATE: autoload/shop/class.Promotion.php — usunięto extends DbModel + use DbModel, wbudowano minimalny konstruktor z $mdb->get() i get() - Testy: 454 OK, 1449 asercji

ver. 0.283 - 16.02.2026
- class.S.php → Shared\Helpers\Helpers - PRZENIESIONA: class.S.php → autoload/Shared/Helpers/Helpers.php (namespace Shared\Helpers, klasa Helpers) - ZAMIENIONE: ~140 plików — \S:: → \Shared\Helpers\Helpers:: - CLEANUP: usunięto 12 nieużywanych metod (set_array_value, parse_name, clear_redis_cache, get_domain, pre_dump, escape, chmod_r, rrmdir, rcopy, pre, json_to_array, is_empty_dir) - FIX: array_cartesian_product() — iteracja po niezdefiniowanej zmiennej $array zamiast parametru $input - NOWY: tests/stubs/Helpers.php — stub klasy Helpers dla testów - USUNIETA: autoload/class.S.php - Shared\Html\Html — autoload/class.Html.php → autoload/Shared/Html/Html.php - Shared\Email\Email — autoload/class.Email.php → autoload/Shared/Email/Email.php - Shared\Image\Image — autoload/class.Image.php → autoload/Shared/Image/Image.php - Shared\Log\Log — autoload/class.Log.php → autoload/Shared/Log/Log.php - Mobile_Detect — USUNIETA: przestarzała detekcja UA (v2.8.16), zastąpiona responsive design - USUNIETA: metoda S::is_mobile() i 3 warunki mobilne w front\view\Site - USUNIETE z LayoutsRepository: pola m_html, m_css, m_js - Testy: 454 OK, 1449 asercji

ver. 0.282 - 16.02.2026
- Shared\Cache namespace — przeniesienie CacheHandler i RedisConnection do Shared\Cache\ - NOWY: autoload/Shared/Cache/CacheHandler.php — glowna implementacja - NOWY: autoload/Shared/Cache/RedisConnection.php — glowna implementacja singleton - USUNIETA: autoload/class.CacheHandler.php — wrapper usuniety, 60 odwolan przepietych na \Shared\Cache\CacheHandler - USUNIETA: autoload/class.RedisConnection.php — wrapper usuniety, 12 odwolan przepietych na \Shared\Cache\RedisConnection - Eliminacja legacy Cache — usuniecie plikowego cache class.Cache.php - USUNIETA: autoload/class.Cache.php — legacy file-based cache (store/fetch z base64+serialize) - UPDATE: front\factory\ShopProduct — 5 metod przepietych z \Cache:: na CacheHandler (get_minimal_price, product_name, product_image, random_products, promoted_products) - UPDATE: front\factory\ShopPaymentMethod — 3 metody przepiete (payment_methods_by_transport, payment_method, payment_methods) - UPDATE: front\factory\ShopCategory — 2 metody przepiete (get_category_sort, category_name) - UPDATE: front\factory\ShopTransport — 2 metody przepiete (transport_cost, transport) - UPDATE: front\factory\ShopAttribute — 1 metoda przepieta (attribute_details) - UPDATE: Domain\Dictionaries\DictionariesRepository — prywatne wrappery cacheFetch/cacheStore przepiete na CacheHandler - FIX: naprawione rozbieznosci kluczy cache (random_products, category_name) — fetch i store uzywaly roznych kluczy - Testy: 454 OK, 1449 asercji

ver. 0.281 - 16.02.2026
- Banners (frontend) — migracja na Domain + Views - NOWE METODY w BannerRepository: banners(string $langId), mainBanner(string $langId) — z Redis cache, filtrowanie dat, plaski format $banner['languages'] (zgodny z szablonami) - NOWY: front\Views\Banners — czysty VIEW (banners(), mainBanner()) - USUNIETA: front\factory\Banners — logika przeniesiona do BannerRepository - USUNIETA: front\view\Banners — zastapiona przez front\Views\Banners - UPDATE: front\view\Site::show() — przepiecie linii 62-63 na repo + Views (bezposrednio $bannerRepo->banners() / $bannerRepo->mainBanner()) - Testy: 454 OK, 1449 asercji (+4 nowe testy w BannerRepositoryTest)

ver. 0.280 - 16.02.2026
- Articles (frontend) — pelna migracja na Domain + Views - NOWE METODY w ArticleRepository: articleDetailsFrontend(), articlesIds(), pageArticlesCount(), pageArticles(), news(), articleNoindex(), topArticles(), newsListArticles() - NOWY: front\Views\Articles — czysty VIEW + utility (renderowanie, generateTableOfContents, generateHeadersIds, getImage) - UPDATE: front\view\Site::show() — przepiecie 5 sekcji na repo + Views (BOX aktualnosci, article meta, noindex, news list, top articles) - UPDATE: front\controls\Site::route() — przepiecie single article + page_type switch (4 typy) na repo + Views - UPDATE: 5 szablonow templates/articles/* — przepiecie na \front\Views\Articles:: - FASADA: front\factory\Articles — 10 metod delegujacych do repo + Views - FASADA: front\view\Articles — 5 metod delegujacych do repo + Views - USUNIETA: class.Article — encja + metody statyczne; logika przeniesiona do ArticleRepository + front\Views\Articles - FIX: eliminacja global $lang z articleNoindex() — zamiana na jawny parametr $langId - FIX: eliminacja zaleznosci od \front\factory\Pages::page_sort() w news() — inline query - FIX: naprawione kolizje nazw zmiennych w front\view\Site::show() ($news_list → $news_list_matches, $top_news_matches) - Testy: 450 OK, 1431 asercji (+13 nowych testow w ArticleRepositoryTest) - UPDATE: tests/bootstrap.php — dodany stub S::is_array_fix()

ver. 0.279 - 16.02.2026
- Languages (view) — migracja do nowego namespace - USUNIĘTA: front\factory\Languages — fasada niepotrzebna, wszystkie zależności przepięte na Domain\Languages\LanguagesRepository - USUNIĘTA: front\view\Languages → przeniesiona do front\Views\Languages (nowy namespace, bez class. prefix) - UPDATE: 26 plików przepiętych z fasady na repozytorium (kontrolery DI, entry points, szablony, shop classes) - UPDATE: admin\App — DI factory dla ShopProductController rozszerzona o LanguagesRepository - Newsletter (frontend) — pełna migracja na Domain - NOWE METODY w NewsletterRepository: unsubscribe(), confirmSubscription(), getHashByEmail(), removeByEmail(), signup(), sendQueued() - NOWY: front\Controllers\NewsletterController — pierwszy frontowy kontroler z DI (nowy namespace front\Controllers\) - NOWY: front\Views\Newsletter — czysty VIEW (nowy namespace front\Views\) - USUNIĘTA: front\factory\Newsletter — logika przeniesiona do NewsletterRepository - USUNIĘTA: front\view\Newsletter → zastąpiona przez front\Views\Newsletter - USUNIĘTA: front\controls\Newsletter → zastąpiona przez front\Controllers\NewsletterController - UPDATE: front\controls\Site::route() — nowy routing: getControllerFactories() (DI) → fallback stare front\controls\ - UPDATE: front\factory\ShopClient — 4x get_template() przepięte na NewsletterRepository::templateByName() - UPDATE: index.php — newsletter_send() przepięte na $repo->sendQueued() - FIX: newsletter_unsubscribe() — błędna składnia medoo delete() (3 argumenty zamiast 2) - UPDATE: tests/bootstrap.php — dodane stuby: S::email_check(), S::get_session(), S::set_session() - Testy: 437 OK, 1398 asercji (+10 nowych testów w NewsletterRepositoryTest)

ver. 0.278 - 16.02.2026
- Settings + Languages (frontend) — pierwszy etap refaktoringu frontendu - NOWE METODY: SettingsRepository::allSettings($skipCache) — pobranie ustawien z cache Redis - NOWE METODY: SettingsRepository::getSingleValue($param) — pobranie pojedynczej wartosci ustawienia - NOWE METODY: LanguagesRepository::defaultLanguage() — domyslny jezyk z cache Redis - NOWE METODY: LanguagesRepository::activeLanguages() — lista aktywnych jezykow z cache Redis - NOWE METODY: LanguagesRepository::translations($lang) — tlumaczenia z cache Redis - UPDATE: front\factory\Settings → fasada delegujaca do SettingsRepository - UPDATE: front\factory\Languages → fasada delegujaca do LanguagesRepository - FIX: get_single_settings_value() — parametr $param poprawnie uzywany (wczesniej hardcoded 'firm_name') - Testy: 427 OK, 1378 asercji (+13 nowych)

ver. 0.277 - 16.02.2026
- ShopProduct (factory) - pelna migracja modulu #29 na Domain + DI - NOWE: ProductRepository rozszerzony o ~40 metod: CRUD (countProducts, listForAdmin, findForAdmin, allProductsList, productCategoriesText, getParentId, productDefaultName), zapis (saveProduct + 9 prywatnych helperow), operacje (delete, duplicate, toggleStatus, updatePriceBrutto/Promo, updateCustomLabel), kombinacje (getPermutations, generateCombinations, deleteCombination, countCombinations, saveCombination*), zdjecia/pliki (deleteImage, updateImageAlt, saveImagesOrder, deleteFile, updateFileName, deleteNonassigned*), Google Feed XML (generateGoogleFeedXml, generateEAN), custom labels (customLabelSuggestions, saveCustomLabel, saveXmlName), updateCombinationPricesFromBase - NOWE: ShopProductController rozszerzony o ~30 akcji: view_list, product_edit, save, duplicate_product, product_archive/unarchive, product_delete, change_product_status, product_change_price_brutto/promo, product_change_custom_label, product_custom_label_suggestions/save, ajax_product_url, generate_sku_code, product_combination, generate_combination, delete_combination, product_combination_*_save, image_delete, images_order_save, image_alt_change, product_file_delete, product_file_name_change, product_image_delete - UPDATE: przepiecie zaleznosci zewnetrznych: ProductArchiveController, order-details.php, cron.php, cron-xml.php, product-edit.php, mass-edit-custom-script.php - CLEANUP: usuniete autoload/admin/controls/class.ShopProduct.php, autoload/admin/factory/class.ShopProduct.php, admin/ajax/shop.php + require z admin/ajax.php - ShopOrder (stabilizacja po migracji) - FIX: Domain\Order\OrderRepository::listForAdmin() - poprawa zapytan SQL (count/list), bezpieczne fallbacki i poprawne zwracanie listy zamowien w /admin/shop_order/list/ - FIX: wyrównanie wysokości komórek w components/table-list (vertical-align + lokalny override dla .text-right w tabeli) - Integrations (cleanup) - CLEANUP: usunieta fasada autoload/admin/factory/class.Integrations.php - UPDATE: przepięcie wywołań na Domain\Integrations\IntegrationsRepository w: cron.php, shop\Order, admin\Controllers\ShopPaymentMethodController, admin\Controllers\ShopStatusesController, admin\Controllers\ShopTransportController - Admin UX - NOWE: globalna wyszukiwarka w top-barze (obok "Wyczysc cache") dla produktow i zamowien - NOWE: endpoint /admin/settings/globalSearchAjax/ (SettingsController::globalSearchAjax) - FIX: wsparcie wyszukiwania po pełnym imieniu i nazwisku (np. "Jan Kowalski") + poprawka escapingu SQL w CONCAT_WS - Dashboard - migracja modulu #30 na Domain + DI - NOWE: Domain\Dashboard\DashboardRepository (summaryOrders, summarySales, salesGrid, mostViewedProducts, bestSalesProducts, last24MonthsSales, lastOrders, Redis caching) - NOWE: admin\Controllers\DashboardController (DI z DashboardRepository + ShopStatusRepository) - CLEANUP: usuniete autoload/admin/controls/class.Dashboard.php, autoload/shop/class.Dashboard.php - Update - migracja modulu #31 na Domain + DI - NOWE: Domain\Update\UpdateRepository (update, runPendingMigrations, downloadAndApply, executeSql, deleteFiles, extractZip, saveLog) - NOWE: admin\Controllers\UpdateController (DI z UpdateRepository) - UPDATE: template update/main-view.php - usunieto gridEdit i $.prompt(), zastapiono panelami + $.confirm()/$.alert() - CLEANUP: usuniete autoload/admin/controls/class.Update.php, autoload/admin/factory/class.Update.php, autoload/admin/view/class.Update.php - Legacy cleanup - CLEANUP: usunieto autoload/admin/factory/class.Articles.php (martwy kod, articles_by_date_add przeniesione do ArticleRepository) - UPDATE: front\factory\Newsletter przepieta na Domain\Article\ArticleRepository::articlesByDateAdd() - CLEANUP: usunieto autoload/admin/view/class.Page.php, logika przeniesiona do admin\App::render() - CLEANUP: usuniete puste foldery autoload/admin/controls/, autoload/admin/factory/, autoload/admin/view/ - admin\Site -> admin\App - UPDATE: klasa admin\Site przemianowana na admin\App (plik App.php bez przedrostka class.) - UPDATE: refaktoring App — usunieto martwy fallback na \admin\controls\, uproszczono routing, ujednolicony code style - TEST: - NOWE: DashboardControllerTest (4), DashboardRepositoryTest (6), UpdateControllerTest (6), UpdateRepositoryTest (6) - Pelny suite: OK (414 tests, 1335 assertions)

ver. 0.276 - 15.02.2026
- ShopOrder - migracja /admin/shop_order/* na Domain + DI + nowe widoki - NOWE: Domain\Order\OrderRepository (lista admin z filtrowaniem/sortowaniem, szczegóły, historia statusów, notes, save admin, summary, trustmate, delete) - NOWE: Domain\Order\OrderAdminService (operacje aplikacyjne admin: status/paid/unpaid/resend email/send to apilo/delete) - NOWE: admin\Controllers\ShopOrderController (DI) z akcjami list/view_list, details/order_details, edit/order_edit, save/order_save, notes_save, order_status_change, order_resend_confirmation_email, set_order_as_paid, set_order_as_unpaid, send_order_to_apilo, toggle_trustmate_send, delete/order_delete - UPDATE: routing DI (admin\Site) rozszerzony o modul ShopOrder - UPDATE: menu admin przepiete na kanoniczny URL /admin/shop_order/list/ - UPDATE: lista zamówień przepięta z legacy grid na components/table-list (shop-order/orders-list) - UPDATE: shop-order/order-details i shop-order/order-edit przebudowane bez gridEdit + wydzielenie JS do *-custom-script.php - UPDATE: shop\Order::order_statuses() przepiete na Domain\ShopStatus\ShopStatusRepository - UPDATE: admin\controls\Dashboard pobiera statusy przez Domain\ShopStatus\ShopStatusRepository - CLEANUP: usuniete legacy autoload/admin/controls/class.ShopOrder.php, autoload/admin/factory/class.ShopOrder.php, admin/templates/shop-order/view-list.php - TEST: - NOWE: tests/Unit/Domain/Order/OrderRepositoryTest.php - NOWE: tests/Unit/admin/Controllers/ShopOrderControllerTest.php - Testy punktowe: OK (8 tests, 49 assertions)

ver. 0.275 - 15.02.2026
- ShopCategory - migracja /admin/shop_category/* na Domain + DI + nowe endpointy AJAX - NOWE: Domain\Category\CategoryRepository (sortTypes, subcategories, categoryDetails, categoryProducts, save, categoryDelete, saveCategoriesOrder, saveProductOrder, categoryTitle) - NOWE: admin\Controllers\ShopCategoryController (DI) z akcjami list/view_list, edit/category_edit, save, delete/category_delete, products/category_products, category_url_browser, save_categories_order, save_products_order, cookie_categories - UPDATE: routing DI (admin\Site) rozszerzony o modul ShopCategory - UPDATE: menu admin przepiete na kanoniczny URL /admin/shop_category/list/ - UPDATE: widoki shop-category/* - wydzielenie skryptow do *-custom-script.php, ujednolicone strzalki drzewa (button + caret + aria-expanded) - UPDATE: AJAX drzewek przepiety z /admin/ajax.php?a=* na /admin/shop_category/* - UPDATE: zaleznosci ShopProduct przepiete z admin\factory\ShopCategory na Domain\Category\CategoryRepository - CLEANUP: usuniete legacy autoload/admin/controls/class.ShopCategory.php, autoload/admin/factory/class.ShopCategory.php, autoload/admin/view/class.ShopCategory.php - CLEANUP: usuniety preload class.ShopCategory.php z libraries/grid/config.php - TEST: - NOWE: tests/Unit/Domain/Category/CategoryRepositoryTest.php - NOWE: tests/Unit/admin/Controllers/ShopCategoryControllerTest.php - Testy punktowe: OK (16 tests, 72 assertions) - Pelny suite: OK (377 tests, 1197 assertions)

ver. 0.274 - 15.02.2026
- ShopProduct (mass_edit) - migracja akcji masowej edycji na Domain + DI - NOWE: admin\Controllers\ShopProductController (DI) z akcjami mass_edit, mass_edit_save, get_products_by_category - UPDATE: routing DI (admin\Site) rozszerzony o modul ShopProduct - UPDATE: Domain\Product\ProductRepository rozszerzone o metody allProductsForMassEdit, getProductsByCategory, applyDiscountPercent (+ aktualizacja cen kombinacji) - CLEANUP: usuniete legacy akcje mass_edit, mass_edit_save, get_products_by_category z admin\controls\ShopProduct - ShopProduct mass_edit UI - przebudowa widoku i skryptu - UPDATE: admin/templates/shop-product/mass-edit.php przepiety na nowy partial JS mass-edit-custom-script - NOWE: admin/templates/shop-product/mass-edit-custom-script.php (nestedSortable + iCheck + stabilizacja drzewka) - UPDATE: admin/templates/shop-product/subcategories-list.php ujednolicone strzalki (button + caret) - FIX: zaznaczenie kategorii w drzewku nie zaznacza automatycznie produktow na liscie - Pages / Articles UI - ujednolicenie drzewek - UPDATE: /admin/pages/list/ - nowe strzalki drzewa + aria-expanded + odswiezanie stanu branch/leaf - UPDATE: /admin/articles/edit/* (zakladka wyswietlania) - nowe strzalki i checkboxy (iCheck) dla drzewka stron - ShopClients - migracja /admin/shop_clients na Domain + DI + nowe widoki - NOWE: Domain\Client\ClientRepository (listForAdmin, ordersForClient, totalsForClient) - NOWE: admin\Controllers\ShopClientsController (DI) z akcjami list, details + aliasy legacy view_list, clients_details - UPDATE: routing DI (admin\Site) rozszerzony o modul ShopClients - UPDATE: menu admin przepiete na kanoniczny URL /admin/shop_clients/list/ - UPDATE: widoki shop-clients/view-list i shop-clients/clients-details przepiete na components/table-list - CLEANUP: usuniete legacy autoload/admin/controls/class.ShopClients.php, autoload/admin/factory/class.ShopClients.php - TEST: - NOWE: tests/Unit/admin/Controllers/ShopProductControllerTest.php - NOWE: tests/Unit/Domain/Client/ClientRepositoryTest.php, tests/Unit/admin/Controllers/ShopClientsControllerTest.php - UPDATE: tests/Unit/Domain/Product/ProductRepositoryTest.php (nowe przypadki dla mass_edit) - UPDATE: tests/bootstrap.php (stub S::normalize_decimal()) - Testy: OK (361 tests, 1125 assertions)

ver. 0.273 - 15.02.2026
- ShopProducer - migracja /admin/shop_producer na Domain + DI + nowe widoki - NOWE: Domain\Producer\ProducerRepository (listForAdmin, find, save, delete, allProducers, findForFrontend, producerProducts, allActiveIds) - NOWE: admin\Controllers\ShopProducerController (DI) z akcjami list, edit, save, delete - UPDATE: modul /admin/shop_producer/* dziala na components/table-list i components/form-edit z zakladkami jezykowymi (Opis + SEO) - UPDATE: routing i menu admin na kanoniczny URL /admin/shop_producer/list/ - UPDATE: shop\Producer przepiety na fasade do Domain\Producer\ProducerRepository - UPDATE: admin\factory\ShopProduct - 2 wywolania admin\factory\ShopTransport przepiete na Domain\Transport\TransportRepository - UPDATE: admin\controls\ShopProduct - usuniety fallback do admin\factory\Layouts - CLEANUP: usuniete legacy autoload/admin/controls/class.ShopProducer.php, admin/templates/shop-producer/list.php, admin/templates/shop-producer/edit.php - CLEANUP: usuniete 6 pustych factory facades: admin\factory\Languages, admin\factory\Newsletter, admin\factory\Scontainers, admin\factory\ShopProducer, admin\factory\ShopTransport, admin\factory\Layouts - TEST: dodane tests/Unit/Domain/Producer/ProducerRepositoryTest.php i tests/Unit/admin/Controllers/ShopProducerControllerTest.php - Testy: OK (338 tests, 1063 assertions)

ver. 0.272 - 15.02.2026
- ShopProductSets - migracja /admin/shop_product_sets na Domain + DI + nowe widoki - NOWE: Domain\ProductSet\ProductSetRepository (listForAdmin, find, save, delete, allSets, allProductsMap) - NOWE: admin\Controllers\ShopProductSetsController (DI) z akcjami list, edit, save, delete - UPDATE: modul /admin/shop_product_sets/* dziala na components/table-list i components/form-edit + Selectize multi-select produktow - UPDATE: routing i menu admin na kanoniczny URL /admin/shop_product_sets/list/ - UPDATE: shop\ProductSet przepiety na fasade do Domain\ProductSet\ProductSetRepository - CLEANUP: usuniete legacy autoload/admin/controls/class.ShopProductSets.php, autoload/admin/factory/class.ShopProductSet.php, admin/templates/shop-product-sets/view-list.php, admin/templates/shop-product-sets/set-edit.php - TEST: dodane tests/Unit/Domain/ProductSet/ProductSetRepositoryTest.php i tests/Unit/admin/Controllers/ShopProductSetsControllerTest.php - Testy: OK (324 tests, 1000 assertions)

ver. 0.271 - 14.02.2026
- ShopAttribute - migracja /admin/shop_attribute na Domain + DI + nowe widoki - NOWE: Domain\Attribute\AttributeRepository (listForAdmin, findAttribute, saveAttribute, deleteAttribute, findValues, saveValues, saveLegacyValues, valueDetails) - NOWE: admin\Controllers\ShopAttributeController (DI) z akcjami list, edit, save, delete, values, values_save, value_row_tpl - UPDATE: modul /admin/shop_attribute/* dziala na components/table-list i components/form-edit - UPDATE: nowy edytor wartosci cechy (values-edit) z walidacja serwerowa i stabilnym row_key (bez indeksow do wyboru domyslnej wartosci) - UPDATE: routing i menu admin na kanoniczny URL /admin/shop_attribute/list/ (bez aliasow legacy) - UPDATE: przepiecie zaleznosci kombinacji produktu (admin\controls\ShopProduct, admin\factory\ShopProduct, admin/templates/shop-product/product-combination.php) na Domain\Attribute\AttributeRepository i shop\ProductAttribute - CLEANUP: usuniete legacy autoload/admin/controls/class.ShopAttribute.php, autoload/admin/factory/class.ShopAttribute.php, autoload/admin/view/class.ShopAttribute.php, admin/templates/shop-attribute/_partials/value.php - TEST: dodane tests/Unit/Domain/Attribute/AttributeRepositoryTest.php i tests/Unit/admin/Controllers/ShopAttributeControllerTest.php - Testy: OK (312 tests, 948 assertions)

ver. 0.270 - 14.02.2026
- Shop/Order + Apilo - utwardzenie synchronizacji platnosci i statusow zamowien - FIX: shop\Order::set_as_paid() wysyla do Apilo mapowany typ platnosci (payment_method_id -> apilo_payment_type_id) zamiast stalego type = 1 - NOWE: retry queue dla chwilowej niedostepnosci Apilo (temp/apilo-sync-queue.json) dla sync platnosci i statusu - NOWE: shop\Order::process_apilo_sync_queue() przetwarza zalegle syncy - UPDATE: cron.php uruchamia przetwarzanie kolejki sync Apilo przy aktywnej integracji - UPDATE: rozszerzone logowanie debug (logs/apilo.txt) o HTTP code i bledy cURL dla sync platnosci/statusu - Testy: OK (300 tests, 895 assertions)

ver. 0.269 - 14.02.2026
- ShopTransport - migracja /admin/shop_transport na Domain + DI + nowe widoki - NOWE: Domain\Transport\TransportRepository (listForAdmin, find, save, allActive, allForAdmin, findActiveById, getTransportCost, lowestTransportPrice, getApiloCarrierAccountId) - NOWE: admin\Controllers\ShopTransportController (DI) z akcjami list, edit, save - NOWE: widoki shop-transport/transports-list.php i shop-transport/transport-edit.php + transport-edit-custom-script.php - UPDATE: routing i menu admin na kanoniczny URL /admin/shop_transport/list/ - UPDATE: admin\factory\ShopTransport, front\factory\ShopTransport przepiete na nowe repozytorium - FIX: save() return type ?int zamiast int|bool (spojnosc z PaymentMethod) - FIX: toSwitchValue() helper zamiast === 'on' (obsluga '1', 'on', 'true', 'yes') - FIX: \S::delete_dir() przeniesione z repozytorium do kontrolera (DDD) - FIX: Medoo select() syntax - ORDER w WHERE zamiast 4-arg form - CLEANUP: usuniete legacy autoload/admin/controls/class.ShopTransport.php, autoload/admin/view/class.ShopTransport.php, admin/templates/shop-transport/view-list.php - FIX: transports-list.php - zmienna 'viewModel' zmieniona na 'list' (zgodnie z table-list.php komponentem) - Testy: OK (300 tests, 895 assertions)

ver. 0.268 - 14.02.2026
- ShopPaymentMethod - migracja /admin/shop_payment_method na Domain + DI + nowe widoki - NOWE: Domain\PaymentMethod\PaymentMethodRepository (listForAdmin, find, save, allActive, allForAdmin, findActiveById, isActive, getApiloPaymentTypeId, forTransport) - NOWE: admin\Controllers\ShopPaymentMethodController (DI) z akcjami list, edit, save - NOWE: widoki shop-payment-method/payment-methods-list.php i shop-payment-method/payment-method-edit.php - UPDATE: routing i menu admin na kanoniczny URL /admin/shop_payment_method/list/ - UPDATE: admin\controls\ShopTransport, front\factory\ShopPaymentMethod, shop\PaymentMethod przepiete na nowe repozytorium - CLEANUP: usuniete legacy autoload/admin/controls/class.ShopPaymentMethod.php, autoload/admin/factory/class.ShopPaymentMethod.php, autoload/admin/view/class.ShopPaymentMethod.php, admin/templates/shop-payment-method/view-list.php - Integrations/Apilo - stabilizacja tokenu i lepszy feedback - NOWE: automatyczne odswiezanie tokenu Apilo przed wygasnieciem (apiloKeepalive, refresh lead time) - UPDATE: cron uruchamia keepalive i odswieza konfiguracje Apilo - UPDATE: bardziej szczegolowe komunikaty bledow dla przyciskow integracji Apilo (co zrobic dalej) - Testy: OK (280 tests, 828 assertions)

ver. 0.267 - 14.02.2026
- ShopStatuses - migracja /admin/shop_statuses na Domain + DI + nowe widoki - NOWE: Domain\ShopStatus\ShopStatusRepository (listForAdmin, find, save, getApiloStatusId, getByIntegrationStatusId, allStatuses) - NOWE: admin\Controllers\ShopStatusesController (DI) z akcjami list, edit, save (bez aliasow legacy) - NOWE: typ pola FormFieldType::COLOR + FormField::color() + FormFieldRenderer::renderColor() (color picker HTML5 zsynchronizowany z polem tekstowym) - UPDATE: modul /admin/shop_statuses/* dziala na components/table-list i components/form-edit - UPDATE: front\factory\ShopStatuses jako fasada delegujaca do Domain\ShopStatus\ShopStatusRepository - UPDATE: menu admin przepiete na kanoniczny URL /admin/shop_statuses/list/ - CLEANUP: usuniete legacy autoload/admin/controls/class.ShopStatuses.php, autoload/admin/factory/class.ShopStatuses.php - UWAGA: statusy maja ID od 0 - kluczowe dla walidacji (find/save uzywaja $id < 0) - Testy: OK (254 tests, 736 assertions)

ver. 0.266 - 13.02.2026
- ShopCoupon - migracja /admin/shop_coupon na Domain + DI + nowe widoki - NOWE: Domain\Coupon\CouponRepository (listForAdmin, find, save, delete, categoriesTree) - NOWE: admin\Controllers\ShopCouponController (DI) z akcjami list, 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 na components/table-list i components/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: ujednolicone UI drzewek i checkboxow miedzy kuponami i layoutami - Testy: OK (235 tests, 682 assertions)

ver. 0.265 - 13.02.2026
- ShopPromotion - stabilizacja po migracji - UPDATE: dodane date_from w Domain\Promotion\PromotionRepository (save/find/list/sort) - UPDATE: admin\Controllers\ShopPromotionController rozszerzony o pole Data od na formularzu i kolumne Data od na liscie - UPDATE: shop\Promotion::get_active_promotions() filtruje aktywnosc po date_from i date_to - FIX: zapis edycji promocji nie tworzy nowego rekordu (hidden id + fallback id z URL) - TEST: rozszerzono PromotionRepositoryTest o asercje date_from - Testy: OK (222 tests, 614 assertions)

ver. 0.264 - 13.02.2026
- ShopPromotion - migracja /admin/shop_promotion na Domain + DI + nowe widoki - NOWE: Domain\Promotion\PromotionRepository (listForAdmin, find, save, delete, categoriesTree, invalidacja cache aktywnych promocji) - NOWE: admin\Controllers\ShopPromotionController (DI) z akcjami list, edit, save, delete - UPDATE: routing DI (admin\Site) rozszerzony o modul ShopPromotion - UPDATE: modul /admin/shop_promotion/* dziala na components/table-list i components/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/ - Testy: OK (222 tests, 609 assertions)

ver. 0.263 - 13.02.2026
- NOWE: Domain\Integrations\IntegrationsRepository (settings Apilo/ShopPRO, OAuth, product linking, API fetch) - NOWE: admin\Controllers\IntegrationsController (DI) dla akcji Apilo i ShopPRO - UPDATE: admin\factory\Integrations jako fasada delegujaca do repozytorium - 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, kontrolery/factory/front Shop* - Testy: OK (212 tests, 577 assertions)

ver. 0.262 - 13.02.2026
- NOWE: Domain\Pages\PagesRepository (CRUD menu/stron, drzewo stron, sortowanie, SEO) - NOWE: admin\Controllers\PagesController (DI) dla akcji menu/page/AJAX - UPDATE: widoki admin/templates/pages/* przepiete na dane z kontrolera/repozytorium - UPDATE: endpointy AJAX przepiete z admin/ajax.php?a=* na /admin/pages/* - CLEANUP: usuniete legacy controls/Pages, view/Pages, factory/Pages, ajax/pages.php - Testy: OK (186 tests, 478 assertions)

ver. 0.261 - 13.02.2026
- UPDATE: Domain\Article\ArticleRepository rozszerzone o metody UI/admin i saveFilesOrder() - UPDATE: admin\Controllers\ArticlesController obsluguje AJAX: article_image_alt_change, article_file_name_change, article_image_delete, article_file_delete, filesOrderSave - UPDATE: lista artykulow nie korzysta juz z admin\factory\Articles::article_pages() - UPDATE: widok edycji przepiety z /admin/ajax.php na /admin/articles/* - UPDATE: drag&drop sortowania listy zalacznikow - CLEANUP: usuniete autoload/admin/view/class.Articles.php i admin/ajax/articles.php - Testy: OK (178 tests, 443 assertions)

ver. 0.260 - 12.02.2026
- NOWE: admin\Controllers\ArticlesArchiveController (DI) - UPDATE: Domain\Article\ArticleRepository rozszerzone o listArchivedForAdmin(), restore(), deletePermanently() - UPDATE: /admin/articles_archive/view_list/ migrowane na components/table-list - CLEANUP: usuniete legacy controls/ArticlesArchive, factory/ArticlesArchive, view/ArticlesArchive - Testy: OK (165 tests, 424 assertions)

ver. 0.259 - 12.02.2026
- NOWE: Domain\Scontainers\ScontainersRepository (listForAdmin, find, save, delete, detailsForLanguage) - NOWE: admin\Controllers\ScontainersController (DI) - UPDATE: /admin/scontainers/* migrowane na components/table-list i components/form-edit - UPDATE: admin\factory\Scontainers i front\factory\Scontainers jako fasady - CLEANUP: usuniete controls/Scontainers, view/Scontainers - Testy: OK (158 tests, 397 assertions)

ver. 0.258 - 12.02.2026
- 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

ver. 0.257 - 12.02.2026
- NOWE: Domain\Newsletter\NewsletterRepository (subskrybenci, szablony, ustawienia, kolejka wysylki) - NOWE: Domain\Newsletter\NewsletterPreviewRenderer (render podgladu) - NOWE: admin\Controllers\NewsletterController (DI) - UPDATE: /admin/newsletter/* migrowane na components/table-list i components/form-edit - UPDATE: admin\factory\Newsletter jako fasada; front\factory\Newsletter bez admin\view\Newsletter - CLEANUP: usuniete controls/Newsletter, view/Newsletter - Testy: OK (150 tests, 372 assertions)

ver. 0.256 - 12.02.2026
- NOWE: Domain\Layouts\LayoutsRepository (find, save, delete, listForAdmin, menusWithPages, categoriesTree) - NOWE: admin\Controllers\LayoutsController (DI) - UPDATE: lista /admin/layouts/view_list/ migrowana na components/table-list - UPDATE: widok layouts/layout-edit korzysta z danych z repozytorium - NOWE: partial admin/templates/layouts/subcategories-list.php - UPDATE: Domain\Languages\LanguagesRepository::defaultLanguageId() jako wspolna metoda - UPDATE: ArticlesController korzysta z LayoutsRepository (DI) - CLEANUP: usuniete controls/Layouts, view/Layouts; factory/Layouts jako fasada - Testy: OK (141 tests, 336 assertions)

ver. 0.255 - 12.02.2026
- UPDATE: SettingsController, BannerController, DictionariesController, ArticlesController pobieraja liste jezykow przez Domain/Languages/LanguagesRepository (DI) - UPDATE: router DI przekazuje LanguagesRepository do kontrolerow - UPDATE: legacy admin/controls, admin/factory/Shop* przepiete na LanguagesRepository - FIX: admin/factory/class.Languages.php poprawione na <?php (short_open_tag=Off) - Testy: OK (130 tests, 303 assertions)

ver. 0.254 - 12.02.2026
- NOWE: Domain\Languages\LanguagesRepository (languages + translations CRUD/list) - NOWE: admin\Controllers\LanguagesController (DI) - UPDATE: widoki languages/* migrowane na components/table-list i components/form-edit - CLEANUP: usuniete controls/Languages, view/Languages; factory/Languages jako fasada - Testy: OK (130 tests, 301 assertions)

ver. 0.253 - 12.02.2026
- NOWE: Domain\User\UserRepository (CRUD, logon, 2FA, checkLogin) - NOWE: admin\Controllers\UsersController (DI: view_list, user_edit, user_save, user_delete, login_form, twofa) - UPDATE: admin\factory\Users jako fasada; admin/ajax/users.php oparty o UserRepository - UPDATE: widoki users migrowane na components/table-list i components/form-edit - UPDATE: walidacja warunkowa: twofa_email wymagany gdy twofa_enabled = 1 - CLEANUP: usuniete controls/Users, factory/Users, view/Users - Testy: OK (119 tests, 256 assertions)

ver. 0.252 - 10.02.2026
- UPDATE: ProductArchiveController i szablony przepiete na components/table-list - UPDATE: CSS/JS dla list wydzielone do osobnych widoków *-custom-script.php - NOWE: admin\Controllers\FilemanagerController - przepieto filemanager na nowy routing - FIX: naprawiono błąd Invalid Key w filemanagerze - CLEANUP: usunieto legacy controls/Archive, controls/Filemanager, view/FileManager, stare szablony - RENAME: admin/templates/product_archive/ → admin/templates/product-archive/ - Testy: OK (82 tests, 181 assertions)

ver. 0.251 - 09.02.2026
- NOWE: Domain\Dictionaries\DictionariesRepository (listForAdmin, find, save, delete, allUnits) - NOWE: admin\Controllers\DictionariesController (lista + formularz na nowych komponentach) - UPDATE: migracja słowników na components/table-list i components/form-edit - FIX: obsługa lang_id jako string (pl, en) w zapisie tłumaczeń - CLEANUP: usunięto legacy klasy Dictionaries (admin\controls, admin\factory, front\factory) - Testy: OK (82 tests, 181 assertions)

ver. 0.250 - 09.02.2026
- UPDATE: Domain\Settings\SettingsRepository ma bezpośredni dostęp do DB (bez delegacji do admin\factory\Settings) - UPDATE: przepięto użycia admin\factory\Settings na Domain\Settings\SettingsRepository - CLEANUP: usunięto legacy klasy Settings (factory, controls, view) - Testy: OK (82 tests, 181 assertions)

ver. 0.246 - 07.02.2026
- CLEANUP: usunięto autoload/admin/controls/class.Articles.php - UPDATE: admin\Controllers\ArticlesController::galleryOrderSave() uzywa ArticleRepository::saveGalleryOrder() - FIX: sortowanie list admin po reloadzie - RewriteRule dla /admin/... ma QSA - FIX: generator \S::htacces() komentuje dyrektywy AddHandler|SetHandler|ForceType - Testy: OK (65 tests, 131 assertions)

ver. 0.245 - 06.02.2026
- UPDATE: Domain\Article\ArticleRepository - dodano archive() (status = -1) - UPDATE: admin\Controllers\ArticlesController - nowa akcja delete() z DI - UPDATE: admin\factory\Articles::articles_set_archive() deleguje do repozytorium - Testy: OK (59 tests, 123 assertions)

ver. 0.244 - 06.02.2026
- UPDATE: Domain\Article\ArticleRepository - dodano save() z prywatnych helperow - UPDATE: admin\Controllers\ArticlesController - nowa akcja save() z DI - UPDATE: tests/bootstrap.php - dodano stub S::seo() - Testy: OK (57 tests, 119 assertions)

ver. 0.243 - 06.02.2026
- UPDATE: Domain\Article\ArticleRepository - dodano deleteNonassignedImages() i deleteNonassignedFiles() - UPDATE: admin\Controllers\ArticlesController::edit() uses repository cleanup methods - Testy: OK (50 tests, 95 assertions)

ver. 0.242 - 06.02.2026
- NOWE: Domain\Article\ArticleRepository (find: artykuł + relacje) - UPDATE: admin\Controllers\ArticlesController - konstruktor DI + edit() używa repozytorium - UPDATE: admin\factory\Articles::article_details() deleguje do repozytorium - Testy: OK (48 tests, 91 assertions)

ver. 0.241 - 06.02.2026
- NOWE: admin\Controllers\ProductArchiveController (DI) - NOWE: ProductRepository::archive(), unarchive() - RENAME: admin/templates/archive/ → admin/templates/product_archive/ - FIX: SQL w ajax_products_list_archive() (puste wyszukiwanie + brak archive = 1) - Testy: OK (50 tests, 95 assertions)

ver. 0.240 - 05.02.2026
- NOWE: Domain\Settings\SettingsRepository (fasada → factory) - NOWE: Domain\Cache\CacheRepository (dirs + Redis) - NOWE: admin\Controllers\SettingsController (DI: clearCache, save, view) - FIX: Brakujący id="content" w main-layout.php - FIX: persist_edit = true w settings.php - Testy: OK (29 tests, 60 assertions)

ver. 0.239 - 05.02.2026
- NOWE: Domain\Banner\BannerRepository (find, delete, save) - NOWE: admin\Controllers\BannerController - pierwszy kontroler z DI - NOWE: Router z mapą $newControllers + fallback na stare kontrolery - NOWE: Autoloader PSR-4 fallback w 9 entry pointach - Zmigrowano: get_product_price() → ProductRepository::getPrice() - Zmigrowano: get_product_name() → ProductRepository::getName() - Testy: OK (15 tests, 31 assertions)

ver. 0.238 - 05.02.2025
- NOWE: Domain\Product\ProductRepository - pierwsza klasa w nowej architekturze - NOWE: Dependency Injection zamiast global $mdb - NOWE: Testy jednostkowe (5 testów, 100% pokrycie) - Zmigrowano: get_product_quantity() → ProductRepository::getQuantity() - Kompatybilność: Stara klasa shop\Product działa jako fasada

ver. 0.237 - 05.02.2025
- Automatyczne czyszczenie cache produktu po aktualizacji przez CRON - AJAX dla przycisku "Wyczyść cache" w panelu admin - Metody delete() i deletePattern() w CacheHandler - Metoda clear_product_cache() w klasie S *Dokument aktualizowany: 2026-02-17 (ver. 0.293)*