docs: add comprehensive audit report and architectural recommendation
Checkpoint before implementation. Includes audit findings (FINDINGS.md), architectural recommendation (RECOMMENDATION.md), and existing code changes to Form, Order, Render, and form-action.js from recent development. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
469
RECOMMENDATION.md
Normal file
469
RECOMMENDATION.md
Normal file
@@ -0,0 +1,469 @@
|
||||
# 🏗️ Formipay — Architectural Recommendation
|
||||
|
||||
**Date:** April 17, 2026
|
||||
**Context:** Based on `FINDINGS.md` audit
|
||||
|
||||
---
|
||||
|
||||
## The Question
|
||||
|
||||
> **Rebuild the plugin with React (admin + frontend), or keep the current SSR shortcode + Vue admin approach and fix all findings?**
|
||||
|
||||
---
|
||||
|
||||
## TL;DR — The Recommendation
|
||||
|
||||
### **Option B: Incremental Modernization (Keep SSR + Vue, Fix & Upgrade)**
|
||||
|
||||
**Do NOT do a full rewrite.** Instead, adopt a **phased modernization strategy** that:
|
||||
|
||||
1. **Fixes all critical bugs immediately** (Phase 1 — weeks 1-2)
|
||||
2. **Introduces React only where it adds clear value** (Phase 2 — weeks 3-6)
|
||||
3. **Gradually migrates Vue admin → React** as features are touched (Phase 3 — ongoing)
|
||||
|
||||
This is the industry-standard approach for WordPress plugins at this stage. Here's why and how.
|
||||
|
||||
---
|
||||
|
||||
## Why NOT a Full React Rebuild
|
||||
|
||||
| Factor | Full React Rebuild | Incremental Modernization |
|
||||
|--------|--------------------|---------------------------|
|
||||
| **Time** | 3-4 months minimum | 2-4 weeks for critical fixes |
|
||||
| **Risk** | Complete rewrite = complete regression risk | Fixes are targeted and testable |
|
||||
| **Revenue** | No updates for 3-4 months | Continuous delivery |
|
||||
| **WordPress ecosystem** | Fighting against WP conventions | Working with WP conventions |
|
||||
| **SEO / Accessibility** | Client-side rendering = SEO problems for public forms | SSR = perfect SEO & accessibility |
|
||||
| **Complexity** | Need build pipeline, state management, API layer | Build on what works |
|
||||
| **Team onboarding** | Entire codebase unfamiliar | Familiar patterns + gradual React intro |
|
||||
|
||||
### Industry Precedent
|
||||
|
||||
- **WooCommerce** — Still PHP/SSR for storefront, React only for admin (block editor, settings). Did NOT rewrite frontend in React.
|
||||
- **Easy Digital Downloads** — Same approach. PHP templates + React for admin features.
|
||||
- **GiveWP** — PHP/SSR frontend, React for admin dashboard and form builder.
|
||||
- **Gravity Forms** — PHP/SSR rendering, React for the form builder only.
|
||||
|
||||
**The pattern is clear:** WordPress payment/e-commerce plugins keep **SSR for public-facing forms** (SEO, accessibility, speed, no-JS fallback) and use **React for admin UX** (form builder, dashboards, settings).
|
||||
|
||||
---
|
||||
|
||||
## Recommended Architecture
|
||||
|
||||
### What to KEEP (SSR / PHP)
|
||||
|
||||
```
|
||||
✅ Public form rendering (shortcode → PHP template)
|
||||
✅ Order processing & payment flow (PHP backend)
|
||||
✅ Email notifications (PHP wp_mail)
|
||||
✅ Database layer (custom tables via dbDelta)
|
||||
✅ Webhook handlers (REST routes in PHP)
|
||||
✅ Thank-you page (PHP template)
|
||||
```
|
||||
|
||||
**Why:** Server-side rendered forms are the **correct choice** for WordPress checkout forms. They provide:
|
||||
- Zero JavaScript dependency (forms work without JS)
|
||||
- Perfect SEO (crawlers see full HTML)
|
||||
- Fast initial paint (no JS bundle download needed)
|
||||
- Native WordPress shortcode/block integration
|
||||
- Accessibility out of the box (screen readers work)
|
||||
|
||||
### What to MIGRATE to React
|
||||
|
||||
```
|
||||
🔄 Admin form builder (currently partial Vue → full React)
|
||||
🔄 Admin dashboard / analytics (new)
|
||||
🔄 Admin order details view (currently Handlebars → React)
|
||||
🔄 Admin settings pages (currently WPCFTO → custom React)
|
||||
🔄 Gutenberg block (new — React is required)
|
||||
```
|
||||
|
||||
### What to ADD as React
|
||||
|
||||
```
|
||||
🆕 React-powered shortcode replacement (as <script> islands)
|
||||
🆕 React-based order tracking widget for customer portal
|
||||
🆕 React-based product catalog (optional)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Implementation Plan
|
||||
|
||||
### Phase 1: Critical Fixes & Stabilization (Weeks 1-2)
|
||||
|
||||
**Goal:** Make the existing plugin production-ready.
|
||||
|
||||
```
|
||||
Week 1 — Critical Bug Fixes:
|
||||
├── Fix Customer::update() undefined variables
|
||||
├── Fix Order::delete() $id → $order_id
|
||||
├── Fix Order::bulk_delete() loop variable
|
||||
├── Fix Email::send_email() class reference
|
||||
├── Fix Paypal::auto_cancel_order_on_timeout() import
|
||||
├── Fix BankTransfer unique_code triple-call
|
||||
├── Fix color field label ('Number' → 'Color')
|
||||
└── Add missing nonce checks (Customer::tabledata)
|
||||
|
||||
Week 2 — Performance & Security:
|
||||
├── Remove flush_rewrite_rules() from init → activation hook only
|
||||
├── Replace maybe_serialize() in cookies with json_encode()
|
||||
├── Add PayPal webhook signature verification
|
||||
├── Add rate limiting on public AJAX endpoints
|
||||
├── Cache currency/country JSON reads in static vars
|
||||
├── Add pagination to Customer::tabledata
|
||||
├── Optimize Order::tabledata queries (COUNT + GROUP BY)
|
||||
└── Add uninstall.php for cleanup
|
||||
```
|
||||
|
||||
### Phase 2: React Admin Foundation (Weeks 3-6)
|
||||
|
||||
**Goal:** Set up React build pipeline and migrate the most impactful admin pages.
|
||||
|
||||
```
|
||||
Week 3 — Build Pipeline:
|
||||
├── Set up @wordpress/scripts (wp-scripts) build system
|
||||
├── Configure webpack with React Fast Refresh
|
||||
├── Create React component library structure
|
||||
├── Set up API layer (fetch wrapper with nonce handling)
|
||||
└── Create admin page shell component (sidebar + routing)
|
||||
|
||||
Week 4 — Form Builder (highest admin ROI):
|
||||
├── Build drag-and-drop field palette (React)
|
||||
├── Build field settings panel (React)
|
||||
├── Build live preview canvas (React)
|
||||
├── Connect to existing PHP save endpoints
|
||||
└── Replace current Vue/Classic Editor metabox
|
||||
|
||||
Week 5 — Order Management & Dashboard:
|
||||
├── Build order list page with filters (React + TanStack Table)
|
||||
├── Build order detail view (replace Handlebars templates)
|
||||
├── Build status change workflow with timeline
|
||||
├── Build simple analytics dashboard (orders, revenue, charts)
|
||||
└── Build notification log viewer
|
||||
|
||||
Week 6 — Settings & Product Editor:
|
||||
├── Build global settings page (replace WPCFTO dependency)
|
||||
├── Build product editor page (replace classic editor metaboxes)
|
||||
├── Build coupon editor page
|
||||
├── Build access items manager
|
||||
└── Build license management page
|
||||
```
|
||||
|
||||
### Phase 3: Frontend Enhancements (Weeks 7-10)
|
||||
|
||||
**Goal:** Add React-powered frontend features while keeping SSR as the default.
|
||||
|
||||
```
|
||||
Week 7-8 — React Island Architecture:
|
||||
├── Create a render_php() method (existing SSR — default)
|
||||
├── Create a render_react() method (new — optional)
|
||||
├── Build React form renderer component
|
||||
├── Implement "island hydration" — React attaches to SSR HTML
|
||||
├── Add setting: "Render Mode: Classic (SSR) | Modern (React)"
|
||||
└── Add multi-step form navigation (missing in current SSR)
|
||||
|
||||
Week 9 — Gutenberg Block:
|
||||
├── Register formipay/form block with block.json
|
||||
├── Block renders shortcode server-side in edit.js preview
|
||||
├── Full React experience in editor
|
||||
├── Settings panel in InspectorControls
|
||||
└── Replace shortcode-only workflow
|
||||
|
||||
Week 10 — Customer Portal:
|
||||
├── Build customer order history page (React)
|
||||
├── Build order detail / download access page (React)
|
||||
├── Build access link request form (React)
|
||||
├── Integrate with WordPress user accounts
|
||||
└── Shortcode [formipay_my_orders] for portal
|
||||
```
|
||||
|
||||
### Phase 4: Complete Missing Features (Weeks 11-16)
|
||||
|
||||
```
|
||||
Week 11-12 — Payment & Commerce:
|
||||
├── Implement ExchangeRateAPI (currently empty)
|
||||
├── Implement License API endpoints (currently stubs)
|
||||
├── Add Stripe payment gateway
|
||||
├── Add tax calculation engine
|
||||
└── Add product variations on frontend
|
||||
|
||||
Week 13-14 — Stock & Shipping:
|
||||
├── Implement stock management (decrement, validation, messages)
|
||||
├── Add weight-based shipping calculation
|
||||
├── Add shipping zone support
|
||||
└── Add order fulfillment workflow
|
||||
|
||||
Week 15-16 — Advanced Features:
|
||||
├── Build donation form mode (pay-what-you-want, suggested amounts)
|
||||
├── Add PDF invoice generation
|
||||
├── Add CSV export for orders/customers
|
||||
├── Add webhook notification system
|
||||
└── Add analytics & reporting dashboard
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Technical Architecture Diagram
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ WordPress Plugin │
|
||||
│ │
|
||||
│ ┌──────────────────────┐ ┌──────────────────────────┐ │
|
||||
│ │ PHP Backend Core │ │ React Admin (wp-scripts)│ │
|
||||
│ │ │ │ │ │
|
||||
│ │ • Custom Post Types │◄──►│ • Form Builder │ │
|
||||
│ │ • Custom DB Tables │ │ • Order Management │ │
|
||||
│ │ • Payment Gateways │ │ • Product Editor │ │
|
||||
│ │ • Email System │ │ • Settings Pages │ │
|
||||
│ │ • REST API Endpoints│ │ • Dashboard/Analytics │ │
|
||||
│ │ • Webhook Handlers │ │ • License Manager │ │
|
||||
│ │ • Cron Jobs │ │ • Notification Log │ │
|
||||
│ └──────────┬───────────┘ └──────────────────────────┘ │
|
||||
│ │ │
|
||||
│ ┌──────────▼───────────┐ ┌──────────────────────────┐ │
|
||||
│ │ SSR Form Renderer │ │ React Frontend Islands │ │
|
||||
│ │ (PHP + Shortcode) │ │ (Optional Enhancement) │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ • [formipay] render │ │ • Multi-step navigation │ │
|
||||
│ │ • Thank-you page │ │ • Real-time validation │ │
|
||||
│ │ • Payment confirm │ │ • Customer portal │ │
|
||||
│ │ • No-JS fallback ✅ │ │ • Gutenberg block │ │
|
||||
│ └──────────────────────┘ └──────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────┐ │
|
||||
│ │ Shared API Layer (WordPress REST API + admin-ajax) │ │
|
||||
│ │ • /wp-json/formipay/v1/* │ │
|
||||
│ │ • admin-ajax.php actions (backward compat) │ │
|
||||
│ └──────────────────────────────────────────────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Build Toolchain
|
||||
|
||||
```
|
||||
formipay/
|
||||
├── package.json # @wordpress/scripts + deps
|
||||
├── webpack.config.js # Extend wp-scripts config
|
||||
├── .eslintrc.js # ESLint with WP rules
|
||||
├── .prettierrc # Prettier config
|
||||
├── tsconfig.json # TypeScript (recommended)
|
||||
│
|
||||
├── src/ # React source code
|
||||
│ ├── admin/ # Admin React app
|
||||
│ │ ├── index.js # Entry point
|
||||
│ │ ├── components/ # Shared components
|
||||
│ │ │ ├── DataTable/ # Reusable table component
|
||||
│ │ │ ├── SettingsPanel/ # Settings form builder
|
||||
│ │ │ ├── Modal/ # Confirmation modals
|
||||
│ │ │ └── StatusBadge/ # Order status badges
|
||||
│ │ ├── pages/ # Page components
|
||||
│ │ │ ├── Dashboard/
|
||||
│ │ │ ├── FormBuilder/
|
||||
│ │ │ ├── Orders/
|
||||
│ │ │ ├── Products/
|
||||
│ │ │ ├── Customers/
|
||||
│ │ │ ├── Coupons/
|
||||
│ │ │ ├── Licenses/
|
||||
│ │ │ ├── AccessItems/
|
||||
│ │ │ └── Settings/
|
||||
│ │ ├── hooks/ # Custom React hooks
|
||||
│ │ │ ├── useOrders.js
|
||||
│ │ │ ├── useProducts.js
|
||||
│ │ │ └── useSettings.js
|
||||
│ │ └── api/ # API client
|
||||
│ │ ├── client.js # Fetch wrapper with nonce
|
||||
│ │ ├── orders.js
|
||||
│ │ ├── products.js
|
||||
│ │ └── settings.js
|
||||
│ │
|
||||
│ ├── frontend/ # Frontend React islands
|
||||
│ │ ├── blocks/ # Gutenberg blocks
|
||||
│ │ │ └── formipay-form/
|
||||
│ │ │ ├── block.json
|
||||
│ │ │ ├── edit.jsx
|
||||
│ │ │ └── view.js
|
||||
│ │ └── widgets/ # Embeddable widgets
|
||||
│ │ ├── CustomerPortal/
|
||||
│ │ └── OrderTracker/
|
||||
│ │
|
||||
│ └── shared/ # Shared between admin/frontend
|
||||
│ ├── utils/
|
||||
│ └── constants/
|
||||
│
|
||||
├── assets/build/ # Compiled output (gitignored)
|
||||
│ ├── admin.bundle.js
|
||||
│ ├── admin.bundle.css
|
||||
│ ├── frontend.bundle.js
|
||||
│ └── blocks/
|
||||
│
|
||||
├── includes/ # PHP backend (existing, fixed)
|
||||
├── admin/ # PHP admin pages (kept for PHP render)
|
||||
├── public/ # Public templates (SSR)
|
||||
├── vendor/ # Composer dependencies (new)
|
||||
└── templates/ # WordPress templates
|
||||
```
|
||||
|
||||
### `package.json` (minimal)
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "formipay",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "wp-scripts build",
|
||||
"start": "wp-scripts start",
|
||||
"lint:js": "wp-scripts lint-js src/",
|
||||
"lint:css": "wp-scripts lint-style",
|
||||
"format": "wp-scripts format src/"
|
||||
},
|
||||
"dependencies": {
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"@wordpress/api-fetch": "^6.0.0",
|
||||
"@wordpress/components": "^25.0.0",
|
||||
"@wordpress/data": "^9.0.0",
|
||||
"@wordpress/element": "^5.0.0",
|
||||
"@wordpress/i18n": "^4.0.0",
|
||||
"@tanstack/react-table": "^8.0.0",
|
||||
"@tanstack/react-query": "^5.0.0",
|
||||
"recharts": "^2.10.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@wordpress/scripts": "^27.0.0"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## React Frontend Integration Strategy
|
||||
|
||||
### Pattern: React Islands (Hybrid SSR + React)
|
||||
|
||||
The key pattern is **"islands of interactivity"** — the PHP renders the initial HTML (SSR), and React optionally hydrates specific sections:
|
||||
|
||||
```php
|
||||
// Render.php — The shortcode handler
|
||||
public function shortcode($atts) {
|
||||
// ... existing SSR rendering (default) ...
|
||||
|
||||
// Option: If React mode is enabled, render a mount point instead
|
||||
if ($render_mode === 'react') {
|
||||
return sprintf(
|
||||
'<div id="formipay-react-form-%d" data-form-id="%d" data-nonce="%s"></div>',
|
||||
$post_id,
|
||||
$post_id,
|
||||
wp_create_nonce('formipay_order_submit')
|
||||
);
|
||||
}
|
||||
|
||||
// Default: existing PHP-rendered form (SSR)
|
||||
return $this->render_php_form($post_id);
|
||||
}
|
||||
```
|
||||
|
||||
```jsx
|
||||
// src/frontend/widgets/FormRenderer.jsx
|
||||
import { createRoot } from '@wordpress/element';
|
||||
import Form from './components/Form';
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
document.querySelectorAll('[id^="formipay-react-form-"]').forEach(el => {
|
||||
const formId = parseInt(el.dataset.formId);
|
||||
const nonce = el.dataset.nonce;
|
||||
createRoot(el).render(<Form formId={formId} nonce={nonce} />);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
This gives you:
|
||||
- **Backward compatibility** — existing `[formipay]` shortcodes keep working with SSR
|
||||
- **Opt-in React** — new features use React when enabled
|
||||
- **Gutenberg block** — renders React in editor, SSR or React on frontend
|
||||
- **No lock-in** — each form can use either mode independently
|
||||
|
||||
---
|
||||
|
||||
## What to Do With the Vue Code
|
||||
|
||||
The existing Vue admin code (`admin/assets/vue/`) should be **deprecated, not deleted immediately**:
|
||||
|
||||
1. **Keep** Vue code working during Phase 1 (critical fixes)
|
||||
2. **Build** React equivalents in Phase 2 alongside Vue
|
||||
3. **Switch** admin pages to React one at a time (form builder first)
|
||||
4. **Remove** Vue code once all pages are migrated in Phase 3
|
||||
|
||||
Do NOT try to mix Vue and React on the same page — they'll conflict. Migrate page-by-page.
|
||||
|
||||
---
|
||||
|
||||
## Gutenberg Block Strategy
|
||||
|
||||
```jsx
|
||||
// src/frontend/blocks/formipay-form/block.json
|
||||
{
|
||||
"apiVersion": 3,
|
||||
"name": "formipay/form",
|
||||
"title": "Formipay Form",
|
||||
"category": "widgets",
|
||||
"attributes": {
|
||||
"formId": { "type": "number", "default": 0 },
|
||||
"renderMode": { "type": "string", "default": "ssr" }
|
||||
},
|
||||
"supports": {
|
||||
"html": false,
|
||||
"align": true
|
||||
},
|
||||
"editorScript": "file:./index.js",
|
||||
"editorStyle": "file:./index.css",
|
||||
"style": "file:./style-index.css",
|
||||
"render": "file:./render.php"
|
||||
}
|
||||
```
|
||||
|
||||
The `render.php` file uses Server-Side Rendering (required by WordPress for blocks), which calls the existing PHP form renderer. The editor experience (`edit.jsx`) is fully React.
|
||||
|
||||
---
|
||||
|
||||
## Testing Strategy
|
||||
|
||||
```
|
||||
Phase 1: Manual testing of all bug fixes
|
||||
Phase 2: PHPUnit for backend + Jest for React components
|
||||
Phase 3: E2E tests with Playwright for critical flows
|
||||
Phase 4: CI/CD with GitHub Actions
|
||||
|
||||
Coverage targets:
|
||||
├── Backend (PHP): 80% on payment + order paths
|
||||
├── Admin (React): 70% on components
|
||||
├── Frontend: E2E for form submission, payment, thank-you
|
||||
└── API: Integration tests for all REST endpoints
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Cost-Benefit Summary
|
||||
|
||||
| Approach | Time | Cost | Risk | Deliverable |
|
||||
|----------|------|------|------|-------------|
|
||||
| **Full React rebuild** | 3-4 months | Very high | Very high | Complete rewrite, likely with new bugs |
|
||||
| **Keep PHP + fix only** | 2-3 weeks | Low | Low | Fixes bugs, no UX improvement |
|
||||
| **Incremental modernization** ✅ | 4-6 weeks for Phases 1-2 | Medium | Low-Medium | Bugs fixed + modern admin UX |
|
||||
|
||||
### Recommended: **Incremental Modernization**
|
||||
|
||||
This approach:
|
||||
1. **Delivers value immediately** — critical bugs fixed in Week 1
|
||||
2. **Reduces risk** — changes are targeted and testable
|
||||
3. **Follows WordPress conventions** — SSR forms, React admin
|
||||
4. **Enables future growth** — React foundation for new features
|
||||
5. **Matches industry patterns** — same approach as WooCommerce, GiveWP, Gravity Forms
|
||||
|
||||
---
|
||||
|
||||
*End of recommendation.*
|
||||
Reference in New Issue
Block a user