| Both sides previous revisionPrevious revision | |
| scriptlog:architecture:overview [2026/09/28 01:57] – admin admin | scriptlog:architecture:overview [2026/09/28 02:01] (current) – admin admin |
|---|
| ===== 3. Wiring ===== | ===== 3. Wiring ===== |
| |
| `Bootstrap` is a static factory made of many small private methods. `initialize()` runs four stages: `loadConfiguration()`, the `utility-loader.php` require, `initializeServices()`, then `applySecurity()` (which ends in `initializePostSecurity()`). The service graph inside `initializeServices()` runs in this order: | `Bootstrap` is a static factory made of many small private methods. `initialize()` runs four stages: `loadConfiguration()`, the `utility-loader.php` require, `initializeServices()`, then `applySecurity()` (which ends in `initializePostSecurity()`). The service graph inside `initializeServices()` runs top to bottom: |
| |
| * `createDatabaseConnection()`, `defineRoutingRules()`, `initializeRegistry()` | ^ Order ^ Methods ^ |
| * `createBaseDaos()`, `createSession()`, `createAuthenticator()` | | 1 | `createDatabaseConnection()`, `defineRoutingRules()`, `initializeRegistry()` | |
| * `createThemeRenderer()`, `createDownloadChain()`, `createContentDaos()` | | 2 | `createBaseDaos()`, `createSession()`, `createAuthenticator()` | |
| * `storeInRegistry()`, `createFrontService()`, `createDispatcher()` | | 3 | `createThemeRenderer()`, `createDownloadChain()`, `createContentDaos()` | |
| * `buildServiceMap()`, `buildHandlerRegistry()`, `buildAdminActionRegistry()` | | 4 | `storeInRegistry()`, `createFrontService()`, `createDispatcher()` | |
| * `initializeI18n()` | | 5 | `buildServiceMap()`, `buildHandlerRegistry()`, `buildAdminActionRegistry()` | |
| | | 6 | `initializeI18n()` | |
| |
| Note the ordering constraint the code comments on: `createFrontService()` resolves its DAOs from the `Registry` at construction time, so it must run *after* `storeInRegistry()`. | **Ordering constraint:** `createFrontService()` resolves its DAOs from the `Registry` at construction time, so it must run *after* `storeInRegistry()`. |
| |
| The graph is composed with plain `new` calls, so each object's collaborators are visible in its constructor signature. Shared instances are additionally published into the global `Registry` (`Registry::setAll()` in `initializeRegistry()`, plus `Registry::set('frontService', ...)` afterwards) for late binding from theme helpers, `HandleRequest` and `front_service()`. | The graph is composed with plain `new` calls, so each object's collaborators are visible in its constructor signature. Shared instances are additionally published into the global `Registry` (`Registry::setAll()` in `initializeRegistry()`, plus `Registry::set('frontService', ...)` afterwards) for late binding from theme helpers, `HandleRequest` and `front_service()`. |
| ===== 4. Request lifecycle ===== | ===== 4. Request lifecycle ===== |
| |
| Once `Dispatcher::dispatch()` runs, the shape of the response depends on one | Once `Dispatcher::dispatch()` runs, one configuration value decides the shape of the response: `rewrite_status`. |
| configuration value, `rewrite_status`: | |
| |
| * `'yes'` — SEO-friendly URLs. `handleSeoFriendlyUrl()` resolves an optional locale prefix first, strips it, and matches the remainder against the route table. | ^ `rewrite_status` ^ Handler ^ Behavior ^ |
| * anything else — `handleQueryStringUrl()` serves the classic `?pg=`, `?p=`, `?a=`, `?cat=`, `?tag=`, `?search=`, `?q=` form. | | `'yes'` | `handleSeoFriendlyUrl()` | Resolves an optional locale prefix first, strips it, then matches the remainder against the route table. | |
| | | anything else | `handleQueryStringUrl()` | Serves the classic `?pg=`, `?p=`, `?a=`, `?cat=`, `?tag=`, `?search=`, `?q=` form through `HandleRequest::deliverQueryString()`. | |
| |
| The `?download=` case is handled first at the top of the SEO branch as well, so a | The `?download=` case is handled first at the top of the SEO branch as well, so a |
| download keeps working regardless of the permalink setting. | download keeps working regardless of the permalink setting. |
| |
| A matched route is then validated by a `validate*()` method | Every matched route then flows through one pipeline: |
| (`validateContentExists`, `validateSinglePost`, `validatePage`, | |
| `validateCategory`, `validateArchive`, `validateTag`), the matching theme | <code> |
| handler is looked up, and the response is produced by `invokeTheme()`. | route match --> validate*() --> handler lookup |
| `renderTheme()` serves a full page; `renderHtmxFragment()` serves a partial for | --> invokeTheme() --> renderTheme() | renderHtmxFragment() |
| HTMX requests. Frontend routes are compiled once into `$frontendCompiled`. | </code> |
| | |
| | Validation is one `validate*()` method per page type (`validateContentExists`, `validateSinglePost`, `validatePage`, `validateCategory`, `validateArchive`, `validateTag`). `renderTheme()` serves a full page; `renderHtmxFragment()` serves a partial for HTMX requests. Frontend routes are compiled once into `$frontendCompiled`. |
| |
| ===== 5. The route table ===== | ===== 5. The route table ===== |