Files
shopPRO/PROJECT_STRUCTURE.md

312 lines
12 KiB
Markdown

# Struktura Projektu shopPRO
Dokumentacja struktury projektu shopPRO do szybkiego odniesienia.
## System Cache (Redis)
### Klasy odpowiedzialne za cache
#### RedisConnection
- **Plik:** `autoload/class.RedisConnection.php`
- **Opis:** Singleton zarządzający połączeniem z Redis
- **Metody:**
- `getInstance()` - pobiera instancję połączenia
- `getConnection()` - zwraca obiekt Redis
#### CacheHandler
- **Plik:** `autoload/class.CacheHandler.php`
- **Opis:** Handler do obsługi cache Redis
- **Metody:**
- `get($key)` - pobiera wartość z cache
- `set($key, $value, $ttl = 86400)` - zapisuje wartość do cache
- `exists($key)` - sprawdza czy klucz istnieje
- `delete($key)` - usuwa pojedynczy klucz
- `deletePattern($pattern)` - usuwa klucze według wzorca
#### Klasa S (pomocnicza)
- **Plik:** `autoload/class.S.php`
- **Metody cache:**
- `clear_redis_cache()` - czyści cały cache Redis (flushAll)
- `clear_product_cache(int $product_id)` - czyści cache konkretnego produktu
### Wzorce kluczy Redis
#### Produkty
```
shop\product:{product_id}:{lang_id}:{permutation_hash}
```
- Przechowuje zserializowany obiekt produktu
- TTL: 24 godziny (86400 sekund)
- Klasa: `shop\Product::getFromCache()` - `autoload/shop/class.Product.php:121`
#### Opcje ilościowe produktu
```
\shop\Product::get_product_permutation_quantity_options:{product_id}:{permutation}
```
- Przechowuje informacje o ilości i komunikatach magazynowych
- Klasa: `shop\Product::get_product_permutation_quantity_options()` - `autoload/shop/class.Product.php:549`
#### Zestawy produktów
```
\shop\Product::product_sets_when_add_to_basket:{product_id}
```
- Przechowuje produkty często kupowane razem
- Klasa: `shop\Product::product_sets_when_add_to_basket()` - `autoload/shop/class.Product.php:316`
## Integracje z systemami zewnętrznymi (CRON)
### Plik: `cron.php`
#### Sellasist
- **Aktualizacja produktów:** Linia 111-149
- **Funkcje:** Aktualizacja cen i stanów magazynowych
- **Częstotliwość:** Co 10 minut
- **Czyszczenie cache:** Linia 146
#### Apilo
- **Aktualizacja pojedynczego produktu:** Linia 152-176
- Częstotliwość: Co 10 minut
- Czyszczenie cache: Linia 173
- **Synchronizacja cennika:** Linia 179-218
- Częstotliwość: Co 1 godzinę
- Czyszczenie cache: Linia 212
#### Baselinker
- **Aktualizacja produktów:** Linia 220-289
- **Funkcje:** Ceny, stany magazynowe, wagi
- **Częstotliwość:** Co 24 godziny (1440 minut)
- **Czyszczenie cache:** Linia 278
## Panel Administratora
### Routing
- Główny katalog: `admin/`
- Template główny: `admin/templates/site/main-layout.php`
- Kontrolery: `autoload/admin/controls/`
### Przycisk "Wyczyść cache"
- **Lokalizacja UI:** `admin/templates/site/main-layout.php:172`
- **JavaScript:** `admin/templates/site/main-layout.php:235-274`
- **Endpoint AJAX:** `/admin/settings/clear_cache_ajax/`
- **Kontroler:** `autoload/admin/controls/class.Settings.php:20-42`
- **Działanie:**
1. Pokazuje spinner "Czyszczę cache..."
2. Czyści katalogi: `temp/`, `thumbs/`
3. Wykonuje `flushAll()` na Redis
4. Pokazuje "Cache wyczyszczony!" przez 2 sekundy
5. Przywraca stan początkowy
## Struktura katalogów
```
shopPRO/
├── admin/ # Panel administratora
│ ├── templates/ # Szablony widoków
│ └── layout/ # Zasoby CSS/JS/ikony
├── autoload/ # Klasy autoloadowane
│ ├── admin/ # Klasy panelu admin
│ │ ├── controls/ # Kontrolery
│ │ └── factory/ # Fabryki/helpery
│ ├── front/ # Klasy frontendu
│ │ └── factory/ # Fabryki/helpery
│ └── shop/ # Klasy sklepu
├── libraries/ # Biblioteki zewnętrzne
├── temp/ # Cache tymczasowy
├── thumbs/ # Miniatury zdjęć
└── cron.php # Zadania CRON
```
## Baza danych
### Główne tabele produktów
- `pp_shop_products` - produkty główne
- `pp_shop_products_langs` - tłumaczenia produktów
- `pp_shop_products_images` - zdjęcia produktów
- `pp_shop_products_categories` - kategorie produktów
- `pp_shop_products_custom_fields` - pola własne produktów
### Tabele integracji
- Kolumny w `pp_shop_products`:
- `sellasist_product_id`, `sellasist_get_data_date`
- `apilo_product_id`, `apilo_get_data_date`
- `baselinker_product_id`, `baselinker_get_data_date`
## Konfiguracja
### Redis
- Konfiguracja: `config.php` (zmienna `$config['redis']`)
- Parametry: host, port, password
### Autoload
- Funkcja: `__autoload_my_classes()` w `cron.php:6`
- Wzorzec: `autoload/{namespace}/class.{ClassName}.php`
## Klasy pomocnicze
### \S (autoload/class.S.php)
Główna klasa helper z metodami:
- `seo($val)` - generowanie URL SEO
- `normalize_decimal($val, $precision)` - normalizacja liczb
- `send_email()` - wysyłanie emaili
- `delete_dir($dir)` - usuwanie katalogów
- `htacces()` - generowanie .htaccess i sitemap.xml
### Medoo
- Plik: `libraries/medoo/medoo.php`
- Zmienna: `$mdb`
- ORM do operacji na bazie danych
## Najważniejsze wzorce
### Namespace'y
- `\admin\controls\` - kontrolery panelu admin
- `\admin\factory\` - helpery/fabryki admin
- `\front\factory\` - helpery/fabryki frontend
- `\shop\` - klasy sklepu (Product, Order, itp.)
### Cachowanie produktów
```php
// Pobranie produktu z cache
$product = \shop\Product::getFromCache($product_id, $lang_id, $permutation_hash);
// Czyszczenie cache produktu
\S::clear_product_cache($product_id);
// Czyszczenie całego cache
\S::clear_redis_cache();
```
## Refaktoryzacja do Domain-Driven Architecture
### Nowa struktura (w trakcie migracji)
```
autoload/
├── Domain/ # Nowa warstwa biznesowa (namespace \Domain\)
│ ├── Product/
│ │ └── ProductRepository.php # getQuantity, getPrice, getName, find, updateQuantity, archive, unarchive
│ ├── Banner/
│ │ └── BannerRepository.php # find, delete, save
│ ├── Settings/
│ │ └── SettingsRepository.php # saveSettings, getSettings (fasada → factory)
│ └── Cache/
│ └── CacheRepository.php # clearCache (dirs + Redis)
├── admin/
│ ├── Controllers/ # Nowe kontrolery (namespace \admin\Controllers\)
│ │ ├── BannerController.php # DI, instancyjny
│ │ ├── SettingsController.php # DI, instancyjny (clearCache, save, view)
│ │ └── ProductArchiveController.php # DI, instancyjny (list, unarchive)
│ ├── class.Site.php # Router: nowy kontroler → fallback stary
│ ├── controls/ # Stare kontrolery (niezależny fallback)
│ ├── factory/ # Stare helpery (niezależny fallback)
│ └── view/ # Widoki (statyczne - bez zmian)
├── shop/ # Legacy - fasady do Domain
└── front/factory/ # Legacy - stopniowo migrowane
```
### Routing admin (admin\Site::route())
1. Sprawdź mapę `$newControllers` → utwórz instancję z DI → wywołaj
2. Jeśli nowy kontroler nie istnieje (`class_exists()` = false) → fallback na `admin\controls\`
3. Stary kontroler jest NIEZALEŻNY od nowych klas (bezpieczny fallback)
### Dependency Injection
Nowe klasy używają **Dependency Injection** zamiast `global` variables:
```php
// STARE
global $mdb;
$quantity = $mdb->get('pp_shop_products', 'quantity', ['id' => $id]);
// NOWE
$repository = new \Domain\Product\ProductRepository($mdb);
$quantity = $repository->getQuantity($id);
```
## Testowanie (tylko dla deweloperów)
**UWAGA:** Pliki testów NIE są częścią aktualizacji dla klientów!
### Narzędzia
- **PHPUnit 9.6.34** - framework testowy
- **test.bat** - uruchamianie testów
- **composer.json** - autoloading PSR-4
### Struktura
```
tests/
├── Unit/
│ ├── Domain/
│ │ ├── Product/ProductRepositoryTest.php # 11 testów
│ │ ├── Banner/BannerRepositoryTest.php # 4 testy
│ │ ├── Settings/SettingsRepositoryTest.php # 3 testy
│ │ └── Cache/CacheRepositoryTest.php # 4 testy
│ └── admin/
│ └── Controllers/
│ ├── SettingsControllerTest.php # 7 testów
│ └── ProductArchiveControllerTest.php # 6 testów
└── Integration/
```
**Łącznie: 50 tests, 95 assertions**
## Ostatnie modyfikacje
### 2026-02-06: Articles cleanup moved to repository (ver. 0.243)
- **UPDATE:** `Domain\Article\ArticleRepository` - added `deleteNonassignedImages()` and `deleteNonassignedFiles()`
- **UPDATE:** `admin\Controllers\ArticlesController::edit()` uses repository cleanup methods
- **UPDATE:** `admin\factory\Articles::delete_nonassigned_images()` and `delete_nonassigned_files()` delegate to repository (backward compatibility)
- Testy: 50 tests, 95 assertions
### 2026-02-06: Migracja Articles::article_edit do DI (ver. 0.242)
- **NOWE:** `Domain\Article\ArticleRepository` - repozytorium artykułów (`find()`)
- **UPDATE:** `admin\Controllers\ArticlesController` - konstruktor DI + `edit()` używa repozytorium
- **UPDATE:** Router `admin\Site` - factory dla `ArticlesController` z `ArticleRepository`
- **UPDATE:** `admin\factory\Articles::article_details()` deleguje do `Domain\Article\ArticleRepository`
- **UPDATE:** Stare kontrolery `admin\controls\Articles|Banners|Settings` - metody przejęte przez nowe kontrolery oznaczone `@deprecated`
- Testy: 48 testów, 91 asercji
### 2026-02-06: Migracja ProductArchive (ver. 0.241)
- **NOWE:** `admin\Controllers\ProductArchiveController` - kontroler archiwum produktów z DI
- **NOWE:** `ProductRepository::archive()`, `unarchive()` - operacje archiwizacji w repozytorium
- **RENAME:** `admin/templates/archive/``admin/templates/product_archive/`
- **FIX:** SQL w `ajax_products_list_archive()` - puste wyszukiwanie generowało `name|ean|sku LIKE '%%'` (NULL bitwise OR filtrował wyniki)
- **FIX:** Brakujący `archive = 1` w branchu bez wyszukiwania
- **CLEANUP:** Usunięto zbędny JS z szablonu archiwum (apilo, baselinker, duplikowanie, edycja cen)
- Stary kontroler `admin\controls\Archive` zachowany jako fallback
- Testy: 50 tests, 95 assertions (+10 nowych)
### 2026-02-05: Migracja Settings + Cache (ver. 0.240)
- **NOWE:** `Domain\Settings\SettingsRepository` - repozytorium ustawień (fasada → factory)
- **NOWE:** `Domain\Cache\CacheRepository` - repozytorium cache (dirs + Redis)
- **NOWE:** `admin\Controllers\SettingsController` - kontroler z DI (clearCache, save, view)
- **FIX:** Brakujący `id="content"` w main-layout.php (komunikaty grid.js)
- **FIX:** `persist_edit = true` w settings.php (komunikat po zapisie)
- Stary kontroler `admin\controls\Settings` zachowany jako fallback
- Testy: 29 testów, 60 asercji (+14 nowych)
- Bootstrap testów: stuby klas systemowych (S, RedisConnection, Redis, CacheHandler)
### 2026-02-05: Migracja Banner + Product (ver. 0.239)
- **NOWE:** `Domain\Banner\BannerRepository` - repozytorium banerów (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: 15 testów, 31 asercji
### 2025-02-05: Refaktoryzacja - Product Repository (ver. 0.238)
- **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
### 2025-02-05: System cache produktów (ver. 0.237)
- 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-06*