236 lines
10 KiB
Markdown
236 lines
10 KiB
Markdown
# Architecture & Structure
|
|
|
|
## Directory Layout
|
|
|
|
```
|
|
shopPRO/
|
|
├── autoload/ # Core application code (custom autoloader)
|
|
│ ├── Domain/ # Business logic — 29 modules
|
|
│ ├── Shared/ # Cross-cutting utilities
|
|
│ │ ├── Cache/ # CacheHandler, RedisConnection
|
|
│ │ ├── Email/ # Email (PHPMailer wrapper)
|
|
│ │ ├── Helpers/ # Static utility methods
|
|
│ │ ├── Html/ # HTML escaping/generation
|
|
│ │ ├── Image/ # ImageManipulator
|
|
│ │ └── Tpl/ # Template engine
|
|
│ ├── admin/ # Admin panel layer
|
|
│ │ ├── App.php # Router & DI factory
|
|
│ │ ├── Controllers/ # 28 DI controllers
|
|
│ │ ├── Support/ # Forms, TableListRequestFactory
|
|
│ │ ├── Validation/ # FormValidator
|
|
│ │ └── ViewModels/ # Forms/, Common/
|
|
│ ├── front/ # Frontend layer
|
|
│ │ ├── App.php # Router & DI factory
|
|
│ │ ├── LayoutEngine.php # Placeholder-based layout engine
|
|
│ │ ├── Controllers/ # 8 DI controllers
|
|
│ │ └── Views/ # 11 static view classes
|
|
│ └── api/ # REST API layer
|
|
│ ├── ApiRouter.php # Auth + routing
|
|
│ └── Controllers/ # 4 DI controllers
|
|
├── admin/
|
|
│ ├── index.php # Admin entry point
|
|
│ ├── ajax.php # Admin AJAX handler
|
|
│ ├── templates/ # Admin view templates
|
|
│ └── layout/ # Admin CSS/JS/icons
|
|
├── templates/ # Frontend view templates
|
|
├── libraries/ # Third-party libraries
|
|
├── tests/ # PHPUnit test suite
|
|
├── docs/ # Technical documentation
|
|
├── index.php # Frontend entry point
|
|
├── ajax.php # Frontend AJAX handler
|
|
├── api.php # REST API entry point
|
|
├── cron.php # Background job processor
|
|
└── config.php # DB/Redis config (NOT in repo)
|
|
```
|
|
|
|
## Autoloader
|
|
|
|
Custom autoloader in each entry point — tries two conventions:
|
|
1. `autoload/{namespace}/class.{ClassName}.php` (legacy)
|
|
2. `autoload/{namespace}/{ClassName}.php` (PSR-4 style, preferred)
|
|
|
|
**Namespace → directory mapping (case-sensitive on Linux):**
|
|
- `\Domain\` → `autoload/Domain/`
|
|
- `\admin\` → `autoload/admin/` (**lowercase a** — never `\Admin\`)
|
|
- `\front\` → `autoload/front/`
|
|
- `\api\` → `autoload/api/`
|
|
- `\Shared\` → `autoload/Shared/`
|
|
|
|
## Dependency Injection
|
|
|
|
Manual factory pattern in router classes. Each entry point wires dependencies once:
|
|
|
|
```php
|
|
// Example from admin\App::getControllerFactories()
|
|
'ShopProduct' => function() {
|
|
global $mdb;
|
|
return new \admin\Controllers\ShopProductController(
|
|
new \Domain\Product\ProductRepository($mdb),
|
|
new \Domain\Integrations\IntegrationsRepository($mdb),
|
|
new \Domain\Languages\LanguagesRepository($mdb)
|
|
);
|
|
}
|
|
```
|
|
|
|
DI wiring locations:
|
|
- Admin: `autoload/admin/App.php` → `getControllerFactories()`
|
|
- Frontend: `autoload/front/App.php` → `getControllerFactories()`
|
|
- API: `autoload/api/ApiRouter.php` → `getControllerFactories()`
|
|
|
|
## Routing
|
|
|
|
### Admin (`\admin\App`)
|
|
- URL: `/admin/?module=shop_product&action=view_list`
|
|
- `module` → PascalCase (`shop_product` → `ShopProduct`) → controller lookup
|
|
- `action` → method call on controller
|
|
- Auth checked before routing; 2FA supported
|
|
|
|
### Frontend (`\front\App`)
|
|
- Routes stored in `pp_routes` table (regex patterns, cached in Redis as `pp_routes:all`)
|
|
- Match URI → extract destination params → merge with `$_GET`
|
|
- Special params: `?product=ID`, `?category=ID`, `?article=ID`
|
|
- Controller dispatch via `getControllerFactories()`
|
|
- Unmatched → static page content
|
|
|
|
### API (`\api\ApiRouter`)
|
|
- URL: `/api.php?endpoint=orders&action=getOrders`
|
|
- Stateless — auth via `X-Api-Key` header (`hash_equals()`)
|
|
- `endpoint` → controller, `action` → method
|
|
|
|
## Request Lifecycle (Frontend)
|
|
|
|
```
|
|
HTTP GET /produkt/nazwa-produktu
|
|
→ index.php (autoload, init Medoo, session, language)
|
|
→ Fetch pp_routes from Redis (or DB)
|
|
→ Regex match → extract ?product=123
|
|
→ front\LayoutEngine::show()
|
|
→ Determine layout (pp_layouts)
|
|
→ Replace placeholders [MENU:ID], [BANER_STRONA_GLOWNA], etc.
|
|
→ Call view classes / repositories for each placeholder
|
|
→ Output HTML (with GTM, meta OG, WebP, lazy loading)
|
|
```
|
|
|
|
## Request Lifecycle (Admin)
|
|
|
|
```
|
|
HTTP GET /admin/?module=shop_order&action=view_list
|
|
→ admin/index.php (IP check, session, auth cookie check)
|
|
→ admin\App::update() (run pending DB migrations)
|
|
→ admin\App::special_actions() (handle s-action=user-logon etc.)
|
|
→ admin\App::render()
|
|
→ Auth check → if not logged in, show login form
|
|
→ admin\App::route()
|
|
→ 'shop_order' → ShopOrder → factory()
|
|
→ new ShopOrderController(OrderAdminService, ProductRepository)
|
|
→ ShopOrderController::viewList()
|
|
→ Tpl::view('shop-order/orders-list', [...])
|
|
→ Tpl::render('site/main-layout', ['content' => $html])
|
|
→ Output admin HTML
|
|
```
|
|
|
|
## Domain Modules (29)
|
|
|
|
All in `autoload/Domain/{Module}/{Module}Repository.php`:
|
|
|
|
| Module | Repository | Notes |
|
|
|--------|-----------|-------|
|
|
| Article | ArticleRepository | Blog/news |
|
|
| Attribute | AttributeRepository | Product attributes (color, size) |
|
|
| Banner | BannerRepository | Promo banners |
|
|
| Basket | (static) | Cart calculations |
|
|
| Cache | (utilities) | Cache key constants |
|
|
| Category | CategoryRepository | Category tree |
|
|
| Client | ClientRepository | Customer accounts |
|
|
| Coupon | CouponRepository | Discount codes |
|
|
| CronJob | CronJobRepository, CronJobProcessor | Job queue |
|
|
| Dashboard | DashboardRepository | Admin stats |
|
|
| Dictionaries | DictionariesRepository | Units, enums |
|
|
| Integrations | IntegrationsRepository | Apilo, Ekomi (**875 lines — too large**) |
|
|
| Languages | LanguagesRepository | i18n translations |
|
|
| Layouts | LayoutsRepository | Page templates |
|
|
| Newsletter | NewsletterRepository, NewsletterPreviewRenderer | Email campaigns |
|
|
| Order | OrderRepository, OrderAdminService | Orders, status |
|
|
| Pages | PagesRepository | Static pages |
|
|
| PaymentMethod | PaymentMethodRepository | Payment gateways |
|
|
| Producer | ProducerRepository | Brands |
|
|
| Product | ProductRepository | Core catalog (**3583 lines — too large**) |
|
|
| ProductSet | ProductSetRepository | Bundles |
|
|
| Promotion | PromotionRepository | Special offers |
|
|
| Scontainers | ScontainersRepository | Content blocks |
|
|
| Settings | SettingsRepository | Shop config |
|
|
| ShopStatus | ShopStatusRepository | Order statuses |
|
|
| Transport | TransportRepository | Shipping |
|
|
| Update | UpdateRepository | DB migrations |
|
|
| User | UserRepository | Admin users, 2FA |
|
|
|
|
## Admin Controllers (28)
|
|
|
|
All in `autoload/admin/Controllers/`:
|
|
`ArticlesController`, `ArticlesArchiveController`, `BannerController`, `DashboardController`, `DictionariesController`, `FilemanagerController`, `IntegrationsController`, `LanguagesController`, `LayoutsController`, `NewsletterController`, `PagesController`, `ProductArchiveController`, `ScontainersController`, `SettingsController`, `ShopAttributeController`, `ShopCategoryController`, `ShopClientsController`, `ShopCouponController`, `ShopOrderController`, `ShopPaymentMethodController`, `ShopProducerController`, `ShopProductController` (1199 lines), `ShopProductSetsController`, `ShopPromotionController`, `ShopStatusesController`, `ShopTransportController`, `UpdateController`, `UsersController`
|
|
|
|
## Frontend Controllers (8)
|
|
|
|
`autoload/front/Controllers/`: `NewsletterController`, `SearchController`, `ShopBasketController`, `ShopClientController`, `ShopCouponController`, `ShopOrderController`, `ShopProducerController`, `ShopProductController`
|
|
|
|
## Frontend Views (11, static)
|
|
|
|
`autoload/front/Views/`: `Articles`, `Banners`, `Languages`, `Menu`, `Newsletter`, `Scontainers`, `ShopCategory`, `ShopClient`, `ShopPaymentMethod`, `ShopProduct`, `ShopSearch`
|
|
|
|
## API Controllers (4)
|
|
|
|
`autoload/api/Controllers/`: `OrdersApiController`, `ProductsApiController`, `CategoriesApiController`, `DictionariesApiController`
|
|
|
|
## Template System
|
|
|
|
### Tpl Engine (`\Shared\Tpl\Tpl`)
|
|
```php
|
|
// Controller
|
|
return \Shared\Tpl\Tpl::view('shop-category/category-edit', [
|
|
'category' => $data,
|
|
'languages' => $langs,
|
|
]);
|
|
|
|
// Template (templates/shop-category/category-edit.php)
|
|
<h1><?= $this->category['name'] ?></h1>
|
|
```
|
|
|
|
Search order: `templates_user/`, `templates/`, `../templates_user/`, `../templates/`
|
|
|
|
### Frontend Layout Engine (`\front\LayoutEngine`)
|
|
Replaces placeholders in layout HTML loaded from `pp_layouts.html`:
|
|
- `[MENU:ID]`, `[KONTENER:ID]`, `[LANG:key]`
|
|
- `[PROMOWANE_PRODUKTY:limit]`, `[PRODUKTY_TOP:limit]`, `[PRODUKTY_NEW:limit]`
|
|
- `[BANER_STRONA_GLOWNA]`, `[BANERY]`, `[COPYRIGHT]`
|
|
- `[AKTUALNOSCI:layout_id:limit]`, `[PRODUKTY_KATEGORIA:cat_id:limit]`
|
|
|
|
## Admin Form System
|
|
|
|
Universal form system for CRUD views. Full docs: `docs/FORM_EDIT_SYSTEM.md`.
|
|
|
|
| Component | Class | Location |
|
|
|-----------|-------|----------|
|
|
| View model | `FormEditViewModel` | `autoload/admin/ViewModels/Forms/` |
|
|
| Field definition | `FormField` | same |
|
|
| Field type enum | `FormFieldType` | same |
|
|
| Tab | `FormTab` | same |
|
|
| Action | `FormAction` | same |
|
|
| Validation | `FormValidator` | `autoload/admin/Validation/` |
|
|
| POST parsing | `FormRequestHandler` | `autoload/admin/Support/Forms/` |
|
|
| Rendering | `FormFieldRenderer` | `autoload/admin/Support/Forms/` |
|
|
| Template | `form-edit.php` | `admin/templates/components/` |
|
|
|
|
## Authentication
|
|
|
|
### Admin
|
|
- Session: `$_SESSION['user']` after successful login
|
|
- 2FA: 6-digit code sent by email; `twofa_pending` in session during verification
|
|
- Remember Me: 14-day HMAC-SHA256 signed cookie
|
|
|
|
### API
|
|
- Stateless; `X-Api-Key` header vs `pp_settings.api_key` via `hash_equals()`
|
|
|
|
### Frontend
|
|
- Customer session in `$_SESSION['client']`
|
|
- IP validation on every request (`$_SESSION['ip']` vs `REMOTE_ADDR`)
|