91 lines
5.2 KiB
Markdown
91 lines
5.2 KiB
Markdown
# Architecture
|
||
|
||
This project follows a conventional Symfony architecture with clear separation of concerns across controllers, entities, repositories, services, security, forms, and templates.
|
||
|
||
## Naming & reusability standards (PHP)
|
||
|
||
- **Classes**
|
||
- **Controllers** end with `Controller` (e.g. `AlbumController`) and expose HTTP‑oriented actions with verb‑based method names (`search`, `show`, `edit`, `delete`).
|
||
- **Services** are named by capability, not by caller, using nouns or noun‑phrases (e.g. `AlbumSearchService`, `ConsoleCommandRunner`, `RegistrationToggle`). When a service is tightly scoped to a third‑party, the integration appears in the name (e.g. `SpotifyClient`, `SpotifyMetadataRefresher`).
|
||
- **Entities** are singular domain nouns (`Album`, `Review`, `User`) and avoid transport or UI details.
|
||
- **Commands** describe what they do and the environment they are meant for (e.g. `SeedDemoUsersCommand`, `PromoteAdminCommand`).
|
||
|
||
- **Methods**
|
||
- Use **verb‑based, intention‑revealing names** that describe *what* the method does, not *how* it is used (e.g. `refreshAllSpotifyAlbums()`, `resetCatalog()`, `runConsoleCommand()`, `isEnabled()`, `findAlbumByPublicId()`).
|
||
- Accessors start with `get*`, `set*`, `is*` / `has*` for booleans (e.g. `getEnvOverride()`, `isSpotifyConfigured()`).
|
||
- Avoid ambiguous names like `run()`, `handle()`, or `process()` without a clear domain object; prefer `runConsoleCommand()`, `handleAlbumCoverUpload()`, etc.
|
||
|
||
- **Variables & parameters**
|
||
- Use **descriptive, domain‑level names** (e.g. `$albumRepository`, `$reviewCount`, `$spotifyAlbumPayload`) and avoid unclear abbreviations (`$em` is acceptable for `EntityManagerInterface` in local scope, but prefer full names for properties).
|
||
- Booleans read naturally (`$isEnabled`, `$shouldQuerySpotify`, `$needsSync`).
|
||
- Collections are pluralized (`$albums`, `$userReviews`, `$spotifyIds`).
|
||
|
||
- **Files & namespaces**
|
||
- File names match their primary class name and follow PSR‑4 (e.g. `src/Service/AlbumSearchService.php` for `App\Service\AlbumSearchService`).
|
||
- Helper classes that are not tied to HTTP or persistence live under `src/Service` or `src/Dto` with names that describe the abstraction, not the caller.
|
||
|
||
These conventions should be followed for all new PHP code and when refactoring existing classes to keep the codebase reusable and self‑documenting.
|
||
|
||
## High-level flow
|
||
1. Visitors search for albums (Spotify) and view an album page
|
||
2. Logged‑in users can write, edit, and delete reviews
|
||
3. Moderators and admins can moderate content and manage users
|
||
4. Admins configure site settings (Spotify credentials, registration toggle)
|
||
|
||
## Layers & components
|
||
|
||
### Controllers (`src/Controller/*`)
|
||
- `AlbumController` — search, album detail, inline review creation
|
||
- `ReviewController` — view, edit, and delete reviews
|
||
- `AccountController` — profile, password, and user settings pages
|
||
- `Admin/*` — site dashboard, user management, and settings
|
||
- `RegistrationController`, `SecurityController` — sign‑up and login/logout routes
|
||
|
||
### Entities (`src/Entity/*`)
|
||
- `User` — authentication principal and roles
|
||
- `Album`, `AlbumTrack` — normalized album metadata and track list
|
||
- `Review` — user‑authored review with rating and timestamps
|
||
- `Setting` — key/value store for site configuration (e.g., Spotify credentials)
|
||
|
||
### Repositories (`src/Repository/*`)
|
||
- Doctrine repositories for querying by domain (albums, tracks, reviews, settings, users)
|
||
|
||
### Forms (`src/Form/*`)
|
||
- `RegistrationFormType`, `ReviewType`, `ChangePasswordFormType`, `ProfileFormType`, `SiteSettingsType`, etc.
|
||
- Leverage Symfony validation constraints for robust server‑side validation
|
||
|
||
### Services (`src/Service/*`)
|
||
- `SpotifyClient` — Client Credentials token management (cached) and API calls
|
||
- `SpotifyMetadataRefresher`, `SpotifyGenreResolver` — helpers for richer album data
|
||
- `CatalogResetService` — admin action to reset/sync catalog state safely
|
||
- `ImageStorage` — avatar uploads and related image handling
|
||
- `RegistrationToggle` — DB‑backed registration flag with env override
|
||
|
||
### Security (`config/packages/security.yaml`, `src/Security/*`)
|
||
- Role hierarchy: `ROLE_ADMIN` ⊇ `ROLE_MODERATOR` ⊇ `ROLE_USER`
|
||
- `ReviewVoter` — edit/delete permissions for review owners and privileged roles
|
||
- Access control for `/admin/*` enforced via routes and controllers
|
||
|
||
### Views (`templates/*`)
|
||
- Twig templates for pages and partials (`base.html.twig`, `album/*`, `review/*`, `account/*`, `admin/*`)
|
||
- Auth modal in `templates/_partials/auth_modal.html.twig`
|
||
- Navbar with role‑aware links in `templates/_partials/navbar.html.twig`
|
||
|
||
### DTOs (`src/Dto/*`)
|
||
- Simple data transfer objects for admin tables and search results
|
||
|
||
## Data & persistence
|
||
- SQLite by default for local/packaged deployments; Postgres supported via `DATABASE_URL`
|
||
- Migrations run on startup by default (`RUN_MIGRATIONS_ON_START=1`)
|
||
|
||
## Error handling & UX
|
||
- 404 for missing albums
|
||
- Flash messages for success/error on actions
|
||
- Disabled/tooltip states in admin UI for protected actions (e.g., cannot delete an admin)
|
||
|
||
## Testing & tooling
|
||
- PHPUnit setup in `composer.json` (`phpunit/phpunit`), BrowserKit & CSS Selector for functional coverage
|
||
- Web Profiler enabled in dev
|
||
|
||
|