Skip to content

XOOPS 2026 Architecture Diagrams

Visual representations of the Clean Architecture patterns used in XOOPS 2026 modules.

Overview: Clean Architecture Layers

graph TB
    subgraph External["External World"]
        Browser["🌐 Browser"]
        API["📡 API Client"]
        CLI["💻 CLI"]
    end

    subgraph Presentation["Presentation Layer"]
        Controllers["Controllers"]
        Templates["Smarty Templates"]
        APIControllers["API Controllers"]
    end

    subgraph Application["Application Layer"]
        Commands["Commands"]
        Queries["Queries"]
        Handlers["Handlers"]
    end

    subgraph Domain["Domain Layer (Core)"]
        Entities["Entities"]
        ValueObjects["Value Objects"]
        RepoInterfaces["Repository Interfaces"]
        DomainServices["Domain Services"]
        Exceptions["Domain Exceptions"]
    end

    subgraph Infrastructure["Infrastructure Layer"]
        Repositories["MySQL Repositories"]
        XoopsIntegration["XOOPS Integration"]
        Container["DI Container"]
    end

    subgraph External2["External Systems"]
        Database[("MySQL Database")]
        XoopsCore["XOOPS Core"]
    end

    Browser --> Controllers
    API --> APIControllers
    CLI --> Handlers

    Controllers --> Commands
    Controllers --> Queries
    APIControllers --> Commands
    APIControllers --> Queries

    Commands --> Handlers
    Queries --> Handlers
    Handlers --> Entities
    Handlers --> ValueObjects
    Handlers --> RepoInterfaces

    RepoInterfaces -.->|implemented by| Repositories
    Repositories --> Database
    XoopsIntegration --> XoopsCore
    Container --> Repositories
    Container --> Handlers

    classDef domain fill:#e1f5fe,stroke:#01579b
    classDef application fill:#fff3e0,stroke:#e65100
    classDef infrastructure fill:#f3e5f5,stroke:#7b1fa2
    classDef presentation fill:#e8f5e9,stroke:#2e7d32
    classDef external fill:#fce4ec,stroke:#c2185b

    class Entities,ValueObjects,RepoInterfaces,DomainServices,Exceptions domain
    class Commands,Queries,Handlers application
    class Repositories,XoopsIntegration,Container infrastructure
    class Controllers,Templates,APIControllers presentation
    class Browser,API,CLI,Database,XoopsCore external

HTTP Request Flow

sequenceDiagram
    autonumber
    participant B as Browser
    participant C as Controller
    participant H as CommandHandler
    participant E as Entity
    participant R as Repository
    participant DB as MySQL

    B->>C: POST /articles (title, content)
    C->>C: Validate request
    C->>H: CreateArticleCommand

    H->>H: Create Value Objects
    Note over H: ArticleTitle::create()<br/>ArticleContent::create()

    H->>E: Article::create()
    Note over E: Generate ULID<br/>Set initial status

    H->>R: save(article)
    R->>DB: INSERT INTO articles...
    DB-->>R: Success

    R-->>H: void
    H-->>C: Article entity
    C->>C: Format response
    C-->>B: 201 Created + JSON

Command/Query Separation (CQRS)

flowchart LR
    subgraph Write["Write Side (Commands)"]
        CC[CreateArticleCommand]
        UC[UpdateArticleCommand]
        DC[DeleteArticleCommand]

        CH[CreateArticleHandler]
        UH[UpdateArticleHandler]
        DH[DeleteArticleHandler]

        CC --> CH
        UC --> UH
        DC --> DH
    end

    subgraph Read["Read Side (Queries)"]
        GQ[GetArticleQuery]
        LQ[ListArticlesQuery]
        SQ[SearchArticlesQuery]

        GH[GetArticleHandler]
        LH[ListArticlesHandler]
        SH[SearchArticlesHandler]

        GQ --> GH
        LQ --> LH
        SQ --> SH
    end

    subgraph Domain["Domain Model"]
        E[Article Entity]
        R[Repository Interface]
    end

    CH --> E
    UH --> E
    DH --> R

    GH --> R
    LH --> R
    SH --> R

    style Write fill:#ffecb3
    style Read fill:#e3f2fd
    style Domain fill:#e8f5e9

Entity Lifecycle

stateDiagram-v2
    [*] --> Draft: Article::create()

    Draft --> Published: publish()
    Draft --> Archived: archive()

    Published --> Archived: archive()

    Archived --> Draft: restore()

    note right of Draft
        Initial state
        Can edit content
    end note

    note right of Published
        Visible to public
        Limited editing
    end note

    note right of Archived
        Hidden from public
        Can be restored
    end note

Value Object Validation Flow

