# 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*