# Changelog shopPRO

Logi zmian z migracji na Domain-Driven Architecture. Najnowsze na gorze.

---

## ver. 0.285 (2026-02-17) - Tpl namespace, CurlServer removal, thumb.php fix

- **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 (2026-02-16) - DbModel elimination

- **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 (2026-02-16) - Legacy class cleanup — S, Html, Email, Image, Log, Mobile_Detect → Shared namespace

- **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 (2026-02-16) - Cache cleanup, Shared namespace

- **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 (2026-02-16) - Banners frontend migration

- **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 (2026-02-16) - Articles frontend migration

- **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 (2026-02-16) - Newsletter + Languages frontend migration, front\Controllers, front\Views

- **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 (2026-02-16) - Settings + Languages frontend migration

- **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 (2026-02-16) - ShopProduct factory, Dashboard, Update, legacy cleanup, admin\App

- **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 (2026-02-15) - ShopOrder

- **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 (2026-02-15) - ShopCategory

- **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 (2026-02-15) - ShopProduct mass_edit + UI trees

- **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 (2026-02-15) - ShopProducer

- **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 (2026-02-15) - ShopProductSets

- **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 (2026-02-14) - ShopAttribute

- **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 (2026-02-14) - Apilo payment/status sync hardening

- **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 (2026-02-14) - ShopTransport

- **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 (2026-02-14) - ShopPaymentMethod + Apilo token keepalive

- **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 (2026-02-14) - ShopStatuses

- **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 (2026-02-13) - ShopCoupon

- **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 (2026-02-13) - ShopPromotion poprawki

- **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 (2026-02-13) - ShopPromotion

- **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 (2026-02-13) - Integrations + cleanup Sellasist/Baselinker

- 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 (2026-02-13) - Pages

- 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 (2026-02-13) - Articles (dalsza refaktoryzacja)

- 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 (2026-02-12) - ArticlesArchive

- 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 (2026-02-12) - Scontainers

- 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 (2026-02-12) - Newsletter (stabilizacja)

- 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 (2026-02-12) - Newsletter

- 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 (2026-02-12) - Layouts

- 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 (2026-02-12) - Languages DI cleanup

- 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 (2026-02-12) - Languages

- 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 (2026-02-12) - Users

- 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 (2026-02-10) - ProductArchive + Filemanager

- 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 (2026-02-09) - Dictionaries

- 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 (2026-02-09) - Settings (refaktoryzacja)

- 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 (2026-02-07) - Articles legacy cleanup

- 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 (2026-02-06) - Articles::archive

- 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 (2026-02-06) - Articles::save

- 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 (2026-02-06) - Articles cleanup

- 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 (2026-02-06) - Articles::edit

- 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 (2026-02-06) - ProductArchive

- 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 (2026-02-05) - Settings + Cache

- 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 (2026-02-05) - Banner + Product

- 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 (2025-02-05) - Product Repository

- 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 (2025-02-05) - System cache produktów

- 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-14*
