Contribution Guide
How to contribute to the middag-account WordPress plugin.
Branch Strategy
| Branch | Purpose |
|---|---|
main | Production-ready code. Protected branch. |
develop | Integration branch for next release. |
| Feature | feat/{domain}-{description} off develop. |
| Fix | fix/{domain}-{description} off develop. |
| Hotfix | hotfix/{description} off main (critical only). |
Release Flow
feature branch -> PR -> develop -> PR -> main -> tag -> releaseTags trigger the CI/CD build pipeline that produces a distributable ZIP.
Conventional Commits
All commit messages must follow the Conventional Commits specification:
feat(entitlement): add auto-provisioning from paid quotes
fix(auth): validate token expiration before refresh
docs(api): update organization endpoint schemas
chore(deps): upgrade symfony/dependency-injection to 7.4.1
refactor(quote): extract status transition logic to enum
test(collaborator): add permission scope unit tests| Prefix | When to Use |
|---|---|
feat: | New feature or capability |
fix: | Bug fix |
docs: | Documentation only changes |
chore: | Build, CI, dependency updates |
refactor: | Code restructuring without behavior change |
test: | Adding or updating tests |
style: | Code style / formatting only |
Include the domain scope in parentheses when applicable: feat(quote):, fix(auth):.
PR Checklist
Before submitting a pull request, verify:
- [ ] Domain logic has zero WordPress imports (
src/Domain/only) - [ ] Constructor injection used -- no static calls to services
- [ ] Hook classes implement
HookInterfacewithregister() - [ ] REST routes have
permission_callbackon every endpoint - [ ] Input is sanitized (
sanitize_text_field,absint,sanitize_email) - [ ] Output is escaped (
esc_html,esc_attr,esc_url) - [ ] Organization boundary is enforced in queries
- [ ] All user-facing strings use
__()with text domainmiddag-account - [ ] Unit tests cover domain logic (target: 90%+ for Domain/)
- [ ]
composer checkpasses (style + rector + phpstan) - [ ] Integration tests cover REST endpoints if applicable
Code Standards
PHP
- PHP 8.4+ with strict typing in every file
- PSR-4 autoloading under
Middag\Account\namespace - PHP-CS-Fixer enforces code style (run
composer fixto auto-correct) - Rector modernizes code patterns
- PHPStan level 6+ for static analysis
Naming Conventions
| Element | Convention | Example |
|---|---|---|
| Entity class | {Domain}Entity | OrganizationEntity |
| Service class | {Domain}Service | EntitlementService |
| Repository | {Domain}RepositoryInterface | QuoteRepositoryInterface |
| Hook class | {Domain}Hooks | EntitlementHooks |
| Controller | {Domain}Controller | OrderController |
| Page controller | {Domain}PageController | InvoicePageController |
| Status enum | {Domain}Status | ContractStatus |
| CPT slug | middag_{domain} | middag_entitlement |
| Hook name | middag/{domain}/{event} | middag/quote/paid |
Test Naming
| Type | Path Pattern |
|---|---|
| Unit test | tests/Unit/{mirrored-src-path}/{ClassName}Test.php |
| Integration | tests/Integration/{Feature}/{FeatureName}Test.php |
Feature Implementation Order
When adding a new domain or feature, follow this sequence:
- Domain entity + status enum (pure PHP)
- Repository interface (Domain/) then implementation (WordPress/)
- Service layer (Domain/)
- Hook classes (WordPress/Hook/)
- REST controller (Api/)
- Integration layer (if external services involved)
- Inertia page controller (UI/) + React pages
- Tests -- unit + integration
Related
- Local Development -- Setup and tooling
- Architecture Overview -- Project structure