Fixed root cause of 'Indonesia' in billing_phone - was fallback to country value Issue: ❌ billing_phone showing 'Indonesia' instead of phone number ❌ Weak validation: ! empty() allows any non-empty string ❌ No sanitization - direct assignment of raw values ❌ Inconsistent validation between order and customer updates Root Cause: - OrdersController used ! empty() check - Allowed 'Indonesia' (country) to be saved as phone - No sanitization or format validation - Applied to ALL fields, not just phone Changes Made: 1. Created Sanitization Helpers (Lines 9-58): ✅ sanitize_field() - Trims, validates text fields ✅ sanitize_phone() - Removes non-numeric except +, -, spaces ✅ sanitize_email_field() - Validates email format ✅ Returns empty string if invalid (prevents bad data) 2. Fixed Order Billing/Shipping (Lines 645-673, 909-940): ✅ Update method: Sanitize all order address fields ✅ Create method: Sanitize all order address fields ✅ Applied to: first_name, last_name, email, phone, address_1, address_2, city, state, postcode, country 3. Fixed Customer Data - Existing Member (Lines 1089-1132): ✅ Sanitize all billing fields before WC_Customer update ✅ Sanitize all shipping fields before WC_Customer update ✅ Only set if not empty (allow clearing fields) ✅ Prevents 'Indonesia' or invalid data from being saved 4. Fixed Customer Data - New Member (Lines 1161-1204): ✅ Sanitize all billing fields on customer creation ✅ Sanitize all shipping fields on customer creation ✅ Same validation as existing member ✅ Consistent data quality for all customers Sanitization Logic: Phone: - Remove non-numeric except +, -, spaces - Trim whitespace - Return empty if only symbols - Example: 'Indonesia' → '' (empty) - Example: '08123456789' → '08123456789' ✅ Email: - Use sanitize_email() + is_email() - Return empty if invalid format - Prevents malformed emails Text Fields: - Use sanitize_text_field() - Trim whitespace - Return empty if only whitespace - Prevents injection attacks Impact: Before: - 'Indonesia' saved as phone ❌ - Country name in phone field ❌ - No validation ❌ - Inconsistent data ❌ After: - Invalid phone → empty string ✅ - All fields sanitized ✅ - Consistent validation ✅ - Clean customer data ✅ Applies To: ✅ Order creation (new orders) ✅ Order updates (edit orders) ✅ Customer data - existing members ✅ Customer data - new members (auto-register) ✅ All billing fields ✅ All shipping fields Testing Required: 1. Create order with existing customer - verify phone sanitized 2. Create order with new customer - verify no 'Indonesia' in phone 3. Edit order - verify all fields sanitized 4. Virtual products - verify phone still works correctly Result: No more 'Indonesia' or invalid data in customer fields!
WooNooW
WooNooW is a modern experience layer for WooCommerce — enhancing UX, speed, and reliability without data migration.
It keeps WooCommerce as the core engine while providing a modern React-powered interface for both the storefront (cart, checkout, my‑account) and the admin (orders, dashboard).
Three Admin Modes:
- Normal Mode: Traditional wp-admin integration (
/wp-admin/admin.php?page=woonoow) - Fullscreen Mode: Distraction-free interface (toggle in header)
- Standalone Mode: Complete standalone app at
yoursite.com/adminwith custom login ✨
🔍 Background
WooCommerce is the most used e‑commerce engine in the world, but its architecture has become heavy and fragmented.
With React‑based blocks (Checkout, Cart, Product Edit) and HPOS now rolling out, many existing addons are becoming obsolete or unstable.
WooNooW bridges the gap between Woo’s legacy PHP system and the new modern stack — so users get performance and simplicity without losing compatibility.
🚀 Key Principles
- No Migration Needed – Woo data stays intact.
- Safe Activate/Deactivate – revert to native Woo anytime, no data loss.
- Hybrid by Default – SSR + React islands for Cart/Checkout/My‑Account.
- Full SPA Toggle – optional React‑only mode for max performance.
- HPOS Mandatory – optimized datastore and async operations.
- Compat Layer – hook mirror + slot rendering for legacy addons.
- Async Mail & Tasks – powered by Action Scheduler.
🧱 Tech Stack
| Layer | Technology |
|---|---|
| Backend | PHP 8.2+, WordPress, WooCommerce (HPOS), Action Scheduler |
| Frontend | React 18 + TypeScript, Vite, React Query, Tailwind (optional) |
| Build & Package | Composer, NPM, ESM scripts, Zip automation |
| Architecture | Modular PSR‑4 classes, REST‑driven SPA islands |
🧩 Project Structure
woonoow/
├── admin-spa/
│ ├── src/
│ │ ├── components/
│ │ │ ├── filters/
│ │ │ │ ├── DateRange.tsx
│ │ │ │ └── OrderBy.tsx
│ │ │ └── CommandPalette.tsx
│ │ ├── hooks/
│ │ │ └── useShortcuts.tsx
│ │ ├── lib/
│ │ │ ├── api.ts
│ │ │ ├── currency.ts
│ │ │ ├── dates.ts
│ │ │ ├── query-params.ts
│ │ │ ├── useCommandStore.ts
│ │ │ └── utils.ts
│ │ ├── pages/
│ │ │ └── orders/
│ │ │ ├── partials
│ │ │ │ └── OrderForm.tsx
│ │ │ ├── Orders.tsx
│ │ │ ├── OrdersNew.tsx
│ │ │ └── OrderShow.tsx
│ │ ├── routes/
│ │ │ └── Dashboard.tsx
│ │ ├── types/
│ │ │ └── qrcode.d.ts
│ │ ├── App.tsx
│ │ ├── index.css
│ │ └── main.tsx
│ └── vite.config.ts
├── includes/
│ ├── Admin/
│ │ ├── Assets.php
│ │ └── Menu.php
│ ├── Api/
│ │ ├── CheckoutController.php
│ │ ├── OrdersController.php
│ │ ├── Permissions.php
│ │ └── Routes.php
│ ├── Compat/
│ │ ├── HideWooMenus.php
│ │ └── HooksShim.php
│ └── Core/
│ ├── DataStores/
│ │ ├── OrderStore_HPOS.php
│ │ └── OrderStore.php
│ ├── Mail/
│ │ ├── MailQueue.php
│ │ └── WooEmailOverride.php
│ ├── Bootstrap.php
│ └── Features.php
├── woonoow.php
└── docs (project notes, SOP, etc.)
⚙️ Development Workflow
- LocalWP / Docker setup with WordPress + WooCommerce.
- Activate plugin:
WooNooWshould appear in the admin menu. - Build SPAs:
npm run build - Package zip:
npm run pack - Upload
dist/woonoow.zipinto WordPress → Plugins → Add New → Upload.
🧭 Vision
“WooCommerce, reimagined for now.”
WooNooW delivers modern speed and UX while keeping WooCommerce’s ecosystem alive.
No migration. No lock‑in. Just Woo, evolved.