docs: add comprehensive CLAUDE.md for future AI assistance

Add detailed documentation covering plugin architecture, subsystems, workflows, and development practices. Includes GSD workflow requirement for all code changes.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-23 23:10:44 +09:00
parent 1b41b72a3d
commit 369870ef00

277
CLAUDE.md Normal file
View File

@@ -0,0 +1,277 @@
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Project Overview
Digital Dabei Job Manager is a WordPress plugin providing a closed job board for "digital dabei Hamburg". External organizations (providers) self-register and manage job listings. Mentors (existing subscribers) view and apply to jobs. All jobs require admin moderation before publication.
**Core principle**: Every job goes through admin approval before mentors see it. The moderation flow is the trust layer protecting mentors from spam.
## Development Environment
- **Platform**: Local WP (WordPress development environment)
- **WordPress**: 6.0+, PHP 7.4+
- **Required Plugins**: ACF Pro, Formidable Forms Pro, Elementor Pro
- **Email**: WP Mail SMTP on production; disabled in Local WP dev environment
## Development Workflow with GSD
**IMPORTANT**: Use `/gsd` commands for all code-related work in this repository.
The GSD (Get Stuff Done) workflow provides:
- Structured planning and execution phases
- Automatic verification of changes
- State management across sessions
- Parallel execution when possible
Common commands:
- `/gsd:progress` - Check current state and next steps
- `/gsd:plan-phase` - Plan implementation for a phase
- `/gsd:execute-phase` - Execute all plans in a phase
- `/gsd:help` - View all available GSD commands
## Architecture
### Plugin Entry Point
The plugin follows WordPress singleton pattern with class-based initialization:
1. `ddhh-job-manager.php` - Main plugin file that:
- Loads Action Scheduler vendor library **first** (required for async operations)
- Defines constants (DDHH_JM_VERSION, DDHH_JM_PLUGIN_DIR, etc.)
- Requires all class files from `includes/`
- Initializes via `DDHH_JM_Job_Manager::get_instance()` on `plugins_loaded` hook
2. `includes/class-ddhh-job-manager.php` - Singleton orchestrator that initializes all subsystems via `init_hooks()`
### Core Subsystems
The plugin is organized into focused class files in `includes/`:
**Foundation Layer**:
- `class-post-types.php` - Registers `job_offer` CPT with custom capabilities
- `class-roles.php` - Manages `ddhh_provider` role with restricted capabilities
- `class-acf-fields.php` - Programmatically registers ACF field groups for job metadata
- `class-activator.php` / `class-deactivator.php` - Plugin lifecycle hooks
**User Management**:
- `class-formidable.php` - Integration layer for all Formidable Forms (registration, job submission, edit, deactivation, application). Uses form keys like 'provider_registration', 'job_submission', etc.
- `class-access-control.php` - Blocks providers from WP-Admin, enforces login requirements on job archives
- `class-user-preferences.php` - Manages mentor opt-in preferences for job notifications
**Job Workflows**:
- `class-dashboard.php` - Provides `[ddhh_provider_dashboard]` shortcode displaying provider's jobs
- `class-pages.php` - Creates/manages plugin pages (dashboard, login) via option storage
- `class-archive.php` - Filters job queries to show only published jobs to appropriate users
- `class-template.php` - Handles single job display and contact form modal
**Notifications & Async Processing**:
- `class-notifications.php` - Email system triggered by WordPress hooks (`ddhh_job_submitted`, `transition_post_status`, `frm_after_create_entry`)
- `class-scheduler.php` - Action Scheduler wrapper for async batch email processing (chunks of 50 users)
**Admin Experience**:
- `class-admin-ui.php` - Enhances admin screens with custom columns, quick links, status indicators
### Custom Roles & Capabilities
**ddhh_provider role**: Restricted role for external organizations
- Can create/edit/delete only their own `job_offer` posts
- Cannot access WP-Admin (redirected to frontend dashboard)
- Can edit their own profile (`profile.php` access allowed)
**Capability mapping** (in `class-post-types.php`):
- `edit_job_offer` - Owner can edit their own jobs
- `delete_job_offer` - Owner can delete their own jobs
- `read_job_offer` - Users can read published jobs
- Standard WordPress `map_meta_cap` filter enforces ownership
### Formidable Forms Integration
The plugin uses 5 Formidable forms, identified by form keys:
1. **provider_registration** (F1) - Creates user with `ddhh_provider` role, auto-login
2. **job_submission** (F2) - Creates `job_offer` post with `pending` status, maps ACF fields
3. **job_edit** (F3) - Updates existing job (ownership validated), preserves submission date
4. **job_deactivation** (F4) - Sets status to `draft`, captures deactivation reason
5. **job_application** (F5) - Mentor applies to job, emails provider contact address
**Form hooks** (`class-formidable.php`):
- Registration: `frm_after_create_entry` → auto-login → redirect to dashboard
- Job submission: `frm_after_create_entry` → fires `ddhh_job_submitted` action → admin notification
- Job edit: `frm_after_update_entry` → fires `ddhh_job_edited` action → admin notification
- Application: `frm_after_create_entry` → emails provider's contact email from ACF field
### Email Notification System
**Immediate notifications** (`class-notifications.php`):
- Admin receives email on job submission with edit/view links
- Admin receives email on job edit with change summary
- Admin receives email on deactivation with reason
- Provider receives email when mentor applies (via Formidable)
**Async batch notifications** (`class-scheduler.php`):
- Mentor notification on job publish uses Action Scheduler
- Users are queried for `ddhh_jm_notification_optin` meta
- Batched into groups of 50 to prevent email provider limits
- Each batch scheduled as separate `ddhh_jm_send_mentor_notification_batch` action
### Access Control Layers
1. **WP-Admin lockout**: Providers redirected to dashboard unless accessing `profile.php` or AJAX
2. **Dashboard protection**: `template_redirect` hook checks user role, redirects non-providers
3. **Archive protection**: Jobs require login; only `publish` status shown to mentors
4. **Single job protection**: Login required to view job details
5. **Ownership validation**: Forms validate current user owns the job before editing/deactivation
### Template System
**Frontend templates** (`templates/`):
- `provider-dashboard.php` - Displays provider's jobs in table format with status badges and action links
**Elementor integration**:
- Job archive uses Elementor Loop Grid (no custom template file)
- Job detail page uses Elementor single post template with ACF dynamic tags
- Contact form modal injected via `the_content` filter in `class-template.php`
### Job Lifecycle
```
Provider submits → pending → Admin reviews → publish → Mentors see + notified
Admin can reject → trash
Provider deactivates → draft (with reason stored in meta)
```
**Status hooks**:
- `ddhh_job_submitted` - Fired after new job metadata saved (form entry ID passed)
- `ddhh_job_edited` - Fired after job update metadata saved (form entry ID passed)
- `transition_post_status` - Used for publish detection and deactivation detection
### ACF Field Groups
Programmatically registered in `class-acf-fields.php`:
- **Job Details**: `job_location`, `job_type`, `job_deadline` (date picker), `contact_email`
- **Deactivation**: `deactivation_reason`, `deactivation_date`
- **Metadata**: `submission_date` (preserved during edits)
All fields support German labels matching site language.
## Development Workflow
### Testing Locally
Since email is disabled in Local WP, test email functionality by:
1. Checking Action Scheduler status: WP Admin → Tools → Scheduled Actions
2. Monitoring logs: `error_log()` calls throughout notification classes
3. Using a plugin like WP Mail Logging to capture emails during dev
### Working with Forms
Formidable forms are managed through the Formidable UI. When referencing forms in code:
- Use form keys (e.g., 'job_submission') not IDs
- Form ID lookup happens via `FrmForm::getOne('form_key')`
- Field IDs are stored in form configuration, not hardcoded
### Modifying Email Templates
Email templates are inline in `class-notifications.php`:
- Admin emails use `wp_mail()` with HTML content
- Mentor notification emails use `wp_mail()` with plain text
- All emails include job title, provider name, and relevant links
- Date formatting: Use `get_field()` for ACF dates, format with German locale
### Adding New Notifications
1. Identify triggering event (form submission, status change, custom action)
2. Add notification method to `class-notifications.php`
3. Hook into appropriate action in `setup_hooks()`
4. For batch processing, use `DDHH_JM_Scheduler::schedule_mentor_notification_batch()`
## Common Tasks
### Debugging Action Scheduler
```bash
# View scheduled actions in WP CLI
wp action-scheduler list --status=pending
wp action-scheduler list --status=failed
# Run pending actions manually
wp action-scheduler run --batch-size=10
# Clean up old actions
wp action-scheduler clean --days=90
```
### Checking Provider Permissions
Providers should NOT be able to:
- Access WP-Admin (except profile.php)
- Edit other providers' jobs
- Publish jobs directly (must be pending)
- View unpublished jobs by other providers
### Verifying Job Moderation Flow
1. Log in as provider → Submit job → Should create `pending` post
2. Admin receives email with job details and moderation links
3. Admin publishes job → Opted-in mentors receive notification (async batches)
4. Provider sees published job in dashboard
5. Mentors can view and apply to job
### Date Field Handling
Job deadlines use ACF date picker:
- Format conversion in Formidable forms: Slashes auto-converted to dots for display
- Before submission: Dots converted back to ISO format (YYYY-MM-DD)
- Display: Use `get_field('job_deadline')` returns 'Ymd', format with `date_i18n()`
- Validation: Date fields are optional (empty string is valid)
### Logo Auto-Cropping
Featured images (logos) auto-crop to 200×200px on upload:
- Handled by `class-post-types.php` registering 'job-logo' image size
- Uses WordPress `add_image_size()` with hard crop enabled
- Images uploaded via Formidable forms trigger standard WP media processing
## Project State
**Currently**: Phase 6 (Email Notifications) is mostly complete. Phase 7 (Testing & Polish) is next.
**What's working**:
- Provider registration and authentication
- Job submission, editing, deactivation workflows
- Admin moderation and notifications
- Mentor job browsing and applications
- Opt-in preferences for mentor notifications
- Action Scheduler integration for async processing
**What's pending**:
- Phase 6.3: Async batch email processing on job publish (implementation in progress)
- Phase 7: End-to-end testing and production deployment prep
**Documentation**: See `.planning/` for detailed project documentation:
- `PROJECT.md` - Requirements and context
- `ROADMAP.md` - Phase breakdown and progress
- `STATE.md` - Current work and blockers
- `phases/` - Detailed plans and summaries for each phase
## Code Standards
- **WordPress Coding Standards**: Follow WordPress PHP coding standards
- **Text Domain**: Use `ddhh-job-manager` for all translatable strings
- **German Language**: All user-facing text in German
- **Security**: Validate ownership, escape output, verify nonces in forms
- **Hook Naming**: Use `ddhh_jm_` prefix for custom actions/filters
- **Class Naming**: Use `DDHH_JM_` prefix, one class per file
- **Static Methods**: Use static methods for classes that don't maintain state
- **Direct Exit**: Always include `defined( 'ABSPATH' ) || exit;` at top of PHP files
## Critical Files to Review Before Major Changes
- `ddhh-job-manager.php` - Plugin initialization order matters (Action Scheduler first)
- `class-ddhh-job-manager.php` - Hook registration sequence
- `class-formidable.php` - Form IDs and field mappings
- `class-notifications.php` - Email templates and triggering logic
- `class-access-control.php` - Security boundaries for providers
- `class-post-types.php` - Capability mapping for `job_offer` posts