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 0000000..98f3bb8 Binary files /dev/null and b/updates/0.20/ver_0.287.zip differ 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 @@