From a7e44f23fae38d1c15cfca3701cefcb3b708c28d Mon Sep 17 00:00:00 2001 From: Jacek Pyziak Date: Tue, 17 Feb 2026 08:47:21 +0100 Subject: [PATCH] ver. 0.287: Scontainers + ShopAttribute frontend migration to Domain - Scontainers: frontScontainerDetails() with Redis cache in ScontainersRepository - Scontainers: new front\Views\Scontainers VIEW, deleted factory + view legacy - ShopAttribute: frontAttributeDetails(), frontValueDetails() with Redis cache in AttributeRepository - ShopAttribute: clearFrontCache() per attribute/value + language - ShopAttribute: deleted front\factory\ShopAttribute, updated 4 callers - Tests: 476 OK, 1512 assertions (+6 frontend tests) Co-Authored-By: Claude Opus 4.6 --- .../Domain/Attribute/AttributeRepository.php | 89 ++++++++++++++++++ .../Scontainers/ScontainersRepository.php | 38 +++++++- autoload/front/Views/Scontainers.php | 12 +++ autoload/front/factory/class.Scontainers.php | 39 -------- .../front/factory/class.ShopAttribute.php | 51 ---------- autoload/front/factory/class.ShopOrder.php | 5 +- autoload/front/view/class.Scontainers.php | 12 --- autoload/front/view/class.Site.php | 3 +- docs/CHANGELOG.md | 20 ++++ docs/FRONTEND_REFACTORING_PLAN.md | 7 +- docs/PROJECT_STRUCTURE.md | 4 +- docs/TESTING.md | 20 +++- docs/UPDATE_INSTRUCTIONS.md | 12 +-- templates/shop-basket/basket-details.php | 5 +- templates/shop-basket/summary-view.php | 5 +- .../_partial/product-attribute.php | 3 +- .../Attribute/AttributeRepositoryTest.php | 69 ++++++++++++++ .../Scontainers/ScontainersRepositoryTest.php | 35 +++++++ updates/0.20/ver_0.287.zip | Bin 0 -> 20143 bytes updates/0.20/ver_0.287_files.txt | 3 + updates/changelog.php | 5 + updates/versions.php | 2 +- 22 files changed, 314 insertions(+), 125 deletions(-) create mode 100644 autoload/front/Views/Scontainers.php delete mode 100644 autoload/front/factory/class.Scontainers.php delete mode 100644 autoload/front/factory/class.ShopAttribute.php delete mode 100644 autoload/front/view/class.Scontainers.php create mode 100644 updates/0.20/ver_0.287.zip create mode 100644 updates/0.20/ver_0.287_files.txt diff --git a/autoload/Domain/Attribute/AttributeRepository.php b/autoload/Domain/Attribute/AttributeRepository.php index cb35114..b9a1785 100644 --- a/autoload/Domain/Attribute/AttributeRepository.php +++ b/autoload/Domain/Attribute/AttributeRepository.php @@ -191,6 +191,7 @@ class AttributeRepository $this->saveAttributeTranslations($attributeId, $names); $this->clearTempAndCache(); + $this->clearFrontCache($attributeId, 'frontAttributeDetails'); return $attributeId; } @@ -203,6 +204,7 @@ class AttributeRepository $deleted = (bool)$this->db->delete('pp_shop_attributes', ['id' => $attributeId]); if ($deleted) { $this->clearTempAndCache(); + $this->clearFrontCache($attributeId, 'frontAttributeDetails'); } return $deleted; @@ -302,6 +304,7 @@ class AttributeRepository $deleteIds = array_diff($currentIds, $incomingIds); foreach ($deleteIds as $deleteId) { + $this->clearFrontCache((int)$deleteId, 'frontValueDetails'); $this->db->delete('pp_shop_attributes_values_langs', ['value_id' => (int)$deleteId]); $this->db->delete('pp_shop_attributes_values', ['id' => (int)$deleteId]); } @@ -336,6 +339,7 @@ class AttributeRepository $translations = is_array($row['translations'] ?? null) ? $row['translations'] : []; $this->saveValueTranslations($rowId, $translations); $this->refreshCombinationPricesForValue($rowId, $impactOnPrice); + $this->clearFrontCache($rowId, 'frontValueDetails'); if (!empty($row['is_default'])) { $defaultValueId = $rowId; @@ -834,6 +838,91 @@ class AttributeRepository return $this->defaultLangId; } + // ── Frontend methods ────────────────────────────────────────── + + public function frontAttributeDetails(int $attributeId, string $langId): array + { + $cacheHandler = new \Shared\Cache\CacheHandler(); + $cacheKey = "AttributeRepository::frontAttributeDetails:$attributeId:$langId"; + + $objectData = $cacheHandler->get($cacheKey); + if ($objectData) { + $cached = @unserialize($objectData); + if (is_array($cached)) { + return $cached; + } + $cacheHandler->delete($cacheKey); + } + + $attribute = $this->db->get('pp_shop_attributes', '*', ['id' => (int)$attributeId]); + if (!is_array($attribute)) { + $attribute = ['id' => $attributeId, 'status' => 0, 'type' => 0]; + } + + $attribute['language'] = $this->db->get('pp_shop_attributes_langs', ['lang_id', 'name'], [ + 'AND' => [ + 'attribute_id' => (int)$attributeId, + 'lang_id' => $langId, + ], + ]); + if (!is_array($attribute['language'])) { + $attribute['language'] = ['lang_id' => $langId, 'name' => '']; + } + + $cacheHandler->set($cacheKey, $attribute); + return $attribute; + } + + public function frontValueDetails(int $valueId, string $langId): array + { + $cacheHandler = new \Shared\Cache\CacheHandler(); + $cacheKey = "AttributeRepository::frontValueDetails:$valueId:$langId"; + + $objectData = $cacheHandler->get($cacheKey); + if ($objectData) { + $cached = @unserialize($objectData); + if (is_array($cached)) { + return $cached; + } + $cacheHandler->delete($cacheKey); + } + + $value = $this->db->get('pp_shop_attributes_values', '*', ['id' => (int)$valueId]); + if (!is_array($value)) { + $value = ['id' => $valueId]; + } + + $value['language'] = $this->db->get('pp_shop_attributes_values_langs', ['lang_id', 'name'], [ + 'AND' => [ + 'value_id' => (int)$valueId, + 'lang_id' => $langId, + ], + ]); + if (!is_array($value['language'])) { + $value['language'] = ['lang_id' => $langId, 'name' => '']; + } + + $cacheHandler->set($cacheKey, $value); + return $value; + } + + private function clearFrontCache(int $id, string $type): void + { + if ($id <= 0 || !class_exists('\Shared\Cache\CacheHandler')) { + return; + } + + $cacheHandler = new \Shared\Cache\CacheHandler(); + $langs = $this->db->select('pp_langs', 'id', ['status' => 1]); + if (!is_array($langs)) { + return; + } + + foreach ($langs as $langId) { + $cacheHandler->delete("AttributeRepository::$type:$id:$langId"); + } + } + private function clearTempAndCache(): void { if (class_exists('\S')) { diff --git a/autoload/Domain/Scontainers/ScontainersRepository.php b/autoload/Domain/Scontainers/ScontainersRepository.php index d148c3b..12c7402 100644 --- a/autoload/Domain/Scontainers/ScontainersRepository.php +++ b/autoload/Domain/Scontainers/ScontainersRepository.php @@ -213,6 +213,41 @@ class ScontainersRepository "; } + // ── Frontend methods ────────────────────────────────────────── + + public function frontScontainerDetails(int $scontainerId, string $langId): array + { + $cacheHandler = new \Shared\Cache\CacheHandler(); + $cacheKey = "ScontainersRepository::frontScontainerDetails:$scontainerId"; + + $objectData = $cacheHandler->get($cacheKey); + if ($objectData) { + $cached = @unserialize($objectData); + if (is_array($cached)) { + return $cached; + } + $cacheHandler->delete($cacheKey); + } + + $scontainer = $this->detailsForLanguage($scontainerId, $langId); + + if (!is_array($scontainer)) { + $scontainer = [ + 'id' => $scontainerId, + 'status' => 0, + 'show_title' => 0, + 'languages' => [ + 'lang_id' => $langId, + 'title' => '', + 'text' => '', + ], + ]; + } + + $cacheHandler->set($cacheKey, $scontainer); + return $scontainer; + } + private function clearFrontCache(int $containerId): void { if ($containerId <= 0 || !class_exists('\Shared\Cache\CacheHandler')) { @@ -220,8 +255,7 @@ class ScontainersRepository } $cacheHandler = new \Shared\Cache\CacheHandler(); - $cacheKey = '\front\factory\Scontainers::scontainer_details:' . $containerId; - $cacheHandler->delete($cacheKey); + $cacheHandler->delete('ScontainersRepository::frontScontainerDetails:' . $containerId); } /** diff --git a/autoload/front/Views/Scontainers.php b/autoload/front/Views/Scontainers.php new file mode 100644 index 0000000..462962f --- /dev/null +++ b/autoload/front/Views/Scontainers.php @@ -0,0 +1,12 @@ +scontainer = $scontainer; + return $tpl->render( 'scontainers/scontainer' ); + } +} \ No newline at end of file diff --git a/autoload/front/factory/class.Scontainers.php b/autoload/front/factory/class.Scontainers.php deleted file mode 100644 index 675282b..0000000 --- a/autoload/front/factory/class.Scontainers.php +++ /dev/null @@ -1,39 +0,0 @@ -get($cacheKey); - if ($objectData) { - return unserialize($objectData); - } - - $repository = new \Domain\Scontainers\ScontainersRepository($mdb); - $langId = (string)($lang[0] ?? 'pl'); - $scontainer = $repository->detailsForLanguage((int)$scontainer_id, $langId); - - if (!is_array($scontainer)) { - $scontainer = [ - 'id' => (int)$scontainer_id, - 'status' => 0, - 'show_title' => 0, - 'languages' => [ - 'lang_id' => $langId, - 'title' => '', - 'text' => '', - ], - ]; - } - - $cacheHandler->set($cacheKey, $scontainer); - - return $scontainer; - } -} \ No newline at end of file diff --git a/autoload/front/factory/class.ShopAttribute.php b/autoload/front/factory/class.ShopAttribute.php deleted file mode 100644 index 858fa47..0000000 --- a/autoload/front/factory/class.ShopAttribute.php +++ /dev/null @@ -1,51 +0,0 @@ - get( $cacheKey ); - - if ( !$objectData ) - { - $value = $mdb -> get( 'pp_shop_attributes_values', '*', [ 'id' => (int)$value_id ] ); - $value['language'] = $mdb -> get( 'pp_shop_attributes_values_langs', [ 'lang_id', 'name' ], [ 'AND' => [ 'value_id' => (int)$value_id, 'lang_id' => $lang_id ] ] ); - - $cacheHandler -> set( $cacheKey, $value ); - } - else - { - return unserialize( $objectData ); - } - - return $value; - } - - public static function attribute_details( $attribute_id, $lang_id ) - { - global $mdb; - - $cacheHandler = new \Shared\Cache\CacheHandler(); - $cacheKey = 'attribute_details_' . $attribute_id . '_' . $lang_id; - $objectData = $cacheHandler->get( $cacheKey ); - - if ( !$objectData ) - { - $attribute = $mdb -> get( 'pp_shop_attributes', '*', [ 'id' => (int)$attribute_id ] ); - $attribute['language'] = $mdb -> get( 'pp_shop_attributes_langs', [ 'lang_id', 'name' ], [ 'AND' => [ 'attribute_id' => (int)$attribute_id, 'lang_id' => $lang_id ] ] ); - - $cacheHandler->set( $cacheKey, $attribute ); - } - else - { - return unserialize( $objectData ); - } - return $attribute; - } -} diff --git a/autoload/front/factory/class.ShopOrder.php b/autoload/front/factory/class.ShopOrder.php index d0b37c7..39681cf 100644 --- a/autoload/front/factory/class.ShopOrder.php +++ b/autoload/front/factory/class.ShopOrder.php @@ -162,8 +162,9 @@ class ShopOrder foreach ( $basket_position[ 'attributes' ] as $row ) { $row = explode( '-', $row ); - $attribute = \front\factory\ShopAttribute::attribute_details( $row[ 0 ], $lang_id ); - $value = \front\factory\ShopAttribute::value_details( $row[ 1 ], $lang_id ); + $attributeRepo = new \Domain\Attribute\AttributeRepository( $mdb ); + $attribute = $attributeRepo->frontAttributeDetails( (int)$row[ 0 ], $lang_id ); + $value = $attributeRepo->frontValueDetails( (int)$row[ 1 ], $lang_id ); if ( $attributes ) $attributes .= '
'; diff --git a/autoload/front/view/class.Scontainers.php b/autoload/front/view/class.Scontainers.php deleted file mode 100644 index db672f2..0000000 --- a/autoload/front/view/class.Scontainers.php +++ /dev/null @@ -1,12 +0,0 @@ - scontainer = \front\factory\Scontainers::scontainer_details( $id ); - return $tpl -> render( 'scontainers/scontainer' ); - } -} diff --git a/autoload/front/view/class.Site.php b/autoload/front/view/class.Site.php index 3b070e1..113ecc7 100644 --- a/autoload/front/view/class.Site.php +++ b/autoload/front/view/class.Site.php @@ -26,6 +26,7 @@ class Site $bannerRepo = new \Domain\Banner\BannerRepository( $GLOBALS['mdb'] ); $layoutsRepo = new \Domain\Layouts\LayoutsRepository( $GLOBALS['mdb'] ); $pagesRepo = new \Domain\Pages\PagesRepository( $GLOBALS['mdb'] ); + $scontainersRepo = new \Domain\Scontainers\ScontainersRepository( $GLOBALS['mdb'] ); if ( (int) \Shared\Helpers\Helpers::get( 'layout_id' ) ) $layout = new \cms\Layout( (int) \Shared\Helpers\Helpers::get( 'layout_id' ) ); @@ -415,7 +416,7 @@ class Site if ( is_array( $container_list[0] ) ) foreach( $container_list[0] as $container_list_tmp ) { $container_list_tmp = explode( ':', $container_list_tmp ); - $html = str_replace( '[KONTENER:' . $container_list_tmp[1] . ']', \front\view\Scontainers::scontainer( $container_list_tmp[1] ), $html ); + $html = str_replace( '[KONTENER:' . $container_list_tmp[1] . ']', \front\Views\Scontainers::scontainer( $scontainersRepo->frontScontainerDetails( (int)$container_list_tmp[1], $lang_id ) ), $html ); } return $html; diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index f291750..602fea1 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -4,6 +4,26 @@ Logi zmian z migracji na Domain-Driven Architecture. Najnowsze na gorze. --- +## 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 diff --git a/docs/FRONTEND_REFACTORING_PLAN.md b/docs/FRONTEND_REFACTORING_PLAN.md index a45f6e4..0f0e318 100644 --- a/docs/FRONTEND_REFACTORING_PLAN.md +++ b/docs/FRONTEND_REFACTORING_PLAN.md @@ -35,7 +35,7 @@ Panel administratora (33 moduły) został w pełni zmigrowany na architekturę D | ShopTransport | CZĘŚCIOWO zmigrowana | ŚREDNI — transport_methods z filtrowaniem | | ShopPaymentMethod | ZMIGROWANA (Domain) | — | | ShopStatuses | ZMIGROWANA (Domain) | — | -| Scontainers | ZMIGROWANA (Domain) | — | +| Scontainers | ZMIGROWANA (Domain) — usunięta | — | | Newsletter | ZMIGROWANA (Domain) — usunięta | — | | Settings | Fasada (BUG: get_single_settings_value ignoruje $param) | NISKI | | Languages | USUNIĘTA — przepięta na Domain | — | @@ -43,7 +43,7 @@ Panel administratora (33 moduły) został w pełni zmigrowany na architekturę D | Banners | USUNIETA — przepieta na Domain | — | | Menu | USUNIETA — przepieta na Domain | — | | Pages | USUNIETA — przepieta na Domain | — | -| ShopAttribute | Fasada | NISKI | +| ShopAttribute | ZMIGROWANA (Domain) — usunięta | — | | ShopCoupon | Model danych | NISKI | ### front/view/ (12 klas — renderowanie) @@ -51,7 +51,8 @@ Panel administratora (33 moduły) został w pełni zmigrowany na architekturę D |-------|--------| | Site | KRYTYCZNY — show() ~600 linii, pattern substitution engine | | ShopCategory | VIEW z logiką routingu (infinite scroll vs pagination) | -| Articles, Scontainers | Czyste VIEW | +| Articles | Czyste VIEW | +| Scontainers | PRZENIESIONA do `front\Views\Scontainers` | | Menu | PRZENIESIONA do `front\Views\Menu` | | Banners | PRZENIESIONA do `front\Views\Banners` | | Languages, Newsletter | PRZENIESIONE do `front\Views\` (nowy namespace) | diff --git a/docs/PROJECT_STRUCTURE.md b/docs/PROJECT_STRUCTURE.md index f0b12e7..9d3a651 100644 --- a/docs/PROJECT_STRUCTURE.md +++ b/docs/PROJECT_STRUCTURE.md @@ -109,7 +109,7 @@ shopPRO/ │ │ └── Tpl/ # Tpl (silnik szablonow) │ ├── front/ # Klasy frontendu │ │ ├── Controllers/ # Nowe kontrolery DI (Newsletter) -│ │ ├── Views/ # Nowe widoki (Newsletter, Articles, Languages, Banners, Menu) +│ │ ├── Views/ # Nowe widoki (Newsletter, Articles, Languages, Banners, Menu, Scontainers) │ │ ├── controls/ # Kontrolery legacy (Site, ShopBasket, ...) │ │ ├── view/ # Widoki legacy (Site, ...) │ │ └── factory/ # Fabryki/helpery (fasady) @@ -243,7 +243,7 @@ autoload/ │ └── view/ # Widoki (statyczne - bez zmian) ├── front/ │ ├── Controllers/ # Nowe kontrolery frontendowe (namespace \front\Controllers\) z DI -│ ├── Views/ # Nowe widoki (namespace \front\Views\) — czyste VIEW, statyczne (Menu, Newsletter, Articles, Languages, Banners) +│ ├── Views/ # Nowe widoki (namespace \front\Views\) — czyste VIEW, statyczne (Menu, Newsletter, Articles, Languages, Banners, Scontainers) │ ├── controls/ # Legacy kontrolery (fallback) │ ├── factory/ # Legacy helpery (stopniowo migrowane) │ └── view/ # Legacy widoki diff --git a/docs/TESTING.md b/docs/TESTING.md index 6b8f839..b28b5e1 100644 --- a/docs/TESTING.md +++ b/docs/TESTING.md @@ -36,7 +36,14 @@ Alternatywnie (Git Bash): Ostatnio zweryfikowano: 2026-02-17 ```text -OK (470 tests, 1484 assertions) +OK (476 tests, 1512 assertions) +``` + +Aktualizacja po migracji Scontainers + ShopAttribute frontend (2026-02-17, ver. 0.287): +```text +Pelny suite: OK (476 tests, 1512 assertions) +Nowe testy: ScontainersRepositoryTest (+2: frontScontainerDetails, frontScontainerDetailsFallback) +Nowe testy: AttributeRepositoryTest (+4: frontAttributeDetails, frontAttributeDetailsFallback, frontValueDetails, frontValueDetailsFallback) ``` Aktualizacja po migracji Layouts + Menu/Pages frontend (2026-02-17, ver. 0.286): @@ -523,3 +530,14 @@ OK (470 tests, 1484 assertions) Nowe testy dodane 2026-02-17: - `tests/Unit/Domain/Layouts/LayoutsRepositoryTest.php` (rozszerzenie: +8 testow frontend: categoryDefaultLayoutId, getDefaultLayout, getProductLayout, getArticleLayout, getCategoryLayout, getActiveLayout) - `tests/Unit/Domain/Pages/PagesRepositoryTest.php` (rozszerzenie: +8 testow frontend: frontPageDetails, frontMainPageId, frontPageSort, frontLangUrl, frontMenuDetails, frontMenuPages) + +## Aktualizacja suite (Scontainers + ShopAttribute frontend, ver. 0.287) +Ostatnio zweryfikowano: 2026-02-17 + +```text +OK (476 tests, 1512 assertions) +``` + +Nowe testy dodane 2026-02-17: +- `tests/Unit/Domain/Scontainers/ScontainersRepositoryTest.php` (rozszerzenie: +2 testow frontend: frontScontainerDetails, frontScontainerDetailsFallback) +- `tests/Unit/Domain/Attribute/AttributeRepositoryTest.php` (rozszerzenie: +4 testow frontend: frontAttributeDetails, frontAttributeDetailsFallback, frontValueDetails, frontValueDetailsFallback) diff --git a/docs/UPDATE_INSTRUCTIONS.md b/docs/UPDATE_INSTRUCTIONS.md index d776f51..4fe783e 100644 --- a/docs/UPDATE_INSTRUCTIONS.md +++ b/docs/UPDATE_INSTRUCTIONS.md @@ -18,16 +18,16 @@ Aktualizacje znajdują się w folderze `updates/0.XX/` gdzie XX oznacza dziesią ## Procedura tworzenia nowej aktualizacji -## Status biezacej aktualizacji (ver. 0.286) +## Status biezacej aktualizacji (ver. 0.287) -- Wersja udostepniona: `0.286` (data: 2026-02-17). +- Wersja udostepniona: `0.287` (data: 2026-02-17). - Pliki publikacyjne: - - `updates/0.20/ver_0.286.zip`, `ver_0.286_files.txt` + - `updates/0.20/ver_0.287.zip`, `ver_0.287_files.txt` - Pliki metadanych aktualizacji: - - `updates/changelog.php` (dodany wpis `ver. 0.286`) - - `updates/versions.php` (`$current_ver = 286`) + - `updates/changelog.php` (dodany wpis `ver. 0.287`) + - `updates/versions.php` (`$current_ver = 287`) - Weryfikacja testow przed publikacja: - - `OK (470 tests, 1484 assertions)` + - `OK (476 tests, 1512 assertions)` ### 1. Określ numer wersji Sprawdź ostatnią wersję w `updates/` i zwiększ o 1. diff --git a/templates/shop-basket/basket-details.php b/templates/shop-basket/basket-details.php index 240e011..c42dfdb 100644 --- a/templates/shop-basket/basket-details.php +++ b/templates/shop-basket/basket-details.php @@ -49,9 +49,10 @@ if ($row) { $row = explode('-', $row); - $attribute = \front\factory\ShopAttribute::attribute_details($row[0], $this->lang_id); + $attributeRepo = new \Domain\Attribute\AttributeRepository($GLOBALS['mdb']); + $attribute = $attributeRepo->frontAttributeDetails((int)$row[0], $this->lang_id); echo '
' . $attribute['language']['name'] . ':
'; - $value = \front\factory\ShopAttribute::value_details($row[1], $this->lang_id); + $value = $attributeRepo->frontValueDetails((int)$row[1], $this->lang_id); echo '
' . $value['language']['name'] . '
'; } ?> diff --git a/templates/shop-basket/summary-view.php b/templates/shop-basket/summary-view.php index fc7a751..fc079a6 100644 --- a/templates/shop-basket/summary-view.php +++ b/templates/shop-basket/summary-view.php @@ -30,9 +30,10 @@ if ($row) { $row = explode('-', $row); - $attribute = \front\factory\ShopAttribute::attribute_details($row[0], $this->lang_id); + $attributeRepo = new \Domain\Attribute\AttributeRepository($GLOBALS['mdb']); + $attribute = $attributeRepo->frontAttributeDetails((int)$row[0], $this->lang_id); echo '
' . $attribute['language']['name'] . ':
'; - $value = \front\factory\ShopAttribute::value_details($row[1], $this->lang_id); + $value = $attributeRepo->frontValueDetails((int)$row[1], $this->lang_id); echo '
' . $value['language']['name'] . '
'; } ?> diff --git a/templates/shop-product/_partial/product-attribute.php b/templates/shop-product/_partial/product-attribute.php index ad6391d..c42ca62 100644 --- a/templates/shop-product/_partial/product-attribute.php +++ b/templates/shop-product/_partial/product-attribute.php @@ -1,6 +1,7 @@ attribute['id'], $lang_id ); +$attributeRepo = new \Domain\Attribute\AttributeRepository( $GLOBALS['mdb'] ); +$attribute_details = $attributeRepo->frontAttributeDetails( (int)$this -> attribute['id'], $lang_id ); if ( $attribute_details['type'] == 0 ) { ?> diff --git a/tests/Unit/Domain/Attribute/AttributeRepositoryTest.php b/tests/Unit/Domain/Attribute/AttributeRepositoryTest.php index 9b2077d..5b6383d 100644 --- a/tests/Unit/Domain/Attribute/AttributeRepositoryTest.php +++ b/tests/Unit/Domain/Attribute/AttributeRepositoryTest.php @@ -258,6 +258,75 @@ class AttributeRepositoryTest extends TestCase $this->assertSame('Czerwony', $result); } + // ── Frontend methods tests ────────────────────────────────── + + public function testFrontAttributeDetailsReturnsAttributeWithLanguage(): void + { + $mockDb = $this->createMock(\medoo::class); + $mockDb->expects($this->exactly(2)) + ->method('get') + ->willReturnOnConsecutiveCalls( + ['id' => 5, 'status' => 1, 'type' => 0, 'o' => 2], + ['lang_id' => 'pl', 'name' => 'Kolor'] + ); + + $repository = new AttributeRepository($mockDb); + $result = $repository->frontAttributeDetails(5, 'pl'); + + $this->assertIsArray($result); + $this->assertSame(5, (int)$result['id']); + $this->assertSame('Kolor', $result['language']['name']); + $this->assertSame('pl', $result['language']['lang_id']); + } + + public function testFrontAttributeDetailsReturnsFallbackForNotFound(): void + { + $mockDb = $this->createMock(\medoo::class); + $mockDb->method('get')->willReturn(null); + + $repository = new AttributeRepository($mockDb); + $result = $repository->frontAttributeDetails(999, 'pl'); + + $this->assertIsArray($result); + $this->assertSame(999, (int)$result['id']); + $this->assertSame(0, (int)$result['status']); + $this->assertSame('pl', $result['language']['lang_id']); + $this->assertSame('', $result['language']['name']); + } + + public function testFrontValueDetailsReturnsValueWithLanguage(): void + { + $mockDb = $this->createMock(\medoo::class); + $mockDb->expects($this->exactly(2)) + ->method('get') + ->willReturnOnConsecutiveCalls( + ['id' => 12, 'attribute_id' => 5, 'is_default' => 1, 'impact_on_the_price' => null], + ['lang_id' => 'pl', 'name' => 'Czerwony'] + ); + + $repository = new AttributeRepository($mockDb); + $result = $repository->frontValueDetails(12, 'pl'); + + $this->assertIsArray($result); + $this->assertSame(12, (int)$result['id']); + $this->assertSame('Czerwony', $result['language']['name']); + $this->assertSame('pl', $result['language']['lang_id']); + } + + public function testFrontValueDetailsReturnsFallbackForNotFound(): void + { + $mockDb = $this->createMock(\medoo::class); + $mockDb->method('get')->willReturn(null); + + $repository = new AttributeRepository($mockDb); + $result = $repository->frontValueDetails(999, 'en'); + + $this->assertIsArray($result); + $this->assertSame(999, (int)$result['id']); + $this->assertSame('en', $result['language']['lang_id']); + $this->assertSame('', $result['language']['name']); + } + private function hasDeleteCall(array $calls, string $table, array $where): bool { foreach ($calls as $call) { diff --git a/tests/Unit/Domain/Scontainers/ScontainersRepositoryTest.php b/tests/Unit/Domain/Scontainers/ScontainersRepositoryTest.php index 5348e52..74da921 100644 --- a/tests/Unit/Domain/Scontainers/ScontainersRepositoryTest.php +++ b/tests/Unit/Domain/Scontainers/ScontainersRepositoryTest.php @@ -59,5 +59,40 @@ class ScontainersRepositoryTest extends TestCase $this->assertNull($repository->detailsForLanguage(0, 'pl')); $this->assertNull($repository->detailsForLanguage(1, '')); } + + // ── Frontend methods tests ────────────────────────────────── + + public function testFrontScontainerDetailsReturnsContainerWithLanguage(): void + { + $mockDb = $this->createMock(\medoo::class); + $mockDb->expects($this->exactly(2)) + ->method('get') + ->willReturnOnConsecutiveCalls( + ['id' => 3, 'status' => 1, 'show_title' => 1], + ['container_id' => 3, 'lang_id' => 'pl', 'title' => 'Tytul', 'text' => 'Tekst'] + ); + + $repository = new ScontainersRepository($mockDb); + $result = $repository->frontScontainerDetails(3, 'pl'); + + $this->assertIsArray($result); + $this->assertSame(3, (int)$result['id']); + $this->assertSame(1, (int)$result['status']); + $this->assertSame('Tytul', $result['languages']['title']); + } + + public function testFrontScontainerDetailsReturnsFallbackForNotFound(): void + { + $mockDb = $this->createMock(\medoo::class); + $mockDb->method('get')->willReturn(null); + + $repository = new ScontainersRepository($mockDb); + $result = $repository->frontScontainerDetails(999, 'pl'); + + $this->assertIsArray($result); + $this->assertSame(999, (int)$result['id']); + $this->assertSame(0, (int)$result['status']); + $this->assertSame('pl', $result['languages']['lang_id']); + } } diff --git a/updates/0.20/ver_0.287.zip b/updates/0.20/ver_0.287.zip new file mode 100644 index 0000000000000000000000000000000000000000..98f3bb8ae0192d22a5a0787a5db41207cf842286 GIT binary patch literal 20143 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 B+YJB! literal 0 HcmV?d00001 diff --git a/updates/0.20/ver_0.287_files.txt b/updates/0.20/ver_0.287_files.txt new file mode 100644 index 0000000..ba283b1 --- /dev/null +++ b/updates/0.20/ver_0.287_files.txt @@ -0,0 +1,3 @@ +F: ../autoload/front/factory/class.Scontainers.php +F: ../autoload/front/view/class.Scontainers.php +F: ../autoload/front/factory/class.ShopAttribute.php diff --git a/updates/changelog.php b/updates/changelog.php index 7a7b0b9..b44fdca 100644 --- a/updates/changelog.php +++ b/updates/changelog.php @@ -1,3 +1,8 @@ +ver. 0.287 - 17.02.2026
+- UPDATE - migracja front\factory\Scontainers do Domain\Scontainers\ScontainersRepository (frontScontainerDetails z Redis cache) +- UPDATE - migracja front\factory\ShopAttribute do Domain\Attribute\AttributeRepository (frontAttributeDetails, frontValueDetails z Redis cache) +- CLEANUP - usuniete 3 klasy legacy (front\factory\Scontainers, front\view\Scontainers, front\factory\ShopAttribute) +
ver. 0.286 - 17.02.2026
- UPDATE - migracja front\factory\Layouts do Domain\Layouts\LayoutsRepository (6 metod frontend z Redis cache) - UPDATE - migracja front\factory\Menu + front\factory\Pages do Domain\Pages\PagesRepository (6 metod frontend z Redis cache) diff --git a/updates/versions.php b/updates/versions.php index db61101..fd8f7d3 100644 --- a/updates/versions.php +++ b/updates/versions.php @@ -1,5 +1,5 @@