# 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*
