ver. 0.278: Settings + Languages frontend migration, bug fix get_single_settings_value
- Add cached frontend methods to existing Domain repositories (allSettings, getSingleValue, defaultLanguage, activeLanguages, translations) - Convert front\factory\Settings and Languages to facades delegating to Domain repositories - Fix get_single_settings_value() - was hardcoded to 'firm_name', now uses $param correctly - Add CacheHandler stub methods (get/set/exists) to test bootstrap - Establish architectural rule: Domain classes are shared between admin and frontend Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -332,6 +332,85 @@ class LanguagesRepository
|
||||
return $translationId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Zwraca ID domyslnego jezyka (z flaga start=1) z cache Redis.
|
||||
*/
|
||||
public function defaultLanguage(): string
|
||||
{
|
||||
$cacheHandler = new \CacheHandler();
|
||||
$cacheKey = 'Domain\Languages\LanguagesRepository::defaultLanguage';
|
||||
|
||||
$objectData = $cacheHandler->get($cacheKey);
|
||||
if ($objectData) {
|
||||
return unserialize($objectData);
|
||||
}
|
||||
|
||||
$results = $this->db->query(
|
||||
'SELECT id FROM pp_langs WHERE status = 1 ORDER BY start DESC, o ASC LIMIT 1'
|
||||
)->fetchAll();
|
||||
|
||||
$defaultLanguage = $results[0][0] ?? 'pl';
|
||||
|
||||
$cacheHandler->set($cacheKey, $defaultLanguage);
|
||||
|
||||
return $defaultLanguage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Zwraca liste aktywnych jezykow z cache Redis.
|
||||
*/
|
||||
public function activeLanguages(): array
|
||||
{
|
||||
$cacheHandler = new \CacheHandler();
|
||||
$cacheKey = 'Domain\Languages\LanguagesRepository::activeLanguages';
|
||||
|
||||
$objectData = $cacheHandler->get($cacheKey);
|
||||
if ($objectData) {
|
||||
return unserialize($objectData);
|
||||
}
|
||||
|
||||
$activeLanguages = $this->db->select(
|
||||
'pp_langs',
|
||||
['id', 'name'],
|
||||
['status' => 1, 'ORDER' => ['o' => 'ASC']]
|
||||
);
|
||||
|
||||
if (!is_array($activeLanguages)) {
|
||||
$activeLanguages = [];
|
||||
}
|
||||
|
||||
$cacheHandler->set($cacheKey, $activeLanguages);
|
||||
|
||||
return $activeLanguages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Zwraca tlumaczenia dla danego jezyka z cache Redis.
|
||||
*/
|
||||
public function translations(string $language = 'pl'): array
|
||||
{
|
||||
$cacheHandler = new \CacheHandler();
|
||||
$cacheKey = "Domain\Languages\LanguagesRepository::translations:$language";
|
||||
|
||||
$objectData = $cacheHandler->get($cacheKey);
|
||||
if ($objectData) {
|
||||
return unserialize($objectData);
|
||||
}
|
||||
|
||||
$translations = ['0' => $language];
|
||||
|
||||
$results = $this->db->select('pp_langs_translations', ['text', $language]);
|
||||
if (is_array($results)) {
|
||||
foreach ($results as $row) {
|
||||
$translations[$row['text']] = $row[$language];
|
||||
}
|
||||
}
|
||||
|
||||
$cacheHandler->set($cacheKey, $translations);
|
||||
|
||||
return $translations;
|
||||
}
|
||||
|
||||
private function sanitizeLanguageId(string $languageId): ?string
|
||||
{
|
||||
$languageId = strtolower(trim($languageId));
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
namespace Domain\Settings;
|
||||
|
||||
/**
|
||||
* Repozytorium ustawien panelu administratora.
|
||||
* Repozytorium ustawien — wspolne dla admin i frontendu.
|
||||
*/
|
||||
class SettingsRepository
|
||||
{
|
||||
@@ -141,6 +141,58 @@ class SettingsRepository
|
||||
return $settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pobranie wszystkich ustawien z cache Redis.
|
||||
*
|
||||
* @param bool $skipCache Pomija cache (np. przy generowaniu htaccess)
|
||||
*/
|
||||
public function allSettings(bool $skipCache = false): array
|
||||
{
|
||||
$cacheHandler = new \CacheHandler();
|
||||
$cacheKey = 'Domain\Settings\SettingsRepository::allSettings';
|
||||
|
||||
if (!$skipCache) {
|
||||
$objectData = $cacheHandler->get($cacheKey);
|
||||
if ($objectData) {
|
||||
return unserialize($objectData);
|
||||
}
|
||||
}
|
||||
|
||||
$results = $this->db->select('pp_settings', '*');
|
||||
$settings = [];
|
||||
|
||||
if (is_array($results)) {
|
||||
foreach ($results as $row) {
|
||||
$settings[$row['param']] = $row['value'];
|
||||
}
|
||||
}
|
||||
|
||||
$cacheHandler->set($cacheKey, $settings);
|
||||
|
||||
return $settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pobranie pojedynczej wartosci ustawienia po nazwie parametru.
|
||||
*/
|
||||
public function getSingleValue(string $param): string
|
||||
{
|
||||
$cacheHandler = new \CacheHandler();
|
||||
$cacheKey = "Domain\Settings\SettingsRepository::getSingleValue:$param";
|
||||
|
||||
$objectData = $cacheHandler->get($cacheKey);
|
||||
if ($objectData) {
|
||||
return unserialize($objectData);
|
||||
}
|
||||
|
||||
$value = $this->db->get('pp_settings', 'value', ['param' => $param]);
|
||||
$value = (string)($value ?? '');
|
||||
|
||||
$cacheHandler->set($cacheKey, $value);
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
private function isEnabled($value): bool
|
||||
{
|
||||
if (is_bool($value)) {
|
||||
|
||||
@@ -1,78 +1,29 @@
|
||||
<?php
|
||||
namespace front\factory;
|
||||
|
||||
/**
|
||||
* Fasada delegujaca do Domain\Languages\LanguagesRepository.
|
||||
*/
|
||||
class Languages
|
||||
{
|
||||
public static function default_language()
|
||||
{
|
||||
global $mdb;
|
||||
|
||||
$cacheHandler = new \CacheHandler();
|
||||
$cacheKey = "\front\factory\Languages::default_language";
|
||||
|
||||
$objectData = $cacheHandler->get($cacheKey);
|
||||
|
||||
if ( !$objectData )
|
||||
public static function default_language()
|
||||
{
|
||||
$results = $mdb -> query( 'SELECT id FROM pp_langs WHERE status = 1 ORDER BY start DESC, o ASC LIMIT 1' ) -> fetchAll();
|
||||
$default_language = $results[0][0];
|
||||
|
||||
$cacheHandler -> set( $cacheKey, $default_language );
|
||||
}
|
||||
else
|
||||
{
|
||||
return unserialize($objectData);
|
||||
}
|
||||
return $default_language;
|
||||
}
|
||||
|
||||
public static function active_languages()
|
||||
{
|
||||
global $mdb;
|
||||
|
||||
$cacheHandler = new \CacheHandler();
|
||||
$cacheKey = "\front\factory\Languages::active_languages";
|
||||
|
||||
$objectData = $cacheHandler -> get( $cacheKey );
|
||||
|
||||
if ( !$objectData )
|
||||
{
|
||||
$active_languages = $mdb -> select( 'pp_langs', [ 'id', 'name' ], [ 'status' => 1, 'ORDER' => [ 'o' => 'ASC' ] ] );
|
||||
|
||||
$cacheHandler -> set( $cacheKey, $active_languages );
|
||||
}
|
||||
else
|
||||
{
|
||||
return unserialize( $objectData );
|
||||
global $mdb;
|
||||
$repo = new \Domain\Languages\LanguagesRepository($mdb);
|
||||
return $repo->defaultLanguage();
|
||||
}
|
||||
|
||||
return $active_languages;
|
||||
}
|
||||
|
||||
public static function lang_translations( $language = 'pl' )
|
||||
{
|
||||
global $mdb;
|
||||
|
||||
$cacheHandler = new \CacheHandler();
|
||||
$cacheKey = "\front\factory\Languages::lang_translations:$language";
|
||||
|
||||
$objectData = $cacheHandler -> get( $cacheKey );
|
||||
|
||||
if ( !$objectData )
|
||||
public static function active_languages()
|
||||
{
|
||||
$translations[ '0' ] = $language;
|
||||
|
||||
$results = $mdb -> select( 'pp_langs_translations', [ 'text', $language ] );
|
||||
if ( is_array( $results ) ) foreach ( $results as $row )
|
||||
$translations[ $row['text'] ] = $row[ $language ];
|
||||
|
||||
$cacheHandler -> set( $cacheKey, $translations );
|
||||
}
|
||||
else
|
||||
{
|
||||
return unserialize( $objectData );
|
||||
global $mdb;
|
||||
$repo = new \Domain\Languages\LanguagesRepository($mdb);
|
||||
return $repo->activeLanguages();
|
||||
}
|
||||
|
||||
return $translations;
|
||||
}
|
||||
public static function lang_translations($language = 'pl')
|
||||
{
|
||||
global $mdb;
|
||||
$repo = new \Domain\Languages\LanguagesRepository($mdb);
|
||||
return $repo->translations($language);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,43 +1,22 @@
|
||||
<?php
|
||||
namespace front\factory;
|
||||
|
||||
/**
|
||||
* Fasada delegujaca do Domain\Settings\SettingsRepository.
|
||||
*/
|
||||
class Settings
|
||||
{
|
||||
public static function settings_details( $admin = false )
|
||||
{
|
||||
global $mdb;
|
||||
|
||||
$cacheHandler = new \CacheHandler();
|
||||
$cacheKey = "\front\factory\Settings::settings_details";
|
||||
|
||||
$objectData = $cacheHandler->get($cacheKey);
|
||||
|
||||
if ( !$objectData or $admin )
|
||||
public static function settings_details($admin = false)
|
||||
{
|
||||
$results = $mdb -> select( 'pp_settings', '*' );
|
||||
if ( is_array( $results ) ) foreach ( $results as $row )
|
||||
$settings[ $row['param'] ] = $row['value'];
|
||||
|
||||
$cacheHandler -> set( $cacheKey, $settings );
|
||||
global $mdb;
|
||||
$repo = new \Domain\Settings\SettingsRepository($mdb);
|
||||
return $repo->allSettings($admin);
|
||||
}
|
||||
else
|
||||
|
||||
public static function get_single_settings_value($param)
|
||||
{
|
||||
return unserialize( $objectData );
|
||||
global $mdb;
|
||||
$repo = new \Domain\Settings\SettingsRepository($mdb);
|
||||
return $repo->getSingleValue($param);
|
||||
}
|
||||
|
||||
return $settings;
|
||||
}
|
||||
|
||||
static public function get_single_settings_value( $param ) {
|
||||
|
||||
global $mdb;
|
||||
|
||||
if ( !$value = \Cache::fetch( "get_single_settings_value:$param" ) ) {
|
||||
|
||||
$value = $mdb -> get( 'pp_settings', 'value', [ 'param' => 'firm_name' ] );
|
||||
\Cache::store( "get_single_settings_value:$param", $value );
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,21 @@ Logi zmian z migracji na Domain-Driven Architecture. Najnowsze na gorze.
|
||||
|
||||
---
|
||||
|
||||
## 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
|
||||
|
||||
@@ -153,26 +153,27 @@ Legacy Cleanup
|
||||
|
||||
---
|
||||
|
||||
## Plan wersjonowany
|
||||
## Etapy migracji
|
||||
|
||||
### ver. 0.278 — Settings + Languages Frontend Services
|
||||
### Etap: Settings + Languages — ZREALIZOWANY
|
||||
|
||||
**Cel:** Stworzyć serwisy domenowe dla Settings i Languages, naprawić buga Settings.
|
||||
**Cel:** Dodac metody frontendowe (z cache Redis) do istniejacych repozytoriow Domain.
|
||||
|
||||
**NOWE:**
|
||||
- `Domain/Settings/SettingsFrontendService.php` — `allSettings()`, `getSingleValue($param)` (FIX: używa poprawnie $param)
|
||||
- `Domain/Languages/LanguagesFrontendService.php` — `defaultLanguage()`, `activeLanguages()`, `translations($lang)`
|
||||
- Testy: `SettingsFrontendServiceTest`, `LanguagesFrontendServiceTest`
|
||||
**DODANE METODY (do istniejacych klas):**
|
||||
- `Domain/Settings/SettingsRepository` — `allSettings($skipCache)`, `getSingleValue($param)` (FIX: uzywa poprawnie $param)
|
||||
- `Domain/Languages/LanguagesRepository` — `defaultLanguage()`, `activeLanguages()`, `translations($lang)`
|
||||
- Testy: dopisane do `SettingsRepositoryTest` (6 testow), `LanguagesRepositoryTest` (7 testow)
|
||||
|
||||
**ZMIANA:**
|
||||
- `front/factory/Settings` → fasada delegująca do `SettingsFrontendService`
|
||||
- `front/factory/Languages` → fasada delegująca do `LanguagesFrontendService`
|
||||
- `front/factory/Settings` → fasada delegujaca do `SettingsRepository`
|
||||
- `front/factory/Languages` → fasada delegujaca do `LanguagesRepository`
|
||||
- `tests/bootstrap.php` — uzupelniony stub CacheHandler o `get()`/`set()`/`exists()`
|
||||
|
||||
**BUG FIX:** `get_single_settings_value()` — zmiana `['param' => 'firm_name']` na `['param' => $param]`
|
||||
|
||||
---
|
||||
|
||||
### ver. 0.279 — Category Frontend Service
|
||||
### Etap: Category Frontend Service
|
||||
|
||||
**Cel:** Migracja `front\factory\ShopCategory` do Domain.
|
||||
|
||||
@@ -186,7 +187,7 @@ Legacy Cleanup
|
||||
|
||||
---
|
||||
|
||||
### ver. 0.280 — Banners, Menu, Pages, Articles, Layouts Frontend Services
|
||||
### Etap: Banners, Menu, Pages, Articles, Layouts Frontend Services
|
||||
|
||||
**Cel:** Migracja pozostałych fabryk "liściowych".
|
||||
|
||||
@@ -205,7 +206,7 @@ Legacy Cleanup
|
||||
|
||||
---
|
||||
|
||||
### ver. 0.281 — Promotion Engine (rozbicie circular dependency)
|
||||
### Etap: Promotion Engine (rozbicie circular dependency)
|
||||
|
||||
**Cel:** Przeniesienie silnika promocji do Domain. Rozbicie cyklicznej zależności `shop\Promotion ↔ front\factory\ShopPromotion`.
|
||||
|
||||
@@ -231,7 +232,7 @@ front\factory\ShopPromotion::promotion_type_XX() → shop\Product::is_product_on
|
||||
|
||||
---
|
||||
|
||||
### ver. 0.282 — Product Frontend Service
|
||||
### Etap: Product Frontend Service
|
||||
|
||||
**Cel:** Migracja `front\factory\ShopProduct` i statycznych metod `shop\Product` do Domain.
|
||||
|
||||
@@ -245,11 +246,11 @@ front\factory\ShopPromotion::promotion_type_XX() → shop\Product::is_product_on
|
||||
- `front/factory/ShopProduct` → fasada
|
||||
- `shop/Product` statyczne metody → fasady do `ProductFrontendService`
|
||||
|
||||
**UWAGA:** Konstruktor `shop\Product`, `getFromCache()`, `calculate_basket_product_price()` — zostają na razie (instancyjne, używane w szablonach). Migracja w ver. 0.286.
|
||||
**UWAGA:** Konstruktor `shop\Product`, `getFromCache()`, `calculate_basket_product_price()` — zostają na razie (instancyjne, używane w szablonach). Migracja w etapie "Product Instance + Cache".
|
||||
|
||||
---
|
||||
|
||||
### ver. 0.283 — Client Authentication (Security Fix)
|
||||
### Etap: Client Authentication (Security Fix)
|
||||
|
||||
**Cel:** Migracja `front\factory\ShopClient` + NAPRAWIENIE hardcoded password bypass.
|
||||
|
||||
@@ -267,7 +268,7 @@ front\factory\ShopPromotion::promotion_type_XX() → shop\Product::is_product_on
|
||||
|
||||
---
|
||||
|
||||
### ver. 0.284 — Transport, Payment, Coupon Frontend Services
|
||||
### Etap: Transport, Payment, Coupon Frontend Services
|
||||
|
||||
**Cel:** Frontend serwisy dla transportu, płatności i kuponów.
|
||||
|
||||
@@ -285,7 +286,7 @@ front\factory\ShopPromotion::promotion_type_XX() → shop\Product::is_product_on
|
||||
|
||||
---
|
||||
|
||||
### ver. 0.285 — Basket Service
|
||||
### Etap: Basket Service
|
||||
|
||||
**Cel:** Migracja logiki koszyka do `Domain\Basket\BasketService`.
|
||||
|
||||
@@ -305,7 +306,7 @@ front\factory\ShopPromotion::promotion_type_XX() → shop\Product::is_product_on
|
||||
|
||||
---
|
||||
|
||||
### ver. 0.286 — shop\Product Instance + Cache
|
||||
### Etap: shop\Product Instance + Cache
|
||||
|
||||
**Cel:** Refaktoring konstruktora `shop\Product` i `getFromCache()`.
|
||||
|
||||
@@ -321,7 +322,7 @@ front\factory\ShopPromotion::promotion_type_XX() → shop\Product::is_product_on
|
||||
|
||||
---
|
||||
|
||||
### ver. 0.287 — Order Creation Frontend Service
|
||||
### Etap: Order Creation Frontend Service
|
||||
|
||||
**Cel:** Migracja `front\factory\ShopOrder::basket_save()` (~180 linii).
|
||||
|
||||
@@ -337,7 +338,7 @@ front\factory\ShopPromotion::promotion_type_XX() → shop\Product::is_product_on
|
||||
|
||||
---
|
||||
|
||||
### ver. 0.288 — Payment Webhook Service
|
||||
### Etap: Payment Webhook Service
|
||||
|
||||
**Cel:** Wyodrębnienie webhooków płatności z `front\controls\ShopOrder`.
|
||||
|
||||
@@ -356,7 +357,7 @@ front\factory\ShopPromotion::promotion_type_XX() → shop\Product::is_product_on
|
||||
|
||||
---
|
||||
|
||||
### ver. 0.289 — shop\Order Instance + Apilo Service
|
||||
### Etap: shop\Order Instance + Apilo Service
|
||||
|
||||
**Cel:** Refaktoring `shop\Order` instancyjnych metod + wyodrębnienie integracji Apilo.
|
||||
|
||||
@@ -374,7 +375,7 @@ front\factory\ShopPromotion::promotion_type_XX() → shop\Product::is_product_on
|
||||
|
||||
---
|
||||
|
||||
### ver. 0.290 — Frontend App + Controllers (DI layer)
|
||||
### Etap: Frontend App + Controllers (DI layer)
|
||||
|
||||
**Cel:** Stworzenie `front\App` (wzorowanego na `admin\App`) z mapą kontrolerów i DI.
|
||||
|
||||
@@ -390,7 +391,7 @@ front\factory\ShopPromotion::promotion_type_XX() → shop\Product::is_product_on
|
||||
|
||||
---
|
||||
|
||||
### ver. 0.291 — Site Layout Engine
|
||||
### Etap: Site Layout Engine
|
||||
|
||||
**Cel:** Refaktoring `front\view\Site::show()` (~600 linii) na testowalny `LayoutEngine`.
|
||||
|
||||
@@ -406,7 +407,7 @@ front\factory\ShopPromotion::promotion_type_XX() → shop\Product::is_product_on
|
||||
|
||||
---
|
||||
|
||||
### ver. 0.292 — Entry Point Unification
|
||||
### Etap: Entry Point Unification
|
||||
|
||||
**Cel:** Ujednolicenie bootstrapu `index.php` i `ajax.php`.
|
||||
|
||||
@@ -420,7 +421,7 @@ front\factory\ShopPromotion::promotion_type_XX() → shop\Product::is_product_on
|
||||
|
||||
---
|
||||
|
||||
### ver. 0.293 — Legacy Cleanup
|
||||
### Etap: Legacy Cleanup
|
||||
|
||||
**Cel:** Finalne porządki.
|
||||
|
||||
@@ -440,26 +441,26 @@ front\factory\ShopPromotion::promotion_type_XX() → shop\Product::is_product_on
|
||||
|
||||
## Podsumowanie
|
||||
|
||||
| Wersja | Zakres | Priorytet | Nowe klasy Domain | Testy |
|
||||
|--------|--------|-----------|-------------------|-------|
|
||||
| 0.278 | Settings + Languages | FUNDAMENT | 2 serwisy | 2 |
|
||||
| 0.279 | Category Frontend | WYSOKI | 1 serwis | 1 |
|
||||
| 0.280 | Banners/Menu/Pages/Articles/Layouts | ŚREDNI | 5 serwisów | 5 |
|
||||
| 0.281 | Promotion Engine | KRYTYCZNY | 1 serwis | 1 |
|
||||
| 0.282 | Product Frontend | KRYTYCZNY | 1 serwis | 1 |
|
||||
| 0.283 | Client/Auth (security fix) | KRYTYCZNY | 1 serwis | 1 |
|
||||
| 0.284 | Transport/Payment/Coupon | WYSOKI | 3 serwisy | 3 |
|
||||
| 0.285 | Basket Service | WYSOKI | 1 serwis | 1 |
|
||||
| 0.286 | Product Instance + Cache | ŚREDNI | 1 loader | 1 |
|
||||
| 0.287 | Order Creation | WYSOKI | 1 serwis | 1 |
|
||||
| 0.288 | Payment Webhooks | WYSOKI | 1 serwis | 1 |
|
||||
| 0.289 | Order Instance + Apilo | ŚREDNI | 2 serwisy | 2 |
|
||||
| 0.290 | Frontend App + Controllers | WYSOKI | App + 3 kontrolery | 3 |
|
||||
| 0.291 | Layout Engine | ŚREDNI | 1 engine | 1 |
|
||||
| 0.292 | Entry Point Unification | ŚREDNI | Bootstrap + PostProcessor | 1 |
|
||||
| 0.293 | Legacy Cleanup | NISKI | — | — |
|
||||
| Etap | Zakres | Priorytet | Nowe klasy Domain | Testy |
|
||||
|------|--------|-----------|-------------------|-------|
|
||||
| Settings + Languages | Fundamenty | FUNDAMENT | 2 serwisy | 2 |
|
||||
| Category Frontend | Kategorie | WYSOKI | 1 serwis | 1 |
|
||||
| Banners/Menu/Pages/Articles/Layouts | Treści | ŚREDNI | 5 serwisów | 5 |
|
||||
| Promotion Engine | Promocje | KRYTYCZNY | 1 serwis | 1 |
|
||||
| Product Frontend | Produkty | KRYTYCZNY | 1 serwis | 1 |
|
||||
| Client/Auth (security fix) | Klienci | KRYTYCZNY | 1 serwis | 1 |
|
||||
| Transport/Payment/Coupon | Dostawa/Płatności | WYSOKI | 3 serwisy | 3 |
|
||||
| Basket Service | Koszyk | WYSOKI | 1 serwis | 1 |
|
||||
| Product Instance + Cache | Produkt cache | ŚREDNI | 1 loader | 1 |
|
||||
| Order Creation | Zamówienia | WYSOKI | 1 serwis | 1 |
|
||||
| Payment Webhooks | Webhooki | WYSOKI | 1 serwis | 1 |
|
||||
| Order Instance + Apilo | Zamówienie + Apilo | ŚREDNI | 2 serwisy | 2 |
|
||||
| Frontend App + Controllers | DI layer | WYSOKI | App + 3 kontrolery | 3 |
|
||||
| Layout Engine | Silnik layoutu | ŚREDNI | 1 engine | 1 |
|
||||
| Entry Point Unification | Entry points | ŚREDNI | Bootstrap + PostProcessor | 1 |
|
||||
| Legacy Cleanup | Porządki | NISKI | — | — |
|
||||
|
||||
**Łącznie:** 16 wersji, ~24 nowe klasy Domain, ~25 plików testowych
|
||||
**Łącznie:** 16 etapów, ~24 nowe klasy Domain, ~25 plików testowych
|
||||
|
||||
### Wzorce do przestrzegania (z migracji admin)
|
||||
- Konstruktor DI z `$db` (medoo)
|
||||
@@ -468,8 +469,9 @@ front\factory\ShopPromotion::promotion_type_XX() → shop\Product::is_product_on
|
||||
- Testy PHPUnit z mockami medoo
|
||||
- Namespace `\Domain\*` → `autoload/Domain/*/`
|
||||
- Namespace `\front\Controllers\` → `autoload/front/Controllers/`
|
||||
- **Klasy Domain sa wspolne dla admin i frontendu** — NIE tworzymy osobnych FrontendService/AdminService. Metody frontendowe (z cache Redis) dodajemy do istniejacych repozytoriow/serwisow Domain. Klasy sa ladowane lazy (instancja tworzona dopiero przy wywolaniu), wiec nie wplywaja na wydajnosc.
|
||||
|
||||
### Weryfikacja po każdej wersji
|
||||
### Weryfikacja po każdym etapie
|
||||
1. `composer test` (pełny suite PHPUnit)
|
||||
2. Manualne sprawdzenie frontendu: strona główna, kategoria, produkt, koszyk, zamówienie
|
||||
3. Sprawdzenie AJAX: dodawanie do koszyka, zmiana transportu, kupon
|
||||
|
||||
@@ -36,7 +36,14 @@ Alternatywnie (Git Bash):
|
||||
Ostatnio zweryfikowano: 2026-02-16
|
||||
|
||||
```text
|
||||
OK (414 tests, 1335 assertions)
|
||||
OK (427 tests, 1378 assertions)
|
||||
```
|
||||
|
||||
Aktualizacja po migracji Settings + Languages frontend (2026-02-16, ver. 0.278):
|
||||
```text
|
||||
Pelny suite: OK (427 tests, 1378 assertions)
|
||||
Nowe testy: SettingsRepositoryTest (+6: allSettings, getSingleValue, bugfix param), LanguagesRepositoryTest (+7: defaultLanguage, activeLanguages, translations)
|
||||
Zaktualizowane: tests/bootstrap.php (stub CacheHandler: get/set/exists)
|
||||
```
|
||||
|
||||
Aktualizacja po migracji Dashboard + Update + legacy cleanup (2026-02-16, ver. 0.277):
|
||||
|
||||
@@ -18,20 +18,19 @@ Aktualizacje znajdują się w folderze `updates/0.XX/` gdzie XX oznacza dziesią
|
||||
|
||||
## Procedura tworzenia nowej aktualizacji
|
||||
|
||||
## Status biezacej aktualizacji (ver. 0.277)
|
||||
## Status biezacej aktualizacji (ver. 0.278)
|
||||
|
||||
- Wersja udostepniona: `0.277` (data: 2026-02-16).
|
||||
- Wersja udostepniona: `0.278` (data: 2026-02-16).
|
||||
- Pliki publikacyjne:
|
||||
- `updates/0.20/ver_0.277.zip`
|
||||
- `updates/0.20/ver_0.277_files.txt`
|
||||
- `updates/0.20/ver_0.278.zip`
|
||||
- Pliki metadanych aktualizacji:
|
||||
- `updates/changelog.php` (dodany wpis `ver. 0.277`)
|
||||
- `updates/versions.php` (`$current_ver = 277`)
|
||||
- `updates/changelog.php` (dodany wpis `ver. 0.278`)
|
||||
- `updates/versions.php` (`$current_ver = 278`)
|
||||
- Weryfikacja testow przed publikacja:
|
||||
- `OK (414 tests, 1335 assertions)`
|
||||
- `OK (427 tests, 1378 assertions)`
|
||||
|
||||
### 1. Określ numer wersji
|
||||
Sprawdź ostatnią wersję w `temp/` i zwiększ o 1.
|
||||
Sprawdź ostatnią wersję w `updates/` i zwiększ o 1.
|
||||
|
||||
### 2. Utwórz folder tymczasowy ze strukturą w katalogu temp
|
||||
```bash
|
||||
|
||||
@@ -145,4 +145,140 @@ class LanguagesRepositoryTest extends TestCase
|
||||
$this->assertSame('en', $repository->defaultLanguageId());
|
||||
$this->assertSame('pl', $repository->defaultLanguageId());
|
||||
}
|
||||
|
||||
// --- Metody frontendowe (z cache Redis) ---
|
||||
|
||||
public function testDefaultLanguageReturnsId(): void
|
||||
{
|
||||
$mockDb = $this->createMock(\medoo::class);
|
||||
|
||||
$mockStmt = $this->createMock(\PDOStatement::class);
|
||||
$mockStmt->expects($this->once())
|
||||
->method('fetchAll')
|
||||
->willReturn([['pl']]);
|
||||
|
||||
$mockDb->expects($this->once())
|
||||
->method('query')
|
||||
->with('SELECT id FROM pp_langs WHERE status = 1 ORDER BY start DESC, o ASC LIMIT 1')
|
||||
->willReturn($mockStmt);
|
||||
|
||||
$repository = new LanguagesRepository($mockDb);
|
||||
$langId = $repository->defaultLanguage();
|
||||
|
||||
$this->assertEquals('pl', $langId);
|
||||
}
|
||||
|
||||
public function testDefaultLanguageReturnsFallbackWhenEmpty(): void
|
||||
{
|
||||
$mockDb = $this->createMock(\medoo::class);
|
||||
|
||||
$mockStmt = $this->createMock(\PDOStatement::class);
|
||||
$mockStmt->expects($this->once())
|
||||
->method('fetchAll')
|
||||
->willReturn([]);
|
||||
|
||||
$mockDb->expects($this->once())
|
||||
->method('query')
|
||||
->willReturn($mockStmt);
|
||||
|
||||
$repository = new LanguagesRepository($mockDb);
|
||||
$langId = $repository->defaultLanguage();
|
||||
|
||||
$this->assertEquals('pl', $langId);
|
||||
}
|
||||
|
||||
public function testActiveLanguagesReturnsList(): void
|
||||
{
|
||||
$mockDb = $this->createMock(\medoo::class);
|
||||
|
||||
$mockDb->expects($this->once())
|
||||
->method('select')
|
||||
->with(
|
||||
'pp_langs',
|
||||
['id', 'name'],
|
||||
['status' => 1, 'ORDER' => ['o' => 'ASC']]
|
||||
)
|
||||
->willReturn([
|
||||
['id' => 'pl', 'name' => 'Polski'],
|
||||
['id' => 'en', 'name' => 'English'],
|
||||
]);
|
||||
|
||||
$repository = new LanguagesRepository($mockDb);
|
||||
$languages = $repository->activeLanguages();
|
||||
|
||||
$this->assertIsArray($languages);
|
||||
$this->assertCount(2, $languages);
|
||||
$this->assertEquals('pl', $languages[0]['id']);
|
||||
$this->assertEquals('English', $languages[1]['name']);
|
||||
}
|
||||
|
||||
public function testActiveLanguagesReturnsEmptyArrayWhenNone(): void
|
||||
{
|
||||
$mockDb = $this->createMock(\medoo::class);
|
||||
|
||||
$mockDb->expects($this->once())
|
||||
->method('select')
|
||||
->willReturn(null);
|
||||
|
||||
$repository = new LanguagesRepository($mockDb);
|
||||
$languages = $repository->activeLanguages();
|
||||
|
||||
$this->assertIsArray($languages);
|
||||
$this->assertEmpty($languages);
|
||||
}
|
||||
|
||||
public function testTranslationsReturnsArray(): void
|
||||
{
|
||||
$mockDb = $this->createMock(\medoo::class);
|
||||
|
||||
$mockDb->expects($this->once())
|
||||
->method('select')
|
||||
->with('pp_langs_translations', ['text', 'pl'])
|
||||
->willReturn([
|
||||
['text' => 'basket', 'pl' => 'Koszyk'],
|
||||
['text' => 'order', 'pl' => 'Zamowienie'],
|
||||
]);
|
||||
|
||||
$repository = new LanguagesRepository($mockDb);
|
||||
$translations = $repository->translations('pl');
|
||||
|
||||
$this->assertIsArray($translations);
|
||||
$this->assertEquals('pl', $translations['0']);
|
||||
$this->assertEquals('Koszyk', $translations['basket']);
|
||||
$this->assertEquals('Zamowienie', $translations['order']);
|
||||
}
|
||||
|
||||
public function testTranslationsDefaultsToPl(): void
|
||||
{
|
||||
$mockDb = $this->createMock(\medoo::class);
|
||||
|
||||
$mockDb->expects($this->once())
|
||||
->method('select')
|
||||
->with('pp_langs_translations', ['text', 'pl'])
|
||||
->willReturn([]);
|
||||
|
||||
$repository = new LanguagesRepository($mockDb);
|
||||
$translations = $repository->translations();
|
||||
|
||||
$this->assertIsArray($translations);
|
||||
$this->assertEquals('pl', $translations['0']);
|
||||
}
|
||||
|
||||
public function testTranslationsForDifferentLanguage(): void
|
||||
{
|
||||
$mockDb = $this->createMock(\medoo::class);
|
||||
|
||||
$mockDb->expects($this->once())
|
||||
->method('select')
|
||||
->with('pp_langs_translations', ['text', 'en'])
|
||||
->willReturn([
|
||||
['text' => 'basket', 'en' => 'Cart'],
|
||||
]);
|
||||
|
||||
$repository = new LanguagesRepository($mockDb);
|
||||
$translations = $repository->translations('en');
|
||||
|
||||
$this->assertEquals('en', $translations['0']);
|
||||
$this->assertEquals('Cart', $translations['basket']);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,15 +4,6 @@ namespace Tests\Unit\Domain\Settings;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Domain\Settings\SettingsRepository;
|
||||
|
||||
/**
|
||||
* Testy dla SettingsRepository
|
||||
*
|
||||
* UWAGA: SettingsRepository jest krokiem pośrednim migracji - deleguje do
|
||||
* statycznych metod admin\factory\Settings. Pełne testy jednostkowe z mockami
|
||||
* będą możliwe po migracji do DI (jak ProductRepository/BannerRepository).
|
||||
*
|
||||
* Na razie testujemy tylko to, co da się zweryfikować bez bazy danych.
|
||||
*/
|
||||
class SettingsRepositoryTest extends TestCase
|
||||
{
|
||||
public function testCanBeInstantiated(): void
|
||||
@@ -30,4 +21,105 @@ class SettingsRepositoryTest extends TestCase
|
||||
{
|
||||
$this->assertTrue(method_exists(SettingsRepository::class, 'getSettings'));
|
||||
}
|
||||
|
||||
public function testAllSettingsReturnsAssociativeArray(): void
|
||||
{
|
||||
$mockDb = $this->createMock(\medoo::class);
|
||||
|
||||
$mockDb->expects($this->once())
|
||||
->method('select')
|
||||
->with('pp_settings', '*')
|
||||
->willReturn([
|
||||
['param' => 'firm_name', 'value' => 'Test Shop'],
|
||||
['param' => 'contact_email', 'value' => 'test@example.com'],
|
||||
['param' => 'ssl', 'value' => '1'],
|
||||
]);
|
||||
|
||||
$service = new SettingsRepository($mockDb);
|
||||
$settings = $service->allSettings(true);
|
||||
|
||||
$this->assertIsArray($settings);
|
||||
$this->assertEquals('Test Shop', $settings['firm_name']);
|
||||
$this->assertEquals('test@example.com', $settings['contact_email']);
|
||||
$this->assertEquals('1', $settings['ssl']);
|
||||
$this->assertCount(3, $settings);
|
||||
}
|
||||
|
||||
public function testAllSettingsReturnsEmptyArrayWhenNoSettings(): void
|
||||
{
|
||||
$mockDb = $this->createMock(\medoo::class);
|
||||
|
||||
$mockDb->expects($this->once())
|
||||
->method('select')
|
||||
->with('pp_settings', '*')
|
||||
->willReturn([]);
|
||||
|
||||
$service = new SettingsRepository($mockDb);
|
||||
$settings = $service->allSettings(true);
|
||||
|
||||
$this->assertIsArray($settings);
|
||||
$this->assertEmpty($settings);
|
||||
}
|
||||
|
||||
public function testAllSettingsHandlesNullFromDb(): void
|
||||
{
|
||||
$mockDb = $this->createMock(\medoo::class);
|
||||
|
||||
$mockDb->expects($this->once())
|
||||
->method('select')
|
||||
->with('pp_settings', '*')
|
||||
->willReturn(null);
|
||||
|
||||
$service = new SettingsRepository($mockDb);
|
||||
$settings = $service->allSettings(true);
|
||||
|
||||
$this->assertIsArray($settings);
|
||||
$this->assertEmpty($settings);
|
||||
}
|
||||
|
||||
public function testGetSingleValueReturnsCorrectParam(): void
|
||||
{
|
||||
$mockDb = $this->createMock(\medoo::class);
|
||||
|
||||
$mockDb->expects($this->once())
|
||||
->method('get')
|
||||
->with('pp_settings', 'value', ['param' => 'contact_email'])
|
||||
->willReturn('test@example.com');
|
||||
|
||||
$service = new SettingsRepository($mockDb);
|
||||
$value = $service->getSingleValue('contact_email');
|
||||
|
||||
$this->assertEquals('test@example.com', $value);
|
||||
}
|
||||
|
||||
public function testGetSingleValueUsesParamNotHardcoded(): void
|
||||
{
|
||||
$mockDb = $this->createMock(\medoo::class);
|
||||
|
||||
// Kluczowy test: sprawdza ze param NIE jest hardcoded na 'firm_name'
|
||||
$mockDb->expects($this->once())
|
||||
->method('get')
|
||||
->with('pp_settings', 'value', ['param' => 'ssl'])
|
||||
->willReturn('1');
|
||||
|
||||
$service = new SettingsRepository($mockDb);
|
||||
$value = $service->getSingleValue('ssl');
|
||||
|
||||
$this->assertEquals('1', $value);
|
||||
}
|
||||
|
||||
public function testGetSingleValueReturnsEmptyStringWhenNotFound(): void
|
||||
{
|
||||
$mockDb = $this->createMock(\medoo::class);
|
||||
|
||||
$mockDb->expects($this->once())
|
||||
->method('get')
|
||||
->with('pp_settings', 'value', ['param' => 'nonexistent'])
|
||||
->willReturn(null);
|
||||
|
||||
$service = new SettingsRepository($mockDb);
|
||||
$value = $service->getSingleValue('nonexistent');
|
||||
|
||||
$this->assertEquals('', $value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,6 +78,9 @@ if (!class_exists('Redis')) {
|
||||
|
||||
if (!class_exists('CacheHandler')) {
|
||||
class CacheHandler {
|
||||
public function get($key) { return null; }
|
||||
public function set($key, $value, $ttl = 86400) {}
|
||||
public function exists($key) { return false; }
|
||||
public function delete($key) {}
|
||||
public function deletePattern($pattern) {}
|
||||
}
|
||||
|
||||
BIN
updates/0.20/ver_0.278.zip
Normal file
BIN
updates/0.20/ver_0.278.zip
Normal file
Binary file not shown.
@@ -1,3 +1,7 @@
|
||||
<b>ver. 0.278 - 16.02.2026</b><br />
|
||||
- UPDATE - migracja Settings + Languages do wspolnych klas Domain (z cache Redis)
|
||||
- FIX - `get_single_settings_value()` — parametr `$param` poprawnie uzywany (wczesniej hardcoded `firm_name`)
|
||||
<hr>
|
||||
<b>ver. 0.277 - 16.02.2026</b><br />
|
||||
- NEW - migracja modulu `ShopProduct` (factory) — pelna migracja ~40 metod do `ProductRepository` + ~30 akcji w `ShopProductController`
|
||||
- NEW - migracja modulu `Dashboard` do Domain + DI (`DashboardRepository`, `DashboardController`)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?
|
||||
$current_ver = 276;
|
||||
$current_ver = 278;
|
||||
|
||||
for ($i = 1; $i <= $current_ver; $i++)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user