flowchart TD
    Input["Raw Input String"]

    subgraph Validation["Value Object Creation"]
        Trim["trim(input)"]
        CheckMin{"length >= MIN?"}
        CheckMax{"length <= MAX?"}
        Create["new ArticleTitle(value)"]
    end

    subgraph Exceptions["Domain Exceptions"]
        TooShort["InvalidArticleTitle::tooShort()"]
        TooLong["InvalidArticleTitle::tooLong()"]
    end

    Output["Valid ArticleTitle"]

    Input --> Trim
    Trim --> CheckMin
    CheckMin -->|No| TooShort
    CheckMin -->|Yes| CheckMax
    CheckMax -->|No| TooLong
    CheckMax -->|Yes| Create
    Create --> Output

    TooShort --> Error["❌ Exception thrown"]
    TooLong --> Error

    style Output fill:#c8e6c9
    style Error fill:#ffcdd2

Repository Pattern

flowchart TB
    subgraph Application["Application Layer"]
        Handler["Command Handler"]
    end

    subgraph Domain["Domain Layer"]
        Interface["ArticleRepositoryInterface"]
        Entity["Article Entity"]
    end

    subgraph Infrastructure["Infrastructure Layer"]
        MySQL["MySqlArticleRepository"]
        InMemory["InMemoryArticleRepository"]
    end

    subgraph Tests["Test Environment"]
        TestHandler["Test Handler"]
    end

    Handler --> Interface
    Interface -.->|implements| MySQL
    Interface -.->|implements| InMemory

    MySQL --> DB[("Production DB")]
    InMemory --> Memory["In-Memory Storage"]

    TestHandler --> InMemory

    style Interface stroke:#01579b,stroke-width:3px
    style MySQL fill:#f3e5f5
    style InMemory fill:#fff3e0

Dependency Injection Container

flowchart TD
    subgraph Container["Service Container"]
        GetRepo["getArticleRepository()"]
        GetCreate["getCreateArticleHandler()"]
        GetUpdate["getUpdateArticleHandler()"]
        GetQuery["getGetArticleHandler()"]
        GetController["getArticleController()"]
    end

    subgraph Services["Instantiated Services"]
        Repo["MySqlArticleRepository"]
        CreateH["CreateArticleHandler"]
        UpdateH["UpdateArticleHandler"]
        QueryH["GetArticleHandler"]
        Ctrl["ArticleController"]
    end

    subgraph Deps["Dependencies"]
        DB["XoopsDatabase"]
    end

    GetRepo --> Repo
    GetCreate --> CreateH
    GetUpdate --> UpdateH
    GetQuery --> QueryH
    GetController --> Ctrl

    Repo -.->|needs| DB
    CreateH -.->|needs| Repo
    UpdateH -.->|needs| Repo
    QueryH -.->|needs| Repo
    Ctrl -.->|needs| CreateH
    Ctrl -.->|needs| UpdateH
    Ctrl -.->|needs| QueryH

API Request/Response Cycle

sequenceDiagram
    autonumber
    participant Client as API Client
    participant Router as Router
    participant Auth as Auth Middleware
    participant Controller as API Controller
    participant Handler as Query Handler
    participant Repo as Repository

    Client->>Router: GET /api/v1/articles/01HV8X...
    Router->>Auth: Validate JWT Token
    Auth->>Auth: Decode & Verify

    alt Token Invalid
        Auth-->>Client: 401 Unauthorized
    end

    Auth->>Controller: Authenticated Request
    Controller->>Controller: Validate ULID format

    alt Invalid ULID
        Controller-->>Client: 422 Validation Error
    end

    Controller->>Handler: GetArticleQuery(id, userId)
    Handler->>Repo: findById(ArticleId)

    alt Not Found
        Repo-->>Handler: ArticleNotFound
        Handler-->>Controller: Exception
        Controller-->>Client: 404 Not Found
    end

    Repo-->>Handler: Article
    Handler->>Handler: Check permissions

    alt No Permission
        Handler-->>Controller: DomainException
        Controller-->>Client: 403 Forbidden
    end

    Handler-->>Controller: Article
    Controller->>Controller: Format JSON response
    Controller-->>Client: 200 OK + JSON

ULID vs Auto-Increment ID

flowchart LR
    subgraph AutoIncrement["Auto-Increment (Legacy)"]
        AI1["1"]
        AI2["2"]
        AI3["3"]
        AI4["..."]
        AI1 --> AI2 --> AI3 --> AI4
    end

    subgraph ULID["ULID (XOOPS 2026)"]
        U1["01HV8X5Z0K..."]
        U2["01HV8X5Z0M..."]
        U3["01HV8X5Z0N..."]
        U4["..."]
        U1 --> U2 --> U3 --> U4
    end

    subgraph Benefits["ULID Benefits"]
        B1["✓ Time-sortable"]
        B2["✓ URL-safe"]
        B3["✓ No collisions"]
        B4["✓ Better indexing"]
        B5["✓ Works distributed"]
    end

    ULID --> Benefits

    style AutoIncrement fill:#ffcdd2
    style ULID fill:#c8e6c9
    style Benefits fill:#e3f2fd

