UPDATE
This commit is contained in:
235
.paul/codebase/architecture.md
Normal file
235
.paul/codebase/architecture.md
Normal file
@@ -0,0 +1,235 @@
|
||||
# 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`)
|
||||
Reference in New Issue
Block a user