|
| 1 | +# CLAUDE.md |
| 2 | + |
| 3 | +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. |
| 4 | + |
| 5 | +## Project Overview |
| 6 | + |
| 7 | +BNETDocs: Phoenix is a PHP 8.3+ web application for documenting Blizzard Entertainment's Battle.net and in-game protocols. Production site: https://bnetdocs.org |
| 8 | + |
| 9 | +## Commands |
| 10 | + |
| 11 | +### Dependencies |
| 12 | +```bash |
| 13 | +composer install # Install all dependencies |
| 14 | +composer update -o --no-dev # Production update with optimization |
| 15 | +``` |
| 16 | + |
| 17 | +### Linting |
| 18 | +```bash |
| 19 | +# Lint a single PHP file |
| 20 | +php -e -l -f src/path/to/file.php |
| 21 | + |
| 22 | +# Lint all PHP/PHTML files (mirrors CI) |
| 23 | +find src/ -name "*.php" -o -name "*.phtml" | xargs -I{} php -e -l -f {} |
| 24 | +``` |
| 25 | + |
| 26 | +### Testing |
| 27 | +```bash |
| 28 | +lib/bin/phpunit # Run all tests |
| 29 | +``` |
| 30 | + |
| 31 | +### Deployment |
| 32 | +```bash |
| 33 | +bin/deploy -e <environment> -f -y # -f skip composer update, -y skip confirmation |
| 34 | +``` |
| 35 | + |
| 36 | +### Docker (local development) |
| 37 | +```bash |
| 38 | +docker compose up -d # Start nginx, PHP-FPM, MariaDB |
| 39 | +docker compose down # Stop containers |
| 40 | +``` |
| 41 | + |
| 42 | +## Architecture |
| 43 | + |
| 44 | +### Request Flow |
| 45 | + |
| 46 | +``` |
| 47 | +HTTP Request → Nginx (FastCGI) → PHP-FPM → src/main.php |
| 48 | + → Router::invoke() |
| 49 | + → Pattern-matched Controller::invoke($args) # sets $model data |
| 50 | + → Content-negotiated View::invoke($model) # renders output |
| 51 | + → Response with headers and status code |
| 52 | +``` |
| 53 | + |
| 54 | +### MVC Pattern |
| 55 | + |
| 56 | +**Entry point:** `src/main.php` — initializes autoloader, session/auth, logs Blizzard/Slack bot traffic, then delegates to `Libraries/Core/Router`. |
| 57 | + |
| 58 | +**Router** (`Libraries/Core/Router.php`): Regex-based route matching with content negotiation (RFC 7231). Each route maps a URI pattern to a Controller class and an array of View classes (HTML, JSON, Plain, RSS, language-specific). The router selects the View based on the HTTP `Accept` header. |
| 59 | + |
| 60 | +**Controllers** (`src/Controllers/`): Implement `Interfaces\Controller`. The `invoke(?array $args): bool` method processes the request, populates `$model`, sets HTTP status/headers, and returns whether the view should render. |
| 61 | + |
| 62 | +**Models** (`src/Models/`): Implement `Interfaces\Model` and `JsonSerializable`. Extend `Models\Base` (has `_responseCode`/`_responseHeaders`). Key base classes: |
| 63 | +- `Models\ActiveUser` — adds current user authentication context |
| 64 | +- `Models\Core\AccessControl` — extends ActiveUser with ACL checks |
| 65 | + |
| 66 | +**Views** (`src/Views/`): Implement `Interfaces\View` with static `invoke(Model $model): void` and `mimeType(): string`. Base classes: `Html`, `Json`, `Plain`, `RSS`, and language-specific code renderers (`Cpp`, `Go`, `Java`, `Php`, `Vb`). |
| 67 | + |
| 68 | +**Templates** (`src/Templates/`): `.phtml` files used by HTML views. Template path mirrors the view class name (e.g., `Document/View.phtml` for `Document\ViewHtml`). |
| 69 | + |
| 70 | +### Key Libraries (`src/Libraries/`) |
| 71 | + |
| 72 | +- `Core/Config` — Loads `etc/config.phoenix.json` with dot-notation key access; falls back to the `config` DB table. |
| 73 | +- `Core/Router` — Route definitions live here; modifying routes means updating the `$routes` array. |
| 74 | +- `Db/MariaDb` — PDO singleton: `MariaDb::instance()`. Requires `TRADITIONAL,NO_AUTO_VALUE_ON_ZERO` SQL mode. |
| 75 | +- `User/Authentication` — Called early in `main.php`; sets `$_SESSION['bnetdocs']['authenticated_user_id']`. |
| 76 | + |
| 77 | +### Configuration |
| 78 | + |
| 79 | +Copy `etc/config.sample.json` to `etc/config.phoenix.json` and customize. Key sections: |
| 80 | +- `mysql` — database credentials |
| 81 | +- `bnetdocs` — maintenance mode, GeoIP country bans, password policy |
| 82 | +- `geoip` — path to MaxMind GeoLite2-City `.mmdb` file |
| 83 | +- `discord` / `email` / `recaptcha` / `slack` — integrations |
| 84 | + |
| 85 | +Sample configs: `etc/nginx-vhost-sample.conf`, `etc/mysql-server.sample.cnf` |
| 86 | + |
| 87 | +### Namespacing & Autoloading |
| 88 | + |
| 89 | +Namespace root: `BNETDocs\`. PSR-4 autoloading configured in `composer.json` mapping to `src/`. |
| 90 | + |
| 91 | +### Database |
| 92 | + |
| 93 | +MariaDB 10.7+ with UTF8MB4. Initial schema at `etc/database.sample.sql`. Key tables: `documents`, `packets`, `comments`, `users`, `news_posts`, `event_log`, `change_log`, `data_structures`, `servers`, `products`. |
| 94 | + |
| 95 | +## CI/CD |
| 96 | + |
| 97 | +- **php-linter.yml**: Runs on every push/PR — validates `composer.json` and lints all PHP files. |
| 98 | +- **deployment.yml**: Auto-deploys on push to `develop` or `phoenix` branches via rsync. Deploy targets defined in `etc/deploy-targets.csv`. Deployment injects `WEB_CONFIG_JSON` secret as the live config file. |
0 commit comments