# Architecture

Celena is a hand-written PHP CMS with no third-party frameworks (no Laravel/Symfony) and no Composer dependencies in the core. All code is plain PHP 8.3+ with mandatory `declare(strict_types=1)` and strict typing.

If you're just starting out, read this page, then [Project structure](/docs/code/structure) and [Request lifecycle](/docs/code/lifecycle). To build extensions, move on to [What is a plugin](/docs/code/plugins-intro).

## Entry points

| File | Purpose |
|------|---------|
| `index.php` | Site front — all public requests. |
| `admin.php` | Admin panel (thin loader, hands control to `Kernel`). |
| `install.php` | Self-deleting install wizard (after install an `install.lock` appears). |
| `bin/celena` | CLI: migrations, plugins, queue, cache. |

Every request goes through the core `Celena\Core\Kernel`:

```
HTTP request → index.php → core/bootstrap.php → Kernel::boot()
  → Autoloader → Container → Config → services
  → Router::dispatch(Request) → Middleware → Controller → Response → send()
```

## Layers

The code is split into four layers with a strict dependency direction:

| Layer | Folder | Depends on |
|-------|--------|------------|
| Core (domain-agnostic) | `core/` | only `core/*` |
| Built-in CMS modules | `modules/` | `core/*` |
| Plugins (extensions) | `plugins/` | `core/*`, optionally other plugins via manifest |
| Themes (appearance) | `templates/` | template engine tags only |

The core knows nothing about news, shops or forms — it provides the tools (router, DB, template engine, hooks), while concrete functionality comes from modules and plugins.

## Namespaces and autoloading

PSR-4 via `core/Autoloader.php`. Mappings:

- `Celena\Core\` → `core/`
- `Celena\Module\<Name>\` → `modules/<Name>/`
- `Celena\Plugin\<Slug>\` → `plugins/<slug>/src/`
- `Celena\Theme\<Slug>\` → `templates/<slug>/`

**Rule: one class — one file.** The file name matches the class name.

## Contracts

- `declare(strict_types=1)` everywhere; argument and return types are mandatory.
- Any user input goes through `Celena\Core\Security\Filter`.
- Any HTML output goes through `e()` (the escaping helper) or the template engine's auto-escaping.
- Database access only via `QueryBuilder` or `PDO::prepare`. **Concatenating values into SQL is forbidden.**

## Hooks (events)

Extensions talk to the core through a WordPress-style hook system — actions (side effects) and filters (value transformation):

```php
use Celena\Core\Plugin\Hook;

Hook::action('news.published', $news);              // fire an action
Hook::on('news.published', fn($n) => /* ... */);    // subscribe

$title = Hook::filter('news.title', $news['title']); // apply filters
Hook::addFilter('news.title', fn($t) => trim($t));   // subscribe to a filter
```

More on the [Hooks & events](/docs/code/hooks) page.

## Cache

- Data cache is file-based by default (`storage/cache/data`); APCu/Redis optionally.
- Templates are compiled to PHP and cached in `storage/cache/tpl/{hash}.php`. Invalidation is by source modification time (mtime) and manual.
