Files
summercms-initial-research/.planning/codebase/ARCHITECTURE.md
2026-02-04 01:06:15 +01:00

232 lines
10 KiB
Markdown

# Architecture
**Analysis Date:** 2026-02-04
## Pattern Overview
**Overall:** Modular Layer-based MVC with Plugin System
WinterCMS implements a **three-layer modular architecture** consisting of Core Modules (System, Backend, CMS) that form the framework foundation, with a Plugin system overlaid for extensibility. The framework uses Laravel 9.x as its base, with Winter's Storm library acting as a compatibility buffer.
**Key Characteristics:**
- Laravel-based HTTP kernel with module-level routing
- CMS-first approach: frontend pages route through CMS module, backend admin routes through Backend module
- Plugin dependency resolution with automatic component/controller/model discovery
- Extensibility through plugin interdependencies and event-driven architecture
- YAML/JSON configuration for models, forms, lists, and behaviors
- Static theme system with file-based page, layout, and partial management
## Layers
**Core Modules (modules/ directory):**
- **System Module:** Base framework, plugin management, mail system, asset handling, error management
- **Backend Module:** Admin interface, form/list widgets, user role management, controller behaviors
- **CMS Module:** Frontend page rendering, theme management, component system, layout composition
**Plugin Layer (plugins/ directory):**
- Vendor-namespaced plugins (winter/, golem15/)
- Each plugin extends and integrates with core modules
- Plugin dependencies declared via `$require` arrays in Plugin.php
- Core plugins: Apparatus (DI/scenarios), User (auth), PaymentGateway (commerce)
- Domain plugins: Blog, Menu, Translate, AI, Chat, etc.
**Frontend/Theme Layer (themes/ directory):**
- Static theme files organized in theme directories
- Pages, layouts, partials stored as .htm files with Twig syntax
- Assets (CSS, JS, images) co-located with pages/layouts
- URL routing to pages via Theme manager and CMS controller
## Data Flow
**Frontend Request (Page View):**
1. HTTP request to any URL arrives at `index.php`
2. Bootstrap loads application (`bootstrap/app.php`)
3. HTTP Kernel processes request through middleware
4. Laravel Router evaluates all registered routes
5. Backend/System routes handled by their controllers
6. CMS module catch-all route `{slug?}` routes to `Cms\Classes\CmsController@run()`
7. CMS Controller delegates to `Cms\Classes\Controller` (primary frontend controller)
8. Primary Controller:
- Looks up URL in Theme using `Cms\Classes\Router`
- Resolves Page, Layout, and Component objects from theme files
- Renders page through Twig template engine
- Components injected into page output via ComponentManager
9. Response sent back to client
**Backend Request (Admin Interface):**
1. HTTP request to `/backend/...` arrives
2. Backend Router matches `Backend\Classes\BackendController@run()`
3. BackendController parses remaining URL segments to determine target plugin/controller
4. Controller loaded from plugin (e.g., `Golem15\Blog\Controllers\Posts`)
5. Controller action determined by remaining URL parts
6. Behaviors attached (FormController, ListController, etc.) handle CRUD operations
7. Views rendered with form/list widgets
8. JSON/HTML response returned
**Component Lifecycle:**
1. Page YAML/Twig specifies component code (`{% component 'componentName' %}`)
2. ComponentManager resolves code to fully-qualified class name via codeMap
3. Component class instantiated with properties from page markup
4. Component's `onRun()` method called by page renderer
5. Component renders its partial template (HTM file) in page context
6. AJAX handlers on component (e.g., `onUpdateCart`) handled by Snowboard framework
**State Management:**
- Models: Database-backed via Winter\Storm\Database\Model (extends Laravel Eloquent)
- Sessions: Laravel session middleware, stored in `storage/framework/sessions/`
- Cache: Laravel cache (configurable drivers: file, redis, memcached)
- Parameters: System\Models\Parameter table for application-level configuration
- Translation: Text keys cached in parameters, loaded by Translate plugin
## Key Abstractions
**Plugin Architecture:**
Purpose: Enables modular, independently-deployable features with dependency resolution
- Each plugin is a Laravel ServiceProvider extending `System\Classes\PluginBase`
- Plugin.php declares: `pluginDetails()`, `register()`, `boot()`, `registerComponents()`, `registerControllers()`, etc.
- Examples: `golem15-wintercms-starter/plugins/golem15/blog/Plugin.php`, `golem15-wintercms-starter/plugins/golem15/user/Plugin.php`
- Pattern: Plugins register services, components, controllers, and extend existing models
**Component System:**
Purpose: Reusable, composable page elements with their own controllers and views
- Components extend `Cms\Classes\ComponentBase`
- Register in plugin via `registerComponents()` returning [ClassName => 'code']
- ComponentManager loads all registered components into codeMap
- Example: `golem15-wintercms-starter/modules/cms/components/SoftComponent.php`
- Pattern: Component renders partial, handles AJAX, injects CSS/JS
**Theme/Page System:**
Purpose: File-based, non-database-backed content management
- Theme directory contains pages/, layouts/, partials/ subdirectories
- Page class `Cms\Classes\Page` extends `CmsCompoundObject` - represents page file as object
- Page file format: URL metadata → YAML → Twig markup
- Page references layout (inherited structure) and components (functional blocks)
- Example page structure: `themes/demo/pages/home.htm`
- Pattern: Page objects loaded on-demand from disk, cached in memory
**Backend Form/List System:**
Purpose: YAML-driven admin CRUD interfaces
- Controllers use FormController and ListController behaviors
- forms.yaml/fields.yaml define form structure and validation
- lists.yaml/columns.yaml define table columns and filtering
- FormController handles create/read/update/delete operations
- Example files: `plugins/*/models/*/fields.yaml`, `plugins/*/models/*/columns.yaml`
- Pattern: Behaviors parse YAML and generate HTML forms/tables dynamically
**Service Providers & Dependency Injection:**
Purpose: Central registration of services and extensibility hooks
- Plugins register services in `register()` and `boot()` methods
- Services bound to Laravel's DI container via `$this->app->singleton()`
- Example: Apparatus framework registers DI container for component auto-wiring
- Pattern: Late binding allows plugin A to extend plugin B's services
## Entry Points
**Frontend (CMS Page Serving):**
- Location: `golem15-wintercms-starter/modules/cms/classes/CmsController.php` (HTTP entry), `golem15-wintercms-starter/modules/cms/classes/Controller.php` (business logic)
- Triggers: Any URL not matching backend or other routes
- Responsibilities:
- Routes URL to page via Theme manager
- Loads Page, Layout, and Components
- Renders through Twig with component injection
- Returns HTML response
**Backend (Admin Interface):**
- Location: `golem15-wintercms-starter/modules/backend/classes/BackendController.php`
- Triggers: URLs prefixed with `/backend/`
- Responsibilities:
- Parses plugin.controller.action URL pattern
- Instantiates controller from plugin
- Applies middleware and behaviors
- Routes to controller action
- Renders admin interface
**System Initialization:**
- Location: `golem15-wintercms-starter/bootstrap/app.php`, `golem15-wintercms-starter/index.php`
- Triggers: Every HTTP request
- Responsibilities:
- Creates Laravel application instance
- Binds kernel, console kernel, exception handler
- Loads plugin manager and auto-discovers plugins
- Registers module routes
**CLI Commands:**
- Location: `golem15-wintercms-starter/artisan` (entry point), `golem15-wintercms-starter/modules/*/console/` (command classes)
- Triggers: `php artisan <command>`
- Responsibilities:
- Plugin scaffold commands
- Database migrations
- Asset management
- Cache management
- Payment gateway operations (via golem15/paymentgateway)
## Error Handling
**Strategy:** Exception-driven with error page rendering
**Patterns:**
- All exceptions thrown as `SystemException`, `ApplicationException`, or Framework exceptions
- HTTP exceptions converted to error pages by Exception Handler (`modules/system/classes/ErrorHandler.php`)
- In production: Shows generic error page, logs details
- In debug mode: Shows full stack trace and context
- Model validation: Throws ApplicationException with validation messages
- Frontend: 404 errors trigger Page not found response
- Backend: 404 errors redirect to backend dashboard, show toast notifications
## Cross-Cutting Concerns
**Logging:**
- Uses Laravel's log facade (`Log::info()`, `Log::error()`)
- Stored in `storage/logs/`
- Configured in `config/app.php` and environment variables
- EventLog model (`modules/system/models/EventLog.php`) tracks application events
- RequestLog model tracks HTTP requests for debugging
**Validation:**
- Model-level via `$rules` property (Laravel validation rules)
- Form widget validation via fields.yaml `validation` property
- Backend behaviors apply validation before save
- Errors returned as JSON validation responses in AJAX handlers
**Authentication:**
- Winter Backend: Database-backed user with role-based access control
- Frontend API: JWT tokens (via golem15/user plugin)
- Middleware: `Backend\Middleware\AuthenticateBackend`, `User\Middleware\JwtAuth`
- Guards: `web` (session-based), `api` (JWT)
## Extensibility Mechanisms
**Model Extension:**
- Plugins extend models dynamically using `Model::extend(Closure)`
- Example: `User::extend(function($model) { $model->hasMany['payments'] = ...; })`
- Used for adding relationships, attributes, query scopes without modifying core
**Event System:**
- Global events via `Event::listen()` and `Event::fire()`
- Module-level events: `system.route`, `cms.beforeRoute`, `cms.route`, `backend.beforeRoute`
- Model events: `model.saveInternal`, `model.afterCreate`, `model.afterUpdate`, `model.afterDelete`
- Custom events fired by plugins for extensibility
**Behaviors:**
- Controllers implement behaviors via `$implement` array
- Backend behaviors: FormController, ListController, RelationController, ImportExportController
- Each behavior adds methods (e.g., `create`, `update`, `index`) to controller
- Example: `modules/backend/behaviors/FormController.php`
---
*Architecture analysis: 2026-02-04*