Skip to content

Architecture

This codebase is a legacy PHP application that has been partially modernized with Slim 4 and a PHP-DI container. The UI and API entry points now run through Slim middleware stacks, but most request handling still delegates to legacy include-style PHP scripts under app/.

High-Level Map

flowchart LR
    Browser[Browser] --> Apache[Web Server]
    ApiClient[API Client] --> Apache
    Apache --> PublicUI[public/index.php<br/>Slim UI App]
    Apache --> PublicAPI[public/api/index.php<br/>Slim API App]

    PublicUI --> MiddlewareUI[UI Middleware Stack]
    MiddlewareUI --> LegacyUI[LegacyRequestHandler]
    LegacyUI --> AppModules[app/* legacy modules]

    PublicAPI --> MiddlewareAPI[API Middleware Stack]
    MiddlewareAPI --> ApiRoutes[Slim Routes]
    MiddlewareAPI --> LegacyAPI[ApiLegacyFallbackMiddleware]
    LegacyAPI --> ApiIncludes[app/api/* includes]

    AppModules --> Services[App\\Services, Utilities]
    ApiIncludes --> Services
    Services --> DB[(MySQL)]

    Bootstrap[bootstrap.php] --> PublicUI
    Bootstrap --> PublicAPI
    Bootstrap --> Services

Entry Points

  • Web UI: public/index.php builds a Slim app, adds middleware, then delegates all routes to App\HttpHandlers\LegacyRequestHandler.
  • API: public/api/index.php builds a Slim app, registers minimal routes, then falls back to legacy includes via App\Middlewares\Api\ApiLegacyFallbackMiddleware.
  • CLI/Tasks: bin/*, app/tasks/*, and vendor/bin/crunz scripts are used for maintenance, background jobs, and setup.
  • Server-sent events: public/sse/alerts.php requires bootstrap.php directly, outside the Slim stacks, and checks the session itself.

Bootstrap and Configuration

  • bootstrap.php sets session/cookie policies, defines paths, loads Composer autoload, loads system constants and version, registers DI, and installs error/exception handlers.
  • Environment config is loaded from configs/config.<env>.php (defaulting to production).
  • Module toggles, database credentials and interfacing settings live in the config file (see configs/). Other settings are rows in the global_config table, edited under ADMIN > Settings > General Configuration.

Dependency Injection and Registries

  • PHP-DI container setup lives in app/system/di.php.
  • The container is stored in App\Registries\ContainerRegistry for global access.
  • App\Registries\AppRegistry stores per-request data (e.g., current request/URI).

Web UI Request Flow

sequenceDiagram
    participant B as Browser
    participant P as public/index.php
    participant M as UI Middleware Stack
    participant L as LegacyRequestHandler
    participant A as app/* script

    B->>P: HTTP Request
    P->>M: Slim middleware pipeline
    M->>L: catch-all route
    L->>A: include legacy PHP file
    A-->>L: output buffer
    L-->>B: HTTP Response

UI Middleware Stack (order of execution)

  • Error handling: App\Middlewares\ErrorHandlerMiddleware
  • Security headers/CSP
  • CORS: App\Middlewares\CorsMiddleware
  • Request context: sets AppRegistry values
  • Auth split: SystemAdminAuthMiddleware or AppAuthMiddleware
  • CSRF: App\Middlewares\App\CSRFMiddleware
  • ACL: App\Middlewares\App\AclMiddleware

API Request Flow

sequenceDiagram
    participant C as API Client
    participant P as public/api/index.php
    participant M as API Middleware Stack
    participant R as Slim Route (optional)
    participant L as Legacy API include

    C->>P: HTTP Request
    P->>M: Slim middleware pipeline
    M->>R: Matched route (e.g., /api/v1.1/init)
    M->>L: Fallback include when no Slim route
    L-->>C: JSON Response

API Middleware Stack (order of execution)

  • Error handling: App\Middlewares\Api\ApiErrorHandlingMiddleware
  • CORS (including preflight handling)
  • Interface Tool API guard: App\Middlewares\Api\InterfaceRequestGuardMiddleware
  • Body parsing: Slim\Middleware\BodyParsingMiddleware
  • JSON content-type enforcement
  • Auth: App\Middlewares\Api\ApiAuthMiddleware
  • Request context: AppRegistry request
  • Legacy fallback: App\Middlewares\Api\ApiLegacyFallbackMiddleware
  • Content-Length header

GET /api/v1.1/health is a real Slim route (App\HttpHandlers\Api\HealthHandler) and is excluded from auth. It answers 503 when the database is unreachable. Bootstrap connects eagerly, so public/api/index.php recognises the health path before requiring bootstrap and defines INTELIS_HEALTH_PROBE; DatabaseFactory then rethrows the connection failure instead of printing the HTML outage page, and the front controller answers with JSON.

The Interface Tool endpoints are registered as real Slim routes rather than legacy includes. They carry their own InterfaceApiEnabledMiddleware and InterfaceInstallationAuthMiddleware, so a lab is always resolved from the credential instead of the request.

/api/v2/* routes are real Slim handlers under App\HttpHandlers\Api\V2 with one response envelope (App\Http\ApiV2Response). ApiAuthMiddleware skips them, and each handler authenticates its own caller (a user token or a lab token).

Legacy Application Layout

Most business logic and UI pages are in legacy include-based modules under app/:

  • app/<module>/ feature folders (e.g., vl, eid, tb, covid-19, dashboard)
  • app/common/, app/includes/ shared includes and helpers
  • app/header.php, app/footer.php, app/index.php UI scaffolding and redirects
  • app/api/ versioned API scripts (e.g., app/api/v1.1/*)
  • app/classes/ modern PHP classes (services, utilities, middlewares, registries)
  • sys/migrations/ versioned schema migrations, applied by bin/migrate.php. sql/init.sql is the fresh-install seed only.
  • sys/cron/ the Crunz task definitions

Services, Utilities, and Domain Classes

PSR-4 autoloaded classes live under app/classes/:

  • Services/ core services (DB, system, common helpers)
  • Middlewares/ Slim middleware for UI and API
  • HttpHandlers/ request handlers (legacy bridge)
  • Utilities/ logging, helpers, and shared tools
  • Interop/ external system integrations (DHIS2, FHIR)
  • Repositories/ data access classes. composer check-repository-boundaries enforces what may call them.
  • ErrorHandlers/, Exceptions/ error handling and exception types
  • Factories/ object factories, including DatabaseFactory
  • Http/ response helpers such as ApiV2Response
  • Contracts/, Abstracts/, Helpers/ interfaces, base classes and small helpers

These are auto-registered into the DI container and can be fetched via ContainerRegistry.

Database

  • App\Services\DatabaseService is the single database service. The container builds it through App\Factories\DatabaseFactory (app/system/di.php). Code reaches the database through it and never opens a connection of its own.
  • App\Services\AuditTriggerService manages the audit triggers. The post-update run drops them before migrations and reinstalls them afterwards.

Background Jobs and Maintenance

  • Scheduled jobs are defined in sys/cron/ScheduledTasks.php. crunz.yml points Crunz at that folder.
  • cron.sh and vendor/bin/crunz run scheduled tasks.
  • CLI scripts live in bin/ and app/tasks/ (remote sync, archiving, migrations).

Data, Files, and Assets

  • Web root: public/
  • Static assets: public/assets/
  • Uploads: public/uploads/
  • Temporary files: public/temporary/
  • Sensitive temporary files: var/temporary/ (served only through download.php)
  • Runtime cache/logs: var/cache/, var/logs/
  • Backups: backups/
  • SQL schema and utilities: sql/, db-tools.php

Integration Points

  • Remote sync workflows live in app/remote/ and app/tasks/remote/.
  • External service clients are in app/classes/Interop/.

Checks

The CI checks every change must pass are listed in engineering-standards.md.

Notes for Ongoing Modernization

  • Slim is currently used as the entry layer and middleware pipeline.
  • Most routes still resolve to legacy PHP includes. Gradual refactors can move legacy pages into Slim routes or controllers while retaining middleware coverage.