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
3.3 KiB
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-4Unsupervised\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 insrc/:Plugin,Installer,Schema,AdminMenu,RestRegistrar,ShortcodeRegistrar,BlockRegistrar,Val. - Entry:
unsupervised-schedular.php->Plugin::boot()(wires all dependencies). Slug isschedular, notscheduler— filename, text domain (unsupervised-schedular), optionus_schedular_version, table prefixus_. Never "fix" the spelling. - REST:
/wp-json/us-scheduler/v1/,permission_callbackuses capability checks, never role names. - DB: custom
us_*tables viadbDelta;Schema::tables()is the source of truth. All$wpdbaccess inside repository classes only. src/Val.phpcoerces 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-runsInstaller/migrations when storedus_schedular_version !== USC_VERSION. Bump both theVersion:header andUSC_VERSIONinunsupervised-schedular.phpor the change never reaches existing sites.dbDeltadoes not reliably relax column NULL-ability. Follow the existing pattern inPlugin::boot(): repository repair method + ownus_*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(handlesMonkey\setUp/tearDown, stubs translations/escaping/checked/selected). - Mirror layout:
tests/Unit/<Domain>/mirrorssrc/<Domain>/.Functions\when('fn')->alias(fn() => ...)(neverreturnUsing());->justReturn($v)for constants.- Use
when()notexpect()for argument-dependent routing. - No
\Mockery::type()inside plain arrays passed towith()— use\Mockery::on()or\Mockery::any(). $wpdbmock needs$mock->prefix = 'wp_'as a property.
Adding a feature
- Spec first:
docs/features/<feature-name>.md(data model, API, classes, test paths). - Code in
src/<Domain>/; templates intemplates/if needed. - Tests in
tests/Unit/<Domain>/. composer testmust pass (alsocomposer lint+composer csbefore finishing).