Skip to content

Contribution Guide

How to contribute to the middag-account WordPress plugin.

Branch Strategy

BranchPurpose
mainProduction-ready code. Protected branch.
developIntegration branch for next release.
Featurefeat/{domain}-{description} off develop.
Fixfix/{domain}-{description} off develop.
Hotfixhotfix/{description} off main (critical only).

Release Flow

feature branch -> PR -> develop -> PR -> main -> tag -> release

Tags 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
PrefixWhen 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 HookInterface with register()
  • [ ] REST routes have permission_callback on 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 domain middag-account
  • [ ] Unit tests cover domain logic (target: 90%+ for Domain/)
  • [ ] composer check passes (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 fix to auto-correct)
  • Rector modernizes code patterns
  • PHPStan level 6+ for static analysis

Naming Conventions

ElementConventionExample
Entity class{Domain}EntityOrganizationEntity
Service class{Domain}ServiceEntitlementService
Repository{Domain}RepositoryInterfaceQuoteRepositoryInterface
Hook class{Domain}HooksEntitlementHooks
Controller{Domain}ControllerOrderController
Page controller{Domain}PageControllerInvoicePageController
Status enum{Domain}StatusContractStatus
CPT slugmiddag_{domain}middag_entitlement
Hook namemiddag/{domain}/{event}middag/quote/paid

Test Naming

TypePath Pattern
Unit testtests/Unit/{mirrored-src-path}/{ClassName}Test.php
Integrationtests/Integration/{Feature}/{FeatureName}Test.php

Feature Implementation Order

When adding a new domain or feature, follow this sequence:

  1. Domain entity + status enum (pure PHP)
  2. Repository interface (Domain/) then implementation (WordPress/)
  3. Service layer (Domain/)
  4. Hook classes (WordPress/Hook/)
  5. REST controller (Api/)
  6. Integration layer (if external services involved)
  7. Inertia page controller (UI/) + React pages
  8. Tests -- unit + integration