Files
unsupervised-scheduler/CLAUDE.md
James Griffin 0fbafc9d18
Some checks failed
CI / Coding Standards (push) Failing after 2m31s
CI / PHPStan (push) Failing after 50s
CI / Tests (PHP 8.1) (push) Successful in 50s
CI / Tests (PHP 8.2) (push) Successful in 48s
CI / Tests (PHP 8.3) (push) Successful in 40s
CI / No Debug Code (push) Successful in 2s
Initial plugin scaffold: lesson scheduling WordPress plugin
- Custom DB tables for availability slots and lesson bookings
- Instructor (wp-admin) and student (front-end) roles with custom capabilities
- REST API under us-scheduler/v1 for availability CRUD and booking
- [us_booking] and [us_student_login] shortcodes for student front end
- PHPUnit + Brain\Monkey unit test suite (29 tests)
- Gitea Actions CI: lint, PHPStan, tests on PHP 8.1/8.2/8.3, no-debug check
- Feature docs under docs/features/

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 12:44:46 -03:00

4.8 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Commands

composer install                  # Install all dependencies

composer test                     # Run the full test suite (required after every change)
composer lint                     # PHPStan static analysis
composer cs                       # PHPCS coding standards check
composer cs:fix                   # Auto-fix coding standards

# Run a single test file
./vendor/bin/phpunit tests/Unit/Data/AvailabilityRepositoryTest.php

# Run a single test by name
./vendor/bin/phpunit --filter testInsertCallsWpdbInsertAndReturnsId

Run composer test after every code change before considering a task complete.

Architecture

Plugin Bootstrap

unsupervised-schedular.php defines constants (USC_VERSION, USC_PLUGIN_DIR, USC_PLUGIN_URL), registers activation/deactivation hooks, then calls Plugin::boot() on plugins_loaded. No logic lives in the root file.

Directory Structure

src/          — All plugin PHP (PSR-4 namespace: Unsupervised\Schedular\)
templates/    — PHP view files included by controllers/shortcodes
assets/       — CSS and JS (vanilla JS, no build step)
tests/Unit/   — PHPUnit unit tests (PSR-4: Unsupervised\Schedular\Tests\)
docs/features/— One markdown file per feature describing data model, API, and test locations

Data Storage

Two custom database tables (created via dbDelta on activation):

  • {prefix}us_availability — instructor availability windows
  • {prefix}us_lessons — booked lessons

All database access goes through repository classes in src/Data/. No direct $wpdb calls outside repositories.

Key Classes

Class Responsibility
Plugin Wires all components together on plugins_loaded
Installer Creates DB tables and roles on activation
Roles\RoleManager Registers us_instructor and us_student roles with custom caps
Data\AvailabilityRepository CRUD for availability slots
Data\BookingRepository CRUD for lesson bookings
Model\AvailabilitySlot Immutable value object for a slot row
Model\Lesson Immutable value object for a lesson row
Admin\AdminMenu Registers wp-admin menu pages
Admin\AvailabilityController Instructor availability management page
Admin\LessonController Admin and instructor lesson list pages
Api\RestRegistrar Registers all REST routes under us-scheduler/v1
Api\AvailabilityEndpoint REST handlers for availability CRUD
Api\BookingEndpoint REST handlers for booking and status updates
Frontend\ShortcodeRegistrar Registers [us_booking] and [us_student_login] shortcodes
Frontend\BookingPage Renders student booking UI shell (JS takes over)
Frontend\LoginPage Renders front-end student login form

REST API Namespace

All endpoints live under /wp-json/us-scheduler/v1/. Permissions are enforced via permission_callback using capability checks (manage_availability, book_lesson), never role name checks.

Testing Approach

Tests use Brain\Monkey to stub WordPress functions without a full WP installation, and Mockery to mock $wpdb and other dependencies.

All test classes extend tests/Unit/TestCase.php, which handles Monkey\setUp() / Monkey\tearDown() and stubs all WP translation/escape functions automatically.

Brain\Monkey API notes:

  • Functions\when('fn')->alias(fn() => ...) — stub with a closure (NOT returnUsing())
  • Functions\when('fn')->justReturn($val) — stub returning a fixed value
  • Functions\expect('fn')->once()->with(...) — assert call count and arguments
  • Use Functions\when() (not Functions\expect()) when you need argument-routing (e.g. get_role returning different values per argument) to avoid chaining ambiguity
  • Mockery matchers (e.g. \Mockery::type()) inside plain PHP arrays do not work with with() — use \Mockery::on(fn($arr) => ...) or \Mockery::any() instead
  • When mocking $wpdb, set $mock->prefix = 'wp_' explicitly — it is a public property, not a method

Adding a Feature

  1. Write the feature doc in docs/features/<feature-name>.md (data model, API, classes, test paths).
  2. Implement the classes under src/.
  3. Add template(s) under templates/ if needed.
  4. Write unit tests under tests/Unit/ mirroring the src/ directory structure.
  5. Run composer test — all tests must pass before the feature is complete.

CI

Gitea Actions (.gitea/workflows/ci.yml) runs on every push and pull request:

  • lint — PHPCS WordPress coding standards
  • static-analysis — PHPStan level 6
  • test — PHPUnit on PHP 8.1, 8.2, 8.3
  • no-debug — rejects commits with var_dump, error_log, etc. in src/