Phase 6 zamknięta po 2 planach. Pełny fundament dla Phase 7-13 (migracja 17 admin controllers do Admin\ namespace). 06-01 (Forms infrastructure): - Admin\ViewModels\Forms\* — 5 ViewModeli (687 L) - Admin\Validation\FormValidator (196 L) - composer.json: php >=7.4, PSR-4 paths cross-platform safe (Admin\ → autoload/admin/, Frontend\ → autoload/front/) 06-02 (Support layer): - Admin\Support\TableListRequestFactory (99 L) — parser list z $_GET - Admin\Support\Forms\FormRequestHandler (159 L) — POST + CSRF + walidacja + persist - Admin\Support\Forms\FormFieldRenderer (494 L) — renderer HTML pól Decyzje: - Brak BaseController — Phase 7+ kontrolery jako POJOs z DI (jak shopPRO) - PSR-4 filename fix: TableListRequestFactory.php (bez shopPRO 'class.' prefix) - PascalCase namespace (Admin\Support) na lowercase folder admin/ ze względu na Windows fs case-insensitivity vs legacy admin/controls/ Pliki: 8 nowych klas, 1635 L kodu PHP 7.4-kompatybilnego, zero regresji. Smoke test: walidacja e-maila zwraca PL komunikat, factory parsuje ?page=&per_page=&sort=&filter=, Domain/Shared nadal ładują się. PHPUnit: 37/37 OK. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
171 lines
6.9 KiB
Markdown
171 lines
6.9 KiB
Markdown
# Architecture
|
|
|
|
> Generated: 2026-04-26
|
|
|
|
## Overview
|
|
|
|
cmsPRO uses a **3-layer architecture** with clean admin/frontend separation:
|
|
|
|
```
|
|
Request
|
|
↓
|
|
Controls (admin\controls\ or front\controls\) ← request handling
|
|
↓
|
|
Factories (admin\factory\ or front\factory\) ← DEPRECATED wrappers → will be removed
|
|
↓
|
|
Domain Repositories (Domain\*\*Repository) ← data access (new pattern)
|
|
↓
|
|
Medoo ORM → MySQL
|
|
```
|
|
|
|
Views are rendered through `admin\view\*` / `front\view\*` → `Shared\Tpl\Tpl` → Savant3 templates.
|
|
|
|
## Directory Map
|
|
|
|
```
|
|
autoload/
|
|
├── autoloader.php Hybrid PSR-4 + legacy autoloader
|
|
├── class.S.php Global helper facade (deprecated wrapper)
|
|
├── class.Article.php Legacy entity (ArrayAccess)
|
|
├── class.Page.php Legacy entity
|
|
├── class.Scontainer.php Legacy entity
|
|
├── class.Cache.php / class.Cron.php / class.Image.php / class.Html.php
|
|
│
|
|
├── Domain/ NEW — Repository pattern, DDD
|
|
│ ├── Articles/ArticlesRepository.php (648 lines)
|
|
│ ├── Authors/AuthorsRepository.php (156 lines)
|
|
│ ├── Banners/BannersRepository.php (148 lines)
|
|
│ ├── Languages/LanguagesRepository.php (213 lines)
|
|
│ ├── Layouts/LayoutsRepository.php (123 lines)
|
|
│ ├── Newsletter/NewsletterRepository.php (281 lines)
|
|
│ ├── Pages/PagesRepository.php (451 lines)
|
|
│ ├── Scontainers/ScontainersRepository.php (110 lines)
|
|
│ ├── Settings/SettingsRepository.php (73 lines)
|
|
│ └── User/UserRepository.php (235 lines)
|
|
│
|
|
├── Shared/ Cross-cutting services
|
|
│ ├── Helpers/Helpers.php God class — 1220 lines (⚠ needs splitting)
|
|
│ ├── Tpl/Tpl.php Template renderer (checks templates_user/ first)
|
|
│ ├── Email/Email.php Email service (wraps PHPMailer)
|
|
│ ├── Cache/CacheHandler.php File-based cache (gzdeflate, TTL)
|
|
│ ├── Security/CsrfToken.php CSRF token generation + validation
|
|
│ ├── Html/Html.php HTML form element builder
|
|
│ └── Image/ImageManipulator.php Image processing
|
|
│
|
|
├── admin/ Mixed: legacy lowercase namespaces + new Admin\* PSR-4
|
|
│ │
|
|
│ │ NEW (Phase 6) — namespace Admin\* (PascalCase, PSR-4)
|
|
│ ├── ViewModels/Forms/ Admin\ViewModels\Forms\* — Form Edit System (5 VMs, 687 L)
|
|
│ ├── Validation/FormValidator.php
|
|
│ ├── Support/TableListRequestFactory.php Admin\Support — list parser
|
|
│ ├── Support/Forms/FormRequestHandler.php POST + CSRF + validate + persist
|
|
│ ├── Support/Forms/FormFieldRenderer.php HTML renderer (delegates Shared\Html\Html)
|
|
│ │
|
|
│ │ LEGACY — namespace admin\* (lowercase, hybrid loader)
|
|
│ ├── class.Site.php Admin routing + 2FA
|
|
│ ├── controls/class.*.php 18 request handler classes (static methods)
|
|
│ ├── factory/class.*.php 18 @deprecated wrappers
|
|
│ └── view/class.*.php 14 template renderer classes
|
|
│
|
|
└── front/
|
|
├── controls/class.Site.php Main frontend router
|
|
├── controls/class.*.php 4 frontend controllers
|
|
├── factory/class.*.php 17 frontend factories
|
|
└── view/class.*.php View renderers
|
|
|
|
admin/
|
|
├── index.php Admin entry point (IP check, session, routing)
|
|
├── ajax.php Admin AJAX dispatcher → admin/ajax/*.php
|
|
└── templates/ Admin Savant3 templates (per module)
|
|
|
|
templates/ Frontend Savant3 templates
|
|
templates_user/ User-overridable template overrides
|
|
plugins/
|
|
├── special-actions.php Hook: pre-routing
|
|
├── special-actions-middle.php Hook: mid-request
|
|
└── special-actions-end.php Hook: post-rendering
|
|
```
|
|
|
|
## Namespace Convention
|
|
|
|
| Namespace | Path | Convention |
|
|
|-----------|------|-----------|
|
|
| `admin\controls\` | `autoload/admin/controls/class.*.php` | Legacy lowercase |
|
|
| `admin\factory\` | `autoload/admin/factory/class.*.php` | Legacy, @deprecated |
|
|
| `admin\view\` | `autoload/admin/view/class.*.php` | Legacy lowercase |
|
|
| `front\controls\` | `autoload/front/controls/class.*.php` | Legacy lowercase |
|
|
| `front\factory\` | `autoload/front/factory/class.*.php` | Legacy lowercase |
|
|
| `Domain\*\` | `autoload/Domain/*/ClassName.php` | PSR-4 PascalCase |
|
|
| `Shared\*\` | `autoload/Shared/*/ClassName.php` | PSR-4 PascalCase |
|
|
| `Admin\*\` | `autoload/admin/*/ClassName.php` | PSR-4 PascalCase namespace, lowercase folder (Win fs collision with legacy) |
|
|
|
|
## Key Patterns
|
|
|
|
### Repository Pattern (Domain layer)
|
|
```php
|
|
class ArticlesRepository {
|
|
public function __construct($db) { $this->db = $db; }
|
|
public function find(int $id): ?array { ... }
|
|
public function save(...): int { ... }
|
|
}
|
|
```
|
|
|
|
### Factory Wrapper (deprecated bridge)
|
|
```php
|
|
/** @deprecated Używaj Domain\Articles\ArticlesRepository przez DI */
|
|
class Articles {
|
|
private static function repo(): ArticlesRepository {
|
|
global $mdb;
|
|
return new ArticlesRepository($mdb);
|
|
}
|
|
public static function article_delete($id): bool {
|
|
return self::repo()->deleteArticle($id);
|
|
}
|
|
}
|
|
```
|
|
|
|
### Controls (request handler)
|
|
```php
|
|
class Articles {
|
|
public static function article_delete() {
|
|
global $user;
|
|
if (!admin\factory\Users::check_privileges('articles', $user['id']))
|
|
return \S::alert('Brak uprawnień');
|
|
// delegate to factory → repository
|
|
}
|
|
}
|
|
```
|
|
|
|
### Global Helper Facade
|
|
```php
|
|
// class.S.php — calls Shared\Helpers\Helpers via __callStatic
|
|
\S::get('param') // → Helpers::get()
|
|
\S::delete_cache() // → Helpers::delete_cache()
|
|
```
|
|
|
|
## Admin Routing
|
|
|
|
`GET /admin/?a=articles&action=view_list` → `admin\controls\Articles::view_list()`
|
|
|
|
Routing in `admin/index.php`: reads `$_GET['a']` → dynamically loads control class → calls action method.
|
|
|
|
## Frontend Routing
|
|
|
|
`index.php` → `front\controls\Site::route()` — checks `\S::get('search')`, `\S::get('tag')`, `\S::get('article')`, then falls through to page rendering by `page_type`.
|
|
|
|
## Caching Strategy
|
|
|
|
| Cache Type | Location | Engine |
|
|
|-----------|----------|--------|
|
|
| Page cache | `cache/` | Full HTML output |
|
|
| Object cache | `temp/md5[0]/md5[1]/` | gzdeflate + serialize, TTL |
|
|
| WebP images | `cache/` | Filesystem |
|
|
| Language strings | `$_SESSION` | PHP session |
|
|
|
|
## Plugin System
|
|
|
|
3 hook points in frontend lifecycle (files in `plugins/` directory, included if they exist):
|
|
1. `special-actions.php` — after language init, before routing
|
|
2. `special-actions-middle.php` — before cache check
|
|
3. `special-actions-end.php` — before final output
|