Files
unsupervised-scheduler/AGENTS.md
T
Kydoimos 76a314576e
CI / Coding Standards (pull_request) Successful in 34s
CI / No Debug Code (pull_request) Successful in 4s
CI / Tests (PHP 8.5) (pull_request) Successful in 39s
CI / Tests (PHP 8.1) (pull_request) Successful in 49s
CI / Tests (PHP 8.2) (pull_request) Successful in 1m14s
CI / Tests (PHP 8.3) (pull_request) Successful in 1m15s
CI / Static Analysis (pull_request) Successful in 1m22s
CI / Build Plugin Zip (pull_request) Skipped
Add AGENTS.md, point CLAUDE.md files at it
2026-09-16 11:58:19 -03:00

3.3 KiB

AGENTS.md

Commands

composer install
composer test                     # PHPUnit — run after every code change
composer lint                     # PHPStan (level 10, `src/` only)
composer cs                       # PHPCS (WordPress standard + exclusions in phpcs.xml.dist)
composer cs:fix                   # auto-fix coding standards
composer build                    # -> dist/unsupervised-schedular-<version>.zip

./vendor/bin/phpunit tests/Unit/Offering/OfferingRepositoryTest.php
./vendor/bin/phpunit --filter testInsertReturnsId

CI (.gitea/workflows/ci.yml): phpcs, phpstan, test (PHP 8.1/8.2/8.3/8.5), no-debug. Write only PHP 8.1-compatible syntax. No var_dump|var_export|print_r|error_log|dd|dump( in src/ — CI greps and fails.

Architecture

  • WordPress plugin, no front-end build (vanilla JS/CSS in assets/). PSR-4 Unsupervised\Schedular\ -> src/.
  • Package-by-domain: src/<Domain>/ (Auth, Availability, Booking, GroupClass, Guardian, Offering, Payment, Policy, Registration) owns its repos, services, endpoints, pages. Cross-cutting wiring lives directly in src/: Plugin, Installer, Schema, AdminMenu, RestRegistrar, ShortcodeRegistrar, BlockRegistrar, Val.
  • Entry: unsupervised-schedular.php -> Plugin::boot() (wires all dependencies). Slug is schedular, not scheduler — filename, text domain (unsupervised-schedular), option us_schedular_version, table prefix us_. Never "fix" the spelling.
  • REST: /wp-json/us-scheduler/v1/, permission_callback uses capability checks, never role names.
  • DB: custom us_* tables via dbDelta; Schema::tables() is the source of truth. All $wpdb access inside repository classes only.
  • src/Val.php coerces untyped WP input (Val::int(), Val::string(), ...OrNull, etc.). For PHPCS, Val::int/float/bool/... count as unslashing passthrough only — still wrap with a real sanitizer: absint( Val::int( $_GET['id'] ?? 0 ) ).

Schema changes (gotcha)

  • Plugin::boot() only re-runs Installer/migrations when stored us_schedular_version !== USC_VERSION. Bump both the Version: header and USC_VERSION in unsupervised-schedular.php or the change never reaches existing sites.
  • dbDelta does not reliably relax column NULL-ability. Follow the existing pattern in Plugin::boot(): repository repair method + own us_* option flag (e.g. us_questions_offering_nullable), not the version gate.

Tests

  • Brain Monkey + Mockery, no live WP. All test classes extend tests/Unit/TestCase.php (handles Monkey\setUp/tearDown, stubs translations/escaping/checked/selected).
  • Mirror layout: tests/Unit/<Domain>/ mirrors src/<Domain>/.
    • Functions\when('fn')->alias(fn() => ...) (never returnUsing()); ->justReturn($v) for constants.
    • Use when() not expect() for argument-dependent routing.
    • No \Mockery::type() inside plain arrays passed to with() — use \Mockery::on() or \Mockery::any().
    • $wpdb mock needs $mock->prefix = 'wp_' as a property.

Adding a feature

  1. Spec first: docs/features/<feature-name>.md (data model, API, classes, test paths).
  2. Code in src/<Domain>/; templates in templates/ if needed.
  3. Tests in tests/Unit/<Domain>/.
  4. composer test must pass (also composer lint + composer cs before finishing).