Files
formipay/RECOMMENDATION.md
dwindown 35569923a5 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>
2026-04-17 17:00:47 +07:00

470 lines
18 KiB
Markdown

# 🏗️ 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.*