Module Directory Structure

flowchart TD
    Root["modules/mymodule/"]

    subgraph Domain["Domain/ (No Dependencies)"]
        DE["Entity/"]
        DV["ValueObject/"]
        DR["Repository/"]
        DX["Exception/"]
    end

    subgraph Application["Application/ (Uses Domain)"]
        AC["Command/"]
        AQ["Query/"]
    end

    subgraph Infrastructure["Infrastructure/ (Implements)"]
        IP["Persistence/"]
        IX["Xoops/"]
        IA["Api/"]
    end

    subgraph Presentation["Presentation/ (User Interface)"]
        PC["Controller/"]
        PT["templates/"]
    end

    Root --> Domain
    Root --> Application
    Root --> Infrastructure
    Root --> Presentation

    Application -.->|depends on| Domain
    Infrastructure -.->|implements| Domain
    Presentation -.->|uses| Application

    style Domain fill:#e1f5fe
    style Application fill:#fff3e0
    style Infrastructure fill:#f3e5f5
    style Presentation fill:#e8f5e9

Exception Handling Flow

flowchart TD
    Request["HTTP Request"]

    subgraph Controller["Controller Layer"]
        Try["try { ... }"]
        Catch["catch blocks"]
    end

    subgraph Exceptions["Exception Types"]
        Domain["DomainException"]
        NotFound["EntityNotFound"]
        Validation["ValidationException"]
        Auth["UnauthorizedException"]
    end

    subgraph Responses["HTTP Responses"]
        R400["400 Bad Request"]
        R401["401 Unauthorized"]
        R404["404 Not Found"]
        R422["422 Unprocessable"]
        R500["500 Server Error"]
    end

    Request --> Try
    Try --> Catch

    Catch --> Domain
    Catch --> NotFound
    Catch --> Validation
    Catch --> Auth

    Domain --> R400
    NotFound --> R404
    Validation --> R422
    Auth --> R401

    Catch -->|Unexpected| R500

    style R400 fill:#fff3e0
    style R401 fill:#ffcdd2
    style R404 fill:#f3e5f5
    style R422 fill:#fff3e0
    style R500 fill:#ffcdd2

Test Structure

flowchart TB
    subgraph Unit["Unit Tests"]
        VO["Value Object Tests"]
        ET["Entity Tests"]
        HT["Handler Tests"]
    end

    subgraph Fixtures["Test Fixtures"]
        IM["InMemory Repository"]
        MO["Object Mothers"]
        FA["Factories"]
    end

    subgraph Integration["Integration Tests"]
        RT["Repository Tests"]
        AT["API Tests"]
    end

    VO --> Fixtures
    ET --> Fixtures
    HT --> Fixtures

    RT --> DB[("Test Database")]
    AT --> API["Test Server"]

    style Unit fill:#e8f5e9
    style Fixtures fill:#fff3e0
    style Integration fill:#e3f2fd

Complete Request Lifecycle

flowchart TB
    subgraph External["1. External"]
        User["👤 User"]
        Browser["🌐 Browser"]
    end

    subgraph Presentation["2. Presentation"]
        Route["Route Matching"]
        Controller["Controller"]
        Template["Template Rendering"]
    end

    subgraph Application["3. Application"]
        Command["Command/Query"]
        Handler["Handler"]
        Validation["Input Validation"]
    end

    subgraph Domain["4. Domain"]
        Entity["Entity"]
        VO["Value Objects"]
        Rules["Business Rules"]
    end

    subgraph Infrastructure["5. Infrastructure"]
        Repo["Repository"]
        Container["DI Container"]
    end

    subgraph Database["6. Database"]
        MySQL[("MySQL")]
    end

    User -->|1| Browser
    Browser -->|2| Route
    Route -->|3| Controller
    Controller -->|4| Command
    Command -->|5| Handler
    Handler -->|6| Validation
    Validation -->|7| VO
    VO -->|8| Entity
    Entity -->|9| Rules
    Handler -->|10| Repo
    Repo -->|11| MySQL
    MySQL -->|12| Repo
    Repo -->|13| Handler
    Handler -->|14| Controller
    Controller -->|15| Template
    Template -->|16| Browser
    Browser -->|17| User

    style External fill:#fce4ec
    style Presentation fill:#e8f5e9
    style Application fill:#fff3e0
    style Domain fill:#e1f5fe
    style Infrastructure fill:#f3e5f5
    style Database fill:#fafafa