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

6.3 KiB

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