IDEA Extended
This commit is contained in:
228
.planning/codebase/CONVENTIONS.md
Normal file
228
.planning/codebase/CONVENTIONS.md
Normal file
@@ -0,0 +1,228 @@
|
||||
# Coding Conventions
|
||||
|
||||
**Analysis Date:** 2026-02-04
|
||||
|
||||
**Reference:** This document captures WinterCMS/Laravel PHP conventions that should guide the Scala rewrite. As SummerCMS is a greenfield Scala project, these patterns should be adapted to Scala idioms while maintaining architectural consistency.
|
||||
|
||||
## Naming Patterns
|
||||
|
||||
**Files:**
|
||||
- **Classes:** PascalCase, one class per file (e.g., `User.php`, `AuthManager.php`, `FormController.php`)
|
||||
- **Models:** Singular PascalCase (e.g., `User`, `UserRole`, `UserGroup` in `modules/backend/models/`)
|
||||
- **Controllers:** Plural PascalCase with "Controller" suffix (e.g., `Users.php`, `AccessLogs.php` in `modules/backend/controllers/`)
|
||||
- **Namespaces:** Correspond to directory structure with backslash path separators
|
||||
|
||||
**Functions/Methods:**
|
||||
- camelCase (e.g., `getFullNameAttribute()`, `sendInvitation()`, `getPersistCode()`)
|
||||
- Helper methods in models use verb prefixes: `get*`, `set*`, `is*`, `has*` (e.g., `getAvatarThumb()`, `isSuperUser()`)
|
||||
- Event hooks use specific naming: `afterCreate()`, `afterLogin()`, `afterUpdate()` (see `modules/backend/models/User.php` lines 129-158)
|
||||
- Private methods are lowercase camelCase
|
||||
|
||||
**Variables:**
|
||||
- camelCase for all variable names (e.g., `$persist_code`, `$send_invite`, `$full_name`)
|
||||
- Snake_case for database column names mapped to model attributes
|
||||
- Configuration array keys use lowercase dot notation (e.g., `'cms.pluginsPath'`, `'database.default'`)
|
||||
|
||||
**Types/Classes:**
|
||||
- Model classes: Base classes in `modules/*/models/` (e.g., `Backend\Models\User` extends `Winter\Storm\Auth\Models\User as UserBase`)
|
||||
- Controller classes: `Backend\Controllers\Users` implements behaviors
|
||||
- Use fully qualified namespaced class names in type declarations
|
||||
|
||||
**Constants:**
|
||||
- UPPER_SNAKE_CASE for constants (convention follows Laravel)
|
||||
|
||||
## Code Style
|
||||
|
||||
**Formatting:**
|
||||
- EditorConfig enforced via `.editorconfig` at repository root:
|
||||
- End of line: LF
|
||||
- Charset: UTF-8
|
||||
- Indent: 4 spaces
|
||||
- Trim trailing whitespace: enabled
|
||||
- Insert final newline: enabled
|
||||
- Workflow files (`.github/workflows/`): 2-space indent
|
||||
|
||||
**Spacing:**
|
||||
- Opening braces on same line (e.g., `public function getData() {`)
|
||||
- Closing braces on new line
|
||||
- Method declarations with full type hints and documentation (see `modules/backend/models/User.php` lines 78-98)
|
||||
|
||||
**Linting:**
|
||||
- Tool: PHP CodeSniffer (squizlabs/php_codesniffer) via composer script
|
||||
- Command: `composer sniff` - Checks PSR-1, PSR-2, PSR-4 standards
|
||||
- Command: `composer lint` - Parallel lint checking with php-parallel-lint
|
||||
- Excludes: vendor/, storage/, specific test fixtures
|
||||
|
||||
**Documentation:**
|
||||
- PSDoc style comments on all public methods with `@param`, `@return`, `@var` annotations
|
||||
- Class-level doc blocks include package and author info:
|
||||
```php
|
||||
/**
|
||||
* Administrator user model
|
||||
*
|
||||
* @package winter\wn-backend-module
|
||||
* @author Alexey Bobkov, Samuel Georges
|
||||
*/
|
||||
```
|
||||
- Inline comments explain non-obvious logic (see `modules/backend/models/User.php` lines 89-95 option explanation)
|
||||
|
||||
## Import Organization
|
||||
|
||||
**Order (per file):**
|
||||
1. PHP namespace declaration (no blank line)
|
||||
2. Use statements grouped:
|
||||
- Facades first (e.g., `use Backend\Facades\Backend;`)
|
||||
- Models next (e.g., `use Backend\Models\UserGroup;`)
|
||||
- Classes and utilities (e.g., `use Winter\Storm\Database\Traits\SoftDelete;`)
|
||||
3. Blank line before class declaration
|
||||
|
||||
**Example** (`modules/backend/models/User.php` lines 1-15):
|
||||
```php
|
||||
<?php namespace Backend\Models;
|
||||
|
||||
use Backend\Facades\Backend;
|
||||
use Backend\Facades\BackendAuth;
|
||||
use Illuminate\Support\Facades\Event;
|
||||
use Winter\Storm\Auth\Models\User as UserBase;
|
||||
use Winter\Storm\Support\Facades\Mail;
|
||||
|
||||
/**
|
||||
* Administrator user model
|
||||
* ...
|
||||
*/
|
||||
class User extends UserBase
|
||||
```
|
||||
|
||||
**Path Aliases:**
|
||||
- No import aliases in WinterCMS codebase - full namespace paths are used
|
||||
- Traits are explicitly used via `use` keyword within class body (e.g., `use \Winter\Storm\Database\Traits\SoftDelete;`)
|
||||
|
||||
## Error Handling
|
||||
|
||||
**Patterns:**
|
||||
- No explicit try-catch in models/controllers; exceptions bubble to framework handlers
|
||||
- Validation errors handled via model `$rules` property (e.g., `modules/backend/models/User.php` lines 27-32)
|
||||
- Framework handles model validation failures and redirects with flash messages
|
||||
- Exception types: `Winter\Storm\Exception\SystemException` used for framework-level errors (seen in tests)
|
||||
|
||||
**Validation:**
|
||||
- Model rules defined in `public $rules` array with pipe-separated validators:
|
||||
```php
|
||||
public $rules = [
|
||||
'email' => 'required|between:6,255|email|unique:backend_users',
|
||||
'login' => 'required|between:2,255|unique:backend_users',
|
||||
'password' => 'required:create|min:4|confirmed',
|
||||
];
|
||||
```
|
||||
|
||||
## Logging
|
||||
|
||||
**Framework:** Laravel native logging (via `Illuminate\Support\Facades\Log` or helpers)
|
||||
|
||||
**Patterns:**
|
||||
- No explicit logging calls in examined source files
|
||||
- Framework routes all errors through Laravel's error handler
|
||||
- Debug mode toggled via `.env` `APP_DEBUG` setting (defaults to true in config but should be false in production)
|
||||
- Log configuration in `config/logging.php`
|
||||
|
||||
**Observability:**
|
||||
- Model lifecycle events fired via `Event::fire()` for observation/extension:
|
||||
```php
|
||||
Event::fire('backend.user.login', [$this]);
|
||||
```
|
||||
|
||||
## Comments
|
||||
|
||||
**When to Comment:**
|
||||
- Explain "why", not "what" (code explains what it does)
|
||||
- Document non-obvious algorithms or workarounds
|
||||
- Mark uncertain logic with `@todo`, `@TODO` (seen throughout codebase)
|
||||
|
||||
**Comment Styles:**
|
||||
- Single-line: `// Comment`
|
||||
- Multi-line: Block with `/** ... */` for docblocks only
|
||||
- Inline: After code with `// Comment`
|
||||
|
||||
**JSDoc/TSDoc:**
|
||||
- PHP style with `@param`, `@return`, `@var`, `@throws` tags
|
||||
- Event documentation uses `@event` tag with example usage (see `modules/backend/models/User.php` lines 147-158)
|
||||
- Database column documentation via `@var` on property declarations
|
||||
|
||||
## Function Design
|
||||
|
||||
**Size:**
|
||||
- Methods generally 10-40 lines (see examples in User model)
|
||||
- Extracted helper methods for reusable logic
|
||||
- Model lifecycle hooks are concise (afterCreate, afterLogin, etc.)
|
||||
|
||||
**Parameters:**
|
||||
- Type-hinted where applicable
|
||||
- Favor explicit parameters over options arrays
|
||||
- Options arrays used for backward compatibility (e.g., `getAvatarThumb($size = 25, $options = null)`)
|
||||
|
||||
**Return Values:**
|
||||
- Explicit return statements
|
||||
- Type hints on return values in docblocks (though PHP 7.4+ allows native return types)
|
||||
- Null returns used for "not found" cases
|
||||
|
||||
## Module Design
|
||||
|
||||
**Exports:**
|
||||
- Classes explicitly imported via use statements
|
||||
- No wildcard imports (`use Namespace\*;`)
|
||||
- All public classes are explicitly declared
|
||||
|
||||
**Barrel Files:**
|
||||
- No barrel/index files observed in WinterCMS
|
||||
- Direct class imports required
|
||||
|
||||
**Class Properties:**
|
||||
- Public properties for model relations and validation rules:
|
||||
```php
|
||||
public $belongsToMany = [...];
|
||||
public $belongsTo = [...];
|
||||
public $rules = [...];
|
||||
public $implement = [...]; // In controllers
|
||||
```
|
||||
- Protected properties for internal state (e.g., `protected $table`, `protected $dates`)
|
||||
- Magic properties documented via `@var` doc comments
|
||||
|
||||
**Traits:**
|
||||
- Used for cross-cutting concerns (e.g., `SoftDelete`, `UploadableWidget`)
|
||||
- Applied within class body via `use` statement
|
||||
- Traits encapsulate reusable behavior patterns
|
||||
|
||||
## Event System
|
||||
|
||||
**Framework:** Laravel Event system with plugin extension points
|
||||
|
||||
**Patterns:**
|
||||
- Events fired at significant lifecycle points (e.g., `backend.user.login`)
|
||||
- Listeners registered via `Event::listen()` in plugin service providers
|
||||
- Event documentation includes example listener code
|
||||
- Used for non-breaking extensibility across plugins
|
||||
|
||||
## Model Extension Pattern
|
||||
|
||||
**Dynamic Extension:**
|
||||
- Models extended via `extend()` method in plugin registration:
|
||||
```php
|
||||
User::extend(function ($model) {
|
||||
$model->hasMany['payments'] = [PaymentModel::class, 'key' => 'user_id'];
|
||||
});
|
||||
```
|
||||
- Allows plugins to add relations, validation, behaviors without modifying core models
|
||||
|
||||
## Translation/Localization
|
||||
|
||||
**Framework:** Winter's translation system
|
||||
|
||||
**Pattern:**
|
||||
- Backend labels use plugin namespace: `'plugin.namespace::lang.section.key'`
|
||||
- Translation filter in views: `{{ 'String'|_ }}`
|
||||
- Used for all user-facing strings (labels, help text, messages)
|
||||
|
||||
---
|
||||
|
||||
*Convention analysis: 2026-02-04*
|
||||
*Reference: WinterCMS PHP codebase patterns to inform Scala rewrite*
|
||||
Reference in New Issue
Block a user