Skip to content

Local Development

Setup guide for developing the middag-account WordPress plugin locally.

Requirements

ToolVersionNotes
PHP8.4+With extensions: curl, decimal, dom, intl, json, mbstring, openssl, simplexml, soap, xml, zip
Composer2.xDependency management
Node.js20+React UI build
npm10+Package management
WordPress6.5+Local installation
WooCommerce9.0+Required plugin dependency
MySQL8.0+Or MariaDB 10.6+

Initial Setup

bash
# Clone into wp-content/plugins/
cd wp-content/plugins/middag-account

# Install PHP dependencies
composer install

# Install Node dependencies and ReUI blocks
composer ui:setup

# Build React UI (Vite -> assets/dist/app.js)
composer ui:npm:build

Project Structure

middag-account/
├── src/               # PHP source (PSR-4: Middag\Account\)
│   ├── Core/          # Container, Kernel, ServiceProvider
│   ├── Domain/        # Pure PHP domain logic (zero WP deps)
│   ├── Api/V1/        # REST controllers
│   ├── Integration/   # External service adapters
│   ├── WordPress/     # WP abstraction layer
│   └── UI/            # Inertia page controllers
├── tests/             # PHPUnit tests (mirrors src/)
├── ui/                # React 19 + Inertia.js + Tailwind v4
├── assets/dist/       # Built frontend output
├── docs/              # ADRs, use cases, operations
└── docs-site/         # Developer reference docs

Running Tests

bash
# Run full test suite
composer test

# Run a specific test file
./vendor/bin/phpunit tests/Unit/Domain/Entitlement/EntitlementServiceTest.php

# Run tests with coverage report
./vendor/bin/phpunit --coverage-html coverage/

Test structure mirrors src/:

  • tests/Unit/Domain/{Name}/ -- Domain unit tests (Brain\Monkey for WP stubs)
  • tests/Integration/{Feature}/ -- Integration tests with WP bootstrap

Static Analysis

bash
# Run all quality checks (style + rector + phpstan)
composer check

# Auto-fix style issues and apply rector
composer fix

Individual tools:

bash
# PHP-CS-Fixer
./vendor/bin/php-cs-fixer fix --dry-run --diff

# PHPStan (level 6+)
./vendor/bin/phpstan analyse

# Rector
./vendor/bin/rector process --dry-run

UI Development

bash
# Install frontend dependencies
composer ui:setup

# Build production bundle (Vite IIFE -> assets/dist/app.js)
composer ui:npm:build

# Development mode with hot reload
cd ui && npm run dev

The UI uses React 19 + Inertia.js v2 + Tailwind v4 with @middag-io/react design system. Vite 6 builds an IIFE bundle consumed by WordPress.

Read ui/DESIGN.md before making any visual or UI changes.

Internationalization

bash
# Generate .pot translation template
composer i18n:pot

# Compile .mo files from .po translations
composer i18n:mo

Text domain: middag-account. Source language: English. All user-facing strings must use __(), _e(), or esc_html__().

Distribution Build

bash
# Full build: check + i18n + ui:build + composer --no-dev
composer dist:build

This produces a clean ZIP with no dev dependencies, test files, or documentation.

Environment Variables

The plugin loads environment variables via vlucas/phpdotenv. Create a .env file in the plugin root (ignored by git):

MIDDAG_JWT_PRIVATE_KEY_PATH=/path/outside/webroot/private.pem
MIDDAG_JWT_PUBLIC_KEY_PATH=/path/outside/webroot/public.pem
STRIPE_WEBHOOK_SECRET_BR=whsec_...
STRIPE_WEBHOOK_SECRET_GLOBAL=whsec_...
HUBSPOT_CLIENT_SECRET_BR=...
HUBSPOT_CLIENT_SECRET_GLOBAL=...

Private keys must be stored outside the webroot.

Useful Commands Summary

CommandDescription
composer testRun PHPUnit test suite
composer checkStyle + Rector + PHPStan
composer fixAuto-fix style + Rector
composer ui:setupnpm install + ReUI blocks
composer ui:npm:buildBuild React -> assets/dist/
composer i18n:potGenerate .pot file
composer i18n:moCompile .mo files
composer dist:buildFull distribution build