Files
bilety.brzezovka.pl/.paul/codebase/architecture.md
Jacek Pyziak 5bbec72b59 docs: map existing codebase
- stack.md - Technologies and dependencies
- architecture.md - System design and patterns
- structure.md - Directory layout
- conventions.md - Code style and patterns
- testing.md - Test structure (none)
- integrations.md - External services
- concerns.md - Technical debt and issues
- db_schema.md - Database schema and relationships

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-26 22:15:02 +02:00

158 lines
6.3 KiB
Markdown

# Architecture
**Analysis Date:** 2026-04-26
## Pattern Overview
**Overall:** Custom PHP MVC (no framework)
**Key Characteristics:**
- URL-based routing via Apache mod_rewrite in `.htaccess`
- Namespace-organized layers (controls, factory, view)
- Custom autoloader mapping namespaces to file paths
- Session-based shopping cart (no cart persistence until order submit)
- Static public methods as controller actions
- Single config file (`config.php`) containing all settings and ticket definitions
## Layers
**Controller Layer (`autoload/controls/`):**
- Purpose: Handle HTTP actions, coordinate factory/template calls, return rendered HTML
- Contains: Route action methods (e.g., `main_view()`, `basket_view()`, `przelewy24_response()`)
- Depends on: Factory layer, `\Tpl`, `\S`, `\Html`, `global $settings, $mdb, $user`
- Used by: `\controls\Site::route()` dispatcher
**Factory/Service Layer (`autoload/factory/`):**
- Purpose: Business logic, database queries, data processing
- Contains: Calendar availability, order creation, user auth, settings management
- Depends on: `global $mdb` (Medoo), `\R::` (RedBeanPHP)
- Used by: Controllers
**View Layer (`autoload/view/`):**
- Purpose: Layout assembly — wraps controller output in site layout template
- Contains: `show()` dispatcher, layout selection logic
- Depends on: Controllers (via `\controls\Site::route()`), `\Tpl`
- Used by: Entry points (`index.php` calls `\view\Site::show()`)
**Template Layer (`templates/`):**
- Purpose: HTML rendering with embedded PHP
- Contains: Module-organized `.php` template files
- Variables accessed via `$this->key` (injected by `\Tpl`)
- Used by: Any layer via `\Tpl::view('path/name', ['key' => $value])`
**Core Utilities (`autoload/`):**
- `\S` — Session management, email, utilities (`autoload/class.S.php`)
- `\Tpl` — Template engine with variable injection (`autoload/class.Tpl.php`)
- `\Html` — Form component builder (`autoload/class.Html.php`)
- `\DbModel` — Simple active-record base class (`autoload/class.DbModel.php`)
## Data Flow
**HTTP Request Lifecycle:**
1. Browser requests `/tickets/basket_view/`
2. `.htaccess` rewrites to `index.php?module=tickets&action=basket_view`
3. `index.php` bootstraps: autoloader, config, Medoo, RedBeanPHP, PHPMailer, session security
4. `\view\Site::show()` called
5. `\controls\Site::route()` resolves module + action to `\controls\Tickets::basket_view()`
6. Controller method executes: reads session basket, calls factory methods, calls `\Tpl::view()`
7. Rendered HTML returned as string to `\view\Site::show()`
8. `show()` wraps content in `templates/site/layout-logged.php`
9. Final HTML output sent to browser
**AJAX Request Lifecycle:**
1. JavaScript POSTs to `ajax.php?module=tickets&action=ticket_add`
2. `ajax.php` bootstraps similarly to `index.php`
3. Controller method executes, modifies `$_SESSION['basket']`
4. `echo json_encode([...]); exit;` returns JSON response
**Ticket Purchase Flow:**
1. `main_view()` — Shows available tickets + calendar
2. `ticket_add()` — AJAX: validates date, calculates price, updates `$_SESSION['basket']`
3. `basket_view()` — Shows cart + customer form
4. `basketFormHandler()` — Inserts `orders` + `order_tickets` records, generates QR code PNG
5. `przelewy24()` — Renders payment form for P24 gateway
6. `przelewy24_response()` — P24 webhook: marks order paid, generates invoice, sends email
7. `order_confirm()` — Shows final confirmation + Google Analytics data layer
**State Management:**
- Shopping cart: `$_SESSION['basket']` (array keyed by ticket product_id)
- Admin auth: `$_SESSION['user']` (boolean for admin, array for staff users)
- Flash messages: `$_SESSION['alert']` (cleared after display)
- Session regenerated on first visit; IP-validated on each request
## Key Abstractions
**Module/Controller:**
- Purpose: Group of static methods handling a URL namespace (e.g., `/tickets/`)
- Examples: `autoload/controls/class.Tickets.php`, `autoload/controls/class.Apanel.php`
- Pattern: Static public methods, one per URL action
**Factory:**
- Purpose: Data access and business logic for a domain
- Examples: `autoload/factory/class.Tickets.php`, `autoload/factory/class.Users.php`
- Pattern: Static methods returning data arrays or modifying DB
**`\S` Utility Class:**
- Purpose: Centralized session, request, and utility operations
- Key methods: `S::get()` (unified POST/GET), `S::get_session()`, `S::set_session()`, `S::send_email()`, `S::hash()`, `S::alert()`
- Accessed statically throughout the codebase
**`\Tpl` Template Engine:**
- Purpose: Render PHP templates with variable injection
- Usage: `\Tpl::view('tickets/main-view', ['tickets' => $arr])`
- Variables accessible in template as `$this->tickets`
- Template lookup order: `templates_user/``templates/` → root
## Entry Points
**`index.php`:**
- Triggers: All web page requests
- Responsibilities: Session bootstrap, DB init, autoloader, calls `\view\Site::show()`
**`ajax.php`:**
- Triggers: jQuery AJAX calls from frontend
- Responsibilities: Same bootstrap as index.php, routes to controller AJAX actions
**`api.php`:**
- Triggers: External API calls (mobile or third-party)
- Responsibilities: API-specific bootstrap
**`cron.php`:**
- Triggers: Server cron job (scheduled tasks)
- Responsibilities: Email reminders, CEIDG import, task chaining
## Error Handling
**Strategy:** Minimal — most errors are silent (error_reporting suppresses notices/warnings)
**Patterns:**
- Factories return empty arrays on failure (no exceptions thrown)
- No try/catch in most controller methods
- cURL errors ignored (return value unchecked in payment flow)
- `error_reporting(E_ALL ^ E_NOTICE ^ E_STRICT ^ E_WARNING ^ E_DEPRECATED)` in entry points
## Cross-Cutting Concerns
**Session Security:**
- IP address validated on every request; session destroyed if changed
- Session regenerated once on first visit
- Implementation: `index.php` lines 27-31
**Globals:**
- `$settings` — all configuration (from `config.php`)
- `$mdb` — Medoo DB connection
- `$user` — current user (from session)
- Accessed via `global $settings, $mdb, $user` at top of controller methods
**Template Variables:**
- All templates receive data via `\Tpl::view()` second argument
- No direct template output buffering or inheritance
---
*Architecture analysis: 2026-04-26*
*Update when major patterns change*