Fixes static container admin edit flow by preserving id in hiddenFields and adding route-id fallback during save. Adds regression tests for edit/create id behavior, updates release docs (changelog/testing/CLAUDE), and appends SonarQube open issues to docs/TODO. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1425 lines
106 KiB
Markdown
1425 lines
106 KiB
Markdown
# Changelog shopPRO
|
||
|
||
Logi zmian z migracji na Domain-Driven Architecture. Najnowsze na gorze.
|
||
|
||
---
|
||
|
||
## ver. 0.347 (2026-04-18) - Scontainers edit: update zamiast insert
|
||
|
||
- **FIX**: `autoload/admin/Controllers/ScontainersController.php` - `id` formularza przeniesione do `hiddenFields` w `FormEditViewModel`, dzieki czemu edycja kontenera nie gubi identyfikatora w formularzu tabowanym
|
||
- **FIX**: `autoload/admin/Controllers/ScontainersController.php` - dodany fallback `id` z parametru trasy (`/admin/scontainers/save/id={id}`), gdy `id` nie przyjdzie w payloadzie POST
|
||
- **NEW**: `tests/Unit/admin/Controllers/ScontainersControllerTest.php` - testy regresyjne:
|
||
- `testBuildFormViewModelStoresIdInHiddenFieldsForEdit`
|
||
- `testBuildFormViewModelKeepsCreateFlowWithZeroId`
|
||
- **SONARQUBE**: wykonano skan i zaktualizowano `docs/TODO.md` o nowe otwarte issues (bez duplikatow)
|
||
|
||
---
|
||
## ver. 0.346 (2026-04-16) - Fix usuwania wszystkich dodatkowych pĂłl produktu
|
||
|
||
- **FIX**: `autoload/admin/Controllers/ShopProductController.php` — dodany hidden marker `custom_field_name_present` w `renderCustomFieldsBox()`, gwarantujący że sekcja custom fields jest zawsze rozpoznawana w POST nawet gdy wszystkie pola usunięte
|
||
- **FIX**: `autoload/Domain/Product/ProductRepository.php` — warunek zapisu custom fields zmieniony z `array_key_exists('custom_field_name')` na `array_key_exists('custom_field_name_present')` — naprawa buga gdzie jQuery `.serialize()` pomijał klucz pustej tablicy
|
||
- **NEW**: `tests/Unit/Domain/Product/ProductRepositoryTest.php` — test `testSaveCustomFieldsDeletesAllWhenEmpty` potwierdzający poprawne kasowanie wszystkich pól
|
||
|
||
---
|
||
|
||
## ver. 0.345 (2026-03-25) - DataLayer GA4 fix + checkout token fix
|
||
|
||
- **FIX**: `templates/shop-order/order-details.php` — event purchase: id→item_id (string), name→item_name, price via normalize_decimal (fix price:0), usunięty hardcoded value: 25.42, dodany google_business_vertical
|
||
- **FIX**: `templates/shop-basket/summary-view.php` — event begin_checkout: id→item_id, name→item_name, dodany google_business_vertical
|
||
- **FIX**: `templates/shop-product/product.php` — event view_item: dodany currency PLN, value, price jako number (nie string), google_business_vertical; event add_to_cart: dodany google_business_vertical, parseInt(quantity)
|
||
- **NEW**: `templates/shop-basket/basket.php` — nowy event view_cart na stronie koszyka z pełnym zestawem danych GA4 (item_id, item_name, price, quantity, currency, google_business_vertical)
|
||
- **FIX**: `autoload/front/Controllers/ShopBasketController.php` — usunięty błędny guard w summaryView() blokujący kolejne zamówienia po pierwszym (redirect na stare zamówienie zamiast podsumowanie)
|
||
- **FIX**: `autoload/front/Controllers/ShopBasketController.php` — token zamówienia z jednorazowego na TTL 30 min (wiele kart, odświeżenie, "wstecz" nie unieważniają formularza)
|
||
- **NEW**: `autoload/front/Controllers/ShopBasketController.php` — logowanie błędów zamówień do `logs/logs-order-YYYY-MM-DD.log` (double-submit, token invalid, exception, falsy order_id)
|
||
- **FIX**: `autoload/front/Controllers/ShopBasketController.php` — redirect przy złym tokenie na `/koszyk-podsumowanie` zamiast `/koszyk` (użytkownik nie traci kontekstu)
|
||
|
||
---
|
||
|
||
## ver. 0.344 (2026-03-19) - Edycja personalizacji produktu w koszyku
|
||
|
||
- **NEW**: `autoload/front/Controllers/ShopBasketController.php` — nowa metoda `basketUpdateCustomFields()`: AJAX endpoint do edycji custom fields w koszyku z walidacją required, przeliczaniem product_code (MD5 hash) i merge duplikatów
|
||
- **NEW**: `templates/shop-basket/_partials/product-custom-fields.php` — przycisk "Edytuj personalizację" + formularz inline z aktualnymi wartościami
|
||
- **NEW**: `templates/shop-basket/basket-details.php` — przekazanie `product_code` do szablonu custom fields
|
||
- **NEW**: `templates/shop-basket/basket.php` — JavaScript obsługi edycji/zapisu/anulowania personalizacji
|
||
|
||
---
|
||
|
||
## ver. 0.343 (2026-03-19) - Custom fields: type + is_required + obsługa obrazków w koszyku
|
||
|
||
- **FIX**: `autoload/Domain/Product/ProductRepository.php` — kopiowanie custom fields przy duplikacji produktu uwzględnia teraz pola `type` i `is_required`
|
||
- **FIX**: `templates/shop-basket/_partials/product-custom-fields.php` — ochrona XSS (htmlspecialchars), obsługa pola typu `image`, bezpieczny fallback typu na `text`
|
||
|
||
---
|
||
|
||
## ver. 0.342 (2026-03-19) - Apilo: email z danymi zamĂłwienia + infinite retry dla order jobĂłw
|
||
|
||
- **FIX**: `cron.php` — email notyfikacji Apilo zawiera teraz dane zamówienia (numer, klient, data, kwota) zamiast surowego JSON payload; temat emaila zawiera numery zamówień
|
||
- **NEW**: `autoload/Domain/CronJob/CronJobType.php` — `isOrderRelatedApiloJob()` identyfikuje order joby (send_order, sync_payment, sync_status)
|
||
- **NEW**: `autoload/Domain/CronJob/CronJobRepository.php` — order-related Apilo joby ponawiane w nieskończoność co 30 min zamiast permanent failure po 10 próbach
|
||
- **NEW**: `cron.php` — email rozróżnia "PONAWIANY CO 30 MIN" (order joby) vs "TRWAĹY BĹÄ„D" (inne joby)
|
||
- **NEW**: `cron.php` — po udanym wysłaniu zamówienia do Apilo czyszczone są stuck joby sync_payment/sync_status
|
||
- **TEST**: +2 testy infinite retry w `CronJobRepositoryTest`
|
||
|
||
---
|
||
|
||
## ver. 0.341 (2026-03-16) - Bugfix: zamówienia nie wysyłały się do Apilo + retry i powiadomienia
|
||
|
||
- **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 (2026-03-15) - Bugfix: crash przy składaniu zamówienia z kuponem rabatowym
|
||
|
||
- **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 (2026-03-12) - Refactoring: wydzielenie ApiloRepository z IntegrationsRepository
|
||
|
||
- **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 (2026-03-12) - Bugfix: duplikaty zamówień + status COD
|
||
|
||
- **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 (2026-03-12) - Bezpieczeństwo: ochrona CSRF panelu administracyjnego
|
||
|
||
- **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 (2026-03-12) - Poprawki bezpieczeństwa: error handling w krytycznych ścieżkach
|
||
|
||
- **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 (2026-03-12) - Poprawki bezpieczeństwa: path traversal i XSS w szablonach
|
||
|
||
- **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 (2026-03-12) - Poprawki bezpieczeństwa: debug log, SQL, RedBeanPHP
|
||
|
||
- **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 (2026-03-10) - Ochrona przed podwójnym składaniem zamówienia (order submit token)
|
||
|
||
- **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 (2026-03-01) - API produktĂłw: nowe pola new_to_date i additional_message
|
||
|
||
- **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 (2026-03-01) - Bugfix: strona produktu używała layoutu kategorii zamiast domyślnego
|
||
|
||
- **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 (2026-02-27) - Eliminacja htaccess.conf — wszystkie trasy URL w pp_routes
|
||
|
||
- **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 (2026-02-27) - Routing kategorii, stron i artykułów przez pp_routes
|
||
|
||
- **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 (2026-02-27) - Ikona kopiowania wartości atrybutów w szczegółach zamówienia
|
||
|
||
- **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 (2026-02-27) - Masowe usuwanie w archiwum produktĂłw
|
||
|
||
- **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 (2026-02-27) - API: endpoint categories/list
|
||
|
||
- **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 (2026-02-27) - Fix changelog encoding + limit wyświetlania
|
||
|
||
- **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 (2026-02-27) - System kolejki zadań cron
|
||
|
||
- **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 (2026-02-24) - Import zdjęć, trwałe usuwanie, fix API upload
|
||
|
||
- **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 (2026-02-24) - ShopPRO export produktĂłw + API endpoints
|
||
|
||
- **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 (2026-02-23) - Klucz API: przycisk generowania + fix zapisu
|
||
|
||
- **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 (2026-02-23) - Migracja brakujÄ…cej kolumny type w custom fields
|
||
|
||
- **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 (2026-02-23) - Fix listowania atrybutĂłw w admin
|
||
|
||
- **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 (2026-02-23) - Fix wyszukiwarki admin + title zamĂłwienia
|
||
|
||
- **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 (2026-02-23) - Fix sync płatności Apilo + logowanie
|
||
|
||
- **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 (2026-02-23) - Fix krytycznych bugĂłw integracji Apilo
|
||
|
||
- **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 (2026-02-23) - Fix race condition Apilo + persistence filtrĂłw + poprawki cen
|
||
|
||
- **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 (2026-02-23) - Logi integracji w panelu admin
|
||
|
||
- **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 (2026-02-23) - ApiloLogger + cache-busting CSS/JS + poprawki UI
|
||
|
||
- **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 (2026-02-22) - Kolory statusow zamowien + poprawki bezpieczenstwa
|
||
|
||
- **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 (2026-02-22) - Przycisk sprawdzania aktualizacji + auto-changelog
|
||
|
||
- **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 (2026-02-22) - Ukrywanie form dostawy bez dostepnych platnosci
|
||
|
||
- **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 (2026-02-22) - Sortowanie permutacji + pasek darmowej dostawy
|
||
|
||
- **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 (2026-02-22) - Konfigurowalne limity kwotowe metod platnosci
|
||
|
||
- **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 (2026-02-22) - Fix: wyswietlanie atrybutow produktu na froncie + podglad produktu w adminie
|
||
|
||
- **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 (2026-02-22) - REST API: warianty produktow, atrybuty, filtrowanie
|
||
|
||
- **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 (2026-02-22) - Mobile responsive: filtry tabel i szczegoly zamowienia
|
||
|
||
- **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 (2026-02-21) - System aktualizacji oparty na manifestach JSON
|
||
|
||
- **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 (2026-02-21) - Widoczność kolumn w tabelach
|
||
|
||
- **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 (2026-02-19) - REST API produktĂłw
|
||
|
||
- **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 (2026-02-19) - REST API zamówień dla ordersPRO
|
||
|
||
- **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 (2026-02-19) - Admin: edycja produktĂłw w zamĂłwieniu + wyszukiwanie AJAX + korekta stanĂłw magazynowych
|
||
|
||
- **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 (2026-02-19) - Code review: full codebase review complete (96/96 classes), 27 fixes across all layers
|
||
|
||
**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 (2026-02-19) - Code review: fixes ArticleRepository, AttributeRepository, BannerRepository, BasketCalculator, CategoryRepository, PromotionRepository
|
||
|
||
- **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 (2026-02-18) - Usuniecie autoload/shop/ — 12 legacy klas
|
||
|
||
- **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 (2026-02-17) - front\controls\Site + front\view\Site → front\App + front\LayoutEngine
|
||
|
||
- **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 (2026-02-17) - ShopProduct + ShopPaymentMethod + ShopPromotion + ShopStatuses + ShopTransport frontend migration
|
||
|
||
- **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 (2026-02-17) - ShopProducer frontend migration
|
||
|
||
- **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 (2026-02-17) - ShopCoupon + ShopOrder frontend migration
|
||
|
||
- **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 (2026-02-17) - ShopCategory + ShopClient frontend migration
|
||
|
||
- **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 (2026-02-17) - BasketCalculator + ShopBasketController + cms\Layout removal
|
||
|
||
- **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 (2026-02-17) - Scontainers + ShopAttribute frontend migration
|
||
|
||
- **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 (2026-02-17) - Layouts, Menu, Pages frontend migration
|
||
|
||
- **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 (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-17 (ver. 0.293)*
|
||
|