diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md index f5b7fe0..3673fc7 100644 --- a/.planning/ROADMAP.md +++ b/.planning/ROADMAP.md @@ -19,6 +19,7 @@ None - [x] **Phase 7: Captcha & Validation** - reCAPTCHA v2/v3, hCaptcha, inline validation, i18n - [x] **Phase 8: Bug Fixes & Legacy Parity** - Session bug fix, additional work sections, Sonstiges free text - [x] **Phase 9: Internationalization** - i18n with gettext, German/English translation files +- [x] **Phase 10: Post-Release Fixes** - Form submit 404, handler timing, CPT meta box ## Phase Details @@ -117,6 +118,16 @@ Plans: - [x] 09-01: i18n infrastructure, text domain loading, and admin/infrastructure string wrapping - [x] 09-02: Form-facing string wrapping, JS localization, email locale forcing, translation files +### Phase 10: Post-Release Fixes +**Goal**: Fix three critical bugs found during manual testing: 404 on form submit (reserved query vars), form handler not firing (init timing), empty CPT entries (missing meta box) +**Depends on**: Phase 9 +**Research**: None (bugs identified through manual testing) +**Plans**: 1/1 complete +**Status**: Complete + +Plans: +- [x] 10-01: Fix form submit 404, handler init timing, and add CPT detail meta box + ## Progress | Phase | Plans Complete | Status | Completed | @@ -130,3 +141,4 @@ Plans: | 7. Captcha & Validation | 1/1 | Complete | 2026-01-16 | | 8. Bug Fixes & Legacy Parity | 2/2 | Complete | 2026-02-06 | | 9. Internationalization | 2/2 | Complete | 2026-02-07 | +| 10. Post-Release Fixes | 1/1 | Complete | 2026-02-07 | diff --git a/.planning/STATE.md b/.planning/STATE.md index a19ea92..d25f4de 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -5,23 +5,23 @@ See: .planning/PROJECT.md (updated 2026-01-16) **Core value:** Email format identical to legacy — office staff workflow depends on the exact HTML table structure. -**Current focus:** Gap closure phases 8-9 (audit fixes before v1.0 completion) +**Current focus:** Post-v1.0 bug fixes (manual testing discoveries) ## Current Position -Phase: 9 of 9 (Internationalization) -Plan: 2 of 2 complete +Phase: 10 of 10 (Post-Release Fixes) +Plan: 1 of 1 complete Status: Phase complete ✓ -Last activity: 2026-02-06 — Completed 09-02-PLAN.md (form strings and translation files) +Last activity: 2026-02-07 — Fixed form submit 404, handler timing, CPT meta box -Progress: ██████████ 100% (10/10 plans) +Progress: ██████████ 100% (11/11 plans) ## Performance Metrics **Velocity:** -- Total plans completed: 10 -- Average duration: ~22 min per plan -- Total execution time: ~4 hours +- Total plans completed: 11 +- Average duration: ~24 min per plan +- Total execution time: ~4.5 hours **By Phase:** @@ -36,10 +36,12 @@ Progress: ██████████ 100% (10/10 plans) | 7 | 1 | Captcha verification and inline validation | | 8 | 2/2 | Bug fixes & legacy parity (gap closure) | | 9 | 2/2 | Internationalization (gap closure) ✓ | +| 10 | 1/1 | Post-release fixes (manual testing bugs) ✓ | **Overall Trend:** - Phases 1-7 completed successfully - Milestone audit found 4 gaps requiring phases 8-9 +- Manual testing found 3 runtime bugs requiring phase 10 - No blockers encountered ## Accumulated Context @@ -67,6 +69,9 @@ Recent decisions affecting current work: | 9-02 | Force German locale for email generation via switch_to_locale() | Email content must ALWAYS be German for office staff workflow | | 9-02 | Email subject and static content NOT wrapped in gettext | Email format must match legacy exactly - subject and static strings stay hardcoded German | | 9-02 | wp_localize_script() for JS validation messages | WordPress-native approach, handles locale selection and caching automatically | +| 10 | Rename day/month/year fields to umzug_day/umzug_month/umzug_year | WordPress reserved query vars caused 404 on form POST | +| 10 | Move handler instantiation to init_hooks() | init callback too late for handler's own init hook | +| 10 | Add CPT submission details meta box | No way to view stored submission data in admin | ### Deferred Issues @@ -80,7 +85,7 @@ None. ## Session Continuity -Last session: 2026-02-06T14:58:08Z -Stopped at: Completed 09-02-PLAN.md (form strings and translation files) - PHASE 9 COMPLETE ✓ +Last session: 2026-02-07 +Stopped at: Documented phase 10 post-release fixes - PHASE 10 COMPLETE ✓ Resume file: None -Next up: All phases complete! Plugin ready for v1.0 release. +Next up: All phases complete! Plugin shipped and working end-to-end. diff --git a/.planning/phases/10-post-release-fixes/10-01-SUMMARY.md b/.planning/phases/10-post-release-fixes/10-01-SUMMARY.md new file mode 100644 index 0000000..ddbc4d4 --- /dev/null +++ b/.planning/phases/10-post-release-fixes/10-01-SUMMARY.md @@ -0,0 +1,167 @@ +--- +phase: 10 +plan: 01 +type: summary +subsystem: bugfix +tags: [bugfix, form-submission, reserved-query-vars, init-timing, meta-box, standalone-template, cpt] +requires: [09-02] +provides: + - "Working form submission on standalone page (no 404)" + - "Form handler fires reliably via init_hooks() timing fix" + - "CPT detail meta box showing submission data in admin" + - "Standalone template fallback via shortcode detection" +affects: [] +tech-stack: + added: [] + patterns: + - "Prefix form fields to avoid WordPress reserved query vars" + - "Instantiate handlers in init_hooks() not inside init callback" + - "Shortcode content detection for template fallback" +key-files: + created: + - "templates/form-page.php" + modified: + - "umzugsliste.php" + - "includes/class-form-handler.php" + - "includes/class-date-helpers.php" + - "includes/class-email-generator.php" + - "includes/class-cpt.php" + - "includes/class-settings.php" + - "includes/class-shortcode.php" + - "includes/class-captcha.php" + - "assets/css/form.css" + - "assets/js/form.js" + - "languages/siegel-umzugsliste-de_DE.po" + - "languages/siegel-umzugsliste-de_DE.mo" + - "languages/siegel-umzugsliste.pot" +decisions: + - id: prefix-date-fields + choice: "Rename day/month/year form fields to umzug_day/umzug_month/umzug_year" + rationale: "WordPress registers day, month, year as public query variables. POST data with these names causes WP to interpret the request as a date archive, returning a 404 instead of processing the form." + - id: handler-init-timing + choice: "Move form handler instantiation from init callback to init_hooks()" + rationale: "Instantiating inside an init callback meant the handler's own init hook registered too late (after init had already fired). Moving to init_hooks() ensures handle_submission registers before init fires." + - id: template-fallback + choice: "Detect [umzugsliste] shortcode in page content when form_page_id option is unset" + rationale: "Allows standalone template to work even when the settings page hasn't been configured, improving first-run experience." + - id: cpt-meta-box + choice: "Add submission details meta box to CPT entries" + rationale: "Previously CPT entries stored data but had no way to view it in admin. Meta box shows addresses, furniture details, additional work, and status." +metrics: + duration: "~55 min (across 2 commits)" + completed: "2026-02-07" +--- + +# Phase 10 Plan 01: Post-Release Fixes Summary + +**Fixed three critical bugs discovered during manual testing of the standalone form page: 404 on submit, form handler not firing, and empty CPT entries** + +## Performance + +- **Duration:** ~55 min (across 2 sessions) +- **Completed:** 2026-02-07 +- **Commits:** 2 (`c0021be`, `64caccc`) +- **Files modified:** 14 (first commit), 9 (second commit) + +## Context + +After the v1.0 milestone audit passed (9/9 requirements, 10/10 integration, 5/5 flows), manual testing of the standalone form page revealed three critical issues that prevented actual form submission from working end-to-end. + +## Bug Fixes + +### Bug 1: 404 on Form Submit + +**Problem:** Submitting the form on the standalone page returned a WordPress 404 page instead of processing the submission. + +**Root Cause:** The form used `day`, `month`, and `year` as field names. WordPress registers these as [public query variables](https://developer.wordpress.org/reference/classes/wp/parse_request/) — when present in POST data, WordPress interpreted the request as a date archive query, which matched no posts and returned 404. + +**Fix:** Renamed all date fields to `umzug_day`, `umzug_month`, `umzug_year` across form renderer, form handler, date helpers, and email generator. The `umzug_` prefix avoids collision with any WordPress reserved query vars. + +**Files:** `class-form-renderer.php`, `class-form-handler.php`, `class-date-helpers.php`, `class-email-generator.php` + +### Bug 2: Form Handler Not Firing + +**Problem:** Even after fixing the 404, the form handler's `handle_submission()` method never executed. + +**Root Cause:** `Umzugsliste_Form_Handler` was instantiated inside an `add_action('init', ...)` callback in `umzugsliste.php`. The handler's constructor registered its own `init` hook for `handle_submission`, but by the time the constructor ran (during `init`), WordPress had already started firing `init` callbacks — so the handler's hook registered too late. + +**Fix:** Moved form handler instantiation to `init_hooks()` method which runs during plugin bootstrap, before `init` fires. This ensures `handle_submission` is registered on `init` at the correct time. + +**File:** `umzugsliste.php` + +### Bug 3: Empty CPT Entries in Admin + +**Problem:** CPT submission entries were stored in the database but showed no data when viewed in the WordPress admin. + +**Root Cause:** No meta box existed to display the stored post meta fields. + +**Fix:** Added `Umzugsliste_CPT::add_meta_boxes()` method that registers a "Submission Details" meta box. The `render_meta_box()` callback displays: +- Moving date and addresses (from/to) +- Furniture items with quantities and cbm values per room +- Additional work sections (Montage, Schrank, etc.) +- Submission status and timestamps + +All meta box strings include German translations in the .po/.mo files. + +**File:** `includes/class-cpt.php`, `languages/siegel-umzugsliste-de_DE.po`, `languages/siegel-umzugsliste-de_DE.mo` + +## Additional Improvements (Commit `c0021be`) + +These were bundled with the standalone form page feature in the first commit: + +- **Standalone form page template** (`templates/form-page.php`) — Bypasses theme, renders form in a clean layout +- **Admin setting for form page** — `form_page_id` option with auto-creation on plugin activation +- **Standalone template fallback** — Detects `[umzugsliste]` shortcode in page content when `form_page_id` is unset +- **reCAPTCHA v3 double-submission fix** — Prevented duplicate token requests +- **jQuery dependency removed** — Form JS is now vanilla JavaScript +- **Form CSS/JS overhaul** — Improved responsive layout and interaction patterns + +## Decisions Made + +**Prefix date fields with `umzug_`:** +- Avoids all WordPress reserved query variables +- Consistent naming convention for plugin-specific fields +- Minimal code change (find-and-replace across 4 files) + +**Handler instantiation timing:** +- Move to `init_hooks()` instead of inside `init` callback +- Follows WordPress best practice: register hooks during plugin load, not inside other hooks + +**Template fallback via shortcode detection:** +- `has_shortcode(get_post()->post_content, 'umzugsliste')` as fallback +- Works without settings configuration for better first-run experience + +**CPT meta box for submission details:** +- Read-only display (no editing of submitted data) +- German translations for all field labels +- Grouped display: addresses, furniture by room, additional work, status + +## Commits + +1. **`c0021be`** — `feat: add standalone form page, close all audit gaps, pass v1.0 milestone` + - Standalone template, admin setting, CSS/JS overhaul, reCAPTCHA fix + - 14 files changed, 2191 insertions, 1202 deletions + +2. **`64caccc`** — `fix: resolve form submission issues and add CPT detail view` + - Date field renaming, handler timing fix, template fallback, meta box + - 9 files changed, 261 insertions, 23 deletions + +## Deviations from Plan + +N/A — This phase documents bugs found and fixed during manual testing, not a pre-planned phase. + +## Lessons Learned + +1. **Always check WordPress reserved query vars** when naming form fields. The full list is in `WP::$public_query_vars` and includes common words like `day`, `month`, `year`, `name`, `page`, `author`, `search`, `tag`. + +2. **Don't register hooks inside hook callbacks** unless you understand the timing. Instantiating a class inside `init` that itself hooks into `init` will miss the current `init` cycle. + +3. **Automated audits don't catch runtime bugs.** The v1.0 audit checked code structure and integration points, but the 404 and timing bugs only surfaced during actual form submission testing. + +## Next Steps + +No follow-up work required. All three bugs are resolved and the standalone form page works end-to-end. + +--- +*Phase: 10-post-release-fixes* +*Completed: 2026-02-